[elephant-cvs] CVS elephant/src/db-acache

ieslick ieslick at common-lisp.net
Mon Feb 20 21:21:41 UTC 2006


Update of /project/elephant/cvsroot/elephant/src/db-acache
In directory common-lisp:/tmp/cvs-serv10634/src/db-acache

Added Files:
	README acache-collections.lisp acache-controller.lisp 
	acache-transactions.lisp package.lisp 
Log Message:
A quick AllegroCache backend based on the allegrocache map and compound keys - functionality is only partial but the basics work


--- /project/elephant/cvsroot/elephant/src/db-acache/README	2006/02/20 21:21:41	NONE
+++ /project/elephant/cvsroot/elephant/src/db-acache/README	2006/02/20 21:21:41	1.1


This directory contains a quick and dirty sketch of an allegrocache
backend, mostly to test out the new backend abstraction.  Too bad we 
can't use allegroserve directly behind the metaclass protocol...the 
apis are a little too different for that.
--- /project/elephant/cvsroot/elephant/src/db-acache/acache-collections.lisp	2006/02/20 21:21:41	NONE
+++ /project/elephant/cvsroot/elephant/src/db-acache/acache-collections.lisp	2006/02/20 21:21:41	1.1


(in-package :elephant-acache)

;; BTREE

(defclass acache-btree (btree) ())

