1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.hadoop.hbase.client;
19
20 import java.io.DataInput;
21 import java.io.DataOutput;
22 import java.io.IOException;
23 import java.util.ArrayList;
24 import java.util.Arrays;
25 import java.util.List;
26 import java.util.Map;
27
28 import org.apache.hadoop.hbase.KeyValue;
29 import org.apache.hadoop.hbase.util.Bytes;
30
31
32
33
34
35
36
37
38
39
40
41
42
43 public class Append extends Mutation {
44 private static final String RETURN_RESULTS = "_rr_";
45 private static final byte APPEND_VERSION = (byte)1;
46
47
48
49
50
51
52
53 public void setReturnResults(boolean returnResults) {
54 setAttribute(RETURN_RESULTS, Bytes.toBytes(returnResults));
55 }
56
57
58
59
60 public boolean isReturnResults() {
61 byte[] v = getAttribute(RETURN_RESULTS);
62 return v == null ? true : Bytes.toBoolean(v);
63 }
64
65
66 public Append() {}
67
68
69
70
71
72
73
74 public Append(byte[] row) {
75 this.row = Arrays.copyOf(row, row.length);
76 }
77
78
79
80
81
82
83
84
85 public Append add(byte [] family, byte [] qualifier, byte [] value) {
86 List<KeyValue> list = familyMap.get(family);
87 if(list == null) {
88 list = new ArrayList<KeyValue>();
89 }
90 list.add(new KeyValue(
91 this.row, family, qualifier, this.ts, KeyValue.Type.Put, value));
92 familyMap.put(family, list);
93 return this;
94 }
95
96 @Override
97 public void readFields(final DataInput in)
98 throws IOException {
99 int version = in.readByte();
100 if (version > APPEND_VERSION) {
101 throw new IOException("version not supported: "+version);
102 }
103 this.row = Bytes.readByteArray(in);
104 this.ts = in.readLong();
105 this.lockId = in.readLong();
106 this.writeToWAL = in.readBoolean();
107 int numFamilies = in.readInt();
108 if (!this.familyMap.isEmpty()) this.familyMap.clear();
109 for(int i=0;i<numFamilies;i++) {
110 byte [] family = Bytes.readByteArray(in);
111 int numKeys = in.readInt();
112 List<KeyValue> keys = new ArrayList<KeyValue>(numKeys);
113 int totalLen = in.readInt();
114 byte [] buf = new byte[totalLen];
115 int offset = 0;
116 for (int j = 0; j < numKeys; j++) {
117 int keyLength = in.readInt();
118 in.readFully(buf, offset, keyLength);
119 keys.add(new KeyValue(buf, offset, keyLength));
120 offset += keyLength;
121 }
122 this.familyMap.put(family, keys);
123 }
124 readAttributes(in);
125 }
126
127 @Override
128 public void write(final DataOutput out)
129 throws IOException {
130 out.writeByte(APPEND_VERSION);
131 Bytes.writeByteArray(out, this.row);
132 out.writeLong(this.ts);
133 out.writeLong(this.lockId);
134 out.writeBoolean(this.writeToWAL);
135 out.writeInt(familyMap.size());
136 for (Map.Entry<byte [], List<KeyValue>> entry : familyMap.entrySet()) {
137 Bytes.writeByteArray(out, entry.getKey());
138 List<KeyValue> keys = entry.getValue();
139 out.writeInt(keys.size());
140 int totalLen = 0;
141 for(KeyValue kv : keys) {
142 totalLen += kv.getLength();
143 }
144 out.writeInt(totalLen);
145 for(KeyValue kv : keys) {
146 kv.write(out);
147 }
148 }
149 writeAttributes(out);
150 }
151
152
153
154
155
156
157
158 public Append add(KeyValue kv) {
159 if(!(kv.getType() == KeyValue.Type.Put.getCode())){
160 throw new IllegalArgumentException("Added type " + KeyValue.Type.codeToType(kv.getType())
161 + ", but appends can only be of type " + KeyValue.Type.Put + ". Rowkey:"
162 + Bytes.toStringBinary(kv.getRow()));
163 }
164
165 if (!kv.matchingRow(row)) {
166 throw new IllegalArgumentException("The row in the recently added KeyValue "
167 + Bytes.toStringBinary(kv.getRow()) + " doesn't match the original one "
168 + Bytes.toStringBinary(this.row));
169 }
170
171 byte[] family = kv.getFamily();
172 List<KeyValue> list = familyMap.get(family);
173 if (list == null) {
174 list = new ArrayList<KeyValue>();
175 familyMap.put(family, list);
176 }
177 list.add(kv);
178 return this;
179 }
180 }