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.HConstants;
32 import org.apache.hadoop.hbase.HRegionInfo;
33 import org.apache.hadoop.hbase.HTableDescriptor;
34 import org.apache.hadoop.hbase.regionserver.HRegion;
35 import org.apache.hadoop.hbase.regionserver.StoreFile;
36 import org.apache.hadoop.hbase.util.FSUtils;
37 import org.apache.hadoop.hbase.util.HFileArchiveUtil;
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54 @InterfaceAudience.Private
55 public class HFileLink extends FileLink {
56 private static final Log LOG = LogFactory.getLog(HFileLink.class);
57
58
59
60
61
62
63
64
65
66
67
68 public static final String LINK_NAME_REGEX =
69 String.format("%s=%s-%s", HTableDescriptor.VALID_USER_TABLE_REGEX,
70 HRegionInfo.ENCODED_REGION_NAME_REGEX, StoreFile.HFILE_NAME_REGEX);
71
72
73 private static final Pattern LINK_NAME_PATTERN =
74 Pattern.compile(String.format("^(%s)=(%s)-(%s)$", HTableDescriptor.VALID_USER_TABLE_REGEX,
75 HRegionInfo.ENCODED_REGION_NAME_REGEX, StoreFile.HFILE_NAME_REGEX));
76
77
78
79
80
81 private static final Pattern REF_OR_HFILE_LINK_PATTERN =
82 Pattern.compile(String.format("^(%s)=(%s)-(.+)$", HTableDescriptor.VALID_USER_TABLE_REGEX,
83 HRegionInfo.ENCODED_REGION_NAME_REGEX));
84
85 private final Path archivePath;
86 private final Path originPath;
87 private final Path tempPath;
88
89
90
91
92
93
94 public HFileLink(Configuration conf, Path path) throws IOException {
95 this(FSUtils.getRootDir(conf), HFileArchiveUtil.getArchivePath(conf), path);
96 }
97
98
99
100
101
102
103 public HFileLink(final Path rootDir, final Path archiveDir, final Path path) {
104 Path hfilePath = getRelativeTablePath(path);
105 this.tempPath = new Path(new Path(rootDir, HConstants.HBASE_TEMP_DIRECTORY), hfilePath);
106 this.originPath = new Path(rootDir, hfilePath);
107 this.archivePath = new Path(archiveDir, hfilePath);
108 setLocations(originPath, tempPath, archivePath);
109 }
110
111
112
113
114
115
116
117
118
119 public static Path createPath(final String table, final String region,
120 final String family, final String hfile) {
121 if (HFileLink.isHFileLink(hfile)) {
122 return new Path(family, hfile);
123 }
124 return new Path(family, HFileLink.createHFileLinkName(table, region, hfile));
125 }
126
127
128
129
130
131
132
133
134
135
136
137 public static HFileLink create(final Configuration conf, final String table,
138 final String region, final String family, final String hfile) throws IOException {
139 return new HFileLink(conf, createPath(table, region, family, hfile));
140 }
141
142
143
144
145 public Path getOriginPath() {
146 return this.originPath;
147 }
148
149
150
151
152 public Path getArchivePath() {
153 return this.archivePath;
154 }
155
156
157
158
159
160 public static boolean isHFileLink(final Path path) {
161 return isHFileLink(path.getName());
162 }
163
164
165
166
167
168 public static boolean isHFileLink(String fileName) {
169 Matcher m = LINK_NAME_PATTERN.matcher(fileName);
170 if (!m.matches()) return false;
171
172 return m.groupCount() > 2 && m.group(3) != null && m.group(2) != null && m.group(1) != null;
173 }
174
175
176
177
178
179
180
181
182
183
184 private static Path getRelativeTablePath(final Path path) {
185
186 Matcher m = REF_OR_HFILE_LINK_PATTERN.matcher(path.getName());
187 if (!m.matches()) {
188 throw new IllegalArgumentException(path.getName() + " is not a valid HFileLink name!");
189 }
190
191
192 String tableName = m.group(1);
193 String regionName = m.group(2);
194 String hfileName = m.group(3);
195 String familyName = path.getParent().getName();
196 return new Path(new Path(tableName, regionName), new Path(familyName, hfileName));
197 }
198
199
200
201
202
203
204
205 public static String getReferencedHFileName(final String fileName) {
206 Matcher m = REF_OR_HFILE_LINK_PATTERN.matcher(fileName);
207 if (!m.matches()) {
208 throw new IllegalArgumentException(fileName + " is not a valid HFileLink name!");
209 }
210 return(m.group(3));
211 }
212
213
214
215
216
217
218
219 public static String getReferencedRegionName(final String fileName) {
220 Matcher m = REF_OR_HFILE_LINK_PATTERN.matcher(fileName);
221 if (!m.matches()) {
222 throw new IllegalArgumentException(fileName + " is not a valid HFileLink name!");
223 }
224 return(m.group(2));
225 }
226
227
228
229
230
231
232
233 public static String getReferencedTableName(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(1));
239 }
240
241
242
243
244 public boolean exists(final FileSystem fs) throws IOException {
245 return fs.exists(this.originPath) ||
246 fs.exists(this.tempPath) ||
247 fs.exists(this.archivePath);
248 }
249
250
251
252
253
254
255
256
257 public static String createHFileLinkName(final HRegionInfo hfileRegionInfo,
258 final String hfileName) {
259 return createHFileLinkName(hfileRegionInfo.getTableNameAsString(),
260 hfileRegionInfo.getEncodedName(), hfileName);
261 }
262
263
264
265
266
267
268
269
270
271 public static String createHFileLinkName(final String tableName,
272 final String regionName, final String hfileName) {
273 return String.format("%s=%s-%s", tableName, regionName, hfileName);
274 }
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290 public static boolean create(final Configuration conf, final FileSystem fs,
291 final Path dstFamilyPath, final HRegionInfo hfileRegionInfo,
292 final String hfileName) throws IOException {
293 String linkedTable = hfileRegionInfo.getTableNameAsString();
294 String linkedRegion = hfileRegionInfo.getEncodedName();
295 return create(conf, fs, dstFamilyPath, linkedTable, linkedRegion, hfileName);
296 }
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313 public static boolean create(final Configuration conf, final FileSystem fs,
314 final Path dstFamilyPath, final String linkedTable, final String linkedRegion,
315 final String hfileName) throws IOException {
316 String familyName = dstFamilyPath.getName();
317 String regionName = dstFamilyPath.getParent().getName();
318 String tableName = dstFamilyPath.getParent().getParent().getName();
319
320 String name = createHFileLinkName(linkedTable, linkedRegion, hfileName);
321 String refName = createBackReferenceName(tableName, regionName);
322
323
324 fs.mkdirs(dstFamilyPath);
325
326
327 Path archiveStoreDir = HFileArchiveUtil.getStoreArchivePath(conf,
328 linkedTable, linkedRegion, familyName);
329 Path backRefssDir = getBackReferencesDir(archiveStoreDir, hfileName);
330 fs.mkdirs(backRefssDir);
331
332
333 Path backRefPath = new Path(backRefssDir, refName);
334 fs.createNewFile(backRefPath);
335 try {
336
337 return fs.createNewFile(new Path(dstFamilyPath, name));
338 } catch (IOException e) {
339 LOG.error("couldn't create the link=" + name + " for " + dstFamilyPath, e);
340
341 fs.delete(backRefPath, false);
342 throw e;
343 }
344 }
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359 public static boolean createFromHFileLink(final Configuration conf, final FileSystem fs,
360 final Path dstFamilyPath, final String hfileLinkName) throws IOException {
361 Matcher m = LINK_NAME_PATTERN.matcher(hfileLinkName);
362 if (!m.matches()) {
363 throw new IllegalArgumentException(hfileLinkName + " is not a valid HFileLink name!");
364 }
365 return create(conf, fs, dstFamilyPath, m.group(1), m.group(2), m.group(3));
366 }
367
368
369
370
371 private static String createBackReferenceName(final String tableName, final String regionName) {
372 return regionName + "." + tableName;
373 }
374
375
376
377
378
379
380
381
382
383 public static Path getHFileFromBackReference(final Path rootDir, final Path linkRefPath) {
384 int separatorIndex = linkRefPath.getName().indexOf('.');
385 String linkRegionName = linkRefPath.getName().substring(0, separatorIndex);
386 String linkTableName = linkRefPath.getName().substring(separatorIndex + 1);
387 String hfileName = getBackReferenceFileName(linkRefPath.getParent());
388 Path familyPath = linkRefPath.getParent().getParent();
389 Path regionPath = familyPath.getParent();
390 Path tablePath = regionPath.getParent();
391
392 String linkName = createHFileLinkName(tablePath.getName(), regionPath.getName(), hfileName);
393 Path linkTableDir = FSUtils.getTablePath(rootDir, linkTableName);
394 Path regionDir = HRegion.getRegionDir(linkTableDir, linkRegionName);
395 return new Path(new Path(regionDir, familyPath.getName()), linkName);
396 }
397
398
399
400
401
402
403
404
405
406 public static Path getHFileFromBackReference(final Configuration conf, final Path linkRefPath)
407 throws IOException {
408 return getHFileFromBackReference(FSUtils.getRootDir(conf), linkRefPath);
409 }
410 }