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