001/*
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements.  See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership.  The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License.  You may obtain a copy of the License at
009 *
010 *     http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018package org.apache.hadoop.hbase.client;
019
020import java.io.IOException;
021import java.util.List;
022import java.util.Map;
023import java.util.NavigableMap;
024import java.util.UUID;
025import org.apache.hadoop.hbase.Cell;
026import org.apache.hadoop.hbase.KeyValue;
027import org.apache.hadoop.hbase.io.TimeRange;
028import org.apache.hadoop.hbase.security.access.Permission;
029import org.apache.hadoop.hbase.security.visibility.CellVisibility;
030import org.apache.hadoop.hbase.util.Bytes;
031import org.apache.hadoop.hbase.util.ClassSize;
032import org.apache.yetus.audience.InterfaceAudience;
033import org.slf4j.Logger;
034import org.slf4j.LoggerFactory;
035
036/**
037 * Performs Append operations on a single row.
038 * <p>
039 * This operation ensures atomicty to readers. Appends are done under a single row lock, so write
040 * operations to a row are synchronized, and readers are guaranteed to see this operation fully
041 * completed.
042 * <p>
043 * To append to a set of columns of a row, instantiate an Append object with the row to append to.
044 * At least one column to append must be specified using the
045 * {@link #addColumn(byte[], byte[], byte[])} method.
046 */
047@InterfaceAudience.Public
048public class Append extends Mutation {
049  private static final Logger LOG = LoggerFactory.getLogger(Append.class);
050  private static final long HEAP_OVERHEAD = (long) ClassSize.REFERENCE + ClassSize.TIMERANGE;
051  private TimeRange tr = TimeRange.allTime();
052
053  /**
054   * Sets the TimeRange to be used on the Get for this append.
055   * <p>
056   * This is useful for when you have counters that only last for specific periods of time (ie.
057   * counters that are partitioned by time). By setting the range of valid times for this append,
058   * you can potentially gain some performance with a more optimal Get operation. Be careful adding
059   * the time range to this class as you will update the old cell if the time range doesn't include
060   * the latest cells.
061   * <p>
062   * This range is used as [minStamp, maxStamp).
063   * @param minStamp minimum timestamp value, inclusive
064   * @param maxStamp maximum timestamp value, exclusive n
065   */
066  public Append setTimeRange(long minStamp, long maxStamp) {
067    tr = new TimeRange(minStamp, maxStamp);
068    return this;
069  }
070
071  /**
072   * Gets the TimeRange used for this append. n
073   */
074  public TimeRange getTimeRange() {
075    return this.tr;
076  }
077
078  @Override
079  protected long extraHeapSize() {
080    return HEAP_OVERHEAD;
081  }
082
083  /**
084   * n * True (default) if the append operation should return the results. A client that is not
085   * interested in the result can save network bandwidth setting this to false.
086   */
087  @Override
088  public Append setReturnResults(boolean returnResults) {
089    super.setReturnResults(returnResults);
090    return this;
091  }
092
093  /** Returns current setting for returnResults */
094  // This method makes public the superclasses's protected method.
095  @Override
096  public boolean isReturnResults() {
097    return super.isReturnResults();
098  }
099
100  /**
101   * Create a Append operation for the specified row.
102   * <p>
103   * At least one column must be appended to.
104   * @param row row key; makes a local copy of passed in array.
105   */
106  public Append(byte[] row) {
107    this(row, 0, row.length);
108  }
109
110  /**
111   * Copy constructor
112   * @param appendToCopy append to copy
113   */
114  public Append(Append appendToCopy) {
115    super(appendToCopy);
116    this.tr = appendToCopy.getTimeRange();
117  }
118
119  /**
120   * Create a Append operation for the specified row.
121   * <p>
122   * At least one column must be appended to.
123   * @param rowArray Makes a copy out of this buffer. nn
124   */
125  public Append(final byte[] rowArray, final int rowOffset, final int rowLength) {
126    checkRow(rowArray, rowOffset, rowLength);
127    this.row = Bytes.copy(rowArray, rowOffset, rowLength);
128  }
129
130  /**
131   * Construct the Append with user defined data. NOTED: 1) all cells in the familyMap must have the
132   * Type.Put 2) the row of each cell must be same with passed row.
133   * @param row       row. CAN'T be null
134   * @param ts        timestamp
135   * @param familyMap the map to collect all cells internally. CAN'T be null
136   */
137  public Append(byte[] row, long ts, NavigableMap<byte[], List<Cell>> familyMap) {
138    super(row, ts, familyMap);
139  }
140
141  /**
142   * Add the specified column and value to this Append operation.
143   * @param family    family name
144   * @param qualifier column qualifier
145   * @param value     value to append to specified column n * @deprecated As of release 2.0.0, this
146   *                  will be removed in HBase 3.0.0. Use {@link #addColumn(byte[], byte[], byte[])}
147   *                  instead
148   */
149  @Deprecated
150  public Append add(byte[] family, byte[] qualifier, byte[] value) {
151    return this.addColumn(family, qualifier, value);
152  }
153
154  /**
155   * Add the specified column and value to this Append operation.
156   * @param family    family name
157   * @param qualifier column qualifier
158   * @param value     value to append to specified column n
159   */
160  public Append addColumn(byte[] family, byte[] qualifier, byte[] value) {
161    KeyValue kv = new KeyValue(this.row, family, qualifier, this.ts, KeyValue.Type.Put, value);
162    return add(kv);
163  }
164
165  /**
166   * Add column and value to this Append operation. n * @return This instance
167   */
168  @SuppressWarnings("unchecked")
169  @Override
170  public Append add(final Cell cell) {
171    try {
172      super.add(cell);
173    } catch (IOException e) {
174      // we eat the exception of wrong row for BC..
175      LOG.error(e.toString(), e);
176    }
177    return this;
178  }
179
180  @Override
181  public Append setTimestamp(long timestamp) {
182    super.setTimestamp(timestamp);
183    return this;
184  }
185
186  @Override
187  public Append setAttribute(String name, byte[] value) {
188    return (Append) super.setAttribute(name, value);
189  }
190
191  @Override
192  public Append setId(String id) {
193    return (Append) super.setId(id);
194  }
195
196  @Override
197  public Append setDurability(Durability d) {
198    return (Append) super.setDurability(d);
199  }
200
201  /**
202   * Method for setting the Append's familyMap
203   * @deprecated As of release 2.0.0, this will be removed in HBase 3.0.0. Use
204   *             {@link Append#Append(byte[], long, NavigableMap)} instead
205   */
206  @Deprecated
207  @Override
208  public Append setFamilyCellMap(NavigableMap<byte[], List<Cell>> map) {
209    return (Append) super.setFamilyCellMap(map);
210  }
211
212  @Override
213  public Append setClusterIds(List<UUID> clusterIds) {
214    return (Append) super.setClusterIds(clusterIds);
215  }
216
217  @Override
218  public Append setCellVisibility(CellVisibility expression) {
219    return (Append) super.setCellVisibility(expression);
220  }
221
222  @Override
223  public Append setACL(String user, Permission perms) {
224    return (Append) super.setACL(user, perms);
225  }
226
227  @Override
228  public Append setACL(Map<String, Permission> perms) {
229    return (Append) super.setACL(perms);
230  }
231
232  @Override
233  public Append setPriority(int priority) {
234    return (Append) super.setPriority(priority);
235  }
236
237  @Override
238  public Append setTTL(long ttl) {
239    return (Append) super.setTTL(ttl);
240  }
241}