Java Collections.synchronizedSortedMap Examples

Java Collections.synchronizedSortedMap - 11 examples found. These are the top rated real world Java examples of java.util.Collections.synchronizedSortedMap extracted from open source projects. You can rate examples to help us improve the quality of examples.
 /**
  * Creates an option container
  *
  * @param index The index of the option container (0..n).
  */
 public OptionContainer(int index) throws OptionException {
   this.index = index;
   savedOptionMap = Collections.synchronizedSortedMap(new TreeMap<Option, Object>());
   dependenciesResolvedOptionMap =
       Collections.synchronizedSortedMap(new TreeMap<Option, Object>());
   commandLineOptionMap = Collections.synchronizedSortedMap(new TreeMap<Option, Object>());
   optionFileOptionMap = Collections.synchronizedSortedMap(new TreeMap<Option, Object>());
 }
Example #2
0
 /** @param iCapacity Maximum number of entries that cache can hold */
 public DBSubsetCache(int iCapacity) {
   iUsed = 0;
   iTopIndex = 0;
   iCacheCapacity = iCapacity;
   LRUList = new String[iCacheCapacity];
   for (int s = 0; s < iCacheCapacity; s++) LRUList[s] = null;
   oCache = Collections.synchronizedSortedMap(new TreeMap<String, DBCacheEntry>());
 }
  /** Creates a new instance of CMapFormat0 */
  protected CMapFormat4(short language) {
    super((short) 4, language);

    segments = Collections.synchronizedSortedMap(new TreeMap<Segment, Object>());

    char[] map = new char[1];
    map[0] = (char) 0;
    addSegment((short) 0xffff, (short) 0xffff, map);
  }
Example #4
0
  /**
   * 計測対象オブジェクトを与えて初期化
   *
   * @param measuredObject 計測対象オブジェクト
   */
  public MetricsInfo(final T measuredObject) {

    if (null == measuredObject) {
      throw new NullPointerException();
    }

    this.measuredObject = measuredObject;
    this.metrics =
        Collections.synchronizedSortedMap(
            new TreeMap<AbstractPlugin, Number>(new MetricTypeAndNamePluginComparator()));
  }
  public BoteMailbox(EmailFolder folder, long uidValidity, long uid) {
    super(new MailboxPath("I2P-Bote", "bote", folder.getName()), uidValidity);
    this.folder = folder;
    this.messageMap =
        Collections.synchronizedSortedMap(
            new TreeMap<Email, BoteMessage>(
                new Comparator<Email>() {
                  @Override
                  public int compare(Email email1, Email email2) {
                    // Try received dates first, this is set for all received.
                    // emails. If not set, this is a sent email, use sent date.
                    Date msg1date = email1.getReceivedDate();
                    if (msg1date == null)
                      try {
                        msg1date = email1.getSentDate();
                      } catch (MessagingException e) {
                      }

                    Date msg2date = email2.getReceivedDate();
                    if (msg2date == null)
                      try {
                        msg2date = email2.getSentDate();
                      } catch (MessagingException e) {
                      }

                    if (msg1date != null && msg2date != null) return msg1date.compareTo(msg2date);

                    // Catch-all
                    return email1.getMessageID().compareTo(email2.getMessageID());
                  }
                }));
    this.uid = uid;

    modSeq = System.currentTimeMillis();
    modSeq <<= 32;

    startListening();
    try {
      List<Email> emails = folder.getElements();
      for (Email email : emails) messageMap.put(email, new BoteMessage(email, getFolderName()));
      updateMessages();
    } catch (PasswordException e) {
      throw new RuntimeException(_t("Password required or invalid password provided"), e);
    }
  }
