001/*
002 *
003 * Licensed to the Apache Software Foundation (ASF) under one
004 * or more contributor license agreements.  See the NOTICE file
005 * distributed with this work for additional information
006 * regarding copyright ownership.  The ASF licenses this file
007 * to you under the Apache License, Version 2.0 (the
008 * "License"); you may not use this file except in compliance
009 * with the License.  You may obtain a copy of the License at
010 *
011 *     http://www.apache.org/licenses/LICENSE-2.0
012 *
013 * Unless required by applicable law or agreed to in writing, software
014 * distributed under the License is distributed on an "AS IS" BASIS,
015 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
016 * See the License for the specific language governing permissions and
017 * limitations under the License.
018 */
019
020package org.apache.hadoop.hbase.client;
021
022import java.util.HashMap;
023import java.util.Map;
024import java.util.TreeMap;
025
026import org.apache.yetus.audience.InterfaceAudience;
027import org.apache.hadoop.hbase.shaded.protobuf.generated.ClientProtos;
028import org.apache.hadoop.hbase.util.Bytes;
029
030/**
031 * A container for Result objects, grouped by regionName.
032 */
033@InterfaceAudience.Private
034public class MultiResponse extends AbstractResponse {
035
036  // map of regionName to map of Results by the original index for that Result
037  private Map<byte[], RegionResult> results = new TreeMap<>(Bytes.BYTES_COMPARATOR);
038
039  /**
040   * The server can send us a failure for the region itself, instead of individual failure.
041   * It's a part of the protobuf definition.
042   */
043  private Map<byte[], Throwable> exceptions =
044      new TreeMap<>(Bytes.BYTES_COMPARATOR);
045
046  public MultiResponse() {
047    super();
048  }
049
050  /**
051   * @return Number of pairs in this container
052   */
053  public int size() {
054    int size = 0;
055    for (RegionResult result: results.values()) {
056      size += result.size();
057    }
058    return size;
059  }
060
061  /**
062   * Add the pair to the container, grouped by the regionName
063   *
064   * @param regionName
065   * @param originalIndex the original index of the Action (request).
066   * @param resOrEx the result or error; will be empty for successful Put and Delete actions.
067   */
068  public void add(byte[] regionName, int originalIndex, Object resOrEx) {
069    getResult(regionName).addResult(originalIndex, resOrEx);
070  }
071
072  public void addException(byte []regionName, Throwable ie){
073    exceptions.put(regionName, ie);
074  }
075
076  /**
077   * @return the exception for the region, if any. Null otherwise.
078   */
079  public Throwable getException(byte []regionName){
080    return exceptions.get(regionName);
081  }
082
083  public Map<byte[], Throwable> getExceptions() {
084    return exceptions;
085  }
086
087  public void addStatistic(byte[] regionName, ClientProtos.RegionLoadStats stat) {
088    getResult(regionName).setStat(stat);
089  }
090
091  private RegionResult getResult(byte[] region){
092    RegionResult rs = results.get(region);
093    if (rs == null) {
094      rs = new RegionResult();
095      results.put(region, rs);
096    }
097    return rs;
098  }
099
100  public Map<byte[], RegionResult> getResults(){
101    return this.results;
102  }
103
104  @Override
105  public ResponseType type() {
106    return ResponseType.MULTI;
107  }
108
109  static class RegionResult{
110    Map<Integer, Object> result = new HashMap<>();
111    ClientProtos.RegionLoadStats stat;
112
113    public void addResult(int index, Object result){
114      this.result.put(index, result);
115    }
116
117    public void setStat(ClientProtos.RegionLoadStats stat){
118      this.stat = stat;
119    }
120
121    public int size() {
122      return this.result.size();
123    }
124
125    public ClientProtos.RegionLoadStats getStat() {
126      return this.stat;
127    }
128  }
129}