[rucksack-devel] indexing issue?

Cyrus Harmon ch-rucksack at bobobeach.com
Fri Dec 1 00:14:09 UTC 2006


Following up on my previous email, the following works as expected:

(defun test-persistent-class-cycle ()
   (rucksack:with-rucksack (rucksack *test-rucksack*)
     (rucksack:with-transaction ()
       (let ((p (make-instance 'a-persistent-class :name "ape")))
         (setf (info p) p)))))

(defun test-persistent-class-cycle-lookup ()
   (rucksack:with-rucksack (rucksack *test-rucksack*)
     (rucksack:with-transaction ()
       (rucksack:rucksack-map-slot
        rucksack 'a-persistent-class 'name
        (lambda (x)
          (print (list (info (info x)) (name x) x)))
        :equal "ape"))))


but when the cycle is in a non-persistent class reachable from the  
persistent class, bad things happen (i.e. it hangs).

Cyrus

On Nov 30, 2006, at 3:49 PM, Cyrus Harmon wrote:

>
> On Nov 30, 2006, at 12:26 PM, Arthur Lemmens wrote:
>
>> Cyrus Harmon wrote:
>>> Oh?0 is using the index the only way to find it?
>> ...
>> This is not a relational database, it's persistent Lisp objects ;-)
>
> Indeed. Still trying to get my head around that concept fully.
>
> So does this mean that when I have an object of an indexed class I  
> don't need to explicitly call add-rucksack-root?
>
>> The easiest way is probably to use SLOT-MAKUNBOUND.  This should
>> sooner or later call RUCKSACK-MAYBE-INDEX-CHANGED-SLOT, which
>> will call INDEX-DELETE to remove the association between the
>> old slot value and the object instance from the index.
>
> Hmm... I'm confused, but I'll keep digging.
>
>>> Finally, one further question... what does rucksack do about cycles?
>>
>> Nothing special, really.  I'm not sure that I understand your  
>> question.
>
> Well, for starters there are cyclic lists and it looks like  
> rucksacks answer to that is:
>
> Serializing circular lists isn't implemented yet.
>    [Condition of type SIMPLE-ERROR]
>
> Restarts:
>   0: [ABORT] Abort #<RUCKSACK:STANDARD-TRANSACTION #337391780600000  
> with 8 dirty objects>
>   1: [RETRY] Retry #<RUCKSACK:STANDARD-TRANSACTION #337391780600000  
> with 8 dirty objects>
>   2: [ABORT-REQUEST] Abort handling SLIME request.
>   3: [TERMINATE-THREAD] Terminate this thread (#<THREAD "new-repl- 
> thread" {36147FF9}>)
>
> Backtrace:
>   0: ((SB-PCL::FAST-METHOD RUCKSACK::SERIALIZE (CONS T))  
> #<unavailable argument> #<unavailable argument> #1=(1 . #1#)  
> #<RUCKSACK::SERIALIZATION-BUFFER {17625251}>)
>   1: ((SB-PCL::FAST-METHOD RUCKSACK::SAVE-OBJECT (T #1="#<...>" .  
> #1#)) #<unused argument> #<unused argument> #<CYCLE-TEST #58 in  
> #<STANDARD-CACHE of size 10000, heap #P"/Users/sly/projects/ 
> cyrusharmon.org/research/discs/rucksack/heap" and 45 objects in  
> memory.>> 58 #<RUCKSACK:STANDARD-CACHE of size 10000, heap #P"/ 
> Users/sly/projects/cyrusharmon.org/research/discs/rucksack/heap"  
> and 45 objects in memory.> 337391780600000 NIL :SCHEMA NIL)
>   2: ((SB-PCL::FAST-METHOD RUCKSACK::SAVE-DIRTY-OBJECT (T  
> #1="#<...>" . #1#)) #<unused argument> #<unused argument> #<CYCLE- 
> TEST #58 in #<STANDARD-CACHE of size 10000, heap #P"/Users/sly/ 
> projects/cyrusharmon.org/research/discs/rucksack/heap" and 45  
> objects in memory.>> #<RUCKSACK:STANDARD-CACHE of size 10000, heap  
> #P"/Users/sly/projects/cyrusharmon.org/research/discs/rucksack/ 
> heap" and 45 objects in memory.> #<RUCKSACK:STANDARD-TRANSACTION  
> #337391780600000 with 8 dirty objects> 58 :SCHEMA NIL)
>   3: ((SB-PCL::FAST-METHOD RUCKSACK:TRANSACTION-COMMIT-1  
> (RUCKSACK:STANDARD-TRANSACTION RUCKSACK:STANDARD-CACHE  
> RUCKSACK:STANDARD-RUCKSACK)) #<unavailable argument> #<unavailable  
> argument> #<RUCKSACK:STANDARD-TRANSACTION #337391780600000 with 8  
> dirty objects> #<RUCKSACK:STANDARD-CACHE of size 10000, heap #P"/ 
> Users/sly/projects/cyrusharmon.org/research/discs/rucksack/heap"  
> and 45 objects in memory.> #<RUCKSACK::SERIAL-TRANSACTION-RUCKSACK  
> in #P"/Users/sly/projects/cyrusharmon.org/research/discs/rucksack/"  
> with 3 roots {175E4AF9}>)
>   4: ((LAMBDA (SB-PCL::.PV-CELL. SB-PCL::.NEXT-METHOD-CALL. SB- 
> PCL::.ARG0. SB-PCL::.ARG1. SB-PCL::.ARG2.)) #<unavailable argument>  
> #<unavailable argument> #<RUCKSACK:STANDARD-TRANSACTION  
> #337391780600000 with 8 dirty objects> #<RUCKSACK:STANDARD-CACHE of  
> size 10000, heap #P"/Users/sly/projects/cyrusharmon.org/research/ 
> discs/rucksack/heap" and 45 objects in memory.> #<RUCKSACK::SERIAL- 
> TRANSACTION-RUCKSACK in #P"/Users/sly/projects/cyrusharmon.org/ 
> research/discs/rucksack/" with 3 roots {175E4AF9}>)
>   5: (TEST-CYCLE)
>   6: (SB-INT:SIMPLE-EVAL-IN-LEXENV (TEST-CYCLE) #<NULL-LEXENV>)
>   7: (SWANK::EVAL-REGION "(test-cycle)
>
> which is better than spinning for ever.
>
>>> Is there a way to break cycles
>>
>> What kind of cycles would you want to break, and why?
>
> Well, breaking them isn't the right answer, but somehow  
> representing them in persistent storage would be nice.
>
>>> When I try to add an object that points to itself rucksack seems
>>> to spin forever.
>>
>> If it does, that's a bug.  Can you show me the code that does this?
>
> Working on a test case. What I have is an object that contains a  
> (non-persistent) object that points to itself. Which leads me to  
> what is probably another fundamental misunderstanding on my part.  
> What does rucksack do with objects of non-persistent classes?  
> Here's my test:
>
>
> (defclass a-non-persistent-class ()
>   ((bogosity :accessor bogosity :initarg :bogosity)))
>
> (eval-when (:compile-toplevel :load-toplevel)
>   (rucksack:with-rucksack (rucksack *test-rucksack* #+nil :if- 
> exists #+nil :supersede)
>     (rucksack:with-transaction ()
>
>       (defclass a-persistent-class ()
>         ((name :accessor name :initarg :name :index :string-index)
>          (info :accessor info :initarg :info))
>         (:metaclass persistent-class)
>         (:index t)))))
>
>
> (defun test-not-persistent-data-1 ()
>   (let ((np (make-instance 'a-non-persistent-class :bogosity 412)))
>     (rucksack:with-rucksack (rucksack *test-rucksack*)
>       (rucksack:with-transaction ()
>         (let ((p (make-instance 'a-persistent-class :name  
> "moose" :info np)))
>           (print (name p)))))))
>
> (defun test-not-persistent-data-lookup-1 ()
>   (rucksack:with-rucksack (rucksack *test-rucksack*)
>     (rucksack:with-transaction ()
>       (rucksack:rucksack-map-slot
>        rucksack 'a-persistent-class 'name
>        (lambda (x)
>          (print (list (bogosity (info x)) (name x) x)))))))
>
> (defun test-not-persistent-data-2 ()
>   (let ((np (make-instance 'a-non-persistent-class :bogosity 412)))
>     (setf (bogosity np) np)
>     (rucksack:with-rucksack (rucksack *test-rucksack*)
>       (rucksack:with-transaction ()
>         (let ((p (make-instance 'a-persistent-class :name  
> "moose" :info np)))
>           (print (name p)))))))
>
>
>
> test-persistent-data-1 seems to work fine and the slot in a-non- 
> persistent-class is even preserved, it seems. yay!
>
> but, when you go to run test-not-persistent-data-2 you get stuck on  
> a loop. yes, perhaps this is a contrived situation, but it's the  
> situation I find myself when trying to shoe-horn my existing  
> classes into rucksack.
>
> So, in summary, there are two separate issues it seems, cyclic  
> lists, which are not supported but which throw an error and  
> persistent objects that contain objects that point to themselves  
> which just hang.
>
> Thanks again for the insightful discussion and for rucksack in  
> general! It's starting to get clearer.
>
> Cyrus
>
> _______________________________________________
> rucksack-devel mailing list
> rucksack-devel at common-lisp.net
> http://common-lisp.net/cgi-bin/mailman/listinfo/rucksack-devel




More information about the rucksack-devel mailing list