(defmethod build-btree ((sc acache-store-controller))
  (make-instance 'acache-btree :sc sc))

(defmethod get-value (key (bt acache-btree))
  (map-value (controller-btrees (get-con bt)) (cons (oid bt) key)))

(defmethod (setf get-value) (value key (bt acache-btree))
  (setf (map-value (controller-btrees (get-con bt)) (cons (oid bt) key))
	value))

(defmethod existsp (key (bt acache-btree))
  (when (get-value key bt)
    t))

(defmethod remove-kv (key (bt acache-btree))
  (remove-from-map (controller-btrees (get-con bt)) (cons (oid bt) key)))

(defmethod map-btree (fn (bt acache-btree))
  (map-map fn bt))

;;
;; Cursors need to have their own model of where they are
;;

;; INDEXED BTREE

;; How to handle add-index?  Have to hack it up on btrees just like slot
;; values...which means solving the complex key problem--- /project/elephant/cvsroot/elephant/src/db-acache/acache-controller.lisp	2006/02/20 21:21:41	NONE
+++ /project/elephant/cvsroot/elephant/src/db-acache/acache-controller.lisp	2006/02/20 21:21:41	1.1

(in-package :elephant-acache)

(defclass acache-store-controller (store-controller)
  ((db :accessor controller-db :initform nil)
   (slots :accessor controller-slots :initform nil)
   (btrees :accessor controller-btrees :initform nil)
   (oidrec :accessor controller-oidrec :initform nil)))

(defun acache-constructor (spec)
  (make-instance 'acache-store-controller :spec spec))

(eval-when (:compile-toplevel :load-toplevel)
  (register-backend-con-init :acache 'acache-constructor))

(defclass oid-record ()
  ((counter :accessor oid-record-counter :initform 0))
  (:metaclass db.allegrocache:persistent-class))

(defmethod open-controller ((sc acache-store-controller) &key (recover t)
			    (recover-fatal nil) (thread nil))
  (declare (ignore recover thread recover-fatal))
  (let ((db (db.allegrocache:open-file-database (second (controller-spec sc))
						 :if-does-not-exist :create
						 :if-exists :open
						 :use :memory)))
    (when (not db)
      (error "Unable to open astore database for ~A" (controller-spec sc)))
    ;; Main DB ref
    (setf (controller-db sc) db)
    ;; Slots and Btree storage
    (let ((slotmap (retrieve-from-index 'ac-map 'ac-map-name "slots")))
      (setf (controller-slots sc) 
	    (if slotmap slotmap
		(make-instance 'db.allegrocache:ac-map :ac-map-name "slots"))))
    (let ((btreemap (retrieve-from-index 'ac-map 'ac-map-name "btrees")))
      (setf (controller-btrees sc) 
	    (if btreemap btreemap
		(make-instance 'db.allegrocache:ac-map :ac-map-name "btrees"))))
    ;; OIDS
    (let ((oidrec (doclass (inst (find-class 'oid-record) :db db)
		    (when inst (return inst)))))
      (setf (controller-oidrec sc)
	    (if oidrec
		oidrec
		(make-instance 'oid-record))))
    ;; Construct the roots
    (setf (slot-value sc 'root) (make-instance 'acache-btree :from-oid -1))
    (setf (slot-value sc 'class-root) (make-instance 'acache-btree :from-oid -2))
    sc))
    
    
(defmethod next-oid ((sc acache-store-controller))
  (db.allegrocache:with-transaction-restart ()
    (incf (oid-record-counter (controller-oidrec sc)))
    (commit)))

(defmethod close-controller ((sc acache-store-controller))
  ;; Ensure deletion of common
  (setf (slot-value sc 'class-root) nil)
  (setf (slot-value sc 'root) nil)
  (db.allegrocache:close-database :db (controller-db sc)))

(defmethod connection-is-indeed-open ((sc acache-store-controller))
  (db.allegrocache::database-open-p (controller-db sc)))

;; Slot writing

;; This is not thread-safe, but could be a thread-local when we fix that...
;; to avoid extra consing.  Is consing less/more expensive than dynamic
;; var lookups?

(defvar *index-cons* (cons nil nil))

(defmacro fast-key (oid name)
  `(rplacd (rplaca *index-cons* ,oid) ,name))

(defmethod persistent-slot-reader ((sc acache-store-controller) instance name)
  (declare (optimize (speed 3) (safety 1)))
  (multiple-value-bind (val valid?) (map-value (controller-slots sc) (fast-key (oid instance) name))
    (if valid?
	val
	(error "Slot ~A unbound in ~A" name instance))))

(defmethod persistent-slot-writer ((sc acache-store-controller) value instance name)
  (declare (optimize (speed 3) (safety 1)))
  (setf (map-value (controller-slots sc) (fast-key (oid instance) name))
	value))

(defmethod persistent-slot-boundp ((sc acache-store-controller) instance name)
  (declare (optimize (speed 3) (safety 1)))
  (when (map-value (controller-slots sc) (fast-key (oid instance) name))
    t))

(defmethod persistent-slot-makunbound ((sc acache-store-controller) instance name)
  (declare (optimize (speed 3) (safety 1)))
  (remove-from-map (controller-slots sc) (fast-key (oid instance) name)))

--- /project/elephant/cvsroot/elephant/src/db-acache/acache-transactions.lisp	2006/02/20 21:21:41	NONE
+++ /project/elephant/cvsroot/elephant/src/db-acache/acache-transactions.lisp	2006/02/20 21:21:41	1.1


(in-package :elephant-acache)

(defmethod controller-start-transaction ((sc acache-store-controller) &key parent &allow-other-keys)
  "Allegrocache has implicit transactions whenever there's a write"
  (when parent
    (error "ACache backend does not allow nested transactions...a commit will commit everything
            since the last commit"))
  t)

(defmethod controller-commit-transaction ((sc acache-store-controller) &key &allow-other-keys)
  (db.allegrocache:commit :db (controller-db sc)))

(defmethod controller-abort-transaction ((sc acache-store-controller) &key &allow-other-keys)
  (db.allegrocache:rollback :db (controller-db sc)))

(defmethod execute-transaction ((sc acache-store-controller) closure &key parent retries &allow-other-keys)
  (db.allegrocache:with-transaction-restart (:count retries)
    (funcall closure)
    (db.allegrocache:commit :db sc)))--- /project/elephant/cvsroot/elephant/src/db-acache/package.lisp	2006/02/20 21:21:41	NONE
+++ /project/elephant/cvsroot/elephant/src/db-acache/package.lisp	2006/02/20 21:21:41	1.1


(in-package :cl-user)

(eval-when (:load-toplevel :compile-toplevel)
  (require :acache))

(eval-when (:load-toplevel)
  (warn "Allegrocache support is incomplete and should be considered as an example only"))

(defpackage elephant-acache
  (:documentation "A low-level UFFI-based interface to
   Berkeley DB / Sleepycat to implement the elephant front-end
   framework.  Uses the libsleepycat.c wrapper.  Partly intended 
   to be usable outside Elephant, but with some magic for Elephant.  
   In general there is a 1-1 mapping from functions here and 
   functions in Sleepycat, so refer to their documentation for details.")
  (:use common-lisp elephant elephant-backend)
  (:import-from #:db.allegrocache
		#:ac-map
		#:ac-map-name
		#:doclass
		#:commit
		#:retrieve-from-index
		#:map-map
		#:map-value
		#:remove-from-map))





More information about the Elephant-cvs mailing list