Package org.hbase.async

Source Code of org.hbase.async.DeleteRequest

/*
* Copyright (C) 2010-2012  The Async HBase Authors.  All rights reserved.
* This file is part of Async HBase.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*   - Redistributions of source code must retain the above copyright notice,
*     this list of conditions and the following disclaimer.
*   - Redistributions in binary form must reproduce the above copyright notice,
*     this list of conditions and the following disclaimer in the documentation
*     and/or other materials provided with the distribution.
*   - Neither the name of the StumbleUpon nor the names of its contributors
*     may be used to endorse or promote products derived from this software
*     without specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
package org.hbase.async;

import org.jboss.netty.buffer.ChannelBuffer;

import org.hbase.async.generated.ClientPB.MutateRequest;
import org.hbase.async.generated.ClientPB.MutateResponse;
import org.hbase.async.generated.ClientPB.MutationProto;

/**
* Deletes some data into HBase.
*
* <h1>A note on passing {@code byte} arrays in argument</h1>
* None of the method that receive a {@code byte[]} in argument will copy it.
* For more info, please refer to the documentation of {@link HBaseRpc}.
* <h1>A note on passing {@code String}s in argument</h1>
* All strings are assumed to use the platform's default charset.
* <h1>A note on passing {@code timestamp}s in argument</h1>
* Irrespective of the order in which you send RPCs, a {@code DeleteRequest}
* that is created with a specific timestamp in argument will only delete
* values in HBase that were previously stored with a timestamp less than
* or equal to that of the {@code DeleteRequest} unless
* {@link #setDeleteAtTimestampOnly} is also called, in which case only the
* value at the specified timestamp is deleted.
*/
public final class DeleteRequest extends BatchableRpc
  implements HBaseRpc.HasTable, HBaseRpc.HasKey,
             HBaseRpc.HasFamily, HBaseRpc.HasQualifiers, HBaseRpc.IsEdit {

  private static final byte[] DELETE = new byte[] {
    'd', 'e', 'l', 'e', 't', 'e'
  };

  /** Code type used for serialized `Delete' objects.  */
  static final byte CODE = 31;

  /** Special value for {@link #qualifiers} when deleting a whole family.  */
  private static final byte[][] DELETE_FAMILY_MARKER =
    new byte[][] { HBaseClient.EMPTY_ARRAY };

  /** Special value for {@link #family} when deleting a whole row.  */
  static final byte[] WHOLE_ROW = new byte[0];

  private final byte[][] qualifiers;

  /** Whether to delete the value only at the specified timestamp. */
  private boolean at_timestamp_only = false;

  /**
   * Constructor to delete an entire row.
   * <strong>These byte arrays will NOT be copied.</strong>
   * @param table The table to edit.
   * @param key The key of the row to edit in that table.
   * @throws IllegalArgumentException if any argument is malformed.
   */
  public DeleteRequest(final byte[] table, final byte[] key) {
    this(table, key, null, null, KeyValue.TIMESTAMP_NOW, RowLock.NO_LOCK);
  }

  /**
   * Constructor to delete an entire row before a specific timestamp.
   * <strong>These byte arrays will NOT be copied.</strong>
   * @param table The table to edit.
   * @param key The key of the row to edit in that table.
   * @param timestamp The timestamp to set on this edit.
   * @throws IllegalArgumentException if any argument is malformed.
   * @since 1.2
   */
  public DeleteRequest(final byte[] table, final byte[] key,
                       final long timestamp) {
    this(table, key, null, null, timestamp, RowLock.NO_LOCK);
  }

  /**
   * Constructor to delete a specific family.
   * <strong>These byte arrays will NOT be copied.</strong>
   * @param table The table to edit.
   * @param key The key of the row to edit in that table.
   * @param family The column family to edit in that table.
   * @throws IllegalArgumentException if any argument is malformed.
   * @since 1.1
   */
  public DeleteRequest(final byte[] table,
                       final byte[] key,
                       final byte[] family) {
    this(table, key, family, null, KeyValue.TIMESTAMP_NOW, RowLock.NO_LOCK);
  }

  /**
   * Constructor to delete a specific family before a specific timestamp.
   * <strong>These byte arrays will NOT be copied.</strong>
   * @param table The table to edit.
   * @param key The key of the row to edit in that table.
   * @param family The column family to edit in that table.
   * @param timestamp The timestamp to set on this edit.
   * @throws IllegalArgumentException if any argument is malformed.
   * @since 1.2
   */
  public DeleteRequest(final byte[] table,
                       final byte[] key,
                       final byte[] family,
                       final long timestamp) {
    this(table, key, family, null, timestamp, RowLock.NO_LOCK);
  }

  /**
   * Constructor to delete a specific cell.
   * <strong>These byte arrays will NOT be copied.</strong>
   * @param table The table to edit.
   * @param key The key of the row to edit in that table.
   * @param family The column family to edit in that table.
   * @param qualifier The column qualifier to delete in that family.
   * Can be {@code null} since version 1.1.
   * @throws IllegalArgumentException if any argument is malformed.
   */
  public DeleteRequest(final byte[] table,
                       final byte[] key,
                       final byte[] family,
                       final byte[] qualifier) {
      this(table, key, family,
           qualifier == null ? null : new byte[][] { qualifier },
           KeyValue.TIMESTAMP_NOW, RowLock.NO_LOCK);
  }

  /**
   * Constructor to delete a specific cell before a specific timestamp.
   * <strong>These byte arrays will NOT be copied.</strong>
   * @param table The table to edit.
   * @param key The key of the row to edit in that table.
   * @param family The column family to edit in that table.
   * @param qualifier The column qualifier to delete in that family.
   * Can be {@code null}, to delete the whole family.
   * @param timestamp The timestamp to set on this edit.
   * @throws IllegalArgumentException if any argument is malformed.
   * @since 1.2
   */
  public DeleteRequest(final byte[] table,
                       final byte[] key,
                       final byte[] family,
                       final byte[] qualifier,
                       final long timestamp) {
      this(table, key, family,
           qualifier == null ? null : new byte[][] { qualifier },
           timestamp, RowLock.NO_LOCK);
  }

  /**
   * Constructor to delete a specific number of cells in a row.
   * <strong>These byte arrays will NOT be copied.</strong>
   * @param table The table to edit.
   * @param key The key of the row to edit in that table.
   * @param family The column family to edit in that table.
   * @param qualifiers The column qualifiers to delete in that family.
   * @throws IllegalArgumentException if any argument is malformed.
   * @since 1.1
   */
  public DeleteRequest(final byte[] table,
                       final byte[] key,
                       final byte[] family,
                       final byte[][] qualifiers) {
    this(table, key, family, qualifiers,
         KeyValue.TIMESTAMP_NOW, RowLock.NO_LOCK);
  }

  /**
   * Constructor to delete a specific number of cells in a row.
   * <strong>These byte arrays will NOT be copied.</strong>
   * @param table The table to edit.
   * @param key The key of the row to edit in that table.
   * @param family The column family to edit in that table.
   * @param qualifiers The column qualifiers to delete in that family.
   * @param timestamp The timestamp to set on this edit.
   * @throws IllegalArgumentException if any argument is malformed.
   * @since 1.2
   */
  public DeleteRequest(final byte[] table,
                       final byte[] key,
                       final byte[] family,
                       final byte[][] qualifiers,
                       final long timestamp) {
    this(table, key, family, qualifiers, timestamp, RowLock.NO_LOCK);
  }

  /**
   * Constructor to delete a specific cell with an explicit row lock.
   * <strong>These byte arrays will NOT be copied.</strong>
   * @param table The table to edit.
   * @param key The key of the row to edit in that table.
   * @param family The column family to edit in that table.
   * @param qualifier The column qualifier to delete in that family.
   * @param lock An explicit row lock to use with this request.
   * @throws IllegalArgumentException if any argument is malformed.
   */
  public DeleteRequest(final byte[] table,
                       final byte[] key,
                       final byte[] family,
                       final byte[] qualifier,
                       final RowLock lock) {
    this(table, key, family,
         qualifier == null ? null : new byte[][] { qualifier },
         KeyValue.TIMESTAMP_NOW, lock.id());
  }

  /**
   * Constructor to delete a specific cell with an explicit row lock.
   * <strong>These byte arrays will NOT be copied.</strong>
   * @param table The table to edit.
   * @param key The key of the row to edit in that table.
   * @param family The column family to edit in that table.
   * @param qualifier The column qualifier to delete in that family.
   * @param timestamp The timestamp to set on this edit.
   * @param lock An explicit row lock to use with this request.
   * @throws IllegalArgumentException if any argument is malformed.
   * @since 1.2
   */
  public DeleteRequest(final byte[] table,
                       final byte[] key,
                       final byte[] family,
                       final byte[] qualifier,
                       final long timestamp,
                       final RowLock lock) {
    this(table, key, family,
         qualifier == null ? null : new byte[][] { qualifier },
         timestamp, lock.id());
  }

  /**
   * Constructor to delete a specific number of cells in a row.
   * <strong>These byte arrays will NOT be copied.</strong>
   * @param table The table to edit.
   * @param key The key of the row to edit in that table.
   * @param family The column family to edit in that table.
   * @param qualifiers The column qualifiers to delete in that family.
   * Can be {@code null}.
   * @param lock An explicit row lock to use with this request.
   * @throws IllegalArgumentException if any argument is malformed.
   * @since 1.1
   */
  public DeleteRequest(final byte[] table,
                       final byte[] key,
                       final byte[] family,
                       final byte[][] qualifiers,
                       final RowLock lock) {
    this(table, key, family, qualifiers, KeyValue.TIMESTAMP_NOW, lock.id());
  }

  /**
   * Constructor to delete a specific number of cells in a row with a row lock.
   * <strong>These byte arrays will NOT be copied.</strong>
   * @param table The table to edit.
   * @param key The key of the row to edit in that table.
   * @param family The column family to edit in that table.
   * @param qualifiers The column qualifiers to delete in that family.
   * Can be {@code null}.
   * @param timestamp The timestamp to set on this edit.
   * @param lock An explicit row lock to use with this request.
   * @throws IllegalArgumentException if any argument is malformed.
   * @since 1.2
   */
  public DeleteRequest(final byte[] table,
                       final byte[] key,
                       final byte[] family,
                       final byte[][] qualifiers,
                       final long timestamp,
                       final RowLock lock) {
    this(table, key, family, qualifiers, timestamp, lock.id());
  }

  /**
   * Constructor to delete an entire row.
   * @param table The table to edit.
   * @param key The key of the row to edit in that table.
   * @throws IllegalArgumentException if any argument is malformed.
   */
  public DeleteRequest(final String table, final String key) {
    this(table.getBytes(), key.getBytes(), null, null,
         KeyValue.TIMESTAMP_NOW, RowLock.NO_LOCK);
  }

  /**
   * Constructor to delete a specific family.
   * @param table The table to edit.
   * @param key The key of the row to edit in that table.
   * @param family The column family to edit in that table.
   * @throws IllegalArgumentException if any argument is malformed.
   * @since 1.1
   */
  public DeleteRequest(final String table,
                       final String key,
                       final String family) {
    this(table.getBytes(), key.getBytes(), family.getBytes(), null,
         KeyValue.TIMESTAMP_NOW, RowLock.NO_LOCK);
  }

  /**
   * Constructor to delete a specific cell.
   * @param table The table to edit.
   * @param key The key of the row to edit in that table.
   * @param family The column family to edit in that table.
   * @param qualifier The column qualifier to delete in that family.
   * Can be {@code null} since version 1.1.
   * @throws IllegalArgumentException if any argument is malformed.
   */
  public DeleteRequest(final String table,
                       final String key,
                       final String family,
                       final String qualifier) {
    this(table.getBytes(), key.getBytes(), family.getBytes(),
         qualifier == null ? null : new byte[][] { qualifier.getBytes() },
         KeyValue.TIMESTAMP_NOW, RowLock.NO_LOCK);
  }

  /**
   * Constructor to delete a specific cell with an explicit row lock.
   * @param table The table to edit.
   * @param key The key of the row to edit in that table.
   * @param family The column family to edit in that table.
   * @param qualifier The column qualifier to delete in that family.
   * Can be {@code null} since version 1.1.
   * @param lock An explicit row lock to use with this request.
   * @throws IllegalArgumentException if any argument is malformed.
   */
  public DeleteRequest(final String table,
                       final String key,
                       final String family,
                       final String qualifier,
                       final RowLock lock) {
    this(table.getBytes(), key.getBytes(), family.getBytes(),
         qualifier == null ? null : new byte[][] { qualifier.getBytes() },
         KeyValue.TIMESTAMP_NOW, lock.id());
  }

  /**
   * Constructor to delete a specific cell.
   * @param table The table to edit.
   * @param kv The specific {@link KeyValue} to delete.  Note that if this
   * {@link KeyValue} specifies a timestamp, then this specific timestamp only
   * will be deleted.
   * @since 1.2
   */
  public DeleteRequest(final byte[] table, final KeyValue kv) {
    this(table, kv.key(), kv.family(), new byte[][] { kv.qualifier() },
         kv.timestamp(), RowLock.NO_LOCK);
  }

  /**
   * Constructor to delete a specific cell with an explicit row lock.
   * @param table The table to edit.
   * @param kv The specific {@link KeyValue} to delete.  Note that if this
   * {@link KeyValue} specifies a timestamp, then this specific timestamp only
   * will be deleted.
   * @param lock An explicit row lock to use with this request.
   * @since 1.2
   */
  public DeleteRequest(final byte[] table,
                       final KeyValue kv,
                       final RowLock lock) {
    this(table, kv.key(), kv.family(), new byte[][] { kv.qualifier() },
         kv.timestamp(), lock.id());
  }

  /** Private constructor.  */
  private DeleteRequest(final byte[] table,
                        final byte[] key,
                        final byte[] family,
                        final byte[][] qualifiers,
                        final long timestamp,
                        final long lockid) {
    super(table, key, family == null ? WHOLE_ROW : family, timestamp, lockid);
    if (family != null) {
      KeyValue.checkFamily(family);
    }

    if (qualifiers != null) {
      if (family == null) {
        throw new IllegalArgumentException("You can't delete specific qualifiers"
          + " without specifying which family they belong to."
          + "  table=" + Bytes.pretty(table)
          + ", key=" + Bytes.pretty(key));
      }
      if (qualifiers.length == 0) {
        throw new IllegalArgumentException("Don't pass an empty list of"
          + " qualifiers, this would delete the entire row of table="
          + Bytes.pretty(table) + " at key " + Bytes.pretty(key));
      }
      for (final byte[] qualifier : qualifiers) {
        KeyValue.checkQualifier(qualifier);
      }
      this.qualifiers = qualifiers;
    } else {
      // No specific qualifier to delete: delete the entire family.  Not that
      // if `family == null', we'll delete the whole row anyway.
      this.qualifiers = DELETE_FAMILY_MARKER;
    }
  }

  /**
   * Deletes only the cell value with the timestamp specified in the
   * constructor.
   * <p>
   * Only applicable when qualifier(s) is also specified.
   * @since 1.5
   */
  public void setDeleteAtTimestampOnly(final boolean at_timestamp_only) {
    this.at_timestamp_only = at_timestamp_only;
  }

  /**
   * Returns whether to only delete the cell value at the timestamp.
   * @since 1.5
   */
  public boolean deleteAtTimestampOnly() {
    return at_timestamp_only;
  }

  @Override
  byte[] method(final byte server_version) {
    return (server_version >= RegionClient.SERVER_VERSION_095_OR_ABOVE
            ? MUTATE
            : DELETE);
  }

  @Override
  public byte[] table() {
    return table;
  }

  @Override
  public byte[] key() {
    return key;
  }

  @Override
  public byte[][] qualifiers() {
    return qualifiers;
  }

  public String toString() {
    return super.toStringWithQualifiers("DeleteRequest", family, qualifiers);
  }

  // ---------------------- //
  // Package private stuff. //
  // ---------------------- //

  @Override
  byte version(final byte unused_server_version) {
    // Versions are:
    //   1: Before 0.92.0.  This method only gets called for 0.92 and above.
    //   2: HBASE-3921 in 0.92.0 added "attributes" at the end.
    //   3: HBASE-3961 in 0.92.0 allowed skipping the WAL.
    return 3// 3 because we allow skipping the WAL.
  }

  @Override
  byte code() {
    return CODE;
  }

  @Override
  int numKeyValues() {
    return qualifiers.length;
  }

  @Override
  void serializePayload(final ChannelBuffer buf) {
    if (family == null) {
      return// No payload when deleting whole rows.
    }
    // Are we deleting a whole family at once or just a bunch of columns?
    final byte type = (qualifiers == DELETE_FAMILY_MARKER
                       ? KeyValue.DELETE_FAMILY
                       : (at_timestamp_only
                          ? KeyValue.DELETE
                          : KeyValue.DELETE_COLUMN));

    // Write the KeyValues
    for (final byte[] qualifier : qualifiers) {
      KeyValue.serialize(buf, type, timestamp,
                         key, family, qualifier, null);
    }
  }

  /**
   * Predicts a lower bound on the serialized size of this RPC.
   * This is to avoid using a dynamic buffer, to avoid re-sizing the buffer.
   * Since we use a static buffer, if the prediction is wrong and turns out
   * to be less than what we need, there will be an exception which will
   * prevent the RPC from being serialized.  That'd be a severe bug.
   */
  private int predictSerializedSize() {
    int size = 0;
    size += 4// int:  Number of parameters.
    size += 1// byte: Type of the 1st parameter.
    size += 3// vint: region name length (3 bytes => max length = 32768).
    size += region.name().length;  // The region name.

    size += 1// byte: Type of the 2nd parameter.
    size += 1// byte: Type again (see HBASE-2877).
    size += 1// byte: Version of Delete.
    size += 3// vint: row key length (3 bytes => max length = 32768).
    size += key.length;  // The row key.
    size += 8// long: Timestamp.
    size += 8// long: Lock ID.
    size += 4// int:  Number of families.
    size += 1// vint: Family length (guaranteed on 1 byte).
    if (family == null) {
      return size;
    }
    size += family.length;  // The column family.
    size += 4// int:  Number of KeyValues for this family.
    return size + payloadSize();
  }

  /** Returns the serialized size of all the {@link KeyValue}s in this RPC.  */
  @Override
  int payloadSize() {
    if (family == WHOLE_ROW) {
      return 0// No payload when deleting whole rows.
    }
    int size = 0;
    size += 4// int:  Total length of the whole KeyValue.
    size += 4// int:  Total length of the key part of the KeyValue.
    size += 4// int:  Length of the value part of the KeyValue.
    size += 2// short:Length of the key.
    size += key.length;  // The row key (again!).
    size += 1// byte: Family length (again!).
    size += family.length;  // The column family (again!).
    size += 8// long: The timestamp (again!).
    size += 1// byte: The type of KeyValue.
    size *= qualifiers.length;
    for (final byte[] qualifier : qualifiers) {
      size += qualifier.length;  // The column qualifier.
    }
    return size;
  }

  @Override
  MutationProto toMutationProto() {
    final MutationProto.Builder del = MutationProto.newBuilder()
      .setRow(Bytes.wrap(key))
      .setMutateType(MutationProto.MutationType.DELETE);

    if (family != WHOLE_ROW) {
      final MutationProto.ColumnValue.Builder columns = // All columns ...
        MutationProto.ColumnValue.newBuilder()
        .setFamily(Bytes.wrap(family));                 // ... for this family.

      final MutationProto.DeleteType type =
        (qualifiers == DELETE_FAMILY_MARKER
         ? MutationProto.DeleteType.DELETE_FAMILY
         : (at_timestamp_only
            ? MutationProto.DeleteType.DELETE_ONE_VERSION
            : MutationProto.DeleteType.DELETE_MULTIPLE_VERSIONS));

      // Now add all the qualifiers to delete.
      for (int i = 0; i < qualifiers.length; i++) {
        final MutationProto.ColumnValue.QualifierValue column =
          MutationProto.ColumnValue.QualifierValue.newBuilder()
          .setQualifier(Bytes.wrap(qualifiers[i]))
          .setTimestamp(timestamp)
          .setDeleteType(type)
          .build();
        columns.addQualifierValue(column);
      }
      del.addColumnValue(columns);
    }

    if (!durable) {
      del.setDurability(MutationProto.Durability.SKIP_WAL);
    }
    return del.build();
  }

  /** Serializes this request.  */
  ChannelBuffer serialize(final byte server_version) {
    if (server_version < RegionClient.SERVER_VERSION_095_OR_ABOVE) {
      return serializeOld(server_version);
    }

    final MutateRequest req = MutateRequest.newBuilder()
      .setRegion(region.toProtobuf())
      .setMutation(toMutationProto())
      .build();
    return toChannelBuffer(MUTATE, req);
  }

  /** Serializes this request for HBase 0.94 and before.  */
  private ChannelBuffer serializeOld(final byte server_version) {
    final ChannelBuffer buf = newBuffer(server_version,
                                        predictSerializedSize());
    buf.writeInt(2)// Number of parameters.

    // 1st param: byte array containing region name
    writeHBaseByteArray(buf, region.name());

    // 2nd param: Delete object.
    buf.writeByte(CODE); // Code for a `Delete' parameter.
    buf.writeByte(CODE); // Code again (see HBASE-2877).
    buf.writeByte(1);    // Delete#DELETE_VERSION.  Stick to v1 here for now.
    writeByteArray(buf, key);
    buf.writeLong(timestamp)// Maximum timestamp.
    buf.writeLong(lockid)// Lock ID.

    // Families.
    if (family == WHOLE_ROW) {
      buf.writeInt(0)// Number of families that follow.
      return buf;
    }
    buf.writeInt(1);    // Number of families that follow.

    // Each family is then written like so:
    writeByteArray(buf, family)// Column family name.
    buf.writeInt(qualifiers.length)// How many KeyValues for this family?
    serializePayload(buf);
    return buf;
  }

  @Override
  Object deserialize(final ChannelBuffer buf, int cell_size) {
    HBaseRpc.ensureNoCell(cell_size);
    final MutateResponse resp = readProtobuf(buf, MutateResponse.PARSER);
    return null;
  }

}
TOP

Related Classes of org.hbase.async.DeleteRequest

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.