thin-provisioning-tools/functional-tests/temp-file.scm

171 lines
4.7 KiB
Scheme

(library
(temp-file)
(export
working-directory
with-dir-thunk
with-dir
with-temp-file-thunk
with-temp-file-containing-thunk
with-temp-file-sized-thunk
with-temp-file
with-temp-file-containing
with-temp-file-sized
disable-unlink)
(import (chezscheme)
(disk-units)
(fmt fmt)
(srfi s8 receive)
(only (srfi s1 lists) span))
;; FIXME: global var! Not thread safe.
(define working-dir ".")
(define (working-directory) working-dir)
(define (mkdir-p)
(system (string-append "mkdir -p " working-dir)))
(define (with-dir-thunk path thunk)
(fluid-let ((working-dir (string-append working-dir "/" path)))
(mkdir-p)
(thunk)))
(define-syntax with-dir
(syntax-rules ()
((_ path b1 b2 ...)
(with-dir-thunk path (lambda () b1 b2 ...)))))
(define (with-temp-dir-thunk path thunk)
(with-dir-thunk path
(lambda ()
(auto-unlink-file path
(thunk)))))
(define temp-filename
(lambda (filename)
(let ((counter 0))
(let loop ()
(let ((path (fmt #f (cat (dsp working-dir)
(dsp "/")
(pad-char #\0 (pad/left 4 (num counter)))
(dsp "-")
(dsp filename)))))
(set! counter (+ counter 1))
(if (file-exists? path)
(loop)
path))))))
;; fn takes the path
(define (with-temp-file-thunk filename fn)
(let ((path (temp-filename filename)))
(auto-unlink-file path
(lambda () (fn path)))))
(define-syntax with-temp-file
(syntax-rules ()
((_ ((v f)) b1 b2 ...)
(with-temp-file-thunk f
(lambda (v)
b1 b2 ...)))
((_ ((v1 f1) v2 ...) b1 b2 ...)
(with-temp-file-thunk f1
(lambda (v1)
(with-temp-file (v2 ...) b1 b2 ...))))))
;; Creates a temporary file with the specified contents.
(define (with-temp-file-containing-thunk filename contents fn)
(with-temp-file-thunk filename
(lambda (path)
(with-output-to-file path (lambda ()
(put-string (current-output-port) contents)))
(fn path))))
(define-syntax with-temp-file-containing
(syntax-rules ()
((_ ((v f txt)) b1 b2 ...)
(with-temp-file-containing-thunk f
txt (lambda (v) b1 b2 ...)))
((_ ((v f txt) rest ...) b1 b2 ...)
(with-temp-file-containing-thunk f
txt (lambda (v)
(with-temp-file-containing (rest ...)
b1 b2 ...))))))
(define (safe-to-bytes maybe-size)
(if (disk-size? maybe-size)
(to-bytes maybe-size)
maybe-size))
(define (suitable-block-size size)
(let loop ((bs (* 1024 1024 4)))
(if (> (mod size bs) 0)
(loop (/ bs 2))
bs)))
;; It's much faster if we write large blocks
(define (dd-zero-file path size)
(let* ((bytes (safe-to-bytes size))
(bs (suitable-block-size bytes))
(count (floor (/ bytes bs))))
(system (fmt #f "dd if=/dev/zero of=" path
" bs=" (wrt bs)
" count=" (wrt count)
" 2> /dev/null > /dev/null"))))
(define (with-temp-file-sized-thunk filename size fn)
(with-temp-file-thunk filename
(lambda (path)
(dd-zero-file path size)
(fn path))))
(define-syntax with-temp-file-sized
(syntax-rules ()
((_ ((v f size)) b1 b2 ...)
(with-temp-file-sized-thunk f
size
(lambda (v)
b1 b2 ...)))
((_ ((v f size) rest ...) b1 b2 ...)
(with-temp-file-sized-thunk f
size (lambda (v)
(with-temp-file-sized (rest ...) b1 b2 ...))))))
;;-------------------------
(define should-unlink #t)
(define (disable-unlink-thunk fn)
(fluid-let ((should-unlink #f))
(fn)))
(define-syntax disable-unlink
(syntax-rules ()
((_ b1 b2 ...)
(disable-unlink-thunk
(lambda () b1 b2 ...)))))
;; FIXME: use 'run' so we get logging
(define (unlink-file path)
(when should-unlink
(system (string-append "rm -f " path))))
(define (unlink-dir path)
(when should-unlink
(system (string-append "rmdir -f " path))))
(define (auto-unlink-file path thunk)
(dynamic-wind (lambda () #t)
thunk
(lambda () (unlink-file path))))
(define (auto-unlink-dir path thunk)
(dynamic-wind (lambda () #t)
thunk
(lambda () (unlink-dir path))))
)