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