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.regionserver;
019
020import org.apache.hadoop.hbase.HBaseInterfaceAudience;
021import org.apache.hbase.thirdparty.com.google.common.base.Preconditions;
022import org.apache.yetus.audience.InterfaceAudience;
023import org.apache.hadoop.hbase.client.Mutation;
024import org.apache.hadoop.hbase.wal.WALEdit;
025
026/**
027 * Wraps together the mutations which are applied as a batch to the region and their operation
028 * status and WALEdits.
029 * @see org.apache.hadoop.hbase.coprocessor.RegionObserver#preBatchMutate(
030 * org.apache.hadoop.hbase.coprocessor.ObserverContext, MiniBatchOperationInProgress)
031 * @see org.apache.hadoop.hbase.coprocessor.RegionObserver#postBatchMutate(
032 * org.apache.hadoop.hbase.coprocessor.ObserverContext, MiniBatchOperationInProgress)
033 * @param T Pair<Mutation, Integer> pair of Mutations and associated rowlock ids .
034 */
035@InterfaceAudience.LimitedPrivate(HBaseInterfaceAudience.COPROC)
036public class MiniBatchOperationInProgress<T> {
037  private final T[] operations;
038  private Mutation[][] operationsFromCoprocessors;
039  private final OperationStatus[] retCodeDetails;
040  private final WALEdit[] walEditsFromCoprocessors;
041  private final int firstIndex;
042  private final int lastIndexExclusive;
043
044  private int readyToWriteCount = 0;
045  private int cellCount = 0;
046  private int numOfPuts = 0;
047  private int numOfDeletes = 0;
048
049
050  public MiniBatchOperationInProgress(T[] operations, OperationStatus[] retCodeDetails,
051      WALEdit[] walEditsFromCoprocessors, int firstIndex, int lastIndexExclusive,
052      int readyToWriteCount) {
053    Preconditions.checkArgument(readyToWriteCount <= (lastIndexExclusive - firstIndex));
054    this.operations = operations;
055    this.retCodeDetails = retCodeDetails;
056    this.walEditsFromCoprocessors = walEditsFromCoprocessors;
057    this.firstIndex = firstIndex;
058    this.lastIndexExclusive = lastIndexExclusive;
059    this.readyToWriteCount = readyToWriteCount;
060  }
061
062  /**
063   * @return The number of operations(Mutations) involved in this batch.
064   */
065  public int size() {
066    return this.lastIndexExclusive - this.firstIndex;
067  }
068
069  /**
070   * @param index
071   * @return The operation(Mutation) at the specified position.
072   */
073  public T getOperation(int index) {
074    return operations[getAbsoluteIndex(index)];
075  }
076
077  /**
078   * Sets the status code for the operation(Mutation) at the specified position.
079   * By setting this status, {@link org.apache.hadoop.hbase.coprocessor.RegionObserver}
080   * can make HRegion to skip Mutations.
081   * @param index
082   * @param opStatus
083   */
084  public void setOperationStatus(int index, OperationStatus opStatus) {
085    this.retCodeDetails[getAbsoluteIndex(index)] = opStatus;
086  }
087
088  /**
089   * @param index
090   * @return Gets the status code for the operation(Mutation) at the specified position.
091   */
092  public OperationStatus getOperationStatus(int index) {
093    return this.retCodeDetails[getAbsoluteIndex(index)];
094  }
095
096  /**
097   * Sets the walEdit for the operation(Mutation) at the specified position.
098   * @param index
099   * @param walEdit
100   */
101  public void setWalEdit(int index, WALEdit walEdit) {
102    this.walEditsFromCoprocessors[getAbsoluteIndex(index)] = walEdit;
103  }
104
105  /**
106   * @param index
107   * @return Gets the walEdit for the operation(Mutation) at the specified position.
108   */
109  public WALEdit getWalEdit(int index) {
110    return this.walEditsFromCoprocessors[getAbsoluteIndex(index)];
111  }
112
113  private int getAbsoluteIndex(int index) {
114    if (index < 0 || this.firstIndex + index >= this.lastIndexExclusive) {
115      throw new ArrayIndexOutOfBoundsException(index);
116    }
117    return this.firstIndex + index;
118  }
119
120  /**
121   * Add more Mutations corresponding to the Mutation at the given index to be committed atomically
122   * in the same batch. These mutations are applied to the WAL and applied to the memstore as well.
123   * The timestamp of the cells in the given Mutations MUST be obtained from the original mutation.
124   * <b>Note:</b> The durability from CP will be replaced by the durability of corresponding mutation.
125   * @param index the index that corresponds to the original mutation index in the batch
126   * @param newOperations the Mutations to add
127   */
128  public void addOperationsFromCP(int index, Mutation[] newOperations) {
129    if (this.operationsFromCoprocessors == null) {
130      // lazy allocation to save on object allocation in case this is not used
131      this.operationsFromCoprocessors = new Mutation[operations.length][];
132    }
133    this.operationsFromCoprocessors[getAbsoluteIndex(index)] = newOperations;
134  }
135
136  public Mutation[] getOperationsFromCoprocessors(int index) {
137    return operationsFromCoprocessors == null ? null :
138        operationsFromCoprocessors[getAbsoluteIndex(index)];
139  }
140
141  public int getReadyToWriteCount() {
142    return readyToWriteCount;
143  }
144
145  public int getLastIndexExclusive() {
146    return lastIndexExclusive;
147  }
148
149  public int getCellCount() {
150    return cellCount;
151  }
152
153  public void addCellCount(int cellCount) {
154    this.cellCount += cellCount;
155  }
156
157  public int getNumOfPuts() {
158    return numOfPuts;
159  }
160
161  public void incrementNumOfPuts() {
162    this.numOfPuts += 1;
163  }
164
165  public int getNumOfDeletes() {
166    return numOfDeletes;
167  }
168
169  public void incrementNumOfDeletes() {
170    this.numOfDeletes += 1;
171  }
172}