synchronized void save() { Long lastKey = this.lastSyncKey; Set<Entry<Long, RedoLogValue>> entrySet = lastKey == null ? skipListMap.entrySet() : skipListMap.tailMap(lastKey, false).entrySet(); if (!entrySet.isEmpty()) { WriteBuffer buff = WriteBufferPool.poll(); try { for (Entry<Long, RedoLogValue> e : entrySet) { lastKey = e.getKey(); keyType.write(buff, lastKey); valueType.write(buff, e.getValue()); } int chunkLength = buff.position(); if (chunkLength > 0) { buff.limit(chunkLength); buff.position(0); fileStorage.writeFully(pos, buff.getBuffer()); pos += chunkLength; fileStorage.sync(); } this.lastSyncKey = lastKey; } finally { WriteBufferPool.offer(buff); } } }
/** * Get a buffer for writing. This caller must synchronize on the storage before calling the method * and until after using the buffer. * * @return the buffer */ private WriteBuffer getWriteBuffer() { WriteBuffer buff; if (writeBuffer != null) { buff = writeBuffer; buff.clear(); } else { buff = new WriteBuffer(); } return buff; }
private long save() { int currentUnsavedMemory = unsavedMemory; long version = ++currentVersion; long time = getTimeSinceCreation(); lastCommitTime = time; WriteBuffer buff = getWriteBuffer(); BTreeChunk c = new BTreeChunk(++lastChunkId); chunks.put(c.id, c); c.time = time; c.version = version; c.pagePositions = new ArrayList<Long>(); BTreePage p = map.root; if (p.getTotalCount() > 0) { p.writeUnsavedRecursive(c, buff); c.rootPagePos = p.getPos(); p.writeEnd(); } c.pagePositionsOffset = buff.position(); for (long pos : c.pagePositions) buff.putLong(pos); int chunkBodyLength = buff.position(); chunkBodyLength = MathUtils.roundUpInt(chunkBodyLength, BLOCK_SIZE); buff.limit(chunkBodyLength); buff.position(0); c.blockCount = chunkBodyLength / BLOCK_SIZE + CHUNK_HEADER_BLOCKS; // include chunk header(2 blocks). c.fileStorage = getFileStorage(c.id); // chunk header writeChunkHeader(c); // chunk body write(c.fileStorage, CHUNK_HEADER_SIZE, buff.getBuffer()); c.fileStorage.sync(); for (BTreeChunk chunk : chunks.values()) { if (chunk.changed) { writeChunkHeader(chunk); chunk.fileStorage.sync(); chunk.changed = false; } } releaseWriteBuffer(buff); // some pages might have been changed in the meantime (in the newest version) unsavedMemory = Math.max(0, unsavedMemory - currentUnsavedMemory); lastStoredVersion = version - 1; return version; }
/** * Release a buffer for writing. This caller must synchronize on the storage before calling the * method and until after using the buffer. * * @param buff the buffer than can be re-used */ private void releaseWriteBuffer(WriteBuffer buff) { if (buff.capacity() <= 4 * 1024 * 1024) { writeBuffer = buff; } }