1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.hadoop.hbase.regionserver;
21
22 import java.io.FileNotFoundException;
23 import java.io.IOException;
24 import java.io.InterruptedIOException;
25 import java.util.ArrayList;
26 import java.util.Collection;
27 import java.util.List;
28 import java.util.Map;
29 import java.util.UUID;
30
31 import org.apache.commons.logging.Log;
32 import org.apache.commons.logging.LogFactory;
33 import org.apache.hadoop.hbase.classification.InterfaceAudience;
34 import org.apache.hadoop.conf.Configuration;
35 import org.apache.hadoop.fs.FSDataInputStream;
36 import org.apache.hadoop.fs.FSDataOutputStream;
37 import org.apache.hadoop.fs.FileStatus;
38 import org.apache.hadoop.fs.FileSystem;
39 import org.apache.hadoop.fs.FileUtil;
40 import org.apache.hadoop.fs.LocatedFileStatus;
41 import org.apache.hadoop.fs.Path;
42 import org.apache.hadoop.fs.permission.FsPermission;
43 import org.apache.hadoop.hbase.HColumnDescriptor;
44 import org.apache.hadoop.hbase.HConstants;
45 import org.apache.hadoop.hbase.HRegionInfo;
46 import org.apache.hadoop.hbase.HTableDescriptor;
47 import org.apache.hadoop.hbase.KeyValue;
48 import org.apache.hadoop.hbase.KeyValueUtil;
49 import org.apache.hadoop.hbase.backup.HFileArchiver;
50 import org.apache.hadoop.hbase.fs.HFileSystem;
51 import org.apache.hadoop.hbase.io.Reference;
52 import org.apache.hadoop.hbase.util.Bytes;
53 import org.apache.hadoop.hbase.util.FSHDFSUtils;
54 import org.apache.hadoop.hbase.util.FSUtils;
55 import org.apache.hadoop.hbase.util.Pair;
56 import org.apache.hadoop.hbase.util.ServerRegionReplicaUtil;
57
58 import com.google.common.collect.Lists;
59
60
61
62
63
64 @InterfaceAudience.Private
65 public class HRegionFileSystem {
66 private static final Log LOG = LogFactory.getLog(HRegionFileSystem.class);
67
68
69 public final static String REGION_INFO_FILE = ".regioninfo";
70
71
72 public static final String REGION_MERGES_DIR = ".merges";
73
74
75 public static final String REGION_SPLITS_DIR = ".splits";
76
77
78 static final String REGION_TEMP_DIR = ".tmp";
79
80 private final HRegionInfo regionInfo;
81
82 private final HRegionInfo regionInfoForFs;
83 private final Configuration conf;
84 private final Path tableDir;
85 private final FileSystem fs;
86
87
88
89
90
91 private final int hdfsClientRetriesNumber;
92 private final int baseSleepBeforeRetries;
93 private static final int DEFAULT_HDFS_CLIENT_RETRIES_NUMBER = 10;
94 private static final int DEFAULT_BASE_SLEEP_BEFORE_RETRIES = 1000;
95
96
97
98
99
100
101
102
103 HRegionFileSystem(final Configuration conf, final FileSystem fs, final Path tableDir,
104 final HRegionInfo regionInfo) {
105 this.fs = fs;
106 this.conf = conf;
107 this.tableDir = tableDir;
108 this.regionInfo = regionInfo;
109 this.regionInfoForFs = ServerRegionReplicaUtil.getRegionInfoForFs(regionInfo);
110 this.hdfsClientRetriesNumber = conf.getInt("hdfs.client.retries.number",
111 DEFAULT_HDFS_CLIENT_RETRIES_NUMBER);
112 this.baseSleepBeforeRetries = conf.getInt("hdfs.client.sleep.before.retries",
113 DEFAULT_BASE_SLEEP_BEFORE_RETRIES);
114 }
115
116
117 public FileSystem getFileSystem() {
118 return this.fs;
119 }
120
121
122 public HRegionInfo getRegionInfo() {
123 return this.regionInfo;
124 }
125
126 public HRegionInfo getRegionInfoForFS() {
127 return this.regionInfoForFs;
128 }
129
130
131 public Path getTableDir() {
132 return this.tableDir;
133 }
134
135
136 public Path getRegionDir() {
137 return new Path(this.tableDir, this.regionInfoForFs.getEncodedName());
138 }
139
140
141
142
143
144 Path getTempDir() {
145 return new Path(getRegionDir(), REGION_TEMP_DIR);
146 }
147
148
149
150
151 void cleanupTempDir() throws IOException {
152 deleteDir(getTempDir());
153 }
154
155
156
157
158
159
160
161
162
163 public Path getStoreDir(final String familyName) {
164 return new Path(this.getRegionDir(), familyName);
165 }
166
167
168
169
170
171
172
173 Path createStoreDir(final String familyName) throws IOException {
174 Path storeDir = getStoreDir(familyName);
175 if(!fs.exists(storeDir) && !createDir(storeDir))
176 throw new IOException("Failed creating "+storeDir);
177 return storeDir;
178 }
179
180
181
182
183
184
185
186
187
188
189
190
191 public void setStoragePolicy(String familyName, String policyName) throws IOException {
192 if (this.fs instanceof HFileSystem) {
193 FSUtils.setStoragePolicy(
194 ((HFileSystem) this.fs).getBackingFs(),
195 getStoreDir(familyName), policyName);
196 } else {
197 FSUtils.setStoragePolicy(this.fs, getStoreDir(familyName), policyName);
198 }
199 }
200
201
202
203
204
205
206
207 public String getStoragePolicyName(String familyName) {
208 if (this.fs instanceof HFileSystem) {
209 Path storeDir = getStoreDir(familyName);
210 return ((HFileSystem) this.fs).getStoragePolicyName(storeDir);
211 }
212
213 return null;
214 }
215
216
217
218
219
220
221
222 public Collection<StoreFileInfo> getStoreFiles(final byte[] familyName) throws IOException {
223 return getStoreFiles(Bytes.toString(familyName));
224 }
225
226 public Collection<StoreFileInfo> getStoreFiles(final String familyName) throws IOException {
227 return getStoreFiles(familyName, true);
228 }
229
230
231
232
233
234
235
236 public Collection<StoreFileInfo> getStoreFiles(final String familyName, final boolean validate)
237 throws IOException {
238 Path familyDir = getStoreDir(familyName);
239 FileStatus[] files = FSUtils.listStatus(this.fs, familyDir);
240 if (files == null) {
241 if (LOG.isTraceEnabled()) {
242 LOG.trace("No StoreFiles for: " + familyDir);
243 }
244 return null;
245 }
246
247 ArrayList<StoreFileInfo> storeFiles = new ArrayList<StoreFileInfo>(files.length);
248 for (FileStatus status: files) {
249 if (validate && !StoreFileInfo.isValid(status)) {
250 LOG.warn("Invalid StoreFile: " + status.getPath());
251 continue;
252 }
253 StoreFileInfo info = ServerRegionReplicaUtil.getStoreFileInfo(conf, fs, regionInfo,
254 regionInfoForFs, familyName, status.getPath());
255 storeFiles.add(info);
256
257 }
258 return storeFiles;
259 }
260
261
262
263
264
265
266
267 public static List<LocatedFileStatus> getStoreFilesLocatedStatus(
268 final HRegionFileSystem regionfs, final String familyName,
269 final boolean validate) throws IOException {
270 Path familyDir = regionfs.getStoreDir(familyName);
271 List<LocatedFileStatus> locatedFileStatuses = FSUtils.listLocatedStatus(
272 regionfs.getFileSystem(), familyDir);
273 if (locatedFileStatuses == null) {
274 if (LOG.isTraceEnabled()) {
275 LOG.trace("No StoreFiles for: " + familyDir);
276 }
277 return null;
278 }
279
280 List<LocatedFileStatus> validStoreFiles = Lists.newArrayList();
281 for (LocatedFileStatus status : locatedFileStatuses) {
282 if (validate && !StoreFileInfo.isValid(status)) {
283 LOG.warn("Invalid StoreFile: " + status.getPath());
284 } else {
285 validStoreFiles.add(status);
286 }
287 }
288 return validStoreFiles;
289 }
290
291
292
293
294
295
296
297
298 Path getStoreFilePath(final String familyName, final String fileName) {
299 Path familyDir = getStoreDir(familyName);
300 return new Path(familyDir, fileName).makeQualified(this.fs);
301 }
302
303
304
305
306
307
308
309
310 StoreFileInfo getStoreFileInfo(final String familyName, final String fileName)
311 throws IOException {
312 Path familyDir = getStoreDir(familyName);
313 return ServerRegionReplicaUtil.getStoreFileInfo(conf, fs, regionInfo,
314 regionInfoForFs, familyName, new Path(familyDir, fileName));
315 }
316
317
318
319
320
321
322
323 public boolean hasReferences(final String familyName) throws IOException {
324 FileStatus[] files = FSUtils.listStatus(fs, getStoreDir(familyName));
325 if (files != null) {
326 for(FileStatus stat: files) {
327 if(stat.isDirectory()) {
328 continue;
329 }
330 if(StoreFileInfo.isReference(stat.getPath())) {
331 return true;
332 }
333 }
334 }
335 return false;
336 }
337
338
339
340
341
342
343
344 public boolean hasReferences(final HTableDescriptor htd) throws IOException {
345 for (HColumnDescriptor family : htd.getFamilies()) {
346 if (hasReferences(family.getNameAsString())) {
347 return true;
348 }
349 }
350 return false;
351 }
352
353
354
355
356
357 public Collection<String> getFamilies() throws IOException {
358 FileStatus[] fds = FSUtils.listStatus(fs, getRegionDir(), new FSUtils.FamilyDirFilter(fs));
359 if (fds == null) return null;
360
361 ArrayList<String> families = new ArrayList<String>(fds.length);
362 for (FileStatus status: fds) {
363 families.add(status.getPath().getName());
364 }
365
366 return families;
367 }
368
369
370
371
372
373
374 public void deleteFamily(final String familyName) throws IOException {
375
376 HFileArchiver.archiveFamily(fs, conf, regionInfoForFs, tableDir, Bytes.toBytes(familyName));
377
378
379 Path familyDir = getStoreDir(familyName);
380 if(fs.exists(familyDir) && !deleteDir(familyDir))
381 throw new IOException("Could not delete family " + familyName
382 + " from FileSystem for region " + regionInfoForFs.getRegionNameAsString() + "("
383 + regionInfoForFs.getEncodedName() + ")");
384 }
385
386
387
388
389
390
391 private static String generateUniqueName(final String suffix) {
392 String name = UUID.randomUUID().toString().replaceAll("-", "");
393 if (suffix != null) name += suffix;
394 return name;
395 }
396
397
398
399
400
401
402
403
404
405
406
407
408 public Path createTempName() {
409 return createTempName(null);
410 }
411
412
413
414
415
416
417
418
419
420
421
422
423
424 public Path createTempName(final String suffix) {
425 return new Path(getTempDir(), generateUniqueName(suffix));
426 }
427
428
429
430
431
432
433
434
435 public Path commitStoreFile(final String familyName, final Path buildPath) throws IOException {
436 Path dstPath = preCommitStoreFile(familyName, buildPath, -1, false);
437 return commitStoreFile(buildPath, dstPath);
438 }
439
440
441
442
443
444
445
446
447
448
449
450 private Path preCommitStoreFile(final String familyName, final Path buildPath,
451 final long seqNum, final boolean generateNewName) throws IOException {
452 Path storeDir = getStoreDir(familyName);
453 if(!fs.exists(storeDir) && !createDir(storeDir))
454 throw new IOException("Failed creating " + storeDir);
455
456 String name = buildPath.getName();
457 if (generateNewName) {
458 name = generateUniqueName((seqNum < 0) ? null : "_SeqId_" + seqNum + "_");
459 }
460 Path dstPath = new Path(storeDir, name);
461 if (!fs.exists(buildPath)) {
462 throw new FileNotFoundException(buildPath.toString());
463 }
464 if (LOG.isDebugEnabled()) {
465 LOG.debug("Committing store file " + buildPath + " as " + dstPath);
466 }
467 return dstPath;
468 }
469
470
471
472
473
474
475
476
477 Path commitStoreFile(final Path buildPath, Path dstPath) throws IOException {
478
479 if (!rename(buildPath, dstPath)) {
480 throw new IOException("Failed rename of " + buildPath + " to " + dstPath);
481 }
482 return dstPath;
483 }
484
485
486
487
488
489
490 void commitStoreFiles(final Map<byte[], List<StoreFile>> storeFiles) throws IOException {
491 for (Map.Entry<byte[], List<StoreFile>> es: storeFiles.entrySet()) {
492 String familyName = Bytes.toString(es.getKey());
493 for (StoreFile sf: es.getValue()) {
494 commitStoreFile(familyName, sf.getPath());
495 }
496 }
497 }
498
499
500
501
502
503
504
505 public void removeStoreFile(final String familyName, final Path filePath)
506 throws IOException {
507 HFileArchiver.archiveStoreFile(this.conf, this.fs, this.regionInfoForFs,
508 this.tableDir, Bytes.toBytes(familyName), filePath);
509 }
510
511
512
513
514
515
516
517 public void removeStoreFiles(final String familyName, final Collection<StoreFile> storeFiles)
518 throws IOException {
519 HFileArchiver.archiveStoreFiles(this.conf, this.fs, this.regionInfoForFs,
520 this.tableDir, Bytes.toBytes(familyName), storeFiles);
521 }
522
523
524
525
526
527
528
529
530
531
532
533
534 Pair<Path, Path> bulkLoadStoreFile(final String familyName, Path srcPath, long seqNum)
535 throws IOException {
536
537 FileSystem srcFs = srcPath.getFileSystem(conf);
538 srcPath = srcFs.resolvePath(srcPath);
539 FileSystem realSrcFs = srcPath.getFileSystem(conf);
540 FileSystem desFs = fs instanceof HFileSystem ? ((HFileSystem)fs).getBackingFs() : fs;
541
542
543
544
545 if (!FSHDFSUtils.isSameHdfs(conf, realSrcFs, desFs)) {
546 LOG.info("Bulk-load file " + srcPath + " is on different filesystem than " +
547 "the destination store. Copying file over to destination filesystem.");
548 Path tmpPath = createTempName();
549 FileUtil.copy(realSrcFs, srcPath, fs, tmpPath, false, conf);
550 LOG.info("Copied " + srcPath + " to temporary path on destination filesystem: " + tmpPath);
551 srcPath = tmpPath;
552 }
553
554 return new Pair<>(srcPath, preCommitStoreFile(familyName, srcPath, seqNum, true));
555 }
556
557
558
559
560
561 Path getSplitsDir() {
562 return new Path(getRegionDir(), REGION_SPLITS_DIR);
563 }
564
565 Path getSplitsDir(final HRegionInfo hri) {
566 return new Path(getSplitsDir(), hri.getEncodedName());
567 }
568
569
570
571
572 void cleanupSplitsDir() throws IOException {
573 deleteDir(getSplitsDir());
574 }
575
576
577
578
579
580
581
582 void cleanupAnySplitDetritus() throws IOException {
583 Path splitdir = this.getSplitsDir();
584 if (!fs.exists(splitdir)) return;
585
586
587
588
589
590
591
592 FileStatus[] daughters = FSUtils.listStatus(fs, splitdir, new FSUtils.DirFilter(fs));
593 if (daughters != null) {
594 for (FileStatus daughter: daughters) {
595 Path daughterDir = new Path(getTableDir(), daughter.getPath().getName());
596 if (fs.exists(daughterDir) && !deleteDir(daughterDir)) {
597 throw new IOException("Failed delete of " + daughterDir);
598 }
599 }
600 }
601 cleanupSplitsDir();
602 LOG.info("Cleaned up old failed split transaction detritus: " + splitdir);
603 }
604
605
606
607
608
609
610 void cleanupDaughterRegion(final HRegionInfo regionInfo) throws IOException {
611 Path regionDir = new Path(this.tableDir, regionInfo.getEncodedName());
612 if (this.fs.exists(regionDir) && !deleteDir(regionDir)) {
613 throw new IOException("Failed delete of " + regionDir);
614 }
615 }
616
617
618
619
620
621
622
623
624 Path commitDaughterRegion(final HRegionInfo regionInfo)
625 throws IOException {
626 Path regionDir = new Path(this.tableDir, regionInfo.getEncodedName());
627 Path daughterTmpDir = this.getSplitsDir(regionInfo);
628
629 if (fs.exists(daughterTmpDir)) {
630
631
632 Path regionInfoFile = new Path(daughterTmpDir, REGION_INFO_FILE);
633 byte[] regionInfoContent = getRegionInfoFileContent(regionInfo);
634 writeRegionInfoFileContent(conf, fs, regionInfoFile, regionInfoContent);
635
636
637 if (!rename(daughterTmpDir, regionDir)) {
638 throw new IOException("Unable to rename " + daughterTmpDir + " to " + regionDir);
639 }
640 }
641
642 return regionDir;
643 }
644
645
646
647
648 void createSplitsDir(HRegionInfo daughterA, HRegionInfo daughterB) throws IOException {
649 Path splitdir = getSplitsDir();
650 if (fs.exists(splitdir)) {
651 LOG.info("The " + splitdir + " directory exists. Hence deleting it to recreate it");
652 if (!deleteDir(splitdir)) {
653 throw new IOException("Failed deletion of " + splitdir + " before creating them again.");
654 }
655 }
656
657 if (!createDir(splitdir)) {
658 throw new IOException("Failed create of " + splitdir);
659 }
660 Path daughterATmpDir = getSplitsDir(daughterA);
661 if (!createDir(daughterATmpDir)) {
662 throw new IOException("Failed create of " + daughterATmpDir);
663 }
664 Path daughterBTmpDir = getSplitsDir(daughterB);
665 if (!createDir(daughterBTmpDir)) {
666 throw new IOException("Failed create of " + daughterBTmpDir);
667 }
668 }
669
670
671
672
673
674
675
676
677
678
679
680
681
682 Path splitStoreFile(final HRegionInfo hri, final String familyName, final StoreFile f,
683 final byte[] splitRow, final boolean top, RegionSplitPolicy splitPolicy) throws IOException {
684
685 if (splitPolicy == null || !splitPolicy.skipStoreFileRangeCheck(familyName)) {
686
687
688 try {
689 if (top) {
690
691 KeyValue splitKey = KeyValueUtil.createFirstOnRow(splitRow);
692 byte[] lastKey = f.getLastKey();
693
694 if (lastKey == null) {
695 return null;
696 }
697 if (f.getComparator().compareFlatKey(splitKey.getBuffer(),
698 splitKey.getKeyOffset(), splitKey.getKeyLength(), lastKey, 0, lastKey.length) > 0) {
699 return null;
700 }
701 } else {
702
703 KeyValue splitKey = KeyValueUtil.createLastOnRow(splitRow);
704 byte[] firstKey = f.getFirstKey();
705
706 if (firstKey == null) {
707 return null;
708 }
709 if (f.getComparator().compareFlatKey(splitKey.getBuffer(),
710 splitKey.getKeyOffset(), splitKey.getKeyLength(), firstKey, 0, firstKey.length) < 0) {
711 return null;
712 }
713 }
714 } finally {
715 f.closeReader(f.getCacheConf() != null ? f.getCacheConf().shouldEvictOnClose() : true);
716 }
717 }
718
719 Path splitDir = new Path(getSplitsDir(hri), familyName);
720
721 Reference r =
722 top ? Reference.createTopReference(splitRow): Reference.createBottomReference(splitRow);
723
724
725
726
727 String parentRegionName = regionInfoForFs.getEncodedName();
728
729
730 Path p = new Path(splitDir, f.getPath().getName() + "." + parentRegionName);
731 return r.write(fs, p);
732 }
733
734
735
736
737
738 Path getMergesDir() {
739 return new Path(getRegionDir(), REGION_MERGES_DIR);
740 }
741
742 Path getMergesDir(final HRegionInfo hri) {
743 return new Path(getMergesDir(), hri.getEncodedName());
744 }
745
746
747
748
749 void cleanupMergesDir() throws IOException {
750 deleteDir(getMergesDir());
751 }
752
753
754
755
756
757
758 void cleanupMergedRegion(final HRegionInfo mergedRegion) throws IOException {
759 Path regionDir = new Path(this.tableDir, mergedRegion.getEncodedName());
760 if (this.fs.exists(regionDir) && !this.fs.delete(regionDir, true)) {
761 throw new IOException("Failed delete of " + regionDir);
762 }
763 }
764
765 static boolean mkdirs(FileSystem fs, Configuration conf, Path dir) throws IOException {
766 if (FSUtils.isDistributedFileSystem(fs) ||
767 !conf.getBoolean(HConstants.ENABLE_DATA_FILE_UMASK, false)) {
768 return fs.mkdirs(dir);
769 }
770 FsPermission perms = FSUtils.getFilePermissions(fs, conf, HConstants.DATA_FILE_UMASK_KEY);
771 return fs.mkdirs(dir, perms);
772 }
773
774
775
776
777
778 void createMergesDir() throws IOException {
779 Path mergesdir = getMergesDir();
780 if (fs.exists(mergesdir)) {
781 LOG.info("The " + mergesdir
782 + " directory exists. Hence deleting it to recreate it");
783 if (!fs.delete(mergesdir, true)) {
784 throw new IOException("Failed deletion of " + mergesdir
785 + " before creating them again.");
786 }
787 }
788 if (!mkdirs(fs, conf, mergesdir))
789 throw new IOException("Failed create of " + mergesdir);
790 }
791
792
793
794
795
796
797
798
799
800
801
802 Path mergeStoreFile(final HRegionInfo mergedRegion, final String familyName,
803 final StoreFile f, final Path mergedDir)
804 throws IOException {
805 Path referenceDir = new Path(new Path(mergedDir,
806 mergedRegion.getEncodedName()), familyName);
807
808 Reference r = Reference.createTopReference(regionInfoForFs.getStartKey());
809
810
811
812
813 String mergingRegionName = regionInfoForFs.getEncodedName();
814
815
816 Path p = new Path(referenceDir, f.getPath().getName() + "."
817 + mergingRegionName);
818 return r.write(fs, p);
819 }
820
821
822
823
824
825
826
827 void commitMergedRegion(final HRegionInfo mergedRegionInfo) throws IOException {
828 Path regionDir = new Path(this.tableDir, mergedRegionInfo.getEncodedName());
829 Path mergedRegionTmpDir = this.getMergesDir(mergedRegionInfo);
830
831 if (mergedRegionTmpDir != null && fs.exists(mergedRegionTmpDir)) {
832 if (!fs.rename(mergedRegionTmpDir, regionDir)) {
833 throw new IOException("Unable to rename " + mergedRegionTmpDir + " to "
834 + regionDir);
835 }
836 }
837 }
838
839
840
841
842
843
844
845
846
847 void logFileSystemState(final Log LOG) throws IOException {
848 FSUtils.logFileSystemState(fs, this.getRegionDir(), LOG);
849 }
850
851
852
853
854
855
856 private static byte[] getRegionInfoFileContent(final HRegionInfo hri) throws IOException {
857 return hri.toDelimitedByteArray();
858 }
859
860
861
862
863
864
865
866
867 public static HRegionInfo loadRegionInfoFileContent(final FileSystem fs, final Path regionDir)
868 throws IOException {
869 FSDataInputStream in = fs.open(new Path(regionDir, REGION_INFO_FILE));
870 try {
871 return HRegionInfo.parseFrom(in);
872 } finally {
873 in.close();
874 }
875 }
876
877
878
879
880 private static void writeRegionInfoFileContent(final Configuration conf, final FileSystem fs,
881 final Path regionInfoFile, final byte[] content) throws IOException {
882
883 FsPermission perms = FSUtils.getFilePermissions(fs, conf, HConstants.DATA_FILE_UMASK_KEY);
884
885 FSDataOutputStream out = FSUtils.create(conf, fs, regionInfoFile, perms, null);
886 try {
887 out.write(content);
888 } finally {
889 out.close();
890 }
891 }
892
893
894
895
896
897 void checkRegionInfoOnFilesystem() throws IOException {
898
899
900
901
902
903 byte[] content = getRegionInfoFileContent(regionInfoForFs);
904
905
906
907
908 try {
909 FileStatus status = fs.getFileStatus(getRegionDir());
910 } catch (FileNotFoundException e) {
911 LOG.warn(getRegionDir() + " doesn't exist for region: " + regionInfoForFs.getEncodedName() +
912 " on table " + regionInfo.getTable());
913 }
914
915 try {
916 Path regionInfoFile = new Path(getRegionDir(), REGION_INFO_FILE);
917 FileStatus status = fs.getFileStatus(regionInfoFile);
918 if (status != null && status.getLen() == content.length) {
919
920
921 return;
922 }
923
924 LOG.info("Rewriting .regioninfo file at: " + regionInfoFile);
925 if (!fs.delete(regionInfoFile, false)) {
926 throw new IOException("Unable to remove existing " + regionInfoFile);
927 }
928 } catch (FileNotFoundException e) {
929 LOG.warn(REGION_INFO_FILE + " file not found for region: " + regionInfoForFs.getEncodedName() +
930 " on table " + regionInfo.getTable());
931 }
932
933
934 writeRegionInfoOnFilesystem(content, true);
935 }
936
937
938
939
940
941 private void writeRegionInfoOnFilesystem(boolean useTempDir) throws IOException {
942 byte[] content = getRegionInfoFileContent(regionInfoForFs);
943 writeRegionInfoOnFilesystem(content, useTempDir);
944 }
945
946
947
948
949
950
951 private void writeRegionInfoOnFilesystem(final byte[] regionInfoContent,
952 final boolean useTempDir) throws IOException {
953 Path regionInfoFile = new Path(getRegionDir(), REGION_INFO_FILE);
954 if (useTempDir) {
955
956
957
958
959
960
961 Path tmpPath = new Path(getTempDir(), REGION_INFO_FILE);
962
963
964
965
966
967 if (FSUtils.isExists(fs, tmpPath)) {
968 FSUtils.delete(fs, tmpPath, true);
969 }
970
971
972 writeRegionInfoFileContent(conf, fs, tmpPath, regionInfoContent);
973
974
975 if (fs.exists(tmpPath) && !rename(tmpPath, regionInfoFile)) {
976 throw new IOException("Unable to rename " + tmpPath + " to " + regionInfoFile);
977 }
978 } else {
979
980 writeRegionInfoFileContent(conf, fs, regionInfoFile, regionInfoContent);
981 }
982 }
983
984
985
986
987
988
989
990
991
992 public static HRegionFileSystem createRegionOnFileSystem(final Configuration conf,
993 final FileSystem fs, final Path tableDir, final HRegionInfo regionInfo) throws IOException {
994 HRegionFileSystem regionFs = new HRegionFileSystem(conf, fs, tableDir, regionInfo);
995
996
997 if (regionInfo.getReplicaId() == HRegionInfo.DEFAULT_REPLICA_ID) {
998 Path regionDir = regionFs.getRegionDir();
999 if (fs.exists(regionDir)) {
1000 LOG.warn("Trying to create a region that already exists on disk: " + regionDir);
1001 throw new IOException("The specified region already exists on disk: " + regionDir);
1002 }
1003
1004
1005 if (!createDirOnFileSystem(fs, conf, regionDir)) {
1006 LOG.warn("Unable to create the region directory: " + regionDir);
1007 throw new IOException("Unable to create region directory: " + regionDir);
1008 }
1009
1010
1011 regionFs.writeRegionInfoOnFilesystem(false);
1012 } else {
1013 if (LOG.isDebugEnabled())
1014 LOG.debug("Skipping creation of .regioninfo file for " + regionInfo);
1015 }
1016 return regionFs;
1017 }
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028 public static HRegionFileSystem openRegionFromFileSystem(final Configuration conf,
1029 final FileSystem fs, final Path tableDir, final HRegionInfo regionInfo, boolean readOnly)
1030 throws IOException {
1031 HRegionFileSystem regionFs = new HRegionFileSystem(conf, fs, tableDir, regionInfo);
1032 Path regionDir = regionFs.getRegionDir();
1033
1034 if (!fs.exists(regionDir)) {
1035 LOG.warn("Trying to open a region that do not exists on disk: " + regionDir);
1036 throw new IOException("The specified region do not exists on disk: " + regionDir);
1037 }
1038
1039 if (!readOnly) {
1040
1041 regionFs.cleanupTempDir();
1042 regionFs.cleanupSplitsDir();
1043 regionFs.cleanupMergesDir();
1044
1045
1046
1047 if (regionInfo.getReplicaId() == HRegionInfo.DEFAULT_REPLICA_ID) {
1048 regionFs.checkRegionInfoOnFilesystem();
1049 } else {
1050 if (LOG.isDebugEnabled()) {
1051 LOG.debug("Skipping creation of .regioninfo file for " + regionInfo);
1052 }
1053 }
1054 }
1055
1056 return regionFs;
1057 }
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067 public static void deleteRegionFromFileSystem(final Configuration conf,
1068 final FileSystem fs, final Path tableDir, final HRegionInfo regionInfo) throws IOException {
1069 HRegionFileSystem regionFs = new HRegionFileSystem(conf, fs, tableDir, regionInfo);
1070 Path regionDir = regionFs.getRegionDir();
1071
1072 if (!fs.exists(regionDir)) {
1073 LOG.warn("Trying to delete a region that do not exists on disk: " + regionDir);
1074 return;
1075 }
1076
1077 if (LOG.isDebugEnabled()) {
1078 LOG.debug("DELETING region " + regionDir);
1079 }
1080
1081
1082 Path rootDir = FSUtils.getRootDir(conf);
1083 HFileArchiver.archiveRegion(fs, rootDir, tableDir, regionDir);
1084
1085
1086 if (!fs.delete(regionDir, true)) {
1087 LOG.warn("Failed delete of " + regionDir);
1088 }
1089 }
1090
1091
1092
1093
1094
1095
1096
1097
1098 boolean createDir(Path dir) throws IOException {
1099 int i = 0;
1100 IOException lastIOE = null;
1101 do {
1102 try {
1103 return mkdirs(fs, conf, dir);
1104 } catch (IOException ioe) {
1105 lastIOE = ioe;
1106 if (fs.exists(dir)) return true;
1107 try {
1108 sleepBeforeRetry("Create Directory", i+1);
1109 } catch (InterruptedException e) {
1110 throw (InterruptedIOException)new InterruptedIOException().initCause(e);
1111 }
1112 }
1113 } while (++i <= hdfsClientRetriesNumber);
1114 throw new IOException("Exception in createDir", lastIOE);
1115 }
1116
1117
1118
1119
1120
1121
1122
1123
1124 boolean rename(Path srcpath, Path dstPath) throws IOException {
1125 IOException lastIOE = null;
1126 int i = 0;
1127 do {
1128 try {
1129 return fs.rename(srcpath, dstPath);
1130 } catch (IOException ioe) {
1131 lastIOE = ioe;
1132 if (!fs.exists(srcpath) && fs.exists(dstPath)) return true;
1133
1134 try {
1135 sleepBeforeRetry("Rename Directory", i+1);
1136 } catch (InterruptedException e) {
1137 throw (InterruptedIOException)new InterruptedIOException().initCause(e);
1138 }
1139 }
1140 } while (++i <= hdfsClientRetriesNumber);
1141
1142 throw new IOException("Exception in rename", lastIOE);
1143 }
1144
1145
1146
1147
1148
1149
1150
1151 boolean deleteDir(Path dir) throws IOException {
1152 IOException lastIOE = null;
1153 int i = 0;
1154 do {
1155 try {
1156 return fs.delete(dir, true);
1157 } catch (IOException ioe) {
1158 lastIOE = ioe;
1159 if (!fs.exists(dir)) return true;
1160
1161 try {
1162 sleepBeforeRetry("Delete Directory", i+1);
1163 } catch (InterruptedException e) {
1164 throw (InterruptedIOException)new InterruptedIOException().initCause(e);
1165 }
1166 }
1167 } while (++i <= hdfsClientRetriesNumber);
1168
1169 throw new IOException("Exception in DeleteDir", lastIOE);
1170 }
1171
1172
1173
1174
1175 private void sleepBeforeRetry(String msg, int sleepMultiplier) throws InterruptedException {
1176 sleepBeforeRetry(msg, sleepMultiplier, baseSleepBeforeRetries, hdfsClientRetriesNumber);
1177 }
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189 private static boolean createDirOnFileSystem(FileSystem fs, Configuration conf, Path dir)
1190 throws IOException {
1191 int i = 0;
1192 IOException lastIOE = null;
1193 int hdfsClientRetriesNumber = conf.getInt("hdfs.client.retries.number",
1194 DEFAULT_HDFS_CLIENT_RETRIES_NUMBER);
1195 int baseSleepBeforeRetries = conf.getInt("hdfs.client.sleep.before.retries",
1196 DEFAULT_BASE_SLEEP_BEFORE_RETRIES);
1197 do {
1198 try {
1199 return fs.mkdirs(dir);
1200 } catch (IOException ioe) {
1201 lastIOE = ioe;
1202 if (fs.exists(dir)) return true;
1203 try {
1204 sleepBeforeRetry("Create Directory", i+1, baseSleepBeforeRetries, hdfsClientRetriesNumber);
1205 } catch (InterruptedException e) {
1206 throw (InterruptedIOException)new InterruptedIOException().initCause(e);
1207 }
1208 }
1209 } while (++i <= hdfsClientRetriesNumber);
1210
1211 throw new IOException("Exception in createDir", lastIOE);
1212 }
1213
1214
1215
1216
1217
1218 private static void sleepBeforeRetry(String msg, int sleepMultiplier, int baseSleepBeforeRetries,
1219 int hdfsClientRetriesNumber) throws InterruptedException {
1220 if (sleepMultiplier > hdfsClientRetriesNumber) {
1221 if (LOG.isDebugEnabled()) {
1222 LOG.debug(msg + ", retries exhausted");
1223 }
1224 return;
1225 }
1226 if (LOG.isDebugEnabled()) {
1227 LOG.debug(msg + ", sleeping " + baseSleepBeforeRetries + " times " + sleepMultiplier);
1228 }
1229 Thread.sleep((long)baseSleepBeforeRetries * sleepMultiplier);
1230 }
1231 }