1 | package com.joelpm.bidiMessages.client;
|
---|
2 |
|
---|
3 | import java.util.ArrayList;
|
---|
4 | import java.util.List;
|
---|
5 | import java.util.Timer;
|
---|
6 | import java.util.TimerTask;
|
---|
7 | import java.util.concurrent.atomic.AtomicBoolean;
|
---|
8 |
|
---|
9 | import org.apache.thrift.transport.TTransport;
|
---|
10 | import org.apache.thrift.transport.TTransportException;
|
---|
11 |
|
---|
12 | /**
|
---|
13 | * This class is responsible for notifying others when the
|
---|
14 | * connection is lost or established and for attempting to
|
---|
15 | * reconnect when the connection is lost.
|
---|
16 | *
|
---|
17 | * @author Joel Meyer
|
---|
18 | */
|
---|
19 | public class ConnectionStatusMonitor {
|
---|
20 | /**
|
---|
21 | * Simple task used to attempt a reconnect every few seconds.
|
---|
22 | */
|
---|
23 | private class RetryTask extends TimerTask {
|
---|
24 | @Override public void run() {
|
---|
25 | tryOpen();
|
---|
26 | }
|
---|
27 | }
|
---|
28 |
|
---|
29 | private final Timer timer;
|
---|
30 |
|
---|
31 | private final TTransport transport;
|
---|
32 | private final AtomicBoolean connected;
|
---|
33 | private final List<ConnectionStatusListener> listeners;
|
---|
34 |
|
---|
35 | public ConnectionStatusMonitor(TTransport transport) {
|
---|
36 | this.transport = transport;
|
---|
37 | this.connected = new AtomicBoolean(false);
|
---|
38 | this.listeners = new ArrayList<ConnectionStatusListener>();
|
---|
39 |
|
---|
40 | this.timer = new Timer();
|
---|
41 | }
|
---|
42 |
|
---|
43 | public void addListener(ConnectionStatusListener listener) {
|
---|
44 | listeners.add(listener);
|
---|
45 | }
|
---|
46 |
|
---|
47 | public void disconnected(ConnectionStatusListener noticer) {
|
---|
48 | if (connected.compareAndSet(true, false)) {
|
---|
49 | for (ConnectionStatusListener listener : listeners) {
|
---|
50 | // The thread running the noticer is our current execution thread. If we
|
---|
51 | // notify him he'll block and we'll be deadlocked. Since he noticed the
|
---|
52 | // disconnect he is responsible for initiating his own wait state.
|
---|
53 | if (listener == noticer) continue;
|
---|
54 | listener.connectionLost();
|
---|
55 | }
|
---|
56 |
|
---|
57 | // Try to reconnect in five seconds
|
---|
58 | timer.schedule(new RetryTask(), 5 * 1000);
|
---|
59 | }
|
---|
60 | }
|
---|
61 |
|
---|
62 | /**
|
---|
63 | * Attempts to reconnect to the server.
|
---|
64 | */
|
---|
65 | public void tryOpen() {
|
---|
66 | if (connected.get()) return;
|
---|
67 |
|
---|
68 | // Make sure it's closed
|
---|
69 | transport.close();
|
---|
70 |
|
---|
71 | try {
|
---|
72 | transport.open();
|
---|
73 | connected.set(true);
|
---|
74 | for (ConnectionStatusListener listener : listeners) {
|
---|
75 | listener.connectionEstablished();
|
---|
76 | }
|
---|
77 | return;
|
---|
78 | } catch (TTransportException e) {
|
---|
79 |
|
---|
80 | }
|
---|
81 |
|
---|
82 | timer.schedule(new RetryTask(), 5 * 1000);
|
---|
83 | }
|
---|
84 | }
|
---|
85 |
|
---|