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.