private unsafe void LoadExistingDatabase() { var header = stackalloc TransactionHeader[1]; bool hadIntegrityIssues = _journal.RecoverDatabase(header); if (hadIntegrityIssues) { var message = _journal.Files.Count == 0 ? "Unrecoverable database" : "Database recovered partially. Some data was lost."; _options.InvokeRecoveryError(this, message, null); } var entry = _headerAccessor.CopyHeader(); var nextPageNumber = (header->TransactionId == 0 ? entry.LastPageNumber : header->LastPageNumber) + 1; State = new StorageEnvironmentState(null, null, nextPageNumber) { NextPageNumber = nextPageNumber }; _transactionsCounter = (header->TransactionId == 0 ? entry.TransactionId : header->TransactionId); using (var tx = NewTransaction(TransactionFlags.ReadWrite)) { var root = Tree.Open(tx, _sliceComparer, header->TransactionId == 0 ? &entry.Root : &header->Root); var freeSpace = Tree.Open(tx, _sliceComparer, header->TransactionId == 0 ? &entry.FreeSpace : &header->FreeSpace); tx.UpdateRootsIfNeeded(root, freeSpace); tx.Commit(); } }
private unsafe void LoadExistingDatabase() { var header = stackalloc TransactionHeader[1]; bool hadIntegrityIssues = _journal.RecoverDatabase(header); if (hadIntegrityIssues) { var message = _journal.Files.Count == 0 ? "Unrecoverable database" : "Database recovered partially. Some data was lost."; _options.InvokeRecoveryError(this, message, null); } var entry = _headerAccessor.CopyHeader(); var nextPageNumber = (header->TransactionId == 0 ? entry.LastPageNumber : header->LastPageNumber) + 1; State = new StorageEnvironmentState(null, nextPageNumber) { NextPageNumber = nextPageNumber, Options = Options }; _transactionsCounter = (header->TransactionId == 0 ? entry.TransactionId : header->TransactionId); var transactionPersistentContext = new TransactionPersistentContext(true); using (var tx = NewLowLevelTransaction(transactionPersistentContext, TransactionFlags.ReadWrite)) { using (var root = Tree.Open(tx, null, Constants.RootTreeNameSlice, header->TransactionId == 0 ? &entry.Root : &header->Root)) { tx.UpdateRootsIfNeeded(root); using (var treesTx = new Transaction(tx)) { var metadataTree = treesTx.ReadTree(Constants.MetadataTreeNameSlice); if (metadataTree == null) { VoronUnrecoverableErrorException.Raise(this, "Could not find metadata tree in database, possible mismatch / corruption?"); } var dbId = metadataTree.Read("db-id"); if (dbId == null) { VoronUnrecoverableErrorException.Raise(this, "Could not find db id in metadata tree, possible mismatch / corruption?"); } var buffer = new byte[16]; var dbIdBytes = dbId.Reader.Read(buffer, 0, 16); if (dbIdBytes != 16) { VoronUnrecoverableErrorException.Raise(this, "The db id value in metadata tree wasn't 16 bytes in size, possible mismatch / corruption?"); } var databseGuidId = _options.GenerateNewDatabaseId == false ? new Guid(buffer) : Guid.NewGuid(); DbId = databseGuidId; FillBase64Id(databseGuidId); if (_options.GenerateNewDatabaseId) { // save the new database id metadataTree.Add("db-id", DbId.ToByteArray()); } var schemaVersion = metadataTree.Read("schema-version"); if (schemaVersion == null) { VoronUnrecoverableErrorException.Raise(this, "Could not find schema version in metadata tree, possible mismatch / corruption?"); } var schemaVersionVal = schemaVersion.Reader.ReadLittleEndianInt32(); if (Options.SchemaVersion != 0 && schemaVersionVal != Options.SchemaVersion) { VoronUnrecoverableErrorException.Raise(this, "The schema version of this database is expected to be " + Options.SchemaVersion + " but is actually " + schemaVersionVal + ". You need to upgrade the schema."); } tx.Commit(); } } } }