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