David,

Your not executing inside a database level (JDBC) transaction. I'm afraid model.begin/commit does not know about JDBC properly. You need to control the JDBC transaction in your code to get isolation between JVMs.

Which SQL database are you using?

        Andy

On 10/04/13 16:12, Lebling, David (US SSA) wrote:
The method below is a somewhat over-decorated (with extra non-production checks and error 
log messages) version of "write a model to the SDB repository safely" that I am 
using. The Individual res (or rather, the in-memory model it is in) is written to the 
Model model (obtained via SDBFactory.connectNamedModel), replacing any current contents.

It attempts to protect the model update from horrible concurrency death during the 
process. However, I'm seeing that in cases where there are multiple readers and writers 
(in different services - i.e., different JVMs) beating on the particular model, the error 
messages with "****" appear, sometimes surprisingly often. When the first one 
appears, the second one also always appears.

The outcome in the above cases is a repository model that is empty when read 
later. The obvious idea is that between model.removeAll() and the later 
model.add() the reader is reading the temporarily empty model. I don't know if 
that idea is correct, but I don't have any others.

Any suggestions as to what I am doing wrong would be appreciated.

/**
* Single place to write or delete a model from the store
* @param model store-based model
* @param res in-memory resource to write into model, or null to just delete 
model
*/
void internalWrite(Model model, Individual res) {
    if (model != null) {
       try {
          logger.debug("begin write model");
          model.enterCriticalSection(Lock.WRITE);
          model.notifyEvent(GraphEvents.startRead); // TEST I don't know if 
this is worth doing
          model.begin();
          model.removeAll(); // clear out the existing statements in the repo 
model
          if (res != null) {
             Model base = res.getOntModel().getBaseModel();
             if (base.size() == 0) {
                logger.error("internalWrite: base model empty");
             }
             model.add(base); // add in-memory model to repository model
             if (model.size() == 0) {
                logger.error("internalWrite: model empty after add"); // **** 
if this happens ****
             }
          }
          else {
             logger.debug("internalWrite: resource passed is null: delete");
          }
          model.commit();
          if (model.size() == 0) {
             logger.error("internalWrite: model empty after commit"); // **** 
this also happens ****
          }
       }
       catch (SDBException ex) {
          model.abort();
          logger.error(ex);
       }
       finally {
          model.notifyEvent(GraphEvents.finishRead);  // TEST I don't know if 
this is worth doing
          model.leaveCriticalSection();
          logger.debug("end write model");
       }
    }
}

Thanks,

Dave

David Lebling
BAE Systems, Inc.


Reply via email to