recordstoreindex.java

来自「This is a resource based on j2me embedde」· Java 代码 · 共 1,179 行 · 第 1/3 页

JAVA
1,179
字号
/* * * * Copyright  1990-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER *  * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version * 2 only, as published by the Free Software Foundation. *  * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License version 2 for more details (a copy is * included at /legal/license.txt). *  * You should have received a copy of the GNU General Public License * version 2 along with this work; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA *  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa * Clara, CA 95054 or visit www.sun.com if you need additional * information or have any questions. */package com.sun.midp.rms;import java.io.IOException;import javax.microedition.rms.*;import com.sun.midp.log.Logging;import com.sun.midp.log.LogChannels;/** * A class implementing a index of the record store. * *  Methods used by the RecordStoreImpl *      close() *      deleteIndex() *      getRecordIDs() *      getRecordHeader() *      getFreeBlock() *      updateBlock() *      deleteRecordIndex() *      removeBlock() * */class RecordStoreIndex {    /*     * The layout of the database file is as follows:     *     * Bytes - Usage     * 00-03 - Size of index file (big endian)     * 04-07 - Offset to recordId tree root (big endian)     * 08-11 - Offset to free block tree root (big endian)     * 12-15 - Offset to the list of free tree blocks (big endian)     * 16-xx - Tree Blocks     */    /** IDX_SIZE offset */    static final int IDX0_SIZE = 0;    /** IDX_ID_ROOT offset */    static final int IDX1_ID_ROOT = 4;    /** IDX_FREE_ROOT offset */    static final int IDX2_FREE_BLOCK_ROOT = 8;    /** IDX_FREE_NODES offset */    static final int IDX3_FREE_NODE_HEAD = 12;    /** Size of the index header */    static final int IDX_HEADER_SIZE = 16;    /** The maximum number of data elements in each  node */    static final int NODE_ELEMENTS = 8;    /** The size of the tree blocks */    static final int NODE_SIZE = 4 + (NODE_ELEMENTS * (4 + 4 + 4));    /** The Record Store that this object indexes */    private AbstractRecordStoreImpl recordStore;    /** The Record Store database file */    private AbstractRecordStoreFile dbFile;    /** The Record Store database index file */    private AbstractRecordStoreFile idxFile;    /** The header of the index file */    private byte[] idxHeader = new byte[IDX_HEADER_SIZE];    /** The node buffer for initializing nodes */    private byte[] nodeBuf = new byte[NODE_SIZE];    /**     * Constructor for creating an index object for the given Record Store.     *     * @param rs record store that this object indexes     * @param suiteId unique ID of the suite that owns the store     * @param recordStoreName a string to name the record store     *     * @exception IOException if there are any file errors     */    RecordStoreIndex(AbstractRecordStoreImpl rs, int suiteId,                     String recordStoreName) throws IOException {        recordStore = rs;        if (rs != null) {            dbFile = rs.getDbFile();        }        boolean exist =          RecordStoreUtil.exists(suiteId, recordStoreName,                                 AbstractRecordStoreFile.IDX_EXTENSION);        idxFile = rs.createIndexFile(suiteId, recordStoreName);        if (exist) {            // load header            if (idxFile.read(idxHeader) != IDX_HEADER_SIZE) {               throw new IOException("Index file corrupted");            }        } else {            RecordStoreUtil.putInt(IDX_HEADER_SIZE + NODE_SIZE * 2,                                   idxHeader, IDX0_SIZE);            RecordStoreUtil.putInt(IDX_HEADER_SIZE, idxHeader, IDX1_ID_ROOT);            RecordStoreUtil.putInt(IDX_HEADER_SIZE + NODE_SIZE,                                   idxHeader, IDX2_FREE_BLOCK_ROOT);            idxFile.write(idxHeader);            idxFile.write(nodeBuf);            idxFile.write(nodeBuf);            idxFile.commitWrite();        }    }    /**     * Closes the index file.     *     * @exception IOException if there are any file errors     */    void close() throws IOException {        idxFile.close();    }    /**     * Deletes index files of the named record store. MIDlet suites are     * only allowed to delete their own record stores.     *     * @param suiteId ID of the MIDlet suite that owns the record store     * @param recordStoreName the MIDlet suite unique record store to     *          delete     * @return <code>true</code> if file was found and deleted successfully,     *         <code>false</code> otherwise.     */    static boolean deleteIndex(int suiteId, String recordStoreName) {        return RecordStoreUtil.quietDeleteFile(suiteId,                                   recordStoreName,                                   AbstractRecordStoreFile.IDX_EXTENSION);    }    /**     * Returns all of the recordId's currently in the record store index.     *     * @return an array of the recordId's currently in the index.     */    int[] getRecordIDs() {        int count = recordStore.getNumRecords();        int[] recordIdList = new int[count];        getRecordIds(recordIdList);        return recordIdList;    }    /**     * Returns places all of the recordId's in the index.     * If the array is not big enough, the recordId list will be     * limited to the size of the given array.     *     * @param recordIdList array to place the recordId's     *     * @return the number of recordId's placed in the array.     */    int getRecordIds(int[] recordIdList) {        int count = 0;        try {            Node node = new Node(idxFile);            node.load(getRecordIdRootOffset());            count = walk(node, recordIdList, 0);        } catch (IOException e) {            if (Logging.REPORT_LEVEL <= Logging.ERROR) {                Logging.report(Logging.ERROR, LogChannels.LC_RMS,                               "Could not walk the tree");            }        }        return count;    }    /**     *  Finds the record header for the given record and returns the     *  offset to the header.     *     * @param recordId the ID of the record to use in this operation     * @param header the header of the block to free     *     * @exception IOException if there is an error accessing the db file     * @exception InvalidRecordIDException if the recordId is invalid     *     * @return the offset in the db file of the block added     */    int getRecordHeader(int recordId, byte[] header)        throws IOException, InvalidRecordIDException {        if (recordId <= 0) {            throw new InvalidRecordIDException("error finding record data");        }        int loc_offset = getBlockOffsetOfRecord(recordId);        if (loc_offset == 0) {            // did not find the recordId            throw new InvalidRecordIDException();        }        // read the header        dbFile.seek(loc_offset);        // read the block header        if (dbFile.read(header) != AbstractRecordStoreImpl.BLOCK_HEADER_SIZE) {            // did not find the recordId            throw new InvalidRecordIDException();        }        return loc_offset;    }    /**     *  Returns the offset to the header for the given recordId     *     * @param recordId the ID of the record to use in this operation     *     * @exception IOException if there is an error accessing the db file     * @exception InvalidRecordIDException if the recordId is invalid     *     * @return the offset in the db file of the record block     */    int getBlockOffsetOfRecord(int recordId)        throws IOException, InvalidRecordIDException {        Node node = new Node(idxFile);        node.load(getRecordIdRootOffset());        int loc_offset = getKeyValue(node, recordId);        if (loc_offset == 0) {            // did not find the recordId            throw new InvalidRecordIDException();        }        return loc_offset;    }    /**     * Updates the index of the given block and its offset.     *     * @param blockOffset the offset in db file to the block to update     * @param header the header of the block to update     *     * @exception IOException if there is an error accessing the index file     */    void updateBlock(int blockOffset, byte[] header) throws IOException {        int recordId = RecordStoreUtil.getInt(header, 0);        if (recordId > 0) {            updateRecordId(recordId, blockOffset);        }    }    /**     * Updates the given recordId with the given offset. Adds the     * recordId if it did not already exist.     *     * @param recordId the id of the record     * @param blockOffset the offset in db file to the block to update     *     * @exception IOException if there is an error accessing the index file     */    void updateRecordId(int recordId, int blockOffset) throws IOException {        Node node = new Node(idxFile);        node.load(getRecordIdRootOffset());        // update the key        int newOffset = updateKey(node, recordId, blockOffset);        // check if a new root node was added        if (newOffset > 0) {            // save the new root node offset            setRecordIdRootOffset(newOffset);        }    }    /**     * The record is deleted from the record store index.     *     * @param recordId the ID of the record index to delete     *     * @exception IOException if there is an error accessing the db index     */    void deleteRecordIndex(int recordId) throws IOException {        int rootOffset = getRecordIdRootOffset();        Node node = new Node(idxFile);        node.load(rootOffset);        // find the key's node        int loc_offset = deleteKey(node, recordId);        // check if the offset of a new root was returned        if (loc_offset > 0) {            // new root, free old one            freeNode(rootOffset);            // save the new root            setRecordIdRootOffset(loc_offset);        }    }    /**     * 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;        // 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));            // check for a free block big enough to hold the data            if (currentId < 0 && currentSize >= targetSize) {                // a free block                return currentOffset;            }            // added the block size to the currentOffset            currentOffset += currentSize;        }        return 0;    }    /**     * Removes the given block from the list of free blocks.     *     * @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 {    }    /**     *  Getter/Setter for header info     */    /**

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?