opencog / atomspace-rocks

AtomSpace Graph Database RocksDB backend
Other
13 stars 8 forks source link

Bug or User error? when using frames #21

Open linas opened 1 year ago

linas commented 1 year ago

Here's some weird unexpected, confusing behavior w.r.t. frames. It's both a bug and a user-error. It is exhibited by the following:

(use-modules (opencog) (opencog exec))
(use-modules (opencog persist))
(use-modules (opencog persist-rocks))

(define a (AtomSpace))
(define b (AtomSpace))
(define c (AtomSpace a b))
(cog-set-atomspace! a)
(Concept "foo")
(Concept "bar")
(Concept "baz")
(Concept "I'm in A")

(cog-set-atomspace! c)
(define rsn (RocksStorageNode "rocks:///tmp/foo"))
(cog-open rsn)

; Oh no! Saving atomspace contents without saving frames first!!
(store-atomspace)
(cog-rocks-print rsn "")

; Now store atomspace b (which should be empty!!)
(store-frames b)

; Hmm looks like all atoms got assigned to atomspace b! Oh no!
(cog-rocks-print rsn "")

If the store-frames is done first, before the store-atomspace, then the correct behavior is seen. This is a user-error, since the user should have done the store-frames first. It is also a bug, since the store-frames should not have re-assigned the atoms to the wrong atomspace.

sikefield3 commented 1 year ago

; Hmm looks like all atoms got assigned to atomspace b! Oh no! (cog-rocks-print rsn "")

Maybe my understanding of this is wrong, but shouldn't RocksDB stay connected with the atomspace it was created in (in this case AS 'C') and so the content of atomspace 'A' is still in the DB.

If I just print the AS B:

(cog-set-atomspace! b)
(cog-prt-atomspace)

, I get nothing (as expected).

linas commented 1 year ago

Sure! Let me walk through the example, and some of the design choices (which could be faulty, but seemed like the "right thing to do", at the time.)

OK, so far, so good. Now, when cog-open is called, it prints

Rocks: DB-version=2 multi-space=0 initial aid=1

The initial-aid=1 basically says that the storage node is empty. The multi-space=0 thing says that it is initialized to hold only one atomspace; that the concept of multiple frames hasn't been turned on, yet. Now, we could have noticed that rsn is in c, and initialized it to be multi-space=true. But this creates problems:

So, it seemed best to just open it, and leave however we found it, i.e. in this case, leave it as monospace.

OK, so far, so good. Now comes the store-atomspace. What should that do? Should it go "a ha, I'm in some non-trivial frame, and therefore I should switch to multi-space mode, and store the frames, before doing anything else?" Or should it just store the current atomspace, as instructed, (in mono-space mode) without trying to second-guess the user's intent? The second choice seemed best, since, if the user wanted to store frames, they should have said so.

So ... the current atomspace gets stored, but it gets stored in monospace mode. Which seems fine. Its a minimalist, simple thing to do.

Next is (store-frames b) -- this is arguably a user-error. It tells the systems to switch from monospace mode to multi-space mode. Fine. But it then tags all the atoms in rocks with frame b (without realizing that "in reality", it's "empty") Note that if instead the user had said (store-frames c) at this point, it would have thrown an error: when switching from monospace mode to multi-space, all the atoms have to be assigned a space: but which one? a, b or c? It would be horrible to try to start guessing, by comparing rocks contents to atomspace contents, matching and pairing them up, sorting them into buckets. Yuck, a real mess that gets messier the more complicated the example. Easier to throw an error.

So now we arrive to the present moment. You are right, that if you print b, you will see that it is empty. And that is as it should be. But now try this:

(store-frames c)
(store-atomspace)
(cog-rocks-print rsn "")

You will now see that rocks has atoms in both a and in b, which might be "surprising" to the user. It might not be what they were expecting. The print shows this:

rkey: >>a@4:<<    rval: >>(ConceptNode "foo")<<     ;; foo has UID 4
rkey: >>d@7<<    rval: >>(as "(uuid . 3)")<<        ;; atomspace b as uid 7
rkey: >>d@8<<    rval: >>(as "(uuid . 2)")<<        ;; atomspace a has uid 8
rkey: >>d@9<<    rval: >>(as "(uuid . 4)" 8 7)<<    ;; atomspace c has uid 9
rkey: >>k@4:7:+1<<    rval: >><<                    ;; foo (uid 4) is in uid 7 aka atomspace b
rkey: >>k@4:8:+1<<    rval: >><<                    ;; foo (uid 4) is in uid 8 aka atomspace a

If you closed, exited, restarted, and loaded, you would now get "foo" in both a and b, and b would not be empty. That's the surprise.

Overall, the whole thing feels like a user-error, to me. The code could have done something else, instead, but I don't really see any good reason to "fix" anything, just right now. The alternatives seem worse.

linas commented 1 year ago

So, I'm thinking this is a user error. There are two choices:

The second choice is icky. Suppose we created a rocks monospace store a few months ago. Now we want to add a few layers on top of it. It would be nice to be able to "just do it", instead of getting an error.

So I'm tempted to close this as "user error, working as designed".