-
Notifications
You must be signed in to change notification settings - Fork 0
/
CarbonRouterInstance.h
250 lines (206 loc) · 7.75 KB
/
CarbonRouterInstance.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#pragma once
#include <atomic>
#include <condition_variable>
#include <functional>
#include <memory>
#include <mutex>
#include <thread>
#include <vector>
#include <folly/Range.h>
#include "mcrouter/CallbackPool.h"
#include "mcrouter/CarbonRouterClient.h"
#include "mcrouter/CarbonRouterInstanceBase.h"
#include "mcrouter/ConfigApi.h"
#include "mcrouter/FileObserver.h"
#include "mcrouter/Proxy.h"
#include "mcrouter/ProxyConfigBuilder.h"
namespace facebook {
namespace memcache {
namespace mcrouter {
namespace detail {
class McrouterManager;
}
class ProxyThread;
/**
* A single mcrouter instance. A mcrouter instance has a single config,
* but might run across multiple threads.
*/
template <class RouterInfo>
class CarbonRouterInstance
: public CarbonRouterInstanceBase,
public std::enable_shared_from_this<CarbonRouterInstance<RouterInfo>> {
public:
/* Creation methods. All mcrouter instances are managed automatically,
so the users don't need to worry about destruction. */
/**
* @return If an instance with the given persistenceId already exists,
* returns a pointer to it. Options are ignored in this case.
* Otherwise spins up a new instance and returns the pointer to it. May
* return nullptr if the McRouterManager singleton is unavailable, perhaps
* due to misconfiguration.
* @param evbs Must be either empty or contain options.num_proxies
* event bases. If empty, mcrouter will spawn its own proxy threads.
* Otherwise, proxies will run on the provided event bases
* (auxiliary threads will still be spawned).
* @throw runtime_error If no valid instance can be constructed from
* the provided options.
*/
static CarbonRouterInstance<RouterInfo>* init(
folly::StringPiece persistenceId,
const McrouterOptions& options,
const std::vector<folly::EventBase*>& evbs =
std::vector<folly::EventBase*>());
/**
* If an instance with the given persistenceId already exists,
* returns a pointer to it. Otherwise returns nullptr.
*/
static CarbonRouterInstance<RouterInfo>* get(
folly::StringPiece persistenceId);
/**
* If an instance with the given persistenceId already exists,
* returns true. Otherwise returns false.
*/
static bool hasInstance(folly::StringPiece persistenceId);
/**
* Intended for short-lived instances with unusual configs
* (i.e. for debugging).
*
* Create a new mcrouter instance.
* @return Pointer to the newly brought up instance or nullptr
* if there was a problem starting it up.
* @throw runtime_error If no valid instance can be constructed from
* the provided options.
*/
static std::shared_ptr<CarbonRouterInstance<RouterInfo>> create(
McrouterOptions input_options,
const std::vector<folly::EventBase*>& evbs = {});
/**
* Destroys ALL active instances for ALL RouterInfos.
*/
static void freeAllMcrouters();
/**
* Create a handle to talk to mcrouter.
*
* @param maximum_outstanding_requests If nonzero, at most this many requests
* will be allowed to be in flight at any single point in time.
* send() will block until the number of outstanding requests
* is less than this limit.
* @throw std::runtime_error If the client cannot be created
* (i.e. attempting to create multiple clients to transient mcrouter).
*/
typename CarbonRouterClient<RouterInfo>::Pointer createClient(
size_t maximum_outstanding_requests,
bool maximum_outstanding_requests_error = false);
/**
* Same as createClient(), but you must use it from the same thread that's
* running the assigned proxy's event base. The sends call into proxy
* callbacks directly, bypassing the queue.
*/
typename CarbonRouterClient<RouterInfo>::Pointer createSameThreadClient(
size_t maximum_outstanding_requests);
/**
* Shutdown all threads started by this instance. It's a blocking call and
* should be called at most once. If it is not called, destructor will block
* until all threads are stopped.
*/
void shutdown() noexcept;
ProxyBase* getProxyBase(size_t index) const override;
/**
* @return nullptr if index is >= opts.num_proxies,
* pointer to the proxy otherwise.
*/
Proxy<RouterInfo>* getProxy(size_t index) const;
const std::vector<Proxy<RouterInfo>*>& getProxies() const;
CarbonRouterInstance(const CarbonRouterInstance&) = delete;
CarbonRouterInstance& operator=(const CarbonRouterInstance&) = delete;
CarbonRouterInstance(CarbonRouterInstance&&) noexcept = delete;
CarbonRouterInstance& operator=(CarbonRouterInstance&&) = delete;
private:
CallbackPool<> onReconfigureSuccess_;
// Lock to get before regenerating config structure
std::mutex configReconfigLock_;
// Corresponding handle
ObservableRuntimeVars::CallbackHandle rxmitHandle_;
/**
* Logs mcrouter stats to disk every opts->stats_logging_interval
* milliseconds
*/
std::unique_ptr<McrouterLogger> mcrouterLogger_;
std::atomic<bool> shutdownStarted_{false};
FileObserverHandle runtimeVarsObserverHandle_;
ConfigApi::CallbackHandle configUpdateHandle_;
/**
* Both these vectors will contain opts.num_proxies elements.
*/
std::vector<Proxy<RouterInfo>*> proxies_;
std::vector<std::unique_ptr<folly::VirtualEventBase>> proxyEvbs_;
/**
* This will contain opts.num_proxies elements in Embedded mode (mcrouter
* owns proxy threads).
* In case of Standalone/sync mode, this vector is empty.
*/
std::vector<std::unique_ptr<ProxyThread>> proxyThreads_;
/**
* The only reason this is a separate function is due to legacy accessor
* needs.
*/
static CarbonRouterInstance<RouterInfo>* createRaw(
McrouterOptions input_options,
const std::vector<folly::EventBase*>& evbs);
explicit CarbonRouterInstance(McrouterOptions input_options);
~CarbonRouterInstance() override;
folly::Expected<folly::Unit, std::string> spinUp(
const std::vector<folly::EventBase*>& evbs);
void spawnAuxiliaryThreads();
void joinAuxiliaryThreads() noexcept;
void shutdownImpl() noexcept;
void subscribeToConfigUpdate();
void spawnStatLoggerThread();
void startObservingRuntimeVarsFile();
folly::Expected<folly::Unit, std::string> configure(
const ProxyConfigBuilder& builder);
/** (re)configure the router. true on success, false on error.
NB file-based configuration is synchronous
but server-based configuration is asynchronous */
bool reconfigure(const ProxyConfigBuilder& builder);
/** Create the ProxyConfigBuilder used to reconfigure.
Returns error reason if constructor fails. **/
folly::Expected<ProxyConfigBuilder, std::string> createConfigBuilder();
void registerOnUpdateCallbackForRxmits();
public:
/* Do not use for new code */
class LegacyPrivateAccessor {
public:
static CarbonRouterInstance<RouterInfo>* createRaw(
const McrouterOptions& opts,
const std::vector<folly::EventBase*>& evbs) {
return CarbonRouterInstance<RouterInfo>::createRaw(opts.clone(), evbs);
}
static void destroy(CarbonRouterInstance<RouterInfo>* mcrouter) {
delete mcrouter;
}
static CallbackPool<>& onReconfigureSuccess(
CarbonRouterInstance<RouterInfo>& mcrouter) {
return mcrouter.onReconfigureSuccess_;
}
};
private:
friend class LegacyPrivateAccessor;
friend class CarbonRouterClient<RouterInfo>;
friend class detail::McrouterManager;
friend class ProxyDestinationMap;
};
/**
* Destroy all active instances.
*/
void freeAllRouters();
} // namespace mcrouter
} // namespace memcache
} // namespace facebook
#include "CarbonRouterInstance-inl.h"