/**
 * Regionserver which provides transactional support for atomic transactions. This is achieved with
 * optimistic concurrency control (see http://www.seas.upenn.edu/~zives/cis650/papers/opt-cc.pdf).
 * We keep track read and write sets for each transaction, and hold off on processing the writes. To
 * decide to commit a transaction we check its read sets with all transactions that have committed
 * while it was running for overlaps.
 *
 * <p>Because transactions can span multiple regions, all regions must agree to commit a
 * transactions. The client side of this commit protocol is encoded in
 * org.apache.hadoop.hbase.client.transactional.TransactionManger
 *
 * <p>In the event of an failure of the client mid-commit, (after we voted yes), we will have to
 * consult the transaction log to determine the final decision of the transaction. This is not yet
 * implemented.
 */
public class TransactionalRegion extends HRegion {

  private static final String OLD_TRANSACTION_FLUSH = "hbase.transaction.flush";
  private static final int DEFAULT_OLD_TRANSACTION_FLUSH = 100; // Do a flush if
  // we have this
  // many old
  // transactions..

  static final Log LOG = LogFactory.getLog(TransactionalRegion.class);

  // Collection of active transactions (PENDING) keyed by id.
  protected Map<String, TransactionState> transactionsById =
      new HashMap<String, TransactionState>();

  // Map of recent transactions that are COMMIT_PENDING or COMMITED keyed by
  // their sequence number
  private SortedMap<Integer, TransactionState> commitedTransactionsBySequenceNumber =
      Collections.synchronizedSortedMap(new TreeMap<Integer, TransactionState>());

  // Collection of transactions that are COMMIT_PENDING
  private Set<TransactionState> commitPendingTransactions =
      Collections.synchronizedSet(new HashSet<TransactionState>());

  private AtomicInteger nextSequenceId = new AtomicInteger(0);
  private Object commitCheckLock = new Object();
  private THLog transactionLog;
  private final int oldTransactionFlushTrigger;
  private Leases transactionLeases;

  /**
   * @param basedir
   * @param log
   * @param fs
   * @param conf
   * @param regionInfo
   * @param flushListener
   */
  public TransactionalRegion(
      final Path basedir,
      final HLog log,
      final FileSystem fs,
      final Configuration conf,
      final HRegionInfo regionInfo,
      final FlushRequester flushListener) {
    oldTransactionFlushTrigger = conf.getInt(OLD_TRANSACTION_FLUSH, DEFAULT_OLD_TRANSACTION_FLUSH);
  }

  /**
   * Open HRegion. Calls initialize and sets sequenceid to both regular WAL and trx WAL.
   *
   * @param reporter
   * @return Returns <code>this</code>
   * @throws IOException
   */
  @Override
  protected HRegion openHRegion(final CancelableProgressable reporter) throws IOException {
    super.openHRegion(reporter);
    if (this.transactionLog != null) {
      this.transactionLog.setSequenceNumber(super.getLog().getSequenceNumber());
    }
    return this;
  }

  /* protected long replayRecoveredEditsIfAny(final Path regiondir, final long minSeqId, final Progressable reporter)
          throws UnsupportedEncodingException, IOException {
      long maxSeqId = super.replayRecoveredEdits(regiondir, minSeqId, reporter);

      Path recoveredEdits = new Path(regiondir, HLogSplitter.RECOVERED_EDITS);

      doReconstructionLog(recoveredEdits, minSeqId, maxSeqId, reporter);

      return maxSeqId;
  }*/

