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:
Brian Stansberry 2009-10-08 19:43:00 +00:00
parent 2ad3cfb6c0
commit 0ddf421e78
1 changed files with 438 additions and 432 deletions

View File

@ -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);
} }
} }