Repository: hbase
Updated Branches:
  refs/heads/HBASE-14850 8335e1529 -> f27075a6f


HBASE-18188 [C++] Fix Handling do not retry exceptions


Project: http://git-wip-us.apache.org/repos/asf/hbase/repo
Commit: http://git-wip-us.apache.org/repos/asf/hbase/commit/f27075a6
Tree: http://git-wip-us.apache.org/repos/asf/hbase/tree/f27075a6
Diff: http://git-wip-us.apache.org/repos/asf/hbase/diff/f27075a6

Branch: refs/heads/HBASE-14850
Commit: f27075a6fa0a3219ef87421339b2a11af9e2df30
Parents: 8335e15
Author: Enis Soztutar <e...@apache.org>
Authored: Fri Jun 16 11:38:22 2017 -0700
Committer: Enis Soztutar <e...@apache.org>
Committed: Fri Jun 16 11:38:22 2017 -0700

----------------------------------------------------------------------
 hbase-native-client/bin/cpplint.sh              |   2 +-
 hbase-native-client/core/client-test.cc         |  11 +-
 hbase-native-client/core/location-cache.cc      |   4 +-
 hbase-native-client/exceptions/BUCK             |  13 +-
 .../exceptions/exception-test.cc                |  64 ++++++
 hbase-native-client/exceptions/exception.cc     | 128 ++++++++++++
 hbase-native-client/exceptions/exception.h      | 201 +++++++++++++------
 7 files changed, 362 insertions(+), 61 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/hbase/blob/f27075a6/hbase-native-client/bin/cpplint.sh
----------------------------------------------------------------------
diff --git a/hbase-native-client/bin/cpplint.sh 
b/hbase-native-client/bin/cpplint.sh
index 81795fd..3684c2e 100755
--- a/hbase-native-client/bin/cpplint.sh
+++ b/hbase-native-client/bin/cpplint.sh
@@ -27,4 +27,4 @@ wget -nc $CPPLINT_LOC -O $OUTPUT
 # Exclude the following rules: build/header_guard (We use #pragma once instead)
 #                              readability/todo (TODOs are generic)
 #                              build/c++11 (We are building with c++14)
-find core connection serde utils test-util security -name "*.h" -or -name 
"*.cc" | xargs -P8 python $OUTPUT 
--filter=-build/header_guard,-readability/todo,-build/c++11 --linelength=100
+find core connection exceptions serde utils test-util security -name "*.h" -or 
-name "*.cc" | xargs -P8 python $OUTPUT 
--filter=-build/header_guard,-readability/todo,-build/c++11 --linelength=100

http://git-wip-us.apache.org/repos/asf/hbase/blob/f27075a6/hbase-native-client/core/client-test.cc
----------------------------------------------------------------------
diff --git a/hbase-native-client/core/client-test.cc 
b/hbase-native-client/core/client-test.cc
index ed413e8..6462e6a 100644
--- a/hbase-native-client/core/client-test.cc
+++ b/hbase-native-client/core/client-test.cc
@@ -30,6 +30,7 @@
 #include "core/put.h"
 #include "core/result.h"
 #include "core/table.h"
+#include "exceptions/exception.h"
 #include "serde/table-name.h"
 #include "test-util/test-util.h"
 #include "utils/bytes-util.h"
@@ -37,6 +38,7 @@
 using hbase::Cell;
 using hbase::Configuration;
 using hbase::Get;
+using hbase::RetriesExhaustedException;
 using hbase::Put;
 using hbase::Table;
 using hbase::TestUtil;
