Beispiel #1
0
  @Override
  public <A> void delete(long recid, Serializer<A> serializer) {
    assert (recid > 0);
    final long ioRecid = IO_USER_START + recid * 8;
    final Lock lock;
    if (disableLocks) {
      lock = null;
    } else {
      lock = locks[Store.lockPos(ioRecid)].writeLock();
      lock.lock();
    }
    try {
      // get index val and zero it out
      final long indexVal = index.getLong(ioRecid);
      index.putLong(ioRecid, 0L | MASK_ARCHIVE);

      if (!spaceReclaimTrack) return; // free space is not tracked, so do not mark stuff as free

      long[] linkedRecords = getLinkedRecordsIndexVals(indexVal);

      // now lock everything and mark free space
      if (!disableLocks) {
        structuralLock.lock();
      }
      try {
        // free recid
        freeIoRecidPut(ioRecid);
        // free first record pointed from indexVal\
        if ((indexVal >>> 48) > 0) freePhysPut(indexVal, false);

        // if there are more linked records, free those as well
        if (linkedRecords != null) {
          for (int i = 0; i < linkedRecords.length && linkedRecords[i] != 0; i++) {
            freePhysPut(linkedRecords[i], false);
          }
        }
      } finally {
        if (!disableLocks) {
          structuralLock.unlock();
        }
      }

    } finally {
      if (!disableLocks) {
        lock.unlock();
      }
    }
  }
Beispiel #2
0
  protected void update2(DataIO.DataOutputByteArray out, long ioRecid) {
    final long indexVal = index.getLong(ioRecid);
    final int size = (int) (indexVal >>> 48);
    final boolean linked = (indexVal & MASK_LINKED) != 0;
    assert (disableLocks || locks[Store.lockPos(ioRecid)].writeLock().isHeldByCurrentThread());

    if (!linked && out.pos > 0 && size > 0 && size2ListIoRecid(size) == size2ListIoRecid(out.pos)) {
      // size did change, but still fits into this location
      final long offset = indexVal & MASK_OFFSET;

      // note: if size would not change, we still have to write MASK_ARCHIVE bit
      index.putLong(ioRecid, (((long) out.pos) << 48) | offset | MASK_ARCHIVE);

      phys.putData(offset, out.buf, 0, out.pos);
    } else {

      long[] indexVals = spaceReclaimTrack ? getLinkedRecordsIndexVals(indexVal) : null;

      if (!disableLocks) {
        structuralLock.lock();
      }
      try {

        if (spaceReclaimTrack) {
          // free first record pointed from indexVal
          if (size > 0) freePhysPut(indexVal, false);

          // if there are more linked records, free those as well
          if (indexVals != null) {
            for (int i = 0; i < indexVals.length && indexVals[i] != 0; i++) {
              freePhysPut(indexVals[i], false);
            }
          }
        }

        indexVals = physAllocate(out.pos, true, false);
      } finally {
        if (!disableLocks) {
          structuralLock.unlock();
        }
      }

      put2(out, ioRecid, indexVals);
    }
    assert (disableLocks || locks[Store.lockPos(ioRecid)].writeLock().isHeldByCurrentThread());
  }
Beispiel #3
0
  protected long longStackTake(final long ioList, boolean recursive) {
    assert (disableLocks || structuralLock.isHeldByCurrentThread());
    assert (ioList >= IO_FREE_RECID && ioList < IO_USER_START) : "wrong ioList: " + ioList;

    long dataOffset = index.getLong(ioList);
    if (dataOffset == 0) return 0; // there is no such list, so just return 0

    long pos = dataOffset >>> 48;
    dataOffset &= MASK_OFFSET;

    if (pos < 8) throw new AssertionError();

    final long ret = phys.getSixLong(dataOffset + pos);

    // was it only record at that page?
    if (pos == 8) {
      // yes, delete this page
      long next = phys.getLong(dataOffset);
      long size = next >>> 48;
      next &= MASK_OFFSET;
      if (next != 0) {
        // update index so it points to previous page
        long nextSize = phys.getUnsignedShort(next);
        assert ((nextSize - 8) % 6 == 0);
        index.putLong(ioList, ((nextSize - 6) << 48) | next);
      } else {
        // zero out index
        index.putLong(ioList, 0L);
        if (maxUsedIoList == ioList) {
          // max value was just deleted, so find new maxima
          while (index.getLong(maxUsedIoList) == 0 && maxUsedIoList > IO_FREE_RECID) {
            maxUsedIoList -= 8;
          }
        }
      }
      // put space used by this page into free list
      freePhysPut((size << 48) | dataOffset, true);
    } else {
      // no, it was not last record at this page, so just decrement the counter
      pos -= 6;
      index.putLong(ioList, (pos << 48) | dataOffset); // TODO update just 2 bytes
    }

    // System.out.println("longStackTake: "+ioList+" - "+ret);

    return ret;
  }
Beispiel #4
0
  protected long freePhysTake(int size, boolean ensureAvail, boolean recursive) {
    assert (disableLocks || structuralLock.isHeldByCurrentThread());
    assert (size > 0);
    // check free space
    if (spaceReclaimReuse) {
      long ret = longStackTake(size2ListIoRecid(size), recursive);
      if (ret != 0) {
        freeSize -= roundTo16(size);
        return ret;
      }
    }
    // try to take large record and split it into two
    if (!recursive && spaceReclaimSplit) {
      for (long s = roundTo16(size) + 16; s < MAX_REC_SIZE; s += 16) {
        final long ioList = size2ListIoRecid(s);
        if (ioList > maxUsedIoList) break;
        long ret = longStackTake(ioList, recursive);
        if (ret != 0) {
          // found larger record, split in two slices, take first, mark second free
          final long offset = ret & MASK_OFFSET;

          long remaining = s - roundTo16(size);
          long markFree = (remaining << 48) | (offset + s - remaining);
          freePhysPut(markFree, recursive);

          freeSize -= roundTo16(s);
          return (((long) size) << 48) | offset;
        }
      }
    }

    // not available, increase file size
    if ((physSize & SLICE_SIZE_MOD_MASK) + size > SLICE_SIZE)
      physSize += SLICE_SIZE - (physSize & SLICE_SIZE_MOD_MASK);
    long physSize2 = physSize;
    physSize = roundTo16(physSize + size);
    if (ensureAvail) phys.ensureAvailable(physSize);
    return physSize2;
  }