  protected void doReconstructionLog(
      final Path oldCoreLogFile,
      final long minSeqId,
      final long maxSeqId,
      final Progressable reporter)
      throws UnsupportedEncodingException, IOException {

    Path trxPath = new Path(oldCoreLogFile.getParent(), THLog.HREGION_OLD_THLOGFILE_NAME);

    // We can ignore doing anything with the Trx Log table, it is
    // not-transactional.
    if (super.getTableDesc().getNameAsString().equals(HBaseBackedTransactionLogger.TABLE_NAME)) {
      return;
    }

    THLogRecoveryManager recoveryManager = new THLogRecoveryManager(this);
    Map<Long, WALEdit> commitedTransactionsById =
        recoveryManager.getCommitsFromLog(trxPath, minSeqId, reporter);

    if (commitedTransactionsById != null && commitedTransactionsById.size() > 0) {
      LOG.debug("found " + commitedTransactionsById.size() + " COMMITED transactions to recover.");

      for (Entry<Long, WALEdit> entry : commitedTransactionsById.entrySet()) {
        LOG.debug(
            "Writing " + entry.getValue().size() + " updates for transaction " + entry.getKey());
        WALEdit b = entry.getValue();

        for (KeyValue kv : b.getKeyValues()) {
          // FIXME need to convert these into puts and deletes. Not sure this is
          // the write way.
          // Could probably combine multiple KV's into single put/delete.
          // Also timestamps?
          if (kv.getType() == KeyValue.Type.Put.getCode()) {
            Put put = new Put();
            put.add(kv);
            super.put(put);
          } else if (kv.isDelete()) {
            Delete del = new Delete(kv.getRow());
            if (kv.isDeleteFamily()) {
              del.deleteFamily(kv.getFamily());
            } else if (kv.isDeleteType()) {
              del.deleteColumn(kv.getFamily(), kv.getQualifier());
            }
          }
        }
      }

      LOG.debug("Flushing cache"); // We must trigger a cache flush,
      // otherwise we will would ignore the log on subsequent failure
      if (!super.flushcache()) {
        LOG.warn("Did not flush cache");
      }
    }
  }

  /**
   * We need to make sure that we don't complete a cache flush between running transactions. If we
   * did, then we would not find all log messages needed to restore the transaction, as some of them
   * would be before the last "complete" flush id.
   */
  @Override
  protected long getCompleteCacheFlushSequenceId(final long currentSequenceId) {
    LinkedList<TransactionState> transactionStates;
    synchronized (transactionsById) {
      transactionStates = new LinkedList<TransactionState>(transactionsById.values());
    }

    long minPendingStartSequenceId = currentSequenceId;
    for (TransactionState transactionState : transactionStates) {
      minPendingStartSequenceId =
          Math.min(minPendingStartSequenceId, transactionState.getHLogStartSequenceId());
    }
    return minPendingStartSequenceId;
  }

  /**
   * @param transactionId
   * @throws IOException
   */
  public void beginTransaction(final long transactionId) throws IOException {
    checkClosing();
    String key = String.valueOf(transactionId);
    if (transactionsById.get(key) != null) {
      TransactionState alias = getTransactionState(transactionId);
      if (alias != null) {
        alias.setStatus(Status.ABORTED);
        retireTransaction(alias);
      }
      LOG.error(
          "Existing trasaction with id ["
              + key
              + "] in region ["
              + super.getRegionInfo().getRegionNameAsString()
              + "]");
      throw new IOException("Already exiting transaction id: " + key);
    }

    TransactionState state =
        new TransactionState(
            transactionId, super.getLog().getSequenceNumber(), super.getRegionInfo());

    state.setStartSequenceNumber(nextSequenceId.get());
    List<TransactionState> commitPendingCopy =
        new ArrayList<TransactionState>(commitPendingTransactions);
    for (TransactionState commitPending : commitPendingCopy) {
      state.addTransactionToCheck(commitPending);
    }

    synchronized (transactionsById) {
      transactionsById.put(key, state);
    }
    try {
      transactionLeases.createLease(getLeaseId(transactionId), new TransactionLeaseListener(key));
    } catch (LeaseStillHeldException e) {
      LOG.error(
          "Lease still held for ["
              + key
              + "] in region ["
              + super.getRegionInfo().getRegionNameAsString()
              + "]");
      throw new RuntimeException(e);
    }
    LOG.debug(
        "Begining transaction "
            + key
            + " in region "
            + super.getRegionInfo().getRegionNameAsString());

    maybeTriggerOldTransactionFlush();
  }

  private String getLeaseId(final long transactionId) {
    return super.getRegionInfo().getRegionNameAsString() + transactionId;
  }

