guix-commits
[Top][All Lists]
Advanced

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

[no subject]


From: Ludovic Courtès
Date: Wed, 13 Sep 2023 13:05:39 -0400 (EDT)

branch: wip-actors
commit b0f93551bc15bb589c247380f5e91221113e036e
Author: Ludovic Courtès <ludo@gnu.org>
AuthorDate: Wed Sep 13 16:15:14 2023 +0200

    Move store and GC helpers from (cuirass base) to (cuirass store).
    
    * src/cuirass/base.scm (default-gc-root-directory, %gc-root-directory)
    (%gc-root-ttl, gc-roots, gc-root-expiration-time)
    (register-gc-root, register-gc-roots)
    (non-blocking-port, ensure-non-blocking-store-connection)
    (with-store/non-blocking, process-build-log, build-derivations&): Move
    to…
    * src/cuirass/store.scm: … here.  New file.
    * src/cuirass/scripts/remote-server.scm: Adjust accordingly.
    * src/cuirass/scripts/remote-worker.scm: Likewise.
    * src/cuirass/scripts/register.scm: Likewise.
    * Makefile.am (dist_pkgmodule_DATA): Add ‘src/cuirass/store.scm’.
---
 Makefile.am                           |   1 +
 src/cuirass/base.scm                  | 164 +---------------------------
 src/cuirass/scripts/register.scm      |   3 +-
 src/cuirass/scripts/remote-server.scm |   3 +-
 src/cuirass/scripts/remote-worker.scm |   5 +-
 src/cuirass/store.scm                 | 199 ++++++++++++++++++++++++++++++++++
 6 files changed, 210 insertions(+), 165 deletions(-)

diff --git a/Makefile.am b/Makefile.am
index d8ed3f7..8a6f87a 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -48,6 +48,7 @@ jsdir = $(staticdir)/js
 systemdservicedir = $(libdir)/systemd/system
 
 dist_pkgmodule_DATA =                          \
+  src/cuirass/store.scm                                \
   src/cuirass/base.scm                         \
   src/cuirass/database.scm                     \
   src/cuirass/http.scm                         \
diff --git a/src/cuirass/base.scm b/src/cuirass/base.scm
index 8ecc15f..329ddb8 100644
--- a/src/cuirass/base.scm
+++ b/src/cuirass/base.scm
@@ -27,6 +27,7 @@
   #:use-module (cuirass database)
   #:use-module (cuirass remote)
   #:use-module (cuirass specification)
+  #:use-module (cuirass store)
   #:use-module (cuirass utils)
   #:use-module ((cuirass config) #:select (%localstatedir))
   #:use-module (gnu packages)
@@ -36,9 +37,7 @@
   #:use-module (guix store)
   #:use-module (guix ui)
   #:use-module (guix git)
-  #:use-module (guix cache)
   #:use-module (zlib)
-  #:use-module ((guix config) #:select (%state-directory))
   #:use-module (git)
   #:use-module (ice-9 binary-ports)
   #:use-module (ice-9 control)
@@ -46,12 +45,9 @@
   #:use-module (ice-9 match)
   #:use-module (ice-9 popen)
   #:use-module (ice-9 ports internal)
-  #:use-module (ice-9 rdelim)
-  #:use-module (ice-9 receive)
   #:use-module (ice-9 regex)
-  #:use-module (ice-9 atomic)
   #:use-module (ice-9 ftw)
-  #:use-module (ice-9 threads)
+  #:autoload   (ice-9 threads) (current-processor-count)
   #:use-module (ice-9 vlist)
   #:use-module (srfi srfi-1)
   #:use-module (srfi srfi-11)
@@ -61,13 +57,9 @@
   #:use-module (srfi srfi-35)
   #:use-module (rnrs bytevectors)
   #:export (;; Procedures.
-            default-gc-root-directory
             call-with-time-display
-            register-gc-roots
             read-parameters
             evaluate
-            with-store/non-blocking
-            build-derivations&
             set-build-successful!
             clear-build-queue
             cancel-old-builds
@@ -88,8 +80,6 @@
             ;; Parameters.
             %bridge-socket-file-name
             %package-cachedir
