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

📄 recordstore.java

📁 用于移动设备上的java虚拟机源代码
💻 JAVA
📖 第 1 页 / 共 5 页
字号:
	r = (r << 8) | ((int)(data[offset++]) & 0xff);	r = (r << 8) | ((int)(data[offset++]) & 0xff);	return r;    }    /**     * A convenience method for converting a byte array into     * a long (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 a long corresponding to the first eight bytes      *         of the array passed in.     */    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;    }    /**     * A convenience method for converting an integer into     * a byte array.     *     * @param i the integer to turn into a byte array.     * @param data a place to store the bytes of <code>i</code>.     * @param offset starting point within <code>data<code> to      *        store <code>i</code>.     *     * @return the number of bytes written to the array.     */    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;    }    /**     * A convenience method for converting a long into     * a byte array.     *     * @param l the <code>long<code> to turn into a byte array.     * @param data a place to store the bytes of <code>l</code>.     * @param offset Starting point within <code>data</code> to      *        store <code>l</code>.     *     * @return the number of bytes written to the array.     */    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;    }    /**     * Returns all of the recordId's currently in the record store.     *     * MUST be called after obtaining rsLock, e.g in a      * <code>synchronized (rsLock) {</code> block.     *     * @return an array of the recordId's currently in the record store     *         or null if the record store is closed.     */    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;    }    /**     * Remove free blocks from the record store and compact records     * with data into as small a space in <code>rsFile</code> as     * possible.  Operates from smallest to greatest offset in      * <code>rsFile</code>, copying data in chunks towards the      * beginning of the file, and updating record store meta-data     * as it progresses.     *     * Warning: This is a slow operation that scales linearly     * with rsFile size.       *     * @exception RecordStoreNotOpenException if this record store      *            is closed     * @exception RecordStoreException if an error occurs during record      *            store compaction     */    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();    }    /*     * Internal Classes       */    /**     * A class representing a RecordHeader, which may be the start of a      * record block or a free block.  (In a free block, only the      * <code> NextOffset </code> and <code> BlockSize </code> fields     * are valid.)  Currently it is a conveinience structure, with     * fields visible and directly modifyable by the enclosing     * RecordStore class.     */    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);	}    }    /**     * RecordHeaderCache providing a per RecordStore, in memory cac

⌨️ 快捷键说明

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