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