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.io.UncheckedIOException; 022import java.util.List; 023import java.util.Map; 024import java.util.NavigableMap; 025import java.util.UUID; 026import org.apache.hadoop.hbase.Cell; 027import org.apache.hadoop.hbase.CellBuilder; 028import org.apache.hadoop.hbase.CellBuilderType; 029import org.apache.hadoop.hbase.KeyValue; 030import org.apache.hadoop.hbase.io.TimeRange; 031import org.apache.hadoop.hbase.security.access.Permission; 032import org.apache.hadoop.hbase.security.visibility.CellVisibility; 033import org.apache.hadoop.hbase.util.Bytes; 034import org.apache.hadoop.hbase.util.ClassSize; 035import org.apache.yetus.audience.InterfaceAudience; 036import org.slf4j.Logger; 037import org.slf4j.LoggerFactory; 038 039/** 040 * Performs Append operations on a single row. 041 * <p> 042 * This operation ensures atomicty to readers. Appends are done under a single row lock, so write 043 * operations to a row are synchronized, and readers are guaranteed to see this operation fully 044 * completed. 045 * <p> 046 * To append to a set of columns of a row, instantiate an Append object with the row to append to. 047 * At least one column to append must be specified using the 048 * {@link #addColumn(byte[], byte[], byte[])} method. 049 */ 050@InterfaceAudience.Public 051public class Append extends Mutation { 052 private static final Logger LOG = LoggerFactory.getLogger(Append.class); 053 private static final long HEAP_OVERHEAD = (long) ClassSize.REFERENCE + ClassSize.TIMERANGE; 054 private TimeRange tr = TimeRange.allTime(); 055 056 /** 057 * Sets the TimeRange to be used on the Get for this append. 058 * <p> 059 * This is useful for when you have counters that only last for specific periods of time (ie. 060 * counters that are partitioned by time). By setting the range of valid times for this append, 061 * you can potentially gain some performance with a more optimal Get operation. Be careful adding 062 * the time range to this class as you will update the old cell if the time range doesn't include 063 * the latest cells. 064 * <p> 065 * This range is used as [minStamp, maxStamp). 066 * @param minStamp minimum timestamp value, inclusive 067 * @param maxStamp maximum timestamp value, exclusive 068 */ 069 public Append setTimeRange(long minStamp, long maxStamp) { 070 tr = TimeRange.between(minStamp, maxStamp); 071 return this; 072 } 073 074 /** 075 * Gets the TimeRange used for this append. 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 * True (default) if the append operation should return the results. A client that is not 088 * interested in the result can save network bandwidth setting this to false. 089 */ 090 @Override 091 public Append setReturnResults(boolean returnResults) { 092 super.setReturnResults(returnResults); 093 return this; 094 } 095 096 /** Returns current setting for returnResults */ 097 // This method makes public the superclasses's protected method. 098 @Override 099 public boolean isReturnResults() { 100 return super.isReturnResults(); 101 } 102 103 /** 104 * Create a Append operation for the specified row. 105 * <p> 106 * At least one column must be appended to. 107 * @param row row key; makes a local copy of passed in array. 108 */ 109 public Append(byte[] row) { 110 this(row, 0, row.length); 111 } 112 113 /** 114 * Copy constructor 115 * @param appendToCopy append to copy 116 */ 117 public Append(Append appendToCopy) { 118 super(appendToCopy); 119 this.tr = appendToCopy.getTimeRange(); 120 } 121 122 /** 123 * Create a Append operation for the specified row. 124 * <p> 125 * At least one column must be appended to. 126 * @param rowArray Makes a copy out of this buffer. 127 */ 128 public Append(final byte[] rowArray, final int rowOffset, final int rowLength) { 129 checkRow(rowArray, rowOffset, rowLength); 130 this.row = Bytes.copy(rowArray, rowOffset, rowLength); 131 } 132 133 /** 134 * Construct the Append with user defined data. NOTED: 1) all cells in the familyMap must have the 135 * Type.Put 2) the row of each cell must be same with passed row. 136 * @param row row. CAN'T be null 137 * @param ts timestamp 138 * @param familyMap the map to collect all cells internally. CAN'T be null 139 */ 140 public Append(byte[] row, long ts, NavigableMap<byte[], List<Cell>> familyMap) { 141 super(row, ts, familyMap); 142 } 143 144 /** 145 * Add the specified column and value to this Append operation. 146 * @param family family name 147 * @param qualifier column qualifier 148 * @param value value to append to specified column 149 */ 150 public Append addColumn(byte[] family, byte[] qualifier, byte[] value) { 151 KeyValue kv = new KeyValue(this.row, family, qualifier, this.ts, KeyValue.Type.Put, value); 152 return add(kv); 153 } 154 155 /** 156 * Add column and value to this Append operation. 157 * @return This instance 158 * @deprecated Since 3.0.0, and the method signature will be changed in 4.0.0, where we will throw 159 * IOException out when the row of the given cell does not match. 160 */ 161 @Deprecated 162 @Override 163 public Append add(final Cell cell) { 164 try { 165 super.add(cell); 166 } catch (IOException e) { 167 // we can not simply change the method signature for a IA.Public method, so here we convert it 168 // to an unchecked exception 169 throw new UncheckedIOException(e); 170 } 171 return this; 172 } 173 174 @Override 175 public Append setTimestamp(long timestamp) { 176 super.setTimestamp(timestamp); 177 return this; 178 } 179 180 @Override 181 public Append setAttribute(String name, byte[] value) { 182 return (Append) super.setAttribute(name, value); 183 } 184 185 @Override 186 public Append setId(String id) { 187 return (Append) super.setId(id); 188 } 189 190 @Override 191 public Append setDurability(Durability d) { 192 return (Append) super.setDurability(d); 193 } 194 195 @Override 196 public Append setClusterIds(List<UUID> clusterIds) { 197 return (Append) super.setClusterIds(clusterIds); 198 } 199 200 @Override 201 public Append setCellVisibility(CellVisibility expression) { 202 return (Append) super.setCellVisibility(expression); 203 } 204 205 @Override 206 public Append setACL(String user, Permission perms) { 207 return (Append) super.setACL(user, perms); 208 } 209 210 @Override 211 public Append setACL(Map<String, Permission> perms) { 212 return (Append) super.setACL(perms); 213 } 214 215 @Override 216 public Append setPriority(int priority) { 217 return (Append) super.setPriority(priority); 218 } 219 220 @Override 221 public Append setTTL(long ttl) { 222 return (Append) super.setTTL(ttl); 223 } 224 225 @Override 226 public CellBuilder getCellBuilder(CellBuilderType type) { 227 return getCellBuilder(type, Cell.Type.Put); 228 } 229}