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); }