-            %gc-root-directory
-            %gc-root-ttl
             %build-remote?
             %fallback?))
 
@@ -112,71 +102,6 @@
           (scm-error 'wrong-type-arg
                      "%package-cachedir" "Not a string: ~S" (list #f) #f)))))
 
-(define (default-gc-root-directory)
-  (string-append %state-directory
-                 "/gcroots/profiles/per-user/"
-                 (passwd:name (getpwuid (getuid)))
-                 "/cuirass"))
-
-(define %gc-root-directory
-  ;; Directory where garbage collector roots are stored.  We register build
-  ;; outputs there.
-  (make-parameter (default-gc-root-directory)))
-
-(define %gc-root-ttl
-  ;; The "time to live" (TTL) of GC roots.
-  (make-parameter (* 30 24 3600)))
-
-(define (gc-roots directory)
-  ;; Return the list of GC roots (symlinks) in DIRECTORY.
-  (map (cut string-append directory "/" <>)
-       (scandir directory
-                (lambda (file)
-                  (not (member file '("." "..")))))))
-
-(define (gc-root-expiration-time file)
-  "Return \"expiration time\" of FILE (a symlink in %GC-ROOT-DIRECTORY)
-computed as its modification time + TTL seconds."
-  (match (false-if-exception (lstat file))
-    (#f 0)                         ;FILE may have been deleted in the meantime
-    (st (+ (stat:mtime st) (%gc-root-ttl)))))
-
-(define (register-gc-root item)
-  "Create a GC root pointing to ITEM, a store item."
-  (catch 'system-error
-    (lambda ()
-      (symlink item
-               (string-append (%gc-root-directory)
-                              "/" (basename item))))
-    (lambda args
-      ;; If the symlink already exist, assume it points to ITEM.
-      (unless (= EEXIST (system-error-errno args))
-        (apply throw args)))))
-
-(define* (register-gc-roots drv
-                            #:key (mode 'outputs))
-  "Register GC roots for the outputs of the given DRV when MODE is 'outputs or
-for DRV itself when MODE is 'derivation.  Also remove the expired GC roots if
-any."
-  (catch 'system-error
-    (lambda ()
-      (case mode
-        ((outputs)
-         (for-each (match-lambda
-                     ((name . output)
-                      (register-gc-root output)))
-                   (derivation-path->output-paths drv)))
-        ((derivation)
-         (register-gc-root drv))))
-    (lambda args
-      (unless (= ENOENT (system-error-errno args)) ;collected in the meantime
-        (apply throw args))))
-
-  (maybe-remove-expired-cache-entries (%gc-root-directory)
-                                      gc-roots
-                                      #:entry-expiration
-                                      gc-root-expiration-time))
-
 (define (report-git-error error)
   "Report the given Guile-Git error."
   (format (current-error-port)
@@ -194,30 +119,6 @@ any."
   (name evaluation-error-spec-name)
   (id   evaluation-error-id))
 
-(define (non-blocking-port port)
-  "Make PORT non-blocking and return it."
-  (let ((flags (fcntl port F_GETFL)))
-    (when (zero? (logand O_NONBLOCK flags))
-      (fcntl port F_SETFL (logior O_NONBLOCK flags)))
-    port))
-
-(define (ensure-non-blocking-store-connection store)
-  "Mark the file descriptor that backs STORE, a <store-connection>, as
-O_NONBLOCK."
-  (match (store-connection-socket store)
-    ((? file-port? port)
-     (non-blocking-port port))
-    (_ #f)))
-
-(define-syntax-rule (with-store/non-blocking store exp ...)
-  "Like 'with-store', bind STORE to a connection to the store, but ensure that
-said connection is non-blocking (O_NONBLOCK).  Evaluate EXP... in that
-context."
-  (with-store store
-    (ensure-non-blocking-store-connection store)
-    (let ()
-      exp ...)))
-
 (define %cuirass-state-directory
   ;; Directory where state files are stored, usually "/var".
   (make-parameter (or (getenv "CUIRASS_STATE_DIRECTORY")
@@ -243,67 +144,6 @@ context."
     (load* file modules)))
 
 
-;;;
-;;; Build status.
-;;;
-
-(define (process-build-log port proc seed)
-  "Read from PORT the build log, calling PROC for each build event like 'fold'
-does.  Return the result of the last call to PROC."
-  (define (process-line line state)
-    (when (string-prefix? "@ " line)
-      (match (string-tokenize (string-drop line 2))
-        (((= string->symbol event-name) args ...)
-         (proc (cons event-name args) state)))))
-
-  (let loop ((state seed))
-    (match (read-line port)
-      ((? eof-object?)
-       state)
-      ((? string? line)
-       (loop (process-line line state))))))
-
-(define (build-derivations& store lst)
-  "Like 'build-derivations' but return two values: a file port from which to
-read the build log, and a thunk to call after EOF has been read.  The thunk
-returns the value of the underlying 'build-derivations' call, or raises the
-exception that 'build-derivations' raised.
-
-Essentially this procedure inverts the inversion-of-control that
-'build-derivations' imposes, whereby 'build-derivations' writes to
-'current-build-output-port'."
-  ;; XXX: Make this part of (guix store)?
-  (define result
-    (make-atomic-box #f))
-
-  (match (pipe)
-    ((input . output)
-     (call-with-new-thread
-      (lambda ()
-        (catch #t
-          (lambda ()
-            ;; String I/O primitives are going to be used on PORT so make it
-            ;; Unicode-capable and resilient to encoding issues.
-            (set-port-encoding! output "UTF-8")
-            (set-port-conversion-strategy! output 'substitute)
-
-            (guard (c ((store-error? c)
-                       (atomic-box-set! result c)))
-              (parameterize ((current-build-output-port output))
-                (let ((x (build-derivations store lst)))
-                  (atomic-box-set! result x))))
-            (close-port output))
-          (lambda _
-            (close-port output)))))
-
-     (values (non-blocking-port input)
-             (lambda ()
-               (match (atomic-box-ref result)
-                 ((? condition? c)
-                  (raise c))
-                 (x x)))))))
-
-
 ;;;
 ;;; Building packages.
 ;;;
diff --git a/src/cuirass/scripts/register.scm b/src/cuirass/scripts/register.scm
index 9fab157..6d3ee75 100644
--- a/src/cuirass/scripts/register.scm
+++ b/src/cuirass/scripts/register.scm
@@ -21,13 +21,14 @@
 
 (define-module (cuirass scripts register)
   #:use-module (cuirass)
-  #:use-module (cuirass base)
   #:use-module (cuirass database)
   #:use-module (cuirass ui)
   #:use-module (cuirass logging)
   #:use-module (cuirass metrics)
   #:use-module (cuirass notification)
   #:use-module (cuirass specification)
+  #:use-module ((cuirass store)
+                #:select (%gc-root-directory %gc-root-ttl))
   #:use-module (cuirass utils)
   #:use-module (cuirass zabbix)
   #:use-module (guix ui)
diff --git a/src/cuirass/scripts/remote-server.scm 
b/src/cuirass/scripts/remote-server.scm
index 95f1499..bbe19f1 100644
--- a/src/cuirass/scripts/remote-server.scm
+++ b/src/cuirass/scripts/remote-server.scm
@@ -18,7 +18,7 @@
 ;;; along with GNU Guix.  If not, see <http://www.gnu.org/licenses/>.
 
 (define-module (cuirass scripts remote-server)
-  #:use-module (cuirass base)
+  #:autoload   (cuirass base) (read-parameters set-build-successful!)
   #:use-module (cuirass config)
   #:use-module (cuirass database)
   #:use-module (cuirass logging)
@@ -26,6 +26,7 @@
   #:use-module (cuirass notification)
   #:use-module (cuirass parameters)
   #:use-module (cuirass remote)
+  #:use-module (cuirass store)
   #:use-module (cuirass utils)
   #:use-module (gcrypt pk-crypto)
   #:use-module (guix avahi)
diff --git a/src/cuirass/scripts/remote-worker.scm 
b/src/cuirass/scripts/remote-worker.scm
index 039c0be..6295584 100644
--- a/src/cuirass/scripts/remote-worker.scm
+++ b/src/cuirass/scripts/remote-worker.scm
@@ -20,7 +20,10 @@
 (define-module (cuirass scripts remote-worker)
   #:use-module (fibers)
   #:use-module (fibers channels)
-  #:use-module (cuirass base)
+  #:autoload   (cuirass store) (build-derivations&
+                                register-gc-roots
+                                %gc-root-directory
+                                %gc-root-ttl)
   #:use-module (cuirass logging)
   #:use-module (cuirass remote)
   #:use-module (cuirass ui)
diff --git a/src/cuirass/store.scm b/src/cuirass/store.scm
new file mode 100644
index 0000000..9cf9b7d
--- /dev/null
+++ b/src/cuirass/store.scm
@@ -0,0 +1,199 @@
+;;; store.scm -- Fiberized access to the store.
+;;; Copyright © 2016-2019, 2022-2023 Ludovic Courtès <ludo@gnu.org>
+;;; Copyright © 2017, 2020, 2021 Mathieu Othacehe <othacehe@gnu.org>
+;;;
+;;; This file is part of Cuirass.
+;;;
+;;; Cuirass is free software: you can redistribute it and/or modify
+;;; it under the terms of the GNU General Public License as published by
+;;; the Free Software Foundation, either version 3 of the License, or
+;;; (at your option) any later version.
+;;;
+;;; Cuirass is distributed in the hope that it will be useful,
+;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;;; GNU General Public License for more details.
+;;;
+;;; You should have received a copy of the GNU General Public License
+;;; along with Cuirass.  If not, see <http://www.gnu.org/licenses/>.
+
+(define-module (cuirass store)
+  #:use-module (guix store)
+  #:autoload   (guix derivations) (build-derivations
+                                   derivation-path->output-paths)
+  #:use-module ((guix config) #:select (%state-directory))
+  #:autoload   (guix cache) (maybe-remove-expired-cache-entries)
+  #:autoload   (srfi srfi-26) (cut)
+  #:use-module (srfi srfi-34)
+  #:use-module ((srfi srfi-35) #:select (condition?))
+  #:use-module (ice-9 atomic)
+  #:use-module (ice-9 match)
+  #:autoload   (ice-9 ftw) (scandir)
+  #:autoload   (ice-9 rdelim) (read-line)
+  #:use-module (ice-9 threads)
+  #:export (non-blocking-port
+            with-store/non-blocking
+            process-build-log
+            build-derivations&
+
+            register-gc-root
+            register-gc-roots
+            default-gc-root-directory
+            %gc-root-directory
+            %gc-root-ttl))
+
+
+;;;
+;;; Garbage collector roots.
+;;;
+
+(define (default-gc-root-directory)
+  (string-append %state-directory
+                 "/gcroots/profiles/per-user/"
+                 (passwd:name (getpwuid (getuid)))
+                 "/cuirass"))
+
+(define %gc-root-directory
+  ;; Directory where garbage collector roots are stored.  We register build
+  ;; outputs there.
+  (make-parameter (default-gc-root-directory)))
+
+(define %gc-root-ttl
+  ;; The "time to live" (TTL) of GC roots.
+  (make-parameter (* 30 24 3600)))
+
+(define (gc-roots directory)
+  ;; Return the list of GC roots (symlinks) in DIRECTORY.
+  (map (cut string-append directory "/" <>)
+       (scandir directory
+                (lambda (file)
+                  (not (member file '("." "..")))))))
+
+(define (gc-root-expiration-time file)
+  "Return \"expiration time\" of FILE (a symlink in %GC-ROOT-DIRECTORY)
+computed as its modification time + TTL seconds."
+  (match (false-if-exception (lstat file))
+    (#f 0)                         ;FILE may have been deleted in the meantime
+    (st (+ (stat:mtime st) (%gc-root-ttl)))))
+
+(define (register-gc-root item)
+  "Create a GC root pointing to ITEM, a store item."
+  (catch 'system-error
+    (lambda ()
+      (symlink item
+               (string-append (%gc-root-directory)
+                              "/" (basename item))))
+    (lambda args
+      ;; If the symlink already exist, assume it points to ITEM.
+      (unless (= EEXIST (system-error-errno args))
+        (apply throw args)))))
+
+(define* (register-gc-roots drv
+                            #:key (mode 'outputs))
+  "Register GC roots for the outputs of the given DRV when MODE is 'outputs or
+for DRV itself when MODE is 'derivation.  Also remove the expired GC roots if
+any."
+  (catch 'system-error
+    (lambda ()
+      (case mode
+        ((outputs)
+         (for-each (match-lambda
+                     ((name . output)
+                      (register-gc-root output)))
+                   (derivation-path->output-paths drv)))
+        ((derivation)
+         (register-gc-root drv))))
+    (lambda args
+      (unless (= ENOENT (system-error-errno args)) ;collected in the meantime
+        (apply throw args))))
+
+  (maybe-remove-expired-cache-entries (%gc-root-directory)
+                                      gc-roots
+                                      #:entry-expiration
+                                      gc-root-expiration-time))
+
+
+;;;
+;;; Fiberized access to the store.
+;;;
+
+(define (non-blocking-port port)
+  "Make PORT non-blocking and return it."
+  (let ((flags (fcntl port F_GETFL)))
+    (when (zero? (logand O_NONBLOCK flags))
+      (fcntl port F_SETFL (logior O_NONBLOCK flags)))
+    port))
+
+(define (ensure-non-blocking-store-connection store)
+  "Mark the file descriptor that backs STORE, a <store-connection>, as
+O_NONBLOCK."
+  (match (store-connection-socket store)
+    ((? file-port? port)
+     (non-blocking-port port))
+    (_ #f)))
+
+(define-syntax-rule (with-store/non-blocking store exp ...)
+  "Like 'with-store', bind STORE to a connection to the store, but ensure that
+said connection is non-blocking (O_NONBLOCK).  Evaluate EXP... in that
+context."
+  (with-store store
+    (ensure-non-blocking-store-connection store)
+    (let ()
+      exp ...)))
+
+(define (process-build-log port proc seed)
+  "Read from PORT the build log, calling PROC for each build event like 'fold'
+does.  Return the result of the last call to PROC."
+  (define (process-line line state)
+    (when (string-prefix? "@ " line)
+      (match (string-tokenize (string-drop line 2))
+        (((= string->symbol event-name) args ...)
+         (proc (cons event-name args) state)))))
+
+  (let loop ((state seed))
+    (match (read-line port)
+      ((? eof-object?)
+       state)
+      ((? string? line)
+       (loop (process-line line state))))))
+
+(define (build-derivations& store lst)
+  "Like 'build-derivations' but return two values: a file port from which to
+read the build log, and a thunk to call after EOF has been read.  The thunk
+returns the value of the underlying 'build-derivations' call, or raises the
+exception that 'build-derivations' raised.
+
+Essentially this procedure inverts the inversion-of-control that
+'build-derivations' imposes, whereby 'build-derivations' writes to
+'current-build-output-port'."
+  ;; XXX: Make this part of (guix store)?
+  (define result
+    (make-atomic-box #f))
+
+  (match (pipe)
+    ((input . output)
+     (call-with-new-thread
+      (lambda ()
+        (catch #t
+          (lambda ()
+            ;; String I/O primitives are going to be used on PORT so make it
+            ;; Unicode-capable and resilient to encoding issues.
+            (set-port-encoding! output "UTF-8")
+            (set-port-conversion-strategy! output 'substitute)
+
+            (guard (c ((store-error? c)
+                       (atomic-box-set! result c)))
+              (parameterize ((current-build-output-port output))
+                (let ((x (build-derivations store lst)))
+                  (atomic-box-set! result x))))
+            (close-port output))
+          (lambda _
+            (close-port output)))))
+
+     (values (non-blocking-port input)
+             (lambda ()
+               (match (atomic-box-ref result)
+                 ((? condition? c)
+                  (raise c))
+                 (x x)))))))
+



reply via email to

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