  public Result get(final long transactionId, final Get get) throws IOException {
    Scan scan = new Scan(get);
    List<KeyValue> results = new ArrayList<KeyValue>();

    InternalScanner scanner = null;
    try {
      scanner = getScanner(transactionId, scan);
      scanner.next(results);
    } finally {
      if (scanner != null) {
        scanner.close();
      }
    }
    return new Result(results);
  }

  /** Get a transactional scanner. */
  public RegionScanner getScanner(final long transactionId, final Scan scan) throws IOException {
    checkClosing();

    TransactionState state = getTransactionState(transactionId);
    state.addScan(scan);
    List<KeyValueScanner> scanners = new ArrayList<KeyValueScanner>(1);
    scanners.add(state.getScanner(scan));
    return super.getScanner(wrapWithDeleteFilter(scan, state), scanners);
  }

  private Scan wrapWithDeleteFilter(final Scan scan, final TransactionState state) {
    FilterBase deleteFilter =
        new FilterBase() {

          private boolean rowFiltered = false;

          @Override
          public void reset() {
            rowFiltered = false;
          }

          @Override
          public boolean hasFilterRow() {
            return true;
          }

          @Override
          public void filterRow(final List<KeyValue> kvs) {
            state.applyDeletes(kvs, scan.getTimeRange().getMin(), scan.getTimeRange().getMax());
            rowFiltered = kvs.isEmpty();
          }

          @Override
          public boolean filterRow() {
            return rowFiltered;
          }

          @Override
          public void write(final DataOutput out) throws IOException {
            // does nothing
          }

          @Override
          public void readFields(final DataInput in) throws IOException {
            // does nothing
          }
        };

    if (scan.getFilter() == null) {
      scan.setFilter(deleteFilter);
      return scan;
    }

    FilterList wrappedFilter = new FilterList(Arrays.asList(deleteFilter, scan.getFilter()));
    scan.setFilter(wrappedFilter);
    return scan;
  }

  /**
   * Add a write to the transaction. Does not get applied until commit process.
   *
   * @param transactionId
   * @param put
   * @throws IOException
   */
  public void put(final long transactionId, final Put put) throws IOException {
    checkClosing();

    TransactionState state = getTransactionState(transactionId);
    state.addWrite(put);
  }

  /**
   * Add multiple writes to the transaction. Does not get applied until commit process.
   *
   * @param transactionId
   * @param puts
   * @throws IOException
   */
  public void put(final long transactionId, final Put[] puts) throws IOException {
    checkClosing();

    TransactionState state = getTransactionState(transactionId);
    for (Put put : puts) {
      state.addWrite(put);
    }
  }

  /**
   * Add a delete to the transaction. Does not get applied until commit process.
   *
   * @param transactionId
   * @param delete
   * @throws IOException
   */
  public void delete(final long transactionId, final Delete delete) throws IOException {
    checkClosing();
    TransactionState state = getTransactionState(transactionId);
    state.addDelete(delete);
  }

  /**
   * @param transactionId
   * @return TransactionRegionInterface commit code
   * @throws IOException
   */
  public int commitRequest(final long transactionId) throws IOException {
    checkClosing();

    synchronized (commitCheckLock) {
      TransactionState state = getTransactionState(transactionId);
      if (state == null) {
        return TransactionalRegionInterface.COMMIT_UNSUCESSFUL;
      }

      if (hasConflict(state)) {
        state.setStatus(Status.ABORTED);
        retireTransaction(state);
        return TransactionalRegionInterface.COMMIT_UNSUCESSFUL;
      }

      // No conflicts, we can commit.
      LOG.trace(
          "No conflicts for transaction "
              + transactionId
              + " found in region "
              + super.getRegionInfo().getRegionNameAsString()
              + ". Voting for commit");

      // If there are writes we must keep record off the transaction
      if (state.hasWrite()) {
        // Order is important
        state.setStatus(Status.COMMIT_PENDING);
        commitPendingTransactions.add(state);
        state.setSequenceNumber(nextSequenceId.getAndIncrement());
        commitedTransactionsBySequenceNumber.put(state.getSequenceNumber(), state);
        transactionLog.writeCommitResuestToLog(getRegionInfo(), state);

        return TransactionalRegionInterface.COMMIT_OK;
      }
      // Otherwise we were read-only and commitable, so we can forget it.
      state.setStatus(Status.COMMITED);
      retireTransaction(state);
      return TransactionalRegionInterface.COMMIT_OK_READ_ONLY;
    }
  }

