1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.hadoop.hbase;
20
21 import java.nio.ByteBuffer;
22 import java.util.ArrayList;
23 import java.util.List;
24
25 import org.apache.hadoop.classification.InterfaceAudience;
26 import org.apache.hadoop.hbase.util.ByteBufferUtils;
27 import org.apache.hadoop.hbase.util.Bytes;
28 import org.apache.hadoop.hbase.util.IterableUtils;
29 import org.apache.hadoop.hbase.util.SimpleByteRange;
30 import org.apache.hadoop.io.WritableUtils;
31
32 import com.google.common.base.Function;
33 import com.google.common.collect.Lists;
34
35
36
37
38 @InterfaceAudience.Private
39 public class KeyValueUtil {
40
41
42
43 public static int length(final Cell cell) {
44 return (int) (KeyValue.getKeyValueDataStructureSize(cell.getRowLength(),
45 cell.getFamilyLength(), cell.getQualifierLength(), cell.getValueLength(),
46 cell.getTagsLengthUnsigned()));
47 }
48
49 protected static int keyLength(final Cell cell) {
50 return (int)KeyValue.getKeyDataStructureSize(cell.getRowLength(), cell.getFamilyLength(),
51 cell.getQualifierLength());
52 }
53
54 public static int lengthWithMvccVersion(final KeyValue kv, final boolean includeMvccVersion) {
55 int length = kv.getLength();
56 if (includeMvccVersion) {
57 length += WritableUtils.getVIntSize(kv.getMvccVersion());
58 }
59 return length;
60 }
61
62 public static int totalLengthWithMvccVersion(final Iterable<? extends KeyValue> kvs,
63 final boolean includeMvccVersion) {
64 int length = 0;
65 for (KeyValue kv : IterableUtils.nullSafe(kvs)) {
66 length += lengthWithMvccVersion(kv, includeMvccVersion);
67 }
68 return length;
69 }
70
71
72
73
74 public static KeyValue copyToNewKeyValue(final Cell cell) {
75 byte[] bytes = copyToNewByteArray(cell);
76 KeyValue kvCell = new KeyValue(bytes, 0, bytes.length);
77 kvCell.setMvccVersion(cell.getMvccVersion());
78 return kvCell;
79 }
80
81 public static ByteBuffer copyKeyToNewByteBuffer(final Cell cell) {
82 byte[] bytes = new byte[keyLength(cell)];
83 appendKeyToByteArrayWithoutValue(cell, bytes, 0);
84 ByteBuffer buffer = ByteBuffer.wrap(bytes);
85 buffer.position(buffer.limit());
86 return buffer;
87 }
88
89 public static byte[] copyToNewByteArray(final Cell cell) {
90 int v1Length = length(cell);
91 byte[] backingBytes = new byte[v1Length];
92 appendToByteArray(cell, backingBytes, 0);
93 return backingBytes;
94 }
95
96 protected static int appendKeyToByteArrayWithoutValue(final Cell cell, final byte[] output,
97 final int offset) {
98 int nextOffset = offset;
99 nextOffset = Bytes.putShort(output, nextOffset, cell.getRowLength());
100 nextOffset = CellUtil.copyRowTo(cell, output, nextOffset);
101 nextOffset = Bytes.putByte(output, nextOffset, cell.getFamilyLength());
102 nextOffset = CellUtil.copyFamilyTo(cell, output, nextOffset);
103 nextOffset = CellUtil.copyQualifierTo(cell, output, nextOffset);
104 nextOffset = Bytes.putLong(output, nextOffset, cell.getTimestamp());
105 nextOffset = Bytes.putByte(output, nextOffset, cell.getTypeByte());
106 return nextOffset;
107 }
108
109
110
111
112 public static int appendToByteArray(final Cell cell, final byte[] output, final int offset) {
113 int pos = offset;
114 pos = Bytes.putInt(output, pos, keyLength(cell));
115 pos = Bytes.putInt(output, pos, cell.getValueLength());
116 pos = appendKeyToByteArrayWithoutValue(cell, output, pos);
117 pos = CellUtil.copyValueTo(cell, output, pos);
118 if ((cell.getTagsLengthUnsigned() > 0)) {
119 pos = Bytes.putAsShort(output, pos, cell.getTagsLengthUnsigned());
120 pos = CellUtil.copyTagTo(cell, output, pos);
121 }
122 return pos;
123 }
124
125 public static ByteBuffer copyToNewByteBuffer(final Cell cell) {
126 byte[] bytes = new byte[length(cell)];
127 appendToByteArray(cell, bytes, 0);
128 ByteBuffer buffer = ByteBuffer.wrap(bytes);
129 buffer.position(buffer.limit());
130 return buffer;
131 }
132
133 public static void appendToByteBuffer(final ByteBuffer bb, final KeyValue kv,
134 final boolean includeMvccVersion) {
135
136 bb.limit(bb.position() + kv.getLength());
137 bb.put(kv.getBuffer(), kv.getOffset(), kv.getLength());
138 if (includeMvccVersion) {
139 int numMvccVersionBytes = WritableUtils.getVIntSize(kv.getMvccVersion());
140 ByteBufferUtils.extendLimit(bb, numMvccVersionBytes);
141 ByteBufferUtils.writeVLong(bb, kv.getMvccVersion());
142 }
143 }
144
145
146
147
148
149
150
151
152
153
154
155 public static KeyValue nextShallowCopy(final ByteBuffer bb, final boolean includesMvccVersion,
156 boolean includesTags) {
157 if (bb.isDirect()) {
158 throw new IllegalArgumentException("only supports heap buffers");
159 }
160 if (bb.remaining() < 1) {
161 return null;
162 }
163 KeyValue keyValue = null;
164 int underlyingArrayOffset = bb.arrayOffset() + bb.position();
165 int keyLength = bb.getInt();
166 int valueLength = bb.getInt();
167 ByteBufferUtils.skip(bb, keyLength + valueLength);
168 int tagsLength = 0;
169 if (includesTags) {
170
171 tagsLength = ((bb.get() & 0xff) << 8) ^ (bb.get() & 0xff);
172 ByteBufferUtils.skip(bb, tagsLength);
173 }
174 int kvLength = (int) KeyValue.getKeyValueDataStructureSize(keyLength, valueLength, tagsLength);
175 keyValue = new KeyValue(bb.array(), underlyingArrayOffset, kvLength);
176 if (includesMvccVersion) {
177 long mvccVersion = ByteBufferUtils.readVLong(bb);
178 keyValue.setMvccVersion(mvccVersion);
179 }
180 return keyValue;
181 }
182
183
184
185
186
187
188
189 public static KeyValue createFirstKeyInNextRow(final Cell in){
190 byte[] nextRow = new byte[in.getRowLength() + 1];
191 System.arraycopy(in.getRowArray(), in.getRowOffset(), nextRow, 0, in.getRowLength());
192 nextRow[nextRow.length - 1] = 0;
193 return KeyValue.createFirstOnRow(nextRow);
194 }
195
196
197
198
199 public static KeyValue createFirstKeyInIncrementedRow(final Cell in){
200 byte[] thisRow = new SimpleByteRange(in.getRowArray(), in.getRowOffset(), in.getRowLength())
201 .deepCopyToNewArray();
202 byte[] nextRow = Bytes.unsignedCopyAndIncrement(thisRow);
203 return KeyValue.createFirstOnRow(nextRow);
204 }
205
206
207
208
209
210
211
212
213 public static KeyValue previousKey(final KeyValue in) {
214 return KeyValue.createFirstOnRow(CellUtil.cloneRow(in), CellUtil.cloneFamily(in),
215 CellUtil.cloneQualifier(in), in.getTimestamp() - 1);
216 }
217
218
219
220
221
222
223
224 public static KeyValue ensureKeyValue(final Cell cell) {
225 if (cell == null) return null;
226 return cell instanceof KeyValue? (KeyValue)cell: copyToNewKeyValue(cell);
227 }
228
229 public static List<KeyValue> ensureKeyValues(List<Cell> cells) {
230 List<KeyValue> lazyList = Lists.transform(cells, new Function<Cell, KeyValue>() {
231 public KeyValue apply(Cell arg0) {
232 return KeyValueUtil.ensureKeyValue(arg0);
233 }
234 });
235 return new ArrayList<KeyValue>(lazyList);
236 }
237 }