Creates a new errback to handle errors while trying to get more rows.
()
| 842 | * Creates a new errback to handle errors while trying to get more rows. |
| 843 | */ |
| 844 | final Callback<Object, Object> nextRowErrback() { |
| 845 | return new Callback<Object, Object>() { |
| 846 | public Object call(final Object error) { |
| 847 | final RegionInfo old_region = region; // Save before invalidate(). |
| 848 | invalidate(); // If there was an error, don't assume we're still OK. |
| 849 | if (error instanceof NotServingRegionException) { |
| 850 | // We'll resume scanning on another region, and we want to pick up |
| 851 | // right after the last key we successfully returned. Padding the |
| 852 | // last key with an extra 0 gives us the next possible key. |
| 853 | // TODO(tsuna): If we get 2 NSRE in a row, well pad the key twice! |
| 854 | start_key = Arrays.copyOf(start_key, start_key.length + 1); |
| 855 | return nextRows(); // XXX dangerous endless retry |
| 856 | } else if (error instanceof UnknownScannerException) { |
| 857 | // This can happen when our scanner lease expires. Unfortunately |
| 858 | // there's no way for us to distinguish between an expired lease |
| 859 | // and a real problem, for 2 reasons: the server doesn't keep track |
| 860 | // of recently expired scanners and the lease time is only known by |
| 861 | // the server and never communicated to the client. The normal |
| 862 | // HBase client assumes that the client will share the same |
| 863 | // hbase-site.xml configuration so that both the client and the |
| 864 | // server will know the same lease time, but this assumption is bad |
| 865 | // as nothing guarantees that the client's configuration will be in |
| 866 | // sync with the server's. This unnecessarily increases deployment |
| 867 | // complexity and it's brittle. |
| 868 | final Scanner scnr = Scanner.this; |
| 869 | LOG.warn(old_region + " pretends to not know " + scnr + ". I will" |
| 870 | + " retry to open a scanner but this is typically because you've" |
| 871 | + " been holding the scanner open and idle for too long (possibly" |
| 872 | + " due to a long GC pause on your side or in the RegionServer)", |
| 873 | error); |
| 874 | // Let's re-open ourselves and keep scanning. |
| 875 | return nextRows(); // XXX dangerous endless retry |
| 876 | } |
| 877 | return error; // Let the error propagate. |
| 878 | } |
| 879 | public String toString() { |
| 880 | return "NextRow errback"; |
| 881 | } |
| 882 | }; |
| 883 | } |
| 884 | |
| 885 | /** |
| 886 | * Closes this scanner (don't forget to call this when you're done with it!). |