  /**
   * @param transactionId
   * @return true if commit is successful
   * @throws IOException
   */
  public boolean commitIfPossible(final long transactionId) throws IOException {
    int status = commitRequest(transactionId);

    if (status == TransactionalRegionInterface.COMMIT_OK) {
      commit(transactionId);
      return true;
    } else if (status == TransactionalRegionInterface.COMMIT_OK_READ_ONLY) {
      return true;
    }
    return false;
  }

  private boolean hasConflict(final TransactionState state) {
    // Check transactions that were committed while we were running
    for (int i = state.getStartSequenceNumber(); i < nextSequenceId.get(); i++) {
      TransactionState other = commitedTransactionsBySequenceNumber.get(i);
      if (other == null) {
        continue;
      }
      state.addTransactionToCheck(other);
    }

    return state.hasConflict();
  }

  /**
   * Commit the transaction.
   *
   * @param transactionId
   * @throws IOException
   */
  public void commit(final long transactionId) throws IOException {
    TransactionState state;
    try {
      state = getTransactionState(transactionId);
    } catch (UnknownTransactionException e) {
      LOG.fatal(
          "Asked to commit unknown transaction: "
              + transactionId
              + " in region "
              + super.getRegionInfo().getRegionNameAsString());
      // TODO. Anything to handle here?
      throw e;
    }

    if (!state.getStatus().equals(Status.COMMIT_PENDING)) {
      LOG.fatal("Asked to commit a non pending transaction");
      // TODO. Anything to handle here?
      throw new IOException("commit failure");
    }

    commit(state);
  }

  /**
   * Abort the transaction.
   *
   * @param transactionId
   * @throws IOException
   */
  public void abort(final long transactionId) throws IOException {
    // Not checking closing...
    TransactionState state;
    try {
      state = getTransactionState(transactionId);
    } catch (UnknownTransactionException e) {
      LOG.info(
          "Asked to abort unknown transaction ["
              + transactionId
              + "] in region ["
              + getRegionInfo().getRegionNameAsString()
              + "], ignoring");
      return;
    }

    state.setStatus(Status.ABORTED);

    if (state.hasWrite()) {
      this.transactionLog.writeAbortToLog(super.getRegionInfo(), state.getTransactionId());
    }

    // Following removes needed if we have voted
    if (state.getSequenceNumber() != null) {
      commitedTransactionsBySequenceNumber.remove(state.getSequenceNumber());
    }
    commitPendingTransactions.remove(state);

    retireTransaction(state);
  }

  private void commit(final TransactionState state) throws IOException {

    LOG.debug(
        "Commiting transaction: "
            + state.toString()
            + " to "
            + super.getRegionInfo().getRegionNameAsString());

    // Perform write operations timestamped to right now
    List<WriteAction> writeOrdering = state.getWriteOrdering();
    for (WriteAction action : writeOrdering) {
      Put put = action.getPut();
      if (null != put) {
        this.put(put, true);
      }

      Delete delete = action.getDelete();
      if (null != delete) {
        delete(delete, null, true);
      }
    }

    // Now the transactional writes live in the core WAL, we can write a commit
    // to the log
    // so we don't have to recover it from the transactional WAL.
    if (state.hasWrite()) {
      this.transactionLog.writeCommitToLog(super.getRegionInfo(), state.getTransactionId());
    }

    state.setStatus(Status.COMMITED);
    if (state.hasWrite() && !commitPendingTransactions.remove(state)) {
      LOG.fatal("Commiting a non-query transaction that is not in commitPendingTransactions");
      // Something has gone really wrong.
      throw new IOException("commit failure");
    }
    retireTransaction(state);
  }

