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
;
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
;
38 * Used to perform Increment operations on a single row.
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.
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();
54 * Create a Increment operation for the specified row.
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
);
64 * Create a Increment operation for the specified row.
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
);
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());
89 * Add the specified KeyValue to this operation.
90 * @param cell individual Cell
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
));
107 * Increment the column from the specific family with the specified qualifier
108 * by the specified amount.
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
));
127 * Gets the TimeRange used for this increment.
130 public TimeRange
getTimeRange() {
135 * Sets the TimeRange to be used on the Get for this increment.
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.
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
150 public Increment
setTimeRange(long minStamp
, long maxStamp
)
152 tr
= new TimeRange(minStamp
, maxStamp
);
157 public Increment
setTimestamp(long timestamp
) {
158 super.setTimestamp(timestamp
);
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
168 public Increment
setReturnResults(boolean returnResults
) {
169 super.setReturnResults(returnResults
);
174 * @return current setting for returnResults
176 // This method makes public the superclasses's protected method.
178 public boolean isReturnResults() {
179 return super.isReturnResults();
183 * Method for retrieving the number of families to increment from
184 * @return number of families
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
204 * @return Map of families to a Map of qualifiers and their Long increments.
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
);
225 public String
toString() {
226 StringBuilder sb
= new StringBuilder();
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()) {
242 sb
.append("(family=");
243 sb
.append(Bytes
.toString(entry
.getKey()));
244 sb
.append(", columns=");
245 if(entry
.getValue() == null) {
249 boolean moreThanOneB
= false;
250 for(Cell cell
: entry
.getValue()) {
256 sb
.append(CellUtil
.getCellKeyAsString(cell
) + "+=" +
257 Bytes
.toLong(cell
.getValueArray(), cell
.getValueOffset(), cell
.getValueLength()));
263 return sb
.toString();
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());
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());
280 public boolean equals(Object obj
) {
281 // TODO: This is wrong. Can't have two the same just because on same row.
285 if (obj
== null || getClass() != obj
.getClass()) {
288 Row other
= (Row
) obj
;
289 return compareTo(other
) == 0;
293 protected long extraHeapSize(){
294 return HEAP_OVERHEAD
;
298 public Increment
setAttribute(String name
, byte[] value
) {
299 return (Increment
) super.setAttribute(name
, value
);
303 public Increment
setId(String id
) {
304 return (Increment
) super.setId(id
);
308 public Increment
setDurability(Durability d
) {
309 return (Increment
) super.setDurability(d
);
313 public Increment
setFamilyCellMap(NavigableMap
<byte[], List
<Cell
>> map
) {
314 return (Increment
) super.setFamilyCellMap(map
);
318 public Increment
setClusterIds(List
<UUID
> clusterIds
) {
319 return (Increment
) super.setClusterIds(clusterIds
);
323 public Increment
setCellVisibility(CellVisibility expression
) {
324 return (Increment
) super.setCellVisibility(expression
);
328 public Increment
setACL(String user
, Permission perms
) {
329 return (Increment
) super.setACL(user
, perms
);
333 public Increment
setACL(Map
<String
, Permission
> perms
) {
334 return (Increment
) super.setACL(perms
);
338 public Increment
setTTL(long ttl
) {
339 return (Increment
) super.setTTL(ttl
);
343 public Increment
setPriority(int priority
) {
344 return (Increment
) super.setPriority(priority
);