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.util.HashMap;
021import java.util.Map;
022import java.util.TreeMap;
023import org.apache.hadoop.hbase.util.Bytes;
024import org.apache.yetus.audience.InterfaceAudience;
025
026import org.apache.hadoop.hbase.shaded.protobuf.generated.ClientProtos;
027
028/**
029 * A container for Result objects, grouped by regionName.
030 */
031@InterfaceAudience.Private
032public class MultiResponse extends AbstractResponse {
033
034  // map of regionName to map of Results by the original index for that Result
035  private Map<byte[], RegionResult> results = new TreeMap<>(Bytes.BYTES_COMPARATOR);
036
037  /**
038   * The server can send us a failure for the region itself, instead of individual failure. It's a
039   * part of the protobuf definition.
040   */
041  private Map<byte[], Throwable> exceptions = new TreeMap<>(Bytes.BYTES_COMPARATOR);
042
043  public MultiResponse() {
044    super();
045  }
046
047  /**
048   * @return Number of pairs in this container
049   */
050  public int size() {
051    int size = 0;
052    for (RegionResult result : results.values()) {
053      size += result.size();
054    }
055    return size;
056  }
057
058  /**
059   * Add the pair to the container, grouped by the regionName n * @param originalIndex the original
060   * index of the Action (request).
061   * @param resOrEx the result or error; will be empty for successful Put and Delete actions.
062   */
063  public void add(byte[] regionName, int originalIndex, Object resOrEx) {
064    getResult(regionName).addResult(originalIndex, resOrEx);
065  }
066
067  public void addException(byte[] regionName, Throwable ie) {
068    exceptions.put(regionName, ie);
069  }
070
071  /**
072   * @return the exception for the region, if any. Null otherwise.
073   */
074  public Throwable getException(byte[] regionName) {
075    return exceptions.get(regionName);
076  }
077
078  public Map<byte[], Throwable> getExceptions() {
079    return exceptions;
080  }
081
082  public void addStatistic(byte[] regionName, ClientProtos.RegionLoadStats stat) {
083    getResult(regionName).setStat(stat);
084  }
085
086  private RegionResult getResult(byte[] region) {
087    RegionResult rs = results.get(region);
088    if (rs == null) {
089      rs = new RegionResult();
090      results.put(region, rs);
091    }
092    return rs;
093  }
094
095  public Map<byte[], RegionResult> getResults() {
096    return this.results;
097  }
098
099  @Override
100  public ResponseType type() {
101    return ResponseType.MULTI;
102  }
103
104  static class RegionResult {
105    Map<Integer, Object> result = new HashMap<>();
106    ClientProtos.RegionLoadStats stat;
107
108    public void addResult(int index, Object result) {
109      this.result.put(index, result);
110    }
111
112    public void setStat(ClientProtos.RegionLoadStats stat) {
113      this.stat = stat;
114    }
115
116    public int size() {
117      return this.result.size();
118    }
119
120    public ClientProtos.RegionLoadStats getStat() {
121      return this.stat;
122    }
123  }
124}