Hi Klaus,
I have just committed http://bknr.net/trac/changeset/2600 which adds multiple store support through the WITH-TRANSACTION macro. You need to use the :MAKE-DEFAULT NIL as initarg when making a store instance to prevent setting the *STORE* special variable. WITH-STORE must then be used to select a store to work with:
DATASTORE> (defvar *state* 0) *STATE* DATASTORE> (defvar store1 (make-instance 'store :directory "/tmp/store1/" :make-default nil)) STORE1 DATASTORE> (defvar store2 (make-instance 'store :directory "/tmp/store2/" :make-default nil)) STORE2 DATASTORE> (deftransaction foo (value) (setf *state* value)) FOO DATASTORE> (with-store (store1) (foo 1)) 1 DATASTORE> (with-store (store2) (foo 2)) 2 DATASTORE> (with-store (store1) (restore) *state*) reading store random state restoring #<STORE DIR: "/tmp/store1/"> loading transaction log /tmp/store1/current/transaction-log 1 DATASTORE> (with-store (store2) (restore) *state*) reading store random state restoring #<STORE DIR: "/tmp/store2/"> loading transaction log /tmp/store2/current/transaction-log 2 DATASTORE>
Let me know if that suits and works for you.
-Hans
Hi Hans,
thanks for the commits. If i got it right with-store does not apply to the STORE-OBJECT-SUBSYSTEM which is based on indices. Therfore it is not possible to use with-store for parallel stores based on all-store-objects and friends, right? In regards to the transaction log it does work for me, and it is a handy thing, but not what I was originally looking for. What I meant would be like:
DATASTORE> (with-store (store1) (make-object 'store-object))
=> #<STORE-OBJECT ID: 0>
DATASTORE> (with-store (store2) (make-object 'foo-store-object))
=> #<FOO-STORE-OBJECT ID: 0>
DATASTORE> (with-store (store1) (all-store-objects))
(#<STORE-OBJECT ID: 0>)
DATASTORE> (with-store (store2) (all-store-objects))
(#<FOO-STORE-OBJECT ID: 0>)
This is not really meant as serial, but more like a multi threaded parallel execution. Obviously it would be possible to do this prepending a (restore), but this would bei a performance nightmare and require additional synchronization.
From how I understand the code this would require to make indexed-class-indices and index-effective-slot-definition-indices dependant on the current *store* for persistent-class and persistent-effective-slot-definition.
- Klaus
P.S.: I begin to feel guilty for always nagging, so I have to emphasize again that I am really thankful for the commununication and your patience. Also bknr is already really helpful for me in its current form! If we can be improve it - even better.
Am Samstag, 23. Februar 2008 17:49:16 schrieb Hans Hübner:
Hi Klaus,
I have just committed http://bknr.net/trac/changeset/2600 which adds multiple store support through the WITH-TRANSACTION macro. You need to use the :MAKE-DEFAULT NIL as initarg when making a store instance to prevent setting the *STORE* special variable. WITH-STORE must then be used to select a store to work with:
DATASTORE> (defvar *state* 0) *STATE* DATASTORE> (defvar store1 (make-instance 'store :directory "/tmp/store1/"
:make-default nil))
STORE1 DATASTORE> (defvar store2 (make-instance 'store :directory "/tmp/store2/"
:make-default nil))
STORE2 DATASTORE> (deftransaction foo (value) (setf *state* value)) FOO DATASTORE> (with-store (store1) (foo 1)) 1 DATASTORE> (with-store (store2) (foo 2)) 2 DATASTORE> (with-store (store1) (restore) *state*) reading store random state restoring #<STORE DIR: "/tmp/store1/"> loading transaction log /tmp/store1/current/transaction-log 1 DATASTORE> (with-store (store2) (restore) *state*) reading store random state restoring #<STORE DIR: "/tmp/store2/"> loading transaction log /tmp/store2/current/transaction-log 2 DATASTORE>
Let me know if that suits and works for you.
-Hans
Hi Klaus,
don't worry. For the upcoming release, it is good when I spend some time in the store code to get a grasp of where changes are needed.
You are certainly right: My multi-store patch does not properly rebind special variables used by subsystems, and this is something I will add. I want to make sure that there is no "performance overhead" for the single-store case, which makes it slightly more complicated. I'll let you know once I have committed. While fixing the subsystem issues, I will need to repair random state handling which is also broken in the multiple store case.
If you did not see it: Trac generates RSS feeds for the Subversion log, which is why I have stopped distributing commit notifications by email. http://bknr.net/trac/timeline?milestone=on&ticket=on&changeset=on&am... the full feed.
-Hans
Hi Klaus,
I have given this some more thought: Supporting multiple stores in the indexing subsystem is possible, but it is rather complicated because an additional dispatch in the INDEXED-CLASS metaclass is required to make the indices dependent on *STORE*. Currently, the indices are stored in the INDEXED-CLASS instance which would be shared by multiple worlds running in the same Lisp image.
The issue here is: The change is relatively complex, requires testing and I don't need it to support our development style. In our architecture, the persistent objects make up one world, and if I need multiple worlds, I start multiple Lisps. I would not benefit from running mulltiple independent applications within one Lisp image, and the lack of isolation would really be more bothersome than anything else.
That said, if you can make a good case for the functionality, I would try to implement in the not-so-far future. Please provide me with a good application architecture example that would be significantly harder to implement in multiple Lisp images.
-Hans