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.nio.ByteBuffer;
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.HConstants;
028import org.apache.hadoop.hbase.IndividualBytesFieldCell;
029import org.apache.hadoop.hbase.KeyValue;
030import org.apache.hadoop.hbase.io.HeapSize;
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.yetus.audience.InterfaceAudience;
035
036/**
037 * Used to perform Put operations for a single row.
038 * <p>
039 * To perform a Put, instantiate a Put object with the row to insert to, and for each column to be
040 * inserted, execute {@link #addColumn(byte[], byte[], byte[]) add} or
041 * {@link #addColumn(byte[], byte[], long, byte[]) add} if setting the timestamp.
042 */
043@InterfaceAudience.Public
044public class Put extends Mutation implements HeapSize {
045  /**
046   * Create a Put operation for the specified row.
047   * @param row row key
048   */
049  public Put(byte[] row) {
050    this(row, HConstants.LATEST_TIMESTAMP);
051  }
052
053  /**
054   * Create a Put operation for the specified row, using a given timestamp.
055   * @param row row key; we make a copy of what we are passed to keep local.
056   * @param ts  timestamp
057   */
058  public Put(byte[] row, long ts) {
059    this(row, 0, row.length, ts);
060  }
061
062  /**
063   * We make a copy of the passed in row key to keep local.
064   */
065  public Put(byte[] rowArray, int rowOffset, int rowLength) {
066    this(rowArray, rowOffset, rowLength, HConstants.LATEST_TIMESTAMP);
067  }
068
069  /**
070   * @param row row key; we make a copy of what we are passed to keep local.
071   * @param ts  timestamp
072   */
073  public Put(ByteBuffer row, long ts) {
074    if (ts < 0) {
075      throw new IllegalArgumentException("Timestamp cannot be negative. ts=" + ts);
076    }
077    checkRow(row);
078    this.row = new byte[row.remaining()];
079    row.get(this.row);
080    this.ts = ts;
081  }
082
083  /**
084   * @param row row key; we make a copy of what we are passed to keep local.
085   */
086  public Put(ByteBuffer row) {
087    this(row, HConstants.LATEST_TIMESTAMP);
088  }
089
090  /**
091   * We make a copy of the passed in row key to keep local.
092   */
093  public Put(byte[] rowArray, int rowOffset, int rowLength, long ts) {
094    checkRow(rowArray, rowOffset, rowLength);
095    this.row = Bytes.copy(rowArray, rowOffset, rowLength);
096    this.ts = ts;
097    if (ts < 0) {
098      throw new IllegalArgumentException("Timestamp cannot be negative. ts=" + ts);
099    }
100  }
101
102  /**
103   * Create a Put operation for an immutable row key.
104   * @param row            row key
105   * @param rowIsImmutable whether the input row is immutable. Set to true if the caller can
106   *                       guarantee that the row will not be changed for the Put duration.
107   */
108  public Put(byte[] row, boolean rowIsImmutable) {
109    this(row, HConstants.LATEST_TIMESTAMP, rowIsImmutable);
110  }
111
112  /**
113   * Create a Put operation for an immutable row key, using a given timestamp.
114   * @param row            row key
115   * @param ts             timestamp
116   * @param rowIsImmutable whether the input row is immutable. Set to true if the caller can
117   *                       guarantee that the row will not be changed for the Put duration.
118   */
119  public Put(byte[] row, long ts, boolean rowIsImmutable) {
120    // Check and set timestamp
121    if (ts < 0) {
122      throw new IllegalArgumentException("Timestamp cannot be negative. ts=" + ts);
123    }
124    this.ts = ts;
125
126    // Deal with row according to rowIsImmutable
127    checkRow(row);
128    if (rowIsImmutable) { // Row is immutable
129      this.row = row; // Do not make a local copy, but point to the provided byte array directly
130    } else { // Row is not immutable
131      this.row = Bytes.copy(row, 0, row.length); // Make a local copy
132    }
133  }
134
135  /**
136   * Copy constructor. Creates a Put operation cloned from the specified Put.
137   * @param putToCopy put to copy
138   */
139  public Put(Put putToCopy) {
140    super(putToCopy);
141  }
142
143  /**
144   * Construct the Put with user defined data. NOTED: 1) all cells in the familyMap must have the
145   * Type.Put 2) the row of each cell must be same with passed row.
146   * @param row       row. CAN'T be null
147   * @param ts        timestamp
148   * @param familyMap the map to collect all cells internally. CAN'T be null
149   */
150  public Put(byte[] row, long ts, NavigableMap<byte[], List<Cell>> familyMap) {
151    super(row, ts, familyMap);
152  }
153
154  /**
155   * Add the specified column and value to this Put operation.
156   * @param family    family name
157   * @param qualifier column qualifier
158   * @param value     column value
159   */
160  public Put addColumn(byte[] family, byte[] qualifier, byte[] value) {
161    return addColumn(family, qualifier, this.ts, value);
162  }
163
164  /**
165   * See {@link #addColumn(byte[], byte[], byte[])}. This version expects that the underlying arrays
166   * won't change. It's intended for usage internal HBase to and for advanced client applications.
167   * @deprecated As of release 2.0.0, this will be removed in HBase 3.0.0. Use {@link #add(Cell)}
168   *             and {@link org.apache.hadoop.hbase.CellBuilder} instead
169   */
170  @Deprecated
171  public Put addImmutable(byte[] family, byte[] qualifier, byte[] value) {
172    return addImmutable(family, qualifier, this.ts, value);
173  }
174
175  /**
176   * Add the specified column and value, with the specified timestamp as its version to this Put
177   * operation.
178   * @param family    family name
179   * @param qualifier column qualifier
180   * @param ts        version timestamp
181   * @param value     column value
182   */
183  public Put addColumn(byte[] family, byte[] qualifier, long ts, byte[] value) {
184    if (ts < 0) {
185      throw new IllegalArgumentException("Timestamp cannot be negative. ts=" + ts);
186    }
187    List<Cell> list = getCellList(family);
188    KeyValue kv = createPutKeyValue(family, qualifier, ts, value);
189    list.add(kv);
190    return this;
191  }
192
193  /**
194   * See {@link #addColumn(byte[], byte[], long, byte[])}. This version expects that the underlying
195   * arrays won't change. It's intended for usage internal HBase to and for advanced client
196   * applications.
197   * @deprecated As of release 2.0.0, this will be removed in HBase 3.0.0. Use {@link #add(Cell)}
198   *             and {@link org.apache.hadoop.hbase.CellBuilder} instead
199   */
200  @Deprecated
201  public Put addImmutable(byte[] family, byte[] qualifier, long ts, byte[] value) {
202    // Family can not be null, otherwise NullPointerException is thrown when putting the cell into
203    // familyMap
204    if (family == null) {
205      throw new IllegalArgumentException("Family cannot be null");
206    }
207
208    // Check timestamp
209    if (ts < 0) {
210      throw new IllegalArgumentException("Timestamp cannot be negative. ts=" + ts);
211    }
212
213    List<Cell> list = getCellList(family);
214    list
215      .add(new IndividualBytesFieldCell(this.row, family, qualifier, ts, KeyValue.Type.Put, value));
216    return this;
217  }
218
219  /**
220   * Add the specified column and value, with the specified timestamp as its version to this Put
221   * operation.
222   * @param family    family name
223   * @param qualifier column qualifier
224   * @param ts        version timestamp
225   * @param value     column value
226   */
227  public Put addColumn(byte[] family, ByteBuffer qualifier, long ts, ByteBuffer value) {
228    if (ts < 0) {
229      throw new IllegalArgumentException("Timestamp cannot be negative. ts=" + ts);
230    }
231    List<Cell> list = getCellList(family);
232    KeyValue kv = createPutKeyValue(family, qualifier, ts, value, null);
233    list.add(kv);
234    return this;
235  }
236
237  /**
238   * See {@link #addColumn(byte[], ByteBuffer, long, ByteBuffer)}. This version expects that the
239   * underlying arrays won't change. It's intended for usage internal HBase to and for advanced
240   * client applications.
241   * @deprecated As of release 2.0.0, this will be removed in HBase 3.0.0. Use {@link #add(Cell)}
242   *             and {@link org.apache.hadoop.hbase.CellBuilder} instead
243   */
244  @Deprecated
245  public Put addImmutable(byte[] family, ByteBuffer qualifier, long ts, ByteBuffer value) {
246    if (ts < 0) {
247      throw new IllegalArgumentException("Timestamp cannot be negative. ts=" + ts);
248    }
249    List<Cell> list = getCellList(family);
250    KeyValue kv = createPutKeyValue(family, qualifier, ts, value, null);
251    list.add(kv);
252    return this;
253  }
254
255  /**
256   * Add the specified KeyValue to this Put operation. Operation assumes that the passed KeyValue is
257   * immutable and its backing array will not be modified for the duration of this Put.
258   * @param cell individual cell
259   * @throws java.io.IOException e
260   */
261  @Override
262  public Put add(Cell cell) throws IOException {
263    super.add(cell);
264    return this;
265  }
266
267  @Override
268  public Put setTimestamp(long timestamp) {
269    super.setTimestamp(timestamp);
270    return this;
271  }
272
273  @Override
274  public Put setAttribute(String name, byte[] value) {
275    return (Put) super.setAttribute(name, value);
276  }
277
278  @Override
279  public Put setId(String id) {
280    return (Put) super.setId(id);
281  }
282
283  @Override
284  public Put setDurability(Durability d) {
285    return (Put) super.setDurability(d);
286  }
287
288  /**
289   * Method for setting the put's familyMap
290   * @deprecated As of release 2.0.0, this will be removed in HBase 3.0.0. Use
291   *             {@link Put#Put(byte[], long, NavigableMap)} instead
292   */
293  @Deprecated
294  @Override
295  public Put setFamilyCellMap(NavigableMap<byte[], List<Cell>> map) {
296    return (Put) super.setFamilyCellMap(map);
297  }
298
299  @Override
300  public Put setClusterIds(List<UUID> clusterIds) {
301    return (Put) super.setClusterIds(clusterIds);
302  }
303
304  @Override
305  public Put setCellVisibility(CellVisibility expression) {
306    return (Put) super.setCellVisibility(expression);
307  }
308
309  @Override
310  public Put setACL(String user, Permission perms) {
311    return (Put) super.setACL(user, perms);
312  }
313
314  @Override
315  public Put setACL(Map<String, Permission> perms) {
316    return (Put) super.setACL(perms);
317  }
318
319  @Override
320  public Put setTTL(long ttl) {
321    return (Put) super.setTTL(ttl);
322  }
323
324  @Override
325  public Put setPriority(int priority) {
326    return (Put) super.setPriority(priority);
327  }
328}