1 /*
2   Copyright (c) DataStax, Inc.
3 
4   Licensed under the Apache License, Version 2.0 (the "License");
5   you may not use this file except in compliance with the License.
6   You may obtain a copy of the License at
7 
8   http://www.apache.org/licenses/LICENSE-2.0
9 
10   Unless required by applicable law or agreed to in writing, software
11   distributed under the License is distributed on an "AS IS" BASIS,
12   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   See the License for the specific language governing permissions and
14   limitations under the License.
15 */
16 
17 #ifndef DATASTAX_INTERNAL_RETRY_POLICY_HPP
18 #define DATASTAX_INTERNAL_RETRY_POLICY_HPP
19 
20 #include "cassandra.h"
21 #include "error_response.hpp"
22 #include "external.hpp"
23 #include "ref_counted.hpp"
24 
25 #ifdef _WIN32
26 #ifdef IGNORE
27 #undef IGNORE
28 #endif
29 #endif
30 
31 namespace datastax { namespace internal { namespace core {
32 
33 class ErrorResponse;
34 class Request;
35 
36 class RetryPolicy : public RefCounted<RetryPolicy> {
37 public:
38   typedef SharedRefPtr<RetryPolicy> Ptr;
39 
40   enum Type { DEFAULT, DOWNGRADING, FALLTHROUGH, LOGGING };
41 
42   class RetryDecision {
43   public:
44     enum Type { RETURN_ERROR, RETRY, IGNORE };
45 
RetryDecision(Type type,CassConsistency retry_cl,bool retry_current_host)46     RetryDecision(Type type, CassConsistency retry_cl, bool retry_current_host)
47         : type_(type)
48         , retry_cl_(retry_cl)
49         , retry_current_host_(retry_current_host) {}
50 
type() const51     Type type() const { return type_; }
retry_consistency() const52     CassConsistency retry_consistency() const { return retry_cl_; }
retry_current_host() const53     bool retry_current_host() const { return retry_current_host_; }
54 
return_error()55     static RetryDecision return_error() {
56       return RetryDecision(RETURN_ERROR, CASS_CONSISTENCY_UNKNOWN, false);
57     }
58 
retry(CassConsistency cl)59     static RetryDecision retry(CassConsistency cl) { return RetryDecision(RETRY, cl, true); }
60 
retry_next_host(CassConsistency cl)61     static RetryDecision retry_next_host(CassConsistency cl) {
62       return RetryDecision(RETRY, cl, false);
63     }
64 
ignore()65     static RetryDecision ignore() { return RetryDecision(IGNORE, CASS_CONSISTENCY_UNKNOWN, false); }
66 
67   private:
68     Type type_;
69     CassConsistency retry_cl_;
70     bool retry_current_host_;
71   };
72 
RetryPolicy(Type type)73   RetryPolicy(Type type)
74       : type_(type) {}
75 
~RetryPolicy()76   virtual ~RetryPolicy() {}
77 
type() const78   Type type() const { return type_; }
79 
80   virtual RetryDecision on_read_timeout(const Request* request, CassConsistency cl, int received,
81                                         int required, bool data_recevied,
82                                         int num_retries) const = 0;
83   virtual RetryDecision on_write_timeout(const Request* request, CassConsistency cl, int received,
84                                          int required, CassWriteType write_type,
85                                          int num_retries) const = 0;
86   virtual RetryDecision on_unavailable(const Request* request, CassConsistency cl, int required,
87                                        int alive, int num_retries) const = 0;
88   virtual RetryDecision on_request_error(const Request* request, CassConsistency cl,
89                                          const ErrorResponse* error, int num_retries) const = 0;
90 
91 private:
92   Type type_;
93 };
94 
95 class DefaultRetryPolicy : public RetryPolicy {
96 public:
DefaultRetryPolicy()97   DefaultRetryPolicy()
98       : RetryPolicy(DEFAULT) {}
99 
100   virtual RetryDecision on_read_timeout(const Request* request, CassConsistency cl, int received,
101                                         int required, bool data_recevied, int num_retries) const;
102   virtual RetryDecision on_write_timeout(const Request* request, CassConsistency cl, int received,
103                                          int required, CassWriteType write_type,
104                                          int num_retries) const;
105   virtual RetryDecision on_unavailable(const Request* request, CassConsistency cl, int required,
106                                        int alive, int num_retries) const;
107   virtual RetryDecision on_request_error(const Request* request, CassConsistency cl,
108                                          const ErrorResponse* error, int num_retries) const;
109 };
110 
111 class DowngradingConsistencyRetryPolicy : public RetryPolicy {
112 public:
DowngradingConsistencyRetryPolicy()113   DowngradingConsistencyRetryPolicy()
114       : RetryPolicy(DOWNGRADING) {}
115 
116   virtual RetryDecision on_read_timeout(const Request* request, CassConsistency cl, int received,
117                                         int required, bool data_recevied, int num_retries) const;
118   virtual RetryDecision on_write_timeout(const Request* request, CassConsistency cl, int received,
119                                          int required, CassWriteType write_type,
120                                          int num_retries) const;
121   virtual RetryDecision on_unavailable(const Request* request, CassConsistency cl, int required,
122                                        int alive, int num_retries) const;
123   virtual RetryDecision on_request_error(const Request* request, CassConsistency cl,
124                                          const ErrorResponse* error, int num_retries) const;
125 };
126 
127 class FallthroughRetryPolicy : public RetryPolicy {
128 public:
FallthroughRetryPolicy()129   FallthroughRetryPolicy()
130       : RetryPolicy(FALLTHROUGH) {}
131 
132   virtual RetryDecision on_read_timeout(const Request* request, CassConsistency cl, int received,
133                                         int required, bool data_recevied, int num_retries) const;
134   virtual RetryDecision on_write_timeout(const Request* request, CassConsistency cl, int received,
135                                          int required, CassWriteType write_type,
136                                          int num_retries) const;
137   virtual RetryDecision on_unavailable(const Request* request, CassConsistency cl, int required,
138                                        int alive, int num_retries) const;
139   virtual RetryDecision on_request_error(const Request* request, CassConsistency cl,
140                                          const ErrorResponse* error, int num_retries) const;
141 };
142 
143 class LoggingRetryPolicy : public RetryPolicy {
144 public:
LoggingRetryPolicy(const RetryPolicy::Ptr & retry_policy)145   LoggingRetryPolicy(const RetryPolicy::Ptr& retry_policy)
146       : RetryPolicy(LOGGING)
147       , retry_policy_(retry_policy) {}
148 
149   virtual RetryDecision on_read_timeout(const Request* request, CassConsistency cl, int received,
150                                         int required, bool data_recevied, int num_retries) const;
151   virtual RetryDecision on_write_timeout(const Request* request, CassConsistency cl, int received,
152                                          int required, CassWriteType write_type,
153                                          int num_retries) const;
154   virtual RetryDecision on_unavailable(const Request* request, CassConsistency cl, int required,
155                                        int alive, int num_retries) const;
156   virtual RetryDecision on_request_error(const Request* request, CassConsistency cl,
157                                          const ErrorResponse* response, int num_retries) const;
158 
159 private:
160   RetryPolicy::Ptr retry_policy_;
161 };
162 
163 }}} // namespace datastax::internal::core
164 
165 EXTERNAL_TYPE(datastax::internal::core::RetryPolicy, CassRetryPolicy)
166 
167 #endif
168