guix-commits
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[shepherd] 03/05: herd: Parse service sexps into records.


From: Ludovic Courtès
Subject: [shepherd] 03/05: herd: Parse service sexps into records.
Date: Fri, 21 Apr 2023 16:59:18 -0400 (EDT)

civodul pushed a commit to branch master
in repository shepherd.

commit 253ccf82de21b2a94e7609a01a853073df6157f5
Author: Ludovic Courtès <ludo@gnu.org>
AuthorDate: Thu Apr 20 21:42:33 2023 +0200

    herd: Parse service sexps into records.
    
    This makes it easier to fiddle with service info.
    
    * modules/shepherd/scripts/herd.scm (<live-service>): New record type.
    (live-service-canonical-name): New procedure.
    (service-canonical-name): Remove.
    (sexp->live-service): New procedure.
    (display-status-summary): Expect a list of <live-service>; adjust
    accordingly.
    (display-service-status): Likewise.
    (run-command): Adjust callers accordingly.
---
 modules/shepherd/scripts/herd.scm | 184 +++++++++++++++++++++-----------------
 1 file changed, 104 insertions(+), 80 deletions(-)

diff --git a/modules/shepherd/scripts/herd.scm 
b/modules/shepherd/scripts/herd.scm
index a840291..b9e989b 100644
--- a/modules/shepherd/scripts/herd.scm
+++ b/modules/shepherd/scripts/herd.scm
@@ -26,11 +26,33 @@
   #:use-module (ice-9 rdelim)
   #:use-module (ice-9 match)
   #:use-module (srfi srfi-1)
+  #:use-module (srfi srfi-9)
   #:use-module (srfi srfi-71)
   #:use-module (srfi srfi-19)
   #:export (main))
 
 
