/* * Scan the INList for all dirty INs. Arrange them in level sorted * map for level ordered flushing. */ private SortedMap selectDirtyINs(boolean flushAll, boolean flushExtraLevel) throws DatabaseException { SortedMap newDirtyMap = new TreeMap(); INList inMemINs = envImpl.getInMemoryINs(); inMemINs.latchMajor(); /* * Opportunistically recalculate the environment wide memory * count. Incurs no extra cost because we're walking the IN * list anyway. Not the best in terms of encapsulation as * prefereably all memory calculations are done in * MemoryBudget, but done this way to avoid any extra * latching. */ long totalSize = 0; MemoryBudget mb = envImpl.getMemoryBudget(); try { Iterator iter = inMemINs.iterator(); while (iter.hasNext()) { IN in = (IN) iter.next(); in.latch(); totalSize = mb.accumulateNewUsage(in, totalSize); boolean isDirty = in.getDirty(); in.releaseLatch(); if (isDirty) { Integer level = new Integer(in.getLevel()); Set dirtySet; if (newDirtyMap.containsKey(level)) { dirtySet = (Set) newDirtyMap.get(level); } else { dirtySet = new HashSet(); newDirtyMap.put(level, dirtySet); } dirtySet.add(in); } } // Later release: refresh env count. // mb.refreshCacheMemoryUsage(totalSize); /* * If we're flushing all for cleaning, we must flush to * the point that there are no nodes with LSNs in the * cleaned files. We could figure this out by perusing * every node to see what children it has, but that's so * expensive that instead we'll flush to the root. */ if (newDirtyMap.size() > 0) { if (flushAll) { highestFlushLevel = envImpl.getDbMapTree().getHighestLevel(); } else { highestFlushLevel = ((Integer) newDirtyMap.lastKey()).intValue(); if (flushExtraLevel) { highestFlushLevel += 1; } } } } finally { inMemINs.releaseMajorLatchIfHeld(); } return newDirtyMap; }