database.scm 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446
  1. ;;; GNU Guix --- Functional package management for GNU
  2. ;;; Copyright © 2017, 2019 Caleb Ristvedt <caleb.ristvedt@cune.org>
  3. ;;; Copyright © 2018, 2020, 2021 Ludovic Courtès <ludo@gnu.org>
  4. ;;; Copyright © 2020 Jan (janneke) Nieuwenhuizen <janneke@gnu.org>
  5. ;;; Copyright © 2022 Efraim Flashner <efraim@flashner.co.il>
  6. ;;;
  7. ;;; This file is part of GNU Guix.
  8. ;;;
  9. ;;; GNU Guix is free software; you can redistribute it and/or modify it
  10. ;;; under the terms of the GNU General Public License as published by
  11. ;;; the Free Software Foundation; either version 3 of the License, or (at
  12. ;;; your option) any later version.
  13. ;;;
  14. ;;; GNU Guix is distributed in the hope that it will be useful, but
  15. ;;; WITHOUT ANY WARRANTY; without even the implied warranty of
  16. ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17. ;;; GNU General Public License for more details.
  18. ;;;
  19. ;;; You should have received a copy of the GNU General Public License
  20. ;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
  21. (define-module (guix store database)
  22. #:use-module (sqlite3)
  23. #:use-module (guix config)
  24. #:use-module (guix store deduplication)
  25. #:use-module (guix base16)
  26. #:use-module (guix progress)
  27. #:use-module (guix build syscalls)
  28. #:use-module ((guix build utils)
  29. #:select (mkdir-p executable-file?))
  30. #:use-module (guix build store-copy)
  31. #:use-module (srfi srfi-1)
  32. #:use-module (srfi srfi-11)
  33. #:use-module (srfi srfi-19)
  34. #:use-module (srfi srfi-26)
  35. #:use-module (rnrs io ports)
  36. #:use-module (ice-9 match)
  37. #:export (sql-schema
  38. %default-database-file
  39. store-database-file
  40. call-with-database
  41. with-database
  42. path-id
  43. sqlite-register
  44. register-items
  45. %epoch
  46. reset-timestamps
  47. vacuum-database))
  48. ;;; Code for working with the store database directly.
  49. (define sql-schema
  50. ;; Name of the file containing the SQL scheme or #f.
  51. (make-parameter #f))
  52. (define* (store-database-directory #:key prefix state-directory)
  53. "Return the store database directory, taking PREFIX and STATE-DIRECTORY into
  54. account when provided."
  55. ;; Priority for options: first what is given, then environment variables,
  56. ;; then defaults. %state-directory, %store-directory, and
  57. ;; %store-database-directory already handle the "environment variables /
  58. ;; defaults" question, so we only need to choose between what is given and
  59. ;; those.
  60. (cond (state-directory
  61. (string-append state-directory "/db"))
  62. (prefix
  63. (string-append prefix %localstatedir "/guix/db"))
  64. (else
  65. %store-database-directory)))
  66. (define* (store-database-file #:key prefix state-directory)
  67. "Return the store database file name, taking PREFIX and STATE-DIRECTORY into
  68. account when provided."
  69. (string-append (store-database-directory #:prefix prefix
  70. #:state-directory state-directory)
  71. "/db.sqlite"))
  72. (define (initialize-database db)
  73. "Initializing DB, an empty database, by creating all the tables and indexes
  74. as specified by SQL-SCHEMA."
  75. (define schema
  76. (or (sql-schema)
  77. (search-path %load-path "guix/store/schema.sql")))
  78. (sqlite-exec db (call-with-input-file schema get-string-all)))
  79. (define* (call-with-database file proc #:key (wal-mode? #t))
  80. "Pass PROC a database record corresponding to FILE. If FILE doesn't exist,
  81. create it and initialize it as a new database. Unless WAL-MODE? is set to #f,
  82. set journal_mode=WAL."
  83. (let ((new? (and (not (file-exists? file))
  84. (begin
  85. (mkdir-p (dirname file))
  86. #t)))
  87. (db (sqlite-open file)))
  88. ;; Using WAL breaks for the Hurd <https://bugs.gnu.org/42151>.
  89. (when wal-mode?
  90. ;; Turn DB in "write-ahead log" mode, which should avoid SQLITE_LOCKED
  91. ;; errors when we have several readers: <https://www.sqlite.org/wal.html>.
  92. (sqlite-exec db "PRAGMA journal_mode=WAL;"))
  93. ;; Install a busy handler such that, when the database is locked, sqlite
  94. ;; retries until 30 seconds have passed, at which point it gives up and
  95. ;; throws SQLITE_BUSY.
  96. (sqlite-exec db "PRAGMA busy_timeout = 30000;")
  97. (dynamic-wind noop
  98. (lambda ()
  99. (when new?
  100. (initialize-database db))
  101. (proc db))
  102. (lambda ()
  103. (sqlite-close db)))))
  104. ;; XXX: missing in guile-sqlite3@0.1.2
  105. (define SQLITE_BUSY 5)
  106. (define (call-with-SQLITE_BUSY-retrying thunk)
  107. "Call THUNK, retrying as long as it exits abnormally due to SQLITE_BUSY
  108. errors."
  109. (catch 'sqlite-error
  110. thunk
  111. (lambda (key who code errmsg)
  112. (if (= code SQLITE_BUSY)
  113. (call-with-SQLITE_BUSY-retrying thunk)
  114. (throw key who code errmsg)))))
  115. (define* (call-with-transaction db proc #:key restartable?)
  116. "Start a transaction with DB and run PROC. If PROC exits abnormally, abort
  117. the transaction, otherwise commit the transaction after it finishes.
  118. RESTARTABLE? may be set to a non-#f value when it is safe to run PROC multiple
  119. times. This may reduce contention for the database somewhat."
  120. (define (exec sql)
  121. (with-statement db sql stmt
  122. (sqlite-fold cons '() stmt)))
  123. ;; We might use begin immediate here so that if we need to retry, we figure
  124. ;; that out immediately rather than because some SQLITE_BUSY exception gets
  125. ;; thrown partway through PROC - in which case the part already executed
  126. ;; (which may contain side-effects!) might have to be executed again for
  127. ;; every retry.
  128. (exec (if restartable? "begin;" "begin immediate;"))
  129. (catch #t
  130. (lambda ()
  131. (let-values ((result (proc)))
  132. (exec "commit;")
  133. (apply values result)))
  134. (lambda args
  135. ;; The roll back may or may not have occurred automatically when the
  136. ;; error was generated. If it has occurred, this does nothing but signal
  137. ;; an error. If it hasn't occurred, this needs to be done.
  138. (false-if-exception (exec "rollback;"))
  139. (apply throw args))))
  140. (define* (call-with-savepoint db proc
  141. #:optional (savepoint-name "SomeSavepoint"))
  142. "Call PROC after creating a savepoint named SAVEPOINT-NAME. If PROC exits
  143. abnormally, rollback to that savepoint. In all cases, remove the savepoint
  144. prior to returning."
  145. (define (exec sql)
  146. (with-statement db sql stmt
  147. (sqlite-fold cons '() stmt)))
  148. (dynamic-wind
  149. (lambda ()
  150. (exec (string-append "SAVEPOINT " savepoint-name ";")))
  151. (lambda ()
  152. (catch #t
  153. proc
  154. (lambda args
  155. (exec (string-append "ROLLBACK TO " savepoint-name ";"))
  156. (apply throw args))))
  157. (lambda ()
  158. (exec (string-append "RELEASE " savepoint-name ";")))))
  159. (define* (call-with-retrying-transaction db proc #:key restartable?)
  160. (call-with-SQLITE_BUSY-retrying
  161. (lambda ()
  162. (call-with-transaction db proc #:restartable? restartable?))))
  163. (define* (call-with-retrying-savepoint db proc
  164. #:optional (savepoint-name
  165. "SomeSavepoint"))
  166. (call-with-SQLITE_BUSY-retrying
  167. (lambda ()
  168. (call-with-savepoint db proc savepoint-name))))
  169. (define %default-database-file
  170. ;; Default location of the store database.
  171. (string-append %store-database-directory "/db.sqlite"))
  172. (define-syntax with-database
  173. (syntax-rules ()
  174. "Open DB from FILE and close it when the dynamic extent of EXP... is left.
  175. If FILE doesn't exist, create it and initialize it as a new database. Pass
  176. #:wal-mode? to call-with-database."
  177. ((_ file db #:wal-mode? wal-mode? exp ...)
  178. (call-with-database file (lambda (db) exp ...) #:wal-mode? wal-mode?))
  179. ((_ file db exp ...)
  180. (call-with-database file (lambda (db) exp ...)))))
  181. (define (call-with-statement db sql proc)
  182. (let ((stmt (sqlite-prepare db sql #:cache? #t)))
  183. (dynamic-wind
  184. (const #t)
  185. (lambda ()
  186. (proc stmt))
  187. (lambda ()
  188. (sqlite-finalize stmt)))))
  189. (define-syntax-rule (with-statement db sql stmt exp ...)
  190. "Run EXP... with STMT bound to a prepared statement corresponding to the sql
  191. string SQL for DB."
  192. (call-with-statement db sql
  193. (lambda (stmt) exp ...)))
  194. (define (last-insert-row-id db)
  195. ;; XXX: (sqlite3) currently lacks bindings for 'sqlite3_last_insert_rowid'.
  196. ;; Work around that.
  197. (with-statement db "SELECT last_insert_rowid();" stmt
  198. (match (sqlite-fold cons '() stmt)
  199. ((#(id)) id)
  200. (_ #f))))
  201. (define path-id-sql
  202. "SELECT id FROM ValidPaths WHERE path = :path")
  203. (define* (path-id db path)
  204. "If PATH exists in the 'ValidPaths' table, return its numerical
  205. identifier. Otherwise, return #f."
  206. (with-statement db path-id-sql stmt
  207. (sqlite-bind-arguments stmt #:path path)
  208. (match (sqlite-fold cons '() stmt)
  209. ((#(id) . _) id)
  210. (_ #f))))
  211. (define update-sql
  212. "UPDATE ValidPaths SET hash = :hash, registrationTime = :time, deriver =
  213. :deriver, narSize = :size WHERE id = :id")
  214. (define insert-sql
  215. "INSERT INTO ValidPaths (path, hash, registrationTime, deriver, narSize)
  216. VALUES (:path, :hash, :time, :deriver, :size)")
  217. (define-inlinable (assert-integer proc in-range? key number)
  218. (unless (integer? number)
  219. (throw 'wrong-type-arg proc
  220. "Wrong type argument ~A: ~S" (list key number)
  221. (list number)))
  222. (unless (in-range? number)
  223. (throw 'out-of-range proc
  224. "Integer ~A out of range: ~S" (list key number)
  225. (list number))))
  226. (define* (update-or-insert db #:key path deriver hash nar-size time)
  227. "The classic update-if-exists and insert-if-doesn't feature that sqlite
  228. doesn't exactly have... they've got something close, but it involves deleting
  229. and re-inserting instead of updating, which causes problems with foreign keys,
  230. of course. Returns the row id of the row that was modified or inserted."
  231. ;; Make sure NAR-SIZE is valid.
  232. (assert-integer "update-or-insert" positive? #:nar-size nar-size)
  233. (assert-integer "update-or-insert" (cut >= <> 0) #:time time)
  234. ;; It's important that querying the path-id and the insert/update operation
  235. ;; take place in the same transaction, as otherwise some other
  236. ;; process/thread/fiber could register the same path between when we check
  237. ;; whether it's already registered and when we register it, resulting in
  238. ;; duplicate paths (which, due to a 'unique' constraint, would cause an
  239. ;; exception to be thrown). With the default journaling mode this will
  240. ;; prevent writes from occurring during that sensitive time, but with WAL
  241. ;; mode it will instead arrange to return SQLITE_BUSY when a write occurs
  242. ;; between the start of a read transaction and its upgrading to a write
  243. ;; transaction (see https://sqlite.org/rescode.html#busy_snapshot).
  244. ;; Experimentally, it seems this SQLITE_BUSY will ignore a busy_timeout and
  245. ;; immediately return (makes sense, since waiting won't change anything).
  246. ;; Note that when that kind of SQLITE_BUSY error is returned, it will keep
  247. ;; being returned every time we try to upgrade the same outermost
  248. ;; transaction to a write transaction. So when retrying, we have to restart
  249. ;; the *outermost* write transaction. We can't inherently tell whether
  250. ;; we're the outermost write transaction, so we leave the retry-handling to
  251. ;; the caller.
  252. (call-with-savepoint db
  253. (lambda ()
  254. (let ((id (path-id db path)))
  255. (if id
  256. (with-statement db update-sql stmt
  257. (sqlite-bind-arguments stmt #:id id
  258. #:deriver deriver
  259. #:hash hash #:size nar-size #:time time)
  260. (sqlite-fold cons '() stmt))
  261. (with-statement db insert-sql stmt
  262. (sqlite-bind-arguments stmt
  263. #:path path #:deriver deriver
  264. #:hash hash #:size nar-size #:time time)
  265. (sqlite-fold cons '() stmt)))
  266. (last-insert-row-id db)))))
  267. (define add-reference-sql
  268. "INSERT OR REPLACE INTO Refs (referrer, reference) VALUES (:referrer, :reference);")
  269. (define (add-references db referrer references)
  270. "REFERRER is the id of the referring store item, REFERENCES is a list
  271. ids of items referred to."
  272. (with-statement db add-reference-sql stmt
  273. (for-each (lambda (reference)
  274. (sqlite-reset stmt)
  275. (sqlite-bind-arguments stmt #:referrer referrer
  276. #:reference reference)
  277. (sqlite-fold cons '() stmt))
  278. references)))
  279. (define (timestamp)
  280. "Return a timestamp, either the current time of SOURCE_DATE_EPOCH."
  281. (match (getenv "SOURCE_DATE_EPOCH")
  282. (#f
  283. (current-time time-utc))
  284. ((= string->number seconds)
  285. (if seconds
  286. (make-time time-utc 0 seconds)
  287. (current-time time-utc)))))
  288. (define* (sqlite-register db #:key path (references '())
  289. deriver hash nar-size
  290. (time (timestamp)))
  291. "Registers this stuff in DB. PATH is the store item to register and
  292. REFERENCES is the list of store items PATH refers to; DERIVER is the '.drv'
  293. that produced PATH, HASH is the base16-encoded Nix sha256 hash of
  294. PATH (prefixed with \"sha256:\"), and NAR-SIZE is the size in bytes PATH after
  295. being converted to nar form. TIME is the registration time to be recorded in
  296. the database or #f, meaning \"right now\".
  297. Every store item in REFERENCES must already be registered."
  298. (let ((id (update-or-insert db #:path path
  299. #:deriver deriver
  300. #:hash hash
  301. #:nar-size nar-size
  302. #:time (time-second time))))
  303. ;; Call 'path-id' on each of REFERENCES. This ensures we get a
  304. ;; "non-NULL constraint" failure if one of REFERENCES is unregistered.
  305. (add-references db id
  306. (map (cut path-id db <>) references))))
  307. ;;;
  308. ;;; High-level interface.
  309. ;;;
  310. (define* (reset-timestamps file #:key preserve-permissions?)
  311. "Reset the modification time on FILE and on all the files it contains, if
  312. it's a directory. Canonicalize file permissions unless PRESERVE-PERMISSIONS?
  313. is true."
  314. ;; Note: We're resetting to one second after the Epoch like 'guix-daemon'
  315. ;; has always done.
  316. (let loop ((file file)
  317. (type (stat:type (lstat file))))
  318. (case type
  319. ((directory)
  320. (unless preserve-permissions?
  321. (chmod file #o555))
  322. (utime file 1 1 0 0)
  323. (let ((parent file))
  324. (for-each (match-lambda
  325. (("." . _) #f)
  326. ((".." . _) #f)
  327. ((file . properties)
  328. (let ((file (string-append parent "/" file)))
  329. (loop file
  330. (match (assoc-ref properties 'type)
  331. ((or 'unknown #f)
  332. (stat:type (lstat file)))
  333. (type type))))))
  334. (scandir* parent))))
  335. ((symlink)
  336. (utime file 1 1 0 0 AT_SYMLINK_NOFOLLOW))
  337. (else
  338. (unless preserve-permissions?
  339. (chmod file (if (executable-file? file) #o555 #o444)))
  340. (utime file 1 1 0 0)))))
  341. (define %epoch
  342. ;; When it all began.
  343. (make-time time-utc 0 1))
  344. (define* (register-items db items
  345. #:key prefix
  346. (registration-time (timestamp))
  347. (log-port (current-error-port)))
  348. "Register all of ITEMS, a list of <store-info> records as returned by
  349. 'read-reference-graph', in DB. ITEMS must be in topological order (with
  350. leaves first.) REGISTRATION-TIME must be the registration time to be recorded
  351. in the database; #f means \"now\". Write a progress report to LOG-PORT. All
  352. of ITEMS must be protected from GC and locked during execution of this,
  353. typically by adding them as temp-roots."
  354. (define store-dir
  355. (if prefix
  356. (string-append prefix %storedir)
  357. %store-directory))
  358. (define (register db item)
  359. (define to-register
  360. (if prefix
  361. (string-append %storedir "/" (basename (store-info-item item)))
  362. ;; note: we assume here that if path is, for example,
  363. ;; /foo/bar/gnu/store/thing.txt and prefix isn't given, then an
  364. ;; environment variable has been used to change the store directory
  365. ;; to /foo/bar/gnu/store, since otherwise real-path would end up
  366. ;; being /gnu/store/thing.txt, which is probably not the right file
  367. ;; in this case.
  368. (store-info-item item)))
  369. (define real-file-name
  370. (string-append store-dir "/" (basename (store-info-item item))))
  371. ;; When TO-REGISTER is already registered, skip it. This makes a
  372. ;; significant differences when 'register-closures' is called
  373. ;; consecutively for overlapping closures such as 'system' and 'bootcfg'.
  374. (unless (path-id db to-register)
  375. (let-values (((hash nar-size) (nar-sha256 real-file-name)))
  376. (call-with-retrying-transaction db
  377. (lambda ()
  378. (sqlite-register db #:path to-register
  379. #:references (store-info-references item)
  380. #:deriver (store-info-deriver item)
  381. #:hash (string-append
  382. "sha256:"
  383. (bytevector->base16-string hash))
  384. #:nar-size nar-size
  385. #:time registration-time))))))
  386. (let* ((prefix (format #f "registering ~a items" (length items)))
  387. (progress (progress-reporter/bar (length items)
  388. prefix log-port)))
  389. (call-with-progress-reporter progress
  390. (lambda (report)
  391. (for-each (lambda (item)
  392. (register db item)
  393. (report))
  394. items)))))
  395. (define (vacuum-database)
  396. (let ((db (sqlite-open (store-database-file))))
  397. (sqlite-exec db "VACUUM;")
  398. (sqlite-close db)))