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 static org.apache.hadoop.hbase.client.ConnectionUtils.filterCells; 021 022import java.io.IOException; 023import java.util.Arrays; 024 025import org.apache.hadoop.hbase.Cell; 026import org.apache.hadoop.hbase.CellUtil; 027import org.apache.yetus.audience.InterfaceAudience; 028 029/** 030 * A ScanResultCache that may return partial result. 031 * <p> 032 * As we can only scan from the starting of a row when error, so here we also implement the logic 033 * that skips the cells that have already been returned. 034 */ 035@InterfaceAudience.Private 036class AllowPartialScanResultCache implements ScanResultCache { 037 038 // used to filter out the cells that already returned to user as we always start from the 039 // beginning of a row when retry. 040 private Cell lastCell; 041 042 private boolean lastResultPartial; 043 044 private int numberOfCompleteRows; 045 046 private void recordLastResult(Result result) { 047 lastCell = result.rawCells()[result.rawCells().length - 1]; 048 lastResultPartial = result.mayHaveMoreCellsInRow(); 049 } 050 051 @Override 052 public Result[] addAndGet(Result[] results, boolean isHeartbeatMessage) throws IOException { 053 if (results.length == 0) { 054 if (!isHeartbeatMessage && lastResultPartial) { 055 // An empty non heartbeat result indicate that there must be a row change. So if the 056 // lastResultPartial is true then we need to increase numberOfCompleteRows. 057 numberOfCompleteRows++; 058 } 059 return EMPTY_RESULT_ARRAY; 060 } 061 int i; 062 for (i = 0; i < results.length; i++) { 063 Result r = filterCells(results[i], lastCell); 064 if (r != null) { 065 results[i] = r; 066 break; 067 } 068 } 069 if (i == results.length) { 070 return EMPTY_RESULT_ARRAY; 071 } 072 if (lastResultPartial && !CellUtil.matchingRows(lastCell, results[0].getRow())) { 073 // there is a row change, so increase numberOfCompleteRows 074 numberOfCompleteRows++; 075 } 076 recordLastResult(results[results.length - 1]); 077 if (i > 0) { 078 results = Arrays.copyOfRange(results, i, results.length); 079 } 080 for (Result result : results) { 081 if (!result.mayHaveMoreCellsInRow()) { 082 numberOfCompleteRows++; 083 } 084 } 085 return results; 086 } 087 088 @Override 089 public void clear() { 090 // we do not cache anything 091 } 092 093 @Override 094 public int numberOfCompleteRows() { 095 return numberOfCompleteRows; 096 } 097}