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.Iterator;
23
24 import org.apache.hadoop.hbase.classification.InterfaceAudience;
25 import org.apache.hadoop.hbase.client.metrics.ScanMetrics;
26
27 /**
28 * Helper class for custom client scanners.
29 */
30 @InterfaceAudience.Private
31 public abstract class AbstractClientScanner implements ResultScanner {
32 protected ScanMetrics scanMetrics;
33
34 /**
35 * Check and initialize if application wants to collect scan metrics
36 */
37 protected void initScanMetrics(Scan scan) {
38 // check if application wants to collect scan metrics
39 if (scan.isScanMetricsEnabled()) {
40 scanMetrics = new ScanMetrics();
41 }
42 }
43
44 /**
45 * Used internally accumulating metrics on scan. To
46 * enable collection of metrics on a Scanner, call {@link Scan#setScanMetricsEnabled(boolean)}.
47 * These metrics are cleared at key transition points. Metrics are accumulated in the
48 * {@link Scan} object itself.
49 * @see Scan#getScanMetrics()
50 * @return Returns the running {@link ScanMetrics} instance or null if scan metrics not enabled.
51 */
52 public ScanMetrics getScanMetrics() {
53 return scanMetrics;
54 }
55
56 /**
57 * Get <param>nbRows</param> rows.
58 * How many RPCs are made is determined by the {@link Scan#setCaching(int)}
59 * setting (or hbase.client.scanner.caching in hbase-site.xml).
60 * @param nbRows number of rows to return
61 * @return Between zero and <param>nbRows</param> RowResults. Scan is done
62 * if returned array is of zero-length (We never return null).
63 * @throws IOException
64 */
65 @Override
66 public Result [] next(int nbRows) throws IOException {
67 // Collect values to be returned here
68 ArrayList<Result> resultSets = new ArrayList<Result>(nbRows);
69 for(int i = 0; i < nbRows; i++) {
70 Result next = next();
71 if (next != null) {
72 resultSets.add(next);
73 } else {
74 break;
75 }
76 }
77 return resultSets.toArray(new Result[resultSets.size()]);
78 }
79
80 @Override
81 public Iterator<Result> iterator() {
82 return new Iterator<Result>() {
83 // The next RowResult, possibly pre-read
84 Result next = null;
85
86 // return true if there is another item pending, false if there isn't.
87 // this method is where the actual advancing takes place, but you need
88 // to call next() to consume it. hasNext() will only advance if there
89 // isn't a pending next().
90 @Override
91 public boolean hasNext() {
92 if (next == null) {
93 try {
94 next = AbstractClientScanner.this.next();
95 return next != null;
96 } catch (IOException e) {
97 throw new RuntimeException(e);
98 }
99 }
100 return true;
101 }
102
103 // get the pending next item and advance the iterator. returns null if
104 // there is no next item.
105 @Override
106 public Result next() {
107 // since hasNext() does the real advancing, we call this to determine
108 // if there is a next before proceeding.
109 if (!hasNext()) {
110 return null;
111 }
112
113 // if we get to here, then hasNext() has given us an item to return.
114 // we want to return the item and then null out the next pointer, so
115 // we use a temporary variable.
116 Result temp = next;
117 next = null;
118 return temp;
119 }
120
121 @Override
122 public void remove() {
123 throw new UnsupportedOperationException();
124 }
125 };
126 }
127 /**
128 * Allow the client to renew the scanner's lease on the server.
129 * @return true if the lease was successfully renewed, false otherwise.
130 */
131 // Note that this method should be on ResultScanner, but that is marked stable.
132 // Callers have to cast their instance of ResultScanner to AbstractClientScanner to use this.
133 public abstract boolean renewLease();
134 }