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.yetus.audience.InterfaceAudience;
028
029import org.apache.hbase.thirdparty.org.apache.commons.collections4.CollectionUtils;
030
031/**
032 * Performs multiple mutations atomically on a single row.
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("Cannot 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   * @param mutations The data to send.
113   * @throws IOException if the row of added mutation doesn't match the original row
114   */
115  public RowMutations add(List<? extends Mutation> mutations) throws IOException {
116    for (Mutation mutation : mutations) {
117      if (!Bytes.equals(row, mutation.getRow())) {
118        throw new WrongRowIOException("The row in the recently added Mutation <" +
119          Bytes.toStringBinary(mutation.getRow()) + "> doesn't match the original one <" +
120          Bytes.toStringBinary(this.row) + ">");
121      }
122    }
123    this.mutations.addAll(mutations);
124    return this;
125  }
126
127  /**
128   * @deprecated As of release 2.0.0, this will be removed in HBase 3.0.0.
129   *             Use {@link Row#COMPARATOR} instead
130   */
131  @Deprecated
132  @Override
133  public int compareTo(Row i) {
134    return Bytes.compareTo(this.getRow(), i.getRow());
135  }
136
137  /**
138   * @deprecated As of release 2.0.0, this will be removed in HBase 3.0.0.
139   *             No replacement
140   */
141  @Deprecated
142  @Override
143  public boolean equals(Object obj) {
144    if (obj == this) return true;
145    if (obj instanceof RowMutations) {
146      RowMutations other = (RowMutations)obj;
147      return compareTo(other) == 0;
148    }
149    return false;
150  }
151
152  /**
153   * @deprecated As of release 2.0.0, this will be removed in HBase 3.0.0.
154   *             No replacement
155   */
156  @Deprecated
157  @Override
158  public int hashCode(){
159    return Arrays.hashCode(row);
160  }
161
162  @Override
163  public byte[] getRow() {
164    return row;
165  }
166
167  /**
168   * @return An unmodifiable list of the current mutations.
169   */
170  public List<Mutation> getMutations() {
171    return Collections.unmodifiableList(mutations);
172  }
173
174  public int getMaxPriority() {
175    int maxPriority = Integer.MIN_VALUE;
176    for (Mutation mutation : mutations) {
177      maxPriority = Math.max(maxPriority, mutation.getPriority());
178    }
179    return maxPriority;
180  }
181}