diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ac8f968 --- /dev/null +++ b/.gitignore @@ -0,0 +1,20 @@ +# Compiled source # +################### +*.com +*.class +*.dll +*.exe +*.o +*.so +*.pyc + +# Logs and databases # +###################### +*.log + +# OS generated files # +###################### +.DS_Store* +ehthumbs.db +Icon? +Thumbs.db diff --git a/planks.org b/planks.org index 97a4542..91ced88 100644 --- a/planks.org +++ b/planks.org @@ -1,31 +1,31 @@ planks: persistent lisp, mumble mumble mumble mumble -* Features +* Features - 100% portable common lisp uses bordeaux threads! - functional, append-only index - persistent CLOS objects - thread safe - - multi-value concurrency control + - multi-value concurrency control - easy to install and to use * Download and Install ** Release tarballs - + http://common-lisp.net/project/planks/planks-release.tar.gz - + ** Version Control - planks is available via git + planks is available via git + + + - - - * Examples ** Basic key/value store diff --git a/src/btree-class.lisp b/src/btree-class.lisp index eea325d..5b5b0e0 100644 --- a/src/btree-class.lisp +++ b/src/btree-class.lisp @@ -16,18 +16,18 @@ (defmethod btree-pathname (object) (btree-class-pathname (class-of object))) -(defmethod shared-initialize :around - ((object btree-object) slots &rest initargs +(defmethod shared-initialize :around + ((object btree-object) slots &rest initargs &key (btree (btree-pathname object))) (declare (ignore slots initargs)) (let* ((parent (find-btree btree)) (lock (btree-lock parent))) (bt:with-recursive-lock-held (lock) (let ((id (btree-footer-next-id (btree-file-footer parent)))) - (setf (btree-object-id object) + (setf (btree-object-id object) id) (update-btree parent :key id :value (call-next-method) :action :make-instance))))) - + (defmethod initialize-instance :around ((class btree-class) &rest initargs &key direct-superclasses) diff --git a/src/btree-protocol.lisp b/src/btree-protocol.lisp index 5b70b9b..792719d 100644 --- a/src/btree-protocol.lisp +++ b/src/btree-protocol.lisp @@ -79,7 +79,7 @@ ORDER is either :ASCENDING (default) or :DESCENDING.")) (defgeneric update-btree (btree &key key value &allow-other-keys) - (:documentation + (:documentation "This is the function that implements the functional b+tree. It is not meant to be called by users, but is specialized when extending")) (define-condition btree-error (error) diff --git a/src/btree-search.lisp b/src/btree-search.lisp index 2ddca3a..b95f088 100644 --- a/src/btree-search.lisp +++ b/src/btree-search.lisp @@ -77,7 +77,7 @@ (:method (btree (node null) function min max include-min include-max order) - nil) + nil) (:method (btree node function min max include-min include-max order) diff --git a/src/btree-test.lisp b/src/btree-test.lisp index dd5c3fd..6b89257 100644 --- a/src/btree-test.lisp +++ b/src/btree-test.lisp @@ -1,6 +1,6 @@ (in-package :cl) -(defpackage :planks.btree-test +(defpackage :planks.btree-test (:use :cl :planks.btree)) (in-package :planks.btree-test) @@ -26,7 +26,7 @@ (defun test-btree-balance (&key (path *path*)) (let ((bt (make-btree path :if-exists :supersede :max-node-size 5))) (assert (null (btree-search bt 1 :errorp nil))) - (loop for i upto 1234 for b = (btree-insert bt i i) then (btree-insert b i i) + (loop for i upto 1234 for b = (btree-insert bt i i) then (btree-insert b i i) :finally (assert (planks.btree::btree-balanced-p b))))) (defun reverse-map (k v) @@ -41,18 +41,18 @@ (list (cons v (length v)))) (defun test-multi-btree-existing-data-insert (&key (path *path*)) - (let ((bt (make-btree path + (let ((bt (make-btree path :if-exists :supersede :class 'multi-btree)) - (data (remove-duplicates - (loop - for i upto 1234 + (data (remove-duplicates + (loop + for i upto 1234 for r = (format nil "~R" i) :collect (cons i r)) :key #'car))) - (loop - for (i . r) in data - for b = (btree-insert bt i r) + (loop + for (i . r) in data + for b = (btree-insert bt i r) then (btree-insert b i r)) (add-function-btree (find-btree path) 'reverse-map :key= 'equal :key< 'string<) @@ -62,16 +62,16 @@ (find-btree path))) (defun test-multi-btree-existing-data (&optional (bt (test-multi-btree-existing-data-insert))) - - (map-btree (find-function-btree bt 'reverse-map) + + (map-btree (find-function-btree bt 'reverse-map) (lambda (k v) (assert (equal k (btree-search bt v))))) - (map-btree (find-function-btree bt 'add-one-to-key) + (map-btree (find-function-btree bt 'add-one-to-key) (lambda (k v) (assert (equal (1+ k) v)))) - (map-btree (find-function-btree bt 'length-of-value) + (map-btree (find-function-btree bt 'length-of-value) (lambda (k v) (assert (equal (length k) v))))) @@ -93,23 +93,23 @@ :key< 'string< :key= 'equalp) (symbol-macrolet ((bt (find-btree *path*))) - (loop for n to 115000 do + (loop for n to 115000 do (btree-insert bt (uuid:print-bytes nil (uuid:make-v1-uuid)) n) (close-btree bt)) - + (format t "File Size : ~A" (float (/ (btree-file-size bt) (* 1024 1024)))) bt)) - - - -(progn + + + +(progn (test-file-btree-insert) (test-btree-balance) (test-multi-btree-existing-data)) - - - + + + diff --git a/src/btree-utils.lisp b/src/btree-utils.lisp index 1b3a8f6..1d569d6 100644 --- a/src/btree-utils.lisp +++ b/src/btree-utils.lisp @@ -9,7 +9,7 @@ (let ((key< (slot-value btree 'key<)) (key-key (btree-key-key btree))) (lambda (key1 key2) - (and + (and (funcall key< (funcall key-key key1) (funcall key-key key2)))))) @@ -63,7 +63,7 @@ 0 (loop for i below (btree-node-binding-count node) for binding = (btree-node-binding node i) - maximize (1+ (btree-node-max-depth (btree-node-binding-value + maximize (1+ (btree-node-max-depth (btree-node-binding-value node binding)))))) (defmethod btree-node-min-depth ((node btree-node)) @@ -71,7 +71,7 @@ 0 (loop for i below (btree-node-binding-count node) for binding = (btree-node-binding node i) - minimize (1+ (btree-node-min-depth (btree-node-binding-value + minimize (1+ (btree-node-min-depth (btree-node-binding-value node binding)))))) (defmethod btree-depths ((btree btree)) diff --git a/src/btree.lisp b/src/btree.lisp index c59cd83..6ff31be 100644 --- a/src/btree.lisp +++ b/src/btree.lisp @@ -40,7 +40,7 @@ of keys per btree node.") (SETF (SLOT-VALUE NEW 'KEY<) (SLOT-VALUE btree 'KEY<) (SLOT-VALUE NEW 'KEY=) (SLOT-VALUE btree 'KEY=) (SLOT-VALUE NEW 'KEY-KEY) (SLOT-VALUE btree 'KEY-KEY) - (SLOT-VALUE NEW 'VALUE-KEY) (SLOT-VALUE btree 'VALUE-KEY) + (SLOT-VALUE NEW 'VALUE-KEY) (SLOT-VALUE btree 'VALUE-KEY) (SLOT-VALUE NEW 'VALUE=) (SLOT-VALUE btree 'VALUE=) (SLOT-VALUE NEW 'NODE-CLASS) (SLOT-VALUE btree 'NODE-CLASS) (SLOT-VALUE NEW 'MAX-NODE-SIZE) (SLOT-VALUE btree 'MAX-NODE-SIZE) @@ -53,19 +53,19 @@ of keys per btree node.") (if (and (null key) (null value)) (%update-btree btree) (let ((root (btree-root btree))) - (%update-btree - btree - :root (cond - ((not root) + (%update-btree + btree + :root (cond + ((not root) (make-root-node btree key value)) ((node-almost-full-p btree root) - (update-node - root :index (split-binding-node + (update-node + root :index (split-binding-node btree root key value nil))) - (t - (update-node - root :index (update-index-for-insert - btree (btree-node-index root) + (t + (update-node + root :index (update-index-for-insert + btree (btree-node-index root) key value (btree-node-leaf-p root))))))))) (defclass btree-node () @@ -84,18 +84,18 @@ of keys per btree node.") (format stream "~A" (btree-node-index object)))) (defmethod update-node (node &key (index (btree-node-index node)) - (leaf-p (btree-node-leaf-p node))) + (leaf-p (btree-node-leaf-p node))) (make-instance (class-of node) :index index :leaf-p leaf-p)) (defmethod make-root-node (btree key val) - (let* ((left (update-node (make-instance (btree-node-class btree) - :leaf-p t - :index (vector (funcall + (let* ((left (update-node (make-instance (btree-node-class btree) + :leaf-p t + :index (vector (funcall (if (btree-unique-keys-p btree) 'cons 'list) key val)))))) - (update-node (make-instance (btree-node-class btree) + (update-node (make-instance (btree-node-class btree) :index (vector (cons key left)) :leaf-p nil)))) @@ -107,7 +107,7 @@ of keys per btree node.") ;; Find the first binding with a key >= the given key and return ;; the corresponding subnode. ;; DO: We should probably use binary search for this. - (loop + (loop :for (bkey . value) :across index :for i from 0 :when (or (= (1+ i) (length index)) @@ -126,7 +126,7 @@ of keys per btree node.") (defmethod btree-node-binding-value (node binding) (cdr binding)) - + (defmethod largest-key-in-node (node) (let ((index (btree-node-index node)) (leaf-p (btree-node-leaf-p node))) @@ -137,32 +137,32 @@ of keys per btree node.") (defun update-bnode (btree node key value) - (update-node - node :index (update-index-for-insert - btree (btree-node-index node) + (update-node + node :index (update-index-for-insert + btree (btree-node-index node) key value (btree-node-leaf-p node)))) (defun update-index-for-insert (btree index key value leaf-p) (cond ((eql 0 (length index)) (vector (cons key value))) - (t + (t (let* ((pos (find-key-position-in-index btree index key)) (binding (aref index pos)) - (left-index (unless (eql 0 pos) + (left-index (unless (eql 0 pos) (make-array pos :displaced-to index))) - (right-index (unless (<= (length index) (1+ pos)) + (right-index (unless (<= (length index) (1+ pos)) (make-array (1- (- (length index) pos)) :displaced-to index :displaced-index-offset (1+ pos))))) - (concatenate 'vector - left-index + (concatenate 'vector + left-index (update-binding-for-insert btree binding key value leaf-p) right-index))))) (defmethod update-node-for-insert (btree node binding-key key value leaf-p) (if (and (not leaf-p) (node-almost-full-p btree node)) (split-binding-node btree node key value (btree-node-leaf-p node)) - (if leaf-p + (if leaf-p (if (funcall (btree-key= btree) binding-key key) ;; replacing existing binding (vector (cons key (if (btree-unique-keys-p btree) @@ -172,9 +172,9 @@ of keys per btree node.") ))) ;;new key (sort (vector (funcall (if (btree-unique-keys-p btree) - 'cons + 'cons 'list) - key value) + key value) (cons binding-key node)) (btree-key< btree) :key #'car)) (vector (cons binding-key (update-bnode btree node key value)))))) @@ -192,11 +192,11 @@ of keys per btree node.") (sub-index (if (<= (1+ node-pos) (length split-left-index)) split-left-index split-right-index)) - (left-node (update-node + (left-node (update-node node :index (if (eql split-left-index sub-index) (update-index-for-insert btree split-left-index key value leaf-p) split-left-index))) - (right-node (update-node + (right-node (update-node node :index (if (eql split-right-index sub-index) (update-index-for-insert btree split-right-index key value leaf-p) split-right-index)))) diff --git a/src/file-btree.lisp b/src/file-btree.lisp index 8df8930..ec6632f 100644 --- a/src/file-btree.lisp +++ b/src/file-btree.lisp @@ -31,7 +31,7 @@ (zerop (ldb (byte 1 0) byte))) (setf (btree-node-index node) (make-array (ash byte -1))))) - + (defmethod write-node-tag (node &key (stream *btree-stream*)) (let* ((length (length (btree-node-index node))) (byte (dpb (if (btree-node-leaf-p node) @@ -45,23 +45,23 @@ (read-node-tag node :stream stream) (prog1 node (setf (btree-node-address node) address) - (loop - :with index = (btree-node-index node) + (loop + :with index = (btree-node-index node) :for n :from 0 :to (1- (length index)) :do (setf (aref index n) (cons (rs::deserialize stream) (rs::deserialize stream))))))) - + (defun load-btree-node (btree address) (typecase address (file-btree-node address) - (integer + (integer (call-with-btree-stream btree - (lambda (s) - (file-position s address) + (lambda (s) + (file-position s address) (load-btree-node-from-stream btree s)) :input)))) - + (defmethod persist (node &key (stream *btree-stream*)) (finish-output stream) (assert (not (slot-boundp node 'address)) () @@ -70,25 +70,25 @@ (setf (btree-node-address node) eof) (file-position stream eof) (write-node-tag node :stream stream) - (loop :for (key . value) :across (btree-node-index node) - :do + (loop :for (key . value) :across (btree-node-index node) + :do (rs::serialize key stream) - (rs::serialize value stream)) + (rs::serialize value stream)) (finish-output stream))) (defmethod rs::serialize ((object file-btree-node) stream) (rs::serialize (btree-node-address object) stream)) (defun btree-node-file-position (node) - (typecase node + (typecase node (integer node) (file-btree-node (btree-node-address node)))) (defmethod btree-root ((btree file-btree)) (let ((root (call-next-method))) - (when root + (when root (load-btree-node btree root)))) - + (defmethod update-node-for-insert (btree (pointer integer) binding-key key value (leaf-p null)) (call-next-method btree (load-btree-node btree pointer) binding-key key value leaf-p)) @@ -124,14 +124,14 @@ (defmethod update-node :around ((node file-btree-node) &key &allow-other-keys) (let ((new-node (call-next-method))) - (prog1 new-node + (prog1 new-node (persist new-node)))) (defmethod update-btree :around ((btree file-btree) &key &allow-other-keys) (let ((%btree% btree)) (declare (special %btree%)) (let ((new-btree (call-next-method))) - (prog1 new-btree + (prog1 new-btree (setf (btree-pathname new-btree) (btree-pathname btree) (btree-root btree) @@ -150,20 +150,20 @@ ((root-node-address :initform nil :initarg :root-node-position :accessor root-node-file-position) (address :initarg :address :accessor btree-file-footer-address) - + (action :initform :create :initarg :action :accessor btree-file-footer-action) (version :initform 0 :accessor btree-file-footer-version :initarg :version) (previous-address :accessor btree-file-footer-previous-address :initarg :previous-address) - (key :initform nil + (key :initform nil :accessor btree-file-footer-key))) (defmethod make-btree-footer ((btree single-file-btree) old-footer &key (action :create)) - (make-instance + (make-instance (btree-file-footer-class btree) :action action :root-node-position (when (btree-root btree) - - (btree-node-file-position + + (btree-node-file-position (btree-root btree))) :version (if old-footer (1+ (btree-file-footer-version old-footer)) 0) :previous-address (when old-footer (btree-file-footer-previous-address old-footer)))) @@ -174,7 +174,7 @@ (defmethod read-footer-checksum (btree stream) (let ((seq (make-array 4 :element-type '(unsigned-byte 8)))) (read-sequence seq stream) seq)) - + (defparameter +footer-marker+ #b10101010) (defparameter *max-footer-size* 1024) @@ -190,7 +190,7 @@ (let* ((buffer (make-footer-buffer footer)) (checksum (ironclad:digest-sequence :crc32 (rs::contents buffer)))) (finish-output stream) - (file-position stream (file-length stream)) + (file-position stream (file-length stream)) (dotimes (n 2) (write-byte +footer-marker+ stream) (rs::serialize-byte-32 (rs::buffer-count buffer) stream) @@ -198,19 +198,19 @@ (write-footer-checksum btree stream checksum))) (finish-output stream)) -(defun read-file-footer (btree stream - &key (count 25) +(defun read-file-footer (btree stream + &key (count 25) (start (- (file-length stream) count))) (file-position stream (setf start (if (>= start 0) start 0))) - (let ((footer - (loop + (let ((footer + (loop :for n from 1 to count :for byte = (read-byte stream nil) :while byte :when (eql byte +footer-marker+) - :do + :do (let* ((pos (file-position stream)) (length (ignore-errors (rs::deserialize-byte-32 stream))) (buffer (if (or (not length) (> length *max-footer-size*)) @@ -222,7 +222,7 @@ (prog1 object (rs::load-slots object buffer)))) (file-position stream pos)))))) - (or footer + (or footer (if (not (zerop start)) (read-file-footer btree stream :start (- start count) :count count) (error "FATAL: Can't read btree footer"))))) @@ -230,7 +230,7 @@ (defun make-btree-lock (btree) (bordeaux-threads:make-lock (format nil "BTREE lock for ~A" (btree-pathname btree)))) -(defun make-btree (pathname &rest args &key (if-exists :error) +(defun make-btree (pathname &rest args &key (if-exists :error) (class 'single-file-btree) &allow-other-keys) (bordeaux-threads:with-lock-held (=big-btree-lock=) (with-open-file (stream pathname @@ -240,7 +240,7 @@ :element-type '(unsigned-byte 8)) (let* ((btree (apply 'make-instance class (alexandria:remove-from-plist args :if-exists :class))) - (footer (make-btree-footer btree nil))) + (footer (make-btree-footer btree nil))) (setf (btree-pathname btree) pathname) (rs::serialize btree stream) (write-file-footer btree stream footer) @@ -255,35 +255,35 @@ (footer (read-file-footer btree stream)) (root-position (root-node-file-position footer))) (setf (btree-file-footer btree) footer) - (when root-position + (when root-position (file-position stream root-position) (setf (btree-root btree) (load-btree-node-from-stream btree stream))) btree)) (defun find-btree (path) - (or (gethash path *btrees*) + (or (gethash path *btrees*) (bordeaux-threads:with-lock-held (=big-btree-lock=) - (or (gethash path *btrees*) - (setf (gethash path *btrees*) - (with-open-file (s path - :if-does-not-exist :error + (or (gethash path *btrees*) + (setf (gethash path *btrees*) + (with-open-file (s path + :if-does-not-exist :error :direction :input :element-type '(unsigned-byte 8)) (let ((btree (read-btree-from-file-stream s))) (setf (btree-lock btree) (make-btree-lock btree)) - (setf (btree-root btree) (load-btree-node btree (root-node-file-position (btree-file-footer btree)))) + (setf (btree-root btree) (load-btree-node btree (root-node-file-position (btree-file-footer btree)))) btree))))))) (defun close-btree (path) (typecase path (btree (close-btree (btree-pathname path))) - (t + (t (bordeaux-threads:with-lock-held (=big-btree-lock=) (remhash path *btrees*))))) - -(defmethod update-btree :around ((btree single-file-btree) &rest args - &key + +(defmethod update-btree :around ((btree single-file-btree) &rest args + &key &allow-other-keys) (let* ((current-btree (find-btree (btree-pathname btree))) (lock (btree-lock btree))) @@ -295,11 +295,11 @@ :if-exists :overwrite :direction :output :element-type '(unsigned-byte 8)) - (let ((btree (call-next-method))) + (let ((btree (call-next-method))) (prog1 btree (setf (btree-file-footer-class btree) (btree-file-footer-class current-btree)) - (let ((footer (apply #'make-btree-footer - btree (btree-file-footer current-btree) + (let ((footer (apply #'make-btree-footer + btree (btree-file-footer current-btree) args))) (setf (btree-file-footer-address footer) (file-position *btree-stream*)) (write-file-footer btree *btree-stream* footer) @@ -308,11 +308,10 @@ (setf (gethash (btree-pathname btree) *btrees*) btree)) (finish-output *btree-stream*))))) (apply #'update-btree current-btree args)))) - - \ No newline at end of file + diff --git a/src/heap-btree.lisp b/src/heap-btree.lisp index 1b959ad..10b03bd 100644 --- a/src/heap-btree.lisp +++ b/src/heap-btree.lisp @@ -1,7 +1,7 @@ (in-package :planks.btree) (defclass heap-btree (multi-btree) - ((heap-size :initarg :heap-size + ((heap-size :initarg :heap-size :initform (* 1024 1024) :accessor btree-heap-size) (heap-start :initform 0) @@ -18,42 +18,42 @@ (defmethod btree-heap-free-space-start ((btree heap-btree)) (slot-value (btree-file-footer btree) 'free-space-start)) -(defmethod make-btree-footer :around ((btree heap-btree) old-footer - &key +(defmethod make-btree-footer :around ((btree heap-btree) old-footer + &key &allow-other-keys) (let ((footer (call-next-method))) - (prog1 footer + (prog1 footer (with-slots (heap-start free-space-start) btree ; (break "~A bts~A btf~A" t heap-start free-space-start) (with-slots ((hs heap-start) (fss free-space-start)) footer (setf hs heap-start fss free-space-start)))))) - + (defmethod allocate-heap ((btree heap-btree) start stream) - (file-position *btree-stream* start) + (file-position *btree-stream* start) (loop repeat (slot-value btree 'heap-size) do (write-byte rs::+FREE-BLOCK+ stream)) start) (defmethod allocate-object ((btree heap-btree) object object-start heap-start stream) (let* ((buffer (make-instance 'rs::serialization-buffer)) - (object-length (progn (rs::serialize object buffer) + (object-length (progn (rs::serialize object buffer) (length (slot-value buffer 'rs::contents)))) - (free-space (- (slot-value btree 'heap-size) + (free-space (- (slot-value btree 'heap-size) (- object-start heap-start)))) (assert (> (btree-heap-size btree) object-length) () "Objects larger then heap size not supported") (when (> object-length free-space) - (setf heap-start + (setf heap-start (setf object-start (allocate-heap btree (file-length stream) stream)))) (rs::save-buffer buffer stream :file-position object-start) (values object-start (file-position stream) heap-start))) (defmethod find-heap-object (heap address) (alexandria:with-input-from-file (s (btree-pathname heap) :element-type '(unsigned-byte 8)) - (file-position s address) + (file-position s address) (rs::deserialize s))) - + (defmethod update-btree ((btree heap-btree) &rest args &key value action) (assert (sb-thread:holding-mutex-p (btree-lock btree))) (let ((start (btree-heap-start btree)) @@ -64,8 +64,8 @@ (setf free start) (allocate-heap btree start *btree-stream*)) - (case action - (:insert + (case action + (:insert (multiple-value-setq (value free start) (allocate-object btree value free start *btree-stream*)))) (let ((new-tree (apply #'call-next-method btree :value value args))) @@ -82,19 +82,19 @@ (defmethod map-btree :around ((bt heap-btree) fn &rest args &key address-only &allow-other-keys) - (let ((fun (if address-only - fn - (if (btree-unique-keys-p bt) - (lambda (k address) + (let ((fun (if address-only + fn + (if (btree-unique-keys-p bt) + (lambda (k address) (funcall fn k (find-heap-object bt address))) - (lambda (k address) - (funcall fn k (mapcar (lambda (a) (find-heap-object bt a)) address))))))) + (lambda (k address) + (funcall fn k (mapcar (lambda (a) (find-heap-object bt a)) address))))))) (apply #'call-next-method bt fun args))) - - - - - - + + + + + + diff --git a/src/map-btree.lisp b/src/map-btree.lisp index 4170fa8..ed0161a 100644 --- a/src/map-btree.lisp +++ b/src/map-btree.lisp @@ -25,7 +25,7 @@ (:method (btree (node null) function min max include-min include-max order) - nil) + nil) (:method (btree node function min max include-min include-max order) diff --git a/src/object-btree.lisp b/src/object-btree.lisp index cdf91ba..8530277 100644 --- a/src/object-btree.lisp +++ b/src/object-btree.lisp @@ -1,6 +1,6 @@ (in-package :planks.btree) -(defclass object-storage-btree (single-file-btree) +(defclass object-storage-btree (single-file-btree) () (:default-initargs :footer-class 'object-storage-footer)) @@ -11,15 +11,15 @@ (defmethod make-btree-footer :around ((btree object-storage-btree) old-footer &key action) (let ((footer (call-next-method))) - (prog1 footer + (prog1 footer (setf (btree-footer-next-id footer) (if (eql :make-instance action) (if old-footer (1+ (btree-footer-next-id old-footer)) 0) (if old-footer (btree-footer-next-id old-footer) 0)))))) -(defmethod update-btree ((btree object-storage-btree) &rest args +(defmethod update-btree ((btree object-storage-btree) &rest args &key value-thunk &allow-other-keys) - (if value-thunk + (if value-thunk (let ((value (funcall value-thunk))) (apply #'call-next-method btree (list* :value value (alexandria:remove-from-plist args :value-thunk)))) (call-next-method))) @@ -39,9 +39,9 @@ (declare (special %btree-path%)) (bt:with-recursive-lock-held ((btree-lock parent)) (let* ((value) - (value-thunk - (lambda () - (setf value + (value-thunk + (lambda () + (setf value (let ((value (call-next-method))) (prog1 value #+nil (setf (btree-object-id value) diff --git a/src/persistent-objects.lisp b/src/persistent-objects.lisp index 9ca409c..d984260 100644 --- a/src/persistent-objects.lisp +++ b/src/persistent-objects.lisp @@ -8,7 +8,7 @@ (defclass persistent-standard-object () ((slot-btree :accessor persistent-standard-object-slot-btree))) - + (defclass persistent-standard-object-slot-btree (nested-btree) ((class-name :accessor persistent-standard-object-slot-btree-class-name :initarg :class-name)) @@ -26,7 +26,7 @@ (prog1 new-btree (setf (persistent-standard-object-slot-btree-class-name new-btree) (persistent-standard-object-slot-btree-class-name btree))))) - + (defconstant +persistent-standard-object-marker+ #xC2) @@ -39,7 +39,7 @@ (defmethod rs::deserialize-contents ((marker (eql +persistent-standard-object-marker+)) stream) (let* ((btree (rs::deserialize stream)) - (instance (allocate-instance (find-class + (instance (allocate-instance (find-class (persistent-standard-object-slot-btree-class-name btree))))) (setf (persistent-standard-object-slot-btree instance) btree) @@ -49,17 +49,17 @@ (btree-class-pathname (class-of object))) (defclass persistent-standard-class-slot-definition () - ((persistentp :accessor slot-definition-persistentp + ((persistentp :accessor slot-definition-persistentp :initarg :persistent :initform t))) -(defclass persistent-standard-class-direct-slot-definition - (persistent-standard-class-slot-definition - closer-mop:standard-direct-slot-definition) +(defclass persistent-standard-class-direct-slot-definition + (persistent-standard-class-slot-definition + closer-mop:standard-direct-slot-definition) ()) -(defclass persistent-standard-class-effective-slot-definition - (persistent-standard-class-slot-definition - closer-mop:standard-effective-slot-definition) +(defclass persistent-standard-class-effective-slot-definition + (persistent-standard-class-slot-definition + closer-mop:standard-effective-slot-definition) ()) (defmethod closer-mop:direct-slot-definition-class @@ -84,36 +84,36 @@ (defmethod shared-initialize :before ((object persistent-standard-object) slots &rest initargs) (declare (ignore slots initargs)) - (setf (persistent-standard-object-slot-btree object) - (make-instance 'persistent-standard-object-slot-btree + (setf (persistent-standard-object-slot-btree object) + (make-instance 'persistent-standard-object-slot-btree :btree (btree-pathname object) :class-name (class-name (class-of object))))) (defmethod closer-mop:slot-value-using-class ((class persistent-standard-class) (object persistent-standard-object) (slotd persistent-standard-class-effective-slot-definition)) - (btree-search (persistent-standard-object-slot-btree object) + (btree-search (persistent-standard-object-slot-btree object) (closer-mop:slot-definition-name slotd))) -(defmethod (setf closer-mop:slot-value-using-class) (value +(defmethod (setf closer-mop:slot-value-using-class) (value (class persistent-standard-class) (object persistent-standard-object) (slotd persistent-standard-class-effective-slot-definition)) - + (prog1 value (setf (persistent-standard-object-slot-btree object) - (btree-insert (persistent-standard-object-slot-btree object) + (btree-insert (persistent-standard-object-slot-btree object) (closer-mop:slot-definition-name slotd) value)))) -(defmethod closer-mop:slot-boundp-using-class +(defmethod closer-mop:slot-boundp-using-class ((class persistent-standard-class) (object persistent-standard-object) (slotd persistent-standard-class-effective-slot-definition)) - (btree-search (persistent-standard-object-slot-btree object) + (btree-search (persistent-standard-object-slot-btree object) (closer-mop:slot-definition-name slotd) :errorp nil)) - + (defmethod initialize-instance :around ((class persistent-standard-class) &rest initargs &key direct-superclasses) diff --git a/src/view.lisp b/src/view.lisp index e335aa3..4d75224 100644 --- a/src/view.lisp +++ b/src/view.lisp @@ -3,11 +3,11 @@ (defclass function-btree (file-btree) ((name :accessor btree-function-name :initarg :name))) -(defmethod update-btree :around ((btree function-btree) &rest args) +(defmethod update-btree :around ((btree function-btree) &rest args) (let ((new-btree (call-next-method))) (prog1 new-btree (setf (btree-function-name new-btree) (btree-function-name btree))))) - + (defclass multi-btree-file-footer (btree-footer) ((btrees :initform nil))) @@ -24,31 +24,31 @@ (defun current-btree () *current-btree*) -(defmethod make-btree-footer :around ((btree multi-btree) old-footer - &key key value action function-name function-index-initargs +(defmethod make-btree-footer :around ((btree multi-btree) old-footer + &key key value action function-name function-index-initargs &allow-other-keys) (let* ((new-footer (call-next-method)) - (btrees (and old-footer + (btrees (and old-footer (slot-value old-footer 'btrees) (remove function-name (slot-value old-footer 'btrees) :key 'btree-function-name))) (*current-btree* btree) (*current-footer* new-footer)) - (if (eql action :add-function) - (let ((function-btree (apply #'make-instance 'function-btree - :pathname (btree-pathname btree) - :name function-name + (if (eql action :add-function) + (let ((function-btree (apply #'make-instance 'function-btree + :pathname (btree-pathname btree) + :name function-name function-index-initargs))) - (map-btree + (map-btree btree (lambda (k v) (loop for (fk . fv) in (funcall function-name k v) :do (setf function-btree (update-btree function-btree :key fk :value fv))))) - (setf (slot-value new-footer 'btrees) + (setf (slot-value new-footer 'btrees) (cons function-btree btrees)) new-footer) - (prog1 new-footer - (setf (slot-value new-footer 'btrees) - (loop :for btree :in btrees - :collect + (prog1 new-footer + (setf (slot-value new-footer 'btrees) + (loop :for btree :in btrees + :collect (loop for (fk . fv) in (funcall (btree-function-name btree) key value) :for b = (btree-insert btree fk fv) :then (btree-insert b fk fv) @@ -60,7 +60,7 @@ (defun find-function-btree (btree function-name) (find function-name (slot-value (btree-file-footer btree) 'btrees) :key 'btree-function-name)) - + (defmethod btree-search :around ((btree multi-btree) key &key (errorp t) (default-value nil) (function nil)) (if function (btree-search (find function (slot-value (btree-file-footer btree) 'btrees) @@ -69,5 +69,4 @@ (call-next-method))) - - \ No newline at end of file +