[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
02/10: guix: store: Make register-items transactional.
From: |
guix-commits |
Subject: |
02/10: guix: store: Make register-items transactional. |
Date: |
Sun, 17 Feb 2019 17:37:06 -0500 (EST) |
reepca pushed a commit to branch guile-daemon
in repository guix.
commit 634089c947ef83b1f2424eda84445a2404d0779c
Author: Caleb Ristvedt <address@hidden>
Date: Wed Jan 30 17:03:38 2019 -0600
guix: store: Make register-items transactional.
* guix/store/database.scm (SQLITE_BUSY, register-output-sql): new variables
(add-references): don't try finalizing after each use, only after all the
uses (otherwise a finalized statement would be used if #:cache? was #f).
(call-with-transaction): New procedure.
(register-items): Use call-with-transaction to prevent broken intermediate
states from being visible.
* .dir-locals.el (call-with-transaction): indent it.
---
.dir-locals.el | 1 +
guix/store/database.scm | 50 ++++++++++++++++++++++++++++++++++++++-----------
2 files changed, 40 insertions(+), 11 deletions(-)
diff --git a/.dir-locals.el b/.dir-locals.el
index 593c767..550e06e 100644
--- a/.dir-locals.el
+++ b/.dir-locals.el
@@ -79,6 +79,7 @@
(eval . (put 'with-extensions 'scheme-indent-function 1))
(eval . (put 'with-database 'scheme-indent-function 2))
+ (eval . (put 'call-with-transaction 'scheme-indent-function 2))
(eval . (put 'call-with-container 'scheme-indent-function 1))
(eval . (put 'container-excursion 'scheme-indent-function 1))
diff --git a/guix/store/database.scm b/guix/store/database.scm
index 4791f49..af7f82b 100644
--- a/guix/store/database.scm
+++ b/guix/store/database.scm
@@ -96,6 +96,31 @@ create it and initialize it as a new database."
(lambda ()
(sqlite-close db)))))
+;; XXX: missing in address@hidden
+(define SQLITE_BUSY 5)
+
+(define (call-with-transaction db proc)
+ "Start a transaction with DB (make as many attempts as necessary) and run
+PROC. If PROC exits abnormally, abort the transaction, otherwise commit the
+transaction after it finishes."
+ (catch 'sqlite-error
+ (lambda ()
+ ;; We use begin immediate here so that if we need to retry, we
+ ;; figure that out immediately rather than because some SQLITE_BUSY
+ ;; exception gets thrown partway through PROC - in which case the
+ ;; part already executed (which may contain side-effects!) would be
+ ;; executed again for every retry.
+ (sqlite-exec db "begin immediate;")
+ (let ((result (proc)))
+ (sqlite-exec db "commit;")
+ result))
+ (lambda (key who error description)
+ (if (= error SQLITE_BUSY)
+ (call-with-transaction db proc)
+ (begin
+ (sqlite-exec db "rollback;")
+ (throw 'sqlite-error who error description))))))
+
(define %default-database-file
;; Default location of the store database.
(string-append %store-database-directory "/db.sqlite"))
@@ -172,9 +197,9 @@ ids of items referred to."
(sqlite-bind-arguments stmt #:referrer referrer
#:reference reference)
(sqlite-fold cons '() stmt) ;execute it
- (sqlite-finalize stmt)
(last-insert-row-id db))
- references)))
+ references)
+ (sqlite-finalize stmt)))
(define* (sqlite-register db #:key path (references '())
deriver hash nar-size time)
@@ -305,6 +330,7 @@ Write a progress report to LOG-PORT."
(define real-file-name
(string-append store-dir "/" (basename (store-info-item item))))
+
;; When TO-REGISTER is already registered, skip it. This makes a
;; significant differences when 'register-closures' is called
;; consecutively for overlapping closures such as 'system' and 'bootcfg'.
@@ -325,12 +351,14 @@ Write a progress report to LOG-PORT."
(mkdir-p db-dir)
(parameterize ((sql-schema schema))
(with-database (string-append db-dir "/db.sqlite") db
- (let* ((prefix (format #f "registering ~a items" (length items)))
- (progress (progress-reporter/bar (length items)
- prefix log-port)))
- (call-with-progress-reporter progress
- (lambda (report)
- (for-each (lambda (item)
- (register db item)
- (report))
- items)))))))
+ (call-with-transaction db
+ (lambda ()
+ (let* ((prefix (format #f "registering ~a items" (length items)))
+ (progress (progress-reporter/bar (length items)
+ prefix log-port)))
+ (call-with-progress-reporter progress
+ (lambda (report)
+ (for-each (lambda (item)
+ (register db item)
+ (report))
+ items)))))))))
- branch guile-daemon created (now 7b291ff), guix-commits, 2019/02/17
- 02/10: guix: store: Make register-items transactional.,
guix-commits <=
- 01/10: gnu: address@hidden: Honor NIX_STORE., guix-commits, 2019/02/17
- 09/10: build-derivations: Leaked environment variables more robust., guix-commits, 2019/02/17
- 05/10: linux-container: new use-output argument., guix-commits, 2019/02/17
- 03/10: guix: store: Register derivation outputs., guix-commits, 2019/02/17
- 07/10: build-derivations: initial build-group support, guix-commits, 2019/02/17
- 10/10: gnu: linux-container: Make it more suitable for derivation-building., guix-commits, 2019/02/17
- 06/10: build-derivations: use call-with-container, guix-commits, 2019/02/17
- 08/10: linux-container: don't include /dev/ptmx or /dev/pts from host., guix-commits, 2019/02/17
- 04/10: guix/store/build-derivations.scm: new module., guix-commits, 2019/02/17