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