Ejemplo n.º 1
0
  @Override
  public void compact() {

    if (readOnly) throw new IllegalAccessError();

    final File indexFile = index.getFile();
    final File physFile = phys.getFile();

    final int rafMode;
    if (index instanceof Volume.FileChannelVol) {
      rafMode = 2;
    } else if (index instanceof Volume.MappedFileVol && phys instanceof Volume.FileChannelVol) {
      rafMode = 1;
    } else {
      rafMode = 0;
    }

    lockAllWrite();
    try {
      final File compactedFile =
          new File(
              (indexFile != null ? indexFile : File.createTempFile("mapdb", "compact"))
                  + ".compact");
      Volume.Factory fab =
          Volume.fileFactory(compactedFile, rafMode, false, sizeLimit, CC.VOLUME_SLICE_SHIFT, 0);
      StoreDirect store2 =
          new StoreDirect(fab, false, false, 5, false, 0L, checksum, compress, password, false, 0);

      compactPreUnderLock();

      index.putLong(IO_PHYS_SIZE, physSize);
      index.putLong(IO_INDEX_SIZE, indexSize);
      index.putLong(IO_FREE_SIZE, freeSize);

      // create secondary files for compaction
      store2.lockAllWrite();

      // transfer stack of free recids
      // TODO long stack take modifies the original store
      for (long recid = longStackTake(IO_FREE_RECID, false);
          recid != 0;
          recid = longStackTake(IO_FREE_RECID, false)) {
        store2.longStackPut(IO_FREE_RECID, recid, false);
      }

      // iterate over recids and transfer physical records
      store2.index.putLong(IO_INDEX_SIZE, indexSize);

      for (long ioRecid = IO_USER_START; ioRecid < indexSize; ioRecid += 8) {
        byte[] bb = get2(ioRecid, Serializer.BYTE_ARRAY_NOSIZE);
        store2.index.ensureAvailable(ioRecid + 8);
        if (bb == null || bb.length == 0) {
          store2.index.putLong(ioRecid, 0);
        } else {
          DataIO.DataOutputByteArray out = serialize(bb, Serializer.BYTE_ARRAY_NOSIZE);
          long[] indexVals = store2.physAllocate(out.pos, true, false);
          store2.put2(out, ioRecid, indexVals);
        }
      }

      File indexFile2 = store2.index.getFile();
      File physFile2 = store2.phys.getFile();
      store2.unlockAllWrite();

      final boolean useDirectBuffer =
          index instanceof Volume.MemoryVol && ((Volume.MemoryVol) index).useDirectBuffer;
      index.sync(); // TODO is sync needed here?
      index.close();
      index = null;
      phys.sync(); // TODO is sync needed here?
      phys.close();
      phys = null;

      if (indexFile != null) {
        final long time = System.currentTimeMillis();
        final File indexFile_ =
            indexFile != null ? new File(indexFile.getPath() + "_" + time + "_orig") : null;
        final File physFile_ =
            physFile != null ? new File(physFile.getPath() + "_" + time + "_orig") : null;

        store2.close();
        // not in memory, so just rename files
        if (!indexFile.renameTo(indexFile_)) throw new AssertionError("could not rename file");
        if (!physFile.renameTo(physFile_)) throw new AssertionError("could not rename file");

        if (!indexFile2.renameTo(indexFile)) throw new AssertionError("could not rename file");
        // TODO process may fail in middle of rename, analyze sequence and add recovery
        if (!physFile2.renameTo(physFile)) throw new AssertionError("could not rename file");

        final Volume.Factory fac2 =
            Volume.fileFactory(indexFile, rafMode, false, sizeLimit, CC.VOLUME_SLICE_SHIFT, 0);
        index = fac2.createIndexVolume();
        phys = fac2.createPhysVolume();

        indexFile_.delete();
        physFile_.delete();
      } else {
        // in memory, so copy files into memory
        Volume indexVol2 = new Volume.MemoryVol(useDirectBuffer, sizeLimit, CC.VOLUME_SLICE_SHIFT);
        Volume.volumeTransfer(indexSize, store2.index, indexVol2);
        Volume physVol2 = new Volume.MemoryVol(useDirectBuffer, sizeLimit, CC.VOLUME_SLICE_SHIFT);
        Volume.volumeTransfer(store2.physSize, store2.phys, physVol2);

        store2.close();

        index = indexVol2;
        phys = physVol2;
      }

      physSize = store2.physSize;
      freeSize = store2.freeSize;
      index.putLong(IO_PHYS_SIZE, physSize);
      index.putLong(IO_INDEX_SIZE, indexSize);
      index.putLong(IO_FREE_SIZE, freeSize);
      index.putLong(IO_INDEX_SUM, indexHeaderChecksum());

      maxUsedIoList = IO_USER_START - 8;
      while (index.getLong(maxUsedIoList) != 0 && maxUsedIoList > IO_FREE_RECID) maxUsedIoList -= 8;

      compactPostUnderLock();

    } catch (IOException e) {
      throw new IOError(e);
    } finally {
      unlockAllWrite();
    }
  }
Ejemplo n.º 2
0
 @After
 public void close() {
   engine.close();
 }