[elephant-cvs] CVS elephant/src/contrib/eslick/db-acache
ieslick
ieslick at common-lisp.net
Sun Feb 4 10:17:20 UTC 2007
Update of /project/elephant/cvsroot/elephant/src/contrib/eslick/db-acache
In directory clnet:/tmp/cvs-serv8664/src/contrib/eslick/db-acache
Added Files:
README acache-collections.lisp acache-controller.lisp
acache-transactions.lisp package.lisp
Log Message:
Cleaning up source directory, moving partial projects to contrib
--- /project/elephant/cvsroot/elephant/src/contrib/eslick/db-acache/README 2007/02/04 10:17:20 NONE
+++ /project/elephant/cvsroot/elephant/src/contrib/eslick/db-acache/README 2007/02/04 10:17:20 1.1
This directory contains a quick and dirty sketch of an allegrocache
backend, mostly to test out the new backend abstraction.
Basic btrees work fine but iteration (cursors) are very limited.
I think the best way to go is reverse engineer the db.btree API
and just implement the elephant backend on top of that API. I
may do this at some point, but not today...
Or better yet, find someone willing to write a btree library in
lisp. John Fedaro said it wasn't a huge amount of work and can
be done with very high performance in all Common Lisp.
Ian
--- /project/elephant/cvsroot/elephant/src/contrib/eslick/db-acache/acache-collections.lisp 2007/02/04 10:17:20 NONE
+++ /project/elephant/cvsroot/elephant/src/contrib/eslick/db-acache/acache-collections.lisp 2007/02/04 10:17:20 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))
;; INDEXED BTREE
(defclass acache-indexed-btree (indexed-btree acache-btree)
((indices :accessor indices :initarg :indices :initform (make-hash-table))
(indices-cache :accessor indices-cache :initarg :indicies-cache :initform nil :transient t))
(:metaclass persistent-metaclass))
(defmethod build-indexed-btree ((sc acache-store-controller))
(make-instance 'acache-indexed-btree :sc sc))
(defclass acache-btree-index (btree-index acache-btree)
()
(:metaclass persistent-metaclass))
(defmethod build-btree-index ((sc acache-store-controller) &key primary key-form)
(make-instance 'acache-btree-index :primary primary :key-form :sc sc))
;;
;; CURSORS
;;
(defclass acache-cursor (cursor)
())
(defmethod make-cursor ((bt acache-btree))
(make-instance 'acache-cursor))
--- /project/elephant/cvsroot/elephant/src/contrib/eslick/db-acache/acache-controller.lisp 2007/02/04 10:17:20 NONE
+++ /project/elephant/cvsroot/elephant/src/contrib/eslick/db-acache/acache-controller.lisp 2007/02/04 10:17:20 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))
(incf (oid-record-counter (controller-oidrec sc))))
(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/contrib/eslick/db-acache/acache-transactions.lisp 2007/02/04 10:17:20 NONE
+++ /project/elephant/cvsroot/elephant/src/contrib/eslick/db-acache/acache-transactions.lisp 2007/02/04 10:17:20 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/contrib/eslick/db-acache/package.lisp 2007/02/04 10:17:20 NONE
+++ /project/elephant/cvsroot/elephant/src/contrib/eslick/db-acache/package.lisp 2007/02/04 10:17:20 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