Exemple #1
0
  private WriteBatchImpl readWriteBatch(SliceInput record, int updateSize) throws IOException {
    WriteBatchImpl writeBatch = new WriteBatchImpl();
    int entries = 0;
    while (record.isReadable()) {
      entries++;
      ValueType valueType = ValueType.getValueTypeByPersistentId(record.readByte());
      if (valueType == VALUE) {
        Slice key = readLengthPrefixedBytes(record);
        Slice value = readLengthPrefixedBytes(record);
        writeBatch.put(key, value);
      } else if (valueType == DELETION) {
        Slice key = readLengthPrefixedBytes(record);
        writeBatch.delete(key);
      } else {
        throw new IllegalStateException("Unexpected value type " + valueType);
      }
    }

    if (entries != updateSize) {
      throw new IOException(
          String.format(
              "Expected %d entries in log record but found %s entries", updateSize, entries));
    }

    return writeBatch;
  }
Exemple #2
0
  private long recoverLogFile(long fileNumber, VersionEdit edit) throws IOException {
    Preconditions.checkState(mutex.isHeldByCurrentThread());
    File file = new File(databaseDir, Filename.logFileName(fileNumber));
    FileChannel channel = new FileInputStream(file).getChannel();
    try {
      LogMonitor logMonitor = LogMonitors.logMonitor();
      LogReader logReader = new LogReader(channel, logMonitor, true, 0);

      // Log(options_.info_log, "Recovering log #%llu", (unsigned long long) log_number);

      // Read all the records and add to a memtable
      long maxSequence = 0;
      MemTable memTable = null;
      for (Slice record = logReader.readRecord(); record != null; record = logReader.readRecord()) {
        SliceInput sliceInput = record.input();
        // read header
        if (sliceInput.available() < 12) {
          logMonitor.corruption(sliceInput.available(), "log record too small");
          continue;
        }
        long sequenceBegin = sliceInput.readLong();
        int updateSize = sliceInput.readInt();

        // read entries
        WriteBatchImpl writeBatch = readWriteBatch(sliceInput, updateSize);

        // apply entries to memTable
        if (memTable == null) {
          memTable = new MemTable(internalKeyComparator);
        }
        writeBatch.forEach(new InsertIntoHandler(memTable, sequenceBegin));

        // update the maxSequence
        long lastSequence = sequenceBegin + updateSize - 1;
        if (lastSequence > maxSequence) {
          maxSequence = lastSequence;
        }

        // flush mem table if necessary
        if (memTable.approximateMemoryUsage() > options.writeBufferSize()) {
          writeLevel0Table(memTable, edit, null);
          memTable = null;
        }
      }

      // flush mem table
      if (memTable != null && !memTable.isEmpty()) {
        writeLevel0Table(memTable, edit, null);
      }

      return maxSequence;
    } finally {
      channel.close();
    }
  }
Exemple #3
0
  private Slice writeWriteBatch(WriteBatchImpl updates, long sequenceBegin) {
    Slice record = Slices.allocate(SIZE_OF_LONG + SIZE_OF_INT + updates.getApproximateSize());
    final SliceOutput sliceOutput = record.output();
    sliceOutput.writeLong(sequenceBegin);
    sliceOutput.writeInt(updates.size());
    updates.forEach(
        new Handler() {
          @Override
          public void put(Slice key, Slice value) {
            sliceOutput.writeByte(VALUE.getPersistentId());
            writeLengthPrefixedBytes(sliceOutput, key);
            writeLengthPrefixedBytes(sliceOutput, value);
          }

          @Override
          public void delete(Slice key) {
            sliceOutput.writeByte(DELETION.getPersistentId());
            writeLengthPrefixedBytes(sliceOutput, key);
          }
        });
    return record.slice(0, sliceOutput.size());
  }
Exemple #4
0
  public Snapshot writeInternal(WriteBatchImpl updates, WriteOptions options) throws DBException {
    checkBackgroundException();
    mutex.lock();
    try {
      long sequenceEnd;
      if (updates.size() != 0) {
        makeRoomForWrite(false);

        // Get sequence numbers for this change set
        final long sequenceBegin = versions.getLastSequence() + 1;
        sequenceEnd = sequenceBegin + updates.size() - 1;

        // Reserve this sequence in the version set
        versions.setLastSequence(sequenceEnd);

        // Log write
        Slice record = writeWriteBatch(updates, sequenceBegin);
        try {
          log.addRecord(record, options.sync());
        } catch (IOException e) {
          throw Throwables.propagate(e);
        }

        // Update memtable
        updates.forEach(new InsertIntoHandler(memTable, sequenceBegin));
      } else {
        sequenceEnd = versions.getLastSequence();
      }

      if (options.snapshot()) {
        return new SnapshotImpl(versions.getCurrent(), sequenceEnd);
      } else {
        return null;
      }
    } finally {
      mutex.unlock();
    }
  }