class ServerLockCleaner {

  public Pair<Long, PrimaryLock> cleanPrimaryLock(ColumnCoordinate columnCoordinate,
      long prewriteTs) throws IOException {
    // read back and erase primary lock if exist
    ThemisLock lock = cpClient.getLockAndErase(columnCoordinate, prewriteTs);
    // make sure we must get a primary lock when there are logic errors in code
    if (lock != null && !(lock instanceof PrimaryLock)) {
      throw new ThemisFatalException("encounter no-primary lock when cleanPrimaryLock, column="
          + columnCoordinate + ", prewriteTs=" + prewriteTs + ", lock=" + lock);
    }
    PrimaryLock primaryLock = (PrimaryLock)lock;
    Long commitTs = primaryLock != null ? null :
      getTimestampOfWriteIndexingPrewriteTs(columnCoordinate, prewriteTs);
    // commitTs = null indicates the conflicted transaction has been erased by other client; otherwise
    // the conflicted must be committed by other client.
    if (commitTs == null) {
      ThemisCpStatistics.getThemisCpStatistics().cleanLockByEraseCount.inc();
    } else {
      ThemisCpStatistics.getThemisCpStatistics().cleanLockByCommitCount.inc();
    }
    return new Pair<Long, PrimaryLock>(commitTs, primaryLock);
  }

  public  ServerLockCleaner(HConnection conn, ThemisCoprocessorClient cpClient);

}