Skip to content

Commit 1ae1c62

Browse files
committed
OMID-271 Support HBase 3
build with -Dhbase.version=3.0.0-beta-2-SNAPSHOT
1 parent 9cf86fe commit 1ae1c62

File tree

14 files changed

+646
-56
lines changed

14 files changed

+646
-56
lines changed
Lines changed: 363 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,363 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS,
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*/
18+
package org.apache.omid.transaction;
19+
20+
import org.apache.hadoop.hbase.Cell;
21+
import org.apache.hadoop.hbase.CellUtil;
22+
import org.apache.hadoop.hbase.ExtendedCell;
23+
import org.apache.hadoop.hbase.HConstants;
24+
import org.apache.hadoop.hbase.KeyValue;
25+
import org.apache.hadoop.hbase.PrivateCellUtil;
26+
import org.apache.hadoop.hbase.util.Bytes;
27+
import org.apache.hadoop.hbase.util.ClassSize;
28+
import static org.apache.hadoop.hbase.HConstants.EMPTY_BYTE_ARRAY;
29+
30+
/**
31+
* This copies the code necessary for ensureKeyValue from KeyvalueUtil and
32+
* createFirstOnRow in PrivateCellUtil in HBase 3+. The signature changes
33+
* between HBase 3 and 2, which results in ensureKeyValue only working when Omid
34+
* is running with the same HBase version (2/3) as it was compiled with. By
35+
* copying the code here, we can work around this problem.
36+
*/
37+
public class OmidCellUtil {
38+
39+
/**
40+
* @return <code>cell</code> if it is an object of class {@link KeyValue} else
41+
* we will return a new {@link KeyValue} instance made from
42+
* <code>cell</code> Note: Even if the cell is an object of any of the
43+
* subclass of {@link KeyValue}, we will create a new {@link KeyValue}
44+
* object wrapping same buffer. This API is used only with MR based
45+
* tools which expect the type to be exactly KeyValue. That is the
46+
* reason for doing this way.
47+
*/
48+
public static KeyValue ensureKeyValue(final ExtendedCell cell) {
49+
if (cell == null)
50+
return null;
51+
if (cell instanceof KeyValue) {
52+
if (cell.getClass().getName().equals(KeyValue.class.getName())) {
53+
return (KeyValue) cell;
54+
}
55+
// Cell is an Object of any of the sub classes of KeyValue. Make a new KeyValue
56+
// wrapping the
57+
// same byte[]
58+
KeyValue kv = (KeyValue) cell;
59+
KeyValue newKv = new KeyValue(kv.getRowArray(), kv.getOffset(), kv.getLength());
60+
newKv.setSequenceId(kv.getSequenceId());
61+
return newKv;
62+
}
63+
return copyToNewKeyValue(cell);
64+
}
65+
66+
public static KeyValue copyToNewKeyValue(final ExtendedCell cell) {
67+
byte[] bytes = copyToNewByteArray(cell);
68+
KeyValue kvCell = new KeyValue(bytes, 0, bytes.length);
69+
kvCell.setSequenceId(cell.getSequenceId());
70+
return kvCell;
71+
}
72+
73+
public static byte[] copyToNewByteArray(final ExtendedCell cell) {
74+
int v1Length = cell.getSerializedSize();
75+
byte[] backingBytes = new byte[v1Length];
76+
appendToByteArray(cell, backingBytes, 0, true);
77+
return backingBytes;
78+
}
79+
80+
public static int appendToByteArray(ExtendedCell cell, byte[] output, int offset, boolean withTags) {
81+
int pos = offset;
82+
pos = Bytes.putInt(output, pos, keyLength(cell));
83+
pos = Bytes.putInt(output, pos, cell.getValueLength());
84+
pos = appendKeyTo(cell, output, pos);
85+
pos = CellUtil.copyValueTo(cell, output, pos);
86+
if (withTags && (cell.getTagsLength() > 0)) {
87+
pos = Bytes.putAsShort(output, pos, cell.getTagsLength());
88+
pos = PrivateCellUtil.copyTagsTo(cell, output, pos);
89+
}
90+
return pos;
91+
}
92+
93+
public static int length(short rlen, byte flen, int qlen, int vlen, int tlen, boolean withTags) {
94+
if (withTags) {
95+
return (int) KeyValue.getKeyValueDataStructureSize(rlen, flen, qlen, vlen, tlen);
96+
}
97+
return (int) KeyValue.getKeyValueDataStructureSize(rlen, flen, qlen, vlen);
98+
}
99+
100+
/**
101+
* Returns number of bytes this cell's key part would have been used if
102+
* serialized as in {@link KeyValue}. Key includes rowkey, family, qualifier,
103+
* timestamp and type.
104+
*
105+
* @return the key length
106+
*/
107+
public static int keyLength(final Cell cell) {
108+
return keyLength(cell.getRowLength(), cell.getFamilyLength(), cell.getQualifierLength());
109+
}
110+
111+
private static int keyLength(short rlen, byte flen, int qlen) {
112+
return (int) KeyValue.getKeyDataStructureSize(rlen, flen, qlen);
113+
}
114+
115+
public static int appendKeyTo(final ExtendedCell cell, final byte[] output, final int offset) {
116+
int nextOffset = offset;
117+
nextOffset = Bytes.putShort(output, nextOffset, cell.getRowLength());
118+
nextOffset = CellUtil.copyRowTo(cell, output, nextOffset);
119+
nextOffset = Bytes.putByte(output, nextOffset, cell.getFamilyLength());
120+
nextOffset = CellUtil.copyFamilyTo(cell, output, nextOffset);
121+
nextOffset = CellUtil.copyQualifierTo(cell, output, nextOffset);
122+
nextOffset = Bytes.putLong(output, nextOffset, cell.getTimestamp());
123+
nextOffset = Bytes.putByte(output, nextOffset, cell.getTypeByte());
124+
return nextOffset;
125+
}
126+
127+
// =========================================================================================
128+
// Code below is copied from PrivateCellUtil
129+
// =========================================================================================
130+
131+
public static ExtendedCell createFirstOnRow(final byte[] row, int roffset, short rlength,
132+
final byte[] family, int foffset, byte flength, final byte[] col, int coffset, int clength) {
133+
return new FirstOnRowColCell(row, roffset, rlength, family, foffset, flength, col, coffset,
134+
clength);
135+
}
136+
137+
138+
/**
139+
* These cells are used in reseeks/seeks to improve the read performance. They are not real cells
140+
* that are returned back to the clients
141+
*/
142+
private static abstract class EmptyCell implements ExtendedCell {
143+
144+
@Override
145+
public void setSequenceId(long seqId) {
146+
// Fake cells don't need seqId, so leaving it as a noop.
147+
}
148+
149+
@Override
150+
public void setTimestamp(long ts) {
151+
// Fake cells can't be changed timestamp, so leaving it as a noop.
152+
}
153+
154+
@Override
155+
public void setTimestamp(byte[] ts) {
156+
// Fake cells can't be changed timestamp, so leaving it as a noop.
157+
}
158+
159+
@Override
160+
public byte[] getRowArray() {
161+
return EMPTY_BYTE_ARRAY;
162+
}
163+
164+
@Override
165+
public int getRowOffset() {
166+
return 0;
167+
}
168+
169+
@Override
170+
public short getRowLength() {
171+
return 0;
172+
}
173+
174+
@Override
175+
public byte[] getFamilyArray() {
176+
return EMPTY_BYTE_ARRAY;
177+
}
178+
179+
@Override
180+
public int getFamilyOffset() {
181+
return 0;
182+
}
183+
184+
@Override
185+
public byte getFamilyLength() {
186+
return 0;
187+
}
188+
189+
@Override
190+
public byte[] getQualifierArray() {
191+
return EMPTY_BYTE_ARRAY;
192+
}
193+
194+
@Override
195+
public int getQualifierOffset() {
196+
return 0;
197+
}
198+
199+
@Override
200+
public int getQualifierLength() {
201+
return 0;
202+
}
203+
204+
@Override
205+
public long getSequenceId() {
206+
return 0;
207+
}
208+
209+
@Override
210+
public byte[] getValueArray() {
211+
return EMPTY_BYTE_ARRAY;
212+
}
213+
214+
@Override
215+
public int getValueOffset() {
216+
return 0;
217+
}
218+
219+
@Override
220+
public int getValueLength() {
221+
return 0;
222+
}
223+
224+
@Override
225+
public byte[] getTagsArray() {
226+
return EMPTY_BYTE_ARRAY;
227+
}
228+
229+
@Override
230+
public int getTagsOffset() {
231+
return 0;
232+
}
233+
234+
@Override
235+
public int getTagsLength() {
236+
return 0;
237+
}
238+
}
239+
240+
241+
private static class FirstOnRowCell extends EmptyCell {
242+
// @formatter:off
243+
private static final int FIXED_HEAPSIZE =
244+
ClassSize.OBJECT // object
245+
+ ClassSize.REFERENCE // row array
246+
+ Bytes.SIZEOF_INT // row offset
247+
+ Bytes.SIZEOF_SHORT; // row length
248+
// @formatter:on
249+
private final byte[] rowArray;
250+
private final int roffset;
251+
private final short rlength;
252+
253+
public FirstOnRowCell(final byte[] row, int roffset, short rlength) {
254+
this.rowArray = row;
255+
this.roffset = roffset;
256+
this.rlength = rlength;
257+
}
258+
259+
@Override
260+
public long heapSize() {
261+
return ClassSize.align(FIXED_HEAPSIZE)
262+
// array overhead
263+
+ (rlength == 0 ? ClassSize.sizeOfByteArray(rlength) : rlength);
264+
}
265+
266+
@Override
267+
public byte[] getRowArray() {
268+
return this.rowArray;
269+
}
270+
271+
@Override
272+
public int getRowOffset() {
273+
return this.roffset;
274+
}
275+
276+
@Override
277+
public short getRowLength() {
278+
return this.rlength;
279+
}
280+
281+
@Override
282+
public long getTimestamp() {
283+
return HConstants.LATEST_TIMESTAMP;
284+
}
285+
286+
@Override
287+
public byte getTypeByte() {
288+
return KeyValue.Type.Maximum.getCode();
289+
}
290+
291+
@Override
292+
public Cell.Type getType() {
293+
throw new UnsupportedOperationException();
294+
}
295+
}
296+
297+
298+
private static class FirstOnRowColCell extends FirstOnRowCell {
299+
// @formatter:off
300+
private static final long FIXED_HEAPSIZE = (long) FirstOnRowCell.FIXED_HEAPSIZE
301+
+ Bytes.SIZEOF_BYTE // flength
302+
+ Bytes.SIZEOF_INT * 3 // foffset, qoffset, qlength
303+
+ ClassSize.REFERENCE * 2; // fArray, qArray
304+
// @formatter:on
305+
private final byte[] fArray;
306+
private final int foffset;
307+
private final byte flength;
308+
private final byte[] qArray;
309+
private final int qoffset;
310+
private final int qlength;
311+
312+
public FirstOnRowColCell(byte[] rArray, int roffset, short rlength, byte[] fArray, int foffset,
313+
byte flength, byte[] qArray, int qoffset, int qlength) {
314+
super(rArray, roffset, rlength);
315+
this.fArray = fArray;
316+
this.foffset = foffset;
317+
this.flength = flength;
318+
this.qArray = qArray;
319+
this.qoffset = qoffset;
320+
this.qlength = qlength;
321+
}
322+
323+
@Override
324+
public long heapSize() {
325+
return ClassSize.align(FIXED_HEAPSIZE)
326+
// array overhead
327+
+ (flength == 0 ? ClassSize.sizeOfByteArray(flength) : flength)
328+
+ (qlength == 0 ? ClassSize.sizeOfByteArray(qlength) : qlength);
329+
}
330+
331+
@Override
332+
public byte[] getFamilyArray() {
333+
return this.fArray;
334+
}
335+
336+
@Override
337+
public int getFamilyOffset() {
338+
return this.foffset;
339+
}
340+
341+
@Override
342+
public byte getFamilyLength() {
343+
return this.flength;
344+
}
345+
346+
@Override
347+
public byte[] getQualifierArray() {
348+
return this.qArray;
349+
}
350+
351+
@Override
352+
public int getQualifierOffset() {
353+
return this.qoffset;
354+
}
355+
356+
@Override
357+
public int getQualifierLength() {
358+
return this.qlength;
359+
}
360+
}
361+
362+
363+
}

0 commit comments

Comments
 (0)