Update of /project/elephant/cvsroot/elephant/src
In directory common-lisp.net:/tmp/cvs-serv4345/src
Modified Files:
utils.lisp sleepycat.lisp serializer.lisp controller.lisp
berkeley-db.lisp
Log Message:
updates for sbcl unicode, sleepycat 4.3, new sequences and degree-2
Date: Thu Feb 24 02:06:10 2005
Author: blee
Index: elephant/src/utils.lisp
diff -u elephant/src/utils.lisp:1.7 elephant/src/utils.lisp:1.8
--- elephant/src/utils.lisp:1.7 Sun Sep 19 19:52:18 2004
+++ elephant/src/utils.lisp Thu Feb 24 02:06:08 2005
@@ -47,6 +47,9 @@
(type hash-table *circularity-hash*)
(type boolean *auto-commit*))
+(defvar *cachesize* 100
+ "Size of the OID sequence cache.")
+
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;
;;; Thread-local specials
@@ -106,7 +109,7 @@
(environment '(controller-environment
*store-controller*))
(parent '*current-transaction*)
- dirty-read txn-nosync
+ degree-2 dirty-read txn-nosync
txn-nowait txn-sync
(retries 100))
&body body)
@@ -118,6 +121,7 @@
`(sleepycat:with-transaction (:transaction ,transaction
:environment ,environment
:parent ,parent
+ :degree-2 ,degree-2
:dirty-read ,dirty-read
:txn-nosync ,txn-nosync
:txn-nowait ,txn-nowait
Index: elephant/src/sleepycat.lisp
diff -u elephant/src/sleepycat.lisp:1.12 elephant/src/sleepycat.lisp:1.13
--- elephant/src/sleepycat.lisp:1.12 Tue Sep 21 03:37:21 2004
+++ elephant/src/sleepycat.lisp Thu Feb 24 02:06:09 2005
@@ -71,7 +71,11 @@
#:buffer-write-uint #:buffer-write-float #:buffer-write-double
#:buffer-write-string #:buffer-read-byte #:buffer-read-fixnum
#:buffer-read-int #:buffer-read-uint #:buffer-read-float
- #:buffer-read-double #:buffer-read-string #:byte-length
+ #:buffer-read-double
+ #-(and allegro ics) #:buffer-read-ucs1-string
+ #+(or lispworks (and allegro ics)) #:buffer-read-ucs2-string
+ #+(and sbcl sb-unicode) #:buffer-read-ucs4-string
+ #:byte-length
#:pointer-int #:pointer-void #:array-or-pointer-char
@@ -92,7 +96,14 @@
#:db-cursor-pget-both-buffered #:db-cursor-put-buffered
#:db-transaction-begin #:db-transaction-abort
#:db-transaction-commit #:with-transaction
- #:db-transaction-id #:db-env-lock-id #:db-env-lock-id-free
+ #:db-transaction-id
+ #:db-sequence-create #:db-sequence-open #:db-sequence-close
+ #:db-sequence-get #:db-sequence-get-fixnum
+ #:db-sequence-initial-value #:db-sequence-remove
+ #:db-sequence-set-cachesize #:db-sequence-get-cachesize
+ #:db-sequence-set-flags #:db-sequence-set-range
+ #:db-sequence-get-range
+ #:db-env-lock-id #:db-env-lock-id-free
#:db-env-lock-get #:db-env-lock-put #:with-lock
#:db-env-set-timeout #:db-env-get-timeout
#:db-env-set-lock-detect #:db-env-get-lock-detect
@@ -132,12 +143,12 @@
(uffi:load-foreign-library
;; Sleepycat: this works on linux
#+linux
- "/usr/local/BerkeleyDB.4.2/lib/libdb.so"
+ "/db/ben/lisp/db43/lib/libdb.so"
;; this works on FreeBSD
#+(and (or bsd freebsd) (not darwin))
- "/usr/local/lib/db42/libdb.so"
+ "/usr/local/lib/db43/libdb.so"
#+darwin
- "/usr/local/BerkeleyDB.4.2/lib/libdb.dylib"
+ "/usr/local/BerkeleyDB.4.3/lib/libdb.dylib"
:module "sleepycat")
(error "Couldn't load libdb (Sleepycat)!"))
@@ -165,7 +176,7 @@
(declaim (inline read-int read-uint read-float read-double
write-int write-uint write-float write-double
- offset-char-pointer copy-str-to-buf copy-bufs
+ offset-char-pointer copy-str-to-buf %copy-str-to-buf copy-bufs
;;resize-buffer-stream
;;buffer-stream-buffer buffer-stream-size buffer-stream-position
;;buffer-stream-length
@@ -174,7 +185,9 @@
buffer-write-float buffer-write-double buffer-write-string
buffer-read-byte buffer-read-fixnum buffer-read-int
buffer-read-uint buffer-read-float buffer-read-double
- buffer-read-string))
+ #-(and allegreo ics) buffer-read-ucs1-string
+ #+(or lispworks (and allegro ics)) buffer-read-ucs2-string
+ #+(and sbcl sb-unicode) buffer-read-ucs4-string))
;; Constants and Flags
;; eventually write a macro which generates a custom flag function.
@@ -182,8 +195,8 @@
;I don't like the UFFI syntax for enumerations
(defconstant DB-BTREE 1)
(defconstant DB-HASH 2)
-(defconstant DB-QUEUE 3)
-(defconstant DB-RECNO 4)
+(defconstant DB-RECNO 3)
+(defconstant DB-QUEUE 4)
(defconstant DB-UNKNOWN 5)
(defconstant DB_AUTO_COMMIT #x1000000)
@@ -201,7 +214,8 @@
(defconstant DB_SYSTEM_MEM #x0400000)
(defconstant DB_THREAD #x0000040)
(defconstant DB_FORCE #x0000004)
-(defconstant DB_DIRTY_READ #x2000000)
+(defconstant DB_DEGREE_2 #x2000000)
+(defconstant DB_DIRTY_READ #x4000000)
(defconstant DB_CREATE #x0000001)
(defconstant DB_EXCL #x0001000)
(defconstant DB_NOMMAP #x0000008)
@@ -210,7 +224,7 @@
(defconstant DB_TXN_NOSYNC #x0000100)
(defconstant DB_TXN_NOWAIT #x0001000)
(defconstant DB_TXN_SYNC #x0002000)
-(defconstant DB_LOCK_NOWAIT #x001)
+(defconstant DB_LOCK_NOWAIT #x002)
(defconstant DB_DUP #x0000002)
(defconstant DB_DUPSORT #x0000004)
@@ -238,6 +252,11 @@
(defconstant DB_POSITION 24)
+(defconstant DB_SEQ_DEC #x00000001)
+(defconstant DB_SEQ_INC #x00000002)
+(defconstant DB_SEQ_WRAP #x00000008)
+
+
(defconstant DB_SET_LOCK_TIMEOUT 29)
(defconstant DB_SET_TXN_TIMEOUT 33)
@@ -245,16 +264,17 @@
(defconstant DB_KEYEXIST -30996)
(defconstant DB_LOCK_DEADLOCK -30995)
(defconstant DB_LOCK_NOTGRANTED -30994)
-(defconstant DB_NOTFOUND -30990)
+(defconstant DB_NOTFOUND -30989)
(defconstant DB_LOCK_DEFAULT 1)
(defconstant DB_LOCK_EXPIRE 2)
(defconstant DB_LOCK_MAXLOCKS 3)
-(defconstant DB_LOCK_MINLOCKS 4)
-(defconstant DB_LOCK_MINWRITE 5)
-(defconstant DB_LOCK_OLDEST 6)
-(defconstant DB_LOCK_RANDOM 7)
-(defconstant DB_LOCK_YOUNGEST 8)
+(defconstant DB_LOCK_MAXWRITE 4)
+(defconstant DB_LOCK_MINLOCKS 5)
+(defconstant DB_LOCK_MINWRITE 6)
+(defconstant DB_LOCK_OLDEST 7)
+(defconstant DB_LOCK_RANDOM 8)
+(defconstant DB_LOCK_YOUNGEST 9)
(defvar +NULL-VOID+ (make-null-pointer :void)
"A null pointer to a void type.")
@@ -299,6 +319,22 @@
(defvar *buffer-streams* (make-array 0 :adjustable t :fill-pointer t)
"Vector of buffer-streams, which you can grab / return.")
+(defconstant +2^32+ 4294967296)
+(defconstant +2^64+ 18446744073709551616)
+(defconstant +2^32-1+ (1- +2^32+))
+
+(defmacro make-64-bit-integer (high32 low32)
+ `(+ ,low32 (ash ,high32 32)))
+
+(defmacro high32 (int64)
+ `(ash ,int64 -32))
+
+(defmacro low32 (int64)
+ `(logand ,int64 +2^32-1+))
+
+(defmacro split-64-bit-integer (int64)
+ `(values (ash ,int64 -32) (logand ,int64 +2^32-1+)))
+
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;
;;; buffer-streams
@@ -498,9 +534,13 @@
(defmacro byte-length (s)
"Return the number of bytes of the internal representation
of a string."
- #+(or lispworks (and allegro ics))
+ #+(and allegro ics)
`(let ((l (length ,s))) (+ l l))
- #-(or lispworks (and allegro ics))
+ #+(or (and sbcl sb-unicode) lispworks)
+ `(etypecase ,s
+ (base-string (length ,s))
+ (string (* (length ,s) #+sbcl 4 #+lispworks 2)))
+ #-(or lispworks (and allegro ics) (and sbcl sb-unicode))
`(length ,s))
;; for copying the bytes of a string to a foreign buffer
@@ -517,14 +557,27 @@
:returning :void)
#+(or cmu sbcl scl)
-(def-function ("copy_buf" copy-str-to-buf)
+(def-function ("copy_buf" %copy-str-to-buf)
((dest array-or-pointer-char)
(dest-offset :int)
- (src :cstring)
+ (src array-or-pointer-char)
(src-offset :int)
(length :int))
:returning :void)
+#+(or cmu sbcl scl)
+(defun copy-str-to-buf (d do s so l)
+ (declare (optimize (speed 3) (safety 0))
+ (type array-or-pointer-char d)
+ (type fixnum do so l)
+ (type string s))
+ (%copy-str-to-buf d do
+ #+sbcl
+ (sb-sys:vector-sap s)
+ #+(or cmu scl)
+ (sys:vector-sap s)
+ so l))
+
;; but OpenMCL can't directly pass string bytes.
#+openmcl
(defun copy-str-to-buf (dest dest-offset src src-offset length)
@@ -775,27 +828,62 @@
(setf (buffer-stream-position bs) (+ position 8))
(read-double (buffer-stream-buffer bs) position)))
-(defun buffer-read-string (bs length)
- "Read a string. On Unicode Lisps this is a 16-bit operation!"
+(defun buffer-read-ucs1-string (bs byte-length)
+ "Read a UCS1 string."
(declare (optimize (speed 3) (safety 0))
(type buffer-stream bs)
- (type fixnum length))
+ (type fixnum byte-length))
+ (let ((position (buffer-stream-position bs)))
+ (setf (buffer-stream-position bs) (+ position byte-length))
+ #-(and sbcl sb-unicode)
+ (convert-from-foreign-string
+ (offset-char-pointer (buffer-stream-buffer bs) position)
+ :length byte-length :null-terminated-p nil)
+ #+(and sbcl sb-unicode)
+ (let ((res (make-string byte-length :element-type 'base-char)))
+ (sb-kernel:copy-from-system-area
+ (sb-alien:alien-sap (buffer-stream-buffer bs))
+ (* position sb-vm:n-byte-bits)
+ res
+ (* sb-vm:vector-data-offset sb-vm:n-word-bits)
+ (* byte-length sb-vm:n-byte-bits))
+ res)))
+
+#+(or lispworks (and allegro ics))
+(defun buffer-read-ucs2-string (bs byte-length)
+ "Read a UCS2 string."
+ (declare (optimize (speed 3) (safety 0))
+ (type buffer-stream bs)
+ (type fixnum byte-length))
(let ((position (buffer-stream-position bs)))
- (setf (buffer-stream-position bs) (+ position length))
+ (setf (buffer-stream-position bs) (+ position byte-length))
;; wide!!!
#+(and allegro ics)
(excl:native-to-string
(offset-char-pointer (buffer-stream-buffer bs) position)
- :length length
+ :length byte-length
:external-format :unicode)
#+lispworks
(fli:convert-from-foreign-string
(offset-char-pointer (buffer-stream-buffer bs) position)
- :length length :external-format :unicode :null-terminated-p nil)
- #-(or lispworks (and allegro ics))
- (convert-from-foreign-string
- (offset-char-pointer (buffer-stream-buffer bs) position)
- :length length :null-terminated-p nil)))
+ :length byte-length :external-format :unicode :null-terminated-p nil)))
+
+#+(and sbcl sb-unicode)
+(defun buffer-read-ucs4-string (bs byte-length)
+ "Read a UCS4 string."
+ (declare (optimize (speed 3) (safety 0))
+ (type buffer-stream bs)
+ (type fixnum byte-length))
+ (let ((position (buffer-stream-position bs)))
+ (setf (buffer-stream-position bs) (+ position byte-length))
+ (let ((res (make-string (/ byte-length 4) :element-type 'character)))
+ (sb-kernel:copy-from-system-area
+ (sb-alien:alien-sap (buffer-stream-buffer bs))
+ (* position sb-vm:n-byte-bits)
+ res
+ (* sb-vm:vector-data-offset sb-vm:n-word-bits)
+ (* byte-length sb-vm:n-byte-bits))
+ res)))
;; Wrapper macro -- handles errno return values
;; makes flags into keywords
@@ -881,12 +969,14 @@
(defmacro flags (&key auto-commit joinenv init-cdb init-lock init-log
init-mpool init-rep init-txn recover recover-fatal lockdown
- private system-mem thread force dirty-read create excl nommap
+ private system-mem thread force degree-2 dirty-read create
+ excl nommap
rdonly truncate txn-nosync txn-nowait txn-sync lock-nowait
dup dup-sort current first get-both get-both-range last next
next-dup next-nodup prev prev-nodup set set-range
after before keyfirst keylast
- no-dup-data no-overwrite nosync position set-lock-timeout
+ no-dup-data no-overwrite nosync position
+ seq-dec seq-inc seq-wrap set-lock-timeout
set-transaction-timeout)
(let ((flags (gensym)))
`(let ((,flags 0))
@@ -906,6 +996,7 @@
,@(when system-mem `((when ,system-mem (setq ,flags (logior ,flags DB_SYSTEM_MEM)))))
,@(when thread `((when ,thread (setq ,flags (logior ,flags DB_THREAD)))))
,@(when force `((when ,force (setq ,flags (logior ,flags DB_FORCE)))))
+ ,@(when degree-2 `((when ,degree-2 (setq ,flags (logior ,flags DB_DEGREE_2)))))
,@(when dirty-read `((when ,dirty-read (setq ,flags (logior ,flags DB_DIRTY_READ)))))
,@(when create `((when ,create (setq ,flags (logior ,flags DB_CREATE)))))
,@(when excl `((when ,excl (setq ,flags (logior ,flags DB_EXCL)))))
@@ -938,6 +1029,9 @@
,@(when no-overwrite `((when ,no-overwrite (setq ,flags (logior ,flags DB_NOOVERWRITE)))))
,@(when nosync `((when ,nosync (setq ,flags (logior ,flags DB_NOSYNC)))))
,@(when position `((when ,position (setq ,flags (logior ,flags DB_POSITION)))))
+ ,@(when seq-dec `((when ,seq-dec (setq ,flags (logior ,flags DB_SEQ_DEC)))))
+ ,@(when seq-inc `((when ,seq-inc (setq ,flags (logior ,flags DB_SEQ_INC)))))
+ ,@(when seq-wrap `((when ,seq-wrap (setq ,flags (logior ,flags DB_SEQ_WRAP)))))
,@(when set-lock-timeout `((when ,set-lock-timeout (setq ,flags (logior ,flags DB_SET_LOCK_TIMEOUT)))))
,@(when set-transaction-timeout `((when ,set-transaction-timeout (setq ,flags (logior ,flags DB_SET_TXN_TIMEOUT)))))
,flags)))
Index: elephant/src/serializer.lisp
diff -u elephant/src/serializer.lisp:1.9 elephant/src/serializer.lisp:1.10
--- elephant/src/serializer.lisp:1.9 Thu Sep 16 06:20:41 2004
+++ elephant/src/serializer.lisp Thu Feb 24 02:06:10 2005
@@ -62,20 +62,19 @@
(defconstant +nil+ 8)
;; 8-bit
-#-(or lispworks (and allegro ics))
-(defconstant +symbol+ 9)
-#-(or lispworks (and allegro ics))
-(defconstant +string+ 10)
-#-(or lispworks (and allegro ics))
-(defconstant +pathname+ 11)
+(defconstant +ucs1-symbol+ 9)
+(defconstant +ucs1-string+ 10)
+(defconstant +ucs1-pathname+ 11)
;; 16-bit
-#+(or lispworks (and allegro ics))
-(defconstant +symbol+ 12)
-#+(or lispworks (and allegro ics))
-(defconstant +string+ 13)
-#+(or lispworks (and allegro ics))
-(defconstant +pathname+ 14)
+(defconstant +ucs2-symbol+ 12)
+(defconstant +ucs2-string+ 13)
+(defconstant +ucs2-pathname+ 14)
+
+;; 32-bit
+(defconstant +ucs4-symbol+ 20)
+(defconstant +ucs4-string+ 21)
+(defconstant +ucs4-pathname+ 22)
(defconstant +persistent+ 15)
(defconstant +cons+ 16)
@@ -105,7 +104,15 @@
(symbol
(let ((s (symbol-name frob)))
(declare (type string s) (dynamic-extent s))
- (buffer-write-byte +symbol+ bs)
+ (buffer-write-byte
+ #+(and allegro ics) +ucs2-symbol+
+ #+(or (and sbcl sb-unicode) lispworks)
+ (etypecase s
+ (base-string +ucs1-symbol+)
+ (string #+sbcl +ucs4-symbol+ #+lispwoks +ucs2-symbol+))
+ #-(or lispworks (and allegro ics) (and sbcl sb-unicode))
+ +ucs1-symbol+
+ bs)
(buffer-write-int (byte-length s) bs)
(buffer-write-string s bs)
(let ((package (symbol-package frob)))
@@ -113,7 +120,15 @@
(%serialize (package-name package))
(%serialize nil)))))
(string
- (buffer-write-byte +string+ bs)
+ (buffer-write-byte
+ #+(and allegro ics) +ucs2-string+
+ #+(or (and sbcl sb-unicode) lispworks)
+ (etypecase frob
+ (base-string +ucs1-string+)
+ (string #+sbcl +ucs4-string+ #+lispwoks +ucs2-string+))
+ #-(or lispworks (and allegro ics) (and sbcl sb-unicode))
+ +ucs1-string+
+ bs)
(buffer-write-int (byte-length frob) bs)
(buffer-write-string frob bs))
(persistent
@@ -134,7 +149,15 @@
(pathname
(let ((s (namestring frob)))
(declare (type string s) (dynamic-extent s))
- (buffer-write-byte +pathname+ bs)
+ (buffer-write-byte
+ #+(and allegro ics) +ucs2-pathname+
+ #+(or (and sbcl sb-unicode) lispworks)
+ (etypecase s
+ (base-string +ucs1-pathname+)
+ (string #+sbcl +ucs4-pathname+ #+lispwoks +ucs2-pathname+))
+ #-(or lispworks (and allegro ics) (and sbcl sb-unicode))
+ +ucs1-pathname+
+ bs)
(buffer-write-int (byte-length s) bs)
(buffer-write-string s bs)))
(integer
@@ -252,14 +275,36 @@
((= tag +fixnum+)
(buffer-read-fixnum bs))
((= tag +nil+) nil)
- ((= tag +symbol+)
- (let ((name (buffer-read-string bs (buffer-read-fixnum bs)))
+ #-(and allegro ics)
+ ((= tag +ucs1-symbol+)
+ (let ((name (buffer-read-ucs1-string bs (buffer-read-fixnum bs)))
+ (maybe-package-name (%deserialize bs)))
+ (if maybe-package-name
+ (intern name (find-package maybe-package-name))
+ (make-symbol name))))
+ #+(or lispworks (and allegro ics))
+ ((= tag +ucs2-symbol+)
+ (let ((name (buffer-read-ucs2-string bs (buffer-read-fixnum bs)))
(maybe-package-name (%deserialize bs)))
(if maybe-package-name
(intern name (find-package maybe-package-name))
(make-symbol name))))
- ((= tag +string+)
- (buffer-read-string bs (buffer-read-fixnum bs)))
+ #+(and sbcl sb-unicode)
+ ((= tag +ucs4-symbol+)
+ (let ((name (buffer-read-ucs4-string bs (buffer-read-fixnum bs)))
+ (maybe-package-name (%deserialize bs)))
+ (if maybe-package-name
+ (intern name (find-package maybe-package-name))
+ (make-symbol name))))
+ #-(and allegro ics)
+ ((= tag +ucs1-string+)
+ (buffer-read-ucs1-string bs (buffer-read-fixnum bs)))
+ #+(or lispworks (and allegro ics))
+ ((= tag +ucs2-string+)
+ (buffer-read-ucs2-string bs (buffer-read-fixnum bs)))
+ #+(and sbcl sb-unicode)
+ ((= tag +ucs4-string+)
+ (buffer-read-ucs4-string bs (buffer-read-fixnum bs)))
((= tag +persistent+)
(get-cached-instance *store-controller*
(buffer-read-fixnum bs)
@@ -270,9 +315,18 @@
(buffer-read-double bs))
((= tag +char+)
(code-char (buffer-read-uint bs)))
- ((= tag +pathname+)
+ #-(and allegro ics)
+ ((= tag +ucs1-pathname+)
+ (parse-namestring
+ (or (buffer-read-ucs1-string bs (buffer-read-fixnum bs)) "")))
+ #+(or lispworks (and allegro ics))
+ ((= tag +ucs2-pathname+)
+ (parse-namestring
+ (or (buffer-read-ucs2-string bs (buffer-read-fixnum bs)) "")))
+ #+(and sbcl sb-unicode)
+ ((= tag +ucs4-pathname+)
(parse-namestring
- (or (buffer-read-string bs (buffer-read-fixnum bs)) "")))
+ (or (buffer-read-ucs4-string bs (buffer-read-fixnum bs)) "")))
((= tag +positive-bignum+)
(deserialize-bignum bs (buffer-read-fixnum bs) t))
((= tag +negative-bignum+)
Index: elephant/src/controller.lisp
diff -u elephant/src/controller.lisp:1.11 elephant/src/controller.lisp:1.12
--- elephant/src/controller.lisp:1.11 Sun Sep 19 19:49:25 2004
+++ elephant/src/controller.lisp Thu Feb 24 02:06:10 2005
@@ -49,6 +49,8 @@
(environment :type (or null pointer-void)
:accessor controller-environment)
(db :type (or null pointer-void) :accessor controller-db)
+ (oid-db :type (or null pointer-void) :accessor controller-oid-db)
+ (oid-seq :type (or null pointer-void) :accessor controller-oid-seq)
(btrees :type (or null pointer-void) :accessor controller-btrees)
(indices :type (or null pointer-void) :accessor controller-indices)
(indices-assoc :type (or null pointer-void)
@@ -102,33 +104,11 @@
;; Should get cached since make-instance calls cache-instance
(make-instance class-name :from-oid oid))))
-;; OID stuff
-;; This stuff is all a hack until sequences appear in Sleepycat 4.3
-(defvar %oid-entry (uffi:allocate-foreign-object :char 12))
-(defvar %oid-lock (uffi:allocate-foreign-object :char 16))
-
-(eval-when (:load-toplevel)
- (loop for c across "%ELEPHANTOID"
- for i from 0 to 11
- do (setf (uffi:deref-array %oid-entry '(:array :char) i)
- (char-code c)))
- (loop for c across "%ELEPHANTOIDLOCK"
- for i from 0 to 15
- do (setf (uffi:deref-array %oid-lock '(:array :char) i)
- (char-code c)))
- )
-
-(defvar %oid-entry-length 12)
-(defvar %oid-lock-length 16)
-
(defun next-oid (sc)
"Get the next OID."
(declare (type store-controller sc))
- (sleepycat::next-counter (controller-environment sc)
- (controller-db sc)
- *current-transaction*
- %oid-entry %oid-entry-length
- %oid-lock %oid-lock-length))
+ (db-sequence-get-fixnum (controller-oid-seq sc) 1 :transaction +NULL-VOID+
+ :auto-commit t :txn-nosync t))
;; Open/close
(defmethod open-controller ((sc store-controller) &key (recover nil)
@@ -166,20 +146,23 @@
(db-open indices-assoc :file "%ELEPHANT" :database "%ELEPHANTINDICES"
:auto-commit t :type DB-UNKNOWN :thread thread :rdonly t)
(sleepycat::db-fake-associate btrees indices-assoc :auto-commit t)
+
+ (let ((db (db-create env)))
+ (setf (controller-oid-db sc) db)
+ (db-open db :file "%ELEPHANTOID" :database "%ELEPHANTOID"
+ :auto-commit t :type DB-BTREE :create t :thread thread)
+ (let ((oid-seq (db-sequence-create db)))
+ (db-sequence-set-cachesize oid-seq *cachesize*)
+ (db-sequence-set-flags oid-seq :seq-inc t :seq-wrap t)
+ (db-sequence-set-range oid-seq 0 most-positive-fixnum)
+ (db-sequence-initial-value oid-seq 0)
+ (db-sequence-open oid-seq "%ELEPHANTOID"
+ :auto-commit t :create t :thread t)
+ (setf (controller-oid-seq sc) oid-seq)))
(let ((root (make-instance 'btree :from-oid -1)))
- (setf (slot-value sc 'root) root)
- (with-transaction ()
- (with-buffer-streams (key-buf value-buf)
- (let ((key-b (buffer-stream-buffer key-buf)))
- (setf (buffer-stream-buffer key-buf) %oid-entry)
- (setf (sleepycat::buffer-stream-size key-buf) %oid-entry-length)
- (unless (db-get-key-buffered db key-buf value-buf)
- (reset-buffer-stream value-buf)
- (buffer-write-int 0 value-buf)
- (db-put-buffered db key-buf value-buf))
- (setf (buffer-stream-buffer key-buf) key-b))))
- sc))))
+ (setf (slot-value sc 'root) root))
+ sc)))
(defmethod close-controller ((sc store-controller))
(when (slot-value sc 'root)
@@ -188,6 +171,10 @@
;; clean instance cache
(setf (instance-cache sc) (make-cache-table :test 'eql))
;; close handles / environment
+ (db-sequence-close (controller-oid-seq sc))
+ (setf (controller-oid-seq sc) nil)
+ (db-close (controller-oid-db sc))
+ (setf (controller-oid-db sc) nil)
(db-close (controller-indices-assoc sc))
(setf (controller-indices-assoc sc) nil)
(db-close (controller-indices sc))
@@ -232,6 +219,7 @@
(progn ,@body)
(close-controller *store-controller*))))
+;;; Make these respect the transaction keywords (e.g. degree-2)
(defun start-transaction (&key (parent *current-transaction*))
"Start a transaction. May be nested but not interleaved."
(vector-push-extend *current-transaction* *transaction-stack*)
Index: elephant/src/berkeley-db.lisp
diff -u elephant/src/berkeley-db.lisp:1.2 elephant/src/berkeley-db.lisp:1.3
--- elephant/src/berkeley-db.lisp:1.2 Sun Sep 19 19:46:56 2004
+++ elephant/src/berkeley-db.lisp Thu Feb 24 02:06:10 2005
@@ -64,7 +64,9 @@
%db-txn-begin db-transaction-begin
%db-txn-abort db-transaction-abort
%db-txn-commit db-transaction-commit
- %db-transaction-id
+ %db-transaction-id
+ %db-sequence-get db-sequence-get
+ %db-sequence-get-lower db-sequence-get-fixnum
))
;; Environment
@@ -298,7 +300,7 @@
(defun db-get-key-buffered (db key-buffer-stream value-buffer-stream
&key (transaction *current-transaction*)
- auto-commit get-both dirty-read)
+ auto-commit get-both degree-2 dirty-read)
"Get a key / value pair from a DB. The key is encoded in
a buffer-stream. Space for the value is passed in as a
buffer-stream. On success the buffer-stream is returned for
@@ -306,7 +308,7 @@
(declare (optimize (speed 3) (safety 0))
(type pointer-void db transaction)
(type buffer-stream key-buffer-stream value-buffer-stream)
- (type boolean auto-commit get-both dirty-read))
+ (type boolean auto-commit get-both degree-2 dirty-read))
(loop
for value-length fixnum = (buffer-stream-length value-buffer-stream)
do
@@ -318,6 +320,7 @@
value-length
(flags :auto-commit auto-commit
:get-both get-both
+ :degree-2 degree-2
:dirty-read dirty-read))
(declare (type fixnum result-size errno))
(cond
@@ -347,7 +350,7 @@
(defun db-get-buffered (db key value-buffer-stream &key
(key-size (length key))
(transaction *current-transaction*)
- auto-commit get-both dirty-read)
+ auto-commit get-both degree-2 dirty-read)
"Get a key / value pair from a DB. The key is passed as a
string. Space for the value is passed in as a
buffer-stream. On success the buffer-stream is returned for
@@ -357,7 +360,7 @@
(type string key)
(type buffer-stream value-buffer-stream)
(type fixnum key-size)
- (type boolean auto-commit get-both dirty-read))
+ (type boolean auto-commit get-both degree-2 dirty-read))
(with-cstring (k key)
(loop
for value-length fixnum = (buffer-stream-length value-buffer-stream)
@@ -368,6 +371,7 @@
value-length
(flags :auto-commit auto-commit
:get-both get-both
+ :degree-2 degree-2
:dirty-read dirty-read))
(declare (type fixnum result-size errno))
(cond
@@ -385,7 +389,7 @@
(defun db-get (db key &key (key-size (length key))
(transaction *current-transaction*)
- auto-commit get-both dirty-read)
+ auto-commit get-both degree-2 dirty-read)
"Get a key / value pair from a DB. The key is passed as a
string, and the value is returned as a string. If nothing
is found, NIL is returned."
@@ -393,7 +397,7 @@
(type pointer-void db transaction)
(type string key)
(type fixnum key-size)
- (type boolean auto-commit get-both dirty-read))
+ (type boolean auto-commit get-both degree-2 dirty-read))
(with-cstring (k key)
(with-buffer-streams (value-buffer-stream)
(loop
@@ -405,6 +409,7 @@
value-length
(flags :auto-commit auto-commit
:get-both get-both
+ :degree-2 degree-2
:dirty-read dirty-read))
(declare (type fixnum result-size errno))
(cond
@@ -585,13 +590,14 @@
:returning :pointer-void)
(defun db-cursor (db &key (transaction *current-transaction*)
- dirty-read)
+ degree-2 dirty-read)
"Create a cursor."
(declare (optimize (speed 3) (safety 0))
(type pointer-void db)
- (type boolean dirty-read)
+ (type boolean degree-2 dirty-read)
(type pointer-int *errno-buffer*))
- (let* ((curs (%db-cursor db transaction (flags :dirty-read dirty-read)
+ (let* ((curs (%db-cursor db transaction (flags :degree-2 degree-2
+ :dirty-read dirty-read)
*errno-buffer*))
(errno (deref-array *errno-buffer* '(:array :int) 0)))
(declare (type pointer-void curs)
@@ -1015,17 +1021,18 @@
:returning :pointer-void)
(defun db-transaction-begin (env &key (parent *current-transaction*)
- dirty-read txn-nosync txn-nowait
+ degree-2 dirty-read txn-nosync txn-nowait
txn-sync)
"Start a transaction. Transactions may be nested."
(declare (optimize (speed 3) (safety 0))
(type pointer-void env parent)
- (type boolean dirty-read txn-nosync txn-nowait
+ (type boolean degree-2 dirty-read txn-nosync txn-nowait
txn-sync)
(type pointer-int *errno-buffer*))
(let* ((txn
(%db-txn-begin env parent
- (flags :dirty-read dirty-read
+ (flags :degree-2 degree-2
+ :dirty-read dirty-read
:txn-nosync txn-nosync
:txn-nowait txn-nowait
:txn-sync txn-sync)
@@ -1102,7 +1109,7 @@
(defmacro with-transaction ((&key transaction environment
(parent '*current-transaction*)
(retries 100)
- dirty-read txn-nosync
+ degree-2 dirty-read txn-nosync
txn-nowait txn-sync)
&body body)
"Execute a body with a transaction in place. On success,
@@ -1120,6 +1127,7 @@
(let ((,txn
(db-transaction-begin ,environment
:parent ,parent
+ :degree-2 ,degree-2
:dirty-read ,dirty-read
:txn-nosync ,txn-nosync
:txn-nowait ,txn-nowait
@@ -1332,7 +1340,195 @@
"Sets the duplicate comparision function to a hand-cooked
function for Elephant to compare lisp values.")
-;; Poor man's counters
+;; Sequences
+
+(def-function ("db_sequence_create2" %db-sequence-create)
+ ((db :pointer-void)
+ (flags :unsigned-int)
+ (errno (* :int)))
+ :returning :pointer-void)
+
+(defun db-sequence-create (db)
+ "Create a new sequence."
+ (declare (optimize (speed 3) (safety 0))
+ (type pointer-void db)
+ (type pointer-int *errno-buffer*))
+ (let* ((seq
+ (%db-sequence-create db 0 *errno-buffer*))
+ (errno (deref-array *errno-buffer* '(:array :int) 0)))
+ (declare (type pointer-void seq)
+ (type fixnum errno))
+ (if (= errno 0)
+ seq
+ (error 'db-error :errno errno))))
+
+(def-function ("db_sequence_open" %db-sequence-open)
+ ((seq :pointer-void)
+ (txn :pointer-void)
+ (key :cstring)
+ (key-size :unsigned-int)
+ (flags :unsigned-int))
+ :returning :int)
+
+(wrap-errno db-sequence-open (sequence transaction key key-size flags)
+ :flags (auto-commit create excl thread)
+ :cstrings (key)
+ :keys ((key-size (length key))
+ (transaction *current-transaction*))
+ :transaction transaction
+ :documentation "Open a sequence.")
+
+(def-function ("db_sequence_close" %db-sequence-close)
+ ((seq :pointer-void)
+ (flags :unsigned-int))
+ :returning :int)
+
+(wrap-errno (db-sequence-close %db-sequence-close) (sequence flags)
+ :documentation "Close a sequence.")
+
+(def-function ("db_sequence_get" %db-sequence-get)
+ ((seq :pointer-void)
+ (txn :pointer-void)
+ (delta :int)
+ (low :unsigned-int :out)
+ (high :int :out)
+ (flags :unsigned-int))
+ :returning :int)
+
+(defun db-sequence-get (sequence delta &key auto-commit txn-nosync
+ (transaction *current-transaction*))
+ "Get the next element."
+ (declare (optimize (speed 3) (safety 0))
+ (type pointer-void sequence transaction)
+ (type fixnum delta)
+ (type boolean auto-commit txn-nosync))
+ (multiple-value-bind
+ (errno low high)
+ (%db-sequence-get sequence transaction delta
+ (flags :auto-commit auto-commit
+ :txn-nosync txn-nosync))
+ (declare (type fixnum errno)
+ (type (unsigned-byte 32) low)
+ (type (signed-byte 32) high))
+ (cond ((= errno 0) (make-64-bit-integer high low))
+ ((or (= errno db_lock_deadlock)
+ (= errno db_lock_notgranted))
+ (throw 'transaction transaction))
+ (t (error 'db-error :errno errno)))))
+
+(def-function ("db_sequence_get_lower" %db-sequence-get-lower)
+ ((seq :pointer-void)
+ (txn :pointer-void)
+ (delta :int)
+ (low :int :out)
+ (flags :unsigned-int))
+ :returning :int)
+
+(defun db-sequence-get-fixnum (sequence delta &key auto-commit txn-nosync
+ (transaction *current-transaction*))
+ "Get the next element as a fixnum."
+ (declare (optimize (speed 3) (safety 0))
+ (type pointer-void sequence transaction)
+ (type fixnum delta)
+ (type boolean auto-commit txn-nosync))
+ (multiple-value-bind
+ (errno low)
+ (%db-sequence-get-lower sequence transaction delta
+ (flags :auto-commit auto-commit
+ :txn-nosync txn-nosync))
+ (declare (type fixnum errno low))
+ (cond ((= errno 0) low)
+ ((or (= errno db_lock_deadlock)
+ (= errno db_lock_notgranted))
+ (throw 'transaction transaction))
+ (t (error 'db-error :errno errno)))))
+
+(def-function ("db_sequence_initial_value" %db-sequence-initial-value)
+ ((seq :pointer-void)
+ (low :unsigned-int)
+ (high :int))
+ :returning :int)
+
+(defun db-sequence-initial-value (sequence value)
+ "Set the initial value."
+ (let ((errno
+ (%db-sequence-initial-value sequence (low32 value) (high32 value))))
+ (declare (type fixnum errno))
+ (cond ((= errno 0) nil)
+ (t (error 'db-error :errno errno)))))
+
+(def-function ("db_sequence_remove" %db-sequence-remove)
+ ((seq :pointer-void)
+ (txn :pointer-void)
+ (flags :unsigned-int))
+ :returning :int)
+
+(wrap-errno db-sequence-remove (sequence transaction flags)
+ :keys ((transaction *current-transaction*))
+ :transaction transaction
+ :flags (auto-commit txn-nosync)
+ :documentation "Remove a sequence.")
+
+(def-function ("db_sequence_set_cachesize" %db-sequence-set-cachesize)
+ ((seq :pointer-void)
+ (size :int))
+ :returning :int)
+
+(wrap-errno db-sequence-set-cachesize (sequence size)
+ :documentation "Set cache size for a sequence.")
+
+(def-function ("db_sequence_get_cachesize" %db-sequence-get-cachesize)
+ ((seq :pointer-void)
+ (size :int :out))
+ :returning :int)
+
+(wrap-errno db-sequence-get-cachesize (sequence)
+ :outs 2
+ :documentation "Get cache size for a sequence.")
+
+(def-function ("db_sequence_set_flags" %db-sequence-set-flags)
+ ((seq :pointer-void)
+ (flags :unsigned-int))
+ :returning :int)
+
+(wrap-errno db-sequence-set-flags (sequence flags)
+ :flags (seq-dec seq-inc seq-wrap)
+ :documentation "Set cache size for a sequence.")
+
+(def-function ("db_sequence_set_range" %db-sequence-set-range)
+ ((seq :pointer-void)
+ (minlow :unsigned-int)
+ (minhigh :int)
+ (maxlow :unsigned-int)
+ (maxhigh :int))
+ :returning :int)
+
+(defun db-sequence-set-range (sequence min max)
+ "Set the range of a sequence"
+ (let ((errno
+ (%db-sequence-set-range sequence (low32 min) (high32 min)
+ (low32 max) (high32 max))))
+ (declare (type fixnum errno))
+ (cond ((= errno 0) nil)
+ (t (error 'db-error :errno errno)))))
+
+(def-function ("db_sequence_get_range" %db-sequence-get-range)
+ ((seq :pointer-void)
+ (minlow :unsigned-int :out)
+ (minhigh :int :out)
+ (maxlow :unsigned-int :out)
+ (maxhigh :int :out))
+ :returning :int)
+
+(defun db-sequence-get-range (sequence)
+ "Get the range of a sequence"
+ (multiple-value-bind (errno minlow minhigh maxlow maxhigh)
+ (%db-sequence-get-range sequence)
+ (declare (type fixnum errno)
+ (type integer minlow minhigh maxlow maxhigh))
+ (cond ((= errno 0) (values (make-64-bit-integer minhigh minlow)
+ (make-64-bit-integer maxhigh maxlow)))
+ (t (error 'db-error :errno errno)))))
(def-function ("next_counter" %next-counter)
((env :pointer-void)