use of jetbrains.exodus.tree.ExpiredLoggableCollection in project xodus by JetBrains.
the class EnvironmentImpl method flushTransaction.
boolean flushTransaction(@NotNull final ReadWriteTransaction txn, final boolean forceCommit) {
checkIfTransactionCreatedAgainstThis(txn);
if (!forceCommit && txn.isIdempotent()) {
return true;
}
final ExpiredLoggableCollection expiredLoggables;
final long initialHighAddress;
final long resultingHighAddress;
final boolean isGcTransaction = txn.isGCTransaction();
boolean wasUpSaved = false;
final UtilizationProfile up = gc.getUtilizationProfile();
if (!isGcTransaction && up.isDirty()) {
up.save(txn);
wasUpSaved = true;
}
synchronized (commitLock) {
if (ec.getEnvIsReadonly()) {
throw new ReadonlyTransactionException();
}
checkIsOperative();
if (!txn.checkVersion(metaTree.root)) {
// meta lock not needed 'cause write can only occur in another commit lock
return false;
}
if (wasUpSaved) {
up.setDirty(false);
}
final LogTip logTip = log.beginWrite();
initialHighAddress = logTip.highAddress;
boolean writeConfirmed = false;
try {
final MetaTreeImpl.Proto[] tree = new MetaTreeImpl.Proto[1];
expiredLoggables = txn.doCommit(tree);
// there is a temptation to postpone I/O in order to reduce number of writes to storage device,
// but it's quite difficult to resolve all possible inconsistencies afterwards,
// so think twice before removing the following line
log.flush();
final MetaTreeImpl.Proto proto = tree[0];
metaWriteLock.lock();
try {
final LogTip updatedTip = log.endWrite();
writeConfirmed = true;
resultingHighAddress = updatedTip.approvedHighAddress;
txn.setMetaTree(metaTree = MetaTreeImpl.create(this, updatedTip, proto));
txn.executeCommitHook();
} finally {
metaWriteLock.unlock();
}
// update txn profiler within commitLock
updateTxnProfiler(txn, initialHighAddress, resultingHighAddress);
} catch (Throwable t) {
// pokemon exception handling to decrease try/catch block overhead
loggerError("Failed to flush transaction", t);
if (writeConfirmed) {
// inoperative on failing to read meta tree
throwableOnCommit = t;
throw ExodusException.toExodusException(t, "Failed to read meta tree");
}
try {
log.revertWrite(logTip);
} catch (Throwable th) {
// inoperative on failing to update high address
throwableOnCommit = t;
loggerError("Failed to rollback high address", th);
throw ExodusException.toExodusException(th, "Failed to rollback high address");
}
throw ExodusException.toExodusException(t, "Failed to flush transaction");
}
}
gc.fetchExpiredLoggables(expiredLoggables);
// update statistics
statistics.getStatisticsItem(BYTES_WRITTEN).setTotal(resultingHighAddress);
if (isGcTransaction) {
statistics.getStatisticsItem(BYTES_MOVED_BY_GC).addTotal(resultingHighAddress - initialHighAddress);
}
statistics.getStatisticsItem(FLUSHED_TRANSACTIONS).incTotal();
return true;
}
use of jetbrains.exodus.tree.ExpiredLoggableCollection in project xodus by JetBrains.
the class ReadWriteTransaction method doCommit.
ExpiredLoggableCollection doCommit(@NotNull final MetaTreeImpl.Proto[] out) {
final Set<Map.Entry<Integer, ITreeMutable>> entries = mutableTrees.entrySet();
final Set<Map.Entry<Long, Pair<String, ITree>>> removedEntries = removedStores.entrySet();
ExpiredLoggableCollection expiredLoggables = ExpiredLoggableCollection.getEMPTY();
final ITreeMutable metaTreeMutable = getMetaTree().tree.getMutableCopy();
for (final Map.Entry<Long, Pair<String, ITree>> entry : removedEntries) {
final Pair<String, ITree> value = entry.getValue();
MetaTreeImpl.removeStore(metaTreeMutable, value.getFirst(), entry.getKey());
expiredLoggables = expiredLoggables.mergeWith(TreeMetaInfo.getTreeLoggables(value.getSecond()).trimToSize());
}
removedStores.clear();
for (final Map.Entry<String, TreeMetaInfo> entry : createdStores.entrySet()) {
MetaTreeImpl.addStore(metaTreeMutable, entry.getKey(), entry.getValue());
}
createdStores.clear();
for (final Map.Entry<Integer, ITreeMutable> entry : entries) {
final ITreeMutable treeMutable = entry.getValue();
expiredLoggables = expiredLoggables.mergeWith(treeMutable.getExpiredLoggables().trimToSize());
MetaTreeImpl.saveTree(metaTreeMutable, treeMutable);
}
clearImmutableTrees();
mutableTrees.clear();
expiredLoggables = expiredLoggables.mergeWith(metaTreeMutable.getExpiredLoggables().trimToSize());
out[0] = MetaTreeImpl.saveMetaTree(metaTreeMutable, getEnvironment(), expiredLoggables);
return expiredLoggables;
}
Aggregations