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 */ 018 019package org.apache.hadoop.hbase.client; 020 021import java.io.IOException; 022import java.util.ArrayList; 023import java.util.List; 024 025import org.apache.hadoop.conf.Configuration; 026import org.apache.hadoop.fs.FileSystem; 027import org.apache.hadoop.fs.Path; 028import org.apache.hadoop.hbase.Cell; 029import org.apache.hadoop.hbase.PrivateCellUtil; 030import org.apache.hadoop.hbase.client.metrics.ScanMetrics; 031import org.apache.hadoop.hbase.regionserver.HRegion; 032import org.apache.hadoop.hbase.regionserver.RegionScanner; 033import org.apache.yetus.audience.InterfaceAudience; 034import org.slf4j.Logger; 035import org.slf4j.LoggerFactory; 036 037/** 038 * A client scanner for a region opened for read-only on the client side. Assumes region data 039 * is not changing. 040 */ 041@InterfaceAudience.Private 042public class ClientSideRegionScanner extends AbstractClientScanner { 043 044 private static final Logger LOG = LoggerFactory.getLogger(ClientSideRegionScanner.class); 045 046 private HRegion region; 047 RegionScanner scanner; 048 List<Cell> values; 049 050 public ClientSideRegionScanner(Configuration conf, FileSystem fs, 051 Path rootDir, TableDescriptor htd, RegionInfo hri, Scan scan, ScanMetrics scanMetrics) 052 throws IOException { 053 // region is immutable, set isolation level 054 scan.setIsolationLevel(IsolationLevel.READ_UNCOMMITTED); 055 056 htd = TableDescriptorBuilder.newBuilder(htd).setReadOnly(true).build(); 057 058 // open region from the snapshot directory 059 this.region = HRegion.openHRegion(conf, fs, rootDir, hri, htd, null, null, null); 060 061 // create an internal region scanner 062 this.scanner = region.getScanner(scan); 063 values = new ArrayList<>(); 064 065 if (scanMetrics == null) { 066 initScanMetrics(scan); 067 } else { 068 this.scanMetrics = scanMetrics; 069 } 070 region.startRegionOperation(); 071 } 072 073 @Override 074 public Result next() throws IOException { 075 values.clear(); 076 scanner.nextRaw(values); 077 if (values.isEmpty()) { 078 //we are done 079 return null; 080 } 081 082 Result result = Result.create(values); 083 if (this.scanMetrics != null) { 084 long resultSize = 0; 085 for (Cell cell : values) { 086 resultSize += PrivateCellUtil.estimatedSerializedSizeOf(cell); 087 } 088 this.scanMetrics.countOfBytesInResults.addAndGet(resultSize); 089 this.scanMetrics.countOfRowsScanned.incrementAndGet(); 090 } 091 092 return result; 093 } 094 095 @Override 096 public void close() { 097 if (this.scanner != null) { 098 try { 099 this.scanner.close(); 100 this.scanner = null; 101 } catch (IOException ex) { 102 LOG.warn("Exception while closing scanner", ex); 103 } 104 } 105 if (this.region != null) { 106 try { 107 this.region.closeRegionOperation(); 108 this.region.close(true); 109 this.region = null; 110 } catch (IOException ex) { 111 LOG.warn("Exception while closing region", ex); 112 } 113 } 114 } 115 116 @Override 117 public boolean renewLease() { 118 throw new UnsupportedOperationException(); 119 } 120}