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