From alemmens at common-lisp.net Sun Aug 12 13:01:18 2007 From: alemmens at common-lisp.net (alemmens) Date: Sun, 12 Aug 2007 09:01:18 -0400 (EDT) Subject: [rucksack-cvs] CVS rucksack Message-ID: <20070812130118.D9C014814C@common-lisp.net> Update of /project/rucksack/cvsroot/rucksack In directory clnet:/tmp/cvs-serv13430 Modified Files: do.txt done.txt index.lisp make.lisp p-btrees.lisp rucksack.asd rucksack.lisp test.lisp Log Message: Fix btree bug during btree-delete: if we're deleting the biggest key from a leaf, we should update the parents so they'll use the key that has now become the biggest. (Henrik Hjelte.) Try to signal an error when an incompatible value is given to indexed slots, e.g. trying to put a string into a slot with a :symbol-index. (Henrik Hjelte) Signal an error during when putting duplicate values into a slot for which duplicate values are not allowed. (Henrik Hjelte) Use BTREE-VALUE-TYPE, not BTREE-KEY-TYPE, when type checking a value during BTREE-INSERT. (Henrik Hjelte) Wrap COMPILE-FILE calls in a WITH-COMPILATION-UNIT to prevent superfluous warnings about undefined functions. --- /project/rucksack/cvsroot/rucksack/do.txt 2007/01/22 10:23:14 1.6 +++ /project/rucksack/cvsroot/rucksack/do.txt 2007/08/12 13:01:13 1.7 @@ -1,13 +1,7 @@ DO: -- There's still a btree bug that's detected (very rarely) by the - stress test. Fix it. - - Make Rucksack crash proof. (Use a copying GC?) -- Check that btrees actually signal an error for duplicate keys. - Handle those errors correctly for slot indexes. - - Make sure that the GC gets rid of all obsolete object versions. - Add export/import to s-expression format. This is necessary --- /project/rucksack/cvsroot/rucksack/done.txt 2007/03/13 13:13:00 1.9 +++ /project/rucksack/cvsroot/rucksack/done.txt 2007/08/12 13:01:13 1.10 @@ -1,3 +1,23 @@ +* 2007-08-12 - version 0.1.9 + +- Fix btree bug during btree-delete: if we're deleting the biggest key + from a leaf, we should update the parents so they'll use the key that + has now become the biggest. (Henrik Hjelte.) + +- Try to signal an error when an incompatible value is given to + indexed slots, e.g. trying to put a string into a slot with a + :symbol-index. (Henrik Hjelte) + +- Signal an error during when putting duplicate values into a slot for + which duplicate values are not allowed. (Henrik Hjelte) + +- Use BTREE-VALUE-TYPE, not BTREE-KEY-TYPE, when type checking a value + during BTREE-INSERT. (Henrik Hjelte) + +- Wrap COMPILE-FILE calls in a WITH-COMPILATION-UNIT to prevent + superfluous warnings about undefined functions. + + * 2007-03-13 - version 0.1.8 - Fix a bug in LEAF-DELETE-KEY (thanks to Henrik Hjelte). --- /project/rucksack/cvsroot/rucksack/index.lisp 2007/01/20 18:17:55 1.9 +++ /project/rucksack/cvsroot/rucksack/index.lisp 2007/08/12 13:01:13 1.10 @@ -1,4 +1,4 @@ -;; $Id: index.lisp,v 1.9 2007/01/20 18:17:55 alemmens Exp $ +;; $Id: index.lisp,v 1.10 2007/08/12 13:01:13 alemmens Exp $ (in-package :rucksack) @@ -196,17 +196,18 @@ '(btree :key< < :value= p-eql)) (define-index-spec :string-index - '(btree :key< string< :value p-eql)) + '(btree :key< string< :value p-eql :key-type string)) (define-index-spec :symbol-index - '(btree :key< string< :value p-eql)) + '(btree :key< string< :value p-eql :key-type symbol)) (define-index-spec :case-insensitive-string-index - '(btree :key< string-lessp :value p-eql)) + '(btree :key< string-lessp :value p-eql :key-type string)) (define-index-spec :trimmed-string-index ;; Like :STRING-INDEX, but with whitespace trimmed left ;; and right. '(btree :key< string< :key-key trim-whitespace - :value p-eql))) + :value p-eql + :key-type string))) --- /project/rucksack/cvsroot/rucksack/make.lisp 2007/01/20 18:17:55 1.6 +++ /project/rucksack/cvsroot/rucksack/make.lisp 2007/08/12 13:01:13 1.7 @@ -1,4 +1,5 @@ -;; $Id: make.lisp,v 1.6 2007/01/20 18:17:55 alemmens Exp $ + +;; $Id: make.lisp,v 1.7 2007/08/12 13:01:13 alemmens Exp $ (in-package :cl-user) @@ -8,37 +9,38 @@ (defun make (&key (debug t)) (when debug (proclaim '(optimize (debug 3) (speed 0) (space 0)))) - (loop for file in '("queue" - "package" - "errors" - "mop" - "serialize" - "heap" - "object-table" - "schema-table" - "garbage-collector" - "cache" - "objects" - "p-btrees" - "index" - "rucksack" - "transactions" - "test") - do (tagbody - :retry - (let ((lisp (make-pathname :name file - :type "lisp" - :defaults *rucksack-directory*))) - (multiple-value-bind (fasl warnings failure) - (compile-file lisp) - (declare (ignore warnings)) - (when failure - (restart-case - (error "COMPILE-FILE reported failure on ~A" lisp) - (retry () - :report "Retry compilation" - (go :retry)) - (continue () - :report "Load resulting fasl anyway" - nil))) - (load fasl)))))) + (with-compilation-unit () + (loop for file in '("queue" + "package" + "errors" + "mop" + "serialize" + "heap" + "object-table" + "schema-table" + "garbage-collector" + "cache" + "objects" + "p-btrees" + "index" + "rucksack" + "transactions" + "test") + do (tagbody + :retry + (let ((lisp (make-pathname :name file + :type "lisp" + :defaults *rucksack-directory*))) + (multiple-value-bind (fasl warnings failure) + (compile-file lisp) + (declare (ignore warnings)) + (when failure + (restart-case + (error "COMPILE-FILE reported failure on ~A" lisp) + (retry () + :report "Retry compilation" + (go :retry)) + (continue () + :report "Load resulting fasl anyway" + nil))) + (load fasl))))))) --- /project/rucksack/cvsroot/rucksack/p-btrees.lisp 2007/03/13 13:13:00 1.14 +++ /project/rucksack/cvsroot/rucksack/p-btrees.lisp 2007/08/12 13:01:14 1.15 @@ -1,4 +1,4 @@ -;; $Id: p-btrees.lisp,v 1.14 2007/03/13 13:13:00 alemmens Exp $ +;; $Id: p-btrees.lisp,v 1.15 2007/08/12 13:01:14 alemmens Exp $ (in-package :rucksack) @@ -538,6 +538,61 @@ candidate)))))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; Debugging +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(defun check-btree (btree) + ;; Check that it is completely sorted. + (let (prev-key) + (map-btree-keys btree + (lambda (key value) + (declare (ignore value)) + (when prev-key + (unless (funcall (btree-key< btree) prev-key key) + (pprint (btree-as-cons btree)) + (error "Btree inconsistency between ~D and ~D" prev-key key))) + (setq prev-key key)))) + ;; Check that it is balanced + (unless (btree-balanced-p btree) + (error "Btree ~S is not balanced." btree))) + +(defun check-bnode-keys (tree node) + "Check a btree node (and its descendants) for consistency. This is only used +for debugging." + (car + (last + (loop with index = (btree-node-index node) + with leaf-p = (btree-node-leaf-p node) + for i below (btree-node-index-count node) + for binding = (p-aref index i) + collect + (if leaf-p + (if (btree-unique-keys-p tree) + (binding-key binding) + (binding-key (node-binding node + i))) + (progn + (let ((x (check-bnode-keys tree + (binding-value binding)))) + (when x + (unless (or (eq x 'key-irrelevant) + (eq (binding-key binding) 'key-irrelevant)) + (unless (funcall (btree-key= tree) + (funcall (btree-key-key tree) + (binding-key binding)) + (funcall (btree-key-key tree) + x)) + (print "Found error") + (describe (binding-key binding)) + (describe x) + (pprint (btree-as-cons tree)) + (error "Inconsistent bnode key at ~a binding ~a binding-key ~a val ~a X ~a" + node binding (binding-key binding) + (binding-value binding) x))))) + (binding-key binding))))))) + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; Insert ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; @@ -548,7 +603,7 @@ :btree btree :datum key :expected-type (btree-key-type btree))) - (unless (typep value (btree-key-type btree)) + (unless (typep value (btree-value-type btree)) (error 'btree-type-error :btree btree :datum value @@ -569,21 +624,6 @@ ;; Return the inserted value. value) -(defun check-btree (btree) - ;; Check that it is completely sorted. - (let (prev-key) - (map-btree-keys btree - (lambda (key value) - (declare (ignore value)) - (when prev-key - (unless (funcall (btree-key< btree) prev-key key) - (pprint (btree-as-cons btree)) - (error "Btree inconsistency between ~D and ~D" prev-key key))) - (setq prev-key key)))) - ;; Check that it is balanced - (unless (btree-balanced-p btree) - (error "Btree ~S is not balanced." btree))) - (defun make-root (btree left-key left-subnode right-key right-subnode) (let* ((root (make-instance (btree-node-class btree) :btree btree))) @@ -828,9 +868,20 @@ (ecase if-does-not-exist (:ignore (return-from leaf-delete-key)) (:error (error 'btree-search-error :btree btree :key key)))) - (remove-key leaf (binding-key binding)) - (unless (node-full-enough-p btree leaf) - (enlarge-node btree leaf parent-stack)))) + + (let* ((position (key-position key leaf)) + (length (btree-node-index-count leaf)) + (was-biggest-key-p (= position (1- length)))) + + (remove-key leaf (binding-key binding)) + + (unless (node-full-enough-p btree leaf) + (enlarge-node btree leaf parent-stack)) + + (when was-biggest-key-p + (unless (= 0 (btree-node-index-count leaf)) + (update-parents-for-deleted-key btree parent-stack key (biggest-key leaf))))))) + (defun enlarge-node (btree node parent-stack) ;; NODE is not full enough (less than half full), so we redistribute @@ -859,6 +910,17 @@ (return-from enlarge-node)))) (error "This should not happen.")) + +(defun update-parents-for-deleted-key (btree parent-stack old-key new-key) + (when parent-stack + (let ((node (first parent-stack))) + (when node + (let ((position (key-position old-key node))) + (when position + (setf (binding-key (node-binding node position)) + new-key) + (update-parents-for-deleted-key btree (rest parent-stack) old-key new-key))))))) + ;; The idea is that DISTRIBUTE-ELEMENTS will only be called if the union of ;; the two nodes has enough elements for two "legal" nodes. JOIN-NODES, --- /project/rucksack/cvsroot/rucksack/rucksack.asd 2007/03/13 13:13:00 1.10 +++ /project/rucksack/cvsroot/rucksack/rucksack.asd 2007/08/12 13:01:14 1.11 @@ -1,9 +1,9 @@ -;;; $Id: rucksack.asd,v 1.10 2007/03/13 13:13:00 alemmens Exp $ +;;; $Id: rucksack.asd,v 1.11 2007/08/12 13:01:14 alemmens Exp $ (in-package :cl-user) (asdf:defsystem :rucksack - :version "0.1.8" + :version "0.1.9" :serial t :components ((:file "queue") (:file "package") --- /project/rucksack/cvsroot/rucksack/rucksack.lisp 2007/03/13 13:13:00 1.20 +++ /project/rucksack/cvsroot/rucksack/rucksack.lisp 2007/08/12 13:01:14 1.21 @@ -1,4 +1,4 @@ -;; $Id: rucksack.lisp,v 1.20 2007/03/13 13:13:00 alemmens Exp $ +;; $Id: rucksack.lisp,v 1.21 2007/08/12 13:01:14 alemmens Exp $ (in-package :rucksack) @@ -874,9 +874,13 @@ (when index (let ((id (object-id object))) (when old-boundp - (index-delete index old-value id :if-does-not-exist :ignore)) + (index-delete index old-value id + :if-does-not-exist :ignore)) (when new-boundp - (index-insert index new-value id)))))) + (index-insert index new-value id + :if-exists (if (slot-unique slot) + :error + :overwrite))))))) (defmethod rucksack-slot-index ((rucksack standard-rucksack) class slot --- /project/rucksack/cvsroot/rucksack/test.lisp 2007/01/20 18:17:55 1.14 +++ /project/rucksack/cvsroot/rucksack/test.lisp 2007/08/12 13:01:14 1.15 @@ -1,4 +1,4 @@ -;; $Id: test.lisp,v 1.14 2007/01/20 18:17:55 alemmens Exp $ +;; $Id: test.lisp,v 1.15 2007/08/12 13:01:14 alemmens Exp $ (in-package :rucksack-test) @@ -207,7 +207,9 @@ (defun check-order (btree) (format t "~&Checking order and balance~%") - (rs::check-btree btree)) + (rs::check-btree btree) + (format t " and keys~%") + (rs::check-bnode-keys btree (rs::btree-root btree))) (defun check-contents (btree) (format t "~&Checking contents~%") From alemmens at common-lisp.net Mon Aug 13 15:14:28 2007 From: alemmens at common-lisp.net (alemmens) Date: Mon, 13 Aug 2007 11:14:28 -0400 (EDT) Subject: [rucksack-cvs] CVS rucksack Message-ID: <20070813151428.366E633081@common-lisp.net> Update of /project/rucksack/cvsroot/rucksack In directory clnet:/tmp/cvs-serv19262 Modified Files: done.txt Log Message: Fix credits: some of yesterday's patches were submitted by Takehiko Abe, not by Henrik Hjelte. --- /project/rucksack/cvsroot/rucksack/done.txt 2007/08/12 13:01:13 1.10 +++ /project/rucksack/cvsroot/rucksack/done.txt 2007/08/13 15:14:28 1.11 @@ -6,13 +6,13 @@ - Try to signal an error when an incompatible value is given to indexed slots, e.g. trying to put a string into a slot with a - :symbol-index. (Henrik Hjelte) + :symbol-index. (Takehiko Abe) - Signal an error during when putting duplicate values into a slot for - which duplicate values are not allowed. (Henrik Hjelte) + which duplicate values are not allowed. (Takehiko Abe) - Use BTREE-VALUE-TYPE, not BTREE-KEY-TYPE, when type checking a value - during BTREE-INSERT. (Henrik Hjelte) + during BTREE-INSERT. (Takehiko Abe) - Wrap COMPILE-FILE calls in a WITH-COMPILATION-UNIT to prevent superfluous warnings about undefined functions.