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 + -
显示快捷键?