changelog shortlog graph tags branches changeset files revisions annotate raw help

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

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