public void writeBytes(int record, ByteSequence bytes, boolean fixedSize) throws IOException { synchronized (myLock) { final int requiredLength = bytes.getLength(); final int currentCapacity = myRecordsTable.getCapacity(record); final int currentSize = myRecordsTable.getSize(record); assert currentSize >= 0; if (requiredLength == 0 && currentSize == 0) return; final long address; if (currentCapacity >= requiredLength) { address = myRecordsTable.getAddress(record); } else { myDataTable.reclaimSpace(currentCapacity); int newCapacity = fixedSize ? requiredLength : myCapacityAllocationPolicy.calculateCapacity(requiredLength); if (newCapacity < requiredLength) newCapacity = requiredLength; address = myDataTable.allocateSpace(newCapacity); myRecordsTable.setAddress(record, address); myRecordsTable.setCapacity(record, newCapacity); } myDataTable.writeBytes(address, bytes.getBytes(), bytes.getOffset(), bytes.getLength()); myRecordsTable.setSize(record, requiredLength); } }
public void checkSanity(final int record) { synchronized (myLock) { final int size = myRecordsTable.getSize(record); assert size >= 0; final long address = myRecordsTable.getAddress(record); assert address >= 0; assert address + size < myDataTable.getFileSize(); } }
protected byte[] readBytes(int record) throws IOException { synchronized (myLock) { final int length = myRecordsTable.getSize(record); if (length == 0) return ArrayUtil.EMPTY_BYTE_ARRAY; assert length > 0; final long address = myRecordsTable.getAddress(record); byte[] result = new byte[length]; myDataTable.readBytes(address, result); return result; } }
private void compact(final String path) { synchronized (myLock) { LOG.info( "Space waste in " + path + " is " + myDataTable.getWaste() + " bytes. Compacting now."); long start = System.currentTimeMillis(); try { File newDataFile = new File(path + ".storageData.backup"); FileUtil.delete(newDataFile); FileUtil.createIfDoesntExist(newDataFile); File oldDataFile = new File(path + DATA_EXTENSION); DataTable newDataTable = new DataTable(newDataFile, myPool); final int count = myRecordsTable.getRecordsCount(); for (int i = 1; i <= count; i++) { final long addr = myRecordsTable.getAddress(i); final int size = myRecordsTable.getSize(i); if (size > 0) { assert addr > 0; final int capacity = myCapacityAllocationPolicy.calculateCapacity(size); final long newaddr = newDataTable.allocateSpace(capacity); final byte[] bytes = new byte[size]; myDataTable.readBytes(addr, bytes); newDataTable.writeBytes(newaddr, bytes); myRecordsTable.setAddress(i, newaddr); myRecordsTable.setCapacity(i, capacity); } } myDataTable.dispose(); newDataTable.dispose(); if (!FileUtil.delete(oldDataFile)) { throw new IOException("Can't delete file: " + oldDataFile); } newDataFile.renameTo(oldDataFile); myDataTable = new DataTable(oldDataFile, myPool); } catch (IOException e) { LOG.info("Compact failed: " + e.getMessage()); } long timedelta = System.currentTimeMillis() - start; LOG.info("Done compacting in " + timedelta + "msec."); } }
protected void appendBytes(int record, ByteSequence bytes) throws IOException { final int delta = bytes.getLength(); if (delta == 0) return; synchronized (myLock) { int capacity = myRecordsTable.getCapacity(record); int oldSize = myRecordsTable.getSize(record); int newSize = oldSize + delta; if (newSize > capacity) { if (oldSize > 0) { final byte[] newbytes = new byte[newSize]; System.arraycopy(readBytes(record), 0, newbytes, 0, oldSize); System.arraycopy(bytes.getBytes(), bytes.getOffset(), newbytes, oldSize, delta); writeBytes(record, new ByteSequence(newbytes), false); } else { writeBytes(record, bytes, false); } } else { long address = myRecordsTable.getAddress(record) + oldSize; myDataTable.writeBytes(address, bytes.getBytes(), bytes.getOffset(), bytes.getLength()); myRecordsTable.setSize(record, newSize); } } }