View Javadoc

1   /*
2    *
3    * Licensed to the Apache Software Foundation (ASF) under one
4    * or more contributor license agreements.  See the NOTICE file
5    * distributed with this work for additional information
6    * regarding copyright ownership.  The ASF licenses this file
7    * to you under the Apache License, Version 2.0 (the
8    * "License"); you may not use this file except in compliance
9    * with the License.  You may obtain a copy of the License at
10   *
11   *     http://www.apache.org/licenses/LICENSE-2.0
12   *
13   * Unless required by applicable law or agreed to in writing, software
14   * distributed under the License is distributed on an "AS IS" BASIS,
15   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16   * See the License for the specific language governing permissions and
17   * limitations under the License.
18   */
19  
20  package org.apache.hadoop.hbase.client;
21  
22  import java.io.IOException;
23  import java.util.ArrayList;
24  import java.util.List;
25  import java.util.Map;
26  
27  import org.apache.hadoop.classification.InterfaceAudience;
28  import org.apache.hadoop.classification.InterfaceStability;
29  import org.apache.hadoop.hbase.Cell;
30  import org.apache.hadoop.hbase.HConstants;
31  import org.apache.hadoop.hbase.KeyValue;
32  import org.apache.hadoop.hbase.util.Bytes;
33  
34  /**
35   * Used to perform Delete operations on a single row.
36   * <p>
37   * To delete an entire row, instantiate a Delete object with the row
38   * to delete.  To further define the scope of what to delete, perform
39   * additional methods as outlined below.
40   * <p>
41   * To delete specific families, execute {@link #deleteFamily(byte[]) deleteFamily}
42   * for each family to delete.
43   * <p>
44   * To delete multiple versions of specific columns, execute
45   * {@link #deleteColumns(byte[], byte[]) deleteColumns}
46   * for each column to delete.
47   * <p>
48   * To delete specific versions of specific columns, execute
49   * {@link #deleteColumn(byte[], byte[], long) deleteColumn}
50   * for each column version to delete.
51   * <p>
52   * Specifying timestamps, deleteFamily and deleteColumns will delete all
53   * versions with a timestamp less than or equal to that passed.  If no
54   * timestamp is specified, an entry is added with a timestamp of 'now'
55   * where 'now' is the servers's System.currentTimeMillis().
56   * Specifying a timestamp to the deleteColumn method will
57   * delete versions only with a timestamp equal to that specified.
58   * If no timestamp is passed to deleteColumn, internally, it figures the
59   * most recent cell's timestamp and adds a delete at that timestamp; i.e.
60   * it deletes the most recently added cell.
61   * <p>The timestamp passed to the constructor is used ONLY for delete of
62   * rows.  For anything less -- a deleteColumn, deleteColumns or
63   * deleteFamily -- then you need to use the method overrides that take a
64   * timestamp.  The constructor timestamp is not referenced.
65   */
66  @InterfaceAudience.Public
67  @InterfaceStability.Stable
68  public class Delete extends Mutation implements Comparable<Row> {
69    /**
70     * Create a Delete operation for the specified row.
71     * <p>
72     * If no further operations are done, this will delete everything
73     * associated with the specified row (all versions of all columns in all
74     * families).
75     * @param row row key
76     */
77    public Delete(byte [] row) {
78      this(row, HConstants.LATEST_TIMESTAMP);
79    }
80  
81    /**
82     * Create a Delete operation for the specified row and timestamp.<p>
83     *
84     * If no further operations are done, this will delete all columns in all
85     * families of the specified row with a timestamp less than or equal to the
86     * specified timestamp.<p>
87     *
88     * This timestamp is ONLY used for a delete row operation.  If specifying
89     * families or columns, you must specify each timestamp individually.
90     * @param row row key
91     * @param timestamp maximum version timestamp (only for delete row)
92     */
93    public Delete(byte [] row, long timestamp) {
94      this(row, 0, row.length, timestamp);
95    }
96  
97    /**
98     * Create a Delete operation for the specified row and timestamp.<p>
99     *
100    * If no further operations are done, this will delete all columns in all
101    * families of the specified row with a timestamp less than or equal to the
102    * specified timestamp.<p>
103    *
104    * This timestamp is ONLY used for a delete row operation.  If specifying
105    * families or columns, you must specify each timestamp individually.
106    * @param rowArray We make a local copy of this passed in row.
107    * @param rowOffset
108    * @param rowLength
109    */
110   public Delete(final byte [] rowArray, final int rowOffset, final int rowLength) {
111     this(rowArray, rowOffset, rowLength, HConstants.LATEST_TIMESTAMP);
112   }
113 
114   /**
115    * Create a Delete operation for the specified row and timestamp.<p>
116    *
117    * If no further operations are done, this will delete all columns in all
118    * families of the specified row with a timestamp less than or equal to the
119    * specified timestamp.<p>
120    *
121    * This timestamp is ONLY used for a delete row operation.  If specifying
122    * families or columns, you must specify each timestamp individually.
123    * @param rowArray We make a local copy of this passed in row.
124    * @param rowOffset
125    * @param rowLength
126    * @param ts maximum version timestamp (only for delete row)
127    */
128   public Delete(final byte [] rowArray, final int rowOffset, final int rowLength, long ts) {
129     checkRow(rowArray, rowOffset, rowLength);
130     this.row = Bytes.copy(rowArray, rowOffset, rowLength);
131     this.ts = ts;
132   }
133 
134   /**
135    * @param d Delete to clone.
136    */
137   public Delete(final Delete d) {
138     this.row = d.getRow();
139     this.ts = d.getTimeStamp();
140     this.familyMap.putAll(d.getFamilyCellMap());
141     this.durability = d.durability;
142   }
143 
144   /**
145    * Advanced use only.
146    * Add an existing delete marker to this Delete object.
147    * @param kv An existing KeyValue of type "delete".
148    * @return this for invocation chaining
149    * @throws IOException
150    */
151   @SuppressWarnings("unchecked")
152   public Delete addDeleteMarker(KeyValue kv) throws IOException {
153     // TODO: Deprecate and rename 'add' so it matches how we add KVs to Puts.
154     if (!kv.isDelete()) {
155       throw new IOException("The recently added KeyValue is not of type "
156           + "delete. Rowkey: " + Bytes.toStringBinary(this.row));
157     }
158     if (Bytes.compareTo(this.row, 0, row.length, kv.getBuffer(),
159         kv.getRowOffset(), kv.getRowLength()) != 0) {
160       throw new WrongRowIOException("The row in " + kv.toString() +
161         " doesn't match the original one " +  Bytes.toStringBinary(this.row));
162     }
163     byte [] family = kv.getFamily();
164     List<Cell> list = familyMap.get(family);
165     if (list == null) {
166       list = new ArrayList<Cell>();
167     }
168     list.add(kv);
169     familyMap.put(family, list);
170     return this;
171   }
172 
173   /**
174    * Delete all versions of all columns of the specified family.
175    * <p>
176    * Overrides previous calls to deleteColumn and deleteColumns for the
177    * specified family.
178    * @param family family name
179    * @return this for invocation chaining
180    */
181   public Delete deleteFamily(byte [] family) {
182     this.deleteFamily(family, HConstants.LATEST_TIMESTAMP);
183     return this;
184   }
185 
186   /**
187    * Delete all columns of the specified family with a timestamp less than
188    * or equal to the specified timestamp.
189    * <p>
190    * Overrides previous calls to deleteColumn and deleteColumns for the
191    * specified family.
192    * @param family family name
193    * @param timestamp maximum version timestamp
194    * @return this for invocation chaining
195    */
196   @SuppressWarnings("unchecked")
197   public Delete deleteFamily(byte [] family, long timestamp) {
198     List<Cell> list = familyMap.get(family);
199     if(list == null) {
200       list = new ArrayList<Cell>();
201     } else if(!list.isEmpty()) {
202       list.clear();
203     }
204     KeyValue kv = new KeyValue(row, family, null, timestamp, KeyValue.Type.DeleteFamily);
205     list.add(kv);
206     familyMap.put(family, list);
207     return this;
208   }
209 
210   /**
211    * Delete all columns of the specified family with a timestamp equal to
212    * the specified timestamp.
213    * @param family family name
214    * @param timestamp version timestamp
215    * @return this for invocation chaining
216    */
217   public Delete deleteFamilyVersion(byte [] family, long timestamp) {
218     List<Cell> list = familyMap.get(family);
219     if(list == null) {
220       list = new ArrayList<Cell>();
221     }
222     list.add(new KeyValue(row, family, null, timestamp,
223           KeyValue.Type.DeleteFamilyVersion));
224     familyMap.put(family, list);
225     return this;
226   }
227 
228 
229   /**
230    * Delete all versions of the specified column.
231    * @param family family name
232    * @param qualifier column qualifier
233    * @return this for invocation chaining
234    */
235   public Delete deleteColumns(byte [] family, byte [] qualifier) {
236     this.deleteColumns(family, qualifier, HConstants.LATEST_TIMESTAMP);
237     return this;
238   }
239 
240   /**
241    * Delete all versions of the specified column with a timestamp less than
242    * or equal to the specified timestamp.
243    * @param family family name
244    * @param qualifier column qualifier
245    * @param timestamp maximum version timestamp
246    * @return this for invocation chaining
247    */
248   @SuppressWarnings("unchecked")
249   public Delete deleteColumns(byte [] family, byte [] qualifier, long timestamp) {
250     List<Cell> list = familyMap.get(family);
251     if (list == null) {
252       list = new ArrayList<Cell>();
253     }
254     list.add(new KeyValue(this.row, family, qualifier, timestamp,
255         KeyValue.Type.DeleteColumn));
256     familyMap.put(family, list);
257     return this;
258   }
259 
260   /**
261    * Delete the latest version of the specified column.
262    * This is an expensive call in that on the server-side, it first does a
263    * get to find the latest versions timestamp.  Then it adds a delete using
264    * the fetched cells timestamp.
265    * @param family family name
266    * @param qualifier column qualifier
267    * @return this for invocation chaining
268    */
269   public Delete deleteColumn(byte [] family, byte [] qualifier) {
270     this.deleteColumn(family, qualifier, HConstants.LATEST_TIMESTAMP);
271     return this;
272   }
273 
274   /**
275    * Delete the specified version of the specified column.
276    * @param family family name
277    * @param qualifier column qualifier
278    * @param timestamp version timestamp
279    * @return this for invocation chaining
280    */
281   @SuppressWarnings("unchecked")
282   public Delete deleteColumn(byte [] family, byte [] qualifier, long timestamp) {
283     List<Cell> list = familyMap.get(family);
284     if(list == null) {
285       list = new ArrayList<Cell>();
286     }
287     KeyValue kv = new KeyValue(this.row, family, qualifier, timestamp, KeyValue.Type.Delete);
288     list.add(kv);
289     familyMap.put(family, list);
290     return this;
291   }
292 
293   /**
294    * Set the timestamp of the delete.
295    * 
296    * @param timestamp
297    */
298   public void setTimestamp(long timestamp) {
299     this.ts = timestamp;
300   }
301 
302   @Override
303   public Map<String, Object> toMap(int maxCols) {
304     // we start with the fingerprint map and build on top of it.
305     Map<String, Object> map = super.toMap(maxCols);
306     // why is put not doing this?
307     map.put("ts", this.ts);
308     return map;
309   }
310 }