@@ -326,7 +328,14 @@ TEST_F(ClientTest, GetForNonExistentTable) {
   ASSERT_TRUE(table) << "Unable to get connection to Table.";
 
   // Perform the Get
-  ASSERT_ANY_THROW(table->Get(get)) << "Table does not exist. We should get an 
exception";
+  try {
+    table->Get(get);
+    FAIL() << "Should have thrown RetriesExhaustedException";
+  } catch (const RetriesExhaustedException &ex) {
+    ASSERT_EQ(0, ex.num_retries());
+  } catch (...) {
+    FAIL() << "Should have thrown RetriesExhaustedException";
+  }
 
   table->Close();
   client.Close();

http://git-wip-us.apache.org/repos/asf/hbase/blob/f27075a6/hbase-native-client/core/location-cache.cc
----------------------------------------------------------------------
diff --git a/hbase-native-client/core/location-cache.cc 
b/hbase-native-client/core/location-cache.cc
index d368314..dfe3e9f 100644
--- a/hbase-native-client/core/location-cache.cc
+++ b/hbase-native-client/core/location-cache.cc
@@ -24,9 +24,9 @@
 #include <wangle/concurrent/CPUThreadPoolExecutor.h>
 #include <wangle/concurrent/IOThreadPoolExecutor.h>
 
-#include <folly/Logging.h>
 #include "connection/response.h"
 #include "connection/rpc-connection.h"
+#include "exceptions/exception.h"
 #include "if/Client.pb.h"
 #include "if/ZooKeeper.pb.h"
 #include "serde/region-info.h"
@@ -127,7 +127,7 @@ folly::Future<std::shared_ptr<RegionLocation>> 
LocationCache::LocateFromMeta(
         // Make sure that the correct location was found.
         if (rl->region_info().table_name().namespace_() != tn.namespace_() ||
             rl->region_info().table_name().qualifier() != tn.qualifier()) {
-          throw std::runtime_error("Doesn't look like table exists.");
+          throw TableNotFoundException(folly::to<std::string>(tn));
         }
         return rl;
       })

http://git-wip-us.apache.org/repos/asf/hbase/blob/f27075a6/hbase-native-client/exceptions/BUCK
----------------------------------------------------------------------
diff --git a/hbase-native-client/exceptions/BUCK 
b/hbase-native-client/exceptions/BUCK
index 07ffeaf..e2f03a1 100644
--- a/hbase-native-client/exceptions/BUCK
+++ b/hbase-native-client/exceptions/BUCK
@@ -20,9 +20,20 @@ cxx_library(
     exported_headers=[
         "exception.h",
     ],
-    srcs=[],
+    srcs=[
+        "exception.cc",
+    ],
     deps=[
         "//third-party:folly",
     ],
     compiler_flags=['-Weffc++'],
     visibility=['//core/...', '//connection//...'],)
+cxx_test(
+    name="exception-test",
+    srcs=[
+        "exception-test.cc",
+    ],
+    deps=[
+        ":exceptions",
+    ],
+    run_test_separately=True,)

http://git-wip-us.apache.org/repos/asf/hbase/blob/f27075a6/hbase-native-client/exceptions/exception-test.cc
----------------------------------------------------------------------
diff --git a/hbase-native-client/exceptions/exception-test.cc 
b/hbase-native-client/exceptions/exception-test.cc
new file mode 100644
index 0000000..583240e
--- /dev/null
+++ b/hbase-native-client/exceptions/exception-test.cc
@@ -0,0 +1,64 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+#include <gtest/gtest.h>
+
+#include "exceptions/exception.h"
+
+#include "folly/ExceptionWrapper.h"
+
+using hbase::ExceptionUtil;
+using hbase::IOException;
+using hbase::RemoteException;
+
+TEST(ExceptionUtilTest, IOExceptionShouldRetry) {
+  IOException ex{};
+  EXPECT_TRUE(ExceptionUtil::ShouldRetry(ex));
+
+  ex.set_do_not_retry(true);
+  EXPECT_FALSE(ExceptionUtil::ShouldRetry(ex));
+
+  ex.set_do_not_retry(false);
+  EXPECT_TRUE(ExceptionUtil::ShouldRetry(ex));
+
+  IOException ex2{"description", true};
+  EXPECT_FALSE(ExceptionUtil::ShouldRetry(ex2));
+
+  IOException ex3{"description", std::runtime_error("ex"), true};
+  EXPECT_FALSE(ExceptionUtil::ShouldRetry(ex3));
+}
+
+TEST(ExceptionUtilTest, RemoteExceptionShouldRetry) {
+  RemoteException ex{};
+  EXPECT_TRUE(ExceptionUtil::ShouldRetry(ex));
+
+  ex.set_do_not_retry(true);
+  EXPECT_FALSE(ExceptionUtil::ShouldRetry(ex));
+
+  ex.set_do_not_retry(false);
+  EXPECT_TRUE(ExceptionUtil::ShouldRetry(ex));
+
+  ex.set_exception_class_name("org.apache.hadoop.hbase.FooException");
+  EXPECT_TRUE(ExceptionUtil::ShouldRetry(ex));
+
+  
ex.set_exception_class_name("org.apache.hadoop.hbase.NotServingRegionException");
+  EXPECT_TRUE(ExceptionUtil::ShouldRetry(ex));
+
+  
ex.set_exception_class_name("org.apache.hadoop.hbase.UnknownRegionException");
+  EXPECT_FALSE(ExceptionUtil::ShouldRetry(ex));
+}

http://git-wip-us.apache.org/repos/asf/hbase/blob/f27075a6/hbase-native-client/exceptions/exception.cc
----------------------------------------------------------------------
diff --git a/hbase-native-client/exceptions/exception.cc 
b/hbase-native-client/exceptions/exception.cc
new file mode 100644
index 0000000..c25acb4
--- /dev/null
+++ b/hbase-native-client/exceptions/exception.cc
@@ -0,0 +1,128 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+#include "exceptions/exception.h"
+
+namespace hbase {
+const std::vector<const char*> ExceptionUtil::kAllDoNotRetryIOExceptions = {
+    kDoNotRetryIOException,
+    kTableNotFoundException,
+    kTableNotEnabledException,
+    kCoprocessorException,
+    kBypassCoprocessorException,
+    kInvalidFamilyOperationException,
+    kServerTooBusyException,
+    kFailedSanityCheckException,
+    kCorruptHFileException,
+    kLabelAlreadyExistsException,
+    kFatalConnectionException,
+    kUnsupportedCryptoException,
+    kUnsupportedCellCodecException,
+    kEmptyServiceNameException,
+    kUnknownServiceException,
+    kWrongVersionException,
+    kBadAuthException,
+    kUnsupportedCompressionCodecException,
+    kDoNotRetryRegionException,
+    kRowTooBigException,
+    kRowTooBigExceptionDeprecated,
+    kUnknownRegionException,
+    kMergeRegionException,
+    kNoServerForRegionException,
+    kQuotaExceededException,
+    kSpaceLimitingException,
+    kThrottlingException,
+    kAccessDeniedException,
+    kUnknownProtocolException,
+    kRequestTooBigException,
+    kNotAllMetaRegionsOnlineException,
+    kConstraintException,
+    kNoSuchColumnFamilyException,
+    kLeaseException,
+    kInvalidLabelException,
+    kUnknownScannerException,
+    kScannerResetException,
+    kOutOfOrderScannerNextException};
+
+bool ExceptionUtil::ShouldRetry(const folly::exception_wrapper& error) {
+  bool do_not_retry = false;
+  error.with_exception(
+      [&](const IOException& ioe) { do_not_retry = do_not_retry || 
ioe.do_not_retry(); });
+  error.with_exception([&](const RemoteException& remote_ex) {
+    do_not_retry = do_not_retry || 
IsJavaDoNotRetryException(remote_ex.exception_class_name());
+  });
+  return !do_not_retry;
+}
+
+/**
+ * Returns whether the java exception class extends DoNotRetryException.
+ * In the java side, we just have a hierarchy of Exception classes that we use
+ * both client side and server side. On the client side, we rethrow the server
+ * side exception by un-wrapping the exception from a RemoteException or a 
ServiceException
+ * (see ConnectionUtils.translateException() in Java).
+ * Since this object-hierarchy info is not available in C++ side, we are doing 
a
+ * very fragile catch-all list of all exception types in Java that extend the
+ * DoNotRetryException class type.
+ */
+bool ExceptionUtil::IsJavaDoNotRetryException(const std::string& 
java_class_name) {
+  for (auto exception : kAllDoNotRetryIOExceptions) {
+    if (java_class_name == exception) {
+      return true;
+    }
+  }
+  return false;
+}
+
+/**
+ * Returns whether the scanner is closed when the client received the
+ * remote exception.
+ * Since the object-hierarchy info is not available in C++ side, we are doing a
+ * very fragile catch-all list of all exception types in Java that extend these
+ * three base classes: UnknownScannerException, NotServingRegionException,
+ * RegionServerStoppedException
+ */
+bool ExceptionUtil::IsScannerClosed(const folly::exception_wrapper& exception) 
{
+  bool scanner_closed = false;
+  exception.with_exception([&](const RemoteException& remote_ex) {
+    auto java_class = remote_ex.exception_class_name();
+    if (java_class == kUnknownScannerException || java_class == 
kNotServingRegionException ||
+        java_class == kRegionInRecoveryException || java_class == 
kRegionOpeningException ||
+        java_class == kRegionMovedException || java_class == 
kRegionServerStoppedException ||
+        java_class == kRegionServerAbortedException) {
+      scanner_closed = true;
+    }
+  });
+  return scanner_closed;
+}
+
+/**
+ * Returns whether the wrapped exception is a java exception of type 
OutOfOrderScannerNextException
+ * or ScannerResetException. These two exception types are thrown from the 
server side when the
+ * scanner on the server side is closed.
+ */
+bool ExceptionUtil::IsScannerOutOfOrder(const folly::exception_wrapper& 
exception) {
+  bool scanner_out_of_order = false;
+  exception.with_exception([&](const RemoteException& remote_ex) {
+    auto java_class = remote_ex.exception_class_name();
+    if (java_class == kOutOfOrderScannerNextException || java_class == 
kScannerResetException) {
+      scanner_out_of_order = true;
+    }
+  });
+  return scanner_out_of_order;
+}
+}  // namespace hbase

