View Javadoc

1   /**
2    * Copyright 2010 The Apache Software Foundation
3    *
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *     http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing, software
15   * distributed under the License is distributed on an "AS IS" BASIS,
16   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17   * See the License for the specific language governing permissions and
18   * limitations under the License.
19   */
20  
21  package org.apache.hadoop.hbase.client;
22  
23  import org.apache.hadoop.hbase.DoNotRetryIOException;
24  import org.apache.hadoop.hbase.HRegionInfo;
25  import org.apache.hadoop.hbase.NotServingRegionException;
26  import org.apache.hadoop.hbase.RemoteExceptionHandler;
27  import org.apache.hadoop.ipc.RemoteException;
28  import org.mortbay.log.Log;
29  
30  import java.io.IOException;
31  
32  
33  /**
34   * Retries scanner operations such as create, next, etc.
35   * Used by {@link ResultScanner}s made by {@link HTable}.
36   */
37  public class ScannerCallable extends ServerCallable<Result[]> {
38    private long scannerId = -1L;
39    private boolean instantiated = false;
40    private boolean closed = false;
41    private Scan scan;
42    private int caching = 1;
43  
44    /**
45     * @param connection which connection
46     * @param tableName table callable is on
47     * @param scan the scan to execute
48     */
49    public ScannerCallable (HConnection connection, byte [] tableName, Scan scan) {
50      super(connection, tableName, scan.getStartRow());
51      this.scan = scan;
52    }
53  
54    /**
55     * @param reload force reload of server location
56     * @throws IOException
57     */
58    @Override
59    public void instantiateServer(boolean reload) throws IOException {
60      if (!instantiated || reload) {
61        super.instantiateServer(reload);
62        instantiated = true;
63      }
64    }
65  
66    /**
67     * @see java.util.concurrent.Callable#call()
68     */
69    public Result [] call() throws IOException {
70      if (scannerId != -1L && closed) {
71        close();
72      } else if (scannerId == -1L && !closed) {
73        this.scannerId = openScanner();
74      } else {
75        Result [] rrs = null;
76        try {
77          rrs = server.next(scannerId, caching);
78        } catch (IOException e) {
79          IOException ioe = null;
80          if (e instanceof RemoteException) {
81            ioe = RemoteExceptionHandler.decodeRemoteException((RemoteException)e);
82          }
83          if (ioe == null) throw new IOException(e);
84          if (ioe instanceof NotServingRegionException) {
85            // Throw a DNRE so that we break out of cycle of calling NSRE
86            // when what we need is to open scanner against new location.
87            // Attach NSRE to signal client that it needs to resetup scanner.
88            throw new DoNotRetryIOException("Reset scanner", ioe);
89          } else {
90            // The outer layers will retry
91            throw ioe;
92          }
93        }
94        return rrs;
95      }
96      return null;
97    }
98  
99    private void close() {
100     if (this.scannerId == -1L) {
101       return;
102     }
103     try {
104       this.server.close(this.scannerId);
105     } catch (IOException e) {
106       Log.warn("Ignore, probably already closed", e);
107     }
108     this.scannerId = -1L;
109   }
110 
111   protected long openScanner() throws IOException {
112     return this.server.openScanner(this.location.getRegionInfo().getRegionName(),
113       this.scan);
114   }
115 
116   protected Scan getScan() {
117     return scan;
118   }
119 
120   /**
121    * Call this when the next invocation of call should close the scanner
122    */
123   public void setClose() {
124     this.closed = true;
125   }
126 
127   /**
128    * @return the HRegionInfo for the current region
129    */
130   public HRegionInfo getHRegionInfo() {
131     if (!instantiated) {
132       return null;
133     }
134     return location.getRegionInfo();
135   }
136 
137   /**
138    * Get the number of rows that will be fetched on next
139    * @return the number of rows for caching
140    */
141   public int getCaching() {
142     return caching;
143   }
144 
145   /**
146    * Set the number of rows that will be fetched on next
147    * @param caching the number of rows for caching
148    */
149   public void setCaching(int caching) {
150     this.caching = caching;
151   }
152 }