1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.hadoop.hbase.io;
20
21 import java.io.IOException;
22 import java.util.regex.Matcher;
23 import java.util.regex.Pattern;
24
25 import org.apache.commons.logging.Log;
26 import org.apache.commons.logging.LogFactory;
27 import org.apache.hadoop.hbase.classification.InterfaceAudience;
28 import org.apache.hadoop.conf.Configuration;
29 import org.apache.hadoop.fs.FileSystem;
30 import org.apache.hadoop.fs.Path;
31 import org.apache.hadoop.hbase.TableName;
32 import org.apache.hadoop.hbase.HConstants;
33 import org.apache.hadoop.hbase.HRegionInfo;
34 import org.apache.hadoop.hbase.mob.MobConstants;
35 import org.apache.hadoop.hbase.regionserver.HRegion;
36 import org.apache.hadoop.hbase.regionserver.StoreFileInfo;
37 import org.apache.hadoop.hbase.util.FSUtils;
38 import org.apache.hadoop.hbase.util.HFileArchiveUtil;
39 import org.apache.hadoop.hbase.util.Pair;
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56 @InterfaceAudience.Private
57 @edu.umd.cs.findbugs.annotations.SuppressWarnings(value="EQ_DOESNT_OVERRIDE_EQUALS",
58 justification="To be fixed but warning suppressed for now")
59 public class HFileLink extends FileLink {
60 private static final Log LOG = LogFactory.getLog(HFileLink.class);
61
62
63
64
65
66
67
68
69
70
71
72 public static final String LINK_NAME_REGEX =
73 String.format("(?:(?:%s=)?)%s=%s-%s",
74 TableName.VALID_NAMESPACE_REGEX, TableName.VALID_TABLE_QUALIFIER_REGEX,
75 HRegionInfo.ENCODED_REGION_NAME_REGEX, StoreFileInfo.HFILE_NAME_REGEX);
76
77
78
79 static final Pattern LINK_NAME_PATTERN =
80 Pattern.compile(String.format("^(?:(%s)(?:\\=))?(%s)=(%s)-(%s)$",
81 TableName.VALID_NAMESPACE_REGEX, TableName.VALID_TABLE_QUALIFIER_REGEX,
82 HRegionInfo.ENCODED_REGION_NAME_REGEX, StoreFileInfo.HFILE_NAME_REGEX));
83
84
85
86
87
88 private static final Pattern REF_OR_HFILE_LINK_PATTERN =
89 Pattern.compile(String.format("^(?:(%s)(?:=))?(%s)=(%s)-(.+)$",
90 TableName.VALID_NAMESPACE_REGEX, TableName.VALID_TABLE_QUALIFIER_REGEX,
91 HRegionInfo.ENCODED_REGION_NAME_REGEX));
92
93 private final Path archivePath;
94 private final Path originPath;
95 private final Path mobPath;
96 private final Path tempPath;
97
98
99
100
101 public HFileLink(final Path originPath, final Path tempPath, final Path mobPath,
102 final Path archivePath) {
103 this.tempPath = tempPath;
104 this.originPath = originPath;
105 this.mobPath = mobPath;
106 this.archivePath = archivePath;
107 setLocations(originPath, tempPath, mobPath, archivePath);
108 }
109
110
111
112
113
114
115 public static final HFileLink buildFromHFileLinkPattern(Configuration conf, Path hFileLinkPattern)
116 throws IOException {
117 return buildFromHFileLinkPattern(FSUtils.getRootDir(conf),
118 HFileArchiveUtil.getArchivePath(conf), hFileLinkPattern);
119 }
120
121
122
123
124
125
126 public final static HFileLink buildFromHFileLinkPattern(final Path rootDir,
127 final Path archiveDir,
128 final Path hFileLinkPattern) {
129 Path hfilePath = getHFileLinkPatternRelativePath(hFileLinkPattern);
130 Path tempPath = new Path(new Path(rootDir, HConstants.HBASE_TEMP_DIRECTORY), hfilePath);
131 Path originPath = new Path(rootDir, hfilePath);
132 Path mobPath = new Path(new Path(rootDir, MobConstants.MOB_DIR_NAME), hfilePath);
133 Path archivePath = new Path(archiveDir, hfilePath);
134 return new HFileLink(originPath, tempPath, mobPath, archivePath);
135 }
136
137
138
139
140
141
142
143
144
145 public static Path createPath(final TableName table, final String region,
146 final String family, final String hfile) {
147 if (HFileLink.isHFileLink(hfile)) {
148 return new Path(family, hfile);
149 }
150 return new Path(family, HFileLink.createHFileLinkName(table, region, hfile));
151 }
152
153
154
155
156
157
158
159
160
161
162
163 public static HFileLink build(final Configuration conf, final TableName table,
164 final String region, final String family, final String hfile)
165 throws IOException {
166 return HFileLink.buildFromHFileLinkPattern(conf, createPath(table, region, family, hfile));
167 }
168
169
170
171
172
173
174
175
176
177
178
179
180 @Deprecated
181 public static HFileLink create(final Configuration conf, final TableName table,
182 final String region, final String family, final String hfile)
183 throws IOException {
184 return build(conf, table, region, family, hfile);
185 }
186
187
188
189
190 public Path getOriginPath() {
191 return this.originPath;
192 }
193
194
195
196
197 public Path getArchivePath() {
198 return this.archivePath;
199 }
200
201
202
203
204 public Path getMobPath() { return this.mobPath; }
205
206
207
208
209
210 public static boolean isHFileLink(final Path path) {
211 return isHFileLink(path.getName());
212 }
213
214
215
216
217
218
219 public static boolean isHFileLink(String fileName) {
220 Matcher m = LINK_NAME_PATTERN.matcher(fileName);
221 if (!m.matches()) return false;
222 return m.groupCount() > 2 && m.group(4) != null && m.group(3) != null && m.group(2) != null;
223 }
224
225
226
227
228
229
230
231
232
233
234 private static Path getHFileLinkPatternRelativePath(final Path path) {
235
236 Matcher m = REF_OR_HFILE_LINK_PATTERN.matcher(path.getName());
237 if (!m.matches()) {
238 throw new IllegalArgumentException(path.getName() + " is not a valid HFileLink pattern!");
239 }
240
241
242 TableName tableName = TableName.valueOf(m.group(1), m.group(2));
243 String regionName = m.group(3);
244 String hfileName = m.group(4);
245 String familyName = path.getParent().getName();
246 Path tableDir = FSUtils.getTableDir(new Path("./"), tableName);
247 return new Path(tableDir, new Path(regionName, new Path(familyName,
248 hfileName)));
249 }
250
251
252
253
254
255
256
257 public static String getReferencedHFileName(final String fileName) {
258 Matcher m = REF_OR_HFILE_LINK_PATTERN.matcher(fileName);
259 if (!m.matches()) {
260 throw new IllegalArgumentException(fileName + " is not a valid HFileLink name!");
261 }
262 return(m.group(4));
263 }
264
265
266
267
268
269
270
271 public static String getReferencedRegionName(final String fileName) {
272 Matcher m = REF_OR_HFILE_LINK_PATTERN.matcher(fileName);
273 if (!m.matches()) {
274 throw new IllegalArgumentException(fileName + " is not a valid HFileLink name!");
275 }
276 return(m.group(3));
277 }
278
279
280
281
282
283
284
285 public static TableName getReferencedTableName(final String fileName) {
286 Matcher m = REF_OR_HFILE_LINK_PATTERN.matcher(fileName);
287 if (!m.matches()) {
288 throw new IllegalArgumentException(fileName + " is not a valid HFileLink name!");
289 }
290 return(TableName.valueOf(m.group(1), m.group(2)));
291 }
292
293
294
295
296
297
298
299
300 public static String createHFileLinkName(final HRegionInfo hfileRegionInfo,
301 final String hfileName) {
302 return createHFileLinkName(hfileRegionInfo.getTable(),
303 hfileRegionInfo.getEncodedName(), hfileName);
304 }
305
306
307
308
309
310
311
312
313
314 public static String createHFileLinkName(final TableName tableName,
315 final String regionName, final String hfileName) {
316 String s = String.format("%s=%s-%s",
317 tableName.getNameAsString().replace(TableName.NAMESPACE_DELIM, '='),
318 regionName, hfileName);
319 return s;
320 }
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336 public static boolean create(final Configuration conf, final FileSystem fs,
337 final Path dstFamilyPath, final HRegionInfo hfileRegionInfo,
338 final String hfileName) throws IOException {
339 return create(conf, fs, dstFamilyPath, hfileRegionInfo, hfileName, true);
340 }
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357 public static boolean create(final Configuration conf, final FileSystem fs,
358 final Path dstFamilyPath, final HRegionInfo hfileRegionInfo,
359 final String hfileName, final boolean createBackRef) throws IOException {
360 TableName linkedTable = hfileRegionInfo.getTable();
361 String linkedRegion = hfileRegionInfo.getEncodedName();
362 return create(conf, fs, dstFamilyPath, linkedTable, linkedRegion, hfileName, createBackRef);
363 }
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380 public static boolean create(final Configuration conf, final FileSystem fs,
381 final Path dstFamilyPath, final TableName linkedTable, final String linkedRegion,
382 final String hfileName) throws IOException {
383 return create(conf, fs, dstFamilyPath, linkedTable, linkedRegion, hfileName, true);
384 }
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402 public static boolean create(final Configuration conf, final FileSystem fs,
403 final Path dstFamilyPath, final TableName linkedTable, final String linkedRegion,
404 final String hfileName, final boolean createBackRef) throws IOException {
405 String familyName = dstFamilyPath.getName();
406 String regionName = dstFamilyPath.getParent().getName();
407 String tableName = FSUtils.getTableName(dstFamilyPath.getParent().getParent())
408 .getNameAsString();
409
410 String name = createHFileLinkName(linkedTable, linkedRegion, hfileName);
411 String refName = createBackReferenceName(tableName, regionName);
412
413
414 fs.mkdirs(dstFamilyPath);
415
416
417 Path archiveStoreDir = HFileArchiveUtil.getStoreArchivePath(conf,
418 linkedTable, linkedRegion, familyName);
419 Path backRefPath = null;
420 if (createBackRef) {
421 Path backRefssDir = getBackReferencesDir(archiveStoreDir, hfileName);
422 fs.mkdirs(backRefssDir);
423
424
425 backRefPath = new Path(backRefssDir, refName);
426 fs.createNewFile(backRefPath);
427 }
428 try {
429
430 return fs.createNewFile(new Path(dstFamilyPath, name));
431 } catch (IOException e) {
432 LOG.error("couldn't create the link=" + name + " for " + dstFamilyPath, e);
433
434 if (createBackRef) {
435 fs.delete(backRefPath, false);
436 }
437 throw e;
438 }
439 }
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454 public static boolean createFromHFileLink(final Configuration conf, final FileSystem fs,
455 final Path dstFamilyPath, final String hfileLinkName)
456 throws IOException {
457 return createFromHFileLink(conf, fs, dstFamilyPath, hfileLinkName, true);
458 }
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474 public static boolean createFromHFileLink(final Configuration conf, final FileSystem fs,
475 final Path dstFamilyPath, final String hfileLinkName, final boolean createBackRef)
476 throws IOException {
477 Matcher m = LINK_NAME_PATTERN.matcher(hfileLinkName);
478 if (!m.matches()) {
479 throw new IllegalArgumentException(hfileLinkName + " is not a valid HFileLink name!");
480 }
481 return create(conf, fs, dstFamilyPath, TableName.valueOf(m.group(1), m.group(2)),
482 m.group(3), m.group(4), createBackRef);
483 }
484
485
486
487
488
489 static String createBackReferenceName(final String tableNameStr,
490 final String regionName) {
491
492 return regionName + "." + tableNameStr.replace(TableName.NAMESPACE_DELIM, '=');
493 }
494
495
496
497
498
499
500
501
502 public static Path getHFileFromBackReference(final Path rootDir, final Path linkRefPath) {
503 Pair<TableName, String> p = parseBackReferenceName(linkRefPath.getName());
504 TableName linkTableName = p.getFirst();
505 String linkRegionName = p.getSecond();
506
507 String hfileName = getBackReferenceFileName(linkRefPath.getParent());
508 Path familyPath = linkRefPath.getParent().getParent();
509 Path regionPath = familyPath.getParent();
510 Path tablePath = regionPath.getParent();
511
512 String linkName = createHFileLinkName(FSUtils.getTableName(tablePath),
513 regionPath.getName(), hfileName);
514 Path linkTableDir = FSUtils.getTableDir(rootDir, linkTableName);
515 Path regionDir = HRegion.getRegionDir(linkTableDir, linkRegionName);
516 return new Path(new Path(regionDir, familyPath.getName()), linkName);
517 }
518
519 static Pair<TableName, String> parseBackReferenceName(String name) {
520 int separatorIndex = name.indexOf('.');
521 String linkRegionName = name.substring(0, separatorIndex);
522 String tableSubstr = name.substring(separatorIndex + 1)
523 .replace('=', TableName.NAMESPACE_DELIM);
524 TableName linkTableName = TableName.valueOf(tableSubstr);
525 return new Pair<TableName, String>(linkTableName, linkRegionName);
526 }
527
528
529
530
531
532
533
534
535
536 public static Path getHFileFromBackReference(final Configuration conf, final Path linkRefPath)
537 throws IOException {
538 return getHFileFromBackReference(FSUtils.getRootDir(conf), linkRefPath);
539 }
540
541 }