  @Override
  public List<StoreFile> close(final boolean abort) throws IOException {
    prepareToClose();
    if (!commitPendingTransactions.isEmpty()) {
      LOG.warn(
          "Closing transactional region ["
              + getRegionInfo().getRegionNameAsString()
              + "], but still have ["
              + commitPendingTransactions.size()
              + "] transactions  that are pending commit.");
      // TODO resolve from the Global Trx Log.
    }
    return super.close(abort);
  }

  @Override
  protected void prepareToSplit() {
    prepareToClose();
  }

  boolean closing = false;
  private static final int CLOSE_WAIT_ON_COMMIT_PENDING = 1000;

  /** Get ready to close. */
  void prepareToClose() {
    if (closing) {
      return;
    }

    LOG.info("Preparing to close region " + getRegionInfo().getRegionNameAsString());
    closing = true;

    while (!commitPendingTransactions.isEmpty()) {
      LOG.info(
          "Preparing to closing transactional region ["
              + getRegionInfo().getRegionNameAsString()
              + "], but still have ["
              + commitPendingTransactions.size()
              + "] transactions that are pending commit. Sleeping");
      for (TransactionState s : commitPendingTransactions) {
        LOG.info("commit pending: " + s.toString());
      }
      try {
        Thread.sleep(CLOSE_WAIT_ON_COMMIT_PENDING);
      } catch (InterruptedException e) {
        throw new RuntimeException(e);
      }
    }
  }

  private void checkClosing() throws IOException {
    if (closing) {
      throw new IOException("closing region, no more transaction allowed");
    }
  }

  // Cancel leases, and removed from lease lookup. This transaction may still
  // live in commitedTransactionsBySequenceNumber and commitPendingTransactions
  private void retireTransaction(final TransactionState state) {
    String key = String.valueOf(state.getTransactionId());
    try {
      transactionLeases.cancelLease(getLeaseId(state.getTransactionId()));
    } catch (LeaseException e) {
      // Ignore
    }

    synchronized (transactionsById) {
      transactionsById.remove(key);
    }
  }

  protected TransactionState getTransactionState(final long transactionId)
      throws UnknownTransactionException {
    String key = String.valueOf(transactionId);
    TransactionState state = null;

    state = transactionsById.get(key);

    if (state == null) {
      LOG.debug(
          "Unknown transaction: ["
              + key
              + "], region: ["
              + getRegionInfo().getRegionNameAsString()
              + "]");
      throw new UnknownTransactionException(
          "transaction: [" + key + "], region: [" + getRegionInfo().getRegionNameAsString() + "]");
    }

    try {
      transactionLeases.renewLease(getLeaseId(transactionId));
    } catch (LeaseException e) {
      throw new RuntimeException(e);
    }

    return state;
  }

  private void maybeTriggerOldTransactionFlush() {
    if (commitedTransactionsBySequenceNumber.size() > oldTransactionFlushTrigger) {
      removeUnNeededCommitedTransactions();
    }
  }

