Tuesday, October 19, 2004

Test Port
I started the day by porting AM's unit test code for View resolvers over to the remote resolver. This was time consuming, but reasonably easy. I started by changing all the obvious items to the new resolver setup (for instance, I did a search and replace of RemoteResolver for ViewResolver), and then moved on to a method-by-method comparison of the old code with the View resolver test code. Strangely, the ViewResolverUnitTest tests had all been commented out. AM wasn't sure why he'd done that, but there were no problems putting them back in.

I was pleased to discover that many of my bug fixes and specific code to handle general cases were already in the template. This meant that I could delete some of what I'd written in the past. It bodes well for when someone gets the time to refactor this, and use inheritance to handle the common parts. We all wish we could do it now, but with everyone continuing to modify their own resolvers, it's difficult to find stable common ground between their tests.

Once the tests were happily compiling and running, the results were exactly the same. Wouldn't you know it? :-) At least I had a common base with which I could question AM.

The specific problem which was reported was:

  org.kowari.resolver.spi.LocalizeException: Unable to localize rmi://myserver.com/server1#dc - Couldn't localize node
This told me that the query engine was looking for a string in its string pool, and it wasn't available. Initially I thought that perhaps I had globalized nodes which had come back from the remote resolver, and the action of localizing them was failing. However, AM pointed out that it was actually happening in the Resolver.setModel method, which has no data returned from the resolver.

Resolver.setModel is called by DatabaseSession.setModel. Looking at this method showed that the problem was occuring when the local node number of the destination model was being looked up. The method being used here was:
systemResolver.lookupPersistent(new URIReferenceImpl(destinationModelURI));
This method looks up a node in the string pool, returning the node number if found, and throwing an exception if it isn't. Given that the destination model is on a different server, then the local systemResolver object will not know about that model URI, so the local node number for the model can't possibly be found.

The solution is to do exactly what the source model code was doing:
systemResolver.localize(new URIReferenceImpl(sourceModelURI));
The main difference here is that if a node is not found then it gets created.

At this point the power went off due to a storm that we had. With my test code all on a PC I couldn't test if anything worked. So I started looking at some more of the DatabaseSession code to see if this mistake had been made elsewhere as well. I found it in one other place, this time in the private doModify method.

While getting some advice from AM about the bugs I was seeing, I showed him the RemoteResolver.modifyModel method. While everything was fine, he pointed out that the set of statements could be a streaming object, and if I tried to send everything to the server in one go then I could run out of memory. I've since wrapped this in a loop to send pages of statements at a time. One more thing I should do is wrap this in a transaction, so it becomes an atomic operation on the server.

Spelling
For the last few days the spellcheck button on Firefox has been doing nothing (beyond briefly flashing a window up). I wonder why the behaviour has suddenly changed?

No comments: