public Future store(final long fileId, final long pageIndex, final OCachePointer dataPointer) { Future future = null; synchronized (syncObject) { final GroupKey groupKey = new GroupKey(fileId, pageIndex >>> 4); lockManager.acquireLock(Thread.currentThread(), groupKey, OLockManager.LOCK.EXCLUSIVE); try { WriteGroup writeGroup = writeGroups.get(groupKey); if (writeGroup == null) { writeGroup = new WriteGroup(System.currentTimeMillis()); writeGroups.put(groupKey, writeGroup); } int entryIndex = (int) (pageIndex & 15); if (writeGroup.pages[entryIndex] == null) { dataPointer.incrementReferrer(); writeGroup.pages[entryIndex] = dataPointer; cacheSize.incrementAndGet(); } else { if (!writeGroup.pages[entryIndex].equals(dataPointer)) { writeGroup.pages[entryIndex].decrementReferrer(); dataPointer.incrementReferrer(); writeGroup.pages[entryIndex] = dataPointer; } } writeGroup.recencyBit = true; } finally { lockManager.releaseLock(Thread.currentThread(), groupKey, OLockManager.LOCK.EXCLUSIVE); } if (cacheSize.get() > cacheMaxSize) { future = commitExecutor.submit(new PeriodicFlushTask()); } return future; } }
private int iterateBySubRing( NavigableMap<GroupKey, WriteGroup> subMap, int writeGroupsToFlush, int flushedWriteGroups, boolean forceFlush) throws IOException { Iterator<Map.Entry<GroupKey, WriteGroup>> entriesIterator = subMap.entrySet().iterator(); long currentTime = System.currentTimeMillis(); groupsLoop: while (entriesIterator.hasNext() && flushedWriteGroups < writeGroupsToFlush) { Map.Entry<GroupKey, WriteGroup> entry = entriesIterator.next(); final WriteGroup group = entry.getValue(); final GroupKey groupKey = entry.getKey(); final boolean weakLockMode = group.creationTime - currentTime < groupTTL && !forceFlush; if (group.recencyBit && weakLockMode) { group.recencyBit = false; continue; } lockManager.acquireLock( Thread.currentThread(), entry.getKey(), OLockManager.LOCK.EXCLUSIVE); try { if (group.recencyBit && weakLockMode) group.recencyBit = false; else { group.recencyBit = false; int flushedPages = 0; for (int i = 0; i < 16; i++) { final OCachePointer pagePointer = group.pages[i]; if (pagePointer != null) { if (!pagePointer.tryAcquireExclusiveLock()) continue groupsLoop; try { flushPage( groupKey.fileId, (groupKey.groupIndex << 4) + i, pagePointer.getDataPointer()); flushedPages++; final OLogSequenceNumber flushedLSN = ODurablePage.getLogSequenceNumberFromPage(pagePointer.getDataPointer()); pagePointer.setLastFlushedLsn(flushedLSN); } finally { pagePointer.releaseExclusiveLock(); } } } for (OCachePointer pagePointer : group.pages) if (pagePointer != null) pagePointer.decrementReferrer(); entriesIterator.remove(); flushedWriteGroups++; cacheSize.addAndGet(-flushedPages); } } finally { lockManager.releaseLock( Thread.currentThread(), entry.getKey(), OLockManager.LOCK.EXCLUSIVE); } lastGroupKey = groupKey; } return flushedWriteGroups; }