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 int res = Bytes.compareTo(this.row, 0, row.length,
161 kv.getBuffer(), kv.getRowOffset(), kv.getRowLength());
162 if(res != 0) {
163 throw new IOException("The row in the recently added KeyValue " +
164 Bytes.toStringBinary(kv.getBuffer(), kv.getRowOffset(),
165 kv.getRowLength()) + " doesn't match the original one " +
166 Bytes.toStringBinary(this.row));
167 }
168 list.add(kv);
169 familyMap.put(family, list);
170 return this;
171 }
172
173
174
175
176
177
178 private KeyValue createPutKeyValue(byte[] family, byte[] qualifier, long ts,
179 byte[] value) {
180 return new KeyValue(this.row, family, qualifier, ts, KeyValue.Type.Put,
181 value);
182 }
183
184
185
186
187
188
189
190
191
192
193
194 public boolean has(byte [] family, byte [] qualifier) {
195 return has(family, qualifier, this.ts, new byte[0], true, true);
196 }
197
198
199
200
201
202
203
204
205
206
207
208
209 public boolean has(byte [] family, byte [] qualifier, long ts) {
210 return has(family, qualifier, ts, new byte[0], false, true);
211 }
212
213
214
215
216
217
218
219
220
221
222
223
224 public boolean has(byte [] family, byte [] qualifier, byte [] value) {
225 return has(family, qualifier, this.ts, value, true, false);
226 }
227
228
229
230
231
232
233
234
235
236
237
238
239
240 public boolean has(byte [] family, byte [] qualifier, long ts, byte [] value) {
241 return has(family, qualifier, ts, value, false, false);
242 }
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258 private boolean has(byte[] family, byte[] qualifier, long ts, byte[] value,
259 boolean ignoreTS, boolean ignoreValue) {
260 List<KeyValue> list = getKeyValueList(family);
261 if (list.size() == 0) {
262 return false;
263 }
264
265
266
267
268
269 if (!ignoreTS && !ignoreValue) {
270 for (KeyValue kv : list) {
271 if (Arrays.equals(kv.getFamily(), family) &&
272 Arrays.equals(kv.getQualifier(), qualifier) &&
273 Arrays.equals(kv.getValue(), value) &&
274 kv.getTimestamp() == ts) {
275 return true;
276 }
277 }
278 } else if (ignoreValue && !ignoreTS) {
279 for (KeyValue kv : list) {
280 if (Arrays.equals(kv.getFamily(), family) && Arrays.equals(kv.getQualifier(), qualifier)
281 && kv.getTimestamp() == ts) {
282 return true;
283 }
284 }
285 } else if (!ignoreValue && ignoreTS) {
286 for (KeyValue kv : list) {
287 if (Arrays.equals(kv.getFamily(), family) && Arrays.equals(kv.getQualifier(), qualifier)
288 && Arrays.equals(kv.getValue(), value)) {
289 return true;
290 }
291 }
292 } else {
293 for (KeyValue kv : list) {
294 if (Arrays.equals(kv.getFamily(), family) &&
295 Arrays.equals(kv.getQualifier(), qualifier)) {
296 return true;
297 }
298 }
299 }
300 return false;
301 }
302
303
304
305
306
307
308
309
310
311 public List<KeyValue> get(byte[] family, byte[] qualifier) {
312 List<KeyValue> filteredList = new ArrayList<KeyValue>();
313 for (KeyValue kv: getKeyValueList(family)) {
314 if (Arrays.equals(kv.getQualifier(), qualifier)) {
315 filteredList.add(kv);
316 }
317 }
318 return filteredList;
319 }
320
321
322
323
324
325
326
327
328 private List<KeyValue> getKeyValueList(byte[] family) {
329 List<KeyValue> list = familyMap.get(family);
330 if(list == null) {
331 list = new ArrayList<KeyValue>(0);
332 }
333 return list;
334 }
335
336
337 public long heapSize() {
338 long heapsize = OVERHEAD;
339
340 heapsize += ClassSize.align(ClassSize.ARRAY + this.row.length);
341
342
343 heapsize +=
344 ClassSize.align(this.familyMap.size() * ClassSize.MAP_ENTRY);
345 for(Map.Entry<byte [], List<KeyValue>> entry : this.familyMap.entrySet()) {
346
347 heapsize +=
348 ClassSize.align(ClassSize.ARRAY + entry.getKey().length);
349
350
351
352
353 heapsize += ClassSize.align(ClassSize.ARRAYLIST);
354 int size = entry.getValue().size();
355 heapsize += ClassSize.align(ClassSize.ARRAY +
356 size * ClassSize.REFERENCE);
357
358 for(KeyValue kv : entry.getValue()) {
359 heapsize += kv.heapSize();
360 }
361 }
362 heapsize += getAttributeSize();
363
364 return ClassSize.align((int)heapsize);
365 }
366
367
368 public void readFields(final DataInput in)
369 throws IOException {
370 int version = in.readByte();
371 if (version > PUT_VERSION) {
372 throw new IOException("version not supported");
373 }
374 this.row = Bytes.readByteArray(in);
375 this.ts = in.readLong();
376 this.lockId = in.readLong();
377 this.writeToWAL = in.readBoolean();
378 int numFamilies = in.readInt();
379 if (!this.familyMap.isEmpty()) this.familyMap.clear();
380 for(int i=0;i<numFamilies;i++) {
381 byte [] family = Bytes.readByteArray(in);
382 int numKeys = in.readInt();
383 List<KeyValue> keys = new ArrayList<KeyValue>(numKeys);
384 int totalLen = in.readInt();
385 byte [] buf = new byte[totalLen];
386 int offset = 0;
387 for (int j = 0; j < numKeys; j++) {
388 int keyLength = in.readInt();
389 in.readFully(buf, offset, keyLength);
390 keys.add(new KeyValue(buf, offset, keyLength));
391 offset += keyLength;
392 }
393 this.familyMap.put(family, keys);
394 }
395 if (version > 1) {
396 readAttributes(in);
397 }
398 }
399
400 public void write(final DataOutput out)
401 throws IOException {
402 out.writeByte(PUT_VERSION);
403 Bytes.writeByteArray(out, this.row);
404 out.writeLong(this.ts);
405 out.writeLong(this.lockId);
406 out.writeBoolean(this.writeToWAL);
407 out.writeInt(familyMap.size());
408 for (Map.Entry<byte [], List<KeyValue>> entry : familyMap.entrySet()) {
409 Bytes.writeByteArray(out, entry.getKey());
410 List<KeyValue> keys = entry.getValue();
411 out.writeInt(keys.size());
412 int totalLen = 0;
413 for(KeyValue kv : keys) {
414 totalLen += kv.getLength();
415 }
416 out.writeInt(totalLen);
417 for(KeyValue kv : keys) {
418 out.writeInt(kv.getLength());
419 out.write(kv.getBuffer(), kv.getOffset(), kv.getLength());
420 }
421 }
422 writeAttributes(out);
423 }
424 }