Пример #1
0
 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);
     }
   }
 }
Пример #2
0
 /**
  * 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;
 }
Пример #3
0
  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;
  }
Пример #4
0
 /**
  * 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;
   }
 }