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 boolean flushSome() { synchronized (myLock) { boolean okRecords = myRecordsTable.flushSome(MAX_PAGES_TO_FLUSH_AT_A_TIME); boolean okData = myDataTable.flushSome(MAX_PAGES_TO_FLUSH_AT_A_TIME); return okRecords && okData; } }
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."); } }
private void tryInit(String storageFilePath, PagePool pool, int retryCount) throws IOException { convertFromOldExtensions(storageFilePath); final File recordsFile = new File(storageFilePath + INDEX_EXTENSION); final File dataFile = new File(storageFilePath + DATA_EXTENSION); if (recordsFile.exists() != dataFile.exists()) { deleteFiles(storageFilePath); } FileUtil.createIfDoesntExist(recordsFile); FileUtil.createIfDoesntExist(dataFile); AbstractRecordsTable recordsTable = null; DataTable dataTable; try { recordsTable = createRecordsTable(pool, recordsFile); dataTable = new DataTable(dataFile, pool); } catch (IOException e) { LOG.info(e.getMessage()); if (recordsTable != null) { recordsTable.dispose(); } boolean deleted = deleteFiles(storageFilePath); if (!deleted) { throw new IOException("Can't delete caches at: " + storageFilePath); } if (retryCount >= 5) { throw new IOException("Can't create storage at: " + storageFilePath); } tryInit(storageFilePath, pool, retryCount + 1); return; } myRecordsTable = recordsTable; myDataTable = dataTable; myPool = pool; if (myDataTable.isCompactNecessary()) { compact(storageFilePath); } }
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); } } }
public void dispose() { synchronized (myLock) { myRecordsTable.dispose(); myDataTable.dispose(); } }
protected void doDeleteRecord(int record) throws IOException { myDataTable.reclaimSpace(myRecordsTable.getCapacity(record)); myRecordsTable.deleteRecord(record); }
public boolean isDirty() { synchronized (myLock) { return myDataTable.isDirty() || myRecordsTable.isDirty(); } }
public void force() { synchronized (myLock) { myDataTable.force(); myRecordsTable.force(); } }