{
// Lock the L2 cache so nobody else can have it while we are updating objects
// Without this we can get race conditions between threads taking objects out, and
// us putting objects in leading to assorted exceptions in AbstractStateManager or
// in the PC object jdoReplaceField() methods.
Level2Cache l2Cache = omf.getLevel2Cache();
synchronized (l2Cache)
{
// Process all modified objects adding/updating/removing from L2 cache as appropriate
Iterator txCachedIter = txCachedIds.iterator();
while (txCachedIter.hasNext())
{
Object id = txCachedIter.next();
StateManager sm = enlistedSMCache.get(id);
if (sm == null)
{
// Modified object no longer enlisted so has been GCed, so remove from L2
if (NucleusLogger.CACHE.isDebugEnabled())
{
NucleusLogger.CACHE.debug(LOCALISER.msg("004014",
id, String.valueOf(l2Cache.getSize())));
}
l2Cache.evict(id);
}
else
{
// Modified object still enlisted so cacheable
if (getApiAdapter().isDeleted(sm.getObject()))
{
// Object has been deleted so remove from L2 cache
if (NucleusLogger.CACHE.isDebugEnabled())
{
NucleusLogger.CACHE.debug(LOCALISER.msg("004007",
StringUtils.toJVMIDString(sm.getObject()),
sm.getInternalObjectId(),
String.valueOf(l2Cache.getSize())));
}
l2Cache.evict(getApiAdapter().getIdForObject(sm.getObject()));
}
else if (!getApiAdapter().isDetached(sm.getObject()))
{
// Object has been added/modified so update in L2 cache
putObjectIntoLevel2CacheInternal(sm, true);