All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.sleepycat.je.rep.impl.node.CommitFreezeLatch Maven / Gradle / Ivy

The newest version!
/*-
 * Copyright (C) 2002, 2018, Oracle and/or its affiliates. All rights reserved.
 *
 * This file was distributed by Oracle as part of a version of Oracle Berkeley
 * DB Java Edition made available at:
 *
 * http://www.oracle.com/technetwork/database/database-technologies/berkeleydb/downloads/index.html
 *
 * Please see the LICENSE file included in the top-level directory of the
 * appropriate version of Oracle Berkeley DB Java Edition for a copy of the
 * license and additional information.
 */
package com.sleepycat.je.rep.impl.node;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

import com.sleepycat.je.rep.elections.Proposer.Proposal;

/**
 * Ensures that a VLSN is not advanced at this node while an election is in
 * progress. Note that this is difficult, if not impossible to achieve
 * efficiently in a distributed environment across the entire group, when
 * communications may not always be reliable. So, the implementation really
 * represents a good faith effort to freeze the VLSN. JE HA itself should be
 * able to make forward progress in the event of such a failure.
 *
 * The class coordinates three threads: the acceptor, the learner, and the
 * replay thread. There is exactly one instance of each thread per replication
 * node, so it coordinates the activity of these three threads.
 *
 * The typical serialized sequence of calls is therefore:
 *
 * latch.freeze() -- invoked in response to a Promise by an Acceptor
 * latch.vlsnEvent() -- one or more of them in response to ongoing election
 * latch.awaitThaw() -- by the replica thread waiting for the freeze to lift
 *
 * Both vlsnEvent() and awaitThaw() are NOPs in the absence of a freeze.
 *
 * @see Freezing VLSNs
 */
public class CommitFreezeLatch {

    /* The current frozen promise/vlsn pair */
    private Proposal proposal = null;

    /* Statistics */
    private int freezeCount = 0;
    private int awaitTimeoutCount = 0;
    private int awaitElectionCount = 0;

    /* The latch used internally. */
    private CountDownLatch latch = null;
    /* The end time of the freeze. */
    private long freezeEnd = 0;
    private long timeOut = DEFAULT_LATCH_TIMEOUT;

    private static long DEFAULT_LATCH_TIMEOUT = 5000; // ms

    public int getAwaitTimeoutCount() {
        return awaitTimeoutCount;
    }

    public int getAwaitElectionCount() {
        return awaitElectionCount;
    }

    public int getFreezeCount() {
        return freezeCount;
    }

    public long getTimeOut() {
        return timeOut;
    }

    public void setTimeOut(long timeOut) {
        this.timeOut = timeOut;
    }

    /**
     * Initiates or extends a freeze on a VLSN in response to a new election
     * that is in progress. It's invoked by the Acceptor thread.
     *
     * @param freezeProposal identifies the election that is provoking the freeze
     */
    public synchronized void freeze(Proposal freezeProposal) {
        if ((proposal != null) && (freezeProposal.compareTo(proposal) <= 0)) {
            // Older proposal ignore it.
            return;
        }
        if (latch != null) {
            /* Enable waiters who will reacquire the new latch below. */
            latch.countDown();
        }
        latch = new CountDownLatch(1);
        proposal = freezeProposal;
        freezeEnd = System.currentTimeMillis() + timeOut;
        return;
    }

    /**
     * Invoked by the Learner thread whenever it receives an election result.
     * The freeze on the VLSN is only lifted if the proposal associated with
     * the event is current, that is, it represents a proposal that is newer
     * than the one used to establish the freeze.
     *
     * @param listenerProposal identifies the election that just concluded
     */
    public synchronized void vlsnEvent(Proposal listenerProposal) {
        if (proposal == null) {
            // No VLSN to unfreeze
            return;
        }
        if (listenerProposal.compareTo(this.proposal) >= 0) {
            latch.countDown();
        }
    }

    /**
     * Clears the latch freeing any waiters.
     */
    public synchronized void clearLatch() {
        if (latch != null) {
            latch.countDown();
        }
        latch = null;
        proposal = null;
        freezeEnd = 0;
    }

    /**
     * Used to wait for an event that unfreezes the VLSN. In our case this
     * event is a message to the Learner agent announcing the result of an
     * election. Note that the latch must be re-initialized after a return from
     * this await method.
     *
     * This method is invoked by the Replay thread. Completion of an awaitThaw
     * always results in the freeze being lifted.
     *
     * @return true if the await was satisfied due to completion of an
     * election, false if no freeze was in effect, or the latch was timed out.
     *
     * @throws InterruptedException
     */
    public boolean awaitThaw()
        throws InterruptedException {

        CountDownLatch awaitLatch;
        long awaitTimeout;

        synchronized (this) {
            /* Copy out the values of interest  */
            awaitLatch = latch;
            if (awaitLatch == null) {
                return false;
            }
            awaitTimeout = this.freezeEnd - System.currentTimeMillis();
        }
        freezeCount++;

        boolean done = awaitLatch.await(awaitTimeout, TimeUnit.MILLISECONDS);

        synchronized (this) {
            if (done) {
                awaitElectionCount++;
                clearLatch();
                return true;
            }
            if (this.freezeEnd - System.currentTimeMillis() <= 0) {
                awaitTimeoutCount++;
                /* freeze end was not extended, election completed. */
                clearLatch();
                return false;
            }
        }
        /* Re-acquire the new latch and wait for the extended timeout. */
        return awaitThaw();
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy