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