[elephant-cvs] CVS elephant/src/contrib/eslick

ieslick ieslick at common-lisp.net
Thu Apr 19 22:25:53 UTC 2007


Update of /project/elephant/cvsroot/elephant/src/contrib/eslick
In directory clnet:/tmp/cvs-serv25569/src/contrib/eslick

Modified Files:
	snapshot-db.lisp 
Log Message:
final snapshot scenario and code changes

--- /project/elephant/cvsroot/elephant/src/contrib/eslick/snapshot-db.lisp	2007/04/12 17:16:59	1.3
+++ /project/elephant/cvsroot/elephant/src/contrib/eslick/snapshot-db.lisp	2007/04/19 22:25:52	1.4
@@ -35,6 +35,17 @@
 ;;   to slots are saved to a persistent list that gets reused after
 ;;   snapshots (id slotname value).  Slot reads are as usual.
 ;;
+;; - Avoid stack use during recursions.  Push new objects onto a stack
+;;   for later processing so stack depth is constant.
+;;
+;; - In place restores.  A future version could traverse the existing
+;;   object cache, dropping new references and restoring old ones
+;;   according to the state of the snapshot-set on disk such that the
+;;   existing in-memory lisp pointers were still valid..as long as there
+;;   were not external pointers into objects that are dropped leading to
+;;   an inconsistency.
+;; 
+
 
 (in-package :elephant)
 
@@ -42,7 +53,10 @@
   ((index :accessor snapshot-set-index :initform (make-btree))
    (next-id :accessor snapshot-set-next-id :initform 0)
    (root :accessor snapshot-set-root :initform nil)
-   (cache :accessor snapshot-set-cache :initform (make-hash-table) :transient t))
+   (cache :accessor snapshot-set-cache :initform (make-hash-table :weak-keys t) :transient t)
+   (touched :accessor snapshot-set-touched 
+            :initform (make-array 20 :element-type 'fixnum :initial-element 0 :fill-pointer t :adjustable t)
+	    :transient t))
   (:documentation "Keeps track of a set of standard objects
     allowing a single snapshot call to update the store
     controller with the latest state of all objects registered with
@@ -95,6 +109,7 @@
   (setf (snapshot-set-root set) 
 	(multiple-value-bind (obj id)
 	    (register-object value set)
+	  (declare (ignore obj))
 	  id))
   value)
 
@@ -110,9 +125,10 @@
   "Saves all objects in the set (and any objects reachable from the
    current set of objects) to the persistent store"
   (with-transaction (:store-controller (get-con (snapshot-set-index set)))
-    (maphash (lambda (obj id)
-	       (save-snapshot-object id obj set))
-	     (snapshot-set-cache set))))
+    (loop for (obj . id) in (get-cache-entries (snapshot-set-cache set)) do
+	  (save-snapshot-object id obj set))
+    (collect-untouched set))
+  (values set t))
 
 (defmethod restore ((set snapshot-set))
   "Restores a snapshot by setting the snapshot-set state to the last snapshot.
@@ -123,7 +139,8 @@
   (clear-cache set)
   (map-btree (lambda (id object)
 	       (load-snapshot-object id object set))
-	     (snapshot-set-index set)))
+	     (snapshot-set-index set))
+  (values set t))
 
 ;; ===============
 ;; Shorthand
@@ -152,6 +169,13 @@
 (defun drop-cached-object (obj set)
   (remhash obj (snapshot-set-cache set)))
 
+(defun get-cache-entries (hash)
+  (let ((result nil))
+    (maphash (lambda (obj id)
+	       (push (cons obj id) result))
+	     hash)
+    result))
+
 ;; Save objects
 
 (defclass setref ()
@@ -163,34 +187,45 @@
 (defun standard-object-subclass-p (obj)
   (subtypep (type-of obj) 'standard-object))
 
+(defun touch (id set)
+  (vector-push-extend id (snapshot-set-touched set) 50))
+
+(defun touched (id set)
+  (find id (snapshot-set-touched set)))
+
+(defun clear-touched (set)
+  (loop for i fixnum from 0 upto (1- (length (snapshot-set-touched set))) do
+       (setf (aref (snapshot-set-touched set) i) 0)))
+
 (defun save-snapshot-object (id obj set)
-  (setf (get-value id (snapshot-set-index set))
-	(cond ((standard-object-subclass-p obj)
-	       (save-proxy-object obj set))
-	      ((hash-table-p obj)
-	       (save-proxy-hash obj set))
-	      (t (error "Cannot only snapshot standard-objects and hash-tables"))))
+  (unless (touched id set)
+    (setf (get-value id (snapshot-set-index set))
+	  (cond ((standard-object-subclass-p obj)
+		 (save-proxy-object obj set))
+		((hash-table-p obj)
+		 (save-proxy-hash obj set))
+		(t (error "Cannot only snapshot standard-objects and hash-tables"))))
+    (touch id set))
   id)
 
 (defun save-proxy-object (obj set)
   (let ((svs (subsets 2 (slots-and-values obj))))
-    (if (some #'reified-class-p (mapcar #'second svs))
+    (if (some #'reify-class-p (mapcar #'second svs))
 	(let ((proxy (make-instance (type-of obj))))
 	  (loop for (slotname value) in svs do
 	       (setf (slot-value proxy slotname)
 		     (if (reify-class-p value)
-			 (reify-object value set)
+			 (reify-value value set)
 			 value)))
 	  proxy)
 	obj)))
 
-
 (defun save-proxy-hash (hash set)
   (let ((proxy (make-hash-table)))
     (maphash (lambda (key value)
 	       (setf (gethash key proxy)
 		     (if (reify-class-p value)
-			 (reify-object value set)
+			 (reify-value value set) 
 			 value)))
 	     hash)
     proxy))
@@ -199,11 +234,19 @@
   (or (standard-object-subclass-p obj)
       (hash-table-p obj)))
 
-(defun reify-object (obj set)
+(defun reify-value (obj set)
   (multiple-value-bind (obj id) 
       (register-object obj set)
     (make-instance 'setref :id (save-snapshot-object id obj set))))
 
+(defun collect-untouched (set)
+  (map-btree (lambda (k v) 
+	       (declare (ignore v))
+	       (unless (touched k set)
+		 (remove-kv k (snapshot-set-index set))))
+	     (snapshot-set-index set))
+  (clear-touched set))
+
 ;; Load objects
 
 (defun load-snapshot-object (id object set)
@@ -273,7 +316,8 @@
     (setf set nil)
     (setf hash nil)
     (elephant::flush-instance-cache *store-controller*)
-    (cl-user::gc)
+    #+allegro (excl:gc)
+    #+sbcl (cl-user::gc)
     ;; Reload
     (setf set (get-from-root 'set))
     (setf hash (snapshot-root set))




More information about the Elephant-cvs mailing list