1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.hadoop.hbase.mapreduce;
20
21 import java.io.DataInput;
22 import java.io.DataOutput;
23 import java.io.IOException;
24 import java.util.Arrays;
25
26 import org.apache.commons.logging.Log;
27 import org.apache.commons.logging.LogFactory;
28 import org.apache.hadoop.hbase.classification.InterfaceAudience;
29 import org.apache.hadoop.hbase.classification.InterfaceStability;
30 import org.apache.hadoop.hbase.TableName;
31 import org.apache.hadoop.hbase.HConstants;
32 import org.apache.hadoop.hbase.client.Scan;
33 import org.apache.hadoop.hbase.util.Bytes;
34 import org.apache.hadoop.io.Writable;
35 import org.apache.hadoop.io.WritableUtils;
36 import org.apache.hadoop.mapreduce.InputSplit;
37
38
39
40
41
42 @InterfaceAudience.Public
43 @InterfaceStability.Evolving
44 public class TableSplit extends InputSplit
45 implements Writable, Comparable<TableSplit> {
46 public static final Log LOG = LogFactory.getLog(TableSplit.class);
47
48
49
50 enum Version {
51 UNVERSIONED(0),
52
53 INITIAL(-1);
54
55 final int code;
56 static final Version[] byCode;
57 static {
58 byCode = Version.values();
59 for (int i = 0; i < byCode.length; i++) {
60 if (byCode[i].code != -1 * i) {
61 throw new AssertionError("Values in this enum should be descending by one");
62 }
63 }
64 }
65
66 Version(int code) {
67 this.code = code;
68 }
69
70 boolean atLeast(Version other) {
71 return code <= other.code;
72 }
73
74 static Version fromCode(int code) {
75 return byCode[code * -1];
76 }
77 }
78
79 private static final Version VERSION = Version.INITIAL;
80 private TableName tableName;
81 private byte [] startRow;
82 private byte [] endRow;
83 private String regionLocation;
84 private String scan = "";
85 private long length;
86
87
88 public TableSplit() {
89 this((TableName)null, null, HConstants.EMPTY_BYTE_ARRAY,
90 HConstants.EMPTY_BYTE_ARRAY, "");
91 }
92
93
94
95
96 @Deprecated
97 public TableSplit(final byte [] tableName, Scan scan, byte [] startRow, byte [] endRow,
98 final String location) {
99 this(TableName.valueOf(tableName), scan, startRow, endRow, location);
100 }
101
102
103
104
105
106
107
108
109
110
111
112 public TableSplit(TableName tableName, Scan scan, byte [] startRow, byte [] endRow,
113 final String location) {
114 this(tableName, scan, startRow, endRow, location, 0L);
115 }
116
117
118
119
120
121
122
123
124
125
126 public TableSplit(TableName tableName, Scan scan, byte [] startRow, byte [] endRow,
127 final String location, long length) {
128 this.tableName = tableName;
129 try {
130 this.scan =
131 (null == scan) ? "" : TableMapReduceUtil.convertScanToString(scan);
132 } catch (IOException e) {
133 LOG.warn("Failed to convert Scan to String", e);
134 }
135 this.startRow = startRow;
136 this.endRow = endRow;
137 this.regionLocation = location;
138 this.length = length;
139 }
140
141
142
143
144 @Deprecated
145 public TableSplit(final byte [] tableName, byte[] startRow, byte[] endRow,
146 final String location) {
147 this(TableName.valueOf(tableName), startRow, endRow, location);
148 }
149
150
151
152
153
154
155
156
157
158 public TableSplit(TableName tableName, byte[] startRow, byte[] endRow,
159 final String location) {
160 this(tableName, null, startRow, endRow, location);
161 }
162
163
164
165
166
167
168
169
170
171
172 public TableSplit(TableName tableName, byte[] startRow, byte[] endRow,
173 final String location, long length) {
174 this(tableName, null, startRow, endRow, location, length);
175 }
176
177
178
179
180
181
182
183 public Scan getScan() throws IOException {
184 return TableMapReduceUtil.convertStringToScan(this.scan);
185 }
186
187
188
189
190
191
192 public byte [] getTableName() {
193 return tableName.getName();
194 }
195
196
197
198
199
200
201 public TableName getTable() {
202
203
204
205 return tableName;
206 }
207
208
209
210
211
212
213 public byte [] getStartRow() {
214 return startRow;
215 }
216
217
218
219
220
221
222 public byte [] getEndRow() {
223 return endRow;
224 }
225
226
227
228
229
230
231 public String getRegionLocation() {
232 return regionLocation;
233 }
234
235
236
237
238
239
240
241 @Override
242 public String[] getLocations() {
243 return new String[] {regionLocation};
244 }
245
246
247
248
249
250
251
252 @Override
253 public long getLength() {
254 return length;
255 }
256
257
258
259
260
261
262
263 @Override
264 public void readFields(DataInput in) throws IOException {
265 Version version = Version.UNVERSIONED;
266
267
268
269
270
271
272
273
274 int len = WritableUtils.readVInt(in);
275 if (len < 0) {
276
277 version = Version.fromCode(len);
278 len = WritableUtils.readVInt(in);
279 }
280 byte[] tableNameBytes = new byte[len];
281 in.readFully(tableNameBytes);
282 tableName = TableName.valueOf(tableNameBytes);
283 startRow = Bytes.readByteArray(in);
284 endRow = Bytes.readByteArray(in);
285 regionLocation = Bytes.toString(Bytes.readByteArray(in));
286 if (version.atLeast(Version.INITIAL)) {
287 scan = Bytes.toString(Bytes.readByteArray(in));
288 }
289 length = WritableUtils.readVLong(in);
290 }
291
292
293
294
295
296
297
298 @Override
299 public void write(DataOutput out) throws IOException {
300 WritableUtils.writeVInt(out, VERSION.code);
301 Bytes.writeByteArray(out, tableName.getName());
302 Bytes.writeByteArray(out, startRow);
303 Bytes.writeByteArray(out, endRow);
304 Bytes.writeByteArray(out, Bytes.toBytes(regionLocation));
305 Bytes.writeByteArray(out, Bytes.toBytes(scan));
306 WritableUtils.writeVLong(out, length);
307 }
308
309
310
311
312
313
314
315 @Override
316 public String toString() {
317 StringBuilder sb = new StringBuilder();
318 sb.append("HBase table split(");
319 sb.append("table name: ").append(tableName);
320 sb.append(", scan: ").append(scan);
321 sb.append(", start row: ").append(Bytes.toStringBinary(startRow));
322 sb.append(", end row: ").append(Bytes.toStringBinary(endRow));
323 sb.append(", region location: ").append(regionLocation);
324 sb.append(")");
325 return sb.toString();
326 }
327
328
329
330
331
332
333
334
335 @Override
336 public int compareTo(TableSplit split) {
337
338
339 int tableNameComparison =
340 getTable().compareTo(split.getTable());
341 return tableNameComparison != 0 ? tableNameComparison : Bytes.compareTo(
342 getStartRow(), split.getStartRow());
343 }
344
345 @Override
346 public boolean equals(Object o) {
347 if (o == null || !(o instanceof TableSplit)) {
348 return false;
349 }
350 return tableName.equals(((TableSplit)o).tableName) &&
351 Bytes.equals(startRow, ((TableSplit)o).startRow) &&
352 Bytes.equals(endRow, ((TableSplit)o).endRow) &&
353 regionLocation.equals(((TableSplit)o).regionLocation);
354 }
355
356 @Override
357 public int hashCode() {
358 int result = tableName != null ? tableName.hashCode() : 0;
359 result = 31 * result + (scan != null ? scan.hashCode() : 0);
360 result = 31 * result + (startRow != null ? Arrays.hashCode(startRow) : 0);
361 result = 31 * result + (endRow != null ? Arrays.hashCode(endRow) : 0);
362 result = 31 * result + (regionLocation != null ? regionLocation.hashCode() : 0);
363 return result;
364 }
365 }