void endTransactionTPL(Session session) { int unlockedCount = 0; unlockTablesTPL(session); final int waitingCount = session.waitingSessions.size(); if (waitingCount == 0) { return; } for (int i = 0; i < waitingCount; i++) { Session current = (Session) session.waitingSessions.get(i); current.tempUnlocked = false; long count = current.latch.getCount(); if (count == 1) { boolean canProceed = setWaitedSessionsTPL(current, current.currentStatement); if (!canProceed) { current.abortTransaction = true; } if (current.tempSet.isEmpty()) { lockTablesTPL(current, current.currentStatement); current.tempUnlocked = true; unlockedCount++; } } } for (int i = 0; i < waitingCount; i++) { Session current = (Session) session.waitingSessions.get(i); if (!current.tempUnlocked) { // this can introduce additional waits for the sessions boolean canProceed = setWaitedSessionsTPL(current, current.currentStatement); if (!canProceed) { current.abortTransaction = true; } } } for (int i = 0; i < waitingCount; i++) { Session current = (Session) session.waitingSessions.get(i); setWaitingSessionTPL(current); } session.tempSet.clear(); session.waitingSessions.clear(); }
/** add session to the end of queue when a transaction starts (depending on isolation mode) */ public void beginAction(Session session, Statement cs) { if (session.hasLocks(cs)) { return; } writeLock.lock(); try { if (cs.getCompileTimestamp() < database.schemaManager.getSchemaChangeTimestamp()) { cs = session.statementManager.getStatement(session, cs); session.sessionContext.currentStatement = cs; if (cs == null) { return; } } boolean canProceed = setWaitedSessionsTPL(session, cs); if (canProceed) { if (session.tempSet.isEmpty()) { lockTablesTPL(session, cs); // we don't set other sessions that would now be waiting for this one too } else { setWaitingSessionTPL(session); } } else { session.abortTransaction = true; } } finally { writeLock.unlock(); } }
/** add session to the end of queue when a transaction starts (depending on isolation mode) */ public void beginAction(Session session, Statement cs) { synchronized (liveTransactionTimestamps) { session.actionTimestamp = nextChangeTimestamp(); if (!session.isTransaction) { session.transactionTimestamp = session.actionTimestamp; session.isTransaction = true; liveTransactionTimestamps.addLast(session.actionTimestamp); } } if (session.hasLocks()) { return; } try { writeLock.lock(); boolean canProceed = beginActionTPL(session, cs); if (!canProceed) { session.abortTransaction = true; } } finally { writeLock.unlock(); } }
public void rollback(Session session) { session.abortTransaction = false; session.actionTimestamp = nextChangeTimestamp(); rollbackPartial(session, 0, session.transactionTimestamp); endTransaction(session); try { writeLock.lock(); endTransactionTPL(session); } finally { writeLock.unlock(); } }
public boolean prepareCommitActions(Session session) { Object[] list = session.rowActionList.getArray(); int limit = session.rowActionList.size(); if (session.abortTransaction) { // System.out.println("cascade fail " + session + " " + session.actionTimestamp); return false; } try { writeLock.lock(); for (int i = 0; i < limit; i++) { RowAction rowact = (RowAction) list[i]; if (!rowact.canCommit(session, session.tempSet)) { // System.out.println("commit conflicts " + session + " " + // session.actionTimestamp); return false; } } session.actionTimestamp = nextChangeTimestamp(); for (int i = 0; i < limit; i++) { RowAction action = (RowAction) list[i]; action.prepareCommit(session); } for (int i = 0; i < session.tempSet.size(); i++) { Session current = (Session) session.tempSet.get(i); current.abortTransaction = true; } return true; } finally { writeLock.unlock(); session.tempSet.clear(); } }
public void completeActions(Session session) { Object[] list = session.rowActionList.getArray(); int limit = session.rowActionList.size(); boolean canComplete = true; writeLock.lock(); try { for (int i = session.actionIndex; i < limit; i++) { RowAction rowact = (RowAction) list[i]; if (rowact.complete(session, session.tempSet)) { continue; } canComplete = false; if (session.isolationMode == SessionInterface.TX_REPEATABLE_READ || session.isolationMode == SessionInterface.TX_SERIALIZABLE) { session.abortTransaction = true; break; } } for (int i = session.actionIndex; canComplete && i < limit; i++) { RowAction action = (RowAction) list[i]; if (!action.table.isLogged) { continue; } Row row = action.memoryRow; if (row == null) { PersistentStore store = session.sessionData.getRowStore(action.table); row = (Row) store.get(action.getPos(), false); } Object[] data = row.getData(); try { int actionType = action.getActionType(session.actionTimestamp); if (actionType == RowActionBase.ACTION_INSERT) { database.logger.writeInsertStatement(session, (Table) action.table, data); } else if (actionType == RowActionBase.ACTION_DELETE) { database.logger.writeDeleteStatement(session, (Table) action.table, data); } else if (actionType == RowActionBase.ACTION_NONE) { // no logging } else { throw Error.runtimeError(ErrorCode.U_S0500, "TransactionManager"); } } catch (HsqlException e) { // can put db in special state } } if (!canComplete && !session.abortTransaction) { session.redoAction = true; rollbackAction(session); if (!session.tempSet.isEmpty()) { session.latch.setCount(session.tempSet.size()); for (int i = 0; i < session.tempSet.size(); i++) { Session current = (Session) session.tempSet.get(i); current.waitingSessions.add(session); // waitedSessions.put(current, session); // waitingSessions.put(session, current); } } } } finally { writeLock.unlock(); session.tempSet.clear(); } }