You are viewing a plain text version of this content. The canonical link for it is here.
Posted to slide-dev@jakarta.apache.org by oz...@apache.org on 2004/05/06 11:17:54 UTC
cvs commit: jakarta-slide/src/share/org/apache/slide/store Store.java AbstractStore.java ExtendedStore.java
ozeigermann 2004/05/06 02:17:54
Modified: src/share/org/apache/slide/store Store.java
AbstractStore.java ExtendedStore.java
Log:
Added transient locks to avoid deadlocks when more than
one client uploads data.
Revision Changes Path
1.11 +12 -4 jakarta-slide/src/share/org/apache/slide/store/Store.java
Index: Store.java
===================================================================
RCS file: /home/cvs/jakarta-slide/src/share/org/apache/slide/store/Store.java,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -r1.10 -r1.11
--- Store.java 4 May 2004 12:06:26 -0000 1.10
+++ Store.java 6 May 2004 09:17:54 -0000 1.11
@@ -123,4 +123,12 @@
*/
boolean useBinding();
+ /**
+ * Acquires an exclusive access lock to a resource. This lock is transient, i.e. it will
+ * automatically be released when your transaction terminates.
+ *
+ * @param uri the URI of the resource you want to have exclusive access to
+ * @throws ServiceAccessException thrown if anything goes wrong, including the lock can not be acquired
+ */
+ void exclusiveTransientLock(String uri) throws ServiceAccessException;
}
1.41 +8 -4 jakarta-slide/src/share/org/apache/slide/store/AbstractStore.java
Index: AbstractStore.java
===================================================================
RCS file: /home/cvs/jakarta-slide/src/share/org/apache/slide/store/AbstractStore.java,v
retrieving revision 1.40
retrieving revision 1.41
diff -u -r1.40 -r1.41
--- AbstractStore.java 4 May 2004 12:06:26 -0000 1.40
+++ AbstractStore.java 6 May 2004 09:17:54 -0000 1.41
@@ -1612,4 +1612,8 @@
public boolean useBinding() {
return false;
}
+
+ public void exclusiveTransientLock(String uri) throws ServiceAccessException {
+ }
+
}
1.10 +83 -5 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.9
retrieving revision 1.10
diff -u -r1.9 -r1.10
--- ExtendedStore.java 5 May 2004 12:07:30 -0000 1.9
+++ ExtendedStore.java 6 May 2004 09:17:54 -0000 1.10
@@ -24,7 +24,9 @@
package org.apache.slide.store;
import java.util.Enumeration;
+import java.util.HashSet;
import java.util.Hashtable;
+import java.util.Iterator;
import java.util.Vector;
import org.apache.slide.common.ServiceAccessException;
@@ -40,17 +42,24 @@
import org.apache.slide.content.RevisionNotFoundException;
import org.apache.slide.lock.LockTokenNotFoundException;
import org.apache.slide.lock.NodeLock;
+import org.apache.slide.macro.ConflictException;
import org.apache.slide.security.NodePermission;
import org.apache.slide.structure.LinkNode;
import org.apache.slide.structure.ObjectAlreadyExistsException;
import org.apache.slide.structure.ObjectNode;
import org.apache.slide.structure.ObjectNotFoundException;
-import org.apache.slide.util.*;
+import org.apache.slide.util.ByteSizeLimitedObjectCache;
import org.apache.slide.util.ObjectCache;
+import org.apache.slide.util.TxLRUObjectCache;
+import org.apache.slide.util.XidWrapper;
import javax.transaction.xa.XAException;
import javax.transaction.xa.Xid;
+
+import org.apache.slide.util.locking.impl.GenericLock;
+import org.apache.slide.util.locking.impl.GenericLockManager;
import org.apache.slide.util.logger.Logger;
+import org.apache.slide.util.logger.StoreLogger;
/**
* Store that allows for transactional caching of data. Takes over much modified code from StandardStore.
@@ -104,6 +113,9 @@
protected static final String CACHE_MODE_OFF = "off";
protected static final String DEFAULT_CACHE_MODE = CACHE_MODE_FULL;
+ protected static final int DEFAULT_TLOCK_TIMEOUT = 20000; // 20 sec
+ protected static final String TLOCK_TIMEOUT_PARAMETER = "tlock-timeout";
+
// there might be at least one active transaction branch per thread
protected ThreadLocal activeTransactionBranch = new ThreadLocal();
@@ -114,8 +126,17 @@
protected TxCacheWrapper descriptorsCache;
protected TxCacheWrapper descriptorCache;
+ protected GenericLockManager lockManager;
+ protected ThreadLocal locks = new ThreadLocal();
+ protected long timeout;
+
protected boolean globalCacheOff;
+
+ public ExtendedStore() {
+ lockManager = new GenericLockManager(1, new StoreLogger(getLogger(), LOG_CHANNEL));
+ }
+
public void setParameters(Hashtable parameters)
throws ServiceParameterErrorException, ServiceParameterMissingException {
super.setParameters(parameters);
@@ -132,6 +153,17 @@
long txContentCacheBytes = DEFAULT_TX_CONTENT_CACHE_BYTES;
long maxByteSizePerEntry = DEFAULT_MAX_CONTENT_BYTES_PER_ENTRY;
+ timeout = DEFAULT_TLOCK_TIMEOUT;
+ String timeoutString = (String) parameters.get(TLOCK_TIMEOUT_PARAMETER);
+ if (timeoutString != null) {
+ try {
+ timeout = Integer.parseInt(timeoutString) * 1000;
+ } catch (NumberFormatException nfe) {
+ getLogger().log("TLock timeout must be integer! Using default value", LOG_CHANNEL, Logger.WARNING);
+ }
+ }
+ getLogger().log("Setting TLock timeout for store " + getName() + " to " + timeout / 1000 + " seconds", Logger.INFO);
+
String globalObjectCacheSizeString = (String) parameters.get(GLOBAL_OBJECT_CACHE_SIZE_PARAMETER);
if (globalObjectCacheSizeString != null) {
try {
@@ -340,6 +372,31 @@
noGlobalCacheInTx);
}
+ public void exclusiveTransientLock(String uri) throws ServiceAccessException {
+ Xid txId = (Xid) activeTransactionBranch.get();
+ try {
+ GenericLock lock = (GenericLock) lockManager.atomicGetOrCreateLock(uri);
+ if (lock.getLockLevel(txId) != 1) {
+ Object owner = lock.getOwner();
+ getLogger().log(
+ "Try lock: "
+ + txId
+ + " tries "
+ + uri
+ + (owner != null ? " ---> " + owner.toString() + " has it" : ""),
+ LOG_CHANNEL,
+ Logger.DEBUG);
+ if (!lock.acquire(txId, 1, true, true, timeout)) {
+ throw new ServiceAccessException(this, new ConflictException(uri));
+ }
+ ((HashSet)locks.get()).add(lock);
+ getLogger().log("Has lock: " + txId + " locks " + uri, LOG_CHANNEL, Logger.DEBUG);
+ }
+ } catch (InterruptedException e) {
+ throw new ServiceAccessException(this, new ConflictException(uri));
+ }
+ }
+
//
// overloaded content methods with caching
//
@@ -825,6 +882,8 @@
//
public void forget(Xid xid) throws XAException {
+ releaseTransientLocks();
+
Xid txId = (Xid) XidWrapper.wrap(xid);
activeTransactionBranch.set(null);
@@ -838,6 +897,8 @@
}
public void rollback(Xid xid) throws XAException {
+ releaseTransientLocks();
+
Xid txId = (Xid) XidWrapper.wrap(xid);
activeTransactionBranch.set(null);
@@ -851,6 +912,8 @@
}
public void commit(Xid xid, boolean onePhase) throws XAException {
+ releaseTransientLocks();
+
Xid txId = (Xid) XidWrapper.wrap(xid);
activeTransactionBranch.set(null);
@@ -874,6 +937,8 @@
Xid txId = (Xid) XidWrapper.wrap(xid);
activeTransactionBranch.set(txId);
+ locks.set(new HashSet());
+
objectsCache.getTxCache().start(txId);
permissionsCache.getTxCache().start(txId);
locksCache.getTxCache().start(txId);
@@ -891,6 +956,19 @@
public String toString() {
return getName() + "(" + getClass().getName() + ")";
+ }
+
+ protected void releaseTransientLocks() {
+
+ Xid txId = (Xid) activeTransactionBranch.get();
+ for (Iterator it = ((HashSet)locks.get()).iterator(); it.hasNext();) {
+ GenericLock lock = (GenericLock) it.next();
+ lock.release(txId);
+ getLogger().log(
+ "Release lock: " + txId + " released " + lock.getResourceId().toString(),
+ LOG_CHANNEL,
+ Logger.DEBUG);
+ }
}
protected Vector fillPermissionsCache(Uri uri) throws ServiceAccessException {
---------------------------------------------------------------------
To unsubscribe, e-mail: slide-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: slide-dev-help@jakarta.apache.org