diff mbox series

[bug#44460] Add copyright lines

Message ID 87imabok8j.fsf@asu.edu
State Accepted
Headers show
Series [bug#44460] Add copyright lines | expand

Checks

Context Check Description
cbaines/applying patch fail View Laminar job

Commit Message

John Soo Nov. 11, 2020, 5:51 p.m. UTC
Hello Ludo,

Ludovic Courtès <ludo@gnu.org> writes:

>> +@table @code
>> +@item --normalize
>> +Normalize the output records into record sets (@pxref{Record Sets,,,
>> +recutils, GNU recutils manual}).  Normalizing into record sets allows
>> +joins across record types.
>> +
>> +@example
>> +$ guix processes --normalize | \
>> +    recsel \
>> +    -j Session \
>> +    -t ChildProcess \
>> +    -p Session.PID,PID \
>> +    -e 'Session.ClientCommand ~ build'
>> +Session_PID: 4278
>> +PID: 4435
>> +
>> +Session_PID: 4278
>> +PID: 4554
>> +
>> +Session_PID: 4278
>> +PID: 4646
>> +@end example
>> +@end table
>
> Nice!  Right above the example, I’d suggest adding a sentence like “The
> example below lists…” (what does it list actually? :-)).
>
> In the default format, I wonder if we could already change split
> ‘ChildProcess’ into ‘ChildPID’ and ‘ChildCommand’, as you had initially
> proposed on IRC; would that work?

I think we could do that, but I had two reasons to use the normalized
format instead.

* Backwards incompatibility - I didn't want to break any existing scripts
  that may exist.

* Still not normalized - how can I search for just the child processes
  associated with a particular command?

I wouldn't be opposed to splitting ChildProcess into ChildPID and
ChildCommand.  I would like it best if that change was made in addition
to adding the normalized version, since the normalized version allows
more functionality.

>> +(define (lock->record lock port)
>> +  (format port "LockHeld: ~a~%" lock))
>
> Maybe ‘lock->recutils’ for consistency and to avoid confusion with
> Scheme “records”?

Done.

>> +(define (format-single-record port)
>
> Maybe ‘daemon-sessions->recutils’?  Should ‘sessions’ be a parameter for
> clarity?

Much better, thank you. I updated the normalized version too.

>
>> +  "Display denormalized session information to PORT."
>> +  (for-each (lambda (session)
>> +              (daemon-session->recutils session port)
>> +                (newline port))
>                   ^
> Indentation is off.

Fixed.

>> +(define (child-process->normalized-record process port)
>> +  "Display PROCESS record on PORT in normalized form"
>> +  (format port "PID: ~a" (process-id process))
>> +  (newline port)
>> +  (format port "Command:~{ ~a~}" (process-command process)))
>> +
>> +(define (format-normalized port)
>
> Please add a docstring.  Perhaps make ‘sessions’ a parameter?

Done.

>> +  (define sessions (daemon-sessions))
>> +
>> +  (format port session-rec-type)
>
> As reported by ‘-Wformat’, passing a non-literal format string is risky;
> write this instead:
>
>   (display session-rec-type port)

Done.

>> +  (newline port)
>> +  (newline port)
>> +  (for-each
>> +   (lambda (session)
>
> Preferable indent ‘for-each’ like so:
>
>   (for-each (lambda (session)

Done.

> Likewise below.
>
>> +  (display (G_ "
>> +  --normalize            display results as normalized record sets"))
>
> Should it be ‘--format=normalized’ (just like we have ‘--format’ in
> ‘guix describe’, for instance)?

That makes sense. What do you think of

Other changes:

* Updated the record descriptors to include the possible
  fields for sessions. I got some nice guidance from the recutils irc on
  that.

* Put the PID and Command first for the ChildProcess

* Add a --list-formats like guix describe has.

Thanks!

John

Comments

Ludovic Courtès Nov. 12, 2020, 10:58 a.m. UTC | #1
Hi John,

John Soo <jsoo1@asu.edu> skribis:


[...]

>>> +Session_PID: 4278
>>> +PID: 4646
>>> +@end example
>>> +@end table
>>
>> Nice!  Right above the example, I’d suggest adding a sentence like “The
>> example below lists…” (what does it list actually? :-)).
>>
>> In the default format, I wonder if we could already change split
>> ‘ChildProcess’ into ‘ChildPID’ and ‘ChildCommand’, as you had initially
>> proposed on IRC; would that work?
>
> I think we could do that, but I had two reasons to use the normalized
> format instead.
>
> * Backwards incompatibility - I didn't want to break any existing scripts
>   that may exist.
>
> * Still not normalized - how can I search for just the child processes
>   associated with a particular command?

Like:

  guix processes | recsel -e 'ClientCommand ~ "xyz"' -p ChildProcess

?

Actually what does “normalized” mean in this context?

> I wouldn't be opposed to splitting ChildProcess into ChildPID and
> ChildCommand.  I would like it best if that change was made in addition
> to adding the normalized version, since the normalized version allows
> more functionality.

I would think it’s OK to break compatibility on just these
“ChildProcess” fields.

> * Updated the record descriptors to include the possible
>   fields for sessions. I got some nice guidance from the recutils irc on
>   that.
>
> * Put the PID and Command first for the ChildProcess
>
> * Add a --list-formats like guix describe has.

Great, I’ll take a look.  Thanks!

Ludo’.
John Soo Nov. 12, 2020, 3:37 p.m. UTC | #2
Hi Ludo,

Ludovic Courtès <ludo@gnu.org> writes:

>> * Still not normalized - how can I search for just the child processes
>>   associated with a particular command?
>
> Like:
>
>   guix processes | recsel -e 'ClientCommand ~ "xyz"' -p ChildProcess
>
> ?
>
> Actually what does “normalized” mean in this context?

Excellent question. I was thinking along the lines of database
normalization. The default output has multi-valued fields for child
processes, so the idea is to make them their own record set.  Does that
make sense?

An aside - Probably to be entirely honest about normalizing the output,
locks really would be in a separate record set too.

Another challenge is making sure the user can understand what
"normalized" means.  I am not sure readers of the manual/cli help will
be able to infer what it means from context.  On the other hand, it is
such a small use case that it seems imbalanced to provide a lot of
background for the term "normal". What do you think?

>> I wouldn't be opposed to splitting ChildProcess into ChildPID and
>> ChildCommand.  I would like it best if that change was made in addition
>> to adding the normalized version, since the normalized version allows
>> more functionality.
>
> I would think it’s OK to break compatibility on just these
> “ChildProcess” fields.

Ok. Would it be ok if I put that in a separate commit?

Thanks again!

- John
Ludovic Courtès Nov. 12, 2020, 8:29 p.m. UTC | #3
Hi,

John Soo <jsoo1@asu.edu> skribis:

> Ludovic Courtès <ludo@gnu.org> writes:
>
>>> * Still not normalized - how can I search for just the child processes
>>>   associated with a particular command?
>>
>> Like:
>>
>>   guix processes | recsel -e 'ClientCommand ~ "xyz"' -p ChildProcess
>>
>> ?
>>
>> Actually what does “normalized” mean in this context?
>
> Excellent question. I was thinking along the lines of database
> normalization. The default output has multi-valued fields for child
> processes, so the idea is to make them their own record set.  Does that
> make sense?

Yes it does!  Initially I wondered if it was a term used in recutils,
but apparently it’s not.

> An aside - Probably to be entirely honest about normalizing the output,
> locks really would be in a separate record set too.

Yeah.

> Another challenge is making sure the user can understand what
> "normalized" means.  I am not sure readers of the manual/cli help will
> be able to infer what it means from context.  On the other hand, it is
> such a small use case that it seems imbalanced to provide a lot of
> background for the term "normal". What do you think?

Sure.

Thinking more about it, to me the appeal of recutils is that it’s both
human- and machine-readable.  But here we end up having a specific
machine-readable variant.  But yeah, maybe that’s unavoidable.

>>> I wouldn't be opposed to splitting ChildProcess into ChildPID and
>>> ChildCommand.  I would like it best if that change was made in addition
>>> to adding the normalized version, since the normalized version allows
>>> more functionality.
>>
>> I would think it’s OK to break compatibility on just these
>> “ChildProcess” fields.
>
> Ok. Would it be ok if I put that in a separate commit?

Yes (you mean in addition to ‘-f normalized’, right?).

Thanks,
Ludo’.
diff mbox series

Patch

From a19828e504288c03c7e17a88ac2a35eb70ab302c Mon Sep 17 00:00:00 2001
From: John Soo <jsoo1@asu.edu>
Date: Wed, 4 Nov 2020 07:51:52 -0800
Subject: [PATCH] processes: Optionally normalize recutils output.

* guix/scripts/processes.scm: Add "normalize" flag
---
 doc/guix.texi              |  29 ++++++++
 guix/scripts/processes.scm | 132 +++++++++++++++++++++++++++++++------
 2 files changed, 142 insertions(+), 19 deletions(-)

diff --git a/doc/guix.texi b/doc/guix.texi
index 5e3e0435b4..5df6096f39 100644
--- a/doc/guix.texi
+++ b/doc/guix.texi
@@ -82,6 +82,7 @@  Copyright @copyright{} 2020 Pierre Langlois@*
 Copyright @copyright{} 2020 pinoaffe@*
 Copyright @copyright{} 2020 André Batista@*
 Copyright @copyright{} 2020 Alexandru-Sergiu Marton@*
+Copyright @copyright{} 2020 John Soo@*
 
 Permission is granted to copy, distribute and/or modify this document
 under the terms of the GNU Free Documentation License, Version 1.3 or
@@ -12691,6 +12692,34 @@  ClientPID: 19419
 ClientCommand: cuirass --cache-directory /var/cache/cuirass @dots{}
 @end example
 
+Additional options are listed below.
+
+@table @code
+@item --normalize
+Normalize the output records into record sets (@pxref{Record Sets,,,
+recutils, GNU recutils manual}).  Normalizing into record sets allows
+joins across record types.  The example below lists the PID of each
+ChildProcess and the associated PID for Session that spawned the
+ChildProcess where the Session was started using guix build.
+
+@example
+$ guix processes --normalize | \
+    recsel \
+    -j Session \
+    -t ChildProcess \
+    -p Session.PID,PID \
+    -e 'Session.ClientCommand ~ "guix build'"
+PID: 4435
+Session_PID: 4278
+
+PID: 4554
+Session_PID: 4278
+
+PID: 4646
+Session_PID: 4278
+@end example
+@end table
+
 @node System Configuration
 @chapter System Configuration
 
diff --git a/guix/scripts/processes.scm b/guix/scripts/processes.scm
index b4ca7b1687..af1d220774 100644
--- a/guix/scripts/processes.scm
+++ b/guix/scripts/processes.scm
@@ -1,5 +1,6 @@ 
 ;;; GNU Guix --- Functional package management for GNU
 ;;; Copyright © 2018, 2019, 2020 Ludovic Courtès <ludo@gnu.org>
+;;; Copyright © 2020 John Soo <jsoo1@asu.edu>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
@@ -176,6 +177,9 @@  active sessions, and the master 'guix-daemon' process."
     (values (filter-map child-process->session children)
             master)))
 
+(define (lock->recutils lock port)
+  (format port "LockHeld: ~a~%" lock))
+
 (define (daemon-session->recutils session port)
   "Display SESSION information in recutils format on PORT."
   (format port "SessionPID: ~a~%"
@@ -184,8 +188,7 @@  active sessions, and the master 'guix-daemon' process."
           (process-id (daemon-session-client session)))
   (format port "ClientCommand:~{ ~a~}~%"
           (process-command (daemon-session-client session)))
-  (for-each (lambda (lock)
-              (format port "LockHeld: ~a~%" lock))
+  (for-each (lambda (lock) (lock->recutils lock port))
             (daemon-session-locks-held session))
   (for-each (lambda (process)
               (format port "ChildProcess: ~a:~{ ~a~}~%"
@@ -193,19 +196,89 @@  active sessions, and the master 'guix-daemon' process."
                       (process-command process)))
             (daemon-session-children session)))
 
+(define (daemon-sessions->recutils port sessions)
+  "Display denormalized SESSIONS information to PORT."
+  (for-each (lambda (session)
+              (daemon-session->recutils session port)
+              (newline port))
+            sessions))
+
+(define session-rec-type
+  "%rec: Session
+%type: PID int
+%type: ClientPID int
+%key: PID
+%mandatory: ClientPID ClientCommand
+%allowed: LockHeld")
+
+(define child-process-rec-type
+  "%rec: ChildProcess
+%type: PID int
+%type: Session rec Session
+%key: PID
+%mandatory: Command")
+
+(define (session-key->recutils session port)
+  "Display SESSION PID as a recutils field on PORT."
+  (format
+   port "Session: ~a"
+   (process-id (daemon-session-process session))))
+
+(define (session-scalars->normalized-record session port)
+  "Display SESSION scalar fields to PORT in normalized form."
+  (format port "PID: ~a~%"
+          (process-id (daemon-session-process session)))
+  (format port "ClientPID: ~a~%"
+          (process-id (daemon-session-client session)))
+  (format port "ClientCommand:~{ ~a~}~%"
+          (process-command (daemon-session-client session))))
+
+(define (child-process->normalized-record process port)
+  "Display PROCESS record on PORT in normalized form"
+  (format port "PID: ~a" (process-id process))
+  (newline port)
+  (format port "Command:~{ ~a~}" (process-command process)))
+
+(define (daemon-sessions->normalized-record port sessions)
+  "Display SESSIONS recutils on PORT in normalized form"
+  (display session-rec-type port)
+  (newline port)
+  (newline port)
+  (for-each (lambda (session)
+              (session-scalars->normalized-record session port)
+              (for-each (lambda (lock)
+                          (lock->recutils lock port))
+                        (daemon-session-locks-held session))
+              (newline port))
+            sessions)
+
+  (display child-process-rec-type port)
+  (newline port)
+  (newline port)
+  (for-each (lambda (session)
+              (for-each (lambda (process)
+                          (child-process->normalized-record process port)
+                          (newline port)
+                          (session-key->recutils session port)
+                          (newline port)
+                          (newline port))
+                        (daemon-session-children session)))
+            sessions))
+
 
 ;;;
 ;;; Options.
 ;;;
 
-(define %options
-  (list (option '(#\h "help") #f #f
-                (lambda args
-                  (show-help)
-                  (exit 0)))
-        (option '(#\V "version") #f #f
-                (lambda args
-                  (show-version-and-exit "guix processes")))))
+(define %available-formats
+  '("recutils" "recutils-normalized"))
+
+(define (list-formats)
+  (display (G_ "The available formats are:\n"))
+  (newline)
+  (for-each (lambda (f)
+              (format #t "  - ~a~%" f))
+            %available-formats))
 
 (define (show-help)
   (display (G_ "Usage: guix processes
@@ -216,8 +289,33 @@  List the current Guix sessions and their processes."))
   (display (G_ "
   -V, --version          display version information and exit"))
   (newline)
+  (display (G_ "
+  -f, --format=FORMAT    display results as normalized record sets"))
+  (newline)
+  (display (G_ "
+  --list-formats         display available formats"))
   (show-bug-report-information))
 
+(define %options
+  (list (option '(#\h "help") #f #f
+                (lambda args
+                  (show-help)
+                  (exit 0)))
+        (option '(#\V "version") #f #f
+                (lambda args
+                  (show-version-and-exit "guix processes")))
+        (option '(#\f "format") #t #f
+                (lambda (opt name arg result)
+                  (unless (member arg %available-formats)
+                    (leave (G_ "~a: unsupported output format~%") arg))
+                  (alist-cons 'format (string->symbol arg) result)))
+        (option '("list-formats") #f #f
+                (lambda (opt name arg result)
+                  (list-formats)
+                  (exit 0)))))
+
+(define %default-options '((format . recutils)))
+
 
 ;;;
 ;;; Entry point.
@@ -227,17 +325,13 @@  List the current Guix sessions and their processes."))
   (category plumbing)
   (synopsis "list currently running sessions")
   (define options
-    (args-fold* args %options
-                (lambda (opt name arg result)
-                  (leave (G_ "~A: unrecognized option~%") name))
-                cons
-                '()))
+    (parse-command-line args %options (list %default-options)))
 
   (with-paginated-output-port port
-    (for-each (lambda (session)
-                (daemon-session->recutils session port)
-                (newline port))
-              (daemon-sessions))
+    (match (assoc-ref options 'format)
+      ('recutils-normalized
+       (daemon-sessions->normalized-record port (daemon-sessions)))
+      (_ (daemon-sessions->recutils port (daemon-sessions))))
 
     ;; Pass 'R' (instead of 'r') so 'less' correctly estimates line length.
     #:less-options "FRX"))
-- 
2.29.1