[rucksack-devel] Unexpected results from Rucksack (timing dependence?)

Klaus Harbo klaus at harbo.net
Thu Apr 16 06:34:03 UTC 2009


Hi Everyone -

I was looking at Rucksack yesterday to see if it might be useful for a  
small project I'm considering.  I have very little experience with  
Rucksack and use the material in the tutorial as a starting point for  
my explorations.  However, I'm inconsistent and - to me - surprising  
results, so thought I'd check with a more experienced crowd (i.e. you  
guys, the members of rucksack-devel!)...

What I'm seeing, basically, is that the effect of calling the  
tutorial's MAKE-CONTACT does not seem to show up consistently when  
retrieving instances using RUCKSACK-MAP-CLASS.  I have compiled an  
example to which illustrates (not very pretty, but except for the  
removal of docstrings to keep things short, it's cut-and-paste'd  
straight out of the tutorial):

   (defun try-it (iters &optional (sleep-list '(0)))
     (loop for sleep-period in sleep-list
           for res = (let ((the-dir "/tmp/rs-test/"))
                       (flet ((make-contact (name &optional phone- 
number email address notes)
                                (with-rucksack (rs the-dir)
                                  (with-transaction ()
                                    (make-instance 'contact-details
                                                   :name (or name "")
                                                   :phone-number (or  
phone-number 0)
                                                   :email (or email "")
                                                   :address (or  
address "")
                                                   :notes notes)))))
                         (macrolet ((def-the-class ()
                                      `(with-rucksack (rs the-dir)
                                         (with-transaction ()
                                           (defclass contact-details ()
                                             ((unique- 
id    :initarg :unique-id :accessor unique-id-of
                                                            :index 
  :number-index
                                                            :unique t)
                                               
(name         :initarg :name :accessor name-of
                                                            :index 
  :case-insensitive-string-index)
                                              (phone- 
number :initarg :phone-number :accessor phone-number-of
                                                            :index 
  :number-index)
                                               
(email        :initarg :email :accessor email-of
                                                            :index 
  :case-insensitive-string-index)
                                               
(address      :initarg :address :accessor address-of
                                                            :index 
  :case-insensitive-string-index)
                                               
(notes        :initarg :notes :accessor notes-of))
                                             (:index t)
                                             (:metaclass persistent- 
class))))))
                           (let (ret)
                             (loop repeat iters
                                   do (mapc #'delete-file (directory  
the-dir))
                                   do (def-the-class)
                                   do (tagbody
                                       (loop for count from 1 to 50
                                             do (progn (make-contact  
"name") (sleep sleep-period))
                                             do (with-rucksack (rs the- 
dir)
                                                  (with-transaction ()
                                                    (let ((c 0))
                                                      (rucksack-map- 
class rs 'contact-details (lambda (o) (incf c)))
                                                      (unless (= c  
count)
                                                        (push (list :c  
c :count count) ret)
                                                        (go done))))))
                                       done))
                             (list :sleep sleep-period :ret ret)))))
           do (print res)))

Essentially, the code (is supposed to)

  (1) clear the rucksack directory by deleting everything
  (2) define the CONTACT-DETAILS class in the context of a (thus)  
newly created rucksack
  (3) repeatedly (i) creates a CONTACT-DETAIL and (ii) checks to see  
if the number of created instances is correct

When evaluating (ignoring SLEEP for a moment)

  RUCKSACK 52 > (try-it 5)

  (:SLEEP 0 :RET ((:C 25 :COUNT 26) (:C 28 :COUNT 29) (:C 30 :COUNT  
31) (:C 28 :COUNT 29) (:C 27 :COUNT 28)))
  NIL

  RUCKSACK 53 >

it appears that in the 5 iterations after 26, 29, 31, 29, and 28  
insertions (respectively), one was 'missing' at the least when viewed  
using RUCKSACK-MAP-CLASS.  I would have expected the output

  (:SLEEP 0 :RET NIL)

since I would expect to be able retrieve all the instances that have  
been created.

Due to the apparent variation in the number of insertions and - as far  
as I can see - the lack of variation in the input, I thought that  
perhaps there's some kind of timing issue, so I added calls to SLEEP

  RUCKSACK 54 > (try-it 5 '(0 .01 .1 .25))

  (:SLEEP 0 :RET ((:C 28 :COUNT 29) (:C 29 :COUNT 30) (:C 29 :COUNT  
30) (:C 28 :COUNT 29) (:C 12 :COUNT 13)))
  (:SLEEP 0.01 :RET ((:C 23 :COUNT 24) (:C 23 :COUNT 24) (:C 23 :COUNT  
24) (:C 23 :COUNT 24) (:C 23 :COUNT 24)))
  (:SLEEP 0.1 :RET ((:C 6 :COUNT 7) (:C 6 :COUNT 7) (:C 7 :COUNT 8)  
(:C 6 :COUNT 7) (:C 7 :COUNT 8)))
  (:SLEEP 0.25 :RET ((:C 3 :COUNT 4) (:C 2 :COUNT 3) (:C 2 :COUNT 3)  
(:C 2 :COUNT 3) (:C 4 :COUNT 5)))
  NIL

which does indeed seem to impact the results.  Interestingly, if the  
sleep becomes very long

  RUCKSACK 55 > (try-it 5 '(1))

  (:SLEEP 1 :RET NIL)
  NIL

  RUCKSACK 56 >

I get the expected result.  (The last one is 250+ seconds to evaluate  
- I haven't tried more than a few times but I got the same result in  
all cases).

I do not understand these results.  Offhand, I can think of 4 possible  
explanations

1. The results are correct, I just don't understand Rucksack well  
enough.  I don't think so, but please enlighten me if that's the case...

2. I'm not using Rucksack as intended, leading to undefined results.   
Am I doing something wrong?  If so, where?

3. There's something wrong with my setup - I'm using Rucksack  
downloaded as a tarball from common-lisp.net yesterday and Lispworks  
for Macintosh v5.1 Pro on Mac OSX Leopard.  Can anyone reproduce this  
variation?

4. There's an error in Rucksack.  I do not understand the code very  
well, but the variation in terms of how many insertions are needed and  
the apparent timing dependency surprises me.

Suggestions / insights?

best regards,

Klaus Harbo





More information about the rucksack-devel mailing list