📄 recordstore.java
字号:
// 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;
String uidPath = RecordStoreFile.getUniqueIdPath(vendorName,
suiteName, recordStoreName);
for (int n = 0; n < dbCache.size(); n++) {
db = (RecordStore) dbCache.elementAt(n);
if (db.uniqueIdPath.equals(uidPath)) {
if (db.checkOwner() == false
&& db.dbAuthMode == AUTHMODE_PRIVATE) {
throw new SecurityException();
} else {
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, false);
/*
* Now add the new record store to the cache
*/
db.opencount = 1;
dbCache.addElement(db);
if (db.checkOwner() == false && db.dbAuthMode == AUTHMODE_PRIVATE) {
db.closeRecordStore();
throw new SecurityException();
} else {
return db;
}
}
}
public void setMode(int authmode, boolean writable)
throws RecordStoreException {
synchronized (rsLock) {
if (checkOwner() == false) {
throw new SecurityException();
} else if (authmode != AUTHMODE_PRIVATE && authmode != AUTHMODE_ANY) {
throw new IllegalArgumentException();
} else {
dbAuthMode = authmode;
if ((authmode == AUTHMODE_ANY) && (writable == false)) {
dbAuthMode = AUTHMODE_ANY_RO;
}
}
// flush record store header here
storeDBState();
}
}
public void closeRecordStore() throws RecordStoreNotOpenException,
RecordStoreException {
synchronized (rsLock) {
synchronized (dbCacheLock) {
checkOpen();
/*
* Find the record store within the record store cache. A linear
* seagrch is OK assuming there won't be many concurrently open
* record stores.
*/
RecordStore db = null;
for (int n = 0; n < dbCache.size(); n++) {
db = (RecordStore) dbCache.elementAt(n);
if (db == this) {
db.opencount--;
break;
}
}
if (db.opencount <= 0) { // free stuff - final close
dbCache.removeElement(db);
try {
// closing now...no need to listen
if (!recordListener.isEmpty()) {
recordListener.removeAllElements();
}
// close native fd
if (dbFirstFreeBlockOffset != 0) {
compactRecords(); // compact before close
// truncate file to compacted size
dbraf.truncate(dbDataEnd);
}
dbraf.close();
} catch (java.io.IOException ioe) {
throw new RecordStoreException("error closing .db "
+ "file");
} finally {
dbraf = null;
recHeadCache = null;
}
}
}
}
}
public static String[] listRecordStores() {
// static calls synchronize on dbCacheLock
synchronized (dbCacheLock) {
String[] returnstrings = RecordStoreFile.listRecordStores();
return returnstrings;
}
}
public String getName() throws RecordStoreNotOpenException {
checkOpen();
return recordStoreName;
}
public int getVersion() throws RecordStoreNotOpenException {
checkOpen();
return dbVersion;
}
public int getNumRecords() throws RecordStoreNotOpenException {
checkOpen();
return dbNumLiveRecords;
}
public int getSize() throws RecordStoreNotOpenException {
checkOpen();
// return the file size of the record store file
return dbDataEnd;
}
public int getSizeAvailable() throws RecordStoreNotOpenException {
checkOpen();
int rv = RecordStoreFile.spaceAvailable() - DB_BLOCK_SIZE
- DB_RECORD_HEADER_LENGTH;
return (rv < 0) ? 0 : rv;
}
public long getLastModified() throws RecordStoreNotOpenException {
checkOpen();
return dbLastModified;
}
public void addRecordListener(RecordListener listener) {
synchronized (rsLock) {
if (!recordListener.contains(listener)) {
recordListener.addElement(listener);
}
}
}
public void removeRecordListener(RecordListener listener) {
synchronized (rsLock) {
recordListener.removeElement(listener);
}
}
public int getNextRecordID() throws RecordStoreNotOpenException,
RecordStoreException {
checkOpen();
return dbNextRecordID;
}
public int addRecord(byte[] data, int offset, int numBytes)
throws RecordStoreNotOpenException, RecordStoreException,
RecordStoreFullException {
synchronized (rsLock) {
checkOpen();
if (!checkWritable()) {
throw new SecurityException();
}
if ((data == null) && (numBytes > 0)) {
throw new NullPointerException("illegal arguments: null "
+ "data, numBytes > 0");
}
// get recordId for new record, update db's dbNextRecordID
int id = dbNextRecordID++;
/*
* Find the offset where this record should be stored and seek to
* that location in the file. allocateNewRecordStorage() allocates
* the space for this record.
*/
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;
}
}
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);
}
}
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");
}
}
}
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;
}
}
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;
}
}
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);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -