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.impl.node;
8 
9 import java.util.concurrent.atomic.AtomicReference;
10 import java.util.logging.Logger;
11 
12 import com.sleepycat.je.EnvironmentFailureException;
13 import com.sleepycat.je.dbi.EnvironmentFailureReason;
14 import com.sleepycat.je.rep.ReplicatedEnvironment;
15 import com.sleepycat.je.rep.StateChangeEvent;
16 import com.sleepycat.je.rep.StateChangeListener;
17 import com.sleepycat.je.rep.impl.RepImpl;
18 import com.sleepycat.je.utilint.LoggerUtils;
19 
20 /**
21  * NodeState encapsulates the current replicator state, and the ability to wait
22  * for state transition and fire state change notifications.
23  */
24 public class NodeState {
25     /* The rep impl whose state is being tracked. */
26     private final RepImpl repImpl;
27 
28     /* The application registered state change listener for this node. */
29     private StateChangeListener stateChangeListener = null;
30 
31     /* The state change event that resulted in the current state. */
32     private StateChangeEvent stateChangeEvent = null;
33     private final AtomicReference<ReplicatedEnvironment.State> currentState;
34     private final Logger logger;
35     private final NameIdPair nameIdPair;
36 
NodeState(NameIdPair nameIdPair, RepImpl repImpl)37     public NodeState(NameIdPair nameIdPair,
38                      RepImpl repImpl) {
39 
40         currentState = new AtomicReference<ReplicatedEnvironment.State>
41             (ReplicatedEnvironment.State.DETACHED);
42         this.nameIdPair = nameIdPair;
43         this.repImpl = repImpl;
44         logger = LoggerUtils.getLogger(getClass());
45     }
46 
47     synchronized public
setChangeListener(StateChangeListener stateChangeListener)48         void setChangeListener(StateChangeListener stateChangeListener){
49         this.stateChangeListener = stateChangeListener;
50     }
51 
getChangeListener()52     synchronized public StateChangeListener getChangeListener() {
53         return stateChangeListener;
54     }
55 
56     /**
57      * Change to a new node state and release any threads waiting for a state
58      * transition.
59      */
changeAndNotify(ReplicatedEnvironment.State state, NameIdPair masterNameId)60     synchronized public void changeAndNotify(ReplicatedEnvironment.State state,
61                                              NameIdPair masterNameId) {
62 
63         ReplicatedEnvironment.State newState = state;
64         ReplicatedEnvironment.State oldState = currentState.getAndSet(state);
65         stateChangeEvent = new StateChangeEvent(state, masterNameId);
66 
67         LoggerUtils.finest(logger, repImpl,
68                            "state change from " + oldState + " to " +
69                            newState);
70 
71         if (stateChangeListener != null) {
72             try {
73                 stateChangeListener.stateChange(stateChangeEvent);
74             } catch (Exception e) {
75                 LoggerUtils.severe(logger, repImpl,
76                                    "State Change listener exception" +
77                                    e.getMessage());
78                 throw new EnvironmentFailureException
79                     (repImpl, EnvironmentFailureReason.LISTENER_EXCEPTION, e);
80             }
81         }
82 
83         /* Make things obvious in thread dumps */
84         Thread.currentThread().setName(currentState + " " + nameIdPair);
85     }
86 
getRepEnvState()87     synchronized public ReplicatedEnvironment.State getRepEnvState() {
88         return currentState.get();
89     }
90 
getStateChangeEvent()91     synchronized public StateChangeEvent getStateChangeEvent() {
92         return stateChangeEvent;
93     }
94 }
95