1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.hadoop.hbase.zookeeper;
20
21 import org.apache.commons.logging.Log;
22 import org.apache.commons.logging.LogFactory;
23 import org.apache.hadoop.hbase.classification.InterfaceAudience;
24 import org.apache.hadoop.hbase.TableName;
25 import org.apache.hadoop.hbase.protobuf.ProtobufUtil;
26 import org.apache.hadoop.hbase.protobuf.generated.ZooKeeperProtos;
27 import org.apache.zookeeper.KeeperException;
28
29 import java.util.HashMap;
30 import java.util.HashSet;
31 import java.util.List;
32 import java.util.Map;
33 import java.util.Set;
34
35
36
37
38
39
40
41
42
43
44
45 @InterfaceAudience.Private
46 public class ZKTable {
47
48
49
50
51
52 private static final Log LOG = LogFactory.getLog(ZKTable.class);
53 private final ZooKeeperWatcher watcher;
54
55
56
57
58
59
60 private final Map<TableName, ZooKeeperProtos.Table.State> cache =
61 new HashMap<TableName, ZooKeeperProtos.Table.State>();
62
63
64
65
66 public ZKTable(final ZooKeeperWatcher zkw) throws KeeperException {
67 super();
68 this.watcher = zkw;
69 populateTableStates();
70 }
71
72
73
74
75
76 private void populateTableStates()
77 throws KeeperException {
78 synchronized (this.cache) {
79 List<String> children = ZKUtil.listChildrenNoWatch(this.watcher, this.watcher.tableZNode);
80 if (children == null) return;
81 for (String child: children) {
82 TableName tableName = TableName.valueOf(child);
83 ZooKeeperProtos.Table.State state = ZKTableReadOnly.getTableState(this.watcher, tableName);
84 if (state != null) this.cache.put(tableName, state);
85 }
86 }
87 }
88
89
90
91
92
93
94
95 public void setDisabledTable(TableName tableName)
96 throws KeeperException {
97 synchronized (this.cache) {
98 if (!isDisablingOrDisabledTable(tableName)) {
99 LOG.warn("Moving table " + tableName + " state to disabled but was " +
100 "not first in disabling state: " + this.cache.get(tableName));
101 }
102 setTableState(tableName, ZooKeeperProtos.Table.State.DISABLED);
103 }
104 }
105
106
107
108
109
110
111
112 public void setDisablingTable(final TableName tableName)
113 throws KeeperException {
114 synchronized (this.cache) {
115 if (!isEnabledOrDisablingTable(tableName)) {
116 LOG.warn("Moving table " + tableName + " state to disabling but was " +
117 "not first in enabled state: " + this.cache.get(tableName));
118 }
119 setTableState(tableName, ZooKeeperProtos.Table.State.DISABLING);
120 }
121 }
122
123
124
125
126
127
128
129 public void setEnablingTable(final TableName tableName)
130 throws KeeperException {
131 synchronized (this.cache) {
132 if (!isDisabledOrEnablingTable(tableName)) {
133 LOG.warn("Moving table " + tableName + " state to enabling but was " +
134 "not first in disabled state: " + this.cache.get(tableName));
135 }
136 setTableState(tableName, ZooKeeperProtos.Table.State.ENABLING);
137 }
138 }
139
140
141
142
143
144
145
146
147 public boolean checkAndSetEnablingTable(final TableName tableName)
148 throws KeeperException {
149 synchronized (this.cache) {
150 if (isEnablingOrEnabledTable(tableName)) {
151
152
153
154
155
156
157 ZooKeeperProtos.Table.State currentState =
158 ZKTableReadOnly.getTableState(this.watcher, tableName);
159
160 if (currentState == null ||
161 currentState == ZooKeeperProtos.Table.State.ENABLING ||
162 currentState == ZooKeeperProtos.Table.State.ENABLED) {
163 return false;
164 }
165 }
166 setTableState(tableName, ZooKeeperProtos.Table.State.ENABLING);
167 return true;
168 }
169 }
170
171
172
173
174
175
176
177
178 public boolean checkDisabledAndSetEnablingTable(final TableName tableName)
179 throws KeeperException {
180 synchronized (this.cache) {
181 if (!isDisabledTable(tableName)) {
182 return false;
183 }
184 setTableState(tableName, ZooKeeperProtos.Table.State.ENABLING);
185 return true;
186 }
187 }
188
189
190
191
192
193
194
195
196 public boolean checkEnabledAndSetDisablingTable(final TableName tableName)
197 throws KeeperException {
198 synchronized (this.cache) {
199 if (this.cache.get(tableName) != null && !isEnabledTable(tableName)) {
200 return false;
201 }
202 setTableState(tableName, ZooKeeperProtos.Table.State.DISABLING);
203 return true;
204 }
205 }
206
207 private void setTableState(final TableName tableName, final ZooKeeperProtos.Table.State state)
208 throws KeeperException {
209 String znode = ZKUtil.joinZNode(this.watcher.tableZNode, tableName.getNameAsString());
210 if (ZKUtil.checkExists(this.watcher, znode) == -1) {
211 ZKUtil.createAndFailSilent(this.watcher, znode);
212 }
213 synchronized (this.cache) {
214 ZooKeeperProtos.Table.Builder builder = ZooKeeperProtos.Table.newBuilder();
215 builder.setState(state);
216 byte [] data = ProtobufUtil.prependPBMagic(builder.build().toByteArray());
217 ZKUtil.setData(this.watcher, znode, data);
218 this.cache.put(tableName, state);
219 }
220 }
221
222 public boolean isDisabledTable(final TableName tableName) {
223 return isTableState(tableName, ZooKeeperProtos.Table.State.DISABLED);
224 }
225
226 public boolean isDisablingTable(final TableName tableName) {
227 return isTableState(tableName, ZooKeeperProtos.Table.State.DISABLING);
228 }
229
230 public boolean isEnablingTable(final TableName tableName) {
231 return isTableState(tableName, ZooKeeperProtos.Table.State.ENABLING);
232 }
233
234 public boolean isEnabledTable(TableName tableName) {
235 return isTableState(tableName, ZooKeeperProtos.Table.State.ENABLED);
236 }
237
238 public boolean isDisablingOrDisabledTable(final TableName tableName) {
239 synchronized (this.cache) {
240 return isDisablingTable(tableName) || isDisabledTable(tableName);
241 }
242 }
243
244 public boolean isEnablingOrEnabledTable(final TableName tableName) {
245 synchronized (this.cache) {
246 return isEnablingTable(tableName) || isEnabledTable(tableName);
247 }
248 }
249
250 public boolean isEnabledOrDisablingTable(final TableName tableName) {
251 synchronized (this.cache) {
252 return isEnabledTable(tableName) || isDisablingTable(tableName);
253 }
254 }
255
256 public boolean isDisabledOrEnablingTable(final TableName tableName) {
257 synchronized (this.cache) {
258 return isDisabledTable(tableName) || isEnablingTable(tableName);
259 }
260 }
261
262 private boolean isTableState(final TableName tableName, final ZooKeeperProtos.Table.State state) {
263 synchronized (this.cache) {
264 ZooKeeperProtos.Table.State currentState = this.cache.get(tableName);
265 return ZKTableReadOnly.isTableState(currentState, state);
266 }
267 }
268
269
270
271
272
273
274
275 public void setDeletedTable(final TableName tableName)
276 throws KeeperException {
277 synchronized (this.cache) {
278 if (this.cache.remove(tableName) == null) {
279 LOG.warn("Moving table " + tableName + " state to deleted but was " +
280 "already deleted");
281 }
282 ZKUtil.deleteNodeFailSilent(this.watcher,
283 ZKUtil.joinZNode(this.watcher.tableZNode, tableName.getNameAsString()));
284 }
285 }
286
287
288
289
290
291
292
293
294 public void setEnabledTable(final TableName tableName) throws KeeperException {
295 setTableState(tableName, ZooKeeperProtos.Table.State.ENABLED);
296 }
297
298
299
300
301
302
303
304 public boolean isTablePresent(final TableName tableName) {
305 synchronized (this.cache) {
306 ZooKeeperProtos.Table.State state = this.cache.get(tableName);
307 return !(state == null);
308 }
309 }
310
311
312
313
314
315 public Set<TableName> getDisabledTables() {
316 Set<TableName> disabledTables = new HashSet<TableName>();
317 synchronized (this.cache) {
318 Set<TableName> tables = this.cache.keySet();
319 for (TableName table: tables) {
320 if (isDisabledTable(table)) disabledTables.add(table);
321 }
322 }
323 return disabledTables;
324 }
325
326
327
328
329
330
331 public static Set<TableName> getDisabledTables(ZooKeeperWatcher zkw)
332 throws KeeperException {
333 return getAllTables(zkw, ZooKeeperProtos.Table.State.DISABLED);
334 }
335
336
337
338
339
340
341 public static Set<TableName> getDisablingTables(ZooKeeperWatcher zkw)
342 throws KeeperException {
343 return getAllTables(zkw, ZooKeeperProtos.Table.State.DISABLING);
344 }
345
346
347
348
349
350
351 public static Set<TableName> getEnablingTables(ZooKeeperWatcher zkw)
352 throws KeeperException {
353 return getAllTables(zkw, ZooKeeperProtos.Table.State.ENABLING);
354 }
355
356
357
358
359
360
361 public static Set<TableName> getDisabledOrDisablingTables(ZooKeeperWatcher zkw)
362 throws KeeperException {
363 return getAllTables(zkw, ZooKeeperProtos.Table.State.DISABLED,
364 ZooKeeperProtos.Table.State.DISABLING);
365 }
366
367
368
369
370
371
372
373
374
375
376 public void removeEnablingTable(final TableName tableName, boolean deleteZNode)
377 throws KeeperException {
378 synchronized (this.cache) {
379 if (isEnablingTable(tableName)) {
380 this.cache.remove(tableName);
381 if (deleteZNode) {
382 ZKUtil.deleteNodeFailSilent(this.watcher,
383 ZKUtil.joinZNode(this.watcher.tableZNode, tableName.getNameAsString()));
384 }
385 }
386 }
387 }
388
389
390
391
392
393
394
395 static Set<TableName> getAllTables(final ZooKeeperWatcher zkw,
396 final ZooKeeperProtos.Table.State... states) throws KeeperException {
397 Set<TableName> allTables = new HashSet<TableName>();
398 List<String> children =
399 ZKUtil.listChildrenNoWatch(zkw, zkw.tableZNode);
400 if(children == null) return allTables;
401 for (String child: children) {
402 TableName tableName = TableName.valueOf(child);
403 ZooKeeperProtos.Table.State state = ZKTableReadOnly.getTableState(zkw, tableName);
404 for (ZooKeeperProtos.Table.State expectedState: states) {
405 if (state == expectedState) {
406 allTables.add(tableName);
407 break;
408 }
409 }
410 }
411 return allTables;
412 }
413 }