1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.hadoop.hbase.client;
21
22
23 import org.apache.commons.logging.Log;
24 import org.apache.commons.logging.LogFactory;
25 import org.apache.hadoop.hbase.classification.InterfaceAudience;
26 import org.apache.hadoop.hbase.classification.InterfaceStability;
27 import org.apache.hadoop.conf.Configuration;
28 import org.apache.hadoop.hbase.Cell;
29 import org.apache.hadoop.hbase.HConstants;
30 import org.apache.hadoop.hbase.KeyValueUtil;
31 import org.apache.hadoop.hbase.TableName;
32 import org.apache.hadoop.hbase.util.Bytes;
33
34 import java.io.IOException;
35
36
37
38
39
40
41
42
43 @InterfaceAudience.Public
44 @InterfaceStability.Evolving
45 public class ClientSmallReversedScanner extends ReversedClientScanner {
46 private static final Log LOG = LogFactory.getLog(ClientSmallReversedScanner.class);
47 private RegionServerCallable<Result[]> smallScanCallable = null;
48 private byte[] skipRowOfFirstResult = null;
49
50
51
52
53
54
55
56
57
58
59
60 public ClientSmallReversedScanner(Configuration conf, Scan scan, TableName tableName,
61 HConnection connection) throws IOException {
62 super(conf, scan, tableName, connection);
63 }
64
65
66
67
68
69
70
71
72
73
74
75 private boolean nextScanner(int nbRows, final boolean done,
76 boolean currentRegionDone) throws IOException {
77
78 byte[] localStartKey;
79 int cacheNum = nbRows;
80 skipRowOfFirstResult = null;
81
82 if (this.currentRegion != null && currentRegionDone) {
83 byte[] startKey = this.currentRegion.getStartKey();
84 if (startKey == null
85 || Bytes.equals(startKey, HConstants.EMPTY_BYTE_ARRAY)
86 || checkScanStopRow(startKey) || done) {
87 close();
88 if (LOG.isDebugEnabled()) {
89 LOG.debug("Finished with small scan at " + this.currentRegion);
90 }
91 return false;
92 }
93
94 localStartKey = createClosestRowBefore(startKey);
95 if (LOG.isDebugEnabled()) {
96 LOG.debug("Finished with region " + this.currentRegion);
97 }
98 } else if (this.lastResult != null) {
99 localStartKey = this.lastResult.getRow();
100 skipRowOfFirstResult = this.lastResult.getRow();
101 cacheNum++;
102 } else {
103 localStartKey = this.scan.getStartRow();
104 }
105
106 if (LOG.isTraceEnabled()) {
107 LOG.trace("Advancing internal small scanner to startKey at '"
108 + Bytes.toStringBinary(localStartKey) + "'");
109 }
110
111 smallScanCallable = ClientSmallScanner.getSmallScanCallable(
112 scan, getConnection(), getTable(), localStartKey, cacheNum, this.rpcControllerFactory);
113
114 if (this.scanMetrics != null && skipRowOfFirstResult == null) {
115 this.scanMetrics.countOfRegions.incrementAndGet();
116 }
117 return true;
118 }
119
120 @Override
121 public Result next() throws IOException {
122
123
124 if (cache.size() == 0 && this.closed) {
125 return null;
126 }
127 if (cache.size() == 0) {
128 Result[] values = null;
129 long remainingResultSize = maxScannerResultSize;
130 int countdown = this.caching;
131 boolean currentRegionDone = false;
132
133 while (remainingResultSize > 0 && countdown > 0
134 && nextScanner(countdown, values == null, currentRegionDone)) {
135
136
137
138 values = this.caller.callWithRetries(smallScanCallable, scannerTimeout);
139 this.currentRegion = smallScanCallable.getHRegionInfo();
140 long currentTime = System.currentTimeMillis();
141 if (this.scanMetrics != null) {
142 this.scanMetrics.sumOfMillisSecBetweenNexts.addAndGet(currentTime
143 - lastNext);
144 }
145 lastNext = currentTime;
146 if (values != null && values.length > 0) {
147 for (int i = 0; i < values.length; i++) {
148 Result rs = values[i];
149 if (i == 0 && this.skipRowOfFirstResult != null
150 && Bytes.equals(skipRowOfFirstResult, rs.getRow())) {
151
152 continue;
153 }
154 cache.add(rs);
155 for (Cell kv : rs.rawCells()) {
156 remainingResultSize -= KeyValueUtil.ensureKeyValue(kv).heapSize();
157 }
158 countdown--;
159 this.lastResult = rs;
160 }
161 }
162 currentRegionDone = countdown > 0;
163 }
164 }
165
166 if (cache.size() > 0) {
167 return cache.poll();
168 }
169
170
171 writeScanMetrics();
172 return null;
173 }
174
175
176 @Override
177 protected void initializeScannerInConstruction() throws IOException {
178
179
180 }
181
182 @Override
183 public void close() {
184 if (!scanMetricsPublished) writeScanMetrics();
185 closed = true;
186 }
187
188 }