1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 */
18 package org.apache.hadoop.hbase.client;
19
20 import java.util.ArrayList;
21 import java.util.List;
22 import java.util.Map;
23 import java.util.NavigableMap;
24 import java.util.UUID;
25
26 import org.apache.hadoop.hbase.classification.InterfaceAudience;
27 import org.apache.hadoop.hbase.classification.InterfaceStability;
28 import org.apache.hadoop.hbase.Cell;
29 import org.apache.hadoop.hbase.CellUtil;
30 import org.apache.hadoop.hbase.KeyValue;
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
35 /**
36 * Performs Append operations on a single row.
37 * <p>
38 * Note that this operation does not appear atomic to readers. Appends are done
39 * under a single row lock, so write operations to a row are synchronized, but
40 * readers do not take row locks so get and scan operations can see this
41 * operation partially completed.
42 * <p>
43 * To append to a set of columns of a row, instantiate an Append object with the
44 * row to append to. At least one column to append must be specified using the
45 * {@link #add(byte[], byte[], byte[])} method.
46 */
47 @InterfaceAudience.Public
48 @InterfaceStability.Stable
49 public class Append extends Mutation {
50 private static final String RETURN_RESULTS = "_rr_";
51 /**
52 * @param returnResults
53 * True (default) if the append operation should return the results.
54 * A client that is not interested in the result can save network
55 * bandwidth setting this to false.
56 */
57 public void setReturnResults(boolean returnResults) {
58 setAttribute(RETURN_RESULTS, Bytes.toBytes(returnResults));
59 }
60
61 /**
62 * @return current setting for returnResults
63 */
64 public boolean isReturnResults() {
65 byte[] v = getAttribute(RETURN_RESULTS);
66 return v == null ? true : Bytes.toBoolean(v);
67 }
68
69 /**
70 * Create a Append operation for the specified row.
71 * <p>
72 * At least one column must be appended to.
73 * @param row row key; makes a local copy of passed in array.
74 */
75 public Append(byte[] row) {
76 this(row, 0, row.length);
77 }
78 /**
79 * Copy constructor
80 * @param a
81 */
82 public Append(Append a) {
83 this.row = a.getRow();
84 this.ts = a.getTimeStamp();
85 this.familyMap.putAll(a.getFamilyCellMap());
86 for (Map.Entry<String, byte[]> entry : a.getAttributesMap().entrySet()) {
87 this.setAttribute(entry.getKey(), entry.getValue());
88 }
89 }
90
91 /** Create a Append operation for the specified row.
92 * <p>
93 * At least one column must be appended to.
94 * @param rowArray Makes a copy out of this buffer.
95 * @param rowOffset
96 * @param rowLength
97 */
98 public Append(final byte [] rowArray, final int rowOffset, final int rowLength) {
99 checkRow(rowArray, rowOffset, rowLength);
100 this.row = Bytes.copy(rowArray, rowOffset, rowLength);
101 }
102
103 /**
104 * Add the specified column and value to this Append operation.
105 * @param family family name
106 * @param qualifier column qualifier
107 * @param value value to append to specified column
108 * @return this
109 */
110 public Append add(byte [] family, byte [] qualifier, byte [] value) {
111 KeyValue kv = new KeyValue(this.row, family, qualifier, this.ts, KeyValue.Type.Put, value);
112 return add(kv);
113 }
114
115 /**
116 * Add column and value to this Append operation.
117 * @param cell
118 * @return This instance
119 */
120 @SuppressWarnings("unchecked")
121 public Append add(final Cell cell) {
122 // Presume it is KeyValue for now.
123 byte [] family = CellUtil.cloneFamily(cell);
124 List<Cell> list = this.familyMap.get(family);
125 if (list == null) {
126 list = new ArrayList<Cell>();
127 }
128 // find where the new entry should be placed in the List
129 list.add(cell);
130 this.familyMap.put(family, list);
131 return this;
132 }
133 }