+;; Information about live services.
+(define-record-type <live-service>
+  (live-service provision requirement one-shot? transient? respawn?
+                enabled? status running last-respawns startup-failures)
+  live-service?
+  (provision        live-service-provision)       ;list of symbols
+  (requirement      live-service-requirement)     ;list of symbols
+  (one-shot?        live-service-one-shot?)       ;Boolean
+  (transient?       live-service-transient?)      ;Boolean
+  (respawn?         live-service-respawn?)        ;Boolean
+
+  (enabled?         live-service-enabled?)         ;Boolean
+  (status           live-service-status)           ;symbol
+  (running          live-service-running-value)    ;#f | object
+  (last-respawns    live-service-last-respawns)    ;list of integers
+  (startup-failures live-service-startup-failures)) ;list of integers
+
+(define (live-service-canonical-name service)
+  "Return the 'canonical name' of @var{service}."
+  (first (live-service-provision service)))
+
 (define-syntax alist-let*
   (syntax-rules ()
     "Bind the given KEYs in EXP to the corresponding items in ALIST.  ALIST
@@ -40,43 +62,44 @@ of pairs."
      (let ((key (and=> (assoc-ref alist 'key) car)) ...)
        exp ...))))
 
-(define service-canonical-name
-  (match-lambda
-    (('service ('version 0 _ ...) (provides (name0 _ ...)) _ ...)
-     name0)))
+(define (sexp->live-service sexp)
+  "Turn @var{sexp}, the wire representation of a service returned by shepherd,
+into a @code{live-service} record."
+  (match sexp
+    (('service ('version 0 _ ...) properties ...)
+     (alist-let* properties (provides requires status running respawn? enabled?
+                             last-respawns startup-failures
+                             one-shot? transient?)
+       (live-service provides requires one-shot?
+                     (if (sloppy-assq 'transient? properties)
+                         transient?
+                         (and running *unspecified*))
+                     respawn?
+
+                     enabled?
+                     (or status (if running 'running 'stopped))
+                     running
+                     (or last-respawns '())
+                     (or startup-failures '()))))))
 
 (define (display-status-summary services)
   "Display a summary of the status of all of SERVICES."
   (define (service<? service1 service2)
-    (string<? (symbol->string (service-canonical-name service1))
-              (symbol->string (service-canonical-name service2))))
+    (string<? (symbol->string (live-service-canonical-name service1))
+              (symbol->string (live-service-canonical-name service2))))
 
   (define (display-services header bullet services)
     (unless (null? services)
       (display header)
       (for-each (lambda (service)
                   (format #t " ~a ~a~%" bullet
-                          (service-canonical-name service)))
+                          (live-service-canonical-name service)))
                 (sort services service<?))))      ;get deterministic output
 
-  (let* ((started stopped
-                  (partition (match-lambda
-                               (('service ('version 0 _ ...) properties ...)
-                                (car (assoc-ref properties 'running))))
-                             services))
-         (one-shot stopped
-                   (partition (match-lambda
-                                (('service ('version 0 _ ...) properties ...)
-                                 ;; Prior to 0.6.1, shepherd did not send the
-                                 ;; 'one-shot?' property; thus, do not assume
-                                 ;; that it's available.
-                                 (and=> (assoc-ref properties 'one-shot?) 
car)))
-                              stopped))
+  (let* ((started stopped (partition live-service-running-value services))
+         (one-shot stopped (partition live-service-one-shot? stopped))
          (failing stopped
-                  (partition (match-lambda
-                               (('service ('version 0 _ ...) properties ...)
-                                (and=> (assoc-ref properties 'startup-failures)
-                                       (compose pair? car))))
+                  (partition (compose pair? live-service-startup-failures)
                              stopped)))
     (display-services (highlight (l10n "Started:\n")) "+"
                       started)
@@ -98,61 +121,58 @@ of pairs."
 
 (define (display-service-status service)
   "Display the status of SERVICE, an sexp."
-  (match service
-    (('service ('version 0 _ ...) properties ...)
-     (alist-let* properties (provides requires status running respawn? enabled?
-                             last-respawns startup-failures
-                             one-shot? transient?)
-       (format #t (highlight (l10n "Status of ~a:~%")) (first provides))
+  (format #t (highlight (l10n "Status of ~a:~%"))
+          (live-service-canonical-name service))
 
-       ;; Note: Shepherd up to 0.9.x included did not provide 'status', hence
-       ;; the 'or' below.
-       (match (or status (if running 'running 'stopped))
-         ('running
-          (if transient?
-              (format #t (l10n "  It is started and transient.~%"))
-              (format #t (l10n "  It is started.~%")))
+  ;; Note: Shepherd up to 0.9.x included did not provide 'status', hence
+  ;; the 'or' below.
+  (match (live-service-status service)
+    ('running
+     (if (live-service-transient? service)
+         (format #t (l10n "  It is started and transient.~%"))
+         (format #t (l10n "  It is started.~%")))
 
-          ;; TRANSLATORS: The "~s" bit is most of the time a placeholder
-          ;; for the PID (an integer) of the running process, and
-          ;; occasionally for another Scheme object.
-          (format #t (l10n "  Running value is ~s.~%") running))
-         ('stopped
-          (if one-shot?
-              (format #t (l10n "  It is stopped (one-shot).~%"))
-              (if (pair? startup-failures)
-                  (format #t (highlight/error
-                              (l10n "  It is stopped (failing).~%")))
-                  (format #t (highlight/warn
-                              (l10n "  It is stopped.~%"))))))
-         ('starting
-          (format #t (l10n "  It is starting.~%")))
-         ('stopping
-          (format #t (l10n "  It is being stopped.~%")))
-         (x
-          (format #t (l10n "  Unknown status '~a'~%.") x)))
+     ;; TRANSLATORS: The "~s" bit is most of the time a placeholder
+     ;; for the PID (an integer) of the running process, and
+     ;; occasionally for another Scheme object.
+     (format #t (l10n "  Running value is ~s.~%")
+             (live-service-running-value service)))
+    ('stopped
+     (if (live-service-one-shot? service)
+         (format #t (l10n "  It is stopped (one-shot).~%"))
+         (if (pair? (live-service-startup-failures service))
+             (format #t (highlight/error
+                         (l10n "  It is stopped (failing).~%")))
+             (format #t (highlight/warn
+                         (l10n "  It is stopped.~%"))))))
+    ('starting
+     (format #t (l10n "  It is starting.~%")))
+    ('stopping
+     (format #t (l10n "  It is being stopped.~%")))
+    (x
+     (format #t (l10n "  Unknown status '~a'~%.") x)))
 
-       (if enabled?
-           (format #t (l10n "  It is enabled.~%"))
-           (format #t (highlight/warn (l10n "  It is disabled.~%"))))
-       (format #t (l10n "  Provides ~a.~%") provides)
-       (format #t (l10n "  Requires ~a.~%") requires)
-       (if respawn?
-           (format #t (l10n "  Will be respawned.~%"))
-           (format #t (l10n "  Will not be respawned.~%")))
-       (match last-respawns
-         ((time _ ...)
-          (format #t (l10n "  Last respawned on ~a.~%")
-                  (date->string
-                   (time-utc->date (make-time time-utc 0 time)))))
-         (_ #t))
-       (when (or (eq? status 'stopped) (not running))
-         (match startup-failures
-           ((time _ ...)
-            (format #t (highlight/error (l10n "  Failed to start at ~a.~%"))
-                    (date->string
-                     (time-utc->date (make-time time-utc 0 time)))))
-           (_ #t)))))))
+  (if (live-service-enabled? service)
+      (format #t (l10n "  It is enabled.~%"))
+      (format #t (highlight/warn (l10n "  It is disabled.~%"))))
+  (format #t (l10n "  Provides ~a.~%") (live-service-provision service))
+  (format #t (l10n "  Requires ~a.~%") (live-service-requirement service))
+  (if (live-service-respawn? service)
+      (format #t (l10n "  Will be respawned.~%"))
+      (format #t (l10n "  Will not be respawned.~%")))
+  (match (live-service-last-respawns service)
+    ((time _ ...)
+     (format #t (l10n "  Last respawned on ~a.~%")
+             (date->string
+              (time-utc->date (make-time time-utc 0 time)))))
+    (_ #t))
+  (when (eq? (live-service-status service) 'stopped)
+    (match (live-service-startup-failures service)
+      ((time _ ...)
+       (format #t (highlight/error (l10n "  Failed to start at ~a.~%"))
+               (date->string
+                (time-utc->date (make-time time-utc 0 time)))))
+      (_ #t))))
 
 (define root-service?
   ;; XXX: This procedure is written in a surprising way to work around a
@@ -187,9 +207,11 @@ the daemon via SOCKET-FILE."
         ;; Then interpret the result
         (match (list action service)
           (('status (or 'root 'shepherd))
-           (display-status-summary (first result)))
+           (display-status-summary
+            (map sexp->live-service (first result))))
           (('detailed-status (or 'root 'shepherd))
-           (display-detailed-status (first result)))
+           (display-detailed-status
+            (map sexp->live-service (first result))))
           (('help (or 'root 'shepherd))
            (match result
              ((help-text)
@@ -202,8 +224,10 @@ the daemon via SOCKET-FILE."
               (newline))))
           (('status _)
            ;; We get a list of statuses, in case several services have the
-           ;; same name.
-           (for-each display-service-status result))
+           ;; same name.  FIXME: These days each name maps to exactly one
+           ;; service so RESULT is always a singleton.
+           (for-each (compose display-service-status sexp->live-service)
+                     result))
           (('start _)
            (unless result
              (report-error (l10n "failed to start service ~a")



reply via email to

[Prev in Thread] Current Thread [Next in Thread]