blob: fa468a4121e0c45009a61fd68c86500c6b41cbf3 [file] [log] [blame]
David Reissea2cba82009-03-30 21:35:00 +00001/*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 */
19
Roger Meier49ff8b12012-04-13 09:12:31 +000020#include <thrift/concurrency/ThreadManager.h>
21#include <thrift/concurrency/PlatformThreadFactory.h>
22#include <thrift/concurrency/Monitor.h>
23#include <thrift/concurrency/Util.h>
24#include <thrift/concurrency/Mutex.h>
25#include <thrift/protocol/TBinaryProtocol.h>
26#include <thrift/server/TSimpleServer.h>
27#include <thrift/server/TThreadPoolServer.h>
28#include <thrift/server/TThreadedServer.h>
29#include <thrift/transport/TServerSocket.h>
30#include <thrift/transport/TSocket.h>
31#include <thrift/transport/TTransportUtils.h>
32#include <thrift/transport/TFileTransport.h>
Roger Meier33eaa0f2012-04-13 09:13:13 +000033#include <thrift/TLogging.h>
Aditya Agarwal3950f472006-10-11 02:50:15 +000034
35#include "Service.h"
Marc Slemko3ea00332006-08-17 01:11:13 +000036
37#include <iostream>
38#include <set>
39#include <stdexcept>
40#include <sstream>
Mark Sleeb9ff32a2006-11-16 01:00:24 +000041#include <map>
Jake Farrell5d02b802014-01-07 21:42:01 -050042#if _WIN32
Konrad Grochowski16a23a62014-11-13 15:33:38 +010043#include <thrift/windows/TWinsockSingleton.h>
Jake Farrell5d02b802014-01-07 21:42:01 -050044#endif
Mark Sleeb9ff32a2006-11-16 01:00:24 +000045
Marc Slemko3ea00332006-08-17 01:11:13 +000046using namespace std;
47
T Jake Lucianib5e62212009-01-31 22:36:20 +000048using namespace apache::thrift;
49using namespace apache::thrift::protocol;
50using namespace apache::thrift::transport;
51using namespace apache::thrift::server;
52using namespace apache::thrift::concurrency;
Marc Slemko3ea00332006-08-17 01:11:13 +000053
54using namespace test::stress;
55
Mark Sleeb9ff32a2006-11-16 01:00:24 +000056struct eqstr {
Konrad Grochowski16a23a62014-11-13 15:33:38 +010057 bool operator()(const char* s1, const char* s2) const { return strcmp(s1, s2) == 0; }
Mark Sleeb9ff32a2006-11-16 01:00:24 +000058};
59
60struct ltstr {
Konrad Grochowski16a23a62014-11-13 15:33:38 +010061 bool operator()(const char* s1, const char* s2) const { return strcmp(s1, s2) < 0; }
Mark Sleeb9ff32a2006-11-16 01:00:24 +000062};
63
David Reiss0c90f6f2008-02-06 22:18:40 +000064// typedef hash_map<const char*, int, hash<const char*>, eqstr> count_map;
65typedef map<const char*, int, ltstr> count_map;
Mark Sleeb9ff32a2006-11-16 01:00:24 +000066
Aditya Agarwal3950f472006-10-11 02:50:15 +000067class Server : public ServiceIf {
Konrad Grochowski16a23a62014-11-13 15:33:38 +010068public:
Mark Sleeb9ff32a2006-11-16 01:00:24 +000069 Server() {}
70
71 void count(const char* method) {
David Reiss46379902008-02-04 19:23:57 +000072 Guard m(lock_);
Mark Sleeb9ff32a2006-11-16 01:00:24 +000073 int ct = counts_[method];
74 counts_[method] = ++ct;
75 }
76
77 void echoVoid() {
78 count("echoVoid");
79 return;
80 }
81
82 count_map getCount() {
David Reiss46379902008-02-04 19:23:57 +000083 Guard m(lock_);
Mark Sleeb9ff32a2006-11-16 01:00:24 +000084 return counts_;
85 }
86
Konrad Grochowski16a23a62014-11-13 15:33:38 +010087 int8_t echoByte(const int8_t arg) { return arg; }
88 int32_t echoI32(const int32_t arg) { return arg; }
89 int64_t echoI64(const int64_t arg) { return arg; }
90 void echoString(string& out, const string& arg) {
Aditya Agarwale9ef8d72006-12-08 23:52:57 +000091 if (arg != "hello") {
Roger Meiera8cef6e2011-07-17 18:55:59 +000092 T_ERROR_ABORT("WRONG STRING (%s)!!!!", arg.c_str());
Aditya Agarwale9ef8d72006-12-08 23:52:57 +000093 }
Mark Slee739dbe52007-02-01 22:55:30 +000094 out = arg;
Aditya Agarwale9ef8d72006-12-08 23:52:57 +000095 }
Konrad Grochowski16a23a62014-11-13 15:33:38 +010096 void echoList(vector<int8_t>& out, const vector<int8_t>& arg) { out = arg; }
97 void echoSet(set<int8_t>& out, const set<int8_t>& arg) { out = arg; }
98 void echoMap(map<int8_t, int8_t>& out, const map<int8_t, int8_t>& arg) { out = arg; }
Mark Sleeb9ff32a2006-11-16 01:00:24 +000099
100private:
101 count_map counts_;
102 Mutex lock_;
Marc Slemko3ea00332006-08-17 01:11:13 +0000103};
104
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100105class ClientThread : public Runnable {
Marc Slemko3ea00332006-08-17 01:11:13 +0000106public:
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100107 ClientThread(boost::shared_ptr<TTransport> transport,
108 boost::shared_ptr<ServiceClient> client,
109 Monitor& monitor,
110 size_t& workerCount,
111 size_t loopCount,
112 TType loopType)
113 : _transport(transport),
114 _client(client),
115 _monitor(monitor),
116 _workerCount(workerCount),
117 _loopCount(loopCount),
118 _loopType(loopType) {}
Marc Slemko3ea00332006-08-17 01:11:13 +0000119
120 void run() {
121
David Reiss0c90f6f2008-02-06 22:18:40 +0000122 // Wait for all worker threads to start
Marc Slemko3ea00332006-08-17 01:11:13 +0000123
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100124 {
125 Synchronized s(_monitor);
126 while (_workerCount == 0) {
David Reiss0c90f6f2008-02-06 22:18:40 +0000127 _monitor.wait();
128 }
Marc Slemko3ea00332006-08-17 01:11:13 +0000129 }
130
131 _startTime = Util::currentTime();
132
133 _transport->open();
134
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100135 switch (_loopType) {
136 case T_VOID:
137 loopEchoVoid();
138 break;
139 case T_BYTE:
140 loopEchoByte();
141 break;
142 case T_I32:
143 loopEchoI32();
144 break;
145 case T_I64:
146 loopEchoI64();
147 break;
148 case T_STRING:
149 loopEchoString();
150 break;
151 default:
152 cerr << "Unexpected loop type" << _loopType << endl;
153 break;
Marc Slemko3ea00332006-08-17 01:11:13 +0000154 }
David Reiss0c90f6f2008-02-06 22:18:40 +0000155
Marc Slemko3ea00332006-08-17 01:11:13 +0000156 _endTime = Util::currentTime();
157
158 _transport->close();
David Reiss0c90f6f2008-02-06 22:18:40 +0000159
Marc Slemko3ea00332006-08-17 01:11:13 +0000160 _done = true;
David Reiss0c90f6f2008-02-06 22:18:40 +0000161
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100162 {
163 Synchronized s(_monitor);
Marc Slemko3ea00332006-08-17 01:11:13 +0000164
165 _workerCount--;
David Reiss0c90f6f2008-02-06 22:18:40 +0000166
Mark Slee3e5d2d72007-06-15 01:45:56 +0000167 if (_workerCount == 0) {
David Reiss0c90f6f2008-02-06 22:18:40 +0000168
169 _monitor.notify();
Marc Slemko3ea00332006-08-17 01:11:13 +0000170 }
171 }
172 }
Marc Slemkod97eb612006-08-24 23:37:36 +0000173
174 void loopEchoVoid() {
Mark Slee3e5d2d72007-06-15 01:45:56 +0000175 for (size_t ix = 0; ix < _loopCount; ix++) {
Marc Slemkod97eb612006-08-24 23:37:36 +0000176 _client->echoVoid();
177 }
178 }
179
180 void loopEchoByte() {
Mark Slee3e5d2d72007-06-15 01:45:56 +0000181 for (size_t ix = 0; ix < _loopCount; ix++) {
Aditya Agarwal3950f472006-10-11 02:50:15 +0000182 int8_t arg = 1;
183 int8_t result;
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100184 result = _client->echoByte(arg);
Jake Farrell5d02b802014-01-07 21:42:01 -0500185 (void)result;
Marc Slemkod97eb612006-08-24 23:37:36 +0000186 assert(result == arg);
187 }
188 }
David Reiss0c90f6f2008-02-06 22:18:40 +0000189
Marc Slemkod97eb612006-08-24 23:37:36 +0000190 void loopEchoI32() {
Mark Slee3e5d2d72007-06-15 01:45:56 +0000191 for (size_t ix = 0; ix < _loopCount; ix++) {
Aditya Agarwal3950f472006-10-11 02:50:15 +0000192 int32_t arg = 1;
193 int32_t result;
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100194 result = _client->echoI32(arg);
Jake Farrell5d02b802014-01-07 21:42:01 -0500195 (void)result;
Marc Slemkod97eb612006-08-24 23:37:36 +0000196 assert(result == arg);
197 }
198 }
199
200 void loopEchoI64() {
Mark Slee3e5d2d72007-06-15 01:45:56 +0000201 for (size_t ix = 0; ix < _loopCount; ix++) {
Aditya Agarwal3950f472006-10-11 02:50:15 +0000202 int64_t arg = 1;
203 int64_t result;
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100204 result = _client->echoI64(arg);
Jake Farrell5d02b802014-01-07 21:42:01 -0500205 (void)result;
Marc Slemkod97eb612006-08-24 23:37:36 +0000206 assert(result == arg);
207 }
208 }
David Reiss0c90f6f2008-02-06 22:18:40 +0000209
Marc Slemkod97eb612006-08-24 23:37:36 +0000210 void loopEchoString() {
Mark Slee3e5d2d72007-06-15 01:45:56 +0000211 for (size_t ix = 0; ix < _loopCount; ix++) {
Marc Slemkod97eb612006-08-24 23:37:36 +0000212 string arg = "hello";
213 string result;
Mark Slee739dbe52007-02-01 22:55:30 +0000214 _client->echoString(result, arg);
Marc Slemkod97eb612006-08-24 23:37:36 +0000215 assert(result == arg);
216 }
217 }
David Reiss0c90f6f2008-02-06 22:18:40 +0000218
Roger Meier611f90c2011-12-11 22:08:51 +0000219 boost::shared_ptr<TTransport> _transport;
220 boost::shared_ptr<ServiceClient> _client;
Marc Slemko3ea00332006-08-17 01:11:13 +0000221 Monitor& _monitor;
222 size_t& _workerCount;
223 size_t _loopCount;
Marc Slemkod97eb612006-08-24 23:37:36 +0000224 TType _loopType;
Roger Meier5f9614c2010-11-21 16:59:05 +0000225 int64_t _startTime;
226 int64_t _endTime;
Marc Slemko3ea00332006-08-17 01:11:13 +0000227 bool _done;
228 Monitor _sleep;
229};
Aditya Agarwale9ef8d72006-12-08 23:52:57 +0000230
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100231class TStartObserver : public apache::thrift::server::TServerEventHandler {
Jake Farrell5d02b802014-01-07 21:42:01 -0500232public:
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100233 TStartObserver() : awake_(false) {}
234 virtual void preServe() {
235 apache::thrift::concurrency::Synchronized s(m_);
236 awake_ = true;
237 m_.notifyAll();
238 }
239 void waitForService() {
240 apache::thrift::concurrency::Synchronized s(m_);
241 while (!awake_)
242 m_.waitForever();
243 }
244
245private:
246 apache::thrift::concurrency::Monitor m_;
247 bool awake_;
Jake Farrell5d02b802014-01-07 21:42:01 -0500248};
Aditya Agarwale9ef8d72006-12-08 23:52:57 +0000249
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100250int main(int argc, char** argv) {
Jake Farrell5d02b802014-01-07 21:42:01 -0500251#if _WIN32
252 transport::TWinsockSingleton::create();
253#endif
Marc Slemko3ea00332006-08-17 01:11:13 +0000254
Aditya Agarwale9ef8d72006-12-08 23:52:57 +0000255 int port = 9091;
Marc Slemko3ea00332006-08-17 01:11:13 +0000256 string serverType = "thread-pool";
257 string protocolType = "binary";
258 size_t workerCount = 4;
Aditya Agarwale9ef8d72006-12-08 23:52:57 +0000259 size_t clientCount = 20;
260 size_t loopCount = 50000;
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100261 TType loopType = T_VOID;
Marc Slemkod97eb612006-08-24 23:37:36 +0000262 string callName = "echoVoid";
Marc Slemkob09f5882006-08-23 22:03:34 +0000263 bool runServer = true;
Aditya Agarwal3950f472006-10-11 02:50:15 +0000264 bool logRequests = false;
265 string requestLogPath = "./requestlog.tlog";
Aditya Agarwale9ef8d72006-12-08 23:52:57 +0000266 bool replayRequests = false;
Marc Slemko3ea00332006-08-17 01:11:13 +0000267
Marc Slemkob09f5882006-08-23 22:03:34 +0000268 ostringstream usage;
Marc Slemko3ea00332006-08-17 01:11:13 +0000269
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100270 usage << argv[0] << " [--port=<port number>] [--server] [--server-type=<server-type>] "
271 "[--protocol-type=<protocol-type>] [--workers=<worker-count>] "
272 "[--clients=<client-count>] [--loop=<loop-count>]" << endl
273 << "\tclients Number of client threads to create - 0 implies no clients, i.e. "
274 "server only. Default is " << clientCount << endl
275 << "\thelp Prints this help text." << endl
276 << "\tcall Service method to call. Default is " << callName << endl
277 << "\tloop The number of remote thrift calls each client makes. Default is "
278 << loopCount << endl << "\tport The port the server and clients should bind to "
279 "for thrift network connections. Default is " << port << endl
280 << "\tserver Run the Thrift server in this process. Default is " << runServer
281 << endl << "\tserver-type Type of server, \"simple\" or \"thread-pool\". Default is "
282 << serverType << endl
283 << "\tprotocol-type Type of protocol, \"binary\", \"ascii\", or \"xml\". Default is "
284 << protocolType << endl
285 << "\tlog-request Log all request to ./requestlog.tlog. Default is " << logRequests
286 << endl << "\treplay-request Replay requests from log file (./requestlog.tlog) Default is "
287 << replayRequests << endl << "\tworkers Number of thread pools workers. Only valid "
288 "for thread-pool server type. Default is " << workerCount
289 << endl;
David Reiss0c90f6f2008-02-06 22:18:40 +0000290
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100291 map<string, string> args;
David Reiss0c90f6f2008-02-06 22:18:40 +0000292
Mark Slee3e5d2d72007-06-15 01:45:56 +0000293 for (int ix = 1; ix < argc; ix++) {
Marc Slemko3ea00332006-08-17 01:11:13 +0000294
295 string arg(argv[ix]);
296
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100297 if (arg.compare(0, 2, "--") == 0) {
Marc Slemko3ea00332006-08-17 01:11:13 +0000298
299 size_t end = arg.find_first_of("=", 2);
300
Marc Slemko056f9ba2006-08-17 02:59:05 +0000301 string key = string(arg, 2, end - 2);
302
Mark Slee3e5d2d72007-06-15 01:45:56 +0000303 if (end != string::npos) {
David Reiss0c90f6f2008-02-06 22:18:40 +0000304 args[key] = string(arg, end + 1);
Marc Slemko3ea00332006-08-17 01:11:13 +0000305 } else {
David Reiss0c90f6f2008-02-06 22:18:40 +0000306 args[key] = "true";
Marc Slemko3ea00332006-08-17 01:11:13 +0000307 }
Marc Slemko3ea00332006-08-17 01:11:13 +0000308 } else {
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100309 throw invalid_argument("Unexcepted command line token: " + arg);
Marc Slemko3ea00332006-08-17 01:11:13 +0000310 }
311 }
312
313 try {
314
Mark Slee3e5d2d72007-06-15 01:45:56 +0000315 if (!args["clients"].empty()) {
Marc Slemkob09f5882006-08-23 22:03:34 +0000316 clientCount = atoi(args["clients"].c_str());
317 }
318
Mark Slee3e5d2d72007-06-15 01:45:56 +0000319 if (!args["help"].empty()) {
Marc Slemkob09f5882006-08-23 22:03:34 +0000320 cerr << usage.str();
321 return 0;
322 }
323
Mark Slee3e5d2d72007-06-15 01:45:56 +0000324 if (!args["loop"].empty()) {
Marc Slemkob09f5882006-08-23 22:03:34 +0000325 loopCount = atoi(args["loop"].c_str());
326 }
327
Mark Slee3e5d2d72007-06-15 01:45:56 +0000328 if (!args["call"].empty()) {
Marc Slemkod97eb612006-08-24 23:37:36 +0000329 callName = args["call"];
330 }
331
Mark Slee3e5d2d72007-06-15 01:45:56 +0000332 if (!args["port"].empty()) {
Marc Slemko3ea00332006-08-17 01:11:13 +0000333 port = atoi(args["port"].c_str());
334 }
335
Mark Slee3e5d2d72007-06-15 01:45:56 +0000336 if (!args["server"].empty()) {
Marc Slemkob09f5882006-08-23 22:03:34 +0000337 runServer = args["server"] == "true";
338 }
339
Mark Slee3e5d2d72007-06-15 01:45:56 +0000340 if (!args["log-request"].empty()) {
Aditya Agarwal3950f472006-10-11 02:50:15 +0000341 logRequests = args["log-request"] == "true";
342 }
343
Mark Slee3e5d2d72007-06-15 01:45:56 +0000344 if (!args["replay-request"].empty()) {
Aditya Agarwale9ef8d72006-12-08 23:52:57 +0000345 replayRequests = args["replay-request"] == "true";
346 }
347
Mark Slee3e5d2d72007-06-15 01:45:56 +0000348 if (!args["server-type"].empty()) {
Marc Slemko3ea00332006-08-17 01:11:13 +0000349 serverType = args["server-type"];
David Reiss0c90f6f2008-02-06 22:18:40 +0000350
Mark Slee3e5d2d72007-06-15 01:45:56 +0000351 if (serverType == "simple") {
Marc Slemko3ea00332006-08-17 01:11:13 +0000352
Mark Slee3e5d2d72007-06-15 01:45:56 +0000353 } else if (serverType == "thread-pool") {
Marc Slemko3ea00332006-08-17 01:11:13 +0000354
Mark Slee3e5d2d72007-06-15 01:45:56 +0000355 } else if (serverType == "threaded") {
Mark Slee739dbe52007-02-01 22:55:30 +0000356
Marc Slemko3ea00332006-08-17 01:11:13 +0000357 } else {
358
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100359 throw invalid_argument("Unknown server type " + serverType);
Marc Slemko3ea00332006-08-17 01:11:13 +0000360 }
361 }
362
Mark Slee3e5d2d72007-06-15 01:45:56 +0000363 if (!args["workers"].empty()) {
Marc Slemko3ea00332006-08-17 01:11:13 +0000364 workerCount = atoi(args["workers"].c_str());
365 }
366
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100367 } catch (std::exception& e) {
Marc Slemko3ea00332006-08-17 01:11:13 +0000368 cerr << e.what() << endl;
Jake Farrell5d02b802014-01-07 21:42:01 -0500369 cerr << usage.str();
Marc Slemko3ea00332006-08-17 01:11:13 +0000370 }
371
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100372 boost::shared_ptr<PlatformThreadFactory> threadFactory
373 = boost::shared_ptr<PlatformThreadFactory>(new PlatformThreadFactory());
Marc Slemko3ea00332006-08-17 01:11:13 +0000374
Mark Sleeb9ff32a2006-11-16 01:00:24 +0000375 // Dispatcher
Roger Meier611f90c2011-12-11 22:08:51 +0000376 boost::shared_ptr<Server> serviceHandler(new Server());
Marc Slemko3ea00332006-08-17 01:11:13 +0000377
Aditya Agarwale9ef8d72006-12-08 23:52:57 +0000378 if (replayRequests) {
Roger Meier611f90c2011-12-11 22:08:51 +0000379 boost::shared_ptr<Server> serviceHandler(new Server());
380 boost::shared_ptr<ServiceProcessor> serviceProcessor(new ServiceProcessor(serviceHandler));
David Reiss0c90f6f2008-02-06 22:18:40 +0000381
Aditya Agarwale9ef8d72006-12-08 23:52:57 +0000382 // Transports
Roger Meier611f90c2011-12-11 22:08:51 +0000383 boost::shared_ptr<TFileTransport> fileTransport(new TFileTransport(requestLogPath));
Aditya Agarwale9ef8d72006-12-08 23:52:57 +0000384 fileTransport->setChunkSize(2 * 1024 * 1024);
385 fileTransport->setMaxEventSize(1024 * 16);
386 fileTransport->seekToEnd();
387
388 // Protocol Factory
Roger Meier611f90c2011-12-11 22:08:51 +0000389 boost::shared_ptr<TProtocolFactory> protocolFactory(new TBinaryProtocolFactory());
Aditya Agarwale9ef8d72006-12-08 23:52:57 +0000390
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100391 TFileProcessor fileProcessor(serviceProcessor, protocolFactory, fileTransport);
Aditya Agarwale9ef8d72006-12-08 23:52:57 +0000392
David Reiss0c90f6f2008-02-06 22:18:40 +0000393 fileProcessor.process(0, true);
Aditya Agarwale9ef8d72006-12-08 23:52:57 +0000394 exit(0);
395 }
396
Mark Slee3e5d2d72007-06-15 01:45:56 +0000397 if (runServer) {
Marc Slemko3ea00332006-08-17 01:11:13 +0000398
Roger Meier611f90c2011-12-11 22:08:51 +0000399 boost::shared_ptr<ServiceProcessor> serviceProcessor(new ServiceProcessor(serviceHandler));
Marc Slemko3ea00332006-08-17 01:11:13 +0000400
Marc Slemkob09f5882006-08-23 22:03:34 +0000401 // Transport
Roger Meier611f90c2011-12-11 22:08:51 +0000402 boost::shared_ptr<TServerSocket> serverSocket(new TServerSocket(port));
Marc Slemko3ea00332006-08-17 01:11:13 +0000403
Aditya Agarwal3950f472006-10-11 02:50:15 +0000404 // Transport Factory
Roger Meier611f90c2011-12-11 22:08:51 +0000405 boost::shared_ptr<TTransportFactory> transportFactory(new TBufferedTransportFactory());
Aditya Agarwal3950f472006-10-11 02:50:15 +0000406
Mark Sleed7173472006-10-25 19:52:10 +0000407 // Protocol Factory
Roger Meier611f90c2011-12-11 22:08:51 +0000408 boost::shared_ptr<TProtocolFactory> protocolFactory(new TBinaryProtocolFactory());
Aditya Agarwal3950f472006-10-11 02:50:15 +0000409
410 if (logRequests) {
411 // initialize the log file
Roger Meier611f90c2011-12-11 22:08:51 +0000412 boost::shared_ptr<TFileTransport> fileTransport(new TFileTransport(requestLogPath));
Aditya Agarwale9ef8d72006-12-08 23:52:57 +0000413 fileTransport->setChunkSize(2 * 1024 * 1024);
414 fileTransport->setMaxEventSize(1024 * 16);
David Reiss0c90f6f2008-02-06 22:18:40 +0000415
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100416 transportFactory
417 = boost::shared_ptr<TTransportFactory>(new TPipedTransportFactory(fileTransport));
Aditya Agarwal3950f472006-10-11 02:50:15 +0000418 }
Marc Slemko3ea00332006-08-17 01:11:13 +0000419
Jake Farrell5d02b802014-01-07 21:42:01 -0500420 boost::shared_ptr<TServer> server;
Marc Slemko3ea00332006-08-17 01:11:13 +0000421
Mark Slee3e5d2d72007-06-15 01:45:56 +0000422 if (serverType == "simple") {
David Reiss0c90f6f2008-02-06 22:18:40 +0000423
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100424 server.reset(
425 new TSimpleServer(serviceProcessor, serverSocket, transportFactory, protocolFactory));
David Reiss0c90f6f2008-02-06 22:18:40 +0000426
Mark Slee739dbe52007-02-01 22:55:30 +0000427 } else if (serverType == "threaded") {
428
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100429 server.reset(
430 new TThreadedServer(serviceProcessor, serverSocket, transportFactory, protocolFactory));
David Reiss0c90f6f2008-02-06 22:18:40 +0000431
Mark Slee3e5d2d72007-06-15 01:45:56 +0000432 } else if (serverType == "thread-pool") {
Marc Slemkob09f5882006-08-23 22:03:34 +0000433
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100434 boost::shared_ptr<ThreadManager> threadManager
435 = ThreadManager::newSimpleThreadManager(workerCount);
Marc Slemkob09f5882006-08-23 22:03:34 +0000436
437 threadManager->threadFactory(threadFactory);
David Reiss0c90f6f2008-02-06 22:18:40 +0000438 threadManager->start();
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100439 server.reset(new TThreadPoolServer(serviceProcessor,
440 serverSocket,
441 transportFactory,
442 protocolFactory,
443 threadManager));
Marc Slemkob09f5882006-08-23 22:03:34 +0000444 }
445
Jake Farrell5d02b802014-01-07 21:42:01 -0500446 boost::shared_ptr<TStartObserver> observer(new TStartObserver);
447 server->setServerEventHandler(observer);
448 boost::shared_ptr<Thread> serverThread = threadFactory->newThread(server);
449
Marc Slemkob09f5882006-08-23 22:03:34 +0000450 cerr << "Starting the server on port " << port << endl;
451
452 serverThread->start();
Jake Farrell5d02b802014-01-07 21:42:01 -0500453 observer->waitForService();
David Reiss0c90f6f2008-02-06 22:18:40 +0000454
Marc Slemkob09f5882006-08-23 22:03:34 +0000455 // If we aren't running clients, just wait forever for external clients
Mark Sleed7173472006-10-25 19:52:10 +0000456 if (clientCount == 0) {
Marc Slemkob09f5882006-08-23 22:03:34 +0000457 serverThread->join();
458 }
Marc Slemko3ea00332006-08-17 01:11:13 +0000459 }
460
Mark Sleed7173472006-10-25 19:52:10 +0000461 if (clientCount > 0) {
Marc Slemko3ea00332006-08-17 01:11:13 +0000462
Marc Slemkob09f5882006-08-23 22:03:34 +0000463 Monitor monitor;
Marc Slemko3ea00332006-08-17 01:11:13 +0000464
Marc Slemkob09f5882006-08-23 22:03:34 +0000465 size_t threadCount = 0;
Marc Slemko3ea00332006-08-17 01:11:13 +0000466
Roger Meier611f90c2011-12-11 22:08:51 +0000467 set<boost::shared_ptr<Thread> > clientThreads;
Marc Slemko3ea00332006-08-17 01:11:13 +0000468
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100469 if (callName == "echoVoid") {
470 loopType = T_VOID;
471 } else if (callName == "echoByte") {
472 loopType = T_BYTE;
473 } else if (callName == "echoI32") {
474 loopType = T_I32;
475 } else if (callName == "echoI64") {
476 loopType = T_I64;
477 } else if (callName == "echoString") {
478 loopType = T_STRING;
479 } else {
480 throw invalid_argument("Unknown service call " + callName);
481 }
Marc Slemkod97eb612006-08-24 23:37:36 +0000482
Mark Slee3e5d2d72007-06-15 01:45:56 +0000483 for (size_t ix = 0; ix < clientCount; ix++) {
David Reiss0c90f6f2008-02-06 22:18:40 +0000484
Roger Meier611f90c2011-12-11 22:08:51 +0000485 boost::shared_ptr<TSocket> socket(new TSocket("127.0.0.1", port));
486 boost::shared_ptr<TBufferedTransport> bufferedSocket(new TBufferedTransport(socket, 2048));
487 boost::shared_ptr<TProtocol> protocol(new TBinaryProtocol(bufferedSocket));
488 boost::shared_ptr<ServiceClient> serviceClient(new ServiceClient(protocol));
David Reiss0c90f6f2008-02-06 22:18:40 +0000489
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100490 clientThreads.insert(threadFactory->newThread(boost::shared_ptr<ClientThread>(
491 new ClientThread(socket, serviceClient, monitor, threadCount, loopCount, loopType))));
Marc Slemkob09f5882006-08-23 22:03:34 +0000492 }
David Reiss0c90f6f2008-02-06 22:18:40 +0000493
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100494 for (std::set<boost::shared_ptr<Thread> >::const_iterator thread = clientThreads.begin();
495 thread != clientThreads.end();
496 thread++) {
Marc Slemkob09f5882006-08-23 22:03:34 +0000497 (*thread)->start();
498 }
Marc Slemko3ea00332006-08-17 01:11:13 +0000499
Roger Meier5f9614c2010-11-21 16:59:05 +0000500 int64_t time00;
501 int64_t time01;
David Reiss0c90f6f2008-02-06 22:18:40 +0000502
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100503 {
504 Synchronized s(monitor);
Marc Slemkob09f5882006-08-23 22:03:34 +0000505 threadCount = clientCount;
David Reiss0c90f6f2008-02-06 22:18:40 +0000506
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100507 cerr << "Launch " << clientCount << " client threads" << endl;
David Reiss0c90f6f2008-02-06 22:18:40 +0000508
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100509 time00 = Util::currentTime();
David Reiss0c90f6f2008-02-06 22:18:40 +0000510
Marc Slemkob09f5882006-08-23 22:03:34 +0000511 monitor.notifyAll();
David Reiss0c90f6f2008-02-06 22:18:40 +0000512
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100513 while (threadCount > 0) {
David Reiss0c90f6f2008-02-06 22:18:40 +0000514 monitor.wait();
Marc Slemkob09f5882006-08-23 22:03:34 +0000515 }
David Reiss0c90f6f2008-02-06 22:18:40 +0000516
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100517 time01 = Util::currentTime();
Marc Slemko3ea00332006-08-17 01:11:13 +0000518 }
David Reiss0c90f6f2008-02-06 22:18:40 +0000519
Roger Meier5f9614c2010-11-21 16:59:05 +0000520 int64_t firstTime = 9223372036854775807LL;
521 int64_t lastTime = 0;
Marc Slemko3ea00332006-08-17 01:11:13 +0000522
Marc Slemkob09f5882006-08-23 22:03:34 +0000523 double averageTime = 0;
Roger Meier5f9614c2010-11-21 16:59:05 +0000524 int64_t minTime = 9223372036854775807LL;
525 int64_t maxTime = 0;
David Reiss0c90f6f2008-02-06 22:18:40 +0000526
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100527 for (set<boost::shared_ptr<Thread> >::iterator ix = clientThreads.begin();
528 ix != clientThreads.end();
529 ix++) {
David Reiss0c90f6f2008-02-06 22:18:40 +0000530
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100531 boost::shared_ptr<ClientThread> client
532 = boost::dynamic_pointer_cast<ClientThread>((*ix)->runnable());
David Reiss0c90f6f2008-02-06 22:18:40 +0000533
Roger Meier5f9614c2010-11-21 16:59:05 +0000534 int64_t delta = client->_endTime - client->_startTime;
David Reiss0c90f6f2008-02-06 22:18:40 +0000535
Marc Slemkob09f5882006-08-23 22:03:34 +0000536 assert(delta > 0);
Marc Slemko056f9ba2006-08-17 02:59:05 +0000537
Mark Slee3e5d2d72007-06-15 01:45:56 +0000538 if (client->_startTime < firstTime) {
David Reiss0c90f6f2008-02-06 22:18:40 +0000539 firstTime = client->_startTime;
Marc Slemkob09f5882006-08-23 22:03:34 +0000540 }
David Reiss0c90f6f2008-02-06 22:18:40 +0000541
Mark Slee3e5d2d72007-06-15 01:45:56 +0000542 if (client->_endTime > lastTime) {
David Reiss0c90f6f2008-02-06 22:18:40 +0000543 lastTime = client->_endTime;
Marc Slemkob09f5882006-08-23 22:03:34 +0000544 }
David Reiss0c90f6f2008-02-06 22:18:40 +0000545
Mark Slee3e5d2d72007-06-15 01:45:56 +0000546 if (delta < minTime) {
David Reiss0c90f6f2008-02-06 22:18:40 +0000547 minTime = delta;
Marc Slemkob09f5882006-08-23 22:03:34 +0000548 }
David Reiss0c90f6f2008-02-06 22:18:40 +0000549
Mark Slee3e5d2d72007-06-15 01:45:56 +0000550 if (delta > maxTime) {
David Reiss0c90f6f2008-02-06 22:18:40 +0000551 maxTime = delta;
Marc Slemkob09f5882006-08-23 22:03:34 +0000552 }
David Reiss0c90f6f2008-02-06 22:18:40 +0000553
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100554 averageTime += delta;
Marc Slemkob09f5882006-08-23 22:03:34 +0000555 }
David Reiss0c90f6f2008-02-06 22:18:40 +0000556
Marc Slemkob09f5882006-08-23 22:03:34 +0000557 averageTime /= clientCount;
David Reiss0c90f6f2008-02-06 22:18:40 +0000558
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100559 cout << "workers :" << workerCount << ", client : " << clientCount << ", loops : " << loopCount
560 << ", rate : " << (clientCount * loopCount * 1000) / ((double)(time01 - time00)) << endl;
David Reiss0c90f6f2008-02-06 22:18:40 +0000561
Mark Sleeb9ff32a2006-11-16 01:00:24 +0000562 count_map count = serviceHandler->getCount();
563 count_map::iterator iter;
564 for (iter = count.begin(); iter != count.end(); ++iter) {
565 printf("%s => %d\n", iter->first, iter->second);
566 }
Marc Slemkob09f5882006-08-23 22:03:34 +0000567 cerr << "done." << endl;
Marc Slemko056f9ba2006-08-17 02:59:05 +0000568 }
Marc Slemko056f9ba2006-08-17 02:59:05 +0000569
Marc Slemko3ea00332006-08-17 01:11:13 +0000570 return 0;
571}