changelog shortlog graph tags branches changeset files revisions annotate raw help

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

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