public long calculateTxnLogSizeLimit() {
   long snapSize = 0;
   try {
     snapSize = snapLog.findMostRecentSnapshot().length();
   } catch (IOException e) {
     LOG.error("Unable to get size of most recent snapshot");
   }
   return (long) (snapSize * snapshotSizeFactor);
 }
  /**
   * Truncate the ZKDatabase to the specified zxid
   *
   * @param zxid the zxid to truncate zk database to
   * @return true if the truncate is successful and false if not
   * @throws IOException
   */
  public boolean truncateLog(long zxid) throws IOException {
    clear();

    // truncate the log
    boolean truncated = snapLog.truncateLog(zxid);

    if (!truncated) {
      return false;
    }

    loadDataBase();
    return true;
  }
  /**
   * load the database from the disk onto memory and also add the transactions to the committedlog
   * in memory.
   *
   * @return the last valid zxid on disk
   * @throws IOException
   */
  public long loadDataBase() throws IOException {
    PlayBackListener listener =
        new PlayBackListener() {
          public void onTxnLoaded(TxnHeader hdr, Record txn) {
            Request r = new Request(0, hdr.getCxid(), hdr.getType(), hdr, txn, hdr.getZxid());
            addCommittedProposal(r);
          }
        };

    long zxid = snapLog.restore(dataTree, sessionsWithTimeouts, listener);
    initialized = true;
    return zxid;
  }
  /**
   * Get proposals from txnlog. Only packet part of proposal is populated.
   *
   * @param startZxid the starting zxid of the proposal
   * @param sizeLimit maximum on-disk size of txnlog to fetch 0 is unlimited, negative value means
   *     disable.
   * @return list of proposal (request part of each proposal is null)
   */
  public Iterator<Proposal> getProposalsFromTxnLog(long startZxid, long sizeLimit) {
    if (sizeLimit < 0) {
      LOG.debug("Negative size limit - retrieving proposal via txnlog is disabled");
      return TxnLogProposalIterator.EMPTY_ITERATOR;
    }

    TxnIterator itr = null;
    try {

      itr = snapLog.readTxnLog(startZxid, false);

      // If we cannot guarantee that this is strictly the starting txn
      // after a given zxid, we should fail.
      if ((itr.getHeader() != null) && (itr.getHeader().getZxid() > startZxid)) {
        LOG.warn("Unable to find proposals from txnlog for zxid: " + startZxid);
        itr.close();
        return TxnLogProposalIterator.EMPTY_ITERATOR;
      }

      if (sizeLimit > 0) {
        long txnSize = itr.getStorageSize();
        if (txnSize > sizeLimit) {
          LOG.info("Txnlog size: " + txnSize + " exceeds sizeLimit: " + sizeLimit);
          itr.close();
          return TxnLogProposalIterator.EMPTY_ITERATOR;
        }
      }
    } catch (IOException e) {
      LOG.error("Unable to read txnlog from disk", e);
      try {
        if (itr != null) {
          itr.close();
        }
      } catch (IOException ioe) {
        LOG.warn("Error closing file iterator", ioe);
      }
      return TxnLogProposalIterator.EMPTY_ITERATOR;
    }
    return new TxnLogProposalIterator(itr);
  }