Hi,
when using class indices they do not have a slot name. On destruction/index-remove this throws a condition on checking slot-boundp.
I am using SBCL 1.0.14.23 and the latest bknr indices code, only indices, nothing else.
Best regards Klaus
;Package changed to BKNR.INDICES #<PACKAGE "BKNR.INDICES">
BKNR.INDICES> (defvar *class-index* (index-create 'class-index :index-subclasses t))
*CLASS-INDEX*
BKNR.INDICES> (defclass base-object () () (:metaclass indexed-class) (:class-indices (class :index *class-index* :slots nil :index-reader objects-of-class :index-values all-objects :index-subclasses t :index-keys all-class-names) (classes :index-type class-index :index-initargs (:index-superclasses t) :slots nil :index-subclasses t :index-reader objects-with-class)))
#<INDEXED-CLASS BASE-OBJECT> ; in: LAMBDA NIL ; (SB-KERNEL:FLOAT-WAIT) ; ; note: deleting unreachable code ; ; compilation unit finished ; printed 1 note
BKNR.INDICES> (defclass child1 (base-object) () (:metaclass indexed-class))
#<INDEXED-CLASS CHILD1>
BKNR.INDICES> (defclass child2 (base-object) ((a :initarg :a)) (:metaclass indexed-class))
#<INDEXED-CLASS CHILD2>
BKNR.INDICES> (make-instance 'child1)
#<CHILD1 {AC66381}>
BKNR.INDICES> (all-objects)
(#<CHILD1 {AC66381}>)
BKNR.INDICES> (destroy-object (first (all-objects)))
When attempting to test to see whether slot is bound (SLOT-BOUNDP), the slot NIL is missing from the object #<CHILD1 {A7422D9}>. [Condition of type SIMPLE-ERROR] 0: [ABORT] Return to SLIME's top level. 1: [TERMINATE-THREAD] Terminate this thread (#<THREAD "repl-thread" {B54A251}>) ]> Quit debug
Hi Klaus,
the class-index needs to know a slot that it uses for indexing the objects. This slot is the unique ID that the index works on. It must be added to your base class, but as you can see in the corrected example below, that should not be much of a problem.
Note that the :INDICES option in an INDEXED-CLASS either accepts a predefined index or initargs to create a fresh index. It is confusing to mix both initargs and the :INDEX option (which specifies the preexisting index *CLASS-INDEX* to be used). I added code to detect this case. More error checking would certainly be helpful, so please report problems when you encounter them and I'll try to make the code generate better diagnostics.
Please let us know if you have further questions.
Hans
(in-package :bknr.indices)
(defvar *class-index* (index-create 'class-index :index-subclasses t :slot-name 'id)) (defvar *object-id* 0)
(defclass base-object () ((id :initform (incf *object-id*))) (:metaclass indexed-class) (:class-indices (class :index *class-index* :index-reader objects-of-class :index-values all-objects :index-subclasses t :index-keys all-class-names) (classes :index-type class-index :index-initargs (:index-superclasses t) :slots (id) :index-subclasses t :index-reader objects-with-class)))
(defclass child1 (base-object) () (:metaclass indexed-class))
(defclass child2 (base-object) ((a :initarg :a)) (:metaclass indexed-class))
(defmacro with-tracing (&rest forms) `(progn ,@(mapcar (lambda (form) `(format *trace-output* "~A => ~A~%" (quote ,form) ,form)) forms)))
(with-tracing (make-instance 'child1) (all-objects) (destroy-object (first (all-objects)))
(make-instance 'child1) (make-instance 'child2) (make-instance 'child1) (all-class-names) (all-objects) (objects-with-class 'child1) (objects-with-class 'child2))
2008/2/21, Klaus Unger UngerKlaus@gmx.de:
Hi,
when using class indices they do not have a slot name. On destruction/index-remove this throws a condition on checking slot-boundp.
I am using SBCL 1.0.14.23 and the latest bknr indices code, only indices, nothing else.
Best regards Klaus
;Package changed to BKNR.INDICES #<PACKAGE "BKNR.INDICES">
BKNR.INDICES> (defvar *class-index* (index-create 'class-index :index-subclasses t))
*CLASS-INDEX*
BKNR.INDICES> (defclass base-object () () (:metaclass indexed-class) (:class-indices (class :index *class-index* :slots nil :index-reader objects-of-class :index-values all-objects :index-subclasses t :index-keys all-class-names) (classes :index-type class-index :index-initargs (:index-superclasses t) :slots nil :index-subclasses t :index-reader objects-with-class)))
#<INDEXED-CLASS BASE-OBJECT> ; in: LAMBDA NIL ; (SB-KERNEL:FLOAT-WAIT) ; ; note: deleting unreachable code ; ; compilation unit finished ; printed 1 note
BKNR.INDICES> (defclass child1 (base-object) () (:metaclass indexed-class))
#<INDEXED-CLASS CHILD1>
BKNR.INDICES> (defclass child2 (base-object) ((a :initarg :a)) (:metaclass indexed-class))
#<INDEXED-CLASS CHILD2>
BKNR.INDICES> (make-instance 'child1)
#<CHILD1 {AC66381}>
BKNR.INDICES> (all-objects)
(#<CHILD1 {AC66381}>)
BKNR.INDICES> (destroy-object (first (all-objects)))
When attempting to test to see whether slot is bound (SLOT-BOUNDP), the slot NIL is missing from the object #<CHILD1 {A7422D9}>. [Condition of type SIMPLE-ERROR] 0: [ABORT] Return to SLIME's top level. 1: [TERMINATE-THREAD] Terminate this thread (#<THREAD "repl-thread" {B54A251}>) ]> Quit debug _______________________________________________ bknr-devel mailing list bknr-devel@common-lisp.net http://common-lisp.net/cgi-bin/mailman/listinfo/bknr-devel
Hi Hans,
thanks for the promt response! The code I used was from the datastore-manual page 23. When adding the id slot name I run into the following problem: I use cl-prevalence for serialization. When restoring id-objects I do this without-auto-id, so the objects are created having the id slot unbound and assigned later on. This leads to duplicate entries in the class-index and thus inconsitency. I was not sure what happens if there are multiple objects having a unique-index slot set to Nil.
Instead of optionaly binding the id parameter in the constructor I now use an initform that at least binds the auto-id or Nil. Is this a good idea?:
Best regards Klaus
(defvar *id-counter* 0) (defvar *auto-id* T)
(defmacro without-auto-id (&body body) `(let ((*auto-id* Nil)) ,@body))
(defun next-id () (when *auto-id* (incf *id-counter*)))
(defclass id-object () ((id :reader get-id :initform (next-id) :index-type unique-index :index-initargs (:test #'eql) :index-values find-all-id-objects :index-reader find-object-with-id)) (:metaclass indexed-class) (:class-indices (classes :index-type class-index :index-initargs (:index-superclasses t) :slots (id) :index-reader find-all-id-objects-with-class)))
Am Donnerstag, 21. Februar 2008 07:26:02 schrieb Hans Hübner:
Hi Klaus,
the class-index needs to know a slot that it uses for indexing the objects. This slot is the unique ID that the index works on. It must be added to your base class, but as you can see in the corrected example below, that should not be much of a problem.
Note that the :INDICES option in an INDEXED-CLASS either accepts a predefined index or initargs to create a fresh index. It is confusing to mix both initargs and the :INDEX option (which specifies the preexisting index *CLASS-INDEX* to be used). I added code to detect this case. More error checking would certainly be helpful, so please report problems when you encounter them and I'll try to make the code generate better diagnostics.
Please let us know if you have further questions.
Hans
Hi Klaus,
thank you for the manual bug report. It will be fixed in the upcoming release of BKNR that is planned for summer.
Your approach to handling the problem looks fine, at least from superficially looking at it. I have not looked at cl-prevalence for quite some time, so I can't say if it will work.
Out of curiosity: Why are you using cl-prevalence instead of BKNR datastore? I am happy to see someone being actually able to use the indices without the store, but I'm also interested in knowing what our store is lacking to make you chose another, similar solution.
Thanks, Hans
P.S.: In fact, we started with cl-prevalence but found it to be too limited in several aspects. That was why we started writing BKNR datastore.
2008/2/21, Klaus Unger UngerKlaus@gmx.de:
Hi Hans,
thanks for the promt response! The code I used was from the datastore-manual page 23. When adding the id slot name I run into the following problem: I use cl-prevalence for serialization. When restoring id-objects I do this without-auto-id, so the objects are created having the id slot unbound and assigned later on. This leads to duplicate entries in the class-index and thus inconsitency. I was not sure what happens if there are multiple objects having a unique-index slot set to Nil.
Instead of optionaly binding the id parameter in the constructor I now use an initform that at least binds the auto-id or Nil. Is this a good idea?:
Best regards Klaus
(defvar *id-counter* 0) (defvar *auto-id* T)
(defmacro without-auto-id (&body body) `(let ((*auto-id* Nil)) ,@body))
(defun next-id () (when *auto-id* (incf *id-counter*)))
(defclass id-object () ((id :reader get-id :initform (next-id) :index-type unique-index :index-initargs (:test #'eql) :index-values find-all-id-objects :index-reader find-object-with-id))
(:metaclass indexed-class) (:class-indices
(classes :index-type class-index :index-initargs (:index-superclasses t) :slots (id) :index-reader find-all-id-objects-with-class)))
Am Donnerstag, 21. Februar 2008 07:26:02 schrieb Hans Hübner:
Hi Klaus,
the class-index needs to know a slot that it uses for indexing the objects. This slot is the unique ID that the index works on. It must be added to your base class, but as you can see in the corrected example below, that should not be much of a problem.
Note that the :INDICES option in an INDEXED-CLASS either accepts a predefined index or initargs to create a fresh index. It is confusing to mix both initargs and the :INDEX option (which specifies the preexisting index *CLASS-INDEX* to be used). I added code to detect this case. More error checking would certainly be helpful, so please report problems when you encounter them and I'll try to make the code generate better diagnostics.
Please let us know if you have further questions.
Hans
Hi Hans,
I am using only serialization and indices, not transactions. I didn't manage to easily use the serialization of bknr-datastore in a lightweight manner, so I used the serialization of cl-prevalence.
When I started the project I had the feeling that transactions did not really give me benefits (please tell me If I got anything wrong): - It is hard to map complex generic functions to transactions - A rollback costs to much performance to be used for anything except very rare exceptions - There are no thread isolation mechanisms except a global lock. (I can hardly imagine anything else for the used model.)
Now I implemented some features (store-object) of the datastore myself. So I would like to give the datastore itsself another chance and see if its possible to use it without much overhead due to transactions. It is great to hear that there will be a new major release soon.
- Klaus
Out of curiosity: Why are you using cl-prevalence instead of BKNR datastore? I am happy to see someone being actually able to use the indices without the store, but I'm also interested in knowing what our store is lacking to make you chose another, similar solution.
Thanks, Hans
P.S.: In fact, we started with cl-prevalence but found it to be too limited in several aspects. That was why we started writing BKNR datastore.