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 Row {
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
78
79 public Increment(byte [] row, RowLock rowLock) {
80 this.row = row;
81 if(rowLock != null) {
82 this.lockId = rowLock.getLockId();
83 }
84 }
85
86
87
88
89
90
91
92
93
94
95
96 public Increment addColumn(byte [] family, byte [] qualifier, long amount) {
97 NavigableMap<byte [], Long> set = familyMap.get(family);
98 if(set == null) {
99 set = new TreeMap<byte [], Long>(Bytes.BYTES_COMPARATOR);
100 }
101 set.put(qualifier, amount);
102 familyMap.put(family, set);
103 return this;
104 }
105
106
107
108
109
110
111
112 public byte [] getRow() {
113 return this.row;
114 }
115
116
117
118
119
120
121 public RowLock getRowLock() {
122 return new RowLock(this.row, this.lockId);
123 }
124
125
126
127
128
129
130 public long getLockId() {
131 return this.lockId;
132 }
133
134
135
136
137
138 public boolean getWriteToWAL() {
139 return this.writeToWAL;
140 }
141
142
143
144
145
146
147 public Increment setWriteToWAL(boolean writeToWAL) {
148 this.writeToWAL = writeToWAL;
149 return this;
150 }
151
152
153
154
155
156 public TimeRange getTimeRange() {
157 return this.tr;
158 }
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174 public Increment setTimeRange(long minStamp, long maxStamp)
175 throws IOException {
176 tr = new TimeRange(minStamp, maxStamp);
177 return this;
178 }
179
180
181
182
183
184 public Set<byte[]> familySet() {
185 return this.familyMap.keySet();
186 }
187
188
189
190
191
192 public int numFamilies() {
193 return this.familyMap.size();
194 }
195
196
197
198
199
200 public int numColumns() {
201 if (!hasFamilies()) return 0;
202 int num = 0;
203 for (NavigableMap<byte [], Long> family : familyMap.values()) {
204 num += family.size();
205 }
206 return num;
207 }
208
209
210
211
212
213 public boolean hasFamilies() {
214 return !this.familyMap.isEmpty();
215 }
216
217
218
219
220
221 public Map<byte[],NavigableMap<byte[], Long>> getFamilyMap() {
222 return this.familyMap;
223 }
224
225
226
227
228 @Override
229 public String toString() {
230 StringBuilder sb = new StringBuilder();
231 sb.append("row=");
232 sb.append(Bytes.toStringBinary(this.row));
233 if(this.familyMap.size() == 0) {
234 sb.append(", no columns set to be incremented");
235 return sb.toString();
236 }
237 sb.append(", families=");
238 boolean moreThanOne = false;
239 for(Map.Entry<byte [], NavigableMap<byte[], Long>> entry :
240 this.familyMap.entrySet()) {
241 if(moreThanOne) {
242 sb.append("), ");
243 } else {
244 moreThanOne = true;
245 sb.append("{");
246 }
247 sb.append("(family=");
248 sb.append(Bytes.toString(entry.getKey()));
249 sb.append(", columns=");
250 if(entry.getValue() == null) {
251 sb.append("NONE");
252 } else {
253 sb.append("{");
254 boolean moreThanOneB = false;
255 for(Map.Entry<byte [], Long> column : entry.getValue().entrySet()) {
256 if(moreThanOneB) {
257 sb.append(", ");
258 } else {
259 moreThanOneB = true;
260 }
261 sb.append(Bytes.toStringBinary(column.getKey()) + "+=" + column.getValue());
262 }
263 sb.append("}");
264 }
265 }
266 sb.append("}");
267 return sb.toString();
268 }
269
270
271 public void readFields(final DataInput in)
272 throws IOException {
273 int version = in.readByte();
274 if (version > INCREMENT_VERSION) {
275 throw new IOException("unsupported version");
276 }
277 this.row = Bytes.readByteArray(in);
278 this.tr = new TimeRange();
279 tr.readFields(in);
280 this.lockId = in.readLong();
281 int numFamilies = in.readInt();
282 if (numFamilies == 0) {
283 throw new IOException("At least one column required");
284 }
285 this.familyMap =
286 new TreeMap<byte [],NavigableMap<byte [], Long>>(Bytes.BYTES_COMPARATOR);
287 for(int i=0; i<numFamilies; i++) {
288 byte [] family = Bytes.readByteArray(in);
289 boolean hasColumns = in.readBoolean();
290 NavigableMap<byte [], Long> set = null;
291 if(hasColumns) {
292 int numColumns = in.readInt();
293 set = new TreeMap<byte [], Long>(Bytes.BYTES_COMPARATOR);
294 for(int j=0; j<numColumns; j++) {
295 byte [] qualifier = Bytes.readByteArray(in);
296 set.put(qualifier, in.readLong());
297 }
298 } else {
299 throw new IOException("At least one column required per family");
300 }
301 this.familyMap.put(family, set);
302 }
303 if (version > 1) {
304 this.writeToWAL = in.readBoolean();
305 }
306 }
307
308 public void write(final DataOutput out)
309 throws IOException {
310 out.writeByte(INCREMENT_VERSION);
311 Bytes.writeByteArray(out, this.row);
312 tr.write(out);
313 out.writeLong(this.lockId);
314 if (familyMap.size() == 0) {
315 throw new IOException("At least one column required");
316 }
317 out.writeInt(familyMap.size());
318 for(Map.Entry<byte [], NavigableMap<byte [], Long>> entry :
319 familyMap.entrySet()) {
320 Bytes.writeByteArray(out, entry.getKey());
321 NavigableMap<byte [], Long> columnSet = entry.getValue();
322 if(columnSet == null) {
323 throw new IOException("At least one column required per family");
324 } else {
325 out.writeBoolean(true);
326 out.writeInt(columnSet.size());
327 for(Map.Entry<byte [], Long> qualifier : columnSet.entrySet()) {
328 Bytes.writeByteArray(out, qualifier.getKey());
329 out.writeLong(qualifier.getValue());
330 }
331 }
332 }
333 out.writeBoolean(writeToWAL);
334 }
335
336 @Override
337 public int compareTo(Row i) {
338 return Bytes.compareTo(this.getRow(), i.getRow());
339 }
340 }