On Thu, Feb 23 2006, Hans Hübner wrote:
Hi,
I cannot reproduce this, at least not from what you describe. The warning is the result of a reference to a deleted object being written to the transaction log, presumable referenced from a slot of another object. Can you provide me with an isolated test case?
Dear Hans,
Sorry of not responding earlier.
Here is an isolated test case:
(asdf:oos 'asdf:load-op :bknr-impex) (asdf:oos 'asdf:load-op :bknr-datastore)
(defpackage some-example (:use #:common-lisp #:bknr.impex #:puri #:bknr.indices #:bknr.datastore))
(in-package :some-example)
(define-persistent-class obj (store-object) ())
(deftransaction del (obj) (delete-object obj))
(make-instance 'mp-store :directory "/tmp/tmp-store/" :subsystems (list (make-instance 'store-object-subsystem)))
(del (make-object 'obj :name "a test" :type nil))
I noticed that if "del" is not a transaction it does not signal a warning. I am not sure why is so. Beside delete-object I would like to physically delete the file there. Thanks.
Regards,
Hi Kamen,
the bug that you describe is interesting. The following happens:
Your transaction "del" is entered. "del" calls "delete-object" on the argument object. "delete-object" marks the object as deleted. "delete-object" is exited and a log entry is written to the transaction log. "del" is exited and a log entry is written. During the writing of the log entry, the datastore notices that the argument object has been deleted and issues the warning you have seen.
You can avoid the warning by calling "destroy-object" instead of "delete-object". "delete-object" is a transaction which is meant to be called from non-transaction code, whereas "destroy-object" is a standard function which should be called only from transaction code.
I am not sure whether we should keep it this way. On the positive side, a programmer does need to be aware of whether he writes code that executes within our outside of a transaction, so having to seperate functions here makes some sense. On the negative side, it is harder to remember what API to use, and in fact this is a problem with "setf slot-value" vs. "change-slot-values".
For the time being, I'd recommend that you use "destroy-object" from your transaction code. Also, note that if you delete your blob file at when you delete an object, you loose the ability to roll forward to a point back in time, should you need to do so. Deleting blob files is best deferred to a point where old snapshots are archived using the function "(bknr.datastore::delete-orphaned-blob-files)".
Cheers, Hans
Hi Kamen,
my analysis of your problem was not complete: In fact, the problem is a bit different from what I wrote:
If you pass persistent objects as argument to a transaction and you delete that object within the transaction, serializing the transaction arguments to the transaction log result in the warning that you have seen. The datastore emits a warning because the object is no longer in existence after the transaction has been executed. Upon restore, this will not be a problem since no log entry is written, but the warning is annoying nevertheless.
My suggestion, using "destroy-object" from your transaction, does not help, because you still have the persistent object in the argument list to the transaction function. A proper workaround is to pass only the object ID in the argument list to the transaction (this is how delete-object works). Another workaround is to remove the warning from the datastore. Maybe I will do that in the future, but I have to think about it some more.
My remark about deleting blob files still holds, though.
-Hans
Dear Hans,
Thank you very much for your instant answer to the issue and for the suggested workarounds. I added a wrapper method around the del transaction that sends the ID of the object as a parameter and now it is even better.
Thanks for the suggestion about the deletion of the blob files. I will reconsider using this function. Initially it didn't seem a good idea but I am starting to think that it is.
As to the issues that you have put in your previous message I am not sure yet what the right approach should be. I'd trust your judgement.
Regards,