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