public boolean commitTransaction(Session session) {

    if (session.abortTransaction) {
      return false;
    }

    int limit = session.rowActionList.size();
    Object[] list = session.rowActionList.getArray();

    writeLock.lock();

    try {

      // new actionTimestamp used for commitTimestamp
      session.actionTimestamp = nextChangeTimestamp();
      session.transactionEndTimestamp = session.actionTimestamp;

      endTransaction(session);

      for (int i = 0; i < limit; i++) {
        RowAction action = (RowAction) list[i];

        action.commit(session);
      }

      persistCommit(session, list, limit);

      int newLimit = session.rowActionList.size();

      if (newLimit > limit) {
        list = session.rowActionList.getArray();

        mergeTransaction(session, list, limit, newLimit, session.actionTimestamp);
        finaliseRows(session, list, limit, newLimit, true);
        session.rowActionList.setSize(limit);
      }

      // session.actionTimestamp is the committed tx timestamp
      if (getFirstLiveTransactionTimestamp() > session.actionTimestamp || session == lobSession) {
        mergeTransaction(session, list, 0, limit, session.actionTimestamp);
        finaliseRows(session, list, 0, limit, true);
      } else {
        list = session.rowActionList.toArray();

        addToCommittedQueue(session, list);
      }

      endTransactionTPL(session);
    } finally {
      writeLock.unlock();
    }

    session.tempSet.clear();

    return true;
  }
  public void rollback(Session session) {

    writeLock.lock();

    try {
      session.abortTransaction = false;
      session.actionTimestamp = nextChangeTimestamp();
      session.transactionEndTimestamp = session.actionTimestamp;

      rollbackPartial(session, 0, session.transactionTimestamp);
      endTransaction(session);
      endTransactionTPL(session);
    } finally {
      writeLock.unlock();
    }
  }