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 TableName linkedTable = hfileRegionInfo.getTable();
295 String linkedRegion = hfileRegionInfo.getEncodedName();
296 return create(conf, fs, dstFamilyPath, linkedTable, linkedRegion, hfileName);
297 }
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314 public static boolean create(final Configuration conf, final FileSystem fs,
315 final Path dstFamilyPath, final TableName linkedTable, final String linkedRegion,
316 final String hfileName) throws IOException {
317 String familyName = dstFamilyPath.getName();
318 String regionName = dstFamilyPath.getParent().getName();
319 String tableName = FSUtils.getTableName(dstFamilyPath.getParent().getParent())
320 .getNameAsString();
321
322 String name = createHFileLinkName(linkedTable, linkedRegion, hfileName);
323 String refName = createBackReferenceName(tableName, regionName);
324
325
326 fs.mkdirs(dstFamilyPath);
327
328
329 Path archiveStoreDir = HFileArchiveUtil.getStoreArchivePath(conf,
330 linkedTable, linkedRegion, familyName);
331 Path backRefssDir = getBackReferencesDir(archiveStoreDir, hfileName);
332 fs.mkdirs(backRefssDir);
333
334
335 Path backRefPath = new Path(backRefssDir, refName);
336 fs.createNewFile(backRefPath);
337 try {
338
339 return fs.createNewFile(new Path(dstFamilyPath, name));
340 } catch (IOException e) {
341 LOG.error("couldn't create the link=" + name + " for " + dstFamilyPath, e);
342
343 fs.delete(backRefPath, false);
344 throw e;
345 }
346 }
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361 public static boolean createFromHFileLink(final Configuration conf, final FileSystem fs,
362 final Path dstFamilyPath, final String hfileLinkName) throws IOException {
363 Matcher m = LINK_NAME_PATTERN.matcher(hfileLinkName);
364 if (!m.matches()) {
365 throw new IllegalArgumentException(hfileLinkName + " is not a valid HFileLink name!");
366 }
367 return create(conf, fs, dstFamilyPath, TableName.valueOf(m.group(1), m.group(2)),
368 m.group(3), m.group(4));
369 }
370
371
372
373
374
375 static String createBackReferenceName(final String tableNameStr,
376 final String regionName) {
377
378 return regionName + "." + tableNameStr.replace(TableName.NAMESPACE_DELIM, '=');
379 }
380
381
382
383
384
385
386
387
388
389 public static Path getHFileFromBackReference(final Path rootDir, final Path linkRefPath) {
390 Pair<TableName, String> p = parseBackReferenceName(linkRefPath.getName());
391 TableName linkTableName = p.getFirst();
392 String linkRegionName = p.getSecond();
393
394 String hfileName = getBackReferenceFileName(linkRefPath.getParent());
395 Path familyPath = linkRefPath.getParent().getParent();
396 Path regionPath = familyPath.getParent();
397 Path tablePath = regionPath.getParent();
398
399 String linkName = createHFileLinkName(FSUtils.getTableName(tablePath),
400 regionPath.getName(), hfileName);
401 Path linkTableDir = FSUtils.getTableDir(rootDir, linkTableName);
402 Path regionDir = HRegion.getRegionDir(linkTableDir, linkRegionName);
403 return new Path(new Path(regionDir, familyPath.getName()), linkName);
404 }
405
406 static Pair<TableName, String> parseBackReferenceName(String name) {
407 int separatorIndex = name.indexOf('.');
408 String linkRegionName = name.substring(0, separatorIndex);
409 String tableSubstr = name.substring(separatorIndex + 1)
410 .replace('=', TableName.NAMESPACE_DELIM);
411 TableName linkTableName = TableName.valueOf(tableSubstr);
412 return new Pair<TableName, String>(linkTableName, linkRegionName);
413 }
414
415
416
417
418
419
420
421
422
423 public static Path getHFileFromBackReference(final Configuration conf, final Path linkRefPath)
424 throws IOException {
425 return getHFileFromBackReference(FSUtils.getRootDir(conf), linkRefPath);
426 }
427
428 }