StateWaiter.java
001 /*
002  *
003  * Licensed to the Apache Software Foundation (ASF) under one
004  * or more contributor license agreements.  See the NOTICE file
005  * distributed with this work for additional information
006  * regarding copyright ownership.  The ASF licenses this file
007  * to you under the Apache License, Version 2.0 (the
008  * "License"); you may not use this file except in compliance
009  * with the License.  You may obtain a copy of the License at
010  *
011  *   http://www.apache.org/licenses/LICENSE-2.0
012  *
013  * Unless required by applicable law or agreed to in writing,
014  * software distributed under the License is distributed on an
015  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
016  * KIND, either express or implied.  See the License for the
017  * specific language governing permissions and limitations
018  * under the License.
019  *
020  */
021 package org.apache.qpid.client.state;
022 
023 import org.apache.qpid.client.util.BlockingWaiter;
024 import org.apache.qpid.client.failover.FailoverException;
025 import org.apache.qpid.AMQException;
026 import org.slf4j.LoggerFactory;
027 import org.slf4j.Logger;
028 
029 import java.util.Set;
030 
031 /**
032  * This is an implementation of the {@link BlockingWaiter} to provide error handing and a waiting mechanism for state
033  * changes.
034  *
035  * On construction the current state and a set of States to await for is provided.
036  *
037  * When await() is called the state at constuction is compared against the awaitStates. If the state at construction is
038  * a desired state then await() returns immediately.
039  *
040  * Otherwise it will block for the set timeout for a desired state to be achieved.
041  *
042  * The state changes are notified via the {@link #process} method.
043  *
044  * Any notified error is handled by the BlockingWaiter and thrown from the {@link #block} method.
045  *
046  */
047 public class StateWaiter extends BlockingWaiter<AMQState>
048 {
049     private static final Logger _logger = LoggerFactory.getLogger(StateWaiter.class);
050 
051     Set<AMQState> _awaitStates;
052     private AMQState _startState;
053     private AMQStateManager _stateManager;
054 
055     /**
056      *
057      @param stateManager The StateManager
058      @param currentState
059      @param awaitStates
060      */
061     public StateWaiter(AMQStateManager stateManager, AMQState currentState, Set<AMQState> awaitStates)
062     {
063         _logger.info("New StateWaiter :" + currentState + ":" + awaitStates);
064         _stateManager = stateManager;
065         _awaitStates = awaitStates;
066         _startState = currentState;
067     }
068 
069     /**
070      * When the state is changed this StateWaiter is notified to process the change.
071      *
072      @param state The new state that has been achieved.
073      @return
074      */
075     public boolean process(AMQState state)
076     {
077         return _awaitStates.contains(state);
078     }
079 
080     /**
081      * Await for the requried State to be achieved within the default timeout.
082      @return The achieved state that was requested.
083      @throws AMQException The exception that prevented the required state from being achived.
084      */
085     public AMQState await() throws AMQException
086     {
087         return await(_stateManager.getWaitTimeout());
088     }
089 
090     /**
091      * Await for the requried State to be achieved.
092      *
093      <b>It is the responsibility of this class to remove the waiter from the StateManager
094      *
095      @param timeout The time in milliseconds to wait for any of the states to be achived.
096      @return The achieved state that was requested.
097      @throws AMQException The exception that prevented the required state from being achived.
098      */
099     public AMQState await(long timeoutthrows AMQException
100     {
101         try
102         {
103             if (process(_startState))
104             {
105                 return _startState;
106             }
107 
108             try
109             {
110                 return (AMQStateblock(timeout);
111             }
112             catch (FailoverException e)
113             {
114                 _logger.error("Failover occured whilst waiting for states:" + _awaitStates);
115 
116                 e.printStackTrace();
117                 return null;
118             }
119         }
120         finally
121         {
122             //Prevent any more errors being notified to this waiter.
123             close();
124 
125             //Remove the waiter from the notifcation list in the statee manager
126             _stateManager.removeWaiter(this);
127         }
128     }
129 }