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.Map;
24 import java.util.concurrent.locks.Lock;
25 import java.util.concurrent.locks.ReentrantLock;
26
27 import org.apache.commons.logging.Log;
28 import org.apache.commons.logging.LogFactory;
29 import org.apache.hadoop.conf.Configuration;
30 import org.apache.hadoop.fs.FileStatus;
31 import org.apache.hadoop.fs.FileSystem;
32 import org.apache.hadoop.fs.Path;
33 import org.apache.hadoop.hbase.HColumnDescriptor;
34 import org.apache.hadoop.hbase.HConstants;
35 import org.apache.hadoop.hbase.HRegionInfo;
36 import org.apache.hadoop.hbase.HServerInfo;
37 import org.apache.hadoop.hbase.RemoteExceptionHandler;
38 import org.apache.hadoop.hbase.Server;
39 import org.apache.hadoop.hbase.master.metrics.MasterMetrics;
40 import org.apache.hadoop.hbase.regionserver.HRegion;
41 import org.apache.hadoop.hbase.regionserver.Store;
42 import org.apache.hadoop.hbase.regionserver.wal.HLog;
43 import org.apache.hadoop.hbase.regionserver.wal.HLogSplitter;
44 import org.apache.hadoop.hbase.regionserver.wal.OrphanHLogAfterSplitException;
45 import org.apache.hadoop.hbase.util.Bytes;
46 import org.apache.hadoop.hbase.util.FSUtils;
47
48
49
50
51
52
53 public class MasterFileSystem {
54 private static final Log LOG = LogFactory.getLog(MasterFileSystem.class.getName());
55
56 Configuration conf;
57
58 Server master;
59
60 MasterMetrics metrics;
61
62 private final FileSystem fs;
63
64 private volatile boolean fsOk = true;
65
66 private final Path oldLogDir;
67
68 private final Path rootdir;
69
70 final Lock splitLogLock = new ReentrantLock();
71
72 public MasterFileSystem(Server master, MasterMetrics metrics)
73 throws IOException {
74 this.conf = master.getConfiguration();
75 this.master = master;
76 this.metrics = metrics;
77
78
79
80
81 this.rootdir = FSUtils.getRootDir(conf);
82
83
84 this.fs = this.rootdir.getFileSystem(conf);
85 String fsUri = this.fs.getUri().toString();
86 conf.set("fs.default.name", fsUri);
87 conf.set("fs.defaultFS", fsUri);
88
89
90 this.oldLogDir = new Path(this.rootdir, HConstants.HREGION_OLDLOGDIR_NAME);
91 createInitialFileSystemLayout();
92 }
93
94
95
96
97
98
99
100
101
102
103
104 private void createInitialFileSystemLayout() throws IOException {
105
106 checkRootDir(this.rootdir, conf, this.fs);
107
108
109 if(!this.fs.exists(this.oldLogDir)) {
110 this.fs.mkdirs(this.oldLogDir);
111 }
112 }
113
114 public FileSystem getFileSystem() {
115 return this.fs;
116 }
117
118
119
120
121
122 public Path getOldLogDir() {
123 return this.oldLogDir;
124 }
125
126
127
128
129
130
131 public boolean checkFileSystem() {
132 if (this.fsOk) {
133 try {
134 FSUtils.checkFileSystemAvailable(this.fs);
135 FSUtils.checkDfsSafeMode(this.conf);
136 } catch (IOException e) {
137 master.abort("Shutting down HBase cluster: file system not available", e);
138 this.fsOk = false;
139 }
140 }
141 return this.fsOk;
142 }
143
144
145
146
147
148 public Path getRootDir() {
149 return this.rootdir;
150 }
151
152
153
154
155
156
157
158 void splitLogAfterStartup(final Map<String, HServerInfo> onlineServers) {
159 Path logsDirPath = new Path(this.rootdir, HConstants.HREGION_LOGDIR_NAME);
160 try {
161 if (!this.fs.exists(logsDirPath)) {
162 return;
163 }
164 } catch (IOException e) {
165 throw new RuntimeException("Failed exists test on " + logsDirPath, e);
166 }
167 FileStatus[] logFolders;
168 try {
169 logFolders = this.fs.listStatus(logsDirPath);
170 } catch (IOException e) {
171 throw new RuntimeException("Failed listing " + logsDirPath.toString(), e);
172 }
173 if (logFolders == null || logFolders.length == 0) {
174 LOG.debug("No log files to split, proceeding...");
175 return;
176 }
177 for (FileStatus status : logFolders) {
178 String serverName = status.getPath().getName();
179 if (onlineServers.get(serverName) == null) {
180 LOG.info("Log folder " + status.getPath() + " doesn't belong " +
181 "to a known region server, splitting");
182 splitLog(serverName);
183 } else {
184 LOG.info("Log folder " + status.getPath() +
185 " belongs to an existing region server");
186 }
187 }
188 }
189
190 public void splitLog(final String serverName) {
191 this.splitLogLock.lock();
192 long splitTime = 0, splitLogSize = 0;
193 Path logDir = new Path(this.rootdir, HLog.getHLogDirectoryName(serverName));
194 try {
195 HLogSplitter splitter = HLogSplitter.createLogSplitter(
196 conf, rootdir, logDir, oldLogDir, this.fs);
197 try {
198
199 FSUtils.waitOnSafeMode(conf,
200 conf.getInt(HConstants.THREAD_WAKE_FREQUENCY, 1000));
201 splitter.splitLog();
202 } catch (OrphanHLogAfterSplitException e) {
203 LOG.warn("Retrying splitting because of:", e);
204
205 splitter = HLogSplitter.createLogSplitter(conf, rootdir, logDir,
206 oldLogDir, this.fs);
207 splitter.splitLog();
208 }
209 splitTime = splitter.getTime();
210 splitLogSize = splitter.getSize();
211 } catch (IOException e) {
212 checkFileSystem();
213 LOG.error("Failed splitting " + logDir.toString(), e);
214 } finally {
215 this.splitLogLock.unlock();
216 }
217 if (this.metrics != null) {
218 this.metrics.addSplit(splitTime, splitLogSize);
219 }
220 }
221
222
223
224
225
226
227
228
229
230
231 private static Path checkRootDir(final Path rd, final Configuration c,
232 final FileSystem fs)
233 throws IOException {
234
235 FSUtils.waitOnSafeMode(c, c.getInt(HConstants.THREAD_WAKE_FREQUENCY,
236 10 * 1000));
237
238 if (!fs.exists(rd)) {
239 fs.mkdirs(rd);
240
241
242
243
244
245
246
247 FSUtils.setVersion(fs, rd, c.getInt(HConstants.THREAD_WAKE_FREQUENCY,
248 10 * 1000));
249 } else {
250
251 FSUtils.checkVersion(fs, rd, true, c.getInt(HConstants.THREAD_WAKE_FREQUENCY,
252 10 * 1000));
253 }
254
255 if (!FSUtils.rootRegionExists(fs, rd)) {
256 bootstrap(rd, c);
257 }
258 return rd;
259 }
260
261 private static void bootstrap(final Path rd, final Configuration c)
262 throws IOException {
263 LOG.info("BOOTSTRAP: creating ROOT and first META regions");
264 try {
265
266
267
268
269 HRegionInfo rootHRI = new HRegionInfo(HRegionInfo.ROOT_REGIONINFO);
270 setInfoFamilyCaching(rootHRI, false);
271 HRegionInfo metaHRI = new HRegionInfo(HRegionInfo.FIRST_META_REGIONINFO);
272 setInfoFamilyCaching(metaHRI, false);
273 HRegion root = HRegion.createHRegion(rootHRI, rd, c);
274 HRegion meta = HRegion.createHRegion(metaHRI, rd, c);
275 setInfoFamilyCaching(rootHRI, true);
276 setInfoFamilyCaching(metaHRI, true);
277
278 HRegion.addRegionToMETA(root, meta);
279 root.close();
280 root.getLog().closeAndDelete();
281 meta.close();
282 meta.getLog().closeAndDelete();
283 } catch (IOException e) {
284 e = RemoteExceptionHandler.checkIOException(e);
285 LOG.error("bootstrap", e);
286 throw e;
287 }
288 }
289
290
291
292
293
294 private static void setInfoFamilyCaching(final HRegionInfo hri, final boolean b) {
295 for (HColumnDescriptor hcd: hri.getTableDesc().families.values()) {
296 if (Bytes.equals(hcd.getName(), HConstants.CATALOG_FAMILY)) {
297 hcd.setBlockCacheEnabled(b);
298 hcd.setInMemory(b);
299 }
300 }
301 }
302
303 public void deleteRegion(HRegionInfo region) throws IOException {
304 fs.delete(HRegion.getRegionDir(rootdir, region), true);
305 }
306
307 public void deleteTable(byte[] tableName) throws IOException {
308 fs.delete(new Path(rootdir, Bytes.toString(tableName)), true);
309 }
310
311 public void updateRegionInfo(HRegionInfo region) {
312
313
314
315 }
316
317 public void deleteFamily(HRegionInfo region, byte[] familyName)
318 throws IOException {
319 fs.delete(Store.getStoreHomedir(
320 new Path(rootdir, region.getTableDesc().getNameAsString()),
321 region.getEncodedName(), familyName), true);
322 }
323 }