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