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

📄 recordstore.java

📁 J2me唆哈的代码
💻 JAVA
📖 第 1 页 / 共 4 页
字号:

                try {
                    if (newData != null) {
                        newrh.write(newData, offset);
                        // NOTE: I/O exception leaves space allocated & unused
                    }
                } catch (java.io.IOException ioe) {
                    throw new RecordStoreException("error moving record "
                            + "data");
                }
            }

            // update database header info and sync to file
            dbVersion++;
            storeDBState();
            notifyRecordChangedListeners(recordId);
        }
    }

    public RecordEnumeration enumerateRecords(RecordFilter filter,
            RecordComparator comparator, boolean keepUpdated)
            throws RecordStoreNotOpenException {
        checkOpen();
        return new RecordEnumerationImpl(this, filter, comparator, keepUpdated);
    }

    /*
     * Private Memory Management Methods
     */

    private RecordHeader findRecord(int recordId, boolean addToCache)
            throws InvalidRecordIDException, java.io.IOException {
        RecordHeader rh;
        //int offset;

        int cur_offset = dbFirstRecordOffset;
        // if no records exist, throw an exception
        if (cur_offset == 0) {
            throw new InvalidRecordIDException();
        }

        // look for the record in the cache
        rh = recHeadCache.get(recordId);
        if (rh != null) {
            return rh;
        }

        /*
         * requested record header is NOT in cache... search through the linked
         * list of records in the file.
         */
        rh = new RecordHeader();
        while (cur_offset != 0) {
            rh.load(cur_offset);
            if (rh.id == recordId) {
                break;
            } else {
                cur_offset = rh.nextOffset;
            }
        }

        if (cur_offset == 0) {
            // hit the end of the linked list w/o finding record.
            throw new InvalidRecordIDException();
        }
        if (addToCache) {
            recHeadCache.insert(rh);
        }
        return rh;
    }

    private int getAllocSize(int numBytes) {
        int rv;
        int pad;
        rv = DB_RECORD_HEADER_LENGTH + numBytes;
        pad = DB_BLOCK_SIZE - (rv % DB_BLOCK_SIZE);
        if (pad != DB_BLOCK_SIZE) {
            rv += pad;
        }
        return rv;
    }

    private RecordHeader allocateNewRecordStorage(int id, int dataSize)
            throws RecordStoreException, RecordStoreFullException {
        int allocSize = getAllocSize(dataSize);
        boolean foundBlock = false;

        /*
         * Traverse the free block linked list in the file, looking for the
         * first fit
         */
        RecordHeader block = new RecordHeader();
        try {
            int offset = dbFirstFreeBlockOffset;
            while (offset != 0) {
                block.load(offset);
                // If block is big enough, use it.
                if (block.blockSize >= allocSize) {
                    foundBlock = true;
                    break; // use this free block
                }
                offset = block.dataLenOrNextFree; // next free block
            }
        } catch (java.io.IOException ioe) {
            throw new RecordStoreException("error finding first fit block");
        }

        if (foundBlock == false) {

            /*
             * No free block was found that would hold this record, so find the
             * last (biggest offset) record in the file and append this record
             * after it.
             */

            // Is there room to grow the file?
            if (RecordStoreFile.spaceAvailable() < allocSize) {
                throw new RecordStoreFullException();
            }

            block = new RecordHeader(dbDataEnd, id, dbFirstRecordOffset,
                    allocSize, dataSize);
            try {
                block.store();
            } catch (java.io.IOException ioe) {
                throw new RecordStoreException("error writing "
                        + "new record data");
            }
            dbFirstRecordOffset = dbDataEnd;
            dbDataEnd += allocSize;
        } else {
            // block is where the new record should be stored
            if (block.id != -1) {
                throw new RecordStoreException("ALLOC ERR " + block.id
                        + " is not a free block!");
            }

            removeFreeBlock(block); // remove from free block list

            block.id = id;
            if (block.blockSize - allocSize >= DB_BLOCK_SIZE
                    + DB_RECORD_HEADER_LENGTH) {
                splitRecord(block, allocSize); // sets block.blockSize
            }
            block.dataLenOrNextFree = dataSize;
            try {
                block.store();
            } catch (java.io.IOException ioe) {
                throw new RecordStoreException("error writing free block "
                        + "after alloc");
            }
        }
        // add new record to cache
        recHeadCache.insert(block);
        return block;
    }

    private void splitRecord(RecordHeader recHead, int allocSize)
            throws RecordStoreException {
        RecordHeader newfb;
        int extraSpace = recHead.blockSize - allocSize;
        int oldBlockSize = recHead.blockSize;
        recHead.blockSize = allocSize;

        // only split records inside the linked list
        if (recHead.offset != dbFirstRecordOffset) {
            int fboffset = recHead.offset + allocSize;
            newfb = new RecordHeader(fboffset, -1, recHead.offset, extraSpace,
                    0);
            try {
                freeRecord(newfb); // write new free block to disk
                RecordHeader prh = new RecordHeader(recHead.offset
                        + oldBlockSize);
                prh.nextOffset = fboffset;
                prh.store();
                recHeadCache.invalidate(prh.id);
                storeDBState();
            } catch (java.io.IOException ioe) {
                throw new RecordStoreException("splitRecord error");
            }
        } else {
            // drop free space at the end of the file
            dbDataEnd = recHead.offset + recHead.blockSize;
        }
    }

    private void freeRecord(RecordHeader rh) throws RecordStoreException {
        if (rh.offset == dbFirstRecordOffset) {
            // don't put free blocks at the end of the record file
            dbFirstRecordOffset = rh.nextOffset;
            dbDataEnd = rh.offset;
        } else {
            rh.id = -1; // indicate this is a free block
            rh.dataLenOrNextFree = dbFirstFreeBlockOffset;
            // insert this new free block at front of free list
            dbFirstFreeBlockOffset = rh.offset;
            try {
                rh.store();
            } catch (java.io.IOException ioe) {
                throw new RecordStoreException("free record failed");
            }
        }
    }

    private void removeFreeBlock(RecordHeader blockToFree)
            throws RecordStoreException {
        RecordHeader block = new RecordHeader();
        RecordHeader prev = new RecordHeader();
        RecordHeader tmp = null;
        try {
            int offset = dbFirstFreeBlockOffset;
            while (offset != 0) {
                block.load(offset);
                if (block.offset == blockToFree.offset) {
                    if (block.id != -1) {
                        throw new RecordStoreException("removeFreeBlock id"
                                + " is not -1");
                    }
                    if (prev.offset == 0) {
                        // Set next free block as new freelist head
                        dbFirstFreeBlockOffset = block.dataLenOrNextFree;
                    } else {
                        /*
                         * Update previous block's pointer to the block this
                         * block was pointing to
                         */
                        prev.dataLenOrNextFree = block.dataLenOrNextFree;
                        prev.store();
                    }
                }
                offset = block.dataLenOrNextFree;
                // avoid creating lots of garbage!
                tmp = prev;
                prev = block;
                block = tmp;
            }
        } catch (java.io.IOException ioe) {
            throw new RecordStoreException("removeFreeBlock block not found");
        }
    }

    private void storeDBState() throws RecordStoreException {
        try {
            // set modification time
            dbLastModified = System.currentTimeMillis();
            // Capture the db state into the byte array
            RecordStore.putInt(dbNumLiveRecords, dbState, RS_NUM_LIVE);
            RecordStore.putInt(dbAuthMode, dbState, RS_AUTHMODE);
            RecordStore.putInt(dbVersion, dbState, RS_VERSION);
            RecordStore.putInt(dbNextRecordID, dbState, RS_NEXT_ID);
            RecordStore.putInt(dbFirstRecordOffset, dbState, RS_REC_START);
            RecordStore.putInt(dbFirstFreeBlockOffset, dbState, RS_FREE_START);
            RecordStore.putLong(dbLastModified, dbState, RS_LAST_MODIFIED);
            RecordStore.putInt(dbDataStart, dbState, RS_DATA_START);
            RecordStore.putInt(dbDataEnd, dbState, RS_DATA_END);
            // Write the state to the db file
            dbraf.seek(SIGNATURE_LENGTH); // skip RS header 8 bytes
            int numbytes = DB_INIT.length - SIGNATURE_LENGTH;
            dbraf.write(dbState, SIGNATURE_LENGTH, numbytes);
        } catch (java.io.IOException ioe) {
            throw new RecordStoreException("error writing record store "
                    + "attributes");
        }
    }

    /*
     * Package Private Methods
     */

    public boolean isOpen() {
        if (dbraf == null) {
            return false;
        }
        return true;
    }

    /*
     * Private Utility Methods
     */

    private void checkOpen() throws RecordStoreNotOpenException {
        if (dbraf == null) {
            throw new RecordStoreNotOpenException();
        }
    }

    private void notifyRecordChangedListeners(int recordId) {
        for (int i = 0; i < recordListener.size(); i++) {
            RecordListener rl = (RecordListener) recordListener.elementAt(i);
            rl.recordChanged(this, recordId);
        }
    }

    private void notifyRecordAddedListeners(int recordId) {
        for (int i = 0; i < recordListener.size(); i++) {
            RecordListener rl = (RecordListener) recordListener.elementAt(i);
            rl.recordAdded(this, recordId);
        }
    }

    private void notifyRecordDeletedListeners(int recordId) {
        for (int i = 0; i < recordListener.size(); i++) {
            RecordListener rl = (RecordListener) recordListener.elementAt(i);
            rl.recordDeleted(this, recordId);
        }
    }

    static int getInt(byte[] data, int offset) {
        int r = data[offset++];
        r = (r << 8) | ((int) (data[offset++]) & 0xff);
        r = (r << 8) | ((int) (data[offset++]) & 0xff);
        r = (r << 8) | ((int) (data[offset++]) & 0xff);
        return r;
    }

    static long getLong(byte[] data, int offset) {
        long r = data[offset++];
        r = (r << 8) | ((long) (data[offset++]) & 0xff);
        r = (r << 8) | ((long) (data[offset++]) & 0xff);
        r = (r << 8) | ((long) (data[offset++]) & 0xff);
        r = (r << 8) | ((long) (data[offset++]) & 0xff);
        r = (r << 8) | ((long) (data[offset++]) & 0xff);
        r = (r << 8) | ((long) (data[offset++]) & 0xff);
        r = (r << 8) | ((long) (data[offset++]) & 0xff);
        return r;
    }

    static int putInt(int i, byte[] data, int offset) {
        data[offset++] = (byte) ((i >> 24) & 0xff);
        data[offset++] = (byte) ((i >> 16) & 0xff);
        data[offset++] = (byte) ((i >> 8) & 0xff);
        data[offset] = (byte) (i & 0xff);
        return 4;
    }

    static int putLong(long l, byte[] data, int offset) {
        data[offset++] = (byte) ((l >> 56) & 0xff);
        data[offset++] = (byte) ((l >> 48) & 0xff);
        data[offset++] = (byte) ((l >> 40) & 0xff);
        data[offset++] = (byte) ((l >> 32) & 0xff);
        data[offset++] = (byte) ((l >> 24) & 0xff);
        data[offset++] = (byte) ((l >> 16) & 0xff);
        data[offset++] = (byte) ((l >> 8) & 0xff);
        data[offset] = (byte) (l & 0xff);
        return 8;
    }

⌨️ 快捷键说明

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