changelog shortlog graph tags branches changeset files revisions annotate raw help

Mercurial > core / lisp/lib/rdb/macs.lisp

changeset 689: 2e7d93b892a5
parent: 5f88b237ce29
author: Richard Westhaver <ellis@rwest.io>
date: Tue, 01 Oct 2024 22:29:08 -0400
permissions: -rw-r--r--
description: cli shell tests init
1 ;;; rdb/macs.lisp --- macros
2 
3 ;;; Code:
4 (in-package :rdb)
5 
6 ;;; error handling
7 (defmacro with-errptr ((e &optional errtyp params) &body body)
8  `(with-alien ((,e rocksdb-errptr nil))
9  (unwind-protect
10  (handler-bind ((sb-sys:memory-fault-error
11  (lambda (c)
12  (declare (ignore c))
13  (handle-errptr ,e ,errtyp ,params)))
14  (error
15  (lambda (c)
16  (declare (ignore c))
17  (handle-errptr ,e ,errtyp ,params))))
18  (progn ,@body))
19  (handle-errptr ,e ,errtyp ,params))))
20 
21 ;;; opts
22 (defmacro rdb-opt-setter (key)
23  `(find-symbol (format nil "~:@(rocksdb-options-set-~x~)" ,key) :rocksdb))
24 
25 (defmacro rdb-opt-getter (key)
26  `(find-symbol (format nil "~:@(rocksdb-options-get-~x~)" ,key) :rocksdb))
27 
28 ;;; db
29 (defmacro with-open-db-raw ((db-var db-path &optional (opt (default-rocksdb-options))) &body body)
30  `(let ((,db-var (open-db-raw ,db-path ,opt)))
31  (unwind-protect (progn ,@body)
32  (rocksdb-close ,db-var)
33  (with-errptr (err 'rocksdb-error)
34  ;; (rocksdb-destroy-db ,opt ,db-path err) ;; when :destroy only
35  (rocksdb-options-destroy ,opt)))))
36 
37 (defmacro with-db ((db-var db &key open close) &body body)
38  "Bind DB-VAR to the database object DB for the lifetime of BODY."
39  `(let ((,db-var ,db))
40  (handler-bind ((error (lambda (condition)
41  (error 'rdb-error
42  :message
43  (format nil "WITH-DB signaled: ~A" condition)))))
44  ,@(when open `(open-db ,db-var))
45  ,@(if close `(unwind-protect (progn ,@body) (close ,db-var))
46  body))))
47 
48 ;;; cf
49 (defmacro with-cf ((cf-var cf) &body body)
50  "Bind CF to CF-VAR for the lifetime of BODY."
51  `(let ((,cf-var ,cf))
52  (handler-bind ((error (lambda (condition)
53  (error 'cf-error
54  :message
55  (format nil "WITH-CF signaled: ~A" condition)))))
56  ,@body)))
57 
58 (defmacro do-cfs ((cf cfs) &body body)
59  "Do BODY for each CF in the array CFS."
60  (with-gensyms (%cf)
61  `(loop for ,%cf across ,cfs
62  do (with-cf (,cf ,%cf) ,@body))))
63 
64 ;;; iter
65 (defmacro with-iter-raw ((iter-var db &optional (opt (rocksdb-readoptions-create))) &body body)
66  `(let ((,iter-var (create-iter-raw ,db ,opt)))
67  (unwind-protect (progn ,@body)
68  (destroy-iter-raw ,iter-var))))
69 
70 (defmacro with-iter ((iter-var iter) &body body)
71  "Bind object ITER to ITER-VAR.
72 
73 ((%ITER ITER) BODY) is passed to ROCKSDB:WITH-ITER-RAW, binding the
74 raw handle to the same symbol prefixed with '%'.
75 
76 Errors that occur in the inner body will be handled but the iterator
77 handle will not be freed on exit."
78  (let ((%iter-var (symbolicate '% (symbol-name iter-var))))
79  `(let ((,iter-var ,iter))
80  (let ((,%iter-var (rdb-iter-sap ,iter-var)))
81  (declare (ignorable ,%iter-var))
82  ,@body))))
83 
84 ;; TODO: sb-ext:with-current-source-form ?
85 ;;; backup
86 (defmacro with-open-backup-engine-raw ((be-var be-path &optional (opt (rocksdb-options-create)))
87  &body body)
88  `(let ((,be-var (open-backup-engine-raw ,be-path ,opt)))
89  (unwind-protect (progn ,@body)
90  (rocksdb-backup-engine-close ,be-var))))
91 
92 ;;; top-level
93 ;; TODO 2024-09-26:
94 (defmacro do-db ((db opts) accessors &body body)
95  "Database Iteration construct. OPTS are used to provide top-level
96  options dynamically bound to DB. ACCESSORS is a list of database
97  accessors which are available to call in BODY.")
98 
99 ;;; temp-db
100 (defvar *temp-db-path-generator*
101  (lambda (&optional (name "temp-db"))
102  (make-pathname :directory "tmp" :name (symbol-name (gensym name))))
103  "A single arg function returning the absolute path to a temp-db path.")
104 
105 (defvar *temp-db-destroy* nil)
106 
107 (defmacro with-temp-db ((db-var (&rest cfs) &key (destroy *temp-db-destroy*) open) &body body)
108  "Bind DB-VAR to a temporary RDB object, arranging for CF-VARS to be
109 created as column-families and destroying the database after executing
110 the forms in BODY."
111  (setf cfs
112  (mapcar
113  (lambda (var)
114  (setf var (make-rdb-cf (symbol-name var))))
115  cfs))
116  `(with-db (,db-var (make-rdb
117  (namestring (funcall ,*temp-db-path-generator* ,(symbol-name db-var)))
118  (default-rdb-opts)
119  (make-array ,(length cfs) :element-type 'rdb-cf :initial-contents ',cfs :adjustable t :fill-pointer ,(length cfs))))
120  ,@(when open `((open-db ,db-var)
121  (create-cfs ,db-var)))
122  (prog1
123  (progn ,@body)
124  ,(if destroy
125  `(destroy-db ,db-var)
126  `(shutdown-db ,db-var)))))
127 ;;; sst
128 (defmacro with-sst ((sst &key file comparator destroy) &body body)
129  "Do BODY with SST bound to a SST-FILE-WRITER. When FILE is supplied
130 the writer will automatically open that file.
131 
132 When COMPARATOR is supplied it is used as the comparator function for
133 the writer. Every key inserted MUST be in ascending order, according
134 to the comparator. By default the ordering is binary
135 lexicographically.
136 
137 It is up to the developer to ensure that the comparator used by a
138 writer is exactly the same as the comparator used when ingesting the
139 file by a RDB instance."
140  `(let ((,sst (make-sst-file-writer ,comparator)))
141  ,@(when file `((open-sst ,sst ,file)))
142  ,@body
143  ,@(when destroy `((destroy-sst ,sst)))))
144 
145 ;;; opts
146 (defmacro with-latest-opts (db &body body)
147  `(progn
148  (let ((,db (load-opts ,db)))
149  ,@body)))