1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.hadoop.hbase.master;
20
21 import com.google.common.collect.Sets;
22 import org.apache.commons.logging.Log;
23 import org.apache.commons.logging.LogFactory;
24 import org.apache.hadoop.classification.InterfaceAudience;
25 import org.apache.hadoop.fs.FileStatus;
26 import org.apache.hadoop.fs.FileSystem;
27 import org.apache.hadoop.fs.Path;
28 import org.apache.hadoop.hbase.Chore;
29 import org.apache.hadoop.hbase.HConstants;
30 import org.apache.hadoop.hbase.NamespaceDescriptor;
31 import org.apache.hadoop.hbase.util.FSUtils;
32 import org.apache.hadoop.hbase.zookeeper.ZKUtil;
33 import org.apache.hadoop.hbase.zookeeper.ZooKeeperWatcher;
34 import org.apache.zookeeper.KeeperException;
35
36 import java.io.IOException;
37 import java.util.Set;
38 import java.util.concurrent.atomic.AtomicBoolean;
39
40
41
42
43
44 @InterfaceAudience.Private
45 public class NamespaceJanitor extends Chore {
46 private static final Log LOG = LogFactory.getLog(NamespaceJanitor.class.getName());
47 private final MasterServices services;
48 private AtomicBoolean enabled = new AtomicBoolean(true);
49 private AtomicBoolean alreadyRunning = new AtomicBoolean(false);
50
51 public NamespaceJanitor(final MasterServices services) {
52 super("NamespaceJanitor-" + services.getServerName().toShortString(),
53 services.getConfiguration().getInt("hbase.namespacejanitor.interval", 30000),
54 services);
55 this.services = services;
56 }
57
58 @Override
59 protected boolean initialChore() {
60 try {
61 if (this.enabled.get()) removeOrphans();
62 } catch (IOException e) {
63 LOG.warn("Failed NamespaceJanitor chore", e);
64 return false;
65 } catch (KeeperException e) {
66 LOG.warn("Failed NamespaceJanitor chore", e);
67 return false;
68 }
69 return true;
70 }
71
72
73
74
75 public boolean setEnabled(final boolean enabled) {
76 return this.enabled.getAndSet(enabled);
77 }
78
79 boolean getEnabled() {
80 return this.enabled.get();
81 }
82
83 @Override
84 protected void chore() {
85 try {
86 if (this.enabled.get()) {
87 removeOrphans();
88 } else {
89 LOG.warn("NamepsaceJanitor disabled! Not running scan.");
90 }
91 } catch (IOException e) {
92 LOG.warn("Failed NamespaceJanitor chore", e);
93 } catch (KeeperException e) {
94 LOG.warn("Failed NamespaceJanitor chore", e);
95 }
96 }
97
98 private void removeOrphans() throws IOException, KeeperException {
99
100
101 FileSystem fs = services.getMasterFileSystem().getFileSystem();
102 Set<String> descs = Sets.newHashSet();
103 for(NamespaceDescriptor ns : services.listNamespaceDescriptors()) {
104 descs.add(ns.getName());
105 }
106
107
108 for (FileStatus nsStatus : FSUtils.listStatus(fs,
109 new Path(FSUtils.getRootDir(services.getConfiguration()), HConstants.BASE_NAMESPACE_DIR))) {
110 if (!descs.contains(nsStatus.getPath().getName()) &&
111 !NamespaceDescriptor.RESERVED_NAMESPACES.contains(nsStatus.getPath().getName())) {
112 boolean isEmpty = true;
113 for(FileStatus status : fs.listStatus(nsStatus.getPath())) {
114 if (!HConstants.HBASE_NON_TABLE_DIRS.contains(status.getPath().getName())) {
115 isEmpty = false;
116 break;
117 }
118 }
119 if(isEmpty) {
120 try {
121 if (!fs.delete(nsStatus.getPath(), true)) {
122 LOG.error("Failed to remove namespace directory: " + nsStatus.getPath());
123 }
124 } catch (IOException ex) {
125 LOG.error("Failed to remove namespace directory: " + nsStatus.getPath(),
126 ex);
127 }
128 LOG.debug("Removed namespace directory: "+nsStatus.getPath());
129 } else {
130 LOG.debug("Skipping non-empty namespace directory: " + nsStatus.getPath());
131 }
132 }
133 }
134
135 String baseZnode = ZooKeeperWatcher.namespaceZNode;
136 for(String child : ZKUtil.listChildrenNoWatch(services.getZooKeeper(), baseZnode)) {
137 if (!descs.contains(child) &&
138 !NamespaceDescriptor.RESERVED_NAMESPACES.contains(child)) {
139 String znode = ZKUtil.joinZNode(baseZnode, child);
140 try {
141 ZKUtil.deleteNode(services.getZooKeeper(), znode);
142 LOG.debug("Removed namespace znode: " + znode);
143 } catch (KeeperException ex) {
144 LOG.debug("Failed to remove namespace znode: " + znode, ex);
145 }
146 }
147 }
148
149 }
150 }