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

📄 recordstore.java

📁 用于移动设备上的java虚拟机源代码
💻 JAVA
📖 第 1 页 / 共 5 页
字号:
	    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;    }        /**     * Return the block allocation size for a record with <code>numBytes     * </code> data bytes.  This includes space for the record header     * and is a multiple of <code>DB_BLOCK_SIZE</code>.     *     * @param numBytes number of data bytes that will be stored in record     *     * @return the amount of space to allocate for this record.     */    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;    }    /**     * Returns a new record header for record <code>id</code> large     * enough to hold <code>dataSize</code> bytes of record data.     *     * Picks a free block using a first fit strategy that is      * large enough for a record header and the associated     * record data.  The block will be a multiple of DB_BLOCK_SIZE.     *     * @param id the record id to assign to the returned record header.     * @param dataSize length of record data that will be      *        stored with this record.     *     * @return a new record header      *         the record store's backing file.     */    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;    }    /**     * Splits a free block off the tail end of a large     * record block which contains extra free space.     * After calling this method, the caller must call      * <code>storeDBState</code>.     *     * On return, <code>recHead.blockSize</code> will contain     * allocSize.     *     * @param recHead the current record header     * @param allocSize the size that <code>recHEad</code>     *        will have as its <code>blockSize</code> variable     *        when the call returns.     *     * @exception RecordStoreException if there is an error     *            splitting the record     */    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;	}    }	          /**     * Free a record into the Free list.       * Turns the RecordHeader block <code>rh</code> into a free      * block, then adds it to the free block linked list.       *     * After calling this method the caller must call      * <code>storeDBState</code>.     *     * @param rh RecordHeader of record to make into a free block     *     * @exception RecordStoreException if there is an IO error updating the      *            free list     */    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");	    }	}    }    /**     * Remove a free block from the free block linked list     *     * @param blockToFree record header for the free block to remove     *      * @exception recordStoreException if error occurs during the     *            update.     */    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");	}	    }    /**     * Helper method that stores the internal state variables     * into the record store file.     *     * checkopen should have been called.  will not work     * if dbraf is not open     *     * Updates dbLastModified time to current system time     */    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     */    /**     * Get the open status of this record store.  (Package accessable     * for use by record enumeration objects.)     *     * @return true if record store is open, false otherwise.      */    boolean isOpen() {	if (dbraf == null) {	    return false;	}	return true;    }    /*     * Private Utility Methods     */    /**     * Throws a RecordStoreNotOpenException if the RecordStore     * is closed.  (A RecordStore is closed if the RecordStoreFile     * instance variable <code>dbraf</code> is null.      *     * @exception RecordStoreNotOpenException if RecordStore is closed     */    private void checkOpen() throws RecordStoreNotOpenException    {	if (dbraf == null) {	    throw new RecordStoreNotOpenException();	}    }    /**     * Notifies all registered listeners that a record changed.     *     * @param recordId the record id of the changed record.     */    private void notifyRecordChangedListeners(int recordId)    {	for (int i = 0; i < recordListener.size(); i++) {	    RecordListener rl = (RecordListener)recordListener.elementAt(i);	    rl.recordChanged(this, recordId);	}    }    /**     * Notifies all registered listeners that a record was added.     *     * @param recordId the record id of the added record.     */    private void notifyRecordAddedListeners(int recordId)    {	for (int i = 0; i < recordListener.size(); i++) {	    RecordListener rl = (RecordListener)recordListener.elementAt(i);	    rl.recordAdded(this, recordId);	}    }        /**     * Notifies all registered listeners that a record was deleted.     *     * @param recordId the record id of the changed record.     */    private void notifyRecordDeletedListeners(int recordId)    {	for (int i = 0; i < recordListener.size(); i++) {	    RecordListener rl = (RecordListener)recordListener.elementAt(i);	    rl.recordDeleted(this, recordId);	}    }    /**     * A convenience method for converting a byte array into     * an int (assumes big-endian byte ordering).     *     * @param data the byte array returned from the database.     * @param offset the offset into the array of the first byte to start from.     *     * @return an int corresponding to the first four bytes      *         of the array passed in.     */    static int getInt(byte[] data, int offset)    {	int r = data[offset++];	r = (r << 8) | ((int)(data[offset++]) & 0xff);

⌨️ 快捷键说明

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