  /** Cleanup references to committed transactions that are no longer needed. */
  synchronized void removeUnNeededCommitedTransactions() {
    Integer minStartSeqNumber = getMinStartSequenceNumber();
    if (minStartSeqNumber == null) {
      minStartSeqNumber = Integer.MAX_VALUE; // Remove all
    }

    int numRemoved = 0;
    // Copy list to avoid conc update exception
    for (Entry<Integer, TransactionState> entry :
        new LinkedList<Entry<Integer, TransactionState>>(
            commitedTransactionsBySequenceNumber.entrySet())) {
      if (entry.getKey() >= minStartSeqNumber) {
        break;
      }
      numRemoved =
          numRemoved
              + (commitedTransactionsBySequenceNumber.remove(entry.getKey()) == null ? 0 : 1);
      numRemoved++;
    }

    if (LOG.isDebugEnabled()) {
      StringBuilder debugMessage = new StringBuilder();
      if (numRemoved > 0) {
        debugMessage.append("Removed [").append(numRemoved).append("] commited transactions");

        if (minStartSeqNumber == Integer.MAX_VALUE) {
          debugMessage.append(" with any sequence number.");
        } else {
          debugMessage.append(" with sequence lower than [").append(minStartSeqNumber).append("].");
        }
        if (!commitedTransactionsBySequenceNumber.isEmpty()) {
          debugMessage
              .append(" Still have [")
              .append(commitedTransactionsBySequenceNumber.size())
              .append("] left.");
        } else {
          debugMessage.append(" None left.");
        }
        LOG.debug(debugMessage.toString());
      } else if (commitedTransactionsBySequenceNumber.size() > 0) {
        debugMessage
            .append("Could not remove any transactions, and still have ")
            .append(commitedTransactionsBySequenceNumber.size())
            .append(" left");
        LOG.debug(debugMessage.toString());
      }
    }
  }

  private Integer getMinStartSequenceNumber() {
    List<TransactionState> transactionStates;
    synchronized (transactionsById) {
      transactionStates = new ArrayList<TransactionState>(transactionsById.values());
    }
    Integer min = null;
    for (TransactionState transactionState : transactionStates) {
      if (min == null || transactionState.getStartSequenceNumber() < min) {
        min = transactionState.getStartSequenceNumber();
      }
    }
    return min;
  }

  private void resolveTransactionFromLog(final TransactionState transactionState)
      throws IOException {
    LOG.error(
        "Global transaction log is not Implemented. (Optimisticly) assuming transaction commit!");
    commit(transactionState);
    // throw new RuntimeException("Global transaction log is not Implemented");
  }

  private static final int MAX_COMMIT_PENDING_WAITS = 10;

  private class TransactionLeaseListener implements LeaseListener {

    private final String transactionName;

    TransactionLeaseListener(final String n) {
      this.transactionName = n;
    }

    @Override
    public void leaseExpired() {
      LOG.info(
          "Transaction ["
              + this.transactionName
              + "] expired in region ["
              + getRegionInfo().getRegionNameAsString()
              + "]");
      TransactionState s = null;
      synchronized (transactionsById) {
        s = transactionsById.remove(transactionName);
      }
      if (s == null) {
        LOG.warn("Unknown transaction expired " + this.transactionName);
        return;
      }

      switch (s.getStatus()) {
        case PENDING:
          s.setStatus(Status.ABORTED); // Other transactions may have a ref
          break;
        case COMMIT_PENDING:
          LOG.info("Transaction " + s.getTransactionId() + " expired in COMMIT_PENDING state");

          try {
            if (s.getCommitPendingWaits() > MAX_COMMIT_PENDING_WAITS) {
              LOG.info("Checking transaction status in transaction log");
              resolveTransactionFromLog(s);
              break;
            }
            LOG.info("renewing lease and hoping for commit");
            s.incrementCommitPendingWaits();
            String key = Long.toString(s.getTransactionId());
            transactionsById.put(key, s);
            try {
              transactionLeases.createLease(getLeaseId(s.getTransactionId()), this);
            } catch (LeaseStillHeldException e) {
              transactionLeases.renewLease(getLeaseId(s.getTransactionId()));
            }
          } catch (IOException e) {
            throw new RuntimeException(e);
          }

          break;
        default:
          LOG.warn("Unexpected status on expired lease");
      }
    }
  }

  public void setTransactionLog(final THLog trxHLog) {
    this.transactionLog = trxHLog;
  }

  public void setTransactionalLeases(final Leases transactionalLeases) {
    this.transactionLeases = transactionalLeases;
  }
}