boolean flushTransaction()

in environment/src/main/java/jetbrains/exodus/env/EnvironmentImpl.java [913:991]


    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 (isReadOnly()) {
                throw new ReadonlyTransactionException();
            }
            checkIsOperative();
            if (txn.invalidVersion(metaTree.root)) {
                // meta lock not needed 'cause write can only occur in another commit lock
                return false;
            }

            txn.executeBeforeTransactionFlushAction();

            if (wasUpSaved) {
                up.setDirty(false);
            }
            initialHighAddress = log.beginWrite();
            try {
                final MetaTreeImpl.Proto[] tree = new MetaTreeImpl.Proto[1];
                final long updatedHighAddress;
                try {
                    expiredLoggables = txn.doCommit(tree, log);
                } finally {
                    log.flush();
                    updatedHighAddress = log.endWrite();
                }

                final MetaTreeImpl.Proto proto = tree[0];
                metaWriteLock.lock();
                try {
                    resultingHighAddress = updatedHighAddress;
                    txn.setMetaTree(metaTree = MetaTreeImpl.create(this, proto));
                    txn.executeCommitHook();
                } finally {
                    metaWriteLock.unlock();
                }
                // update txn profiler within commitLock
                updateTxnProfiler(txn, initialHighAddress, resultingHighAddress);
            } catch (final Throwable t) {
                final String errorMessage = "Failed to flush transaction. Please close and open environment " +
                        "to trigger environment recovery routine";

                loggerError(errorMessage, t);

                log.switchToReadOnlyMode();
                throwableOnCommit = t;

                throw ExodusException.toExodusException(t, errorMessage);
            }
        }
        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;
    }