recordstoreindex.java
来自「This is a resource based on j2me embedde」· Java 代码 · 共 480 行 · 第 1/2 页
JAVA
480 行
* Finds the record header for the given record and returns the * offset to the header without using the cache. * * @param recordId the ID of the record to use in this operation * @param header a buffer that receives the header of the block * @return the offset in the db file of the block * @exception IOException * @exception InvalidRecordIDException */ protected int getRecordHeader_NoCache(int recordId, byte[] header) throws IOException, InvalidRecordIDException { final int beginningOffset = AbstractRecordStoreImpl.DB_HEADER_SIZE; final int endOffset = recordStore.getSize(); int resultOffset = INVALID_OFFSET; if (null != recordIdOffsets &&recordIdOffsets.LastSeenOffset != recordIdOffsets.NO_OFFSET) { resultOffset = getRecordHeader_SearchFromTo(recordId, header, recordIdOffsets.LastSeenOffset, endOffset); } if (INVALID_OFFSET == resultOffset) { resultOffset = getRecordHeader_SearchFromTo(recordId, header, beginningOffset, endOffset); } if (INVALID_OFFSET == resultOffset) { throw new InvalidRecordIDException("error finding record"); } return resultOffset; } /** * A helper function for getRecordHeader(). * * @param recordId the ID of the record to use in this operation * @param header a buffer that receives the header of the block * @param offsetFrom offset in the file to start search from * @param offsetUpto offset in the file to abandon search at * @return the offset in the db file of the block, or * -1 (INVALID_OFFSET) in place * of InvalidRecordIDException * @exception IOException * @exception InvalidRecordIDException */ protected int getRecordHeader_SearchFromTo(int recordId, byte[] header, int offsetFrom, int offsetUpto) throws IOException, InvalidRecordIDException { // (we could start from last known index; I tried this, but noticed // no improvement) // search through the data blocks for a matching record int currentId = 0; int currentOffset = offsetFrom; int currentSize = 0; while (currentId != recordId) { // seek to the next offset currentOffset += currentSize; // IMPL_NOTE: is it correct to invoke getSize() once? // IMPL_NOTE: So far it is -- the db file is locked... if (currentOffset >= offsetUpto) { // reached the end and did not find the recordId return INVALID_OFFSET; } dbFile.seek(currentOffset); // read the block header if (dbFile.read(header) != AbstractRecordStoreImpl.BLOCK_HEADER_SIZE) { // did not find the recordId return INVALID_OFFSET; // have a chance to retry } currentId = RecordStoreUtil.getInt(header, 0); currentSize = RecordStoreUtil. calculateBlockSize(RecordStoreUtil.getInt(header, 4)); if (null != recordIdOffsets) { recordIdOffsets.setElementAt(currentOffset, recordId); recordIdOffsets.LastSeenOffset = currentOffset; // if we had to repeat search from the beginning, there has been // something wrong, and it's ok to forget where we have been. // Normally, LastSeenOffset will only grow. } } return currentOffset; } /** * Searches for a free block large enough for the record. * * @param header a block header with the size set to the record data size * * @exception IOException if there is an error accessing the db file * * @return the offset in the db file of the block added */ int getFreeBlock(byte[] header) throws IOException { int targetSize = RecordStoreUtil. calculateBlockSize(RecordStoreUtil.getInt(header, 4)); int currentId = 0; int currentOffset = AbstractRecordStoreImpl.DB_HEADER_SIZE; int currentSize = 0; if (Logging.REPORT_LEVEL <= Logging.INFORMATION) { Logging.report(Logging.INFORMATION, LogChannels.LC_RMS, "getFreeBlock recordId = " + RecordStoreUtil.getInt(header, 0) + " numBytes = " + RecordStoreUtil.getInt(header, 4) + " targetSize = " + targetSize); } // search through the data blocks for a free block that is large enough while (currentOffset < recordStore.getSize()) { // seek to the next offset dbFile.seek(currentOffset); // read the block header if (dbFile.read(header) != AbstractRecordStoreImpl.BLOCK_HEADER_SIZE) { // did not find the recordId throw new IOException(); } currentId = RecordStoreUtil.getInt(header, 0); currentSize = RecordStoreUtil. calculateBlockSize(RecordStoreUtil.getInt(header, 4)); if (Logging.REPORT_LEVEL <= Logging.INFORMATION) { Logging.report(Logging.INFORMATION, LogChannels.LC_RMS, "currentId = " + currentId + " currentSize = " + currentSize); } // check for a free block big enough to hold the data if (currentId < 0 && currentSize >= targetSize) { if (Logging.REPORT_LEVEL <= Logging.INFORMATION) { Logging.report(Logging.INFORMATION, LogChannels.LC_RMS, "found free block at offset " + currentOffset); } // a free block return currentOffset; } // added the block size to the currentOffset currentOffset += currentSize; } return 0; } /** * Updates the index of the given block and its offset. * * Called from RecordStoreImpl.compactRecords() * after the block has been moved. * Called from RecordStoreImpl.writeBlock() * after the block has been written. * * @param blockOffset the offset in db file to the block to update * @param header the header of the block to update * * @exception java.io.IOException if there is an error * accessing the db file */ void updateBlock(int blockOffset, byte[] header) throws IOException { if (Logging.REPORT_LEVEL <= Logging.INFORMATION) { Logging.report(Logging.INFORMATION, LogChannels.LC_RMS, "updateBlock recordId = " + RecordStoreUtil.getInt(header, 0) + " numBytes = " + RecordStoreUtil.getInt(header, 4) + " blockOffset = " + blockOffset); } int recordId = RecordStoreUtil.getInt(header, 0); if (null != recordIdOffsets) { recordIdOffsets.setElementAt(blockOffset, recordId); } } /** * Removes the given block from the index. * * Called from RecordStoreUtil.compactRecords() when a free block * is removed. * * @param blockOffset the offset in db file to the block to remove * @param header the header of the block to remove * * @exception IOException if there is an error accessing the db file */ void removeBlock(int blockOffset, byte[] header) throws IOException { if (Logging.REPORT_LEVEL <= Logging.INFORMATION) { Logging.report(Logging.INFORMATION, LogChannels.LC_RMS, "removeBlock recordId = " + RecordStoreUtil.getInt(header, 0) + " numBytes = " + RecordStoreUtil.getInt(header, 4) + " blockOffset = " + blockOffset); } // blocks get moved, LastSeenOffset may point into the middle // of a record. // In principle, all moved blocks will notify us via UpdateBlock(), // so LastSeenOffset=min(LastSeenOffset,blockOffset) should be ok. if (null != recordIdOffsets) { recordIdOffsets.LastSeenOffset = recordIdOffsets.NO_OFFSET; } } /** * The record is deleted from the record store index. * * Called from RecordStoreImpl.deleteRecord(int recordId) * * @param recordId the ID of the record index to delete * * @exception java.io.IOException if there is an error * accessing the db index */ void deleteRecordIndex(int recordId) throws IOException { if (Logging.REPORT_LEVEL <= Logging.INFORMATION) { Logging.report(Logging.INFORMATION, LogChannels.LC_RMS, "deleteRecordIndex(" + recordId + ")"); } if (null != recordIdOffsets) { recordIdOffsets.removeElementAt(recordId); } }}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?