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.ArrayList;
022import java.util.Arrays;
023import java.util.Collections;
024import java.util.List;
025
026import org.apache.hadoop.hbase.util.Bytes;
027import org.apache.hadoop.hbase.util.CollectionUtils;
028import org.apache.yetus.audience.InterfaceAudience;
029
030/**
031 * Performs multiple mutations atomically on a single row.
032 * Currently {@link Put} and {@link Delete} are supported.
033 *
034 * The mutations are performed in the order in which they
035 * were added.
036 *
037 * <p>We compare and equate mutations based off their row so be careful putting RowMutations
038 * into Sets or using them as keys in Maps.
039 */
040@InterfaceAudience.Public
041public class RowMutations implements Row {
042
043  /**
044   * Create a {@link RowMutations} with the specified mutations.
045   * @param mutations the mutations to send
046   * @return RowMutations
047   * @throws IOException if any row in mutations is different to another
048   */
049  public static RowMutations of(List<? extends Mutation> mutations) throws IOException {
050    if (CollectionUtils.isEmpty(mutations)) {
051      throw new IllegalArgumentException("Can't instantiate a RowMutations by empty list");
052    }
053    return new RowMutations(mutations.get(0).getRow(), mutations.size())
054        .add(mutations);
055  }
056
057  private final List<Mutation> mutations;
058  private final byte [] row;
059
060  public RowMutations(byte [] row) {
061    this(row, -1);
062  }
063  /**
064   * Create an atomic mutation for the specified row.
065   * @param row row key
066   * @param initialCapacity the initial capacity of the RowMutations
067   */
068  public RowMutations(byte [] row, int initialCapacity) {
069    this.row = Bytes.copy(Mutation.checkRow(row));
070    if (initialCapacity <= 0) {
071      this.mutations = new ArrayList<>();
072    } else {
073      this.mutations = new ArrayList<>(initialCapacity);
074    }
075  }
076
077  /**
078   * Add a {@link Put} operation to the list of mutations
079   * @param p The {@link Put} to add
080   * @throws IOException if the row of added mutation doesn't match the original row
081   * @deprecated since 2.0 version and will be removed in 3.0 version.
082   *             use {@link #add(Mutation)}
083   */
084  @Deprecated
085  public void add(Put p) throws IOException {
086    add((Mutation) p);
087  }
088
089  /**
090   * Add a {@link Delete} operation to the list of mutations
091   * @param d The {@link Delete} to add
092   * @throws IOException if the row of added mutation doesn't match the original row
093   * @deprecated since 2.0 version and will be removed in 3.0 version.
094   *             use {@link #add(Mutation)}
095   */
096  @Deprecated
097  public void add(Delete d) throws IOException {
098    add((Mutation) d);
099  }
100
101  /**
102   * Currently only supports {@link Put} and {@link Delete} mutations.
103   *
104   * @param mutation The data to send.
105   * @throws IOException if the row of added mutation doesn't match the original row
106   */
107  public RowMutations add(Mutation mutation) throws IOException {
108    return add(Collections.singletonList(mutation));
109  }
110
111  /**
112   * Currently only supports {@link Put} and {@link Delete} mutations.
113   *
114   * @param mutations The data to send.
115   * @throws IOException if the row of added mutation doesn't match the original row
116   */
117  public RowMutations add(List<? extends Mutation> mutations) throws IOException {
118    for (Mutation mutation : mutations) {
119      if (!Bytes.equals(row, mutation.getRow())) {
120        throw new WrongRowIOException("The row in the recently added Put/Delete <" +
121          Bytes.toStringBinary(mutation.getRow()) + "> doesn't match the original one <" +
122          Bytes.toStringBinary(this.row) + ">");
123      }
124    }
125    this.mutations.addAll(mutations);
126    return this;
127  }
128
129  /**
130   * @deprecated As of release 2.0.0, this will be removed in HBase 3.0.0.
131   *             Use {@link Row#COMPARATOR} instead
132   */
133  @Deprecated
134  @Override
135  public int compareTo(Row i) {
136    return Bytes.compareTo(this.getRow(), i.getRow());
137  }
138
139  /**
140   * @deprecated As of release 2.0.0, this will be removed in HBase 3.0.0.
141   *             No replacement
142   */
143  @Deprecated
144  @Override
145  public boolean equals(Object obj) {
146    if (obj == this) return true;
147    if (obj instanceof RowMutations) {
148      RowMutations other = (RowMutations)obj;
149      return compareTo(other) == 0;
150    }
151    return false;
152  }
153
154  /**
155   * @deprecated As of release 2.0.0, this will be removed in HBase 3.0.0.
156   *             No replacement
157   */
158  @Deprecated
159  @Override
160  public int hashCode(){
161    return Arrays.hashCode(row);
162  }
163
164  @Override
165  public byte[] getRow() {
166    return row;
167  }
168
169  /**
170   * @return An unmodifiable list of the current mutations.
171   */
172  public List<Mutation> getMutations() {
173    return Collections.unmodifiableList(mutations);
174  }
175
176  public int getMaxPriority() {
177    int maxPriority = Integer.MIN_VALUE;
178    for (Mutation mutation : mutations) {
179      maxPriority = Math.max(maxPriority, mutation.getPriority());
180    }
181    return maxPriority;
182  }
183}