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.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 public Path getOriginPath() {
120 return this.originPath;
121 }
122
123
124
125
126 public Path getArchivePath() {
127 return this.archivePath;
128 }
129
130
131
132
133
134 public static boolean isHFileLink(final Path path) {
135 return isHFileLink(path.getName());
136 }
137
138
139
140
141
142
143 public static boolean isHFileLink(String fileName) {
144 Matcher m = LINK_NAME_PATTERN.matcher(fileName);
145 if (!m.matches()) return false;
146 return m.groupCount() > 2 && m.group(4) != null && m.group(3) != null && m.group(2) != null;
147 }
148
149
150
151
152
153
154
155
156
157
158 private static Path getRelativeTablePath(final Path path) {
159
160 Matcher m = REF_OR_HFILE_LINK_PATTERN.matcher(path.getName());
161 if (!m.matches()) {
162 throw new IllegalArgumentException(path.getName() + " is not a valid HFileLink name!");
163 }
164
165
166 TableName tableName = TableName.valueOf(m.group(1), m.group(2));
167 String regionName = m.group(3);
168 String hfileName = m.group(4);
169 String familyName = path.getParent().getName();
170 Path tableDir = FSUtils.getTableDir(new Path("./"), tableName);
171 return new Path(tableDir, new Path(regionName, new Path(familyName,
172 hfileName)));
173 }
174
175
176
177
178
179
180
181 public static String getReferencedHFileName(final String fileName) {
182 Matcher m = REF_OR_HFILE_LINK_PATTERN.matcher(fileName);
183 if (!m.matches()) {
184 throw new IllegalArgumentException(fileName + " is not a valid HFileLink name!");
185 }
186 return(m.group(4));
187 }
188
189
190
191
192
193
194
195 public static String getReferencedRegionName(final String fileName) {
196 Matcher m = REF_OR_HFILE_LINK_PATTERN.matcher(fileName);
197 if (!m.matches()) {
198 throw new IllegalArgumentException(fileName + " is not a valid HFileLink name!");
199 }
200 return(m.group(3));
201 }
202
203
204
205
206
207
208
209 public static TableName getReferencedTableName(final String fileName) {
210 Matcher m = REF_OR_HFILE_LINK_PATTERN.matcher(fileName);
211 if (!m.matches()) {
212 throw new IllegalArgumentException(fileName + " is not a valid HFileLink name!");
213 }
214 return(TableName.valueOf(m.group(1), m.group(2)));
215 }
216
217
218
219
220
221
222
223
224 public static String createHFileLinkName(final HRegionInfo hfileRegionInfo,
225 final String hfileName) {
226 return createHFileLinkName(hfileRegionInfo.getTableName(),
227 hfileRegionInfo.getEncodedName(), hfileName);
228 }
229
230
231
232
233
234
235
236
237
238 public static String createHFileLinkName(final TableName tableName,
239 final String regionName, final String hfileName) {
240 String s = String.format("%s=%s-%s",
241 tableName.getNameAsString().replace(TableName.NAMESPACE_DELIM, '='),
242 regionName, hfileName);
243 return s;
244 }
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260 public static boolean create(final Configuration conf, final FileSystem fs,
261 final Path dstFamilyPath, final HRegionInfo hfileRegionInfo,
262 final String hfileName) throws IOException {
263 TableName linkedTable = hfileRegionInfo.getTableName();
264 String linkedRegion = hfileRegionInfo.getEncodedName();
265 return create(conf, fs, dstFamilyPath, linkedTable, linkedRegion, hfileName);
266 }
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283 public static boolean create(final Configuration conf, final FileSystem fs,
284 final Path dstFamilyPath, final TableName linkedTable, final String linkedRegion,
285 final String hfileName) throws IOException {
286 String familyName = dstFamilyPath.getName();
287 String regionName = dstFamilyPath.getParent().getName();
288 String tableName = FSUtils.getTableName(dstFamilyPath.getParent().getParent())
289 .getNameAsString();
290
291 String name = createHFileLinkName(linkedTable, linkedRegion, hfileName);
292 String refName = createBackReferenceName(tableName, regionName);
293
294
295 fs.mkdirs(dstFamilyPath);
296
297
298 Path archiveStoreDir = HFileArchiveUtil.getStoreArchivePath(conf,
299 linkedTable, linkedRegion, familyName);
300 Path backRefssDir = getBackReferencesDir(archiveStoreDir, hfileName);
301 fs.mkdirs(backRefssDir);
302
303
304 Path backRefPath = new Path(backRefssDir, refName);
305 fs.createNewFile(backRefPath);
306 try {
307
308 return fs.createNewFile(new Path(dstFamilyPath, name));
309 } catch (IOException e) {
310 LOG.error("couldn't create the link=" + name + " for " + dstFamilyPath, e);
311
312 fs.delete(backRefPath, false);
313 throw e;
314 }
315 }
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330 public static boolean createFromHFileLink(final Configuration conf, final FileSystem fs,
331 final Path dstFamilyPath, final String hfileLinkName) throws IOException {
332 Matcher m = LINK_NAME_PATTERN.matcher(hfileLinkName);
333 if (!m.matches()) {
334 throw new IllegalArgumentException(hfileLinkName + " is not a valid HFileLink name!");
335 }
336 return create(conf, fs, dstFamilyPath, TableName.valueOf(m.group(1), m.group(2)),
337 m.group(3), m.group(4));
338 }
339
340
341
342
343
344 static String createBackReferenceName(final String tableNameStr,
345 final String regionName) {
346
347 return regionName + "." + tableNameStr.replace(TableName.NAMESPACE_DELIM, '=');
348 }
349
350
351
352
353
354
355
356
357
358 public static Path getHFileFromBackReference(final Path rootDir, final Path linkRefPath) {
359 Pair<TableName, String> p = parseBackReferenceName(linkRefPath.getName());
360 TableName linkTableName = p.getFirst();
361 String linkRegionName = p.getSecond();
362
363 String hfileName = getBackReferenceFileName(linkRefPath.getParent());
364 Path familyPath = linkRefPath.getParent().getParent();
365 Path regionPath = familyPath.getParent();
366 Path tablePath = regionPath.getParent();
367
368 String linkName = createHFileLinkName(FSUtils.getTableName(tablePath),
369 regionPath.getName(), hfileName);
370 Path linkTableDir = FSUtils.getTableDir(rootDir, linkTableName);
371 Path regionDir = HRegion.getRegionDir(linkTableDir, linkRegionName);
372 return new Path(new Path(regionDir, familyPath.getName()), linkName);
373 }
374
375 static Pair<TableName, String> parseBackReferenceName(String name) {
376 int separatorIndex = name.indexOf('.');
377 String linkRegionName = name.substring(0, separatorIndex);
378 String tableSubstr = name.substring(separatorIndex + 1)
379 .replace('=', TableName.NAMESPACE_DELIM);
380 TableName linkTableName = TableName.valueOf(tableSubstr);
381 return new Pair<TableName, String>(linkTableName, linkRegionName);
382 }
383
384
385
386
387
388
389
390
391
392 public static Path getHFileFromBackReference(final Configuration conf, final Path linkRefPath)
393 throws IOException {
394 return getHFileFromBackReference(FSUtils.getRootDir(conf), linkRefPath);
395 }
396
397 }