1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.hadoop.hbase.master;
21
22 import java.io.IOException;
23 import java.util.Set;
24 import java.util.concurrent.BlockingQueue;
25 import java.util.concurrent.CopyOnWriteArraySet;
26 import java.util.concurrent.DelayQueue;
27 import java.util.concurrent.PriorityBlockingQueue;
28 import java.util.concurrent.TimeUnit;
29 import java.util.concurrent.atomic.AtomicBoolean;
30
31 import org.apache.commons.logging.Log;
32 import org.apache.commons.logging.LogFactory;
33 import org.apache.hadoop.conf.Configuration;
34 import org.apache.hadoop.hbase.HConstants;
35 import org.apache.hadoop.hbase.HMsg;
36 import org.apache.hadoop.hbase.HServerInfo;
37 import org.apache.hadoop.hbase.HServerAddress;
38 import org.apache.hadoop.hbase.RemoteExceptionHandler;
39 import org.apache.hadoop.hbase.util.Sleeper;
40 import org.apache.hadoop.ipc.RemoteException;
41
42
43
44
45
46
47
48
49
50
51
52 public class RegionServerOperationQueue {
53
54 private final Log LOG = LogFactory.getLog(this.getClass());
55
56
57
58
59 public static enum ProcessingResultCode {
60
61
62
63 PROCESSED,
64
65
66
67 NOOP,
68
69
70
71 REQUEUED,
72
73
74
75 FAILED,
76
77
78
79
80 REQUEUED_BUT_PROBLEM
81 };
82
83
84
85
86
87 private final DelayQueue<RegionServerOperation> delayedToDoQueue =
88 new DelayQueue<RegionServerOperation>();
89 private final BlockingQueue<RegionServerOperation> toDoQueue =
90 new PriorityBlockingQueue<RegionServerOperation>();
91 private final Set<RegionServerOperationListener> listeners =
92 new CopyOnWriteArraySet<RegionServerOperationListener>();
93 private final int threadWakeFrequency;
94 private final AtomicBoolean closed;
95 private final Sleeper sleeper;
96
97 RegionServerOperationQueue(final Configuration c, final AtomicBoolean closed) {
98 this.threadWakeFrequency = c.getInt(HConstants.THREAD_WAKE_FREQUENCY, 10 * 1000);
99 this.closed = closed;
100 this.sleeper = new Sleeper(this.threadWakeFrequency, this.closed);
101 }
102
103 public void put(final RegionServerOperation op) {
104 try {
105 this.toDoQueue.put(op);
106 } catch (InterruptedException e) {
107 LOG.warn("Insertion into todo queue interrupted; putting on delay queue", e);
108 putOnDelayQueue(op);
109 }
110 }
111
112
113
114
115
116
117
118 public synchronized ProcessingResultCode process() {
119 RegionServerOperation op = null;
120
121
122
123 if (toDoQueue.isEmpty()) {
124 op = delayedToDoQueue.poll();
125 }
126 if (op == null) {
127 try {
128 op = toDoQueue.poll(threadWakeFrequency, TimeUnit.MILLISECONDS);
129 } catch (InterruptedException e) {
130 LOG.debug("Interrupted", e);
131 }
132 }
133
134
135
136 if (op == null || closed.get()) {
137 return ProcessingResultCode.NOOP;
138 }
139
140 try {
141 if (LOG.isDebugEnabled()) {
142 LOG.debug("Processing todo: " + op.toString());
143 }
144 if (!process(op)) {
145
146 putOnDelayQueue(op);
147 } else if (op.process()) {
148 processed(op);
149 } else {
150
151
152
153
154
155 if (toDoQueue.size() == 0) {
156
157
158 this.sleeper.sleep();
159 }
160 try {
161 if (LOG.isDebugEnabled()) {
162 LOG.debug("Put " + op.toString() + " back on queue");
163 }
164 toDoQueue.put(op);
165 } catch (InterruptedException e) {
166 throw new RuntimeException(
167 "Putting into toDoQueue was interrupted.", e);
168 }
169 }
170 } catch (Exception ex) {
171
172 if (ex instanceof RemoteException) {
173 try {
174 ex = RemoteExceptionHandler.decodeRemoteException(
175 (RemoteException)ex);
176 } catch (IOException e) {
177 ex = e;
178 LOG.warn("main processing loop: " + op.toString(), e);
179 }
180 }
181 LOG.warn("Failed processing: " + op.toString() +
182 "; putting onto delayed todo queue", ex);
183 putOnDelayQueue(op);
184 return ProcessingResultCode.REQUEUED_BUT_PROBLEM;
185 }
186 return ProcessingResultCode.REQUEUED;
187 }
188
189 void putOnDelayQueue(final RegionServerOperation op) {
190 op.resetExpiration();
191 this.delayedToDoQueue.put(op);
192 }
193
194
195
196
197 public synchronized void shutdown() {
198 this.toDoQueue.clear();
199 this.delayedToDoQueue.clear();
200 }
201
202
203
204
205 public void registerRegionServerOperationListener(final RegionServerOperationListener l) {
206 this.listeners.add(l);
207 }
208
209
210
211
212
213 public boolean unregisterRegionServerOperationListener(final RegionServerOperationListener l) {
214 return this.listeners.remove(l);
215 }
216
217
218
219
220
221 private void processed(final RegionServerOperation op) {
222 if (this.listeners.isEmpty()) return;
223 for (RegionServerOperationListener listener: this.listeners) {
224 listener.processed(op);
225 }
226 }
227
228
229
230
231
232
233
234
235
236
237 boolean process(final HServerInfo serverInfo,
238 final HMsg incomingMsg) {
239 if (this.listeners.isEmpty()) return true;
240 for (RegionServerOperationListener listener: this.listeners) {
241 if (!listener.process(serverInfo, incomingMsg)) return false;
242 }
243 return true;
244 }
245
246
247
248
249
250 private boolean process(final RegionServerOperation op) throws IOException {
251 if (this.listeners.isEmpty()) return true;
252 for (RegionServerOperationListener listener: this.listeners) {
253 if (!listener.process(op)) return false;
254 }
255 return true;
256 }
257 }