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