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