⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 recordstore.java

📁 J2me唆哈的代码
💻 JAVA
📖 第 1 页 / 共 4 页
字号:
    public int[] getRecordIDs() {
        if (dbraf == null) { // lower overhead than checkOpen()
            return null;
        }

        int index = 0;
        int[] tmp = new int[dbNumLiveRecords];
        int offset = dbFirstRecordOffset; // start at beginning of file
        RecordHeader rh = new RecordHeader();

        try {
            while (offset != 0) {
                rh.load(offset);
                if (rh.id > 0) {
                    tmp[index++] = rh.id;
                }
                offset = rh.nextOffset;
            }
        } catch (java.io.IOException ioe) {
            return null;
        }
        return tmp;
    }

    private void compactRecords() throws RecordStoreNotOpenException,
            RecordStoreException {
        int offset = dbDataStart; // after record store header structure
        int target = 0;
        int bytesLeft;
        int numToMove;
        byte[] chunkBuffer = new byte[DB_COMPACTBUFFER_SIZE];

        RecordHeader rh = new RecordHeader();

        int prevRec = 0;
        while (offset < dbDataEnd) {
            try {
                rh.load(offset);
            } catch (java.io.IOException ioe) {
                // NOTE - should throw some exception here
                System.out.println("Unexpected IOException in CompactRS!");
            }

            if (rh.id == -1) { // a free block
                if (target == 0) {
                    target = offset;
                } // else skip free block
                offset += rh.blockSize;
            } else { // a record block
                if (target == 0) {
                    // No move needed so far.
                    prevRec = offset;
                    offset += rh.blockSize;
                } else {
                    int old_offset = target;
                    // Move a record back in the file
                    rh.offset = target;
                    rh.nextOffset = prevRec;
                    try {
                        rh.store();
                        offset += DB_RECORD_HEADER_LENGTH;
                        target += DB_RECORD_HEADER_LENGTH;
                        bytesLeft = (rh.blockSize - DB_RECORD_HEADER_LENGTH);
                        while (bytesLeft > 0) {
                            if (bytesLeft < DB_COMPACTBUFFER_SIZE) {
                                numToMove = bytesLeft;
                            } else {
                                numToMove = DB_COMPACTBUFFER_SIZE;
                            }
                            dbraf.seek(offset);
                            dbraf.read(chunkBuffer, 0, numToMove);
                            dbraf.seek(target);
                            dbraf.write(chunkBuffer, 0, numToMove);
                            offset += numToMove;
                            target += numToMove;
                            bytesLeft -= numToMove;
                        }
                    } catch (java.io.IOException ioe) {
                        // NOTE - should throw some exception here
                        System.out.println("Unexpected IOException "
                                + "in CompactRS!");
                    }
                    prevRec = old_offset;
                }
            }
        }
        if (rh.offset != 0) {
            dbDataEnd = rh.offset + rh.blockSize;
        }
        dbFirstRecordOffset = rh.offset;
        dbFirstFreeBlockOffset = 0;
        storeDBState();
    }

    private class RecordHeader {
        /*
         * Each record is laid out in the file system as follows: Bytes - Usage
         * 00-03 - Record ID 04-07 - Next record offset 08-11 - Record
         * size...total (in bytes, big endian). 12-15 - Length of Data. This is
         * stored separately for the case where a record has gotten smaller.
         * 16-xx - Data
         * 
         * Each free block is laid out in the file system as follows: Bytes -
         * Usage 00-03 - Free block ID (set to -1) 04-07 - Next record offset
         * (not used by free block) 08-11 - Free block size in bytes (in bytes,
         * big endian) 12-15 - Next free block offset (zero if this is the last
         * free block) 16-xx - Data (not used by free block)
         */

        /** REC_ID offset */
        private static final int REC_ID = 0;

        /** NEXT_OFFSET offset */
        private static final int NEXT_OFFSET = 4;

        /** BLOCK_SIZE offset */
        private static final int BLOCK_SIZE = 8;

        /**
         * data length offset of record block or next free block offset of free
         * block
         */
        private static final int DATALEN_OR_NEXTFREE = 12;

        /** DATA_OFFSET offset (offset to record data) */
        private static final int DATA_OFFSET = 16;

        /** offset of the record block or free block in RSFile */
        int offset;

        /** record id -or- -1 if free block */
        int id;

        /** next record offset */
        int nextOffset;

        /** record size -or- free block size */
        int blockSize;

        /** record length -or- next free block offset */
        int dataLenOrNextFree;

        /**
         * default RecordHeader constructor - creates an empty header
         */
        RecordHeader() {
        }

        /**
         * Creates a new RecordHeader and initializes it with data read from a
         * RecordStoreFile at offset <code> offset </code>.
         * 
         * @param _offset
         *            seek offset in RecordStoreFile of desired RecordHeader.
         * 
         * @exception IOException
         *                if there is an error reading the underlying
         *                RecordStoreFile.
         */
        RecordHeader(int _offset) throws java.io.IOException {
            load(_offset);
        }

        /**
         * Creates a new RecordHeader and initializes it with data provided in
         * the parameters. This RecordHeader will not be stored (on disk/in
         * persistant storage) until the <code> store </code> method is called.
         * 
         * @param _offset
         *            offset in RecordStoreFile where this RecordHeader should
         *            be stored.
         * @param _id
         *            record id of this new RecordHeader
         * 
         * @param next_offset
         *            next RecordHeader in linked list of records.
         * @param size
         *            total size of the storage block allocated for this record
         *            or free block.
         * @param len_or_free
         *            length of data in this record (may be shorter than
         *            <code>size</code> -or- next free block if this header is
         *            a free block header
         */
        RecordHeader(int _offset, int _id, int next_offset, int size,
                int len_or_free) {
            offset = _offset;
            id = _id;
            nextOffset = next_offset;
            blockSize = size;
            dataLenOrNextFree = len_or_free;
        }

        /**
         * Re-uses a RecordHeader and initializes it with data read from a
         * RecordStoreFile at offset <code> offset </code>.
         * 
         * @param _offset
         *            seek offset in RecordStoreFile of desired RecordHeader.
         * 
         * @exception IOException
         *                if there is an error reading the underlying
         *                RecordStoreFile
         */
        void load(int _offset) throws java.io.IOException {
            offset = _offset;

            // read rec header from file.
            dbraf.seek(offset);
            dbraf.read(recHeadBuf, 0, DB_RECORD_HEADER_LENGTH);

            id = RecordStore.getInt(recHeadBuf, REC_ID);
            nextOffset = RecordStore.getInt(recHeadBuf, NEXT_OFFSET);
            blockSize = RecordStore.getInt(recHeadBuf, BLOCK_SIZE);
            dataLenOrNextFree = RecordStore.getInt(recHeadBuf,
                    DATALEN_OR_NEXTFREE);
        }

        /**
         * Flushes an in memory RecordHeader instance to storage in a a
         * RecordStoreFile at <code>offset</code>.
         * 
         * @exception IOException
         *                if there is an error writing the underlying
         *                RecordStoreFile
         */
        void store() throws java.io.IOException {
            RecordStore.putInt(id, recHeadBuf, REC_ID);
            RecordStore.putInt(nextOffset, recHeadBuf, NEXT_OFFSET);
            RecordStore.putInt(blockSize, recHeadBuf, BLOCK_SIZE);
            RecordStore.putInt(dataLenOrNextFree, recHeadBuf,
                    DATALEN_OR_NEXTFREE);

            // write record header;
            dbraf.seek(offset);
            dbraf.write(recHeadBuf, 0, DB_RECORD_HEADER_LENGTH);
        }

        /**
         * Reads data associated with this record from storage (a
         * RecordStoreFile) at <code>offset</code>.
         * 
         * Assumes CALLER has ensured <code>dataLenOrNextFree</code> is set
         * correctly, and that <code>dataLenOrNextFree</code> bytes will fit
         * into the array.
         * 
         * @param buf
         *            data is read into this buffer.
         * @param _offset
         *            position in <code>buf</code> to start reading data into.
         * 
         * @return number of bytes read.
         * 
         * @exception IOException
         *                if there is an error reading the underlying
         *                RecordStoreFile
         */
        int read(byte[] buf, int _offset) throws java.io.IOException {
            dbraf.seek(offset + DATA_OFFSET);
            return dbraf.read(buf, _offset, dataLenOrNextFree);
        }

        /**
         * Writes data associated with this record to storage (a
         * RecordStoreFile) at <code>offset</code>.
         * 
         * Assumes CALLER has ensured <code>dataLenOrNextFree</code> is set
         * correctly.
         * 
         * @param buf
         *            data to store in this record.
         * @param _offset
         *            point in <code>buf</code> to begin write from.
         * 
         * @exception IOException
         *                if there is an error writing the underlying
         *                RecordStoreFile.
         */
        void write(byte[] buf, int _offset) throws java.io.IOException {
            dbraf.seek(offset + DATA_OFFSET);
            dbraf.write(buf, _offset, dataLenOrNextFree);
        }
    }

    private class RecordHeaderCache {

        /** a cache of RecordHeader objects */
        private RecordHeader[] mCache;

        RecordHeaderCache(int size) {
            mCache = new RecordHeader[size];
        }

        RecordHeader get(int rec_id) {
            int idx = rec_id % mCache.length;
            RecordHeader rh = (RecordHeader) mCache[idx];
            if ((mCache[idx] != null) && (mCache[idx].id != rec_id)) {
                return null;
            }
            return rh;
        }

        void insert(RecordHeader rh) {
            int idx = rh.id % mCache.length;
            mCache[idx] = rh;
        }

        void invalidate(int rec_id) {
            if (rec_id > 0) {
                int idx = rec_id % mCache.length;
                if ((mCache[idx] != null) && (mCache[idx].id == rec_id)) {
                    mCache[idx] = null;
                }
            }
        }
    }

    private boolean checkOwner() {

        // varies with currently running midlet suite
        String myUid = RecordStoreFile.getUniqueIdPath(recordStoreName);
        // fixed at the time dbraf is created
        String rsfUid = dbraf.getUniqueIdPath();

        if (myUid.equals(rsfUid)) {
            return true;
        } else {
            return false;
        }
    }

    private boolean checkWritable() {
        if (checkOwner()) {
            return true;
        } else {
            if (dbAuthMode == AUTHMODE_ANY) { // Read-Write mode
                return true;
            }
        }
        return false;
    }

}

⌨️ 快捷键说明

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