ozeigermann 2004/02/20 03:13:23
Modified: src/share/org/apache/slide/util TxLRUObjectCache.java
src/share/org/apache/slide/store ExtendedStore.java
Log:
Added new local cache mode that allows to use
databases isolation and clustering.
The trick is to skip global inter-tx caching completely and only rely on
intra-tx caching. This means every resource accessed is retrieved from
the database and only repeated requests inside a transaction will be
cached. This allows for the database to apply whatever isolation it has.
Additionally, it allows for clustered solutions as caches are only help for
the duration of a transaction.
Global entries that may get invalid when another cluster node updates
them do not exist, so they are no problem.
Revision Changes Path
1.3 +52 -39
jakarta-slide/src/share/org/apache/slide/util/TxLRUObjectCache.java
Index: TxLRUObjectCache.java
===================================================================
RCS file:
/home/cvs/jakarta-slide/src/share/org/apache/slide/util/TxLRUObjectCache.java,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- TxLRUObjectCache.java 11 Feb 2004 11:30:20 -0000 1.2
+++ TxLRUObjectCache.java 20 Feb 2004 11:13:23 -0000 1.3
@@ -54,7 +54,7 @@
*/
public class TxLRUObjectCache {
- protected Map globalCache;
+ protected Map globalCache = null;
protected Map txChangeCaches;
protected Map txDeleteCaches;
@@ -68,14 +68,19 @@
protected final boolean loggingEnabled;
/**
- * Creates a new object cache.
+ * Creates a new object cache. If global caching is disabled, the cache
+ * reflects isolation of underlying store as only double reads inside a single
transaction
+ * will be cached. This may even increase isolation as repeatable read is
guaranteed.
*
- * @param globalCacheSize maximum size in objects of global cache
+ * @param globalCacheSize maximum size in objects of global cache or
<code>-1</code> to indicate no
+ * global cache shall be used
* @param name the name used to construct logging category / channel
* @param logger Slide logger to be used for logging
*/
public TxLRUObjectCache(int globalCacheSize, String name, Logger logger) {
- globalCache = new LRUMap(globalCacheSize);
+ if (globalCacheSize != -1) {
+ globalCache = new LRUMap(globalCacheSize);
+ }
txChangeCaches = new HashMap();
txDeleteCaches = new HashMap();
@@ -96,7 +101,7 @@
}
public synchronized void clear() {
- globalCache.clear();
+ if (globalCache != null) globalCache.clear();
txChangeCaches.clear();
txDeleteCaches.clear();
}
@@ -118,7 +123,9 @@
return changed;
}
}
-
+
+ if (globalCache == null) return null;
+
// as fall back return value from global cache (if present)
Object global = globalCache.get(key);
if (global != null) {
@@ -142,9 +149,11 @@
logger.log(txId + " added '" + key + "'", logChannel, Logger.DEBUG);
}
} else {
- globalCache.put(key, value);
- if (loggingEnabled) {
- logger.log("Added '" + key + "'", logChannel, Logger.DEBUG);
+ if (globalCache != null) {
+ globalCache.put(key, value);
+ if (loggingEnabled) {
+ logger.log("Added '" + key + "'", logChannel, Logger.DEBUG);
+ }
}
}
}
@@ -163,9 +172,11 @@
logger.log(txId + " removed '" + key + "'", logChannel,
Logger.DEBUG);
}
} else {
- globalCache.remove(key);
- if (loggingEnabled) {
- logger.log("Removed '" + key + "'", logChannel, Logger.DEBUG);
+ if (globalCache != null) {
+ globalCache.remove(key);
+ if (loggingEnabled) {
+ logger.log("Removed '" + key + "'", logChannel, Logger.DEBUG);
+ }
}
}
}
@@ -201,32 +212,34 @@
public synchronized void commit(Object txId) {
if (txId != null) {
- // apply local changes and deletes (is atomic as we have a global lock
on this TxCache)
- Map changeCache = (Map) txChangeCaches.get(txId);
- for (Iterator it = changeCache.entrySet().iterator(); it.hasNext();) {
- Map.Entry entry = (Map.Entry) it.next();
- globalCache.put(entry.getKey(), entry.getValue());
- }
+ if (globalCache != null) {
+ // apply local changes and deletes (is atomic as we have a global
lock on this TxCache)
- Set deleteCache = (Set) txDeleteCaches.get(txId);
- for (Iterator it = deleteCache.iterator(); it.hasNext();) {
- Object key = it.next();
- globalCache.remove(key);
- }
+ Map changeCache = (Map) txChangeCaches.get(txId);
+ for (Iterator it = changeCache.entrySet().iterator();
it.hasNext();) {
+ Map.Entry entry = (Map.Entry) it.next();
+ globalCache.put(entry.getKey(), entry.getValue());
+ }
- if (loggingEnabled) {
- logger.log(
- txId
- + " committed "
- + changeCache.size()
- + " changes and "
- + deleteCache.size()
- + " scheduled deletes",
- logChannel,
- Logger.DEBUG);
+ Set deleteCache = (Set) txDeleteCaches.get(txId);
+ for (Iterator it = deleteCache.iterator(); it.hasNext();) {
+ Object key = it.next();
+ globalCache.remove(key);
+ }
+
+ if (loggingEnabled) {
+ logger.log(
+ txId
+ + " committed "
+ + changeCache.size()
+ + " changes and "
+ + deleteCache.size()
+ + " scheduled deletes",
+ logChannel,
+ Logger.DEBUG);
+ }
}
-
// finally forget about tx
forget(txId);
}
@@ -267,7 +280,7 @@
+ " / "
+ misses
+ " / "
- + globalCache.size());
+ + (globalCache != null ? globalCache.size() : -1));
logger.log(log.toString(), logChannel, Logger.DEBUG);
}
}
1.5 +39 -4
jakarta-slide/src/share/org/apache/slide/store/ExtendedStore.java
Index: ExtendedStore.java
===================================================================
RCS file:
/home/cvs/jakarta-slide/src/share/org/apache/slide/store/ExtendedStore.java,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -r1.4 -r1.5
--- ExtendedStore.java 11 Feb 2004 11:30:18 -0000 1.4
+++ ExtendedStore.java 20 Feb 2004 11:13:23 -0000 1.5
@@ -99,6 +99,12 @@
protected static final long DEFAULT_MAX_CONTENT_BYTES_PER_ENTRY = 50000; // 50 K
protected static final String MAX_CONTENT_BYTES_PER_ENTRY_PARAMETER =
"max-content-bytes-per-entry";
+ protected static final String CACHE_MODE_PARAMETER = "cache-mode";
+ protected static final String CACHE_MODE_FULL = "full";
+ protected static final String CACHE_MODE_LOCAL = "cluster";
+ protected static final String CACHE_MODE_FULL_NO_TX = "isolation-shadow";
+ protected static final String DEFAULT_CACHE_MODE = CACHE_MODE_FULL;
+
// there might be at least one active transaction branch per thread
protected ThreadLocal activeTransactionBranch = new ThreadLocal();
@@ -274,6 +280,35 @@
"Setting maximum byte size for content cache entry for store " +
getName() + " to " + maxByteSizePerEntry,
LOG_CHANNEL,
Logger.INFO);
+
+ String cacheModeString = (String) parameters.get(CACHE_MODE_PARAMETER);
+ if (cacheModeString == null) cacheModeString = DEFAULT_CACHE_MODE;
+ cacheModeString = cacheModeString.trim();
+
+ boolean noGlobalCache;
+ if (cacheModeString.equals(CACHE_MODE_FULL)) {
+ noGlobalCache = false;
+ getLogger().log("Enabling full caching causing low isolation",
LOG_CHANNEL, Logger.INFO);
+ } else if (cacheModeString.equals(CACHE_MODE_LOCAL)) {
+ noGlobalCache = true;
+ getLogger().log("Disabling global cache to shadow store isolation and
allow for clustering", LOG_CHANNEL, Logger.INFO);
+ } else if (cacheModeString.equals(CACHE_MODE_FULL_NO_TX)) {
+ noGlobalCache = true;
+ getLogger().log("Cache mode isolation shadow not yet implemented! Using
cluster mode instead...", LOG_CHANNEL, Logger.WARNING);
+ } else {
+ noGlobalCache = false;
+ getLogger().log("Unknown cache mode "+cacheModeString+" Using full mode
instead...", LOG_CHANNEL, Logger.WARNING);
+ }
+
+ // disable global cache if desired
+ if (noGlobalCache) {
+ globalObjectCacheSize = -1;
+ globalPermissionCacheSize = -1;
+ globalLockCacheSize = -1;
+ globalDescrtiptorsCacheSize = -1;
+ globalDescrtiptorCacheSize = -1;
+ contentCachingEnabled = false;
+ }
init(
globalObjectCacheSize,
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]