📄 recordstore.java
字号:
/*
* Created on 2004-12-24 by Tianlei
* version 1.0.0.3
* since MIDP1.0
* ��ȫ����2.0�����Դ��,����ע�Ͳμ�Դ��
*/
package javax.microedition.rms;
import a.a.a.midp.rms.*;
/**
* @author Tianlei
* @version 1.0.0.3
* @since MIDP1.0
*
* ��ȫ����2.0�����Դ��,����ע�Ͳμ�Դ��
*/
public class RecordStore {
/** pre initialized RecordStore header structure */
private static final byte[] DB_INIT = { (byte) 'm', (byte) 'i', (byte) 'd',
(byte) 'p', (byte) '-', (byte) 'r', (byte) 'm', (byte) 's', 0, 0,
0, 0, // num live records
0, 0, 0, 0, // AUTHMODE_PRIVATE by default
0, 0, 0, 0, // version
0, 0, 0, 1, // next record id
0, 0, 0, 0, // first record offset
0, 0, 0, 0, // first free-space offset
0, 0, 0, 0, // last modified (1st half)
0, 0, 0, 0, // last modified (2nd half)
0, 0, 0, 0, // start of data offset
0, 0, 0, 0 // end of data offset
};
/** length of the signature string in bytes */
private static final int SIGNATURE_LENGTH = 8;
/** size of a per record meta-data object */
private static final int DB_RECORD_HEADER_LENGTH = 16;
private static final int DB_BLOCK_SIZE = 16;
/** size of the buffer for compacting record store */
private static final int DB_COMPACTBUFFER_SIZE = 64;
/** cache of open RecordStore instances */
private static java.util.Vector dbCache = new java.util.Vector(3);
/** lock to protect static dbcache state */
private static final Object dbCacheLock = new Object();
/** name of this record store */
private String recordStoreName;
/** unique storage id for this record store */
private String uniqueIdPath;
/** number of open instances of this record store */
private int opencount;
/** RecordStoreFile where this record store is stored */
private RecordStoreFile dbraf;
/** lock used to synchronize this record store */
public Object rsLock;
/** recordListeners of this record store */
private java.util.Vector recordListener;
/** cache of record headers */
private RecordHeaderCache recHeadCache;
/** number of direct mapped cache entries */
private static int CACHE_SIZE = 8;
/** static buffer used in loading/storing RecordHeader data */
private static byte[] recHeadBuf = new byte[DB_RECORD_HEADER_LENGTH];
/** next record's id */
private int dbNextRecordID = 1;
/** record store version */
private int dbVersion;
private int dbAuthMode;
/** count of live records */
private int dbNumLiveRecords;
/** time record store was last modified (in milliseconds */
private long dbLastModified;
/** offset of first record */
private int dbFirstRecordOffset;
/** offset of first free block */
private int dbFirstFreeBlockOffset;
/** offset of the first data block */
private int dbDataStart = 48;
/** offset of the last data block */
private int dbDataEnd = 48;
/** static buffer used in loading/storing dbState */
private static byte[] dbState = new byte[DB_INIT.length];
/** RS_SIGNATURE offset */
private static final int RS_SIGNATURE = 0;
/** RS_NUM_LIVE offset */
private static final int RS_NUM_LIVE = 8;
/** RS_AUTHMODE offset */
private static final int RS_AUTHMODE = 12;
/** RS_VERSION offset */
private static final int RS_VERSION = 16;
/** RS_NEXT_ID offset */
private static final int RS_NEXT_ID = 20;
/** RS_REC_START offset */
private static final int RS_REC_START = 24;
/** RS_FREE_START offset */
private static final int RS_FREE_START = 28;
/** RS_LAST_MODIFIED offset */
private static final int RS_LAST_MODIFIED = 32;
/** RS_START_OF_DATA offset */
private static final int RS_DATA_START = 40;
/** RS_END_OF_DATA offset */
private static final int RS_DATA_END = 44;
/**
* Authorization to allow access only to the current MIDlet suite.
* AUTHMODE_PRIVATE has a value of 0.
*/
public final static int AUTHMODE_PRIVATE = 0;
/**
* Authorization to allow access to any MIDlet suites. AUTHMODE_ANY has a
* value of 1.
*/
public final static int AUTHMODE_ANY = 1;
/**
* Internal indicator for AUTHMODE_ANY with read only access AUTHMODE_ANY_RO
* has a value of 2.
*/
private final static int AUTHMODE_ANY_RO = 2;
/*
* RecordStore Constructors
*/
private RecordStore() {
}
private RecordStore(String uidPath, String recordStoreName, boolean create)
throws RecordStoreException, RecordStoreNotFoundException {
this.recordStoreName = recordStoreName;
this.uniqueIdPath = uidPath;
recHeadCache = new RecordHeaderCache(CACHE_SIZE);
rsLock = new Object();
recordListener = new java.util.Vector(3);
boolean exists = RecordStoreFile.exists(uidPath);
// Check for errors between app and record store existance.
if (!create && !exists) {
throw new RecordStoreNotFoundException("cannot find record "
+ "store file");
}
/*
* If a new RecordStore will be created in storage, check to see if the
* space required is available.
*/
if (create && !exists) {
int space = RecordStoreFile.spaceAvailable();
if (space - DB_INIT.length < 0) {
throw new RecordStoreFullException();
}
}
// Create a RecordStoreFile for storing the record store.
try {
dbraf = new RecordStoreFile(uidPath);
/*
* At this point we've opened the RecordStoreFile. If we created a
* new record store, initialize the db attributes.
*/
if (create && !exists) {
// Initialize record store attributes
dbraf.seek(RS_SIGNATURE);
// Update the timestamp
RecordStore.putLong(System.currentTimeMillis(), DB_INIT,
RS_LAST_MODIFIED);
RecordStore.putInt(48, DB_INIT, RS_DATA_START);
RecordStore.putInt(48, DB_INIT, RS_DATA_END);
dbraf.write(DB_INIT);
} else {
/*
* Create a buffer and read the database attributes Read the
* record store attributes. Set up internal state.
*/
byte[] buf = new byte[DB_INIT.length];
dbraf.seek(RS_SIGNATURE);
dbraf.read(buf);
/*
* Verify that the file is actually a record store by verifying
* the record store "signature."
*/
for (int i = 0; i < SIGNATURE_LENGTH; i++) {
if (buf[i] != DB_INIT[i]) {
throw new RecordStoreException("invalid record "
+ "store contents");
}
}
// Convert byte array to internal state variables.
dbNumLiveRecords = RecordStore.getInt(buf, RS_NUM_LIVE);
dbVersion = RecordStore.getInt(buf, RS_VERSION);
dbAuthMode = RecordStore.getInt(buf, RS_AUTHMODE);
dbNextRecordID = RecordStore.getInt(buf, RS_NEXT_ID);
dbFirstRecordOffset = RecordStore.getInt(buf, RS_REC_START);
dbFirstFreeBlockOffset = RecordStore.getInt(buf, RS_FREE_START);
dbLastModified = RecordStore.getLong(buf, RS_LAST_MODIFIED);
dbDataStart = RecordStore.getInt(buf, RS_DATA_START);
dbDataEnd = RecordStore.getInt(buf, RS_DATA_END);
}
} catch (java.io.IOException ioe) {
try {
if (dbraf != null) {
dbraf.close();
}
} catch (java.io.IOException ioe2) {
// ignore exception within exception block
} finally {
dbraf = null;
}
throw new RecordStoreException("error opening record store "
+ "file");
}
}
public static void deleteRecordStore(String recordStoreName)
throws RecordStoreException, RecordStoreNotFoundException {
String uidPath = RecordStoreFile.getUniqueIdPath(recordStoreName);
// Check the record store cache for a db with the same name
synchronized (dbCacheLock) {
RecordStore db;
for (int n = 0; n < dbCache.size(); n++) {
db = (RecordStore) dbCache.elementAt(n);
if (db.uniqueIdPath.equals(uidPath)) {
// cannot delete an open record store
throw new RecordStoreException("deleteRecordStore error:"
+ " record store is" + " still open");
}
}
// this record store is not currently open
if (RecordStoreFile.exists(uidPath)) {
boolean success = RecordStoreFile.deleteFile(uidPath);
if (!success) {
throw new RecordStoreException("deleteRecordStore "
+ "failed");
}
} else {
throw new RecordStoreNotFoundException("deleteRecordStore "
+ "error: file " + "not found");
}
}
}
public static RecordStore openRecordStore(String recordStoreName,
boolean createIfNecessary) throws RecordStoreException,
RecordStoreFullException, RecordStoreNotFoundException {
String uidPath = RecordStoreFile.getUniqueIdPath(recordStoreName);
synchronized (dbCacheLock) {
if (recordStoreName.length() > 32 || recordStoreName.length() == 0) {
throw new IllegalArgumentException();
}
// Cache record store objects and ensure that there is only
// one record store object in memory for any given record
// store file. This is good for memory use. This is NOT safe
// in the situation where multiple VM's may be executing code
// concurrently. In that case, you have to sync things through
// file locking or something similar.
// Check the record store cache for a db with the same name
RecordStore db;
for (int n = 0; n < dbCache.size(); n++) {
db = (RecordStore) dbCache.elementAt(n);
if (db.uniqueIdPath.equals(uidPath)) {
db.opencount++; // times rs has been opened
return db; // return ref to cached record store
}
}
/*
* Record store not found in cache, so create it.
*/
db = new RecordStore(uidPath, recordStoreName, createIfNecessary);
/*
* Now add the new record store to the cache
*/
db.opencount = 1;
dbCache.addElement(db);
return db;
}
}
public static RecordStore openRecordStore(String recordStoreName,
boolean createIfNecessary, int authmode, boolean writable)
throws RecordStoreException, RecordStoreFullException,
RecordStoreNotFoundException {
RecordStore rs = RecordStore.openRecordStore(recordStoreName,
createIfNecessary);
rs.setMode(authmode, writable);
return rs;
}
public static RecordStore openRecordStore(String recordStoreName,
String vendorName, String suiteName) throws RecordStoreException,
RecordStoreNotFoundException {
if (vendorName == null || suiteName == null) {
throw new IllegalArgumentException("vendorName and "
+ "suiteName must be " + "non null");
}
synchronized (dbCacheLock) {
if (recordStoreName.length() > 32 || recordStoreName.length() == 0) {
throw new IllegalArgumentException();
}
// Cache record store objects and ensure that there is only
// one record store object in memory for any given record
// store file. This is good for memory use. This is NOT safe
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -