private FileInfo putFileInfo(Long ledger, byte masterKey[], File lf, boolean createdNewFile)
     throws IOException {
   FileInfo fi = new FileInfo(lf, masterKey);
   FileInfo oldFi = fileInfoCache.putIfAbsent(ledger, fi);
   if (null != oldFi) {
     // Some other thread won the race. We should delete our file if we created
     // a new one and the paths are different.
     if (createdNewFile && !oldFi.isSameFile(lf)) {
       fi.delete();
     }
     fi = oldFi;
   } else {
     if (createdNewFile) {
       // Else, we won and the active ledger manager should know about this.
       LOG.debug("New ledger index file created for ledgerId: {}", ledger);
       activeLedgers.put(ledger, true);
     }
     // Evict cached items from the file info cache if necessary
     evictFileInfoIfNecessary();
     synchronized (openLedgers) {
       openLedgers.offer(ledger);
     }
   }
   return fi;
 }
  /**
   * This method will look within the ledger directories for the ledger index files. That will
   * comprise the set of active ledgers this particular BookieServer knows about that have not yet
   * been deleted by the BookKeeper Client. This is called only once during initialization.
   */
  private void getActiveLedgers() throws IOException {
    // Ledger index files are stored in a file hierarchy with a parent and
    // grandParent directory. We'll have to go two levels deep into these
    // directories to find the index files.
    for (File ledgerDirectory : ledgerDirsManager.getAllLedgerDirs()) {
      File[] grandParents = ledgerDirectory.listFiles();
      if (grandParents == null) {
        continue;
      }
      for (File grandParent : grandParents) {
        if (grandParent.isDirectory()) {
          File[] parents = grandParent.listFiles();
          if (parents == null) {
            continue;
          }
          for (File parent : parents) {
            if (parent.isDirectory()) {
              File[] indexFiles = parent.listFiles();
              if (indexFiles == null) {
                continue;
              }
              for (File index : indexFiles) {
                if (!index.isFile()
                    || (!index.getName().endsWith(IDX) && !index.getName().endsWith(RLOC))) {
                  continue;
                }

                // We've found a ledger index file. The file
                // name is the HexString representation of the
                // ledgerId.
                String ledgerIdInHex = index.getName().replace(RLOC, "").replace(IDX, "");
                if (index.getName().endsWith(RLOC)) {
                  if (findIndexFile(Long.parseLong(ledgerIdInHex)) != null) {
                    if (!index.delete()) {
                      LOG.warn("Deleting the rloc file " + index + " failed");
                    }
                    continue;
                  } else {
                    File dest = new File(index.getParentFile(), ledgerIdInHex + IDX);
                    if (!index.renameTo(dest)) {
                      throw new IOException(
                          "Renaming rloc file " + index + " to index file has failed");
                    }
                  }
                }
                activeLedgers.put(Long.parseLong(ledgerIdInHex, 16), true);
              }
            }
          }
        }
      }
    }
  }
  /**
   * This method is called whenever a ledger is deleted by the BookKeeper Client and we want to
   * remove all relevant data for it stored in the LedgerCache.
   */
  void removeLedger(long ledgerId) throws IOException {
    // Delete the ledger's index file and close the FileInfo
    FileInfo fi = null;
    try {
      fi = getFileInfo(ledgerId, null);
      fi.close(false);
      fi.delete();
    } finally {
      // should release use count
      // otherwise the file channel would not be closed.
      if (null != fi) {
        fi.release();
      }
    }

    // Remove it from the active ledger manager
    activeLedgers.remove(ledgerId);

    // Now remove it from all the other lists and maps.
    fileInfoCache.remove(ledgerId);
    synchronized (openLedgers) {
      openLedgers.remove(ledgerId);
    }
  }
 boolean ledgerExists(long ledgerId) throws IOException {
   return activeLedgers.containsKey(ledgerId);
 }