📄 recordstore.java
字号:
*/ RecordHeader rh = allocateNewRecordStorage(id, numBytes); try { if (data != null) { rh.write(data, offset); } } catch (java.io.IOException ioe) { throw new RecordStoreException("error writing new record " + "data"); } // Update the state changes to the db file. dbNumLiveRecords++; dbVersion++; storeDBState(); // tell listeners a record has been added notifyRecordAddedListeners(id); // Return the new record id return id; } } /** * The record is deleted from the record store. The recordId for * this record is NOT reused. * * @param recordId the ID of the record to delete * * @exception RecordStoreNotOpenException if the record store is * not open * @exception InvalidRecordIDException if the recordId is invalid * @exception RecordStoreException if a general record store * exception occurs * @exception SecurityException if the MIDlet has read-only access * to the RecordStore */ public void deleteRecord(int recordId) throws RecordStoreNotOpenException, InvalidRecordIDException, RecordStoreException { synchronized (rsLock) { checkOpen(); if (!checkWritable()) { throw new SecurityException(); } RecordHeader rh = null; // record header try { rh = findRecord(recordId, false); freeRecord(rh); // calls rh.store recHeadCache.invalidate(rh.id); } catch (java.io.IOException ioe) { throw new RecordStoreException("error updating file after" + " record deletion"); } // update database header info and sync to file dbNumLiveRecords--; dbVersion++; storeDBState(); // tell listeners a record has been deleted notifyRecordDeletedListeners(recordId); } } /** * Returns the size (in bytes) of the MIDlet data available * in the given record. * * @param recordId the ID of the record to use in this operation * * @return the size (in bytes) of the MIDlet data available * in the given record * * @exception RecordStoreNotOpenException if the record store is * not open * @exception InvalidRecordIDException if the recordId is invalid * @exception RecordStoreException if a general record store * exception occurs */ public int getRecordSize(int recordId) throws RecordStoreNotOpenException, InvalidRecordIDException, RecordStoreException { synchronized (rsLock) { checkOpen(); try { // throws InvalidRecordIDException RecordHeader rh = findRecord(recordId, true); return (rh.dataLenOrNextFree); } catch (java.io.IOException ioe) { throw new RecordStoreException("error reading record data"); } } } /** * Returns the data stored in the given record. * * @param recordId the ID of the record to use in this operation * @param buffer the byte array in which to copy the data * @param offset the index into the buffer in which to start copying * * @exception RecordStoreNotOpenException if the record store is * not open * @exception InvalidRecordIDException if the recordId is invalid * @exception RecordStoreException if a general record store * exception occurs * @exception ArrayIndexOutOfBoundsException if the record is * larger than the buffer supplied * * @return the number of bytes copied into the buffer, starting at * index <code>offset</code> * @see #setRecord */ public int getRecord(int recordId, byte[] buffer, int offset) throws RecordStoreNotOpenException, InvalidRecordIDException, RecordStoreException { synchronized (rsLock) { checkOpen(); RecordHeader rh; try { // throws InvalidRecordIDException rh = findRecord(recordId, true); rh.read(buffer, offset); } catch (java.io.IOException ioe) { throw new RecordStoreException("error reading record data"); } return rh.dataLenOrNextFree; } } /** * Returns a copy of the data stored in the given record. * * @param recordId the ID of the record to use in this operation * * @exception RecordStoreNotOpenException if the record store is * not open * @exception InvalidRecordIDException if the recordId is invalid * @exception RecordStoreException if a general record store * exception occurs * * @return the data stored in the given record. Note that if the * record has no data, this method will return null. * @see #setRecord */ public byte[] getRecord(int recordId) throws RecordStoreNotOpenException, InvalidRecordIDException, RecordStoreException { synchronized (rsLock) { checkOpen(); int size = 0; byte[] data = null; try { // throws InvalidRecordIDException RecordHeader rh = findRecord(recordId, true); if (rh.dataLenOrNextFree == 0) { return null; } data = new byte[rh.dataLenOrNextFree]; rh.read(data, 0); } catch (java.io.IOException ioe) { throw new RecordStoreException("error reading record data"); } return data; } } /** * Sets the data in the given record to that passed in. After * this method returns, a call to <code>getRecord(int recordId)</code> * will return an array of numBytes size containing the data * supplied here. * * @param recordId the ID of the record to use in this operation * @param newData the new data to store in the record * @param offset the index into the data buffer of the first * relevant byte for this record * @param numBytes the number of bytes of the data buffer to use * for this record * * @exception RecordStoreNotOpenException if the record store is * not open * @exception InvalidRecordIDException if the recordId is invalid * @exception RecordStoreException if a general record store * exception occurs * @exception RecordStoreFullException if the operation cannot be * completed because the record store has no more room * @exception SecurityException if the MIDlet has read-only access * to the RecordStore * @see #getRecord */ public void setRecord(int recordId, byte[] newData, int offset, int numBytes) throws RecordStoreNotOpenException, InvalidRecordIDException, RecordStoreException, RecordStoreFullException { synchronized (rsLock) { checkOpen(); if (!checkWritable()) { throw new SecurityException(); } if ((newData == null) && (numBytes > 0)) { throw new NullPointerException(); } RecordHeader rh = null; RecordHeader newrh = null; try { rh = findRecord(recordId, false); // throws InvalidRIDException } catch (java.io.IOException ioe) { throw new RecordStoreException("error finding record data"); } /* * The size of the data and space allocated to the * current record is known here, as is the new size. * Determine if the new data will fit, or if this * record will have to be stored elsewhere. */ if (numBytes <= rh.blockSize - DB_RECORD_HEADER_LENGTH) { /* * The new data should fit within the existing record * location in the file. Store the new data and * patch up the record's header fields. */ int allocSize = getAllocSize(numBytes); if (rh.blockSize - allocSize >= DB_BLOCK_SIZE + DB_RECORD_HEADER_LENGTH) { splitRecord(rh, allocSize); // sets rh.blockSize } rh.dataLenOrNextFree = numBytes; try { rh.store(); // write the new record header recHeadCache.insert(rh); // add to cache if (newData != null) { rh.write(newData, offset); } } catch (java.io.IOException ioe) { throw new RecordStoreException("error writing record" + " data"); } } else { /* * The new data is longer than the old data. It needs to * be relocated to elsewhere within <code>dbfile</code>. * Search the free list to see if there's a space where to * store it. Otherwise append it to the end of the file. */ freeRecord(rh); // calls rh.store() newrh = allocateNewRecordStorage(recordId, numBytes); 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); } } /** * Returns an enumeration for traversing a set of records in the * record store in an optionally specified order.<p> * * The filter, if non-null, will be used to determine what * subset of the record store records will be used.<p> * * The comparator, if non-null, will be used to determine the * order in which the records are returned.<p> * * If both the filter and comparator is null, the enumeration * will traverse all records in the record store in an undefined * order. This is the most efficient way to traverse all of the * records in a record store. If a filter is used with a null * comparator, the enumeration will traverse the filtered records * in an undefined order. * * The first call to <code>RecordEnumeration.nextRecord()</code> * returns the record data from the first record in the sequence. * Subsequent calls to <code>RecordEnumeration.nextRecord()</code> * return the next consecutive record's data. To return the record * data from the previous consecutive from any * given point in the enumeration, call <code>previousRecord()</code>. * On the other hand, if after creation the first call is to * <code>previousRecord()</code>, the record data of the last element * of the enumeration will be returned. Each subsequent call to * <code>previousRecord()</code> will step backwards through the * sequence. * * @param filter if non-null, will be used to determine what * subset of the record store records will be used * @param comparator if non-null, will be used to determine the * order in which the records are returned * @param keepUpdated if true, the enumerator will keep its enumeration * current with any changes in the records of the record * store. Use with caution as there are possible * performance consequences. If false the enumeration * will not be kept current and may return recordIds for * records that have been deleted or miss records that * are added later. It may also return records out of * order that have been modified after the enumeration * was built. Note that any changes to records in the * record store are accurately reflected when the record * is later retrieved, either directly or through the * enumeration. The thing that is risked by setting this * parameter false is the filtering and sorting order of * the enumeration when records are modified, added, or * deleted. * * @exception RecordStoreNotOpenException if the record store is * not open * * @see RecordEnumeration#rebuild * * @return an enumeration for traversing a set of records in the * record store in an optionally specified order */ public RecordEnumeration enumerateRecords(RecordFilter filter, RecordComparator comparator, boolean keepUpdated) throws RecordStoreNotOpenException { checkOpen(); return new RecordEnumerationImpl(this, filter, comparator, keepUpdated); } /* * Private Memory Management Methods */ /** * Find the record header for a record <code>recordId</code>. * * @param recordId the id of the desired record header. * @param addToCache true if this record should be added to cache * if found. * * @return the record header for the given record, or null if * the record cannot be found. */ 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) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -