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, 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
72 public Put(byte [] row, RowLock rowLock) {
73 this(row, HConstants.LATEST_TIMESTAMP, rowLock);
74 }
75
76
77
78
79
80
81
82 public Put(byte[] row, long ts) {
83 this(row, ts, null);
84 }
85
86
87
88
89
90
91
92
93
94 public Put(byte [] row, long ts, RowLock rowLock) {
95 if(row == null || row.length > HConstants.MAX_ROW_LENGTH) {
96 throw new IllegalArgumentException("Row key is invalid");
97 }
98 this.row = Arrays.copyOf(row, row.length);
99 this.ts = ts;
100 if(rowLock != null) {
101 this.lockId = rowLock.getLockId();
102 }
103 }
104
105
106
107
108
109 public Put(Put putToCopy) {
110 this(putToCopy.getRow(), putToCopy.ts, putToCopy.getRowLock());
111 this.familyMap =
112 new TreeMap<byte [], List<KeyValue>>(Bytes.BYTES_COMPARATOR);
113 for(Map.Entry<byte [], List<KeyValue>> entry :
114 putToCopy.getFamilyMap().entrySet()) {
115 this.familyMap.put(entry.getKey(), entry.getValue());
116 }
117 this.writeToWAL = putToCopy.writeToWAL;
118 }
119
120
121
122
123
124
125
126
127 public Put add(byte [] family, byte [] qualifier, byte [] value) {
128 return add(family, qualifier, this.ts, value);
129 }
130
131
132
133
134
135
136
137
138
139
140 public Put add(byte [] family, byte [] qualifier, long ts, byte [] value) {
141 List<KeyValue> list = getKeyValueList(family);
142 KeyValue kv = createPutKeyValue(family, qualifier, ts, value);
143 list.add(kv);
144 familyMap.put(kv.getFamily(), list);
145 return this;
146 }
147
148
149
150
151
152
153
154
155
156 public Put add(KeyValue kv) throws IOException{
157 byte [] family = kv.getFamily();
158 List<KeyValue> list = getKeyValueList(family);
159
160 if (!kv.matchingRow(row)) {
161 throw new IOException("The row in the recently added KeyValue "
162 + Bytes.toStringBinary(kv.getRow()) + " 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 for (KeyValue kv : list) {
268 if (Arrays.equals(kv.getFamily(), family) &&
269 Arrays.equals(kv.getQualifier(), qualifier) &&
270 Arrays.equals(kv.getValue(), value) &&
271 kv.getTimestamp() == ts) {
272 return true;
273 }
274 }
275 } else if (ignoreValue && !ignoreTS) {
276 for (KeyValue kv : list) {
277 if (Arrays.equals(kv.getFamily(), family) && Arrays.equals(kv.getQualifier(), qualifier)
278 && kv.getTimestamp() == ts) {
279 return true;
280 }
281 }
282 } else if (!ignoreValue && ignoreTS) {
283 for (KeyValue kv : list) {
284 if (Arrays.equals(kv.getFamily(), family) && Arrays.equals(kv.getQualifier(), qualifier)
285 && Arrays.equals(kv.getValue(), value)) {
286 return true;
287 }
288 }
289 } else {
290 for (KeyValue kv : list) {
291 if (Arrays.equals(kv.getFamily(), family) &&
292 Arrays.equals(kv.getQualifier(), qualifier)) {
293 return true;
294 }
295 }
296 }
297 return false;
298 }
299
300
301
302
303
304
305
306
307
308 public List<KeyValue> get(byte[] family, byte[] qualifier) {
309 List<KeyValue> filteredList = new ArrayList<KeyValue>();
310 for (KeyValue kv: getKeyValueList(family)) {
311 if (Arrays.equals(kv.getQualifier(), qualifier)) {
312 filteredList.add(kv);
313 }
314 }
315 return filteredList;
316 }
317
318
319
320
321
322
323
324
325 private List<KeyValue> getKeyValueList(byte[] family) {
326 List<KeyValue> list = familyMap.get(family);
327 if(list == null) {
328 list = new ArrayList<KeyValue>(0);
329 }
330 return list;
331 }
332
333
334 public long heapSize() {
335 long heapsize = OVERHEAD;
336
337 heapsize += ClassSize.align(ClassSize.ARRAY + this.row.length);
338
339
340 heapsize +=
341 ClassSize.align(this.familyMap.size() * ClassSize.MAP_ENTRY);
342 for(Map.Entry<byte [], List<KeyValue>> entry : this.familyMap.entrySet()) {
343
344 heapsize +=
345 ClassSize.align(ClassSize.ARRAY + entry.getKey().length);
346
347
348
349
350 heapsize += ClassSize.align(ClassSize.ARRAYLIST);
351 int size = entry.getValue().size();
352 heapsize += ClassSize.align(ClassSize.ARRAY +
353 size * ClassSize.REFERENCE);
354
355 for(KeyValue kv : entry.getValue()) {
356 heapsize += kv.heapSize();
357 }
358 }
359 heapsize += getAttributeSize();
360
361 return ClassSize.align((int)heapsize);
362 }
363
364
365 public void readFields(final DataInput in)
366 throws IOException {
367 int version = in.readByte();
368 if (version > PUT_VERSION) {
369 throw new IOException("version not supported");
370 }
371 this.row = Bytes.readByteArray(in);
372 this.ts = in.readLong();
373 this.lockId = in.readLong();
374 this.writeToWAL = in.readBoolean();
375 int numFamilies = in.readInt();
376 if (!this.familyMap.isEmpty()) this.familyMap.clear();
377 for(int i=0;i<numFamilies;i++) {
378 byte [] family = Bytes.readByteArray(in);
379 int numKeys = in.readInt();
380 List<KeyValue> keys = new ArrayList<KeyValue>(numKeys);
381 int totalLen = in.readInt();
382 byte [] buf = new byte[totalLen];
383 int offset = 0;
384 for (int j = 0; j < numKeys; j++) {
385 int keyLength = in.readInt();
386 in.readFully(buf, offset, keyLength);
387 keys.add(new KeyValue(buf, offset, keyLength));
388 offset += keyLength;
389 }
390 this.familyMap.put(family, keys);
391 }
392 if (version > 1) {
393 readAttributes(in);
394 }
395 }
396
397 public void write(final DataOutput out)
398 throws IOException {
399 out.writeByte(PUT_VERSION);
400 Bytes.writeByteArray(out, this.row);
401 out.writeLong(this.ts);
402 out.writeLong(this.lockId);
403 out.writeBoolean(this.writeToWAL);
404 out.writeInt(familyMap.size());
405 for (Map.Entry<byte [], List<KeyValue>> entry : familyMap.entrySet()) {
406 Bytes.writeByteArray(out, entry.getKey());
407 List<KeyValue> keys = entry.getValue();
408 out.writeInt(keys.size());
409 int totalLen = 0;
410 for(KeyValue kv : keys) {
411 totalLen += kv.getLength();
412 }
413 out.writeInt(totalLen);
414 for(KeyValue kv : keys) {
415 kv.write(out);
416 }
417 }
418 writeAttributes(out);
419 }
420 }