recordstoreindex.java

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

JAVA
480
字号
/* * * * 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;/** * This class implements a record offset cache. It enables us to quickly * find offsets for records whose IDs we know. */class OffsetCache extends IntToIntMapper {    /**     * A special value for LastSeenOffset.     * There's a database header at offset 0, and 0 means we have not seen any     * records yet.     */    static final int NO_OFFSET = 0;    /**     * After this offset there's no cached record IDs.     * (An OffsetCache may cache offsets only for already seen records.)     * The value NO_OFFSET is a special value for this variable:     * NO_OFFSET means we have not seen any records yet.     */    public int LastSeenOffset = NO_OFFSET;    /**     * Constructs an empty OffsetCache with the specified initial capacity and     * capacity increment.     *     * @param initialCapacity       the initial capacity     * @param defaultElement        the offset value that gets returned for     *                              record IDs that are not there     * @param capacityIncrement     the amount by which the capacity is     *                              increased when the mapper overflows.     *                              (0 means "to be doubled")     * @exception IllegalArgumentException if the specified initial capacity     *            is negative     */    OffsetCache(int initialCapacity, int defaultElement, int capacityIncrement)    {        super(initialCapacity, defaultElement, capacityIncrement);    }}/** * A class implementing a index of the record store. */class RecordStoreIndex {    /** The Record Store that this object indexes */    private AbstractRecordStoreImpl recordStore;    /** The Record Store database file */    private AbstractRecordStoreFile dbFile;    /** specifies record ID to offset mapping */    private OffsetCache recordIdOffsets;    /**     *  This value will be returned by recordIdOffsets.elementAt() when     *  record id is not found     */    private static final int INVALID_OFFSET = -1;    /**     *  Capacity increment for the offset cache. Zero indicates that capacity     *  has to be doubled each time.     */    private static final int CACHE_CAPACITY_INCREMENT = 0;    /** the initial record offset cache capacity */    private static final int INITIAL_CACHE_CAPACITY = 0x20;    /**     * 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     */    RecordStoreIndex(AbstractRecordStoreImpl rs, int suiteId,                     String recordStoreName) throws IOException {        recordStore = rs;        dbFile = rs.getDbFile();    }    /**     * Closes the index file.     *     * @exception IOException if there are any file errors     */    void close() throws IOException {    }    /**     * Deletes index filed of named record store. There is no index     * file in case of linear index implementation, thus makes     * nothing.     *     * Called from RecordStoreImpl where record store files need to     *     be deleted.     *     * @param suiteId not used     * @param recordStoreName not used     * @return always <code>true</code>     */    static boolean deleteIndex(int suiteId, String recordStoreName) {        return true;    }    /**     * 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 numRecordIDs = recordStore.getNumRecords();        int[] recordIDs = new int[numRecordIDs];        byte[] header = new byte[AbstractRecordStoreImpl.BLOCK_HEADER_SIZE];        int currentOffset = AbstractRecordStoreImpl.DB_HEADER_SIZE;        int currentSize = 0;        int currentRecordId = 0;        int dbSize = recordStore.getSize();        int idx = 0;        while (idx < numRecordIDs) {            if (currentOffset >= dbSize) {                // reached end of db file                break;            }            try {                // seek to the next offset                currentOffset += currentSize;                dbFile.seek(currentOffset);                // read the block header                if (dbFile.read(header) !=                    AbstractRecordStoreImpl.BLOCK_HEADER_SIZE) {                    // error reading header                    break;                }            } catch (java.io.IOException ioe) {                break;            }            currentRecordId = RecordStoreUtil.getInt(header, 0);            if (currentRecordId > 0) {                recordIDs[idx++] = currentRecordId;            }            currentSize = RecordStoreUtil.                calculateBlockSize(RecordStoreUtil.getInt(header, 4));        }        return recordIDs;    }    /**     *  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 a buffer that receives the header of the block     *     * @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");        }        if (null != recordIdOffsets)        {            int offset = recordIdOffsets.elementAt(recordId);            if (offset != recordIdOffsets.defaultValue) {                dbFile.seek(offset);                // read the block header                if (dbFile.read(header) !=                    AbstractRecordStoreImpl.BLOCK_HEADER_SIZE) {                    // did not find the recordId at the returned offset                    // throw away the index then!                    // (in principle, this should never happen)                    recordIdOffsets = null;                }                else                {                    int foundId = RecordStoreUtil.getInt(header, 0);                    if (foundId == recordId) {                        return offset;                    }                }            }        }        if (null == recordIdOffsets) {            recordIdOffsets = new OffsetCache(INITIAL_CACHE_CAPACITY,                                              INVALID_OFFSET,                                              CACHE_CAPACITY_INCREMENT);        }        return getRecordHeader_NoCache(recordId, header);    }    /**     *  A helper function for getRecordHeader().

⌨️ 快捷键说明

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