synchronized (_locks) {
// consult with the 'first level' cache, aka current transaction
entry = (ObjectLock) _locks.get(internaloid);
if (entry == null) {
// consult with the 'second level' cache, aka physical cache
CacheEntry cachedEntry = (CacheEntry) _cache.remove(internaloid);
if (cachedEntry != null) {
OID cacheOid = cachedEntry.getOID();
if (internaloid.getName().equals(cacheOid.getName())) {
entry = new ObjectLock(cachedEntry.getOID(),
cachedEntry.getEntry(), cachedEntry.getTimeStamp());
entry.setOID(internaloid);
} else {
entry = new ObjectLock(internaloid);
}
} else {
entry = new ObjectLock(internaloid);
}
_locks.put(internaloid, entry);
}
entry.enter();
}
// ObjectLock.acquire() may call Object.wait(), so a thread can not
// been synchronized with ANY shared object before acquire().
// So, it must be called outside synchronized( locks ) block.
boolean failed = true;
try {
switch (lockAction) {
case ObjectLock.ACTION_READ:
entry.acquireLoadLock(tx, false, timeout);
break;
case ObjectLock.ACTION_WRITE:
entry.acquireLoadLock(tx, true, timeout);
break;
case ObjectLock.ACTION_CREATE:
entry.acquireCreateLock(tx);
break;
case ObjectLock.ACTION_UPDATE:
entry.acquireUpdateLock(tx, timeout);
break;
default:
throw new IllegalArgumentException(
"lockType " + lockAction + " is undefined!");
}
failed = false;
return entry;
} finally {
synchronized (_locks) {
entry.leave();
if (failed) {
// The need of this block may not be too obvious.
// At the very moment, if it happens, current thread
// failed to acquire a lock. Then, another thread just
// release the lock right after. The released entry
// then will not be moved to cache because inLocksGap
// isn't zero. So, there maybe a chance of memory
// leak, as the entry was in "locks", but not in
// "cache" as supposed. To avoid it from happening,
// we ensure here that the entry which should be move
// to "cache" from "locks" is actually moved.
if (entry.isDisposable()) {
_locks.remove(internaloid);
if (entry.isExpired()) {
_cache.expire(internaloid);
entry.expired();
} else {
_cache.put(internaloid, new CacheEntry(
entry.getOID(), entry.getObject(), entry.getTimeStamp()));
}
}
}
}