1 /*-
2  * See the file LICENSE for redistribution information.
3  *
4  * Copyright (c) 2002, 2014 Oracle and/or its affiliates.  All rights reserved.
5  */
6 
7 package com.sleepycat.je.rep.arbitration;
8 
9 import java.util.logging.Logger;
10 
11 import com.sleepycat.je.Durability.ReplicaAckPolicy;
12 import com.sleepycat.je.rep.QuorumPolicy;
13 import com.sleepycat.je.rep.ReplicationMutableConfig;
14 import com.sleepycat.je.rep.impl.RepImpl;
15 import com.sleepycat.je.utilint.LoggerUtils;
16 
17 /**
18  * The locus for management of this node's active arbitration state, and of the
19  * mechanisms available to this node for doing arbitration.
20  * <p>
21  * A node is in active arbitration state if
22  * <ul>
23  * <li> is the master
24  * <li> is lacking the required durability quorum
25  * <li> is maintaining its authoritative master status and its ability to
26  * commit writes through the good graces of an ArbiterProvider.
27  * </ul>
28  * <p>
29  * The Arbiter detects which arbitration options are available in the JE HA
30  * group.
31  */
32 public class Arbiter {
33 
34     /**
35      * True if this node is in active arbitration.
36      */
37     private volatile boolean active;
38 
39     private final ArbiterProvider provider;
40 
41     private final RepImpl repImpl;
42     private final Logger logger;
43 
44     /**
45      * Examine environment configuration and rep group membership to figure out
46      * which arbitration options are in operation for this HA group.
47      */
Arbiter(RepImpl repImpl)48     public Arbiter(RepImpl repImpl) {
49         this.repImpl = repImpl;
50         provider = new DesignatedPrimaryProvider(repImpl);
51         logger = LoggerUtils.getLogger(this.getClass());
52     }
53 
54     /**
55      * The replication node knows that it has lost its durability quorum, and
56      * wants to try to enter active arbitration mode.
57      * @return true if the node successfully transitions to active arbitration,
58      * or was already in active arbitration.
59      */
activateArbitration()60     public synchronized boolean activateArbitration() {
61         if (provider.attemptActivation()) {
62             active = true;
63         } else {
64             active = false;
65         }
66         return active;
67     }
68 
69     /**
70      * The node has determined that it need not be in active arbitration.
71      * End the active arbitration state. If the node was not in active
72      * arbitration, do nothing.
73      */
endArbitration()74     public void endArbitration() {
75         synchronized(this) {
76             if (!active) {
77                 return;
78             }
79 
80             provider.endArbitration();
81             active = false;
82         }
83 
84         LoggerUtils.info(logger, repImpl, "Arbitration is inactivated");
85     }
86 
87     /**
88      * Return true if it's possible that this node can switch into active
89      * arbitration. The criteria for activation depend on the type of
90      * arbitration enabled for this node.
91      * <p>
92      * For example, if designated primary arbitration is used, then it's only
93      * possible to move into active arbitration if the Designated Primary
94      * configuration parameter is set for this node. If LWT Node arbitration is
95      * used, then this node must have a valid connection to the arbiter node.
96      */
activationPossible()97     public boolean activationPossible() {
98         return provider.activationPossible();
99     }
100 
101     /**
102      * Return true if this node is in active arbitration, and if arbitration
103      * should take precedence over the election quorum policy.
104      */
isApplicable(QuorumPolicy quorumPolicy)105     public boolean isApplicable(QuorumPolicy quorumPolicy) {
106         return active && (quorumPolicy.equals(QuorumPolicy.SIMPLE_MAJORITY));
107     }
108 
109     /**
110      * Return true if this node is in active arbitration, and if arbitration
111      * should take precedence over the durability quorum policy.
112      */
isApplicable(ReplicaAckPolicy ackPolicy)113     public boolean isApplicable(ReplicaAckPolicy ackPolicy) {
114         return active && (ackPolicy.equals(ReplicaAckPolicy.SIMPLE_MAJORITY));
115     }
116 
117     /**
118      * Return the arbitration-influenced election quorum size. Arbitration
119      * may reduce the value that would usually be indicated by the quorum
120      * policy.
121      */
getElectionQuorumSize(QuorumPolicy quorumPolicy)122     public int getElectionQuorumSize(QuorumPolicy quorumPolicy) {
123         return provider.getElectionQuorumSize(quorumPolicy);
124     }
125 
126     /**
127      * Return the arbitration-influenced durability quorum size. Arbitration
128      * may reduce the value that would usually be indicated by the ack policy.
129      */
getAckCount(ReplicaAckPolicy ackPolicy)130     public int getAckCount(ReplicaAckPolicy ackPolicy) {
131         return provider.getAckCount(ackPolicy);
132     }
133 
134     /**
135      * The replication configuration was changed. Check the new configuration
136      * to see it impacts active arbitration state or makes more arbitration
137      * mechanisms available. For example, if we are in active arbitration using
138      * designated primary arbitration, a change to the node's designated
139      * primary configuration parameter may affect whether this node can stay in
140      * active arbitration.
141      */
142     public synchronized void
processConfigChange(ReplicationMutableConfig newConfig)143         processConfigChange (ReplicationMutableConfig newConfig) {
144 
145         if (!active) {
146             return;
147         }
148 
149         if (provider.shouldEndArbitration(newConfig)) {
150             endArbitration();
151         }
152     }
153 
154     /**
155      * Return true if this node is in active arbitration.
156      */
isActive()157     public synchronized boolean isActive() {
158         return active;
159     }
160 }
161 
162 
163 
164