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 java.io.IOException;
22 import java.util.NavigableSet;
23
24 import org.apache.commons.logging.Log;
25 import org.apache.commons.logging.LogFactory;
26 import org.apache.hadoop.classification.InterfaceAudience;
27 import org.apache.hadoop.conf.Configuration;
28 import org.apache.hadoop.fs.FileStatus;
29 import org.apache.hadoop.fs.FileSystem;
30 import org.apache.hadoop.hbase.HConstants;
31 import org.apache.hadoop.hbase.HRegionInfo;
32 import org.apache.hadoop.hbase.HTableDescriptor;
33 import org.apache.hadoop.hbase.NamespaceDescriptor;
34 import org.apache.hadoop.hbase.TableName;
35 import org.apache.hadoop.hbase.ZKNamespaceManager;
36 import org.apache.hadoop.hbase.catalog.MetaReader;
37 import org.apache.hadoop.hbase.client.Delete;
38 import org.apache.hadoop.hbase.client.Get;
39 import org.apache.hadoop.hbase.client.HTable;
40 import org.apache.hadoop.hbase.client.Put;
41 import org.apache.hadoop.hbase.client.Result;
42 import org.apache.hadoop.hbase.client.ResultScanner;
43 import org.apache.hadoop.hbase.constraint.ConstraintException;
44 import org.apache.hadoop.hbase.master.handler.CreateTableHandler;
45 import org.apache.hadoop.hbase.protobuf.ProtobufUtil;
46 import org.apache.hadoop.hbase.protobuf.generated.HBaseProtos;
47 import org.apache.hadoop.hbase.util.Bytes;
48
49 import com.google.common.collect.Sets;
50 import org.apache.hadoop.hbase.util.FSUtils;
51
52
53
54
55
56
57
58 @InterfaceAudience.Private
59 public class TableNamespaceManager {
60 private static final Log LOG = LogFactory.getLog(TableNamespaceManager.class);
61
62 private Configuration conf;
63 private MasterServices masterServices;
64 private HTable table;
65 private ZKNamespaceManager zkNamespaceManager;
66
67 public TableNamespaceManager(MasterServices masterServices) throws IOException {
68 this.masterServices = masterServices;
69 this.conf = masterServices.getConfiguration();
70 }
71
72 public void start() throws IOException {
73 TableName tableName = TableName.NAMESPACE_TABLE_NAME;
74 try {
75 if (!MetaReader.tableExists(masterServices.getCatalogTracker(),
76 tableName)) {
77 LOG.info("Namespace table not found. Creating...");
78 createNamespaceTable(masterServices);
79 }
80 } catch (InterruptedException e) {
81 throw new IOException("Wait for namespace table assignment interrupted", e);
82 }
83 table = new HTable(conf, tableName);
84 zkNamespaceManager = new ZKNamespaceManager(masterServices.getZooKeeper());
85 zkNamespaceManager.start();
86
87 if (get(NamespaceDescriptor.DEFAULT_NAMESPACE.getName()) == null) {
88 create(NamespaceDescriptor.DEFAULT_NAMESPACE);
89 }
90 if (get(NamespaceDescriptor.SYSTEM_NAMESPACE.getName()) == null) {
91 create(NamespaceDescriptor.SYSTEM_NAMESPACE);
92 }
93
94 ResultScanner scanner = table.getScanner(HTableDescriptor.NAMESPACE_FAMILY_INFO_BYTES);
95 try {
96 for(Result result : scanner) {
97 NamespaceDescriptor ns =
98 ProtobufUtil.toNamespaceDescriptor(
99 HBaseProtos.NamespaceDescriptor.parseFrom(
100 result.getColumnLatest(HTableDescriptor.NAMESPACE_FAMILY_INFO_BYTES,
101 HTableDescriptor.NAMESPACE_COL_DESC_BYTES).getValue()));
102 zkNamespaceManager.update(ns);
103 }
104 } finally {
105 scanner.close();
106 }
107 }
108
109
110 public synchronized NamespaceDescriptor get(String name) throws IOException {
111 Result res = table.get(new Get(Bytes.toBytes(name)));
112 if (res.isEmpty()) {
113 return null;
114 }
115 return
116 ProtobufUtil.toNamespaceDescriptor(
117 HBaseProtos.NamespaceDescriptor.parseFrom(
118 res.getColumnLatest(HTableDescriptor.NAMESPACE_FAMILY_INFO_BYTES,
119 HTableDescriptor.NAMESPACE_COL_DESC_BYTES).getValue()));
120 }
121
122 public synchronized void create(NamespaceDescriptor ns) throws IOException {
123 if (get(ns.getName()) != null) {
124 throw new ConstraintException("Namespace "+ns.getName()+" already exists");
125 }
126 FileSystem fs = masterServices.getMasterFileSystem().getFileSystem();
127 fs.mkdirs(FSUtils.getNamespaceDir(
128 masterServices.getMasterFileSystem().getRootDir(), ns.getName()));
129 upsert(ns);
130 }
131
132 public synchronized void update(NamespaceDescriptor ns) throws IOException {
133 if (get(ns.getName()) == null) {
134 throw new ConstraintException("Namespace "+ns.getName()+" does not exist");
135 }
136 upsert(ns);
137 }
138
139 private void upsert(NamespaceDescriptor ns) throws IOException {
140 Put p = new Put(Bytes.toBytes(ns.getName()));
141 p.add(HTableDescriptor.NAMESPACE_FAMILY_INFO_BYTES,
142 HTableDescriptor.NAMESPACE_COL_DESC_BYTES,
143 ProtobufUtil.toProtoNamespaceDescriptor(ns).toByteArray());
144 table.put(p);
145 try {
146 zkNamespaceManager.update(ns);
147 } catch(IOException ex) {
148 String msg = "Failed to update namespace information in ZK. Aborting.";
149 LOG.fatal(msg, ex);
150 masterServices.abort(msg, ex);
151 }
152 }
153
154 public synchronized void remove(String name) throws IOException {
155 if (NamespaceDescriptor.RESERVED_NAMESPACES.contains(name)) {
156 throw new ConstraintException("Reserved namespace "+name+" cannot be removed.");
157 }
158 int tableCount = masterServices.listTableDescriptorsByNamespace(name).size();
159 if (tableCount > 0) {
160 throw new ConstraintException("Only empty namespaces can be removed. " +
161 "Namespace "+name+" has "+tableCount+" tables");
162 }
163 Delete d = new Delete(Bytes.toBytes(name));
164 table.delete(d);
165
166
167 zkNamespaceManager.remove(name);
168 FileSystem fs = masterServices.getMasterFileSystem().getFileSystem();
169 for(FileStatus status :
170 fs.listStatus(FSUtils.getNamespaceDir(
171 masterServices.getMasterFileSystem().getRootDir(), name))) {
172 if (!HConstants.HBASE_NON_TABLE_DIRS.contains(status.getPath().getName())) {
173 throw new IOException("Namespace directory contains table dir: "+status.getPath());
174 }
175 }
176 if (!fs.delete(FSUtils.getNamespaceDir(
177 masterServices.getMasterFileSystem().getRootDir(), name), true)) {
178 throw new IOException("Failed to remove namespace: "+name);
179 }
180 }
181
182 public synchronized NavigableSet<NamespaceDescriptor> list() throws IOException {
183 NavigableSet<NamespaceDescriptor> ret =
184 Sets.newTreeSet(NamespaceDescriptor.NAMESPACE_DESCRIPTOR_COMPARATOR);
185 ResultScanner scanner = table.getScanner(HTableDescriptor.NAMESPACE_FAMILY_INFO_BYTES);
186 try {
187 for(Result r : scanner) {
188 ret.add(ProtobufUtil.toNamespaceDescriptor(
189 HBaseProtos.NamespaceDescriptor.parseFrom(
190 r.getColumnLatest(HTableDescriptor.NAMESPACE_FAMILY_INFO_BYTES,
191 HTableDescriptor.NAMESPACE_COL_DESC_BYTES).getValue())));
192 }
193 } finally {
194 scanner.close();
195 }
196 return ret;
197 }
198
199 private void createNamespaceTable(MasterServices masterServices) throws IOException, InterruptedException {
200 HRegionInfo newRegions[] = new HRegionInfo[]{
201 new HRegionInfo(HTableDescriptor.NAMESPACE_TABLEDESC.getTableName(), null, null)};
202
203
204
205 masterServices.getExecutorService()
206 .submit(new CreateTableHandler(masterServices,
207 masterServices.getMasterFileSystem(),
208 HTableDescriptor.NAMESPACE_TABLEDESC,
209 masterServices.getConfiguration(),
210 newRegions,
211 masterServices).prepare());
212
213 int tries = conf.getInt("hbase.master.namespace.init.timeout", 600);
214 while(masterServices.getAssignmentManager()
215 .getRegionStates().getRegionServerOfRegion(newRegions[0]) == null &&
216 tries > 0) {
217 Thread.sleep(100);
218 tries--;
219 }
220 if (tries <= 0) {
221 throw new IOException("Failed to create namespace table.");
222 }
223 }
224 }