http://git-wip-us.apache.org/repos/asf/hbase/blob/f27075a6/hbase-native-client/exceptions/exception.h
----------------------------------------------------------------------
diff --git a/hbase-native-client/exceptions/exception.h 
b/hbase-native-client/exceptions/exception.h
index 9cbd7ae..bdedff4 100644
--- a/hbase-native-client/exceptions/exception.h
+++ b/hbase-native-client/exceptions/exception.h
@@ -21,6 +21,7 @@
 #include <folly/ExceptionWrapper.h>
 #include <folly/io/IOBuf.h>
 #include <exception>
+#include <memory>
 #include <string>
 #include <vector>
 
@@ -28,10 +29,10 @@ namespace hbase {
 
 class ThrowableWithExtraContext {
  public:
-  ThrowableWithExtraContext(folly::exception_wrapper cause, const long& when)
+  ThrowableWithExtraContext(folly::exception_wrapper cause, const int64_t& 
when)
       : cause_(cause), when_(when), extras_("") {}
 
-  ThrowableWithExtraContext(folly::exception_wrapper cause, const long& when,
+  ThrowableWithExtraContext(folly::exception_wrapper cause, const int64_t& 
when,
                             const std::string& extras)
       : cause_(cause), when_(when), extras_(extras) {}
 
@@ -45,23 +46,44 @@ class ThrowableWithExtraContext {
 
  private:
   folly::exception_wrapper cause_;
-  long when_;
+  int64_t when_;
   std::string extras_;
 };
 
 class IOException : public std::logic_error {
  public:
-  IOException() : logic_error("") {}
+  IOException() : logic_error(""), do_not_retry_(false) {}
+
+  explicit IOException(const std::string& what) : logic_error(what), 
do_not_retry_(false) {}
+
+  IOException(const std::string& what, bool do_not_retry)
+      : logic_error(what), do_not_retry_(do_not_retry) {}
 
-  IOException(const std::string& what) : logic_error(what) {}
   IOException(const std::string& what, folly::exception_wrapper cause)
-      : logic_error(what), cause_(cause) {}
+      : logic_error(what), cause_(cause), do_not_retry_(false) {}
+
+  IOException(const std::string& what, folly::exception_wrapper cause, bool 
do_not_retry)
+      : logic_error(what), cause_(cause), do_not_retry_(do_not_retry) {}
+
   virtual ~IOException() = default;
 
   virtual folly::exception_wrapper cause() { return cause_; }
 
+  bool do_not_retry() const { return do_not_retry_; }
+
+  IOException* set_do_not_retry(bool value) {
+    do_not_retry_ = value;
+    return this;
+  }
+
  private:
   folly::exception_wrapper cause_;
+  // In case the exception is a RemoteException, do_not_retry information can 
come from
+  // the PB field in the RPC response, or it can be deduced from the 
Java-exception
+  // hierarchy in ExceptionUtil::ShouldRetry(). In case this is a client-side 
exception
+  // raised from the C++ internals, set this field so that the retrying 
callers can
+  // re-throw the exception without retrying.
+  bool do_not_retry_;
 };
 
 class RetriesExhaustedException : public IOException {
@@ -70,9 +92,12 @@ class RetriesExhaustedException : public IOException {
                             
std::shared_ptr<std::vector<ThrowableWithExtraContext>> exceptions)
       : IOException(GetMessage(num_retries, exceptions),
                     exceptions->empty() ? folly::exception_wrapper{}
-                                        : (*exceptions)[exceptions->size() - 
1].cause()) {}
+                                        : (*exceptions)[exceptions->size() - 
1].cause()),
+        num_retries_(num_retries) {}
   virtual ~RetriesExhaustedException() = default;
 
+  int32_t num_retries() const { return num_retries_; }
+
  private:
   std::string GetMessage(const int& num_retries,
                          
std::shared_ptr<std::vector<ThrowableWithExtraContext>> exceptions) {
@@ -85,18 +110,19 @@ class RetriesExhaustedException : public IOException {
     }
     return buffer;
   }
-};
 
-class HBaseIOException : public IOException {};
+ private:
+  int32_t num_retries_;
+};
 
 class RemoteException : public IOException {
  public:
-  RemoteException() : port_(0), do_not_retry_(false) {}
+  RemoteException() : IOException(), port_(0) {}
 
-  RemoteException(const std::string& what) : IOException(what), port_(0), 
do_not_retry_(false) {}
+  explicit RemoteException(const std::string& what) : IOException(what), 
port_(0) {}
 
   RemoteException(const std::string& what, folly::exception_wrapper cause)
-      : IOException(what, cause), port_(0), do_not_retry_(false) {}
+      : IOException(what, cause), port_(0) {}
 
   virtual ~RemoteException() = default;
 
@@ -128,19 +154,23 @@ class RemoteException : public IOException {
     return this;
   }
 
-  bool do_not_retry() const { return do_not_retry_; }
-
-  RemoteException* set_do_not_retry(bool value) {
-    do_not_retry_ = value;
-    return this;
-  }
-
  private:
   std::string exception_class_name_;
   std::string stack_trace_;
   std::string hostname_;
   int port_;
-  bool do_not_retry_;
+};
+
+/**
+ * Raised from the client side if we cannot find the table (does not have 
anything to
+ * do with the Java exception of the same name).
+ */
+class TableNotFoundException : public IOException {
+ public:
+  explicit TableNotFoundException(const std::string& table_name)
+      : IOException("Table cannot be found:" + table_name, true) {}
+
+  virtual ~TableNotFoundException() = default;
 };
 
 /**
@@ -174,54 +204,113 @@ class ExceptionUtil {
   static constexpr const char* kScannerResetException =
       "org.apache.hadoop.hbase.exceptions.ScannerResetException";
 
+  // All other DoNotRetryIOExceptions
+  static constexpr const char* kDoNotRetryIOException =
+      "org.apache.hadoop.hbase.DoNotRetryIOException";
+  static constexpr const char* kTableNotFoundException =
+      "org.apache.hadoop.hbase.TableNotFoundException";
+  static constexpr const char* kTableNotEnabledException =
+      "org.apache.hadoop.hbase.TableNotEnabledException";
+  static constexpr const char* kCoprocessorException =
+      "org.apache.hadoop.hbase.coprocessor.CoprocessorException";
+  static constexpr const char* kBypassCoprocessorException =
+      "org.apache.hadoop.hbase.coprocessor.BypassCoprocessorException";
+  static constexpr const char* kInvalidFamilyOperationException =
+      "org.apache.hadoop.hbase.InvalidFamilyOperationException";
+  static constexpr const char* kServerTooBusyException =
+      "org.apache.hadoop.hbase.ipc.ServerTooBusyException";  // This should 
NOT be DNRIOE?
+  static constexpr const char* kFailedSanityCheckException =
+      "org.apache.hadoop.hbase.exceptions.FailedSanityCheckException";
+  static constexpr const char* kCorruptHFileException =
+      "org.apache.hadoop.hbase.io.hfile.CorruptHFileException";
+  static constexpr const char* kLabelAlreadyExistsException =
+      
"org.apache.hadoop.hbase.security.visibility.LabelAlreadyExistsException";
+  static constexpr const char* kFatalConnectionException =
+      "org.apache.hadoop.hbase.ipc.FatalConnectionException";
+  static constexpr const char* kUnsupportedCryptoException =
+      "org.apache.hadoop.hbase.ipc.UnsupportedCryptoException";
+  static constexpr const char* kUnsupportedCellCodecException =
+      "org.apache.hadoop.hbase.ipc.UnsupportedCellCodecException";
+  static constexpr const char* kEmptyServiceNameException =
+      "org.apache.hadoop.hbase.ipc.EmptyServiceNameException";
+  static constexpr const char* kUnknownServiceException =
+      "org.apache.hadoop.hbase.ipc.UnknownServiceException";
+  static constexpr const char* kWrongVersionException =
+      "org.apache.hadoop.hbase.ipc.WrongVersionException";
+  static constexpr const char* kBadAuthException = 
"org.apache.hadoop.hbase.ipc.BadAuthException";
+  static constexpr const char* kUnsupportedCompressionCodecException =
+      "org.apache.hadoop.hbase.ipc.UnsupportedCompressionCodecException";
+  static constexpr const char* kDoNotRetryRegionException =
+      "org.apache.hadoop.hbase.client.DoNotRetryRegionException";
+  static constexpr const char* kRowTooBigException =
+      "org.apache.hadoop.hbase.client.RowTooBigException";
+  static constexpr const char* kRowTooBigExceptionDeprecated =
+      "org.apache.hadoop.hbase.regionserver.RowTooBigException";
+  static constexpr const char* kUnknownRegionException =
+      "org.apache.hadoop.hbase.UnknownRegionException";
+  static constexpr const char* kMergeRegionException =
+      "org.apache.hadoop.hbase.exceptions.MergeRegionException";
+  static constexpr const char* kNoServerForRegionException =
+      "org.apache.hadoop.hbase.client.NoServerForRegionException";
+  static constexpr const char* kQuotaExceededException =
+      "org.apache.hadoop.hbase.quotas.QuotaExceededException";
+  static constexpr const char* kSpaceLimitingException =
+      "org.apache.hadoop.hbase.quotas.SpaceLimitingException";
+  static constexpr const char* kThrottlingException =
+      "org.apache.hadoop.hbase.quotas.ThrottlingException";
+  static constexpr const char* kAccessDeniedException =
+      "org.apache.hadoop.hbase.security.AccessDeniedException";
+  static constexpr const char* kUnknownProtocolException =
+      "org.apache.hadoop.hbase.exceptions.UnknownProtocolException";
+  static constexpr const char* kRequestTooBigException =
+      "org.apache.hadoop.hbase.exceptions.RequestTooBigException";
+  static constexpr const char* kNotAllMetaRegionsOnlineException =
+      "org.apache.hadoop.hbase.NotAllMetaRegionsOnlineException";
+  static constexpr const char* kConstraintException =
+      "org.apache.hadoop.hbase.constraint.ConstraintException";
+  static constexpr const char* kNoSuchColumnFamilyException =
+      "org.apache.hadoop.hbase.regionserver.NoSuchColumnFamilyException";
+  static constexpr const char* kLeaseException =
+      "org.apache.hadoop.hbase.regionserver.LeaseException";
+  static constexpr const char* kInvalidLabelException =
+      "org.apache.hadoop.hbase.security.visibility.InvalidLabelException";
+
+  // TODO:
+  // These exceptions are not thrown in the regular read / write paths, 
although they are
+  // DoNotRetryIOExceptions. Add these to the list below in case we start 
doing Admin/DDL ops
+  // ReplicationPeerNotFoundException, XXXSnapshotException, 
NamespaceExistException,
+  // NamespaceNotFoundException, TableExistsException, 
TableNotDisabledException,
+  static const std::vector<const char*> kAllDoNotRetryIOExceptions;
+
  public:
   /**
    * Returns whether or not the exception should be retried by looking at the
-   * remote exception.
+   * client-side IOException, or RemoteException coming from server side.
    */
-  static bool ShouldRetry(const folly::exception_wrapper& error) {
-    bool do_not_retry = false;
-    error.with_exception(
-        [&](const RemoteException& remote_ex) { do_not_retry = 
remote_ex.do_not_retry(); });
-    return !do_not_retry;
-  }
+  static bool ShouldRetry(const folly::exception_wrapper& error);
 
   /**
-   * Returns whether the scanner is closed when the client received the
-   * remote exception.
-   * Ok, here is a nice detail about the java exceptions. In the java side, we
-   * just have a hierarchy of Exception classes that we use both client side 
and
-   * server side. On the client side, we rethrow the server side exception by
-   * un-wrapping the exception from a RemoteException or a ServiceException
+   * Returns whether the java exception class extends DoNotRetryException.
+   * In the java side, we just have a hierarchy of Exception classes that we 
use
+   * both client side and server side. On the client side, we rethrow the 
server
+   * side exception by un-wrapping the exception from a RemoteException or a 
ServiceException
    * (see ConnectionUtils.translateException() in Java).
    * Since this object-hierarchy info is not available in C++ side, we are 
doing a
+   * very fragile catch-all list of all exception types in Java that extend the
+   * DoNotRetryException class type.
+   */
+  static bool IsJavaDoNotRetryException(const std::string& java_class_name);
+
+  /**
+   * Returns whether the scanner is closed when the client received the
+   * remote exception.
+   * Since the object-hierarchy info is not available in C++ side, we are 
doing a
    * very fragile catch-all list of all exception types in Java that extend 
these
    * three base classes: UnknownScannerException, NotServingRegionException,
    * RegionServerStoppedException
    */
-  static bool IsScannerClosed(const folly::exception_wrapper& exception) {
-    bool scanner_closed = false;
-    exception.with_exception([&](const RemoteException& remote_ex) {
-      auto java_class = remote_ex.exception_class_name();
-      if (java_class == kUnknownScannerException || java_class == 
kNotServingRegionException ||
-          java_class == kRegionInRecoveryException || java_class == 
kRegionOpeningException ||
-          java_class == kRegionMovedException || java_class == 
kRegionServerStoppedException ||
-          java_class == kRegionServerAbortedException) {
-        scanner_closed = true;
-      }
-    });
-    return scanner_closed;
-  }
+  static bool IsScannerClosed(const folly::exception_wrapper& exception);
 
-  static bool IsScannerOutOfOrder(const folly::exception_wrapper& exception) {
-    bool scanner_out_of_order = false;
-    exception.with_exception([&](const RemoteException& remote_ex) {
-      auto java_class = remote_ex.exception_class_name();
-      if (java_class == kOutOfOrderScannerNextException || java_class == 
kScannerResetException) {
-        scanner_out_of_order = true;
-      }
-    });
-    return scanner_out_of_order;
-  }
+  static bool IsScannerOutOfOrder(const folly::exception_wrapper& exception);
 };
 }  // namespace hbase

Reply via email to