/** * Releases the write lock held by the provided tx. If it is null then an attempt to acquire the * current transaction from the transaction manager will be made. This is to make safe calling * this method as an <code>afterCompletion()</code> hook where the transaction context is not * necessarily available. If write count is zero and there are waiting transactions in the queue * they will be interrupted if they can acquire the lock. */ synchronized void releaseWriteLock(Object tx) throws LockNotFoundException { TxLockElement tle = getLockElement(tx); if (tle.writeCount == 0) { throw new LockNotFoundException("" + tx + " don't have writeLock"); } totalWriteCount--; tle.writeCount--; if (tle.isFree()) { txLockElementMap.remove(tx); ragManager.lockReleased(this, tx); } // the threads in the waitingList cannot be currentThread // so we only have to wake other elements if writeCount is down to zero // (that is: If writeCount > 0 a waiting thread in the queue cannot be // the thread that holds the write locks because then it would never // have been put into wait mode) if (totalWriteCount == 0 && waitingThreadList.size() > 0) { // wake elements in queue until a write lock is found or queue is // empty do { WaitElement we = waitingThreadList.removeLast(); if (!we.element.movedOn) { we.waitingThread.interrupt(); if (we.lockType == LockType.WRITE) { break; } } } while (waitingThreadList.size() > 0); } }
void commit(Transaction tx) { if (tx != null) { TxCommitHook hook = txCommitHooks.remove(tx); if (hook != null) { for (PropertyIndex index : hook.getAddedPropertyIndexes()) { addPropertyIndex(index); } } } }
public Transaction suspend() throws SystemException { assertTmOk("tx suspend"); // check for ACTIVE/MARKED_ROLLBACK? TransactionImpl tx = txThreadMap.remove(Thread.currentThread()); if (tx != null) { // generate pro-active event suspend tx.markAsSuspended(); } return tx; }
@Test public void testArrayMap() { ArrayMap<String, Integer> map = new ArrayMap<String, Integer>(); assertTrue(map.get("key1") == null); map.put("key1", 0); assertEquals(new Integer(0), map.get("key1")); assertEquals(new Integer(0), map.get("key1")); map.put("key1", 1); assertEquals(new Integer(1), map.get("key1")); map.put("key2", 0); assertEquals(new Integer(0), map.get("key2")); map.put("key2", 2); assertEquals(new Integer(2), map.get("key2")); assertEquals(new Integer(2), map.remove("key2")); assertTrue(map.get("key2") == null); assertEquals(new Integer(1), map.get("key1")); assertEquals(new Integer(1), map.remove("key1")); assertTrue(map.get("key1") == null); map.put("key1", 1); map.put("key2", 2); map.put("key3", 3); map.put("key4", 4); map.put("key5", 5); assertEquals(new Integer(5), map.get("key5")); assertEquals(new Integer(4), map.get("key4")); assertEquals(new Integer(3), map.get("key3")); assertEquals(new Integer(2), map.get("key2")); assertEquals(new Integer(1), map.get("key1")); assertEquals(new Integer(5), map.remove("key5")); assertEquals(new Integer(1), map.get("key1")); assertEquals(new Integer(4), map.get("key4")); assertEquals(new Integer(3), map.get("key3")); assertEquals(new Integer(2), map.get("key2")); assertEquals(new Integer(3), map.remove("key3")); assertEquals(new Integer(1), map.remove("key1")); assertEquals(new Integer(2), map.remove("key2")); for (int i = 0; i < 100; i++) { map.put("key" + i, i); } for (int i = 0; i < 100; i++) { assertEquals(new Integer(i), map.get("key" + i)); } for (int i = 0; i < 100; i++) { assertEquals(new Integer(i), map.remove("key" + i)); } for (int i = 0; i < 100; i++) { assertTrue(map.get("key" + i) == null); } }
private void rollbackCommit(Thread thread, TransactionImpl tx) throws HeuristicMixedException, RollbackException, SystemException { try { tx.doRollback(); } catch (XAException e) { log.log( Level.SEVERE, "Unable to rollback marked transaction. " + "Some resources may be commited others not. " + "Neo4j kernel should be SHUTDOWN for " + "resource maintance and transaction recovery ---->", e); setTmNotOk(e); throw logAndReturn( "TM error tx rollback commit", Exceptions.withCause( new HeuristicMixedException( "Unable to rollback " + " ---> error code for rollback: " + e.errorCode), e)); } tx.doAfterCompletion(); txThreadMap.remove(thread); try { if (tx.isGlobalStartRecordWritten()) { getTxLog().txDone(tx.getGlobalId()); } } catch (IOException e) { log.log(Level.SEVERE, "Error writing transaction log", e); setTmNotOk(e); throw logAndReturn( "TM error tx rollback commit", Exceptions.withCause( new SystemException("TM encountered a problem, " + " error writing transaction log"), e)); } tx.setStatus(Status.STATUS_NO_TRANSACTION); throw new RollbackException("Failed to commit, transaction rolledback"); }
void rollback(Transaction tx) { txCommitHooks.remove(tx); }
public void rollback() throws IllegalStateException, SystemException { assertTmOk("tx rollback"); Thread thread = Thread.currentThread(); TransactionImpl tx = txThreadMap.get(thread); if (tx == null) { throw new IllegalStateException("Not in transaction"); } boolean hasAnyLocks = false; try { hasAnyLocks = finishHook.hasAnyLocks(tx); if (tx.getStatus() == Status.STATUS_ACTIVE || tx.getStatus() == Status.STATUS_MARKED_ROLLBACK || tx.getStatus() == Status.STATUS_PREPARING) { tx.setStatus(Status.STATUS_MARKED_ROLLBACK); tx.doBeforeCompletion(); // delist resources? try { rolledBackTxCount.incrementAndGet(); tx.doRollback(); } catch (XAException e) { log.log( Level.SEVERE, "Unable to rollback marked or active transaction. " + "Some resources may be commited others not. " + "Neo4j kernel should be SHUTDOWN for " + "resource maintance and transaction recovery ---->", e); setTmNotOk(e); throw logAndReturn( "TM error tx rollback", Exceptions.withCause( new SystemException( "Unable to rollback " + " ---> error code for rollback: " + e.errorCode), e)); } tx.doAfterCompletion(); txThreadMap.remove(thread); try { if (tx.isGlobalStartRecordWritten()) { getTxLog().txDone(tx.getGlobalId()); } } catch (IOException e) { log.log(Level.SEVERE, "Error writing transaction log", e); setTmNotOk(e); throw logAndReturn( "TM error tx rollback", Exceptions.withCause( new SystemException( "TM encountered a problem, " + " error writing transaction log"), e)); } tx.setStatus(Status.STATUS_NO_TRANSACTION); } else { throw new IllegalStateException("Tx status is: " + getTxStatusAsString(tx.getStatus())); } } finally { if (hasAnyLocks) { finishHook.finishTransaction(tx.getEventIdentifier(), false); } } }
private void commit(Thread thread, TransactionImpl tx) throws SystemException, HeuristicMixedException, HeuristicRollbackException { // mark as commit in log done TxImpl.doCommit() Throwable commitFailureCause = null; int xaErrorCode = -1; if (tx.getResourceCount() == 0) { tx.setStatus(Status.STATUS_COMMITTED); } else { try { tx.doCommit(); } catch (XAException e) { xaErrorCode = e.errorCode; log.log( Level.SEVERE, "Commit failed, status=" + getTxStatusAsString(tx.getStatus()) + ", errorCode=" + xaErrorCode, e); if (tx.getStatus() == Status.STATUS_COMMITTED) { // this should never be setTmNotOk(e); throw logAndReturn( "TM error tx commit", new TransactionFailureException( "commit threw exception but status is committed?", e)); } } catch (Throwable t) { log.log(Level.SEVERE, "Commit failed", t); commitFailureCause = t; } } if (tx.getStatus() != Status.STATUS_COMMITTED) { try { tx.doRollback(); } catch (Throwable e) { log.log( Level.SEVERE, "Unable to rollback transaction. " + "Some resources may be commited others not. " + "Neo4j kernel should be SHUTDOWN for " + "resource maintance and transaction recovery ---->", e); setTmNotOk(e); String commitError; if (commitFailureCause != null) { commitError = "error in commit: " + commitFailureCause; } else { commitError = "error code in commit: " + xaErrorCode; } String rollbackErrorCode = "Uknown error code"; if (e instanceof XAException) { rollbackErrorCode = Integer.toString(((XAException) e).errorCode); } throw logAndReturn( "TM error tx commit", Exceptions.withCause( new HeuristicMixedException( "Unable to rollback ---> " + commitError + " ---> error code for rollback: " + rollbackErrorCode), e)); } tx.doAfterCompletion(); txThreadMap.remove(thread); try { if (tx.isGlobalStartRecordWritten()) { getTxLog().txDone(tx.getGlobalId()); } } catch (IOException e) { log.log(Level.SEVERE, "Error writing transaction log", e); setTmNotOk(e); throw logAndReturn( "TM error tx commit", Exceptions.withCause( new SystemException( "TM encountered a problem, " + " error writing transaction log"), e)); } tx.setStatus(Status.STATUS_NO_TRANSACTION); if (commitFailureCause == null) { throw logAndReturn( "TM error tx commit", new HeuristicRollbackException( "Failed to commit, transaction rolledback ---> " + "error code was: " + xaErrorCode)); } else { throw logAndReturn( "TM error tx commit", Exceptions.withCause( new HeuristicRollbackException( "Failed to commit, transaction rolledback ---> " + commitFailureCause), commitFailureCause)); } } tx.doAfterCompletion(); txThreadMap.remove(thread); try { if (tx.isGlobalStartRecordWritten()) { getTxLog().txDone(tx.getGlobalId()); } } catch (IOException e) { log.log(Level.SEVERE, "Error writing transaction log", e); setTmNotOk(e); throw logAndReturn( "TM error tx commit", Exceptions.withCause( new SystemException("TM encountered a problem, " + " error writing transaction log"), e)); } tx.setStatus(Status.STATUS_NO_TRANSACTION); }
synchronized void stopWaitOn(Object resource, Transaction tx) { if (waitingTxMap.remove(tx) == null) { throw new LockException(tx + " not waiting on " + resource); } }
void releaseResourceConnectionsForTransaction(Transaction tx) throws NotInTransactionException { T con = txConnectionMap.remove(tx); if (con != null) { con.destroy(); } }
/** * Releases the read lock held by the provided transaction. If it is null then an attempt to * acquire the current transaction will be made. This is to make safe calling the method from the * context of an <code>afterCompletion()</code> hook where the tx is locally stored and not * necessarily available through the tm. If there are waiting transactions in the queue they will * be interrupted if they can acquire the lock. */ synchronized void releaseReadLock(Object tx) throws LockNotFoundException { TxLockElement tle = getLockElement(tx); if (tle.readCount == 0) { throw new LockNotFoundException("" + tx + " don't have readLock"); } totalReadCount--; tle.readCount--; if (tle.isFree()) { txLockElementMap.remove(tx); ragManager.lockReleased(this, tx); } if (waitingThreadList.size() > 0) { WaitElement we = waitingThreadList.getLast(); if (we.lockType == LockType.WRITE) { // this one is tricky... // if readCount > 0 we either have to find a waiting read lock // in the queue or a waiting write lock that has all read // locks, if none of these are found it means that there // is a (are) thread(s) that will release read lock(s) in the // near future... if (totalReadCount == we.element.readCount) { // found a write lock with all read locks waitingThreadList.removeLast(); if (!we.element.movedOn) { we.waitingThread.interrupt(); } } else { ListIterator<WaitElement> listItr = waitingThreadList.listIterator(waitingThreadList.lastIndexOf(we)); // hm am I doing the first all over again? // think I am if cursor is at lastIndex + 0.5 oh well... while (listItr.hasPrevious()) { we = listItr.previous(); if (we.lockType == LockType.WRITE && totalReadCount == we.element.readCount) { // found a write lock with all read locks listItr.remove(); if (!we.element.movedOn) { we.waitingThread.interrupt(); // ---- break; } } else if (we.lockType == LockType.READ) { // found a read lock, let it do the job... listItr.remove(); if (!we.element.movedOn) { we.waitingThread.interrupt(); } } } } } else { // some thread may have the write lock and released a read lock // if writeCount is down to zero we can interrupt the waiting // read lock if (totalWriteCount == 0) { waitingThreadList.removeLast(); if (!we.element.movedOn) { we.waitingThread.interrupt(); } } } } }