Thursday, September 09, 2004

JRDF Removal
I wasn't well today, and I was also in and out of the office a bit, so the day didn't end up as productive as I'd have liked. However, I did finally get the JRDF removal problem fixed.

I did a clean build this morning before I thought about what I was doing. This removed the logs which described the location of the problem code. So I started out by running the time consuming tests again and it took me a little while to trace out the code I needed to change.

Once I found the problem code in ThingJRDFModel, I was still stuck trying to find which code to actually modify as this code only uses general interfaces. The iterator to be modified was an instance of the ClosableIterator interface, with no clue as to which of the numerous implementations would be the appropriate one to change. Fortunately, re-running the tests left a stack trace which showed the class to be ClosableIteratorImpl.

My first attempt to implement the remove() method took the session that the iterator used, retrieved the database, and deleted the requisite triple. This didn't work for two reasons. First, removing a triple in this way was actually going to remove the triple from all models (or graphs), and not just the one referred to by the iterator. More importantly, this deletion mechanism operates outside of any current transactions, so it was not visible to the transaction in which the iterator was being used. Hence, even though the triples were being removed, the results of this were not being seen in the tests.

A little help from DM helped track all of this down. The code which had worked for the Kowari graph prior to this, was using a method with a signature of Graph.remove(Triple). Looking up how this code worked internally showed that it was using the Session.delete(URI,SubjectNode,PredicateNode,ObjectNode) method. Obviously, it should work if I duplicated this call inside the iterator's remove method.

The ClosableIteratorImpl class did not have access to the model URI for the graph, which it was going to need to do the deletion. This meant modifying the constructor of ClosableIteratorImpl to take an extra parameter. Rather than working out which type of Graph implementation was creating the iterator, I tried to side-step tracing the code path completely and checked for all instances of "new ClosableIteratorImpl" in the code. I got lucky, and found it in only 2 of the find() methods of AbstractDatabaseSession (isn't it weird how everything end up in there eventually?).

Fortunately, each find() method had access to the URI of the requested model, so it was easy to pass this through to a modified constructor for ClosableIteratorImpl. The next() method was changed to save the returned triple, and the remove method was implemented trivially by calling:

  session.delete(graphURI, latestTriple.getSubject(), latestTriple.getPredicate(), latestTriple.getObject());
As with the in-memory implementation of JRDF, this was able to throw an exception, and again I resorted to the inappropriate IllegalStateException to throw out of the Iterator.remove() method. I'm such a sell out. At least I didn't use a raw RuntimeException.

No comments: