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; 024import org.apache.hadoop.conf.Configuration; 025import org.apache.hadoop.fs.FileSystem; 026import org.apache.hadoop.fs.Path; 027import org.apache.hadoop.hbase.Cell; 028import org.apache.hadoop.hbase.PrivateCellUtil; 029import org.apache.hadoop.hbase.client.metrics.ScanMetrics; 030import org.apache.hadoop.hbase.mob.MobFileCache; 031import org.apache.hadoop.hbase.regionserver.HRegion; 032import org.apache.hadoop.hbase.regionserver.RegionScanner; 033import org.apache.hadoop.hbase.util.CommonFSUtils; 034import org.apache.yetus.audience.InterfaceAudience; 035import org.slf4j.Logger; 036import org.slf4j.LoggerFactory; 037 038/** 039 * A client scanner for a region opened for read-only on the client side. Assumes region data 040 * is not changing. 041 */ 042@InterfaceAudience.Private 043public class ClientSideRegionScanner extends AbstractClientScanner { 044 045 private static final Logger LOG = LoggerFactory.getLogger(ClientSideRegionScanner.class); 046 047 private HRegion region; 048 RegionScanner scanner; 049 List<Cell> values; 050 051 public ClientSideRegionScanner(Configuration conf, FileSystem fs, 052 Path rootDir, TableDescriptor htd, RegionInfo hri, Scan scan, ScanMetrics scanMetrics) 053 throws IOException { 054 // region is immutable, set isolation level 055 scan.setIsolationLevel(IsolationLevel.READ_UNCOMMITTED); 056 057 htd = TableDescriptorBuilder.newBuilder(htd).setReadOnly(true).build(); 058 059 // open region from the snapshot directory 060 region = HRegion.newHRegion(CommonFSUtils.getTableDir(rootDir, htd.getTableName()), null, fs, 061 conf, hri, htd, null); 062 region.setRestoredRegion(true); 063 // we won't initialize the MobFileCache when not running in RS process. so provided an 064 // initialized cache. Consider the case: an CF was set from an mob to non-mob. if we only 065 // initialize cache for MOB region, NPE from HMobStore will still happen. So Initialize the 066 // cache for every region although it may hasn't any mob CF, BTW the cache is very light-weight. 067 region.setMobFileCache(new MobFileCache(conf)); 068 region.initialize(); 069 070 // create an internal region scanner 071 this.scanner = region.getScanner(scan); 072 values = new ArrayList<>(); 073 074 if (scanMetrics == null) { 075 initScanMetrics(scan); 076 } else { 077 this.scanMetrics = scanMetrics; 078 } 079 region.startRegionOperation(); 080 } 081 082 @Override 083 public Result next() throws IOException { 084 values.clear(); 085 scanner.nextRaw(values); 086 if (values.isEmpty()) { 087 //we are done 088 return null; 089 } 090 091 Result result = Result.create(values); 092 if (this.scanMetrics != null) { 093 long resultSize = 0; 094 for (Cell cell : values) { 095 resultSize += PrivateCellUtil.estimatedSerializedSizeOf(cell); 096 } 097 this.scanMetrics.countOfBytesInResults.addAndGet(resultSize); 098 this.scanMetrics.countOfRowsScanned.incrementAndGet(); 099 } 100 101 return result; 102 } 103 104 @Override 105 public void close() { 106 if (this.scanner != null) { 107 try { 108 this.scanner.close(); 109 this.scanner = null; 110 } catch (IOException ex) { 111 LOG.warn("Exception while closing scanner", ex); 112 } 113 } 114 if (this.region != null) { 115 try { 116 this.region.closeRegionOperation(); 117 this.region.close(true); 118 this.region = null; 119 } catch (IOException ex) { 120 LOG.warn("Exception while closing region", ex); 121 } 122 } 123 } 124 125 @Override 126 public boolean renewLease() { 127 throw new UnsupportedOperationException(); 128 } 129}