Fix code style
git-svn-id: https://svn.jboss.org/repos/hibernate/core/trunk@17658 1b8cb986-b30d-0410-93ca-fae66ebed9b2
This commit is contained in:
parent
2ad3cfb6c0
commit
0ddf421e78
|
@ -39,7 +39,6 @@ import javax.transaction.TransactionManager;
|
||||||
|
|
||||||
import org.hibernate.cache.CacheException;
|
import org.hibernate.cache.CacheException;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Encapsulates logic to allow a {@link TransactionalAccessDelegate} to determine
|
* Encapsulates logic to allow a {@link TransactionalAccessDelegate} to determine
|
||||||
* whether a {@link TransactionalAccessDelegate#putFromLoad(Object, Object, long, Object, boolean)
|
* whether a {@link TransactionalAccessDelegate#putFromLoad(Object, Object, long, Object, boolean)
|
||||||
|
@ -52,12 +51,12 @@ import org.hibernate.cache.CacheException;
|
||||||
*
|
*
|
||||||
* @version $Revision: $
|
* @version $Revision: $
|
||||||
*/
|
*/
|
||||||
public class PutFromLoadValidator
|
public class PutFromLoadValidator {
|
||||||
{
|
|
||||||
/**
|
/**
|
||||||
* Period in ms after a removal during which a call to {@link #isPutValid(Object)}
|
* Period in ms after a removal during which a call to
|
||||||
* that hasn't been {@link #registerPendingPut(Object) pre-registered}
|
* {@link #isPutValid(Object)} that hasn't been
|
||||||
* (aka a "naked put") will return false.
|
* {@link #registerPendingPut(Object) pre-registered} (aka a "naked put")
|
||||||
|
* will return false.
|
||||||
*/
|
*/
|
||||||
public static final long NAKED_PUT_INVALIDATION_PERIOD = 10 * 1000;
|
public static final long NAKED_PUT_INVALIDATION_PERIOD = 10 * 1000;
|
||||||
|
|
||||||
|
@ -67,11 +66,16 @@ public class PutFromLoadValidator
|
||||||
/** Period before which we stop trying to clean out pending puts */
|
/** Period before which we stop trying to clean out pending puts */
|
||||||
private static final long PENDING_PUT_RECENT_PERIOD = 2 * 1000;
|
private static final long PENDING_PUT_RECENT_PERIOD = 2 * 1000;
|
||||||
|
|
||||||
/** Period after which a pending put is never expected to come in
|
/**
|
||||||
* and should be cleaned */
|
* Period after which a pending put is never expected to come in and should
|
||||||
|
* be cleaned
|
||||||
|
*/
|
||||||
private static final long MAX_PENDING_PUT_DELAY = 2 * 60 * 1000;
|
private static final long MAX_PENDING_PUT_DELAY = 2 * 60 * 1000;
|
||||||
|
|
||||||
/** Used to determine whether the owner of a pending put is a thread or a transaction */
|
/**
|
||||||
|
* Used to determine whether the owner of a pending put is a thread or a
|
||||||
|
* transaction
|
||||||
|
*/
|
||||||
private final TransactionManager transactionManager;
|
private final TransactionManager transactionManager;
|
||||||
|
|
||||||
private final long nakedPutInvalidationPeriod;
|
private final long nakedPutInvalidationPeriod;
|
||||||
|
@ -80,46 +84,63 @@ public class PutFromLoadValidator
|
||||||
private final long maxPendingPutDelay;
|
private final long maxPendingPutDelay;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Registry of expected, future, isPutValid calls. If a key+owner is registered
|
* Registry of expected, future, isPutValid calls. If a key+owner is
|
||||||
* in this map, it is not a "naked put" and is allowed to proceed.
|
* registered in this map, it is not a "naked put" and is allowed to
|
||||||
|
* proceed.
|
||||||
|
*/
|
||||||
|
private final ConcurrentMap<Object, PendingPutMap> pendingPuts = new ConcurrentHashMap<Object, PendingPutMap>();
|
||||||
|
/**
|
||||||
|
* List of pending puts. Used to ensure we don't leak memory via the
|
||||||
|
* pendingPuts map
|
||||||
*/
|
*/
|
||||||
private final ConcurrentMap<Object, PendingPutMap> pendingPuts =
|
|
||||||
new ConcurrentHashMap<Object, PendingPutMap>();
|
|
||||||
/** List of pending puts. Used to ensure we don't leak memory via the pendingPuts map */
|
|
||||||
private final List<WeakReference<PendingPut>> pendingQueue = new LinkedList<WeakReference<PendingPut>>();
|
private final List<WeakReference<PendingPut>> pendingQueue = new LinkedList<WeakReference<PendingPut>>();
|
||||||
/** Separate list of pending puts that haven't been resolved within PENDING_PUT_OVERAGE_PERIOD.
|
/**
|
||||||
* Used to ensure we don't leak memory via the pendingPuts map.
|
* Separate list of pending puts that haven't been resolved within
|
||||||
* Tracked separately from more recent pending puts for efficiency reasons. */
|
* PENDING_PUT_OVERAGE_PERIOD. Used to ensure we don't leak memory via the
|
||||||
|
* pendingPuts map. Tracked separately from more recent pending puts for
|
||||||
|
* efficiency reasons.
|
||||||
|
*/
|
||||||
private final List<WeakReference<PendingPut>> overagePendingQueue = new LinkedList<WeakReference<PendingPut>>();
|
private final List<WeakReference<PendingPut>> overagePendingQueue = new LinkedList<WeakReference<PendingPut>>();
|
||||||
/** Lock controlling access to pending put queues */
|
/** Lock controlling access to pending put queues */
|
||||||
private final Lock pendingLock = new ReentrantLock();
|
private final Lock pendingLock = new ReentrantLock();
|
||||||
private final ConcurrentMap<Object, Long> recentRemovals = new ConcurrentHashMap<Object, Long>();
|
private final ConcurrentMap<Object, Long> recentRemovals = new ConcurrentHashMap<Object, Long>();
|
||||||
/** List of recent removals. Used to ensure we don't leak memory via the recentRemovals map */
|
/**
|
||||||
|
* List of recent removals. Used to ensure we don't leak memory via the
|
||||||
|
* recentRemovals map
|
||||||
|
*/
|
||||||
private final List<RecentRemoval> removalsQueue = new LinkedList<RecentRemoval>();
|
private final List<RecentRemoval> removalsQueue = new LinkedList<RecentRemoval>();
|
||||||
/** The time when the first element in removalsQueue will expire. No reason to do
|
/**
|
||||||
* housekeeping on the queue before this time. */
|
* The time when the first element in removalsQueue will expire. No reason
|
||||||
|
* to do housekeeping on the queue before this time.
|
||||||
|
*/
|
||||||
private volatile long earliestRemovalTimestamp;
|
private volatile long earliestRemovalTimestamp;
|
||||||
/** Lock controlling access to removalsQueue */
|
/** Lock controlling access to removalsQueue */
|
||||||
private final Lock removalsLock = new ReentrantLock();
|
private final Lock removalsLock = new ReentrantLock();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The time of the last call to regionRemoved(), plus NAKED_PUT_INVALIDATION_PERIOD.
|
* The time of the last call to regionRemoved(), plus
|
||||||
* All naked puts will be rejected until the current time is greater than this value.
|
* NAKED_PUT_INVALIDATION_PERIOD. All naked puts will be rejected until the
|
||||||
|
* current time is greater than this value.
|
||||||
*/
|
*/
|
||||||
private volatile long invalidationTimestamp;
|
private volatile long invalidationTimestamp;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new PutFromLoadValidator.
|
* Creates a new PutFromLoadValidator.
|
||||||
*
|
*
|
||||||
* @param transactionManager transaction manager to use to associated changes with a transaction;
|
* @param transactionManager
|
||||||
* may be <code>null</code>
|
* transaction manager to use to associated changes with a
|
||||||
|
* transaction; may be <code>null</code>
|
||||||
*/
|
*/
|
||||||
public PutFromLoadValidator(TransactionManager transactionManager) {
|
public PutFromLoadValidator(TransactionManager transactionManager) {
|
||||||
this(transactionManager, NAKED_PUT_INVALIDATION_PERIOD, PENDING_PUT_OVERAGE_PERIOD,
|
this(transactionManager, NAKED_PUT_INVALIDATION_PERIOD,
|
||||||
PENDING_PUT_RECENT_PERIOD, MAX_PENDING_PUT_DELAY);
|
PENDING_PUT_OVERAGE_PERIOD, PENDING_PUT_RECENT_PERIOD,
|
||||||
|
MAX_PENDING_PUT_DELAY);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Constructor variant for use by unit tests; allows control of various timeouts by the test. */
|
/**
|
||||||
|
* Constructor variant for use by unit tests; allows control of various
|
||||||
|
* timeouts by the test.
|
||||||
|
*/
|
||||||
protected PutFromLoadValidator(TransactionManager transactionManager,
|
protected PutFromLoadValidator(TransactionManager transactionManager,
|
||||||
long nakedPutInvalidationPeriod, long pendingPutOveragePeriod,
|
long nakedPutInvalidationPeriod, long pendingPutOveragePeriod,
|
||||||
long pendingPutRecentPeriod, long maxPendingPutDelay) {
|
long pendingPutRecentPeriod, long maxPendingPutDelay) {
|
||||||
|
@ -132,8 +153,7 @@ public class PutFromLoadValidator
|
||||||
|
|
||||||
// ----------------------------------------------------------------- Public
|
// ----------------------------------------------------------------- Public
|
||||||
|
|
||||||
public boolean isPutValid(Object key)
|
public boolean isPutValid(Object key) {
|
||||||
{
|
|
||||||
boolean valid = false;
|
boolean valid = false;
|
||||||
long now = System.currentTimeMillis();
|
long now = System.currentTimeMillis();
|
||||||
|
|
||||||
|
@ -165,13 +185,13 @@ public class PutFromLoadValidator
|
||||||
return valid;
|
return valid;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void keyRemoved(Object key)
|
public void keyRemoved(Object key) {
|
||||||
{
|
|
||||||
// Invalidate any pending puts
|
// Invalidate any pending puts
|
||||||
pendingPuts.remove(key);
|
pendingPuts.remove(key);
|
||||||
|
|
||||||
// Record when this occurred to invalidate later naked puts
|
// Record when this occurred to invalidate later naked puts
|
||||||
RecentRemoval removal = new RecentRemoval(key, this.nakedPutInvalidationPeriod);
|
RecentRemoval removal = new RecentRemoval(key,
|
||||||
|
this.nakedPutInvalidationPeriod);
|
||||||
recentRemovals.put(key, removal.timestamp);
|
recentRemovals.put(key, removal.timestamp);
|
||||||
|
|
||||||
// Don't let recentRemovals map become a memory leak
|
// Don't let recentRemovals map become a memory leak
|
||||||
|
@ -182,13 +202,14 @@ public class PutFromLoadValidator
|
||||||
removalsQueue.add(removal);
|
removalsQueue.add(removal);
|
||||||
|
|
||||||
if (attemptClean) {
|
if (attemptClean) {
|
||||||
if (removalsQueue.size() > 1) { // we have at least one as we just added it
|
if (removalsQueue.size() > 1) { // we have at least one as we
|
||||||
|
// just added it
|
||||||
toClean = removalsQueue.remove(0);
|
toClean = removalsQueue.remove(0);
|
||||||
}
|
}
|
||||||
earliestRemovalTimestamp = removalsQueue.get(0).timestamp.longValue();
|
earliestRemovalTimestamp = removalsQueue.get(0).timestamp
|
||||||
|
.longValue();
|
||||||
}
|
}
|
||||||
}
|
} finally {
|
||||||
finally {
|
|
||||||
removalsLock.unlock();
|
removalsLock.unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -196,7 +217,8 @@ public class PutFromLoadValidator
|
||||||
Long cleaned = recentRemovals.get(toClean.key);
|
Long cleaned = recentRemovals.get(toClean.key);
|
||||||
if (cleaned != null && cleaned.equals(toClean.timestamp)) {
|
if (cleaned != null && cleaned.equals(toClean.timestamp)) {
|
||||||
cleaned = recentRemovals.remove(toClean.key);
|
cleaned = recentRemovals.remove(toClean.key);
|
||||||
if (cleaned != null && cleaned.equals(toClean.timestamp) == false) {
|
if (cleaned != null
|
||||||
|
&& cleaned.equals(toClean.timestamp) == false) {
|
||||||
// Oops; removed the wrong timestamp; restore it
|
// Oops; removed the wrong timestamp; restore it
|
||||||
recentRemovals.putIfAbsent(toClean.key, cleaned);
|
recentRemovals.putIfAbsent(toClean.key, cleaned);
|
||||||
}
|
}
|
||||||
|
@ -204,9 +226,9 @@ public class PutFromLoadValidator
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void regionRemoved()
|
public void regionRemoved() {
|
||||||
{
|
invalidationTimestamp = System.currentTimeMillis()
|
||||||
invalidationTimestamp = System.currentTimeMillis() + this.nakedPutInvalidationPeriod;
|
+ this.nakedPutInvalidationPeriod;
|
||||||
pendingLock.lock();
|
pendingLock.lock();
|
||||||
try {
|
try {
|
||||||
removalsLock.lock();
|
removalsLock.lock();
|
||||||
|
@ -218,48 +240,48 @@ public class PutFromLoadValidator
|
||||||
removalsQueue.clear();
|
removalsQueue.clear();
|
||||||
earliestRemovalTimestamp = invalidationTimestamp;
|
earliestRemovalTimestamp = invalidationTimestamp;
|
||||||
|
|
||||||
}
|
} finally {
|
||||||
finally {
|
|
||||||
removalsLock.unlock();
|
removalsLock.unlock();
|
||||||
}
|
}
|
||||||
}
|
} finally {
|
||||||
finally {
|
|
||||||
pendingLock.unlock();
|
pendingLock.unlock();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Notifies this validator that it is expected that a database read followed by a
|
* Notifies this validator that it is expected that a database read followed
|
||||||
* subsequent {@link #isPutValid(Object)} call will occur. The intent is this method
|
* by a subsequent {@link #isPutValid(Object)} call will occur. The intent
|
||||||
* would be called following a cache miss wherein it is expected that a database
|
* is this method would be called following a cache miss wherein it is
|
||||||
* read plus cache put will occur. Calling this method allows the validator to treat
|
* expected that a database read plus cache put will occur. Calling this
|
||||||
* the subsequent <code>isPutValid</code> as if the database read occurred when
|
* method allows the validator to treat the subsequent
|
||||||
* this method was invoked. This allows the validator to compare the timestamp of
|
* <code>isPutValid</code> as if the database read occurred when this method
|
||||||
* this call against the timestamp of subsequent removal notifications. A put that
|
* was invoked. This allows the validator to compare the timestamp of this
|
||||||
* occurs without this call preceding it is "naked"; i.e the validator must assume
|
* call against the timestamp of subsequent removal notifications. A put
|
||||||
* the put is not valid if any relevant removal has occurred within
|
* that occurs without this call preceding it is "naked"; i.e the validator
|
||||||
* {@link #NAKED_PUT_INVALIDATION_PERIOD} milliseconds.
|
* must assume the put is not valid if any relevant removal has occurred
|
||||||
|
* within {@link #NAKED_PUT_INVALIDATION_PERIOD} milliseconds.
|
||||||
*
|
*
|
||||||
* @param key key that will be used for subsequent put
|
* @param key
|
||||||
|
* key that will be used for subsequent put
|
||||||
*/
|
*/
|
||||||
public void registerPendingPut(Object key)
|
public void registerPendingPut(Object key) {
|
||||||
{
|
|
||||||
PendingPut pendingPut = new PendingPut(key, getOwnerForPut());
|
PendingPut pendingPut = new PendingPut(key, getOwnerForPut());
|
||||||
PendingPutMap pendingForKey = new PendingPutMap();
|
PendingPutMap pendingForKey = new PendingPutMap();
|
||||||
synchronized (pendingForKey) {
|
synchronized (pendingForKey) {
|
||||||
for (;;) {
|
for (;;) {
|
||||||
PendingPutMap existing = pendingPuts.putIfAbsent(key, pendingForKey);
|
PendingPutMap existing = pendingPuts.putIfAbsent(key,
|
||||||
|
pendingForKey);
|
||||||
if (existing != null && existing != pendingForKey) {
|
if (existing != null && existing != pendingForKey) {
|
||||||
synchronized (existing) {
|
synchronized (existing) {
|
||||||
existing.put(pendingPut);
|
existing.put(pendingPut);
|
||||||
PendingPutMap doublecheck = pendingPuts.putIfAbsent(key, existing);
|
PendingPutMap doublecheck = pendingPuts.putIfAbsent(
|
||||||
|
key, existing);
|
||||||
if (doublecheck == null || doublecheck == existing) {
|
if (doublecheck == null || doublecheck == existing) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
// else we hit a race and need to loop to try again
|
// else we hit a race and need to loop to try again
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
pendingForKey.put(pendingPut);
|
pendingForKey.put(pendingPut);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -269,6 +291,7 @@ public class PutFromLoadValidator
|
||||||
// Guard against memory leaks
|
// Guard against memory leaks
|
||||||
preventOutdatedPendingPuts(pendingPut);
|
preventOutdatedPendingPuts(pendingPut);
|
||||||
}
|
}
|
||||||
|
|
||||||
// -------------------------------------------------------------- Protected
|
// -------------------------------------------------------------- Protected
|
||||||
|
|
||||||
/** Only for use by unit tests; may be removed at any time */
|
/** Only for use by unit tests; may be removed at any time */
|
||||||
|
@ -276,8 +299,7 @@ public class PutFromLoadValidator
|
||||||
pendingLock.lock();
|
pendingLock.lock();
|
||||||
try {
|
try {
|
||||||
return pendingQueue.size();
|
return pendingQueue.size();
|
||||||
}
|
} finally {
|
||||||
finally {
|
|
||||||
pendingLock.unlock();
|
pendingLock.unlock();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -287,8 +309,7 @@ public class PutFromLoadValidator
|
||||||
pendingLock.lock();
|
pendingLock.lock();
|
||||||
try {
|
try {
|
||||||
return overagePendingQueue.size();
|
return overagePendingQueue.size();
|
||||||
}
|
} finally {
|
||||||
finally {
|
|
||||||
pendingLock.unlock();
|
pendingLock.unlock();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -298,15 +319,14 @@ public class PutFromLoadValidator
|
||||||
removalsLock.lock();
|
removalsLock.lock();
|
||||||
try {
|
try {
|
||||||
return removalsQueue.size();
|
return removalsQueue.size();
|
||||||
}
|
} finally {
|
||||||
finally {
|
|
||||||
removalsLock.unlock();
|
removalsLock.unlock();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------- Private
|
// ---------------------------------------------------------------- Private
|
||||||
|
|
||||||
private Object getOwnerForPut()
|
private Object getOwnerForPut() {
|
||||||
{
|
|
||||||
Transaction tx = null;
|
Transaction tx = null;
|
||||||
try {
|
try {
|
||||||
if (transactionManager != null) {
|
if (transactionManager != null) {
|
||||||
|
@ -319,20 +339,17 @@ public class PutFromLoadValidator
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void preventOutdatedPendingPuts(PendingPut pendingPut)
|
private void preventOutdatedPendingPuts(PendingPut pendingPut) {
|
||||||
{
|
|
||||||
pendingLock.lock();
|
pendingLock.lock();
|
||||||
try {
|
try {
|
||||||
pendingQueue.add(new WeakReference<PendingPut>(pendingPut));
|
pendingQueue.add(new WeakReference<PendingPut>(pendingPut));
|
||||||
cleanOutdatedPendingPuts(pendingPut.timestamp, false);
|
cleanOutdatedPendingPuts(pendingPut.timestamp, false);
|
||||||
}
|
} finally {
|
||||||
finally {
|
|
||||||
pendingLock.unlock();
|
pendingLock.unlock();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void cleanOutdatedPendingPuts(long now, boolean lock)
|
private void cleanOutdatedPendingPuts(long now, boolean lock) {
|
||||||
{
|
|
||||||
|
|
||||||
PendingPut toClean = null;
|
PendingPut toClean = null;
|
||||||
if (lock) {
|
if (lock) {
|
||||||
|
@ -351,21 +368,17 @@ public class PutFromLoadValidator
|
||||||
PendingPut item = ref.get();
|
PendingPut item = ref.get();
|
||||||
if (item == null || item.completed) {
|
if (item == null || item.completed) {
|
||||||
pendingQueue.remove(pos);
|
pendingQueue.remove(pos);
|
||||||
}
|
} else if (item.timestamp < overaged) {
|
||||||
else if (item.timestamp < overaged) {
|
|
||||||
// Potential leak; move to the overaged queued
|
// Potential leak; move to the overaged queued
|
||||||
pendingQueue.remove(pos);
|
pendingQueue.remove(pos);
|
||||||
overagePendingQueue.add(ref);
|
overagePendingQueue.add(ref);
|
||||||
}
|
} else if (item.timestamp >= recent) {
|
||||||
else if (item.timestamp >= recent) {
|
|
||||||
// Don't waste time on very recent items
|
// Don't waste time on very recent items
|
||||||
break;
|
break;
|
||||||
}
|
} else if (pos > 2) {
|
||||||
else if (pos > 2) {
|
|
||||||
// Don't spend too much time getting nowhere
|
// Don't spend too much time getting nowhere
|
||||||
break;
|
break;
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
// Move on to the next item
|
// Move on to the next item
|
||||||
pos++;
|
pos++;
|
||||||
}
|
}
|
||||||
|
@ -380,8 +393,7 @@ public class PutFromLoadValidator
|
||||||
PendingPut item = ref.get();
|
PendingPut item = ref.get();
|
||||||
if (item == null || item.completed) {
|
if (item == null || item.completed) {
|
||||||
overagePendingQueue.remove(0);
|
overagePendingQueue.remove(0);
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
if (item.timestamp < mustCleanTime) {
|
if (item.timestamp < mustCleanTime) {
|
||||||
overagePendingQueue.remove(0);
|
overagePendingQueue.remove(0);
|
||||||
toClean = item;
|
toClean = item;
|
||||||
|
@ -389,8 +401,7 @@ public class PutFromLoadValidator
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
} finally {
|
||||||
finally {
|
|
||||||
if (lock) {
|
if (lock) {
|
||||||
pendingLock.unlock();
|
pendingLock.unlock();
|
||||||
}
|
}
|
||||||
|
@ -405,8 +416,7 @@ public class PutFromLoadValidator
|
||||||
if (toClean.equals(cleaned) == false) {
|
if (toClean.equals(cleaned) == false) {
|
||||||
// Oops. Restore it.
|
// Oops. Restore it.
|
||||||
map.put(cleaned);
|
map.put(cleaned);
|
||||||
}
|
} else if (map.size() == 0) {
|
||||||
else if (map.size() == 0) {
|
|
||||||
pendingPuts.remove(toClean.key);
|
pendingPuts.remove(toClean.key);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -416,29 +426,25 @@ public class PutFromLoadValidator
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Lazy-initialization map for PendingPut. Optimized
|
* Lazy-initialization map for PendingPut. Optimized for the expected usual
|
||||||
* for the expected usual case where only a single put
|
* case where only a single put is pending for a given key.
|
||||||
* is pending for a given key.
|
|
||||||
*
|
*
|
||||||
* This class is NOT THREAD SAFE. All operations on it
|
* This class is NOT THREAD SAFE. All operations on it must be performed
|
||||||
* must be performed with the object monitor held.
|
* with the object monitor held.
|
||||||
*/
|
*/
|
||||||
private static class PendingPutMap {
|
private static class PendingPutMap {
|
||||||
private PendingPut singlePendingPut;
|
private PendingPut singlePendingPut;
|
||||||
private Map<Object, PendingPut> fullMap;
|
private Map<Object, PendingPut> fullMap;
|
||||||
|
|
||||||
public void put(PendingPut pendingPut)
|
public void put(PendingPut pendingPut) {
|
||||||
{
|
|
||||||
if (singlePendingPut == null) {
|
if (singlePendingPut == null) {
|
||||||
if (fullMap == null) {
|
if (fullMap == null) {
|
||||||
// initial put
|
// initial put
|
||||||
singlePendingPut = pendingPut;
|
singlePendingPut = pendingPut;
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
fullMap.put(pendingPut.owner, pendingPut);
|
fullMap.put(pendingPut.owner, pendingPut);
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
// 2nd put; need a map
|
// 2nd put; need a map
|
||||||
fullMap = new HashMap<Object, PendingPut>(4);
|
fullMap = new HashMap<Object, PendingPut>(4);
|
||||||
fullMap.put(singlePendingPut.owner, singlePendingPut);
|
fullMap.put(singlePendingPut.owner, singlePendingPut);
|
||||||
|
@ -447,24 +453,23 @@ public class PutFromLoadValidator
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public PendingPut remove(Object ownerForPut)
|
public PendingPut remove(Object ownerForPut) {
|
||||||
{
|
|
||||||
PendingPut removed = null;
|
PendingPut removed = null;
|
||||||
if (fullMap == null) {
|
if (fullMap == null) {
|
||||||
if (singlePendingPut != null && singlePendingPut.owner.equals(ownerForPut)) {
|
if (singlePendingPut != null
|
||||||
|
&& singlePendingPut.owner.equals(ownerForPut)) {
|
||||||
removed = singlePendingPut;
|
removed = singlePendingPut;
|
||||||
singlePendingPut = null;
|
singlePendingPut = null;
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
removed = fullMap.remove(ownerForPut);
|
removed = fullMap.remove(ownerForPut);
|
||||||
}
|
}
|
||||||
return removed;
|
return removed;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int size()
|
public int size() {
|
||||||
{
|
return fullMap == null ? (singlePendingPut == null ? 0 : 1)
|
||||||
return fullMap == null ? (singlePendingPut == null ? 0 : 1) : fullMap.size();
|
: fullMap.size();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -487,7 +492,8 @@ public class PutFromLoadValidator
|
||||||
|
|
||||||
private RecentRemoval(Object key, long nakedPutInvalidationPeriod) {
|
private RecentRemoval(Object key, long nakedPutInvalidationPeriod) {
|
||||||
this.key = key;
|
this.key = key;
|
||||||
timestamp = Long.valueOf(System.currentTimeMillis() + nakedPutInvalidationPeriod);
|
timestamp = Long.valueOf(System.currentTimeMillis()
|
||||||
|
+ nakedPutInvalidationPeriod);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue