/** * Remove the LedgerEntryPage from the clean page LRU map * * @param lep Ledger Entry Page object */ private void removeFromCleanPageList(LedgerEntryPage lep) { synchronized (lruCleanPageMap) { if (!lep.isClean() || lep.inUse()) { lruCleanPageMap.remove(lep.getEntryKey()); } } }
/** * Add the LedgerEntryPage to the clean page LRU map * * @param lep Ledger Entry Page object */ private void addToCleanPagesList(LedgerEntryPage lep) { synchronized (lruCleanPageMap) { if (lep.isClean() && !lep.inUse()) { lruCleanPageMap.put(lep.getEntryKey(), lep); } } }
LedgerEntryPage getLedgerEntryPage(Long ledger, Long firstEntry, boolean onlyDirty) { LedgerEntryPage lep = pageMapAndList.getPage(ledger, firstEntry); if (onlyDirty && null != lep && lep.isClean()) { return null; } if (null != lep) { lep.usePage(); } return lep; }
/** * Get a clean page and provision it for the specified ledger and firstEntry within the ledger * * @param ledgerId Ledger id * @param firstEntry Id of the first entry in the page * @returns LedgerEntryPage if present */ LedgerEntryPage grabCleanPage(long ledgerId, long firstEntry) { LedgerEntryPage lep = null; while (lruCleanPageMap.size() > 0) { lep = null; synchronized (lruCleanPageMap) { Iterator<Map.Entry<EntryKey, LedgerEntryPage>> iterator = lruCleanPageMap.entrySet().iterator(); Map.Entry<EntryKey, LedgerEntryPage> entry = null; while (iterator.hasNext()) { entry = iterator.next(); iterator.remove(); if (entry.getValue().isClean() && !entry.getValue().inUse()) { lep = entry.getValue(); break; } } if (null == lep) { LOG.debug("Did not find eligible page in the first pass"); return null; } } // We found a candidate page, lets see if we can reclaim it before its re-used ConcurrentMap<Long, LedgerEntryPage> pageMap = pages.get(lep.getLedger()); // Remove from map only if nothing has changed since we checked this lep. // Its possible for the ledger to have been deleted or the page to have already // been reclaimed. The page map is the definitive source of information, if anything // has changed we should leave this page along and continue iterating to find // another suitable page. if ((null != pageMap) && (pageMap.remove(lep.getFirstEntry(), lep))) { if (!lep.isClean()) { // Someone wrote to this page while we were reclaiming it. pageMap.put(lep.getFirstEntry(), lep); lep = null; } else { // Do some bookkeeping on the page table pages.remove(lep.getLedger(), EMPTY_PAGE_MAP); // We can now safely reset this lep and return it. lep.usePage(); lep.zeroPage(); lep.setLedgerAndFirstEntry(ledgerId, firstEntry); return lep; } } else { lep = null; } } return lep; }
void updatePage(LedgerEntryPage lep) throws IOException { if (!lep.isClean()) { throw new IOException("Trying to update a dirty page"); } FileInfo fi = null; try { fi = getFileInfo(lep.getLedger(), null); long pos = lep.getFirstEntryPosition(); if (pos >= fi.size()) { lep.zeroPage(); } else { lep.readPage(fi); } } finally { if (fi != null) { fi.release(); } } }
/** * Gets the list of pages in memory that have been changed and hence need to be written as a * part of the flush operation that is being issued * * @param ledgerId Ledger id * @returns last entry in the in memory pages. */ private LinkedList<Long> getFirstEntryListToBeFlushed(long ledgerId) { ConcurrentMap<Long, LedgerEntryPage> pageMap = pages.get(ledgerId); if (pageMap == null || pageMap.isEmpty()) { return null; } LinkedList<Long> firstEntryList = new LinkedList<Long>(); for (ConcurrentMap.Entry<Long, LedgerEntryPage> entry : pageMap.entrySet()) { LedgerEntryPage lep = entry.getValue(); if (lep.isClean()) { if (!lep.inUse()) { addToCleanPagesList(lep); } if (LOG.isTraceEnabled()) { LOG.trace("Page is clean " + lep); } } else { firstEntryList.add(lep.getFirstEntry()); } } return firstEntryList; }