HBASE-19498 Fix findbugs and error-prone warnings in hbase-client (branch-2)
[hbase.git] / hbase-client / src / main / java / org / apache / hadoop / hbase / client / Increment.java
blob27cdafeb23b044327af2550c2c93eed29cb1d1e7
1 /**
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
19 package org.apache.hadoop.hbase.client;
21 import java.io.IOException;
22 import java.util.List;
23 import java.util.Map;
24 import java.util.NavigableMap;
25 import java.util.TreeMap;
26 import java.util.UUID;
27 import org.apache.hadoop.hbase.Cell;
28 import org.apache.hadoop.hbase.CellUtil;
29 import org.apache.hadoop.hbase.KeyValue;
30 import org.apache.hadoop.hbase.io.TimeRange;
31 import org.apache.hadoop.hbase.security.access.Permission;
32 import org.apache.hadoop.hbase.security.visibility.CellVisibility;
33 import org.apache.hadoop.hbase.util.Bytes;
34 import org.apache.hadoop.hbase.util.ClassSize;
35 import org.apache.yetus.audience.InterfaceAudience;
37 /**
38 * Used to perform Increment operations on a single row.
39 * <p>
40 * This operation ensures atomicity to readers. Increments are done
41 * under a single row lock, so write operations to a row are synchronized, and
42 * readers are guaranteed to see this operation fully completed.
43 * <p>
44 * To increment columns of a row, instantiate an Increment object with the row
45 * to increment. At least one column to increment must be specified using the
46 * {@link #addColumn(byte[], byte[], long)} method.
48 @InterfaceAudience.Public
49 public class Increment extends Mutation implements Comparable<Row> {
50 private static final int HEAP_OVERHEAD = ClassSize.REFERENCE + ClassSize.TIMERANGE;
51 private TimeRange tr = new TimeRange();
53 /**
54 * Create a Increment operation for the specified row.
55 * <p>
56 * At least one column must be incremented.
57 * @param row row key (we will make a copy of this).
59 public Increment(byte [] row) {
60 this(row, 0, row.length);
63 /**
64 * Create a Increment operation for the specified row.
65 * <p>
66 * At least one column must be incremented.
67 * @param row row key (we will make a copy of this).
69 public Increment(final byte [] row, final int offset, final int length) {
70 checkRow(row, offset, length);
71 this.row = Bytes.copy(row, offset, length);
73 /**
74 * Copy constructor
75 * @param i
77 public Increment(Increment i) {
78 this.row = i.getRow();
79 this.ts = i.getTimeStamp();
80 this.tr = i.getTimeRange();
81 this.familyMap.putAll(i.getFamilyCellMap());
82 for (Map.Entry<String, byte[]> entry : i.getAttributesMap().entrySet()) {
83 this.setAttribute(entry.getKey(), entry.getValue());
85 super.setPriority(i.getPriority());
88 /**
89 * Add the specified KeyValue to this operation.
90 * @param cell individual Cell
91 * @return this
92 * @throws java.io.IOException e
94 public Increment add(Cell cell) throws IOException{
95 byte [] family = CellUtil.cloneFamily(cell);
96 List<Cell> list = getCellList(family);
97 //Checking that the row of the kv is the same as the put
98 if (!CellUtil.matchingRows(cell, this.row)) {
99 throw new WrongRowIOException("The row in " + cell +
100 " doesn't match the original one " + Bytes.toStringBinary(this.row));
102 list.add(cell);
103 return this;
107 * Increment the column from the specific family with the specified qualifier
108 * by the specified amount.
109 * <p>
110 * Overrides previous calls to addColumn for this family and qualifier.
111 * @param family family name
112 * @param qualifier column qualifier
113 * @param amount amount to increment by
114 * @return the Increment object
116 public Increment addColumn(byte [] family, byte [] qualifier, long amount) {
117 if (family == null) {
118 throw new IllegalArgumentException("family cannot be null");
120 List<Cell> list = getCellList(family);
121 KeyValue kv = createPutKeyValue(family, qualifier, ts, Bytes.toBytes(amount));
122 list.add(kv);
123 return this;
127 * Gets the TimeRange used for this increment.
128 * @return TimeRange
130 public TimeRange getTimeRange() {
131 return this.tr;
135 * Sets the TimeRange to be used on the Get for this increment.
136 * <p>
137 * This is useful for when you have counters that only last for specific
138 * periods of time (ie. counters that are partitioned by time). By setting
139 * the range of valid times for this increment, you can potentially gain
140 * some performance with a more optimal Get operation.
141 * Be careful adding the time range to this class as you will update the old cell if the
142 * time range doesn't include the latest cells.
143 * <p>
144 * This range is used as [minStamp, maxStamp).
145 * @param minStamp minimum timestamp value, inclusive
146 * @param maxStamp maximum timestamp value, exclusive
147 * @throws IOException if invalid time range
148 * @return this
150 public Increment setTimeRange(long minStamp, long maxStamp)
151 throws IOException {
152 tr = new TimeRange(minStamp, maxStamp);
153 return this;
156 @Override
157 public Increment setTimestamp(long timestamp) {
158 super.setTimestamp(timestamp);
159 return this;
163 * @param returnResults True (default) if the increment operation should return the results. A
164 * client that is not interested in the result can save network bandwidth setting this
165 * to false.
167 @Override
168 public Increment setReturnResults(boolean returnResults) {
169 super.setReturnResults(returnResults);
170 return this;
174 * @return current setting for returnResults
176 // This method makes public the superclasses's protected method.
177 @Override
178 public boolean isReturnResults() {
179 return super.isReturnResults();
183 * Method for retrieving the number of families to increment from
184 * @return number of families
186 @Override
187 public int numFamilies() {
188 return this.familyMap.size();
192 * Method for checking if any families have been inserted into this Increment
193 * @return true if familyMap is non empty false otherwise
195 public boolean hasFamilies() {
196 return !this.familyMap.isEmpty();
200 * Before 0.95, when you called Increment#getFamilyMap(), you got back
201 * a map of families to a list of Longs. Now, {@link #getFamilyCellMap()} returns
202 * families by list of Cells. This method has been added so you can have the
203 * old behavior.
204 * @return Map of families to a Map of qualifiers and their Long increments.
205 * @since 0.95.0
207 public Map<byte[], NavigableMap<byte [], Long>> getFamilyMapOfLongs() {
208 NavigableMap<byte[], List<Cell>> map = super.getFamilyCellMap();
209 Map<byte [], NavigableMap<byte[], Long>> results = new TreeMap<>(Bytes.BYTES_COMPARATOR);
210 for (Map.Entry<byte [], List<Cell>> entry: map.entrySet()) {
211 NavigableMap<byte [], Long> longs = new TreeMap<>(Bytes.BYTES_COMPARATOR);
212 for (Cell cell: entry.getValue()) {
213 longs.put(CellUtil.cloneQualifier(cell),
214 Bytes.toLong(cell.getValueArray(), cell.getValueOffset(), cell.getValueLength()));
216 results.put(entry.getKey(), longs);
218 return results;
222 * @return String
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.isEmpty()) {
230 sb.append(", no columns set to be incremented");
231 return sb.toString();
233 sb.append(", families=");
234 boolean moreThanOne = false;
235 for(Map.Entry<byte [], List<Cell>> entry: this.familyMap.entrySet()) {
236 if(moreThanOne) {
237 sb.append("), ");
238 } else {
239 moreThanOne = true;
240 sb.append("{");
242 sb.append("(family=");
243 sb.append(Bytes.toString(entry.getKey()));
244 sb.append(", columns=");
245 if(entry.getValue() == null) {
246 sb.append("NONE");
247 } else {
248 sb.append("{");
249 boolean moreThanOneB = false;
250 for(Cell cell : entry.getValue()) {
251 if(moreThanOneB) {
252 sb.append(", ");
253 } else {
254 moreThanOneB = true;
256 sb.append(CellUtil.getCellKeyAsString(cell) + "+=" +
257 Bytes.toLong(cell.getValueArray(), cell.getValueOffset(), cell.getValueLength()));
259 sb.append("}");
262 sb.append("}");
263 return sb.toString();
266 @Override
267 public int compareTo(Row i) {
268 // TODO: This is wrong. Can't have two the same just because on same row.
269 return Bytes.compareTo(this.getRow(), i.getRow());
272 @Override
273 public int hashCode() {
274 // TODO: This is wrong. Can't have two gets the same just because on same row. But it
275 // matches how equals works currently and gets rid of the findbugs warning.
276 return Bytes.hashCode(this.getRow());
279 @Override
280 public boolean equals(Object obj) {
281 // TODO: This is wrong. Can't have two the same just because on same row.
282 if (this == obj) {
283 return true;
285 if (obj == null || getClass() != obj.getClass()) {
286 return false;
288 Row other = (Row) obj;
289 return compareTo(other) == 0;
292 @Override
293 protected long extraHeapSize(){
294 return HEAP_OVERHEAD;
297 @Override
298 public Increment setAttribute(String name, byte[] value) {
299 return (Increment) super.setAttribute(name, value);
302 @Override
303 public Increment setId(String id) {
304 return (Increment) super.setId(id);
307 @Override
308 public Increment setDurability(Durability d) {
309 return (Increment) super.setDurability(d);
312 @Override
313 public Increment setFamilyCellMap(NavigableMap<byte[], List<Cell>> map) {
314 return (Increment) super.setFamilyCellMap(map);
317 @Override
318 public Increment setClusterIds(List<UUID> clusterIds) {
319 return (Increment) super.setClusterIds(clusterIds);
322 @Override
323 public Increment setCellVisibility(CellVisibility expression) {
324 return (Increment) super.setCellVisibility(expression);
327 @Override
328 public Increment setACL(String user, Permission perms) {
329 return (Increment) super.setACL(user, perms);
332 @Override
333 public Increment setACL(Map<String, Permission> perms) {
334 return (Increment) super.setACL(perms);
337 @Override
338 public Increment setTTL(long ttl) {
339 return (Increment) super.setTTL(ttl);
342 @Override
343 public Increment setPriority(int priority) {
344 return (Increment) super.setPriority(priority);