use of javax.jcr.lock.Lock in project jackrabbit by apache.
the class Locked method with.
/**
* Executes the method {@link #run} within the scope of a lock held on
* <code>lockable</code>.
*
* @param lockable the node where the lock is obtained from.
* @param isDeep <code>true</code> if <code>lockable</code> will be locked
* deep.
* @param timeout time in milliseconds to wait at most to aquire the lock.
* @return the object returned by {@link #run} or {@link #TIMED_OUT} if the
* lock on <code>lockable</code> could not be aquired within the
* specified timeout.
* @throws IllegalArgumentException if <code>timeout</code> is negative or
* <code>lockable</code> is not
* <i>mix:lockable</i>.
* @throws RepositoryException if {@link #run} throws an exception.
* @throws UnsupportedRepositoryOperationException
* if this repository does not support
* locking.
* @throws InterruptedException if this thread is interrupted while
* waiting for the lock on node
* <code>lockable</code>.
*/
public Object with(Node lockable, boolean isDeep, long timeout) throws UnsupportedRepositoryOperationException, RepositoryException, InterruptedException {
if (timeout < 0) {
throw new IllegalArgumentException("timeout must be >= 0");
}
Session session = lockable.getSession();
NamePathResolver resolver = new DefaultNamePathResolver(session);
Lock lock;
EventListener listener = null;
try {
// check whether the lockable can be locked at all
if (!lockable.isNodeType(resolver.getJCRName(NameConstants.MIX_LOCKABLE))) {
throw new IllegalArgumentException("Node is not lockable");
}
lock = tryLock(lockable, isDeep);
if (lock != null) {
return runAndUnlock(lock);
}
if (timeout == 0) {
return TIMED_OUT;
}
long timelimit;
if (timeout == Long.MAX_VALUE) {
timelimit = Long.MAX_VALUE;
} else {
timelimit = System.currentTimeMillis() + timeout;
}
// node is locked by other session -> register event listener if possible
if (isObservationSupported(session)) {
ObservationManager om = session.getWorkspace().getObservationManager();
listener = new EventListener() {
public void onEvent(EventIterator events) {
synchronized (this) {
this.notify();
}
}
};
om.addEventListener(listener, Event.PROPERTY_REMOVED, lockable.getPath(), false, null, null, true);
}
// the current thread when the lockable node is possibly unlocked
for (; ; ) {
synchronized (this) {
lock = tryLock(lockable, isDeep);
if (lock != null) {
return runAndUnlock(lock);
} else {
// check timeout
if (System.currentTimeMillis() > timelimit) {
return TIMED_OUT;
}
if (listener != null) {
// event listener *should* wake us up, however
// there is a chance that removal of the lockOwner
// property is notified before the node is acutally
// unlocked. therefore we use a safety net to wait
// at most 1000 millis.
this.wait(Math.min(1000, timeout));
} else {
// repository does not support observation
// wait at most 50 millis then retry
this.wait(Math.min(50, timeout));
}
}
}
}
} catch (NameException e) {
throw new RepositoryException(e);
} finally {
if (listener != null) {
session.getWorkspace().getObservationManager().removeEventListener(listener);
}
}
}
use of javax.jcr.lock.Lock in project jackrabbit by apache.
the class ConcurrentLockingWithTransactionsTest method testConcurrentCreateAndLockUnLockInTransaction.
public void testConcurrentCreateAndLockUnLockInTransaction() throws RepositoryException {
runTask(new Task() {
public void execute(Session session, Node test) throws RepositoryException {
// add versionable nodes
for (int i = 0; i < NUM_OPERATIONS / CONCURRENCY; i++) {
try {
final UserTransaction utx = new UserTransactionImpl(test.getSession());
utx.begin();
Node n = test.addNode("test" + i);
n.addMixin(mixLockable);
session.save();
Lock l = n.lock(false, true);
n.unlock();
utx.commit();
} catch (Exception e) {
final String threadName = Thread.currentThread().getName();
final Throwable deepCause = getLevel2Cause(e);
if (deepCause != null && deepCause instanceof StaleItemStateException) {
// ignore
} else {
throw new RepositoryException(threadName + ", i=" + i + ":" + e.getClass().getName(), e);
}
}
}
}
}, CONCURRENCY);
}
use of javax.jcr.lock.Lock in project jackrabbit by apache.
the class LockTimeoutTest method testExpired.
private void testExpired(boolean xa) throws Exception {
Session s = testRootNode.getSession();
Node n = testRootNode.addNode(nodeName1);
n.addMixin(mixLockable);
s.save();
UserTransaction utx = null;
if (xa) {
utx = new UserTransactionImpl(s);
utx.begin();
}
javax.jcr.lock.LockManager lm = s.getWorkspace().getLockManager();
boolean isDeep;
boolean isSessionScoped;
long timeoutHint;
String ownerInfo;
isDeep = false;
isSessionScoped = false;
timeoutHint = 1;
ownerInfo = "";
Session s2 = getHelper().getSuperuserSession();
Lock l = lm.lock(n.getPath(), isDeep, isSessionScoped, timeoutHint, ownerInfo);
// this works only for timeout = 1,
// as getSecondsRemaining always returns a positive value
assertEquals(timeoutHint, l.getSecondsRemaining());
assertTrue(l.isLive());
if (xa) {
utx.commit();
}
long start = System.currentTimeMillis();
while (true) {
Thread.sleep(100);
long now = System.currentTimeMillis();
boolean success;
try {
s2.getNode(n.getPath()).setProperty("x", 1);
s2.save();
success = true;
} catch (Exception e) {
success = false;
}
long t = now - start;
if (t > timeoutHint + 3000) {
assertTrue(success);
break;
} else if (t < timeoutHint) {
assertFalse(success);
}
}
n.remove();
s.save();
}
use of javax.jcr.lock.Lock in project jackrabbit by apache.
the class XATest method testCreateLockUnlockInDifferentTransactions.
/**
* Test locking and unlocking behavior in transaction
* (see JCR-2356)
* @throws Exception
*/
public void testCreateLockUnlockInDifferentTransactions() throws Exception {
// create new node and lock it
UserTransaction utx = new UserTransactionImpl(superuser);
utx.begin();
// add node that is both lockable and referenceable, save
Node rootNode = superuser.getRootNode();
Node n = rootNode.addNode(nodeName1);
n.addMixin(mixLockable);
n.addMixin(mixReferenceable);
rootNode.save();
String uuid = n.getUUID();
// commit
utx.commit();
// start new Transaction and try to add lock token
utx = new UserTransactionImpl(superuser);
utx.begin();
n = superuser.getNodeByUUID(uuid);
// lock this new node
Lock lock = n.lock(true, false);
// verify node is locked
assertTrue("Node not locked", n.isLocked());
String lockToken = lock.getLockToken();
// assert: session must get a non-null lock token
assertNotNull("session must get a non-null lock token", lockToken);
// assert: session must hold lock token
assertTrue("session must hold lock token", containsLockToken(superuser, lockToken));
n.save();
superuser.removeLockToken(lockToken);
String nlt = lock.getLockToken();
assertTrue("freshly obtained lock token must either be null or the same as the one returned earlier", nlt == null || nlt.equals(lockToken));
assertFalse("session must not hold lock token", containsLockToken(superuser, lockToken));
// commit
utx.commit();
nlt = lock.getLockToken();
assertTrue("freshly obtained lock token must either be null or the same as the one returned earlier", nlt == null || nlt.equals(lockToken));
assertFalse("session must not hold lock token", containsLockToken(superuser, lockToken));
// start new Transaction and try to unlock
utx = new UserTransactionImpl(superuser);
utx.begin();
n = superuser.getNodeByUUID(uuid);
// verify node is locked
assertTrue("Node not locked", n.isLocked());
// assert: session must not hold lock token
assertFalse("session must not hold lock token", containsLockToken(superuser, lockToken));
superuser.addLockToken(lockToken);
// assert: session must not hold lock token
assertTrue("session must hold lock token", containsLockToken(superuser, lockToken));
n.unlock();
// commit
utx.commit();
}
use of javax.jcr.lock.Lock in project jackrabbit by apache.
the class AbstractLockManagementTest method testLockBreaking.
public void testLockBreaking() throws RepositoryException, NotExecutableException {
String locktoken = null;
LockManager sulm = superuser.getWorkspace().getLockManager();
String lockedpath = null;
try {
Node trn = getTestNode();
modifyPrivileges(trn.getPath(), Privilege.JCR_READ, true);
modifyPrivileges(trn.getPath(), PrivilegeRegistry.REP_WRITE, true);
modifyPrivileges(trn.getPath(), Privilege.JCR_LOCK_MANAGEMENT, true);
Session lockingSession = trn.getSession();
assertFalse("super user and test user should have different user ids: " + lockingSession.getUserID() + " vs " + superuser.getUserID(), lockingSession.getUserID().equals(superuser.getUserID()));
trn.addNode("locktest", "nt:unstructured");
trn.addMixin("mix:lockable");
lockingSession.save();
// let the "other" user lock the node
LockManager oulm = lockingSession.getWorkspace().getLockManager();
Lock l = oulm.lock(trn.getPath(), true, false, Long.MAX_VALUE, null);
lockedpath = trn.getPath();
locktoken = l.getLockToken();
lockingSession.logout();
// transfer the lock token to the super user and try the unlock
Node lockednode = superuser.getNode(lockedpath);
assertTrue(lockednode.isLocked());
Lock sl = sulm.getLock(lockedpath);
assertNotNull(sl.getLockToken());
sulm.addLockToken(sl.getLockToken());
sulm.unlock(lockedpath);
locktoken = null;
} finally {
if (locktoken != null && lockedpath != null) {
sulm.addLockToken(locktoken);
sulm.unlock(lockedpath);
}
}
}
Aggregations