Search in sources :

Example 1 with LogTip

use of jetbrains.exodus.log.LogTip 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;
}
Also used : ExpiredLoggableCollection(jetbrains.exodus.tree.ExpiredLoggableCollection) LogTip(jetbrains.exodus.log.LogTip) UtilizationProfile(jetbrains.exodus.gc.UtilizationProfile)

Aggregations

UtilizationProfile (jetbrains.exodus.gc.UtilizationProfile)1 LogTip (jetbrains.exodus.log.LogTip)1 ExpiredLoggableCollection (jetbrains.exodus.tree.ExpiredLoggableCollection)1