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