1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.hadoop.hbase.client;
21
22 import java.io.DataInput;
23 import java.io.DataOutput;
24 import java.io.IOException;
25 import java.util.Map;
26 import java.util.NavigableMap;
27 import java.util.Set;
28 import java.util.TreeMap;
29
30 import org.apache.hadoop.hbase.io.TimeRange;
31 import org.apache.hadoop.hbase.util.Bytes;
32 import org.apache.hadoop.io.Writable;
33
34
35
36
37
38
39
40
41
42
43
44
45
46 public class Increment implements Writable {
47 private static final byte INCREMENT_VERSION = (byte)2;
48
49 private byte [] row = null;
50 private long lockId = -1L;
51 private boolean writeToWAL = true;
52 private TimeRange tr = new TimeRange();
53 private Map<byte [], NavigableMap<byte [], Long>> familyMap =
54 new TreeMap<byte [], NavigableMap<byte [], Long>>(Bytes.BYTES_COMPARATOR);
55
56
57 public Increment() {}
58
59
60
61
62
63
64
65 public Increment(byte [] row) {
66 this(row, null);
67 }
68
69
70
71
72
73
74
75
76
77 public Increment(byte [] row, RowLock rowLock) {
78 this.row = row;
79 if(rowLock != null) {
80 this.lockId = rowLock.getLockId();
81 }
82 }
83
84
85
86
87
88
89
90
91
92
93
94 public Increment addColumn(byte [] family, byte [] qualifier, long amount) {
95 NavigableMap<byte [], Long> set = familyMap.get(family);
96 if(set == null) {
97 set = new TreeMap<byte [], Long>(Bytes.BYTES_COMPARATOR);
98 }
99 set.put(qualifier, amount);
100 familyMap.put(family, set);
101 return this;
102 }
103
104
105
106
107
108
109
110 public byte [] getRow() {
111 return this.row;
112 }
113
114
115
116
117
118 public RowLock getRowLock() {
119 return new RowLock(this.row, this.lockId);
120 }
121
122
123
124
125
126 public long getLockId() {
127 return this.lockId;
128 }
129
130
131
132
133
134 public boolean getWriteToWAL() {
135 return this.writeToWAL;
136 }
137
138
139
140
141
142
143 public Increment setWriteToWAL(boolean writeToWAL) {
144 this.writeToWAL = writeToWAL;
145 return this;
146 }
147
148
149
150
151
152 public TimeRange getTimeRange() {
153 return this.tr;
154 }
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170 public Increment setTimeRange(long minStamp, long maxStamp)
171 throws IOException {
172 tr = new TimeRange(minStamp, maxStamp);
173 return this;
174 }
175
176
177
178
179
180 public Set<byte[]> familySet() {
181 return this.familyMap.keySet();
182 }
183
184
185
186
187
188 public int numFamilies() {
189 return this.familyMap.size();
190 }
191
192
193
194
195
196 public int numColumns() {
197 if (!hasFamilies()) return 0;
198 int num = 0;
199 for (NavigableMap<byte [], Long> family : familyMap.values()) {
200 num += family.size();
201 }
202 return num;
203 }
204
205
206
207
208
209 public boolean hasFamilies() {
210 return !this.familyMap.isEmpty();
211 }
212
213
214
215
216
217 public Map<byte[],NavigableMap<byte[], Long>> getFamilyMap() {
218 return this.familyMap;
219 }
220
221
222
223
224 @Override
225 public String toString() {
226 StringBuilder sb = new StringBuilder();
227 sb.append("row=");
228 sb.append(Bytes.toStringBinary(this.row));
229 if(this.familyMap.size() == 0) {
230 sb.append(", no columns set to be incremented");
231 return sb.toString();
232 }
233 sb.append(", families=");
234 boolean moreThanOne = false;
235 for(Map.Entry<byte [], NavigableMap<byte[], Long>> entry :
236 this.familyMap.entrySet()) {
237 if(moreThanOne) {
238 sb.append("), ");
239 } else {
240 moreThanOne = true;
241 sb.append("{");
242 }
243 sb.append("(family=");
244 sb.append(Bytes.toString(entry.getKey()));
245 sb.append(", columns=");
246 if(entry.getValue() == null) {
247 sb.append("NONE");
248 } else {
249 sb.append("{");
250 boolean moreThanOneB = false;
251 for(Map.Entry<byte [], Long> column : entry.getValue().entrySet()) {
252 if(moreThanOneB) {
253 sb.append(", ");
254 } else {
255 moreThanOneB = true;
256 }
257 sb.append(Bytes.toStringBinary(column.getKey()) + "+=" + column.getValue());
258 }
259 sb.append("}");
260 }
261 }
262 sb.append("}");
263 return sb.toString();
264 }
265
266
267 public void readFields(final DataInput in)
268 throws IOException {
269 int version = in.readByte();
270 if (version > INCREMENT_VERSION) {
271 throw new IOException("unsupported version");
272 }
273 this.row = Bytes.readByteArray(in);
274 this.tr = new TimeRange();
275 tr.readFields(in);
276 this.lockId = in.readLong();
277 int numFamilies = in.readInt();
278 if (numFamilies == 0) {
279 throw new IOException("At least one column required");
280 }
281 this.familyMap =
282 new TreeMap<byte [],NavigableMap<byte [], Long>>(Bytes.BYTES_COMPARATOR);
283 for(int i=0; i<numFamilies; i++) {
284 byte [] family = Bytes.readByteArray(in);
285 boolean hasColumns = in.readBoolean();
286 NavigableMap<byte [], Long> set = null;
287 if(hasColumns) {
288 int numColumns = in.readInt();
289 set = new TreeMap<byte [], Long>(Bytes.BYTES_COMPARATOR);
290 for(int j=0; j<numColumns; j++) {
291 byte [] qualifier = Bytes.readByteArray(in);
292 set.put(qualifier, in.readLong());
293 }
294 } else {
295 throw new IOException("At least one column required per family");
296 }
297 this.familyMap.put(family, set);
298 }
299 if (version > 1) {
300 this.writeToWAL = in.readBoolean();
301 }
302 }
303
304 public void write(final DataOutput out)
305 throws IOException {
306 out.writeByte(INCREMENT_VERSION);
307 Bytes.writeByteArray(out, this.row);
308 tr.write(out);
309 out.writeLong(this.lockId);
310 if (familyMap.size() == 0) {
311 throw new IOException("At least one column required");
312 }
313 out.writeInt(familyMap.size());
314 for(Map.Entry<byte [], NavigableMap<byte [], Long>> entry :
315 familyMap.entrySet()) {
316 Bytes.writeByteArray(out, entry.getKey());
317 NavigableMap<byte [], Long> columnSet = entry.getValue();
318 if(columnSet == null) {
319 throw new IOException("At least one column required per family");
320 } else {
321 out.writeBoolean(true);
322 out.writeInt(columnSet.size());
323 for(Map.Entry<byte [], Long> qualifier : columnSet.entrySet()) {
324 Bytes.writeByteArray(out, qualifier.getKey());
325 out.writeLong(qualifier.getValue());
326 }
327 }
328 }
329 out.writeBoolean(writeToWAL);
330 }
331 }