View Javadoc

1   /**
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *     http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing, software
13   * distributed under the License is distributed on an "AS IS" BASIS,
14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   * See the License for the specific language governing permissions and
16   * limitations under the License.
17   */
18  package org.apache.hadoop.hbase.client;
19  
20  import java.io.IOException;
21  import java.util.ArrayList;
22  import java.util.List;
23  
24  import org.apache.hadoop.hbase.classification.InterfaceAudience;
25  import org.apache.hadoop.hbase.util.Bytes;
26  
27  /**
28   * A scan result cache that only returns complete result.
29   */
30  @InterfaceAudience.Private
31  class CompleteScanResultCache extends ScanResultCache {
32  
33    private final List<Result> partialResults = new ArrayList<>();
34  
35    public CompleteScanResultCache(List<Result> cache) {
36      super(cache);
37    }
38  
39    private Result combine() throws IOException {
40      Result result = Result.createCompleteResult(partialResults);
41      partialResults.clear();
42      return result;
43    }
44  
45    private void prependCombinedAndCache(Result[] results, int length) throws IOException {
46      if (length == 0) {
47        checkUpdateNumberOfCompleteRowsAndCache(combine());
48        return;
49      }
50      // the last part of a partial result may not be marked as partial so here we need to check if
51      // there is a row change.
52      int start = 0;
53      if (Bytes.equals(partialResults.get(0).getRow(), results[0].getRow())) {
54        partialResults.add(results[0]);
55        start = 1;
56      }
57      checkUpdateNumberOfCompleteRowsAndCache(combine());
58      addResultArrayToCache(results, start, length);
59    }
60  
61    @Override
62    public void loadResultsToCache(Result[] results, boolean isHeartbeatMessage) throws IOException {
63      // If no results were returned it indicates that either we have the all the partial results
64      // necessary to construct the complete result or the server had to send a heartbeat message
65      // to the client to keep the client-server connection alive
66      if (results.length == 0) {
67        // If this response was an empty heartbeat message, then we have not exhausted the region
68        // and thus there may be more partials server side that still need to be added to the partial
69        // list before we form the complete Result
70        if (!partialResults.isEmpty() && !isHeartbeatMessage) {
71          checkUpdateNumberOfCompleteRowsAndCache(combine());
72        }
73        return;
74      }
75      // In every RPC response there should be at most a single partial result. Furthermore, if
76      // there is a partial result, it is guaranteed to be in the last position of the array.
77      Result last = results[results.length - 1];
78      if (last.mayHaveMoreCellsInRow()) {
79        if (partialResults.isEmpty()) {
80          partialResults.add(last);
81          addResultArrayToCache(results, 0, results.length - 1);
82          return;
83        }
84        // We have only one result and it is partial
85        if (results.length == 1) {
86          // check if there is a row change
87          if (Bytes.equals(partialResults.get(0).getRow(), last.getRow())) {
88            partialResults.add(last);
89            return;
90          }
91          Result completeResult = combine();
92          partialResults.add(last);
93          checkUpdateNumberOfCompleteRowsAndCache(completeResult);
94          return;
95        }
96        // We have some complete results
97        prependCombinedAndCache(results, results.length - 1);
98        partialResults.add(last);
99        return;
100     }
101     if (!partialResults.isEmpty()) {
102       prependCombinedAndCache(results, results.length);
103       return;
104     }
105     addResultArrayToCache(results, 0, results.length);
106   }
107 
108   @Override
109   protected void checkUpdateNumberOfCompleteRowsAndCache(Result rs) {
110     numberOfCompleteRows++;
111     addResultToCache(rs);
112   }
113 
114   @Override
115   public void clear() {
116     partialResults.clear();
117     super.clear();
118   }
119 }