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 }