use of jetbrains.exodus.tree.btree.BTree in project xodus by JetBrains.
the class MetaTree method create.
static Pair<MetaTree, Integer> create(@NotNull final EnvironmentImpl env) {
final Log log = env.getLog();
LogTip logTip = log.getTip();
if (logTip.highAddress > EMPTY_LOG_BOUND) {
Loggable rootLoggable = log.getLastLoggableOfType(DatabaseRoot.DATABASE_ROOT_TYPE);
while (rootLoggable != null) {
final DatabaseRoot dbRoot = new DatabaseRoot(rootLoggable);
final long root = dbRoot.getAddress();
if (dbRoot.isValid()) {
try {
final LogTip updatedTip = log.setHighAddress(logTip, root + dbRoot.length());
final BTree metaTree = env.loadMetaTree(dbRoot.getRootAddress(), updatedTip);
if (metaTree != null) {
// try to traverse meta tree
cloneTree(metaTree);
return new Pair<>(new MetaTree(metaTree, root, updatedTip), dbRoot.getLastStructureId());
}
logTip = updatedTip;
} catch (ExodusException e) {
logTip = log.getTip();
EnvironmentImpl.loggerError("Failed to recover to valid root" + LogUtil.getWrongAddressErrorMessage(dbRoot.getAddress(), env.getEnvironmentConfig().getLogFileSize()), e);
// XD-449: try next database root if we failed to traverse whole MetaTree
// TODO: this check should become obsolete after XD-334 is implemented
}
}
// continue recovery
rootLoggable = log.getLastLoggableOfTypeBefore(DatabaseRoot.DATABASE_ROOT_TYPE, root, logTip);
}
// "abnormal program termination", "blue screen of doom"
// Something quite strange with the database: it is not empty, but no valid
// root has found. We can't just reset the database and lose all the contents,
// we should have a chance to investigate the case. So failing...
//
// It's extremely likely the database was ciphered with different/unknown cipher parameters.
log.close();
throw new InvalidCipherParametersException();
}
// no roots found: the database is empty
log.setHighAddress(logTip, 0);
final ITree resultTree = getEmptyMetaTree(env);
final long root;
log.beginWrite();
final LogTip createdTip;
try {
final long rootAddress = resultTree.getMutableCopy().save();
root = log.write(DatabaseRoot.DATABASE_ROOT_TYPE, Loggable.NO_STRUCTURE_ID, DatabaseRoot.asByteIterable(rootAddress, EnvironmentImpl.META_TREE_ID));
log.flush();
createdTip = log.endWrite();
} catch (Throwable t) {
// rollback log state
log.abortWrite();
throw new ExodusException("Can't init meta tree in log", t);
}
return new Pair<>(new MetaTree(resultTree, root, createdTip), EnvironmentImpl.META_TREE_ID);
}
use of jetbrains.exodus.tree.btree.BTree in project xodus by JetBrains.
the class StoreImpl method openImmutableTree.
ITree openImmutableTree(@NotNull final MetaTree metaTree) {
final int structureId = getStructureId();
final long upToDateRootAddress = metaTree.getRootAddress(structureId);
final boolean hasDuplicates = metaInfo.hasDuplicates();
final boolean treeIsEmpty = upToDateRootAddress == Loggable.NULL_ADDRESS;
final Log log = environment.getLog();
final ITree result;
if (!metaInfo.isKeyPrefixing()) {
final BTreeBalancePolicy balancePolicy = environment.getBTreeBalancePolicy();
result = treeIsEmpty ? new BTreeEmpty(log, balancePolicy, hasDuplicates, structureId) : new BTree(log, balancePolicy, upToDateRootAddress, hasDuplicates, structureId);
} else {
if (treeIsEmpty) {
result = new PatriciaTreeEmpty(log, structureId, hasDuplicates);
} else {
result = hasDuplicates ? new PatriciaTreeWithDuplicates(log, upToDateRootAddress, structureId) : new PatriciaTree(log, upToDateRootAddress, structureId);
}
}
return result;
}
use of jetbrains.exodus.tree.btree.BTree in project xodus by JetBrains.
the class StoreImpl method openImmutableTree.
ITree openImmutableTree(@NotNull final MetaTreeImpl metaTree) {
final int structureId = getStructureId();
final long upToDateRootAddress = metaTree.getRootAddress(structureId);
final boolean hasDuplicates = metaInfo.hasDuplicates();
final boolean treeIsEmpty = upToDateRootAddress == Loggable.NULL_ADDRESS;
final Log log = environment.getLog();
final ITree result;
if (!metaInfo.isKeyPrefixing()) {
final BTreeBalancePolicy balancePolicy = environment.getBTreeBalancePolicy();
result = treeIsEmpty ? new BTreeEmpty(log, balancePolicy, hasDuplicates, structureId) : new BTree(log, balancePolicy, upToDateRootAddress, hasDuplicates, structureId);
} else {
if (treeIsEmpty) {
result = new PatriciaTreeEmpty(log, structureId, hasDuplicates);
} else {
result = hasDuplicates ? new PatriciaTreeWithDuplicates(log, upToDateRootAddress, structureId) : new PatriciaTree(log, upToDateRootAddress, structureId);
}
}
return result;
}
use of jetbrains.exodus.tree.btree.BTree in project xodus by JetBrains.
the class MetaTreeImpl method create.
static Pair<MetaTreeImpl, Integer> create(@NotNull final EnvironmentImpl env) {
final Log log = env.getLog();
LogTip logTip = log.getTip();
if (logTip.highAddress > EMPTY_LOG_BOUND) {
Loggable rootLoggable = log.getLastLoggableOfType(DatabaseRoot.DATABASE_ROOT_TYPE);
while (rootLoggable != null) {
final long root = rootLoggable.getAddress();
// work around XD-692: load database root in try-catch block
DatabaseRoot dbRoot = null;
try {
dbRoot = new DatabaseRoot(rootLoggable);
} catch (ExodusException e) {
EnvironmentImpl.loggerError("Failed to load database root at " + rootLoggable.getAddress(), e);
}
if (dbRoot != null && dbRoot.isValid()) {
try {
final LogTip updatedTip = log.setHighAddress(logTip, root + dbRoot.length());
final BTree metaTree = env.loadMetaTree(dbRoot.getRootAddress(), updatedTip);
if (metaTree != null) {
// try to traverse meta tree
cloneTree(metaTree);
// flush potential file truncation
log.sync();
return new Pair<>(new MetaTreeImpl(metaTree, root, updatedTip), dbRoot.getLastStructureId());
}
logTip = updatedTip;
} catch (ExodusException e) {
logTip = log.getTip();
EnvironmentImpl.loggerError("Failed to recover to valid root" + LogUtil.getWrongAddressErrorMessage(dbRoot.getAddress(), env.getEnvironmentConfig().getLogFileSize() * 1024L), e);
// XD-449: try next database root if we failed to traverse whole MetaTree
// TODO: this check should become obsolete after XD-334 is implemented
}
}
// continue recovery
rootLoggable = log.getLastLoggableOfTypeBefore(DatabaseRoot.DATABASE_ROOT_TYPE, root, logTip);
}
// "abnormal program termination", "blue screen of doom"
// Something quite strange with the database: it is not empty, but no valid
// root has found. We can't just reset the database and lose all the contents,
// we should have a chance to investigate the case. So failing...
//
// It's extremely likely the database was ciphered with different/unknown cipher parameters.
log.close();
throw new InvalidCipherParametersException();
}
// no roots found: the database is empty
EnvironmentImpl.loggerDebug("No roots found: the database is empty");
logTip = log.setHighAddress(logTip, 0);
final ITree resultTree = getEmptyMetaTree(env);
final long root;
log.beginWrite();
final LogTip createdTip;
try {
final long rootAddress = resultTree.getMutableCopy().save();
root = log.write(DatabaseRoot.DATABASE_ROOT_TYPE, Loggable.NO_STRUCTURE_ID, DatabaseRoot.asByteIterable(rootAddress, EnvironmentImpl.META_TREE_ID));
log.flush();
createdTip = log.endWrite();
} catch (Throwable t) {
log.revertWrite(logTip);
throw new ExodusException("Can't init meta tree in log", t);
}
return new Pair<>(new MetaTreeImpl(resultTree, root, createdTip), EnvironmentImpl.META_TREE_ID);
}
Aggregations