public virtual void Open(IFile file, int pagePoolSize) { lock (this) { if (opened) { throw new StorageError(StorageError.STORAGE_ALREADY_OPENED); } if (lockFile) { if (!file.Lock()) { throw new StorageError(StorageError.STORAGE_IS_USED); } } Page pg; int i; int indexSize = initIndexSize; if (indexSize < dbFirstUserId) { indexSize = dbFirstUserId; } indexSize = (indexSize + dbHandlesPerPage - 1) & ~ (dbHandlesPerPage - 1); dirtyPagesMap = new int[dbDirtyPageBitmapSize / 4 + 1]; gcThreshold = Int64.MaxValue; backgroundGcMonitor = new object(); backgroundGcStartMonitor = new object(); gcThread = null; gcActive = false; gcDone = false; allocatedDelta = 0; nNestedTransactions = 0; nBlockedTransactions = 0; nCommittedTransactions = 0; scheduledCommitTime = Int64.MaxValue; transactionMonitor = new object(); transactionLock = new PersistentResource(); modified = false; objectCache = CreateObjectCache(cacheKind, pagePoolSize, objectCacheInitSize); //UPGRADE_TODO: Class 'java.util.HashMap' was converted to 'System.Collections.Hashtable' which has a different behavior. classDescMap = new Hashtable(); descList = null; header = new Header(); byte[] buf = new byte[Header.Sizeof]; int rc = file.Read(0, buf); if (rc > 0 && rc < Header.Sizeof) { throw new StorageError(StorageError.DATABASE_CORRUPTED); } header.Unpack(buf); if (header.curr < 0 || header.curr > 1) { throw new StorageError(StorageError.DATABASE_CORRUPTED); } if (pool == null) { pool = new PagePool(pagePoolSize / Page.pageSize); pool.Open(file); } if (!header.initialized) { header.curr = currIndex = 0; long used = Page.pageSize; header.root[0].index = used; header.root[0].indexSize = indexSize; header.root[0].indexUsed = dbFirstUserId; header.root[0].freeList = 0; used += indexSize * 8L; header.root[1].index = used; header.root[1].indexSize = indexSize; header.root[1].indexUsed = dbFirstUserId; header.root[1].freeList = 0; used += indexSize * 8L; 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) (SupportClass.URShift((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(); } Console.Error.WriteLine("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(); } Console.Error.WriteLine("Recovery completed"); } currIndexSize = header.root[1 - curr].indexUsed; committedIndexSize = currIndexSize; usedSize = header.root[curr].size; } int bitmapSize2 = header.root[1 - currIndex].bitmapExtent == 0 ? dbBitmapPages : dbLargeBitmapPages; bitmapPageAvailableSpace = new int[bitmapSize2]; for (i = 0; i < bitmapPageAvailableSpace.Length; i++) { bitmapPageAvailableSpace[i] = Int32.MaxValue; } currRBitmapPage = currPBitmapPage = 0; currRBitmapOffs = currPBitmapOffs = 0; opened = true; ReloadScheme(); } }