1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 package org.apache.hadoop.hbase.regionserver.wal;
22
23 import java.io.IOException;
24 import java.lang.Class;
25 import java.lang.reflect.Constructor;
26 import java.lang.reflect.Field;
27
28 import org.apache.hadoop.conf.Configuration;
29 import org.apache.hadoop.fs.FSDataInputStream;
30 import org.apache.hadoop.fs.FileSystem;
31 import org.apache.hadoop.fs.Path;
32 import org.apache.hadoop.hbase.regionserver.wal.HLog;
33 import org.apache.hadoop.hbase.regionserver.wal.WALEdit;
34 import org.apache.hadoop.io.SequenceFile;
35 import org.mortbay.log.Log;
36
37 public class SequenceFileLogReader implements HLog.Reader {
38
39
40
41
42
43
44
45
46
47
48
49
50
51 private static class WALReader extends SequenceFile.Reader {
52
53 WALReader(final FileSystem fs, final Path p, final Configuration c)
54 throws IOException {
55 super(fs, p, c);
56
57 }
58
59 @Override
60 protected FSDataInputStream openFile(FileSystem fs, Path file,
61 int bufferSize, long length)
62 throws IOException {
63 return new WALReaderFSDataInputStream(super.openFile(fs, file,
64 bufferSize, length), length);
65 }
66
67
68
69
70 static class WALReaderFSDataInputStream extends FSDataInputStream {
71 private boolean firstGetPosInvocation = true;
72 private long length;
73
74 WALReaderFSDataInputStream(final FSDataInputStream is, final long l)
75 throws IOException {
76 super(is);
77 this.length = l;
78 }
79
80 @Override
81 public long getPos() throws IOException {
82 if (this.firstGetPosInvocation) {
83 this.firstGetPosInvocation = false;
84
85
86
87
88 long available = this.in.available();
89
90
91 return available >= this.length? available - this.length: this.length;
92 }
93 return super.getPos();
94 }
95 }
96 }
97
98 Configuration conf;
99 WALReader reader;
100
101 Path path;
102 int edit = 0;
103 long entryStart = 0;
104
105 public SequenceFileLogReader() { }
106
107 @Override
108 public void init(FileSystem fs, Path path, Configuration conf)
109 throws IOException {
110 this.conf = conf;
111 this.path = path;
112 reader = new WALReader(fs, path, conf);
113 }
114
115 @Override
116 public void close() throws IOException {
117 try {
118 reader.close();
119 } catch (IOException ioe) {
120 throw addFileInfoToException(ioe);
121 }
122 }
123
124 @Override
125 public HLog.Entry next() throws IOException {
126 return next(null);
127 }
128
129 @Override
130 public HLog.Entry next(HLog.Entry reuse) throws IOException {
131 this.entryStart = this.reader.getPosition();
132 HLog.Entry e = reuse;
133 if (e == null) {
134 HLogKey key = HLog.newKey(conf);
135 WALEdit val = new WALEdit();
136 e = new HLog.Entry(key, val);
137 }
138 boolean b = false;
139 try {
140 b = this.reader.next(e.getKey(), e.getEdit());
141 } catch (IOException ioe) {
142 throw addFileInfoToException(ioe);
143 }
144 edit++;
145 return b? e: null;
146 }
147
148 @Override
149 public void seek(long pos) throws IOException {
150 try {
151 reader.seek(pos);
152 } catch (IOException ioe) {
153 throw addFileInfoToException(ioe);
154 }
155 }
156
157 @Override
158 public long getPosition() throws IOException {
159 return reader.getPosition();
160 }
161
162 private IOException addFileInfoToException(final IOException ioe)
163 throws IOException {
164 long pos = -1;
165 try {
166 pos = getPosition();
167 } catch (IOException e) {
168 Log.warn("Failed getting position to add to throw", e);
169 }
170
171
172 long end = Long.MAX_VALUE;
173 try {
174 Field fEnd = SequenceFile.Reader.class.getDeclaredField("end");
175 fEnd.setAccessible(true);
176 end = fEnd.getLong(this.reader);
177 } catch(Exception e) {
178
179 String msg = (this.path == null? "": this.path.toString()) +
180 ", entryStart=" + entryStart + ", pos=" + pos +
181 ((end == Long.MAX_VALUE) ? "" : ", end=" + end) +
182 ", edit=" + this.edit;
183
184
185 try {
186 return (IOException) ioe.getClass()
187 .getConstructor(String.class)
188 .newInstance(msg)
189 .initCause(ioe);
190 } catch(Exception e) {
191
192 return ioe;
193 }
194 }