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.SimpleByteRange;
28 import org.apache.hadoop.hbase.util.Bytes;
29 import org.apache.hadoop.hbase.util.IterableUtils;
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(), cell.getFamilyLength(),
45 cell.getQualifierLength(), cell.getValueLength());
46 }
47
48 protected static int keyLength(final Cell cell) {
49 return (int)KeyValue.getKeyDataStructureSize(cell.getRowLength(), cell.getFamilyLength(),
50 cell.getQualifierLength());
51 }
52
53 public static int lengthWithMvccVersion(final KeyValue kv, final boolean includeMvccVersion) {
54 int length = kv.getLength();
55 if (includeMvccVersion) {
56 length += WritableUtils.getVIntSize(kv.getMvccVersion());
57 }
58 return length;
59 }
60
61 public static int totalLengthWithMvccVersion(final Iterable<? extends KeyValue> kvs,
62 final boolean includeMvccVersion) {
63 int length = 0;
64 for (KeyValue kv : IterableUtils.nullSafe(kvs)) {
65 length += lengthWithMvccVersion(kv, includeMvccVersion);
66 }
67 return length;
68 }
69
70
71
72
73 public static KeyValue copyToNewKeyValue(final Cell cell) {
74 KeyValue kvCell = new KeyValue(copyToNewByteArray(cell));
75 kvCell.setMvccVersion(cell.getMvccVersion());
76 return kvCell;
77 }
78
79 public static ByteBuffer copyKeyToNewByteBuffer(final Cell cell) {
80 byte[] bytes = new byte[keyLength(cell)];
81 appendKeyToByteArrayWithoutValue(cell, bytes, 0);
82 ByteBuffer buffer = ByteBuffer.wrap(bytes);
83 buffer.position(buffer.limit());
84 return buffer;
85 }
86
87 public static byte[] copyToNewByteArray(final Cell cell) {
88 int v1Length = length(cell);
89 byte[] backingBytes = new byte[v1Length];
90 appendToByteArray(cell, backingBytes, 0);
91 return backingBytes;
92 }
93
94 protected static int appendKeyToByteArrayWithoutValue(final Cell cell, final byte[] output,
95 final int offset) {
96 int nextOffset = offset;
97 nextOffset = Bytes.putShort(output, nextOffset, cell.getRowLength());
98 nextOffset = CellUtil.copyRowTo(cell, output, nextOffset);
99 nextOffset = Bytes.putByte(output, nextOffset, cell.getFamilyLength());
100 nextOffset = CellUtil.copyFamilyTo(cell, output, nextOffset);
101 nextOffset = CellUtil.copyQualifierTo(cell, output, nextOffset);
102 nextOffset = Bytes.putLong(output, nextOffset, cell.getTimestamp());
103 nextOffset = Bytes.putByte(output, nextOffset, cell.getTypeByte());
104 return nextOffset;
105 }
106
107
108
109
110 public static int appendToByteArray(final Cell cell, final byte[] output, final int offset) {
111 int pos = offset;
112 pos = Bytes.putInt(output, pos, keyLength(cell));
113 pos = Bytes.putInt(output, pos, cell.getValueLength());
114 pos = appendKeyToByteArrayWithoutValue(cell, output, pos);
115 CellUtil.copyValueTo(cell, output, pos);
116 return pos + cell.getValueLength();
117 }
118
119 public static ByteBuffer copyToNewByteBuffer(final Cell cell) {
120 byte[] bytes = new byte[length(cell)];
121 appendToByteArray(cell, bytes, 0);
122 ByteBuffer buffer = ByteBuffer.wrap(bytes);
123 buffer.position(buffer.limit());
124 return buffer;
125 }
126
127 public static void appendToByteBuffer(final ByteBuffer bb, final KeyValue kv,
128 final boolean includeMvccVersion) {
129
130 bb.limit(bb.position() + kv.getLength());
131 bb.put(kv.getBuffer(), kv.getOffset(), kv.getLength());
132 if (includeMvccVersion) {
133 int numMvccVersionBytes = WritableUtils.getVIntSize(kv.getMvccVersion());
134 ByteBufferUtils.extendLimit(bb, numMvccVersionBytes);
135 ByteBufferUtils.writeVLong(bb, kv.getMvccVersion());
136 }
137 }
138
139
140
141
142
143
144
145
146 public static KeyValue nextShallowCopy(final ByteBuffer bb, final boolean includesMvccVersion) {
147 if (bb.isDirect()) {
148 throw new IllegalArgumentException("only supports heap buffers");
149 }
150 if (bb.remaining() < 1) {
151 return null;
152 }
153 int underlyingArrayOffset = bb.arrayOffset() + bb.position();
154 int keyLength = bb.getInt();
155 int valueLength = bb.getInt();
156 int kvLength = KeyValue.KEYVALUE_INFRASTRUCTURE_SIZE + keyLength + valueLength;
157 KeyValue keyValue = new KeyValue(bb.array(), underlyingArrayOffset, kvLength);
158 ByteBufferUtils.skip(bb, keyLength + valueLength);
159 if (includesMvccVersion) {
160 long mvccVersion = ByteBufferUtils.readVLong(bb);
161 keyValue.setMvccVersion(mvccVersion);
162 }
163 return keyValue;
164 }
165
166
167
168
169
170
171
172 public static KeyValue createFirstKeyInNextRow(final Cell in){
173 byte[] nextRow = new byte[in.getRowLength() + 1];
174 System.arraycopy(in.getRowArray(), in.getRowOffset(), nextRow, 0, in.getRowLength());
175 nextRow[nextRow.length - 1] = 0;
176 return KeyValue.createFirstOnRow(nextRow);
177 }
178
179
180
181
182 public static KeyValue createFirstKeyInIncrementedRow(final Cell in){
183 byte[] thisRow = new SimpleByteRange(in.getRowArray(), in.getRowOffset(), in.getRowLength())
184 .deepCopyToNewArray();
185 byte[] nextRow = Bytes.unsignedCopyAndIncrement(thisRow);
186 return KeyValue.createFirstOnRow(nextRow);
187 }
188
189
190
191
192
193
194
195
196 public static KeyValue previousKey(final KeyValue in) {
197 return KeyValue.createFirstOnRow(CellUtil.cloneRow(in), CellUtil.cloneFamily(in),
198 CellUtil.cloneQualifier(in), in.getTimestamp() - 1);
199 }
200
201
202
203
204
205
206
207 public static KeyValue ensureKeyValue(final Cell cell) {
208 if (cell == null) return null;
209 return cell instanceof KeyValue? (KeyValue)cell: copyToNewKeyValue(cell);
210 }
211
212 public static List<KeyValue> ensureKeyValues(List<Cell> cells) {
213 List<KeyValue> lazyList = Lists.transform(cells, new Function<Cell, KeyValue>() {
214 public KeyValue apply(Cell arg0) {
215 return KeyValueUtil.ensureKeyValue(arg0);
216 }
217 });
218 return new ArrayList<KeyValue>(lazyList);
219 }
220 }