Author: manik.surtani(a)jboss.com
Date: 2009-03-05 12:20:15 -0500 (Thu, 05 Mar 2009)
New Revision: 7862
Modified:
core/branches/flat/src/main/java/org/horizon/container/CachedValue.java
core/branches/flat/src/main/java/org/horizon/container/DataContainer.java
core/branches/flat/src/main/java/org/horizon/container/ExpirableCachedValue.java
core/branches/flat/src/main/java/org/horizon/container/UnsortedDataContainer.java
core/branches/flat/src/main/java/org/horizon/factories/EntryFactoryImpl.java
core/branches/flat/src/main/java/org/horizon/loader/StoredEntry.java
core/branches/flat/src/main/java/org/horizon/remoting/RPCManager.java
core/branches/flat/src/main/java/org/horizon/remoting/transport/Transport.java
Log:
Minor performance tweaks after a brief profiling session
Modified: core/branches/flat/src/main/java/org/horizon/container/CachedValue.java
===================================================================
--- core/branches/flat/src/main/java/org/horizon/container/CachedValue.java 2009-03-05
16:24:07 UTC (rev 7861)
+++ core/branches/flat/src/main/java/org/horizon/container/CachedValue.java 2009-03-05
17:20:15 UTC (rev 7862)
@@ -27,4 +27,8 @@
public final void setValue(Object value) {
this.value = value;
}
+
+ public long getLifespan() {
+ return -1;
+ }
}
\ No newline at end of file
Modified: core/branches/flat/src/main/java/org/horizon/container/DataContainer.java
===================================================================
--- core/branches/flat/src/main/java/org/horizon/container/DataContainer.java 2009-03-05
16:24:07 UTC (rev 7861)
+++ core/branches/flat/src/main/java/org/horizon/container/DataContainer.java 2009-03-05
17:20:15 UTC (rev 7862)
@@ -60,5 +60,7 @@
StoredEntry createEntryForStorage(Object key);
+ CachedValue getEntry(Object k);
+
Set<StoredEntry> getAllEntriesForStorage();
}
Modified:
core/branches/flat/src/main/java/org/horizon/container/ExpirableCachedValue.java
===================================================================
---
core/branches/flat/src/main/java/org/horizon/container/ExpirableCachedValue.java 2009-03-05
16:24:07 UTC (rev 7861)
+++
core/branches/flat/src/main/java/org/horizon/container/ExpirableCachedValue.java 2009-03-05
17:20:15 UTC (rev 7862)
@@ -34,4 +34,10 @@
public final void setLifespan(long lifespan) {
expiryTime = lifespan < 0 ? -1 : lifespan + createdTime;
}
+
+ @Override
+ public final long getLifespan() {
+ if (createdTime < 0 || expiryTime < 0) return -1;
+ return expiryTime - createdTime;
+ }
}
\ No newline at end of file
Modified:
core/branches/flat/src/main/java/org/horizon/container/UnsortedDataContainer.java
===================================================================
---
core/branches/flat/src/main/java/org/horizon/container/UnsortedDataContainer.java 2009-03-05
16:24:07 UTC (rev 7861)
+++
core/branches/flat/src/main/java/org/horizon/container/UnsortedDataContainer.java 2009-03-05
17:20:15 UTC (rev 7862)
@@ -46,6 +46,7 @@
* @since 1.0
*/
public class UnsortedDataContainer implements DataContainer {
+ // TODO this should ideally have its own hash table rather than delegate to a
concurrent map, which in turn will wrap things up in Entries again. Remove this
unneccessary delegation
// data with expiry and without expiry are stored in different maps, for efficiency.
E.g., so that when purging expired
// stuff, we don't need to iterate through immortal data.
final ConcurrentMap<Object, CachedValue> immortalData = new
ConcurrentHashMap<Object, CachedValue>();
@@ -205,9 +206,22 @@
return new StoredEntry(key, ecv.getValue(), ecv.getCreatedTime(),
ecv.getExpiryTime());
}
+ public CachedValue getEntry(Object key) {
+ CachedValue immortal = immortalData.get(key);
+ if (immortal != null)
+ return immortal;
+ ExpirableCachedValue ecv = expirableData.get(key);
+ if (ecv == null) return null;
+ if (ecv.isExpired()) {
+ expirableData.remove(key);
+ return null;
+ }
+ return ecv;
+ }
+
public Set<StoredEntry> getAllEntriesForStorage() {
Set<StoredEntry> set = new HashSet<StoredEntry>(immortalData.size() +
expirableData.size());
- for (Map.Entry<Object, CachedValue> entry: immortalData.entrySet())
+ for (Map.Entry<Object, CachedValue> entry : immortalData.entrySet())
set.add(new StoredEntry(entry.getKey(), entry.getValue().getValue()));
for (Iterator<Map.Entry<Object, ExpirableCachedValue>> it =
expirableData.entrySet().iterator(); it.hasNext();) {
Modified: core/branches/flat/src/main/java/org/horizon/factories/EntryFactoryImpl.java
===================================================================
---
core/branches/flat/src/main/java/org/horizon/factories/EntryFactoryImpl.java 2009-03-05
16:24:07 UTC (rev 7861)
+++
core/branches/flat/src/main/java/org/horizon/factories/EntryFactoryImpl.java 2009-03-05
17:20:15 UTC (rev 7862)
@@ -22,6 +22,7 @@
package org.horizon.factories;
import org.horizon.config.Configuration;
+import org.horizon.container.CachedValue;
import org.horizon.container.DataContainer;
import org.horizon.container.MVCCEntry;
import org.horizon.container.NullMarkerEntry;
@@ -31,7 +32,6 @@
import org.horizon.factories.annotations.Inject;
import org.horizon.factories.annotations.Start;
import org.horizon.invocation.Options;
-import org.horizon.loader.StoredEntry;
import org.horizon.lock.IsolationLevel;
import org.horizon.lock.LockManager;
import org.horizon.lock.TimeoutException;
@@ -65,17 +65,17 @@
writeSkewCheck = configuration.isWriteSkewCheck();
}
- public MVCCEntry createWrappedEntry(Object key, Object value, boolean isForInsert,
long lifespan) {
+ public final MVCCEntry createWrappedEntry(Object key, Object value, boolean
isForInsert, long lifespan) {
if (value == null && !isForInsert) return useRepeatableRead ? NULL_MARKER :
null;
return useRepeatableRead ? new RepeatableReadEntry(key, value, lifespan) : new
ReadCommittedEntry(key, value, lifespan);
}
- public MVCCEntry wrapEntryForReading(InvocationContext ctx, Object key, boolean
putInContext) throws InterruptedException {
+ public final MVCCEntry wrapEntryForReading(InvocationContext ctx, Object key, boolean
putInContext) throws InterruptedException {
return wrapEntryForReading(ctx, key, putInContext, false);
}
- public MVCCEntry wrapEntryForReading(InvocationContext ctx, Object key, boolean
putInContext, boolean forceWriteLock) throws InterruptedException {
+ public final MVCCEntry wrapEntryForReading(InvocationContext ctx, Object key, boolean
putInContext, boolean forceWriteLock) throws InterruptedException {
// TODO: Do we need to wrap for reading if we are not in a TX?
// TODO: Also, do we need to wrap for reading even IN a TX if we are using
read-committed?
@@ -86,7 +86,7 @@
} else if ((mvccEntry = ctx.lookupEntry(key)) == null) {
if (trace) log.trace("Key " + key + " is not in context, fetching
from container.");
// simple implementation. Peek the entry, wrap it, put wrapped entry in the
context.
- StoredEntry se = container.createEntryForStorage(key);
+ CachedValue se = container.getEntry(key);
mvccEntry = se == null ?
createWrappedEntry(key, null, false, -1) :
createWrappedEntry(key, se.getValue(), false, se.getLifespan());
@@ -98,7 +98,7 @@
}
}
- public MVCCEntry wrapEntryForWriting(InvocationContext ctx, Object key, boolean
createIfAbsent, boolean forceLockIfAbsent) throws InterruptedException {
+ public final MVCCEntry wrapEntryForWriting(InvocationContext ctx, Object key, boolean
createIfAbsent, boolean forceLockIfAbsent) throws InterruptedException {
MVCCEntry mvccEntry = ctx.lookupEntry(key);
if (createIfAbsent && mvccEntry != null && mvccEntry.isNullEntry())
mvccEntry = null;
if (mvccEntry != null) // exists in context! Just acquire lock if needed, and
wrap.
@@ -116,14 +116,14 @@
}
} else {
// else, fetch from dataContainer.
- StoredEntry storedEntry = container.createEntryForStorage(key);
- if (storedEntry != null) {
+ CachedValue cachedValue = container.getEntry(key);
+ if (cachedValue != null) {
if (trace) log.trace("Retrieved from container.");
// exists in cache! Just acquire lock if needed, and wrap.
// do we need a lock?
boolean needToCopy = false;
if (acquireLock(ctx, key)) needToCopy = true;
- mvccEntry = createWrappedEntry(key, storedEntry.getValue(), false,
storedEntry.getLifespan());
+ mvccEntry = createWrappedEntry(key, cachedValue.getValue(), false,
cachedValue.getLifespan());
ctx.putLookedUpEntry(key, mvccEntry);
if (needToCopy) mvccEntry.copyForUpdate(container, writeSkewCheck);
} else if (createIfAbsent) {
@@ -147,7 +147,8 @@
}
/**
- * Attempts to lock an entry if the lock isn't already held in the current scope,
and records the lock in the context.
+ * Attempts to lock an entry if the lock isn't already held in the current scope,
and records the lock in the
+ * context.
*
* @param ctx context
* @param key Key to lock
@@ -157,7 +158,7 @@
* @throws org.horizon.lock.TimeoutException
* if we are unable to acquire the lock after a specified
timeout.
*/
- public boolean acquireLock(InvocationContext ctx, Object key) throws
InterruptedException, TimeoutException {
+ public final boolean acquireLock(InvocationContext ctx, Object key) throws
InterruptedException, TimeoutException {
// don't EVER use lockManager.isLocked() since with lock striping it may be the
case that we hold the relevant
// lock which may be shared with another key that we have a lock for already.
// nothing wrong, just means that we fail to record the lock. And that is a
problem.
@@ -181,7 +182,7 @@
0 : configuration.getLockAcquisitionTimeout();
}
- public void releaseLock(InvocationContext ctx, Object key) {
+ public final void releaseLock(InvocationContext ctx, Object key) {
lockManager.unlock(key, lockManager.getOwner(key));
ctx.removeKeyLocked(key);
}
Modified: core/branches/flat/src/main/java/org/horizon/loader/StoredEntry.java
===================================================================
--- core/branches/flat/src/main/java/org/horizon/loader/StoredEntry.java 2009-03-05
16:24:07 UTC (rev 7861)
+++ core/branches/flat/src/main/java/org/horizon/loader/StoredEntry.java 2009-03-05
17:20:15 UTC (rev 7862)
@@ -38,11 +38,6 @@
return key;
}
- public final long getLifespan() {
- if (createdTime < 0 || expiryTime < 0) return -1;
- return expiryTime - createdTime;
- }
-
@Override
public boolean equals(Object o) {
if (this == o) return true;
Modified: core/branches/flat/src/main/java/org/horizon/remoting/RPCManager.java
===================================================================
--- core/branches/flat/src/main/java/org/horizon/remoting/RPCManager.java 2009-03-05
16:24:07 UTC (rev 7861)
+++ core/branches/flat/src/main/java/org/horizon/remoting/RPCManager.java 2009-03-05
17:20:15 UTC (rev 7862)
@@ -45,7 +45,7 @@
@Scope(Scopes.GLOBAL)
@NonVolatile
public interface RPCManager extends Lifecycle {
-
+ // TODO this needs to be re-thought regarding adding a transport-independent mechanism
of unicasts for distribution based on consistent hashes
/**
* Invokes an RPC call on other caches in the cluster.
*
Modified: core/branches/flat/src/main/java/org/horizon/remoting/transport/Transport.java
===================================================================
---
core/branches/flat/src/main/java/org/horizon/remoting/transport/Transport.java 2009-03-05
16:24:07 UTC (rev 7861)
+++
core/branches/flat/src/main/java/org/horizon/remoting/transport/Transport.java 2009-03-05
17:20:15 UTC (rev 7862)
@@ -27,6 +27,7 @@
@Scope(Scopes.GLOBAL)
@NonVolatile
public interface Transport extends Lifecycle {
+ // TODO discovery should be abstracted away into a separate set of interfaces such
that it is not tightly coupled to the transport
/**
* Initializes the transport with global cache configuration and transport-specific
properties.