1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 package org.apache.hadoop.hbase.client;
22
23 import org.apache.hadoop.hbase.HConstants;
24 import org.apache.hadoop.hbase.KeyValue;
25 import org.apache.hadoop.hbase.io.HeapSize;
26 import org.apache.hadoop.hbase.util.Bytes;
27 import org.apache.hadoop.hbase.util.ClassSize;
28 import org.apache.hadoop.io.Writable;
29
30 import java.io.DataInput;
31 import java.io.DataOutput;
32 import java.io.IOException;
33 import java.util.ArrayList;
34 import java.util.Arrays;
35 import java.util.List;
36 import java.util.Map;
37 import java.util.TreeMap;
38
39
40
41
42
43
44
45
46 public class Put extends Mutation
47 implements HeapSize, Writable, Row, Comparable<Row> {
48 private static final byte PUT_VERSION = (byte)2;
49
50 private static final long OVERHEAD = ClassSize.align(
51 ClassSize.OBJECT + 2 * ClassSize.REFERENCE +
52 2 * Bytes.SIZEOF_LONG + Bytes.SIZEOF_BOOLEAN +
53 ClassSize.REFERENCE + ClassSize.TREEMAP);
54
55
56 public Put() {}
57
58
59
60
61
62 public Put(byte [] row) {
63 this(row, null);
64 }
65
66
67
68
69
70
71 public Put(byte [] row, RowLock rowLock) {
72 this(row, HConstants.LATEST_TIMESTAMP, rowLock);
73 }
74
75
76
77
78
79
80
81 public Put(byte[] row, long ts) {
82 this(row, ts, null);
83 }
84
85
86
87
88
89
90
91 public Put(byte [] row, long ts, RowLock rowLock) {
92 if(row == null || row.length > HConstants.MAX_ROW_LENGTH) {
93 throw new IllegalArgumentException("Row key is invalid");
94 }
95 this.row = Arrays.copyOf(row, row.length);
96 this.ts = ts;
97 if(rowLock != null) {
98 this.lockId = rowLock.getLockId();
99 }
100 }
101
102
103
104
105
106 public Put(Put putToCopy) {
107 this(putToCopy.getRow(), putToCopy.ts, putToCopy.getRowLock());
108 this.familyMap =
109 new TreeMap<byte [], List<KeyValue>>(Bytes.BYTES_COMPARATOR);
110 for(Map.Entry<byte [], List<KeyValue>> entry :
111 putToCopy.getFamilyMap().entrySet()) {
112 this.familyMap.put(entry.getKey(), entry.getValue());
113 }
114 this.writeToWAL = putToCopy.writeToWAL;
115 }
116
117
118
119
120
121
122
123
124 public Put add(byte [] family, byte [] qualifier, byte [] value) {
125 return add(family, qualifier, this.ts, value);
126 }
127
128
129
130
131
132
133
134
135
136
137 public Put add(byte [] family, byte [] qualifier, long ts, byte [] value) {
138 List<KeyValue> list = getKeyValueList(family);
139 KeyValue kv = createPutKeyValue(family, qualifier, ts, value);
140 list.add(kv);
141 familyMap.put(kv.getFamily(), list);
142 return this;
143 }
144
145
146
147
148
149
150
151
152
153 public Put add(KeyValue kv) throws IOException{
154 byte [] family = kv.getFamily();
155 List<KeyValue> list = getKeyValueList(family);
156
157 int res = Bytes.compareTo(this.row, 0, row.length,
158 kv.getBuffer(), kv.getRowOffset(), kv.getRowLength());
159 if(res != 0) {
160 throw new IOException("The row in the recently added KeyValue " +
161 Bytes.toStringBinary(kv.getBuffer(), kv.getRowOffset(),
162 kv.getRowLength()) + " doesn't match the original one " +
163 Bytes.toStringBinary(this.row));
164 }
165 list.add(kv);
166 familyMap.put(family, list);
167 return this;
168 }
169
170
171
172
173
174
175 private KeyValue createPutKeyValue(byte[] family, byte[] qualifier, long ts,
176 byte[] value) {
177 return new KeyValue(this.row, family, qualifier, ts, KeyValue.Type.Put,
178 value);
179 }
180
181
182
183
184
185
186
187
188
189
190
191 public boolean has(byte [] family, byte [] qualifier) {
192 return has(family, qualifier, this.ts, new byte[0], true, true);
193 }
194
195
196
197
198
199
200
201
202
203
204
205
206 public boolean has(byte [] family, byte [] qualifier, long ts) {
207 return has(family, qualifier, ts, new byte[0], false, true);
208 }
209
210
211
212
213
214
215
216
217
218
219
220
221 public boolean has(byte [] family, byte [] qualifier, byte [] value) {
222 return has(family, qualifier, this.ts, value, true, false);
223 }
224
225
226
227
228
229
230
231
232
233
234
235
236
237 public boolean has(byte [] family, byte [] qualifier, long ts, byte [] value) {
238 return has(family, qualifier, ts, value, false, false);
239 }
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255 private boolean has(byte [] family, byte [] qualifier, long ts, byte [] value,
256 boolean ignoreTS, boolean ignoreValue) {
257 List<KeyValue> list = getKeyValueList(family);
258 if (list.size() == 0) {
259 return false;
260 }
261
262
263
264
265
266 if (!ignoreTS && !ignoreValue) {
267 KeyValue kv = createPutKeyValue(family, qualifier, ts, value);
268 return (list.contains(kv));
269 } else if (ignoreValue) {
270 for (KeyValue kv: list) {
271 if (Arrays.equals(kv.getFamily(), family) && Arrays.equals(kv.getQualifier(), qualifier)
272 && kv.getTimestamp() == ts) {
273 return true;
274 }
275 }
276 } else {
277
278 for (KeyValue kv: list) {
279 if (Arrays.equals(kv.getFamily(), family) && Arrays.equals(kv.getQualifier(), qualifier)
280 && Arrays.equals(kv.getValue(), value)) {
281 return true;
282 }
283 }
284 }
285 return false;
286 }
287
288
289
290
291
292
293
294
295
296 public List<KeyValue> get(byte[] family, byte[] qualifier) {
297 List<KeyValue> filteredList = new ArrayList<KeyValue>();
298 for (KeyValue kv: getKeyValueList(family)) {
299 if (Arrays.equals(kv.getQualifier(), qualifier)) {
300 filteredList.add(kv);
301 }
302 }
303 return filteredList;
304 }
305
306
307
308
309
310
311
312
313 private List<KeyValue> getKeyValueList(byte[] family) {
314 List<KeyValue> list = familyMap.get(family);
315 if(list == null) {
316 list = new ArrayList<KeyValue>(0);
317 }
318 return list;
319 }
320
321
322
323
324 public int numFamilies() {
325 return familyMap.size();
326 }
327
328
329
330
331 public int size() {
332 int size = 0;
333 for(List<KeyValue> kvList : this.familyMap.values()) {
334 size += kvList.size();
335 }
336 return size;
337 }
338
339
340 public long heapSize() {
341 long heapsize = OVERHEAD;
342
343 heapsize += ClassSize.align(ClassSize.ARRAY + this.row.length);
344
345
346 heapsize +=
347 ClassSize.align(this.familyMap.size() * ClassSize.MAP_ENTRY);
348 for(Map.Entry<byte [], List<KeyValue>> entry : this.familyMap.entrySet()) {
349
350 heapsize +=
351 ClassSize.align(ClassSize.ARRAY + entry.getKey().length);
352
353
354
355
356 heapsize += ClassSize.align(ClassSize.ARRAYLIST);
357 int size = entry.getValue().size();
358 heapsize += ClassSize.align(ClassSize.ARRAY +
359 size * ClassSize.REFERENCE);
360
361 for(KeyValue kv : entry.getValue()) {
362 heapsize += kv.heapSize();
363 }
364 }
365 heapsize += getAttributeSize();
366
367 return ClassSize.align((int)heapsize);
368 }
369
370
371 public void readFields(final DataInput in)
372 throws IOException {
373 int version = in.readByte();
374 if (version > PUT_VERSION) {
375 throw new IOException("version not supported");
376 }
377 this.row = Bytes.readByteArray(in);
378 this.ts = in.readLong();
379 this.lockId = in.readLong();
380 this.writeToWAL = in.readBoolean();
381 int numFamilies = in.readInt();
382 if (!this.familyMap.isEmpty()) this.familyMap.clear();
383 for(int i=0;i<numFamilies;i++) {
384 byte [] family = Bytes.readByteArray(in);
385 int numKeys = in.readInt();
386 List<KeyValue> keys = new ArrayList<KeyValue>(numKeys);
387 int totalLen = in.readInt();
388 byte [] buf = new byte[totalLen];
389 int offset = 0;
390 for (int j = 0; j < numKeys; j++) {
391 int keyLength = in.readInt();
392 in.readFully(buf, offset, keyLength);
393 keys.add(new KeyValue(buf, offset, keyLength));
394 offset += keyLength;
395 }
396 this.familyMap.put(family, keys);
397 }
398 if (version > 1) {
399 readAttributes(in);
400 }
401 }
402
403 public void write(final DataOutput out)
404 throws IOException {
405 out.writeByte(PUT_VERSION);
406 Bytes.writeByteArray(out, this.row);
407 out.writeLong(this.ts);
408 out.writeLong(this.lockId);
409 out.writeBoolean(this.writeToWAL);
410 out.writeInt(familyMap.size());
411 for (Map.Entry<byte [], List<KeyValue>> entry : familyMap.entrySet()) {
412 Bytes.writeByteArray(out, entry.getKey());
413 List<KeyValue> keys = entry.getValue();
414 out.writeInt(keys.size());
415 int totalLen = 0;
416 for(KeyValue kv : keys) {
417 totalLen += kv.getLength();
418 }
419 out.writeInt(totalLen);
420 for(KeyValue kv : keys) {
421 out.writeInt(kv.getLength());
422 out.write(kv.getBuffer(), kv.getOffset(), kv.getLength());
423 }
424 }
425 writeAttributes(out);
426 }
427 }