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