1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.hadoop.hbase.util;
20
21 import java.io.FileNotFoundException;
22 import java.io.IOException;
23 import java.io.InterruptedIOException;
24 import java.lang.reflect.InvocationTargetException;
25
26 import org.apache.commons.logging.Log;
27 import org.apache.commons.logging.LogFactory;
28 import org.apache.hadoop.conf.Configuration;
29 import org.apache.hadoop.fs.FSDataOutputStream;
30 import org.apache.hadoop.fs.FileSystem;
31 import org.apache.hadoop.fs.Path;
32 import org.apache.hadoop.hbase.RemoteExceptionHandler;
33 import org.apache.hadoop.hdfs.DistributedFileSystem;
34 import org.apache.hadoop.hdfs.protocol.AlreadyBeingCreatedException;
35 import org.apache.hadoop.hdfs.server.namenode.LeaseExpiredException;
36
37
38
39
40
41 public class FSHDFSUtils extends FSUtils{
42 private static final Log LOG = LogFactory.getLog(FSHDFSUtils.class);
43
44
45
46
47
48
49
50
51
52 public static final long LEASE_SOFTLIMIT_PERIOD = 60 * 1000;
53
54 public void recoverFileLease(final FileSystem fs, final Path p, Configuration conf)
55 throws IOException{
56 if (!isAppendSupported(conf)) {
57 LOG.warn("Running on HDFS without append enabled may result in data loss");
58 return;
59 }
60
61
62 if (!(fs instanceof DistributedFileSystem)) {
63 return;
64 }
65 LOG.info("Recovering file " + p);
66 long startWaiting = System.currentTimeMillis();
67
68
69 boolean recovered = false;
70 while (!recovered) {
71 try {
72 try {
73 if (fs instanceof DistributedFileSystem) {
74 DistributedFileSystem dfs = (DistributedFileSystem)fs;
75 DistributedFileSystem.class.getMethod("recoverLease",
76 new Class[] {Path.class}).invoke(dfs, p);
77 } else {
78 throw new Exception("Not a DistributedFileSystem");
79 }
80 } catch (InvocationTargetException ite) {
81
82 throw (IOException) ite.getCause();
83 } catch (Exception e) {
84 LOG.debug("Failed fs.recoverLease invocation, " + e.toString() +
85 ", trying fs.append instead");
86 FSDataOutputStream out = fs.append(p);
87 out.close();
88 }
89 recovered = true;
90 } catch (IOException e) {
91 e = RemoteExceptionHandler.checkIOException(e);
92 if (e instanceof AlreadyBeingCreatedException) {
93
94
95
96
97 long waitedFor = System.currentTimeMillis() - startWaiting;
98 if (waitedFor > LEASE_SOFTLIMIT_PERIOD) {
99 LOG.warn("Waited " + waitedFor + "ms for lease recovery on " + p +
100 ":" + e.getMessage());
101 }
102 } else if (e instanceof LeaseExpiredException &&
103 e.getMessage().contains("File does not exist")) {
104
105 throw new FileNotFoundException(
106 "The given HLog wasn't found at " + p.toString());
107 } else {
108 throw new IOException("Failed to open " + p + " for append", e);
109 }
110 }
111 try {
112 Thread.sleep(1000);
113 } catch (InterruptedException ex) {
114 new InterruptedIOException().initCause(ex);
115 }
116 }
117 LOG.info("Finished lease recover attempt for " + p);
118 }
119 }