📄 storageimpl.java
字号:
header.root[0].shadowIndex = header.root[1].index;
header.root[1].shadowIndex = header.root[0].index;
header.root[0].shadowIndexSize = indexSize;
header.root[1].shadowIndexSize = indexSize;
int bitmapPages =
(int)((used + Page.pageSize*(dbAllocationQuantum*8-1) - 1)
/ (Page.pageSize*(dbAllocationQuantum*8-1)));
long bitmapSize = (long)bitmapPages*Page.pageSize;
int usedBitmapSize = (int)((used + bitmapSize) >>> (dbAllocationQuantumBits + 3));
for (i = 0; i < bitmapPages; i++) {
pg = pool.putPage(used + (long)i*Page.pageSize);
byte[] bitmap = pg.data;
int n = usedBitmapSize > Page.pageSize ? Page.pageSize : usedBitmapSize;
for (int j = 0; j < n; j++) {
bitmap[j] = (byte)0xFF;
}
usedBitmapSize -= Page.pageSize;
pool.unfix(pg);
}
int bitmapIndexSize =
((dbBitmapId + dbBitmapPages)*8 + Page.pageSize - 1)
& ~(Page.pageSize - 1);
byte[] index = new byte[bitmapIndexSize];
Bytes.pack8(index, dbInvalidId*8, dbFreeHandleFlag);
for (i = 0; i < bitmapPages; i++) {
Bytes.pack8(index, (dbBitmapId+i)*8, used | dbPageObjectFlag);
used += Page.pageSize;
}
header.root[0].bitmapEnd = dbBitmapId + i;
header.root[1].bitmapEnd = dbBitmapId + i;
while (i < dbBitmapPages) {
Bytes.pack8(index, (dbBitmapId+i)*8, dbFreeHandleFlag);
i += 1;
}
header.root[0].size = used;
header.root[1].size = used;
usedSize = used;
committedIndexSize = currIndexSize = dbFirstUserId;
pool.write(header.root[1].index, index);
pool.write(header.root[0].index, index);
header.dirty = true;
header.root[0].size = header.root[1].size;
pg = pool.putPage(0);
header.pack(pg.data);
pool.flush();
pool.modify(pg);
header.initialized = true;
header.pack(pg.data);
pool.unfix(pg);
pool.flush();
} else {
int curr = header.curr;
currIndex = curr;
if (header.root[curr].indexSize != header.root[curr].shadowIndexSize) {
throw new StorageError(StorageError.DATABASE_CORRUPTED);
}
if (isDirty()) {
if (listener != null) {
listener.databaseCorrupted();
}
System.err.println("Database was not normally closed: start recovery");
header.root[1-curr].size = header.root[curr].size;
header.root[1-curr].indexUsed = header.root[curr].indexUsed;
header.root[1-curr].freeList = header.root[curr].freeList;
header.root[1-curr].index = header.root[curr].shadowIndex;
header.root[1-curr].indexSize = header.root[curr].shadowIndexSize;
header.root[1-curr].shadowIndex = header.root[curr].index;
header.root[1-curr].shadowIndexSize = header.root[curr].indexSize;
header.root[1-curr].bitmapEnd = header.root[curr].bitmapEnd;
header.root[1-curr].rootObject = header.root[curr].rootObject;
header.root[1-curr].classDescList = header.root[curr].classDescList;
header.root[1-curr].bitmapExtent = header.root[curr].bitmapExtent;
pg = pool.putPage(0);
header.pack(pg.data);
pool.unfix(pg);
pool.copy(header.root[1-curr].index, header.root[curr].index,
(header.root[curr].indexUsed*8L + Page.pageSize - 1) & ~(Page.pageSize-1));
if (listener != null) {
listener.recoveryCompleted();
}
System.err.println("Recovery completed");
}
currIndexSize = header.root[1-curr].indexUsed;
committedIndexSize = currIndexSize;
usedSize = header.root[curr].size;
}
int bitmapSize = header.root[1-currIndex].bitmapExtent == 0 ? dbBitmapPages : dbLargeBitmapPages;
bitmapPageAvailableSpace = new int[bitmapSize];
for (i = 0; i < bitmapPageAvailableSpace.length; i++) {
bitmapPageAvailableSpace[i] = Integer.MAX_VALUE;
}
currRBitmapPage = currPBitmapPage = 0;
currRBitmapOffs = currPBitmapOffs = 0;
opened = true;
reloadScheme();
}
public boolean isOpened() {
return opened;
}
void reloadScheme() {
classDescMap.clear();
int descListOid = header.root[1-currIndex].classDescList;
classDescMap.put(classDescriptorClass,
new ClassDescriptor(this, classDescriptorClass));
if (descListOid != 0) {
ClassDescriptor desc;
descList = findClassDescriptor(descListOid);
for (desc = descList; desc != null; desc = desc.next) {
desc.load();
}
for (desc = descList; desc != null; desc = desc.next) {
if (classDescMap.get(desc.cls) == desc) {
desc.resolve();
}
}
} else {
descList = null;
}
}
final void assignOid(IPersistent obj, int oid) {
obj.assignOid(this, oid, false);
}
final void registerClassDescriptor(ClassDescriptor desc) {
classDescMap.put(desc.cls, desc);
desc.next = descList;
descList = desc;
storeObject0(desc);
header.root[1-currIndex].classDescList = desc.getOid();
modified = true;
}
final ClassDescriptor getClassDescriptor(Class cls) {
ClassDescriptor desc = (ClassDescriptor)classDescMap.get(cls);
if (desc == null) {
desc = new ClassDescriptor(this, cls);
registerClassDescriptor(desc);
}
return desc;
}
public synchronized IPersistent getRoot() {
if (!opened) {
throw new StorageError(StorageError.STORAGE_NOT_OPENED);
}
int rootOid = header.root[1-currIndex].rootObject;
return (rootOid == 0) ? null : lookupObject(rootOid);
}
public synchronized void setRoot(IPersistent root) {
if (!opened) {
throw new StorageError(StorageError.STORAGE_NOT_OPENED);
}
if (root == null) {
header.root[1-currIndex].rootObject = 0;
} else {
if (!root.isPersistent()) {
storeObject0(root);
}
header.root[1-currIndex].rootObject = root.getOid();
}
modified = true;
}
public void commit() {
synchronized (this) {
if (!opened) {
throw new StorageError(StorageError.STORAGE_NOT_OPENED);
}
objectCache.flush();
if (modified) {
commit0();
modified = false;
}
objectCache.clear();
}
}
private final void commit0()
{
int i, j, n;
int curr = currIndex;
int[] map = dirtyPagesMap;
int oldIndexSize = header.root[curr].indexSize;
int newIndexSize = header.root[1-curr].indexSize;
int nPages = committedIndexSize >>> dbHandlesPerPageBits;
Page pg;
if (newIndexSize > oldIndexSize) {
cloneBitmap(header.root[curr].index, oldIndexSize*8L);
long newIndex;
while (true) {
newIndex = allocate(newIndexSize*8L, 0);
if (newIndexSize == header.root[1-curr].indexSize) {
break;
}
free(newIndex, newIndexSize*8L);
newIndexSize = header.root[1-curr].indexSize;
}
header.root[1-curr].shadowIndex = newIndex;
header.root[1-curr].shadowIndexSize = newIndexSize;
free(header.root[curr].index, oldIndexSize*8L);
}
long currSize = header.root[1-curr].size;
for (i = 0; i < nPages; i++) {
if ((map[i >> 5] & (1 << (i & 31))) != 0) {
Page srcIndex = pool.getPage(header.root[1-curr].index + (long)i*Page.pageSize);
Page dstIndex = pool.getPage(header.root[curr].index + (long)i*Page.pageSize);
for (j = 0; j < Page.pageSize; j += 8) {
long pos = Bytes.unpack8(dstIndex.data, j);
if (Bytes.unpack8(srcIndex.data, j) != pos && pos < currSize) {
if ((pos & dbFreeHandleFlag) == 0) {
if ((pos & dbPageObjectFlag) != 0) {
free(pos & ~dbFlagsMask, Page.pageSize);
} else if (pos != 0) {
int offs = (int)pos & (Page.pageSize-1);
pg = pool.getPage(pos-offs);
free(pos, ObjectHeader.getSize(pg.data, offs));
pool.unfix(pg);
}
}
}
}
pool.unfix(srcIndex);
pool.unfix(dstIndex);
}
}
n = committedIndexSize & (dbHandlesPerPage-1);
if (n != 0 && (map[i >> 5] & (1 << (i & 31))) != 0) {
Page srcIndex = pool.getPage(header.root[1-curr].index + (long)i*Page.pageSize);
Page dstIndex = pool.getPage(header.root[curr].index + (long)i*Page.pageSize);
j = 0;
do {
long pos = Bytes.unpack8(dstIndex.data, j);
if (Bytes.unpack8(srcIndex.data, j) != pos && pos < currSize) {
if ((pos & dbFreeHandleFlag) == 0) {
if ((pos & dbPageObjectFlag) != 0) {
free(pos & ~dbFlagsMask, Page.pageSize);
} else if (pos != 0) {
int offs = (int)pos & (Page.pageSize-1);
pg = pool.getPage(pos - offs);
free(pos, ObjectHeader.getSize(pg.data, offs));
pool.unfix(pg);
}
}
}
j += 8;
} while (--n != 0);
pool.unfix(srcIndex);
pool.unfix(dstIndex);
}
for (i = 0; i <= nPages; i++) {
if ((map[i >> 5] & (1 << (i & 31))) != 0) {
pg = pool.putPage(header.root[1-curr].index + (long)i*Page.pageSize);
for (j = 0; j < Page.pageSize; j += 8) {
Bytes.pack8(pg.data, j, Bytes.unpack8(pg.data, j) & ~dbModifiedFlag);
}
pool.unfix(pg);
}
}
if (currIndexSize > committedIndexSize) {
long page = (header.root[1-curr].index
+ committedIndexSize*8L) & ~(Page.pageSize-1);
long end = (header.root[1-curr].index + Page.pageSize - 1
+ currIndexSize*8L) & ~(Page.pageSize-1);
while (page < end) {
pg = pool.putPage(page);
for (j = 0; j < Page.pageSize; j += 8) {
Bytes.pack8(pg.data, j, Bytes.unpack8(pg.data, j) & ~dbModifiedFlag);
}
pool.unfix(pg);
page += Page.pageSize;
}
}
header.root[1-curr].usedSize = usedSize;
pg = pool.putPage(0);
header.pack(pg.data);
pool.flush();
pool.modify(pg);
Assert.that(header.transactionId == transactionId);
header.transactionId = ++transactionId;
header.curr = curr ^= 1;
header.dirty = true;
header.pack(pg.data);
pool.unfix(pg);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -