@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(); } } }
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()); }
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; }
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; }