store: Avoid use of `set!'.
[jackhill/guix/guix.git] / guix / store.scm
CommitLineData
233e7676 1;;; GNU Guix --- Functional package management for GNU
34fcbe3a 2;;; Copyright © 2012, 2013 Ludovic Courtès <ludo@gnu.org>
77d3cf08 3;;;
233e7676 4;;; This file is part of GNU Guix.
77d3cf08 5;;;
233e7676 6;;; GNU Guix is free software; you can redistribute it and/or modify it
77d3cf08
LC
7;;; under the terms of the GNU General Public License as published by
8;;; the Free Software Foundation; either version 3 of the License, or (at
9;;; your option) any later version.
10;;;
233e7676 11;;; GNU Guix is distributed in the hope that it will be useful, but
77d3cf08
LC
12;;; WITHOUT ANY WARRANTY; without even the implied warranty of
13;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14;;; GNU General Public License for more details.
15;;;
16;;; You should have received a copy of the GNU General Public License
233e7676 17;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
77d3cf08
LC
18
19(define-module (guix store)
82058eff 20 #:use-module (guix utils)
d8eea3d2 21 #:use-module (guix config)
77d3cf08
LC
22 #:use-module (rnrs bytevectors)
23 #:use-module (rnrs io ports)
24 #:use-module (srfi srfi-1)
25 #:use-module (srfi srfi-9)
26 #:use-module (srfi srfi-26)
e87088c9
LC
27 #:use-module (srfi srfi-34)
28 #:use-module (srfi srfi-35)
26bbbb95 29 #:use-module (srfi srfi-39)
77d3cf08
LC
30 #:use-module (ice-9 match)
31 #:use-module (ice-9 rdelim)
b37eb5ed 32 #:use-module (ice-9 ftw)
e3d74106 33 #:use-module (ice-9 regex)
77d3cf08
LC
34 #:export (nix-server?
35 nix-server-major-version
36 nix-server-minor-version
37 nix-server-socket
38
e87088c9
LC
39 &nix-error nix-error?
40 &nix-protocol-error nix-protocol-error?
41 nix-protocol-error-message
42 nix-protocol-error-status
43
26bbbb95
LC
44 hash-algo
45
77d3cf08 46 open-connection
3abaf0c4 47 close-connection
77d3cf08 48 set-build-options
31ef99a8 49 valid-path?
82058eff 50 query-path-hash
77d3cf08
LC
51 add-text-to-store
52 add-to-store
26bbbb95 53 build-derivations
3259877d 54 add-temp-root
34811f02 55 add-indirect-root
26bbbb95 56
3259877d
LC
57 live-paths
58 dead-paths
59 collect-garbage
60 delete-paths
61
dcee50c1
LC
62 current-build-output-port
63
26bbbb95
LC
64 %store-prefix
65 store-path?
e3d74106
LC
66 derivation-path?
67 store-path-package-name))
77d3cf08 68
e36a7172 69(define %protocol-version #x10b)
77d3cf08
LC
70
71(define %worker-magic-1 #x6e697863)
72(define %worker-magic-2 #x6478696f)
73
74(define (protocol-major magic)
75 (logand magic #xff00))
76(define (protocol-minor magic)
77 (logand magic #x00ff))
78
79(define-syntax define-enumerate-type
80 (syntax-rules ()
81 ((_ name->int (name id) ...)
82 (define-syntax name->int
83 (syntax-rules (name ...)
84 ((_ name) id) ...)))))
85
86(define-enumerate-type operation-id
87 ;; operation numbers from worker-protocol.hh
88 (quit 0)
89 (valid-path? 1)
90 (has-substitutes? 3)
91 (query-path-hash 4)
92 (query-references 5)
93 (query-referrers 6)
94 (add-to-store 7)
95 (add-text-to-store 8)
96 (build-derivations 9)
97 (ensure-path 10)
98 (add-temp-root 11)
99 (add-indirect-root 12)
100 (sync-with-gc 13)
101 (find-roots 14)
102 (export-path 16)
103 (query-deriver 18)
104 (set-options 19)
105 (collect-garbage 20)
106 (query-substitutable-path-info 21)
107 (query-derivation-outputs 22)
108 (query-valid-paths 23)
109 (query-failed-paths 24)
110 (clear-failed-paths 25)
111 (query-path-info 26)
112 (import-paths 27)
113 (query-derivation-output-names 28))
114
115(define-enumerate-type hash-algo
116 ;; hash.hh
117 (md5 1)
118 (sha1 2)
119 (sha256 3))
120
3259877d
LC
121(define-enumerate-type gc-action
122 ;; store-api.hh
123 (return-live 0)
124 (return-dead 1)
125 (delete-dead 2)
126 (delete-specific 3))
127
77d3cf08 128(define %default-socket-path
d8eea3d2
LC
129 (string-append (or (getenv "NIX_STATE_DIR") %state-directory)
130 "/daemon-socket/socket"))
77d3cf08
LC
131
132\f
133;; serialize.cc
134
135(define (write-int n p)
136 (let ((b (make-bytevector 8 0)))
137 (bytevector-u32-set! b 0 n (endianness little))
138 (put-bytevector p b)))
139
140(define (read-int p)
141 (let ((b (get-bytevector-n p 8)))
142 (bytevector-u32-ref b 0 (endianness little))))
143
144(define (write-long-long n p)
145 (let ((b (make-bytevector 8 0)))
146 (bytevector-u64-set! b 0 n (endianness little))
147 (put-bytevector p b)))
148
3259877d
LC
149(define (read-long-long p)
150 (let ((b (get-bytevector-n p 8)))
151 (bytevector-u64-ref b 0 (endianness little))))
152
77d3cf08
LC
153(define write-padding
154 (let ((zero (make-bytevector 8 0)))
155 (lambda (n p)
156 (let ((m (modulo n 8)))
157 (or (zero? m)
158 (put-bytevector p zero 0 (- 8 m)))))))
159
160(define (write-string s p)
82c38fe6
LC
161 (let* ((s (string->utf8 s))
162 (l (bytevector-length s))
163 (m (modulo l 8))
164 (b (make-bytevector (+ 8 l (if (zero? m) 0 (- 8 m))))))
165 (bytevector-u64-native-set! b 0 l)
166 (bytevector-copy! s 0 b 8 l)
167 (put-bytevector p b)))
77d3cf08
LC
168
169(define (read-string p)
170 (let* ((len (read-int p))
171 (m (modulo len 8))
172 (bv (get-bytevector-n p len))
173 (str (utf8->string bv)))
174 (or (zero? m)
175 (get-bytevector-n p (- 8 m)))
176 str))
177
178(define (write-string-list l p)
179 (write-int (length l) p)
180 (for-each (cut write-string <> p) l))
181
3259877d
LC
182(define (read-string-list p)
183 (let ((len (read-int p)))
184 (unfold (cut >= <> len)
185 (lambda (i)
186 (read-string p))
187 1+
188 0)))
189
190(define (write-store-path f p)
191 (write-string f p)) ; TODO: assert path
192
77d3cf08
LC
193(define (read-store-path p)
194 (read-string p)) ; TODO: assert path
195
3259877d
LC
196(define write-store-path-list write-string-list)
197(define read-store-path-list read-string-list)
198
77d3cf08
LC
199(define (write-contents file p)
200 "Write the contents of FILE to output port P."
201 (define (dump in size)
202 (define buf-size 65536)
203 (define buf (make-bytevector buf-size))
204
205 (let loop ((left size))
206 (if (<= left 0)
207 0
208 (let ((read (get-bytevector-n! in buf 0 buf-size)))
209 (if (eof-object? read)
210 left
211 (begin
212 (put-bytevector p buf 0 read)
213 (loop (- left read))))))))
214
215 (let ((size (stat:size (lstat file))))
216 (write-string "contents" p)
217 (write-long-long size p)
218 (call-with-input-file file
219 (lambda (p)
220 (dump p size)))
221 (write-padding size p)))
222
223(define (write-file f p)
224 (define %archive-version-1 "nix-archive-1")
225
b37eb5ed
LC
226 (write-string %archive-version-1 p)
227
228 (let dump ((f f))
229 (let ((s (lstat f)))
230 (write-string "(" p)
231 (case (stat:type s)
232 ((regular)
233 (write-string "type" p)
234 (write-string "regular" p)
235 (if (not (zero? (logand (stat:mode s) #o100)))
236 (begin
237 (write-string "executable" p)
238 (write-string "" p)))
239 (write-contents f p))
240 ((directory)
241 (write-string "type" p)
242 (write-string "directory" p)
243 (let ((entries (remove (cut member <> '("." ".."))
244 (scandir f))))
245 (for-each (lambda (e)
246 (let ((f (string-append f "/" e)))
247 (write-string "entry" p)
248 (write-string "(" p)
249 (write-string "name" p)
250 (write-string e p)
251 (write-string "node" p)
252 (dump f)
253 (write-string ")" p)))
254 entries)))
255 (else
256 (error "ENOSYS")))
257 (write-string ")" p))))
77d3cf08
LC
258
259(define-syntax write-arg
3259877d
LC
260 (syntax-rules (integer boolean file string string-list
261 store-path store-path-list base16)
77d3cf08
LC
262 ((_ integer arg p)
263 (write-int arg p))
264 ((_ boolean arg p)
265 (write-int (if arg 1 0) p))
266 ((_ file arg p)
267 (write-file arg p))
268 ((_ string arg p)
269 (write-string arg p))
270 ((_ string-list arg p)
82058eff 271 (write-string-list arg p))
3259877d
LC
272 ((_ store-path arg p)
273 (write-store-path arg p))
274 ((_ store-path-list arg p)
275 (write-store-path-list arg p))
82058eff
LC
276 ((_ base16 arg p)
277 (write-string (bytevector->base16-string arg) p))))
77d3cf08
LC
278
279(define-syntax read-arg
3259877d 280 (syntax-rules (integer boolean string store-path store-path-list base16)
77d3cf08
LC
281 ((_ integer p)
282 (read-int p))
283 ((_ boolean p)
284 (not (zero? (read-int p))))
285 ((_ string p)
286 (read-string p))
287 ((_ store-path p)
82058eff 288 (read-store-path p))
3259877d
LC
289 ((_ store-path-list p)
290 (read-store-path-list p))
82058eff
LC
291 ((_ hash p)
292 (base16-string->bytevector (read-string p)))))
77d3cf08
LC
293
294\f
295;; remote-store.cc
296
297(define-record-type <nix-server>
2c3f47ee 298 (%make-nix-server socket major minor
bdcf35a6 299 ats-cache atts-cache)
77d3cf08
LC
300 nix-server?
301 (socket nix-server-socket)
302 (major nix-server-major-version)
2c3f47ee
LC
303 (minor nix-server-minor-version)
304
305 ;; Caches. We keep them per-connection, because store paths build
306 ;; during the session are temporary GC roots kept for the duration of
307 ;; the session.
bdcf35a6
LC
308 (ats-cache nix-server-add-to-store-cache)
309 (atts-cache nix-server-add-text-to-store-cache))
77d3cf08 310
e87088c9
LC
311(define-condition-type &nix-error &error
312 nix-error?)
313
314(define-condition-type &nix-protocol-error &nix-error
315 nix-protocol-error?
316 (message nix-protocol-error-message)
317 (status nix-protocol-error-status))
318
e36a7172
LC
319(define* (open-connection #:optional (file %default-socket-path)
320 #:key (reserve-space? #t))
e531ac2a
LC
321 "Connect to the daemon over the Unix-domain socket at FILE. When
322RESERVE-SPACE? is true, instruct it to reserve a little bit of extra
323space on the file system so that the garbage collector can still
324operate, should the disk become full. Return a server object."
77d3cf08
LC
325 (let ((s (with-fluids ((%default-port-encoding #f))
326 ;; This trick allows use of the `scm_c_read' optimization.
327 (socket PF_UNIX SOCK_STREAM 0)))
328 (a (make-socket-address PF_UNIX file)))
df1fab58
LC
329
330 ;; Enlarge the receive buffer.
331 (setsockopt s SOL_SOCKET SO_RCVBUF (* 12 1024))
332
77d3cf08
LC
333 (connect s a)
334 (write-int %worker-magic-1 s)
335 (let ((r (read-int s)))
336 (and (eqv? r %worker-magic-2)
337 (let ((v (read-int s)))
338 (and (eqv? (protocol-major %protocol-version)
339 (protocol-major v))
340 (begin
341 (write-int %protocol-version s)
e36a7172
LC
342 (if (>= (protocol-minor v) 11)
343 (write-int (if reserve-space? 1 0) s))
77d3cf08
LC
344 (let ((s (%make-nix-server s
345 (protocol-major v)
2c3f47ee 346 (protocol-minor v)
bdcf35a6 347 (make-hash-table)
2c3f47ee 348 (make-hash-table))))
34fcbe3a
LC
349 (let loop ((done? (process-stderr s)))
350 (or done? (process-stderr s)))
77d3cf08
LC
351 s))))))))
352
3abaf0c4
LC
353(define (close-connection server)
354 "Close the connection to SERVER."
355 (close (nix-server-socket server)))
356
dcee50c1
LC
357(define current-build-output-port
358 ;; The port where build output is sent.
359 (make-parameter (current-error-port)))
360
77d3cf08 361(define (process-stderr server)
dcee50c1
LC
362 "Read standard output and standard error from SERVER, writing it to
363CURRENT-BUILD-OUTPUT-PORT. Return #t when SERVER is done sending data, and
364#f otherwise; in the latter case, the caller should call `process-stderr'
365again until #t is returned or an error is raised."
77d3cf08
LC
366 (define p
367 (nix-server-socket server))
368
369 ;; magic cookies from worker-protocol.hh
370 (define %stderr-next #x6f6c6d67)
371 (define %stderr-read #x64617461) ; data needed from source
372 (define %stderr-write #x64617416) ; data for sink
373 (define %stderr-last #x616c7473)
374 (define %stderr-error #x63787470)
375
376 (let ((k (read-int p)))
377 (cond ((= k %stderr-write)
dcee50c1
LC
378 (read-string p)
379 #f)
77d3cf08
LC
380 ((= k %stderr-read)
381 (let ((len (read-int p)))
382 (read-string p) ; FIXME: what to do?
dcee50c1 383 #f))
77d3cf08
LC
384 ((= k %stderr-next)
385 (let ((s (read-string p)))
dcee50c1
LC
386 (display s (current-build-output-port))
387 #f))
77d3cf08
LC
388 ((= k %stderr-error)
389 (let ((error (read-string p))
390 (status (if (>= (nix-server-minor-version server) 8)
391 (read-int p)
392 1)))
e87088c9
LC
393 (raise (condition (&nix-protocol-error
394 (message error)
395 (status status))))))
77d3cf08 396 ((= k %stderr-last)
dcee50c1 397 ;; The daemon is done (see `stopWork' in `nix-worker.cc'.)
77d3cf08
LC
398 #t)
399 (else
e87088c9
LC
400 (raise (condition (&nix-protocol-error
401 (message "invalid error code")
402 (status k))))))))
77d3cf08
LC
403
404(define* (set-build-options server
405 #:key keep-failed? keep-going? try-fallback?
406 (verbosity 0)
407 (max-build-jobs (current-processor-count))
408 (max-silent-time 3600)
409 (use-build-hook? #t)
410 (build-verbosity 0)
411 (log-type 0)
e036c31b
LC
412 (print-build-trace #t)
413 (build-cores 1)
414 (use-substitutes? #t))
77d3cf08
LC
415 ;; Must be called after `open-connection'.
416
417 (define socket
418 (nix-server-socket server))
419
420 (let-syntax ((send (syntax-rules ()
e036c31b
LC
421 ((_ (type option) ...)
422 (begin
423 (write-arg type option socket)
424 ...)))))
425 (write-int (operation-id set-options) socket)
426 (send (boolean keep-failed?) (boolean keep-going?)
427 (boolean try-fallback?) (integer verbosity)
428 (integer max-build-jobs) (integer max-silent-time))
77d3cf08 429 (if (>= (nix-server-minor-version server) 2)
e036c31b 430 (send (boolean use-build-hook?)))
77d3cf08 431 (if (>= (nix-server-minor-version server) 4)
e036c31b
LC
432 (send (integer build-verbosity) (integer log-type)
433 (boolean print-build-trace)))
434 (if (>= (nix-server-minor-version server) 6)
435 (send (integer build-cores)))
436 (if (>= (nix-server-minor-version server) 10)
437 (send (boolean use-substitutes?)))
dcee50c1
LC
438 (let loop ((done? (process-stderr server)))
439 (or done? (process-stderr server)))))
77d3cf08 440
fd060fd3 441(define-syntax operation
77d3cf08 442 (syntax-rules ()
fd060fd3 443 "Define a client-side RPC stub for the given operation."
3259877d 444 ((_ (name (type arg) ...) docstring return ...)
fd060fd3 445 (lambda (server arg ...)
77d3cf08
LC
446 docstring
447 (let ((s (nix-server-socket server)))
448 (write-int (operation-id name) s)
449 (write-arg type arg s)
450 ...
dcee50c1
LC
451 ;; Loop until the server is done sending error output.
452 (let loop ((done? (process-stderr server)))
453 (or done? (loop (process-stderr server))))
3259877d 454 (values (read-arg return s) ...))))))
77d3cf08 455
fd060fd3
LC
456(define-syntax-rule (define-operation (name args ...)
457 docstring return ...)
458 (define name
459 (operation (name args ...) docstring return ...)))
460
31ef99a8
LC
461(define-operation (valid-path? (string path))
462 "Return #t when PATH is a valid store path."
463 boolean)
464
82058eff
LC
465(define-operation (query-path-hash (string path))
466 "Return the SHA256 hash of PATH as a bytevector."
467 base16)
468
fd060fd3
LC
469(define add-text-to-store
470 ;; A memoizing version of `add-to-store', to avoid repeated RPCs with
471 ;; the very same arguments during a given session.
472 (let ((add-text-to-store
473 (operation (add-text-to-store (string name) (string text)
474 (string-list references))
475 #f
476 store-path)))
bdcf35a6
LC
477 (lambda (server name text references)
478 "Add TEXT under file NAME in the store, and return its store path.
479REFERENCES is the list of store paths referred to by the resulting store
480path."
481 (let ((args `(,name ,text ,references))
482 (cache (nix-server-add-text-to-store-cache server)))
483 (or (hash-ref cache args)
fd060fd3 484 (let ((path (add-text-to-store server name text references)))
bdcf35a6
LC
485 (hash-set! cache args path)
486 path))))))
487
fd060fd3 488(define add-to-store
a7b6ffee
LC
489 ;; A memoizing version of `add-to-store'. This is important because
490 ;; `add-to-store' leads to huge data transfers to the server, and
491 ;; because it's often called many times with the very same argument.
fd060fd3
LC
492 (let ((add-to-store (operation (add-to-store (string basename)
493 (boolean fixed?) ; obsolete, must be #t
494 (boolean recursive?)
495 (string hash-algo)
496 (file file-name))
497 #f
498 store-path)))
a7b6ffee
LC
499 (lambda (server basename fixed? recursive? hash-algo file-name)
500 "Add the contents of FILE-NAME under BASENAME to the store. Note that
501FIXED? is for backward compatibility with old Nix versions and must be #t."
2c3f47ee
LC
502 (let* ((st (stat file-name #f))
503 (args `(,basename ,recursive? ,hash-algo ,st))
504 (cache (nix-server-add-to-store-cache server)))
a7b6ffee
LC
505 (or (and st (hash-ref cache args))
506 (let ((path (add-to-store server basename fixed? recursive?
507 hash-algo file-name)))
508 (hash-set! cache args path)
509 path))))))
510
77d3cf08 511(define-operation (build-derivations (string-list derivations))
dcee50c1
LC
512 "Build DERIVATIONS, and return when the worker is done building them.
513Return #t on success."
77d3cf08 514 boolean)
26bbbb95 515
d3648e01
LC
516(define-operation (add-temp-root (store-path path))
517 "Make PATH a temporary root for the duration of the current session.
518Return #t."
519 boolean)
520
34811f02
LC
521(define-operation (add-indirect-root (string file-name))
522 "Make FILE-NAME an indirect root for the garbage collector; FILE-NAME
523can be anywhere on the file system, but it must be an absolute file
524name--it is the caller's responsibility to ensure that it is an absolute
525file name. Return #t on success."
526 boolean)
527
3259877d
LC
528(define (run-gc server action to-delete min-freed)
529 "Perform the garbage-collector operation ACTION, one of the
530`gc-action' values. When ACTION is `delete-specific', the TO-DELETE is
531the list of store paths to delete. IGNORE-LIVENESS? should always be
532#f. MIN-FREED is the minimum amount of disk space to be freed, in
533bytes, before the GC can stop. Return the list of store paths delete,
534and the number of bytes freed."
535 (let ((s (nix-server-socket server)))
536 (write-int (operation-id collect-garbage) s)
537 (write-int action s)
538 (write-store-path-list to-delete s)
539 (write-arg boolean #f s) ; ignore-liveness?
540 (write-long-long min-freed s)
541 (write-int 0 s) ; obsolete
542 (when (>= (nix-server-minor-version server) 5)
543 ;; Obsolete `use-atime' and `max-atime' parameters.
544 (write-int 0 s)
545 (write-int 0 s))
546
547 ;; Loop until the server is done sending error output.
548 (let loop ((done? (process-stderr server)))
549 (or done? (loop (process-stderr server))))
550
551 (let ((paths (read-store-path-list s))
552 (freed (read-long-long s))
553 (obsolete (read-long-long s)))
554 (values paths freed))))
555
556(define-syntax-rule (%long-long-max)
557 ;; Maximum unsigned 64-bit integer.
558 (- (expt 2 64) 1))
559
560(define (live-paths server)
561 "Return the list of live store paths---i.e., store paths still
562referenced, and thus not subject to being garbage-collected."
563 (run-gc server (gc-action return-live) '() (%long-long-max)))
564
565(define (dead-paths server)
566 "Return the list of dead store paths---i.e., store paths no longer
567referenced, and thus subject to being garbage-collected."
568 (run-gc server (gc-action return-dead) '() (%long-long-max)))
569
570(define* (collect-garbage server #:optional (min-freed (%long-long-max)))
571 "Collect garbage from the store at SERVER. If MIN-FREED is non-zero,
572then collect at least MIN-FREED bytes. Return the paths that were
573collected, and the number of bytes freed."
574 (run-gc server (gc-action delete-dead) '() min-freed))
575
576(define* (delete-paths server paths #:optional (min-freed (%long-long-max)))
577 "Delete PATHS from the store at SERVER, if they are no longer
578referenced. If MIN-FREED is non-zero, then stop after at least
579MIN-FREED bytes have been collected. Return the paths that were
580collected, and the number of bytes freed."
581 (run-gc server (gc-action delete-specific) paths min-freed))
582
26bbbb95
LC
583\f
584;;;
585;;; Store paths.
586;;;
587
588(define %store-prefix
589 ;; Absolute path to the Nix store.
cd3ded43 590 (make-parameter (or (and=> (getenv "NIX_STORE_DIR") canonicalize-path)
d8eea3d2 591 %store-directory)))
26bbbb95 592
f39bd08a
LC
593(define (store-path? path)
594 "Return #t if PATH is a store path."
595 ;; This is a lightweight check, compared to using a regexp, but this has to
596 ;; be fast as it's called often in `derivation', for instance.
597 ;; `isStorePath' in Nix does something similar.
598 (string-prefix? (%store-prefix) path))
26bbbb95
LC
599
600(define (derivation-path? path)
601 "Return #t if PATH is a derivation path."
602 (and (store-path? path) (string-suffix? ".drv" path)))
e3d74106
LC
603
604(define (store-path-package-name path)
605 "Return the package name part of PATH, a file name in the store."
606 (define store-path-rx
607 (make-regexp (string-append "^.*" (regexp-quote (%store-prefix))
608 "/[^-]+-(.+)$")))
609
610 (and=> (regexp-exec store-path-rx path)
611 (cut match:substring <> 1)))