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 040 * under a single row lock, so write operations to a row are synchronized, and 041 * readers are guaranteed to see this operation fully completed. 042 * <p> 043 * To append to a set of columns of a row, instantiate an Append object with the 044 * row to append to. 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 = 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 057 * periods of time (ie. counters that are partitioned by time). By setting 058 * the range of valid times for this append, you can potentially gain 059 * some performance with a more optimal Get operation. 060 * Be careful adding the time range to this class as you will update the old cell if the 061 * time range doesn't include the latest cells. 062 * <p> 063 * This range is used as [minStamp, maxStamp). 064 * @param minStamp minimum timestamp value, inclusive 065 * @param maxStamp maximum timestamp value, exclusive 066 * @return this 067 */ 068 public Append setTimeRange(long minStamp, long maxStamp) { 069 tr = new TimeRange(minStamp, maxStamp); 070 return this; 071 } 072 073 /** 074 * Gets the TimeRange used for this append. 075 * @return TimeRange 076 */ 077 public TimeRange getTimeRange() { 078 return this.tr; 079 } 080 081 @Override 082 protected long extraHeapSize(){ 083 return HEAP_OVERHEAD; 084 } 085 086 /** 087 * @param returnResults 088 * True (default) if the append operation should return the results. 089 * A client that is not interested in the result can save network 090 * bandwidth setting this to false. 091 */ 092 @Override 093 public Append setReturnResults(boolean returnResults) { 094 super.setReturnResults(returnResults); 095 return this; 096 } 097 098 /** 099 * @return current setting for returnResults 100 */ 101 // This method makes public the superclasses's protected method. 102 @Override 103 public boolean isReturnResults() { 104 return super.isReturnResults(); 105 } 106 107 /** 108 * Create a Append operation for the specified row. 109 * <p> 110 * At least one column must be appended to. 111 * @param row row key; makes a local copy of passed in array. 112 */ 113 public Append(byte[] row) { 114 this(row, 0, row.length); 115 } 116 /** 117 * Copy constructor 118 * @param appendToCopy append to copy 119 */ 120 public Append(Append appendToCopy) { 121 super(appendToCopy); 122 this.tr = appendToCopy.getTimeRange(); 123 } 124 125 /** Create a Append operation for the specified row. 126 * <p> 127 * At least one column must be appended to. 128 * @param rowArray Makes a copy out of this buffer. 129 * @param rowOffset 130 * @param rowLength 131 */ 132 public Append(final byte [] rowArray, final int rowOffset, final int rowLength) { 133 checkRow(rowArray, rowOffset, rowLength); 134 this.row = Bytes.copy(rowArray, rowOffset, rowLength); 135 } 136 137 /** 138 * Construct the Append with user defined data. NOTED: 139 * 1) all cells in the familyMap must have the Type.Put 140 * 2) the row of each cell must be same with passed row. 141 * @param row row. CAN'T be null 142 * @param ts timestamp 143 * @param familyMap the map to collect all cells internally. CAN'T be null 144 */ 145 public Append(byte[] row, long ts, NavigableMap<byte [], List<Cell>> familyMap) { 146 super(row, ts, familyMap); 147 } 148 149 /** 150 * Add the specified column and value to this Append operation. 151 * @param family family name 152 * @param qualifier column qualifier 153 * @param value value to append to specified column 154 * @return this 155 * @deprecated As of release 2.0.0, this will be removed in HBase 3.0.0. 156 * Use {@link #addColumn(byte[], byte[], byte[])} instead 157 */ 158 @Deprecated 159 public Append add(byte [] family, byte [] qualifier, byte [] value) { 160 return this.addColumn(family, qualifier, value); 161 } 162 163 /** 164 * Add the specified column and value to this Append operation. 165 * @param family family name 166 * @param qualifier column qualifier 167 * @param value value to append to specified column 168 * @return this 169 */ 170 public Append addColumn(byte[] family, byte[] qualifier, byte[] value) { 171 KeyValue kv = new KeyValue(this.row, family, qualifier, this.ts, KeyValue.Type.Put, value); 172 return add(kv); 173 } 174 175 /** 176 * Add column and value to this Append operation. 177 * @param cell 178 * @return This instance 179 */ 180 @SuppressWarnings("unchecked") 181 public Append add(final Cell cell) { 182 try { 183 super.add(cell); 184 } catch (IOException e) { 185 // we eat the exception of wrong row for BC.. 186 LOG.error(e.toString(), e); 187 } 188 return this; 189 } 190 191 @Override 192 public Append setTimestamp(long timestamp) { 193 super.setTimestamp(timestamp); 194 return this; 195 } 196 197 @Override 198 public Append setAttribute(String name, byte[] value) { 199 return (Append) super.setAttribute(name, value); 200 } 201 202 @Override 203 public Append setId(String id) { 204 return (Append) super.setId(id); 205 } 206 207 @Override 208 public Append setDurability(Durability d) { 209 return (Append) super.setDurability(d); 210 } 211 212 /** 213 * Method for setting the Append's familyMap 214 * @deprecated As of release 2.0.0, this will be removed in HBase 3.0.0. 215 * Use {@link Append#Append(byte[], long, NavigableMap)} instead 216 */ 217 @Deprecated 218 @Override 219 public Append setFamilyCellMap(NavigableMap<byte[], List<Cell>> map) { 220 return (Append) super.setFamilyCellMap(map); 221 } 222 223 @Override 224 public Append setClusterIds(List<UUID> clusterIds) { 225 return (Append) super.setClusterIds(clusterIds); 226 } 227 228 @Override 229 public Append setCellVisibility(CellVisibility expression) { 230 return (Append) super.setCellVisibility(expression); 231 } 232 233 @Override 234 public Append setACL(String user, Permission perms) { 235 return (Append) super.setACL(user, perms); 236 } 237 238 @Override 239 public Append setACL(Map<String, Permission> perms) { 240 return (Append) super.setACL(perms); 241 } 242 243 @Override 244 public Append setPriority(int priority) { 245 return (Append) super.setPriority(priority); 246 } 247 248 @Override 249 public Append setTTL(long ttl) { 250 return (Append) super.setTTL(ttl); 251 } 252}