blob: e22a4b8bb2859c55090e45d7ae46e637ddca4de9 [file] [log] [blame]
jsobele02e4242007-05-08 17:51:49 +00001// Copyright (c) 2007- Facebook
2// Distributed under the Thrift Software License
3//
4// See accompanying file LICENSE or visit the Thrift site at:
5// http://developers.facebook.com/thrift/
6
7#include <algorithm>
8#include <iostream>
9
10#include "TSocketPool.h"
11
David Reiss0c90f6f2008-02-06 22:18:40 +000012namespace facebook { namespace thrift { namespace transport {
jsobele02e4242007-05-08 17:51:49 +000013
14using namespace std;
15
David Reiss8f3bce42008-03-18 18:21:52 +000016using boost::shared_ptr;
17
jsobele02e4242007-05-08 17:51:49 +000018/**
David Reiss6d0cccd2008-02-28 21:20:12 +000019 * TSocketPoolServer implementation
20 *
21 * @author Akhil Wable <akhil@facebook.com>
22 */
23TSocketPoolServer::TSocketPoolServer()
24 : host_(""),
25 port_(0),
26 lastFailTime_(0),
27 consecutiveFailures_(0) {}
28
29/**
30 * Constructor for TSocketPool server
31 */
David Reiss8f3bce42008-03-18 18:21:52 +000032TSocketPoolServer::TSocketPoolServer(const string &host, int port)
David Reiss6d0cccd2008-02-28 21:20:12 +000033 : host_(host),
34 port_(port),
35 lastFailTime_(0),
36 consecutiveFailures_(0) {}
37
38/**
jsobele02e4242007-05-08 17:51:49 +000039 * TSocketPool implementation.
40 *
41 * @author Jason Sobel <jsobel@facebook.com>
42 */
43
David Reiss8f3bce42008-03-18 18:21:52 +000044TSocketPool::TSocketPool() : TSocket(),
45 numRetries_(1),
46 retryInterval_(60),
47 maxConsecutiveFailures_(1),
48 randomize_(true),
49 alwaysTryLast_(true) {
50}
51
jsobele02e4242007-05-08 17:51:49 +000052TSocketPool::TSocketPool(const vector<string> &hosts,
53 const vector<int> &ports) : TSocket(),
54 numRetries_(1),
55 retryInterval_(60),
56 maxConsecutiveFailures_(1),
57 randomize_(true),
58 alwaysTryLast_(true)
59{
60 if (hosts.size() != ports.size()) {
boz6ded7752007-06-05 22:41:18 +000061 GlobalOutput("TSocketPool::TSocketPool: hosts.size != ports.size");
jsobele02e4242007-05-08 17:51:49 +000062 throw TTransportException(TTransportException::BAD_ARGS);
63 }
64
65 for (unsigned int i = 0; i < hosts.size(); ++i) {
dweatherfordd1372822007-10-09 22:57:23 +000066 addServer(hosts[i], ports[i]);
jsobele02e4242007-05-08 17:51:49 +000067 }
68}
69
David Reiss8f3bce42008-03-18 18:21:52 +000070TSocketPool::TSocketPool(const vector<pair<string, int> >& servers) : TSocket(),
jsobele02e4242007-05-08 17:51:49 +000071 numRetries_(1),
72 retryInterval_(60),
73 maxConsecutiveFailures_(1),
74 randomize_(true),
75 alwaysTryLast_(true)
76{
David Reiss6d0cccd2008-02-28 21:20:12 +000077 for (unsigned i = 0; i < servers.size(); ++i) {
78 addServer(servers[i].first, servers[i].second);
79 }
jsobele02e4242007-05-08 17:51:49 +000080}
81
David Reiss8f3bce42008-03-18 18:21:52 +000082TSocketPool::TSocketPool(const vector< shared_ptr<TSocketPoolServer> >& servers) : TSocket(),
David Reiss907ad762008-03-02 00:25:58 +000083 servers_(servers),
84 numRetries_(1),
85 retryInterval_(60),
86 maxConsecutiveFailures_(1),
87 randomize_(true),
88 alwaysTryLast_(true)
89{
90}
91
dweatherfordd1372822007-10-09 22:57:23 +000092TSocketPool::TSocketPool(const string& host, int port) : TSocket(),
93 numRetries_(1),
94 retryInterval_(60),
95 maxConsecutiveFailures_(1),
96 randomize_(true),
97 alwaysTryLast_(true)
98{
99 addServer(host, port);
100}
101
jsobele02e4242007-05-08 17:51:49 +0000102TSocketPool::~TSocketPool() {
103 close();
104}
105
dweatherfordd1372822007-10-09 22:57:23 +0000106void TSocketPool::addServer(const string& host, int port) {
David Reiss8f3bce42008-03-18 18:21:52 +0000107 servers_.push_back(shared_ptr<TSocketPoolServer>(new TSocketPoolServer(host, port)));
dweatherfordd1372822007-10-09 22:57:23 +0000108}
109
David Reiss8f3bce42008-03-18 18:21:52 +0000110void TSocketPool::setServers(const vector< shared_ptr<TSocketPoolServer> >& servers) {
111 servers_ = servers;
112}
113
114void TSocketPool::getServers(vector< shared_ptr<TSocketPoolServer> >& servers) {
115 servers = servers_;
David Reiss907ad762008-03-02 00:25:58 +0000116}
117
jsobele02e4242007-05-08 17:51:49 +0000118void TSocketPool::setNumRetries(int numRetries) {
119 numRetries_ = numRetries;
120}
121
122void TSocketPool::setRetryInterval(int retryInterval) {
123 retryInterval_ = retryInterval;
124}
125
126
127void TSocketPool::setMaxConsecutiveFailures(int maxConsecutiveFailures) {
128 maxConsecutiveFailures_ = maxConsecutiveFailures;
129}
130
131void TSocketPool::setRandomize(bool randomize) {
132 randomize_ = randomize;
133}
134
135void TSocketPool::setAlwaysTryLast(bool alwaysTryLast) {
136 alwaysTryLast_ = alwaysTryLast;
137}
138
139/* TODO: without apc we ignore a lot of functionality from the php version */
140void TSocketPool::open() {
141 if (randomize_) {
David Reiss8f3bce42008-03-18 18:21:52 +0000142 random_shuffle(servers_.begin(), servers_.end());
jsobele02e4242007-05-08 17:51:49 +0000143 }
144
David Reiss6d0cccd2008-02-28 21:20:12 +0000145 unsigned int numServers = servers_.size();
146 for (unsigned int i = 0; i < numServers; ++i) {
jsobele02e4242007-05-08 17:51:49 +0000147
David Reiss8f3bce42008-03-18 18:21:52 +0000148 TSocketPoolServer &server = *(servers_[i]);
David Reiss6d0cccd2008-02-28 21:20:12 +0000149 bool retryIntervalPassed = (server.lastFailTime_ == 0);
150 bool isLastServer = alwaysTryLast_ ? (i == (numServers - 1)) : false;
jsobele02e4242007-05-08 17:51:49 +0000151
David Reissf50021a2008-02-29 07:33:47 +0000152 host_ = server.host_;
153 port_ = server.port_;
154
David Reiss6d0cccd2008-02-28 21:20:12 +0000155 if (server.lastFailTime_ > 0) {
156 // The server was marked as down, so check if enough time has elapsed to retry
157 int elapsedTime = time(NULL) - server.lastFailTime_;
158 if (elapsedTime > retryInterval_) {
159 retryIntervalPassed = true;
jsobele02e4242007-05-08 17:51:49 +0000160 }
161 }
David Reiss6d0cccd2008-02-28 21:20:12 +0000162
163 if (retryIntervalPassed || isLastServer) {
164 for (int j = 0; j < numRetries_; ++j) {
165 try {
166 TSocket::open();
167
168 // reset lastFailTime_ is required
169 if (server.lastFailTime_) {
170 server.lastFailTime_ = 0;
171 }
172
173 // success
174 return;
175 } catch (TException e) {
176 // connection failed
177 }
178 }
David Reiss6d0cccd2008-02-28 21:20:12 +0000179
David Reiss8f3bce42008-03-18 18:21:52 +0000180 ++server.consecutiveFailures_;
181 if (server.consecutiveFailures_ > maxConsecutiveFailures_) {
182 // Mark server as down
183 server.consecutiveFailures_ = 0;
184 server.lastFailTime_ = time(NULL);
185 }
David Reiss6d0cccd2008-02-28 21:20:12 +0000186 }
jsobele02e4242007-05-08 17:51:49 +0000187 }
188
boz6ded7752007-06-05 22:41:18 +0000189 GlobalOutput("TSocketPool::open: all connections failed");
jsobele02e4242007-05-08 17:51:49 +0000190 throw TTransportException(TTransportException::NOT_OPEN);
191}
192
193}}} // facebook::thrift::transport