blob: 9371bce78095e05835ac6ef218e0ebe602799988 [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#include <iostream>
37#include <set>
38#include <stdexcept>
39#include <sstream>
Mark Sleeb9ff32a2006-11-16 01:00:24 +000040#include <map>
Jake Farrell5d02b802014-01-07 21:42:01 -050041#if _WIN32
Konrad Grochowski16a23a62014-11-13 15:33:38 +010042#include <thrift/windows/TWinsockSingleton.h>
Jake Farrell5d02b802014-01-07 21:42:01 -050043#endif
Mark Sleeb9ff32a2006-11-16 01:00:24 +000044
Marc Slemko3ea00332006-08-17 01:11:13 +000045using namespace std;
46
T Jake Lucianib5e62212009-01-31 22:36:20 +000047using namespace apache::thrift;
48using namespace apache::thrift::protocol;
49using namespace apache::thrift::transport;
50using namespace apache::thrift::server;
51using namespace apache::thrift::concurrency;
Marc Slemko3ea00332006-08-17 01:11:13 +000052
53using namespace test::stress;
54
Mark Sleeb9ff32a2006-11-16 01:00:24 +000055struct eqstr {
Konrad Grochowski16a23a62014-11-13 15:33:38 +010056 bool operator()(const char* s1, const char* s2) const { return strcmp(s1, s2) == 0; }
Mark Sleeb9ff32a2006-11-16 01:00:24 +000057};
58
59struct ltstr {
Konrad Grochowski16a23a62014-11-13 15:33:38 +010060 bool operator()(const char* s1, const char* s2) const { return strcmp(s1, s2) < 0; }
Mark Sleeb9ff32a2006-11-16 01:00:24 +000061};
62
David Reiss0c90f6f2008-02-06 22:18:40 +000063// typedef hash_map<const char*, int, hash<const char*>, eqstr> count_map;
64typedef map<const char*, int, ltstr> count_map;
Mark Sleeb9ff32a2006-11-16 01:00:24 +000065
Aditya Agarwal3950f472006-10-11 02:50:15 +000066class Server : public ServiceIf {
Konrad Grochowski16a23a62014-11-13 15:33:38 +010067public:
Mark Sleeb9ff32a2006-11-16 01:00:24 +000068 Server() {}
69
70 void count(const char* method) {
David Reiss46379902008-02-04 19:23:57 +000071 Guard m(lock_);
Mark Sleeb9ff32a2006-11-16 01:00:24 +000072 int ct = counts_[method];
73 counts_[method] = ++ct;
74 }
75
76 void echoVoid() {
77 count("echoVoid");
78 return;
79 }
80
81 count_map getCount() {
David Reiss46379902008-02-04 19:23:57 +000082 Guard m(lock_);
Mark Sleeb9ff32a2006-11-16 01:00:24 +000083 return counts_;
84 }
85
Konrad Grochowski16a23a62014-11-13 15:33:38 +010086 int8_t echoByte(const int8_t arg) { return arg; }
87 int32_t echoI32(const int32_t arg) { return arg; }
88 int64_t echoI64(const int64_t arg) { return arg; }
89 void echoString(string& out, const string& arg) {
Aditya Agarwale9ef8d72006-12-08 23:52:57 +000090 if (arg != "hello") {
Roger Meiera8cef6e2011-07-17 18:55:59 +000091 T_ERROR_ABORT("WRONG STRING (%s)!!!!", arg.c_str());
Aditya Agarwale9ef8d72006-12-08 23:52:57 +000092 }
Mark Slee739dbe52007-02-01 22:55:30 +000093 out = arg;
Aditya Agarwale9ef8d72006-12-08 23:52:57 +000094 }
Konrad Grochowski16a23a62014-11-13 15:33:38 +010095 void echoList(vector<int8_t>& out, const vector<int8_t>& arg) { out = arg; }
96 void echoSet(set<int8_t>& out, const set<int8_t>& arg) { out = arg; }
97 void echoMap(map<int8_t, int8_t>& out, const map<int8_t, int8_t>& arg) { out = arg; }
Mark Sleeb9ff32a2006-11-16 01:00:24 +000098
99private:
100 count_map counts_;
101 Mutex lock_;
Marc Slemko3ea00332006-08-17 01:11:13 +0000102};
103
ben-craig02bade12015-07-17 08:40:48 -0500104enum TransportOpenCloseBehavior {
105 OpenAndCloseTransportInThread,
106 DontOpenAndCloseTransportInThread
107};
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100108class ClientThread : public Runnable {
Marc Slemko3ea00332006-08-17 01:11:13 +0000109public:
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100110 ClientThread(boost::shared_ptr<TTransport> transport,
ben-craig02bade12015-07-17 08:40:48 -0500111 boost::shared_ptr<ServiceIf> client,
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100112 Monitor& monitor,
113 size_t& workerCount,
114 size_t loopCount,
ben-craig02bade12015-07-17 08:40:48 -0500115 TType loopType,
116 TransportOpenCloseBehavior behavior)
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100117 : _transport(transport),
118 _client(client),
119 _monitor(monitor),
120 _workerCount(workerCount),
121 _loopCount(loopCount),
ben-craig02bade12015-07-17 08:40:48 -0500122 _loopType(loopType),
123 _behavior(behavior) {}
Marc Slemko3ea00332006-08-17 01:11:13 +0000124
125 void run() {
126
David Reiss0c90f6f2008-02-06 22:18:40 +0000127 // Wait for all worker threads to start
Marc Slemko3ea00332006-08-17 01:11:13 +0000128
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100129 {
130 Synchronized s(_monitor);
131 while (_workerCount == 0) {
David Reiss0c90f6f2008-02-06 22:18:40 +0000132 _monitor.wait();
133 }
Marc Slemko3ea00332006-08-17 01:11:13 +0000134 }
135
136 _startTime = Util::currentTime();
ben-craig02bade12015-07-17 08:40:48 -0500137 if(_behavior == OpenAndCloseTransportInThread) {
138 _transport->open();
139 }
Marc Slemko3ea00332006-08-17 01:11:13 +0000140
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100141 switch (_loopType) {
142 case T_VOID:
143 loopEchoVoid();
144 break;
145 case T_BYTE:
146 loopEchoByte();
147 break;
148 case T_I32:
149 loopEchoI32();
150 break;
151 case T_I64:
152 loopEchoI64();
153 break;
154 case T_STRING:
155 loopEchoString();
156 break;
157 default:
158 cerr << "Unexpected loop type" << _loopType << endl;
159 break;
Marc Slemko3ea00332006-08-17 01:11:13 +0000160 }
David Reiss0c90f6f2008-02-06 22:18:40 +0000161
Marc Slemko3ea00332006-08-17 01:11:13 +0000162 _endTime = Util::currentTime();
163
ben-craig02bade12015-07-17 08:40:48 -0500164 if(_behavior == OpenAndCloseTransportInThread) {
165 _transport->close();
166 }
David Reiss0c90f6f2008-02-06 22:18:40 +0000167
Marc Slemko3ea00332006-08-17 01:11:13 +0000168 _done = true;
David Reiss0c90f6f2008-02-06 22:18:40 +0000169
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100170 {
171 Synchronized s(_monitor);
Marc Slemko3ea00332006-08-17 01:11:13 +0000172
173 _workerCount--;
David Reiss0c90f6f2008-02-06 22:18:40 +0000174
Mark Slee3e5d2d72007-06-15 01:45:56 +0000175 if (_workerCount == 0) {
David Reiss0c90f6f2008-02-06 22:18:40 +0000176
177 _monitor.notify();
Marc Slemko3ea00332006-08-17 01:11:13 +0000178 }
179 }
180 }
Marc Slemkod97eb612006-08-24 23:37:36 +0000181
182 void loopEchoVoid() {
Mark Slee3e5d2d72007-06-15 01:45:56 +0000183 for (size_t ix = 0; ix < _loopCount; ix++) {
Marc Slemkod97eb612006-08-24 23:37:36 +0000184 _client->echoVoid();
185 }
186 }
187
188 void loopEchoByte() {
Mark Slee3e5d2d72007-06-15 01:45:56 +0000189 for (size_t ix = 0; ix < _loopCount; ix++) {
Aditya Agarwal3950f472006-10-11 02:50:15 +0000190 int8_t arg = 1;
191 int8_t result;
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100192 result = _client->echoByte(arg);
Jake Farrell5d02b802014-01-07 21:42:01 -0500193 (void)result;
Marc Slemkod97eb612006-08-24 23:37:36 +0000194 assert(result == arg);
195 }
196 }
David Reiss0c90f6f2008-02-06 22:18:40 +0000197
Marc Slemkod97eb612006-08-24 23:37:36 +0000198 void loopEchoI32() {
Mark Slee3e5d2d72007-06-15 01:45:56 +0000199 for (size_t ix = 0; ix < _loopCount; ix++) {
Aditya Agarwal3950f472006-10-11 02:50:15 +0000200 int32_t arg = 1;
201 int32_t result;
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100202 result = _client->echoI32(arg);
Jake Farrell5d02b802014-01-07 21:42:01 -0500203 (void)result;
Marc Slemkod97eb612006-08-24 23:37:36 +0000204 assert(result == arg);
205 }
206 }
207
208 void loopEchoI64() {
Mark Slee3e5d2d72007-06-15 01:45:56 +0000209 for (size_t ix = 0; ix < _loopCount; ix++) {
Aditya Agarwal3950f472006-10-11 02:50:15 +0000210 int64_t arg = 1;
211 int64_t result;
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100212 result = _client->echoI64(arg);
Jake Farrell5d02b802014-01-07 21:42:01 -0500213 (void)result;
Marc Slemkod97eb612006-08-24 23:37:36 +0000214 assert(result == arg);
215 }
216 }
David Reiss0c90f6f2008-02-06 22:18:40 +0000217
Marc Slemkod97eb612006-08-24 23:37:36 +0000218 void loopEchoString() {
Mark Slee3e5d2d72007-06-15 01:45:56 +0000219 for (size_t ix = 0; ix < _loopCount; ix++) {
Marc Slemkod97eb612006-08-24 23:37:36 +0000220 string arg = "hello";
221 string result;
Mark Slee739dbe52007-02-01 22:55:30 +0000222 _client->echoString(result, arg);
Marc Slemkod97eb612006-08-24 23:37:36 +0000223 assert(result == arg);
224 }
225 }
David Reiss0c90f6f2008-02-06 22:18:40 +0000226
Roger Meier611f90c2011-12-11 22:08:51 +0000227 boost::shared_ptr<TTransport> _transport;
ben-craig02bade12015-07-17 08:40:48 -0500228 boost::shared_ptr<ServiceIf> _client;
Marc Slemko3ea00332006-08-17 01:11:13 +0000229 Monitor& _monitor;
230 size_t& _workerCount;
231 size_t _loopCount;
Marc Slemkod97eb612006-08-24 23:37:36 +0000232 TType _loopType;
Roger Meier5f9614c2010-11-21 16:59:05 +0000233 int64_t _startTime;
234 int64_t _endTime;
Marc Slemko3ea00332006-08-17 01:11:13 +0000235 bool _done;
236 Monitor _sleep;
ben-craig02bade12015-07-17 08:40:48 -0500237 TransportOpenCloseBehavior _behavior;
Marc Slemko3ea00332006-08-17 01:11:13 +0000238};
Aditya Agarwale9ef8d72006-12-08 23:52:57 +0000239
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100240class TStartObserver : public apache::thrift::server::TServerEventHandler {
Jake Farrell5d02b802014-01-07 21:42:01 -0500241public:
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100242 TStartObserver() : awake_(false) {}
243 virtual void preServe() {
244 apache::thrift::concurrency::Synchronized s(m_);
245 awake_ = true;
246 m_.notifyAll();
247 }
248 void waitForService() {
249 apache::thrift::concurrency::Synchronized s(m_);
250 while (!awake_)
251 m_.waitForever();
252 }
253
254private:
255 apache::thrift::concurrency::Monitor m_;
256 bool awake_;
Jake Farrell5d02b802014-01-07 21:42:01 -0500257};
Aditya Agarwale9ef8d72006-12-08 23:52:57 +0000258
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100259int main(int argc, char** argv) {
Jake Farrell5d02b802014-01-07 21:42:01 -0500260#if _WIN32
261 transport::TWinsockSingleton::create();
262#endif
Marc Slemko3ea00332006-08-17 01:11:13 +0000263
Aditya Agarwale9ef8d72006-12-08 23:52:57 +0000264 int port = 9091;
ben-craig02bade12015-07-17 08:40:48 -0500265 string clientType = "regular";
Marc Slemko3ea00332006-08-17 01:11:13 +0000266 string serverType = "thread-pool";
267 string protocolType = "binary";
268 size_t workerCount = 4;
Aditya Agarwale9ef8d72006-12-08 23:52:57 +0000269 size_t clientCount = 20;
270 size_t loopCount = 50000;
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100271 TType loopType = T_VOID;
Marc Slemkod97eb612006-08-24 23:37:36 +0000272 string callName = "echoVoid";
Marc Slemkob09f5882006-08-23 22:03:34 +0000273 bool runServer = true;
Aditya Agarwal3950f472006-10-11 02:50:15 +0000274 bool logRequests = false;
275 string requestLogPath = "./requestlog.tlog";
Aditya Agarwale9ef8d72006-12-08 23:52:57 +0000276 bool replayRequests = false;
Marc Slemko3ea00332006-08-17 01:11:13 +0000277
Marc Slemkob09f5882006-08-23 22:03:34 +0000278 ostringstream usage;
Marc Slemko3ea00332006-08-17 01:11:13 +0000279
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100280 usage << argv[0] << " [--port=<port number>] [--server] [--server-type=<server-type>] "
281 "[--protocol-type=<protocol-type>] [--workers=<worker-count>] "
ben-craig02bade12015-07-17 08:40:48 -0500282 "[--clients=<client-count>] [--loop=<loop-count>] "
283 "[--client-type=<client-type>]" << endl
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100284 << "\tclients Number of client threads to create - 0 implies no clients, i.e. "
ben-craig02bade12015-07-17 08:40:48 -0500285 "server only. Default is " << clientCount << endl
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100286 << "\thelp Prints this help text." << endl
287 << "\tcall Service method to call. Default is " << callName << endl
ben-craig02bade12015-07-17 08:40:48 -0500288 << "\tloop The number of remote thrift calls each client makes. Default is " << loopCount << endl
289 << "\tport The port the server and clients should bind to "
290 "for thrift network connections. Default is " << port << endl
291 << "\tserver Run the Thrift server in this process. Default is " << runServer << endl
292 << "\tserver-type Type of server, \"simple\" or \"thread-pool\". Default is " << serverType << endl
293 << "\tprotocol-type Type of protocol, \"binary\", \"ascii\", or \"xml\". Default is " << protocolType << endl
294 << "\tlog-request Log all request to ./requestlog.tlog. Default is " << logRequests << endl
295 << "\treplay-request Replay requests from log file (./requestlog.tlog) Default is " << replayRequests << endl
296 << "\tworkers Number of thread pools workers. Only valid "
297 "for thread-pool server type. Default is " << workerCount << endl
298 << "\tclient-type Type of client, \"regular\" or \"concurrent\". Default is " << clientType << endl
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100299 << endl;
David Reiss0c90f6f2008-02-06 22:18:40 +0000300
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100301 map<string, string> args;
David Reiss0c90f6f2008-02-06 22:18:40 +0000302
Mark Slee3e5d2d72007-06-15 01:45:56 +0000303 for (int ix = 1; ix < argc; ix++) {
Marc Slemko3ea00332006-08-17 01:11:13 +0000304
305 string arg(argv[ix]);
306
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100307 if (arg.compare(0, 2, "--") == 0) {
Marc Slemko3ea00332006-08-17 01:11:13 +0000308
309 size_t end = arg.find_first_of("=", 2);
310
Marc Slemko056f9ba2006-08-17 02:59:05 +0000311 string key = string(arg, 2, end - 2);
312
Mark Slee3e5d2d72007-06-15 01:45:56 +0000313 if (end != string::npos) {
David Reiss0c90f6f2008-02-06 22:18:40 +0000314 args[key] = string(arg, end + 1);
Marc Slemko3ea00332006-08-17 01:11:13 +0000315 } else {
David Reiss0c90f6f2008-02-06 22:18:40 +0000316 args[key] = "true";
Marc Slemko3ea00332006-08-17 01:11:13 +0000317 }
Marc Slemko3ea00332006-08-17 01:11:13 +0000318 } else {
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100319 throw invalid_argument("Unexcepted command line token: " + arg);
Marc Slemko3ea00332006-08-17 01:11:13 +0000320 }
321 }
322
323 try {
324
Mark Slee3e5d2d72007-06-15 01:45:56 +0000325 if (!args["clients"].empty()) {
Marc Slemkob09f5882006-08-23 22:03:34 +0000326 clientCount = atoi(args["clients"].c_str());
327 }
328
Mark Slee3e5d2d72007-06-15 01:45:56 +0000329 if (!args["help"].empty()) {
Marc Slemkob09f5882006-08-23 22:03:34 +0000330 cerr << usage.str();
331 return 0;
332 }
333
Mark Slee3e5d2d72007-06-15 01:45:56 +0000334 if (!args["loop"].empty()) {
Marc Slemkob09f5882006-08-23 22:03:34 +0000335 loopCount = atoi(args["loop"].c_str());
336 }
337
Mark Slee3e5d2d72007-06-15 01:45:56 +0000338 if (!args["call"].empty()) {
Marc Slemkod97eb612006-08-24 23:37:36 +0000339 callName = args["call"];
340 }
341
Mark Slee3e5d2d72007-06-15 01:45:56 +0000342 if (!args["port"].empty()) {
Marc Slemko3ea00332006-08-17 01:11:13 +0000343 port = atoi(args["port"].c_str());
344 }
345
Mark Slee3e5d2d72007-06-15 01:45:56 +0000346 if (!args["server"].empty()) {
Marc Slemkob09f5882006-08-23 22:03:34 +0000347 runServer = args["server"] == "true";
348 }
349
Mark Slee3e5d2d72007-06-15 01:45:56 +0000350 if (!args["log-request"].empty()) {
Aditya Agarwal3950f472006-10-11 02:50:15 +0000351 logRequests = args["log-request"] == "true";
352 }
353
Mark Slee3e5d2d72007-06-15 01:45:56 +0000354 if (!args["replay-request"].empty()) {
Aditya Agarwale9ef8d72006-12-08 23:52:57 +0000355 replayRequests = args["replay-request"] == "true";
356 }
357
Mark Slee3e5d2d72007-06-15 01:45:56 +0000358 if (!args["server-type"].empty()) {
Marc Slemko3ea00332006-08-17 01:11:13 +0000359 serverType = args["server-type"];
David Reiss0c90f6f2008-02-06 22:18:40 +0000360
Mark Slee3e5d2d72007-06-15 01:45:56 +0000361 if (serverType == "simple") {
Marc Slemko3ea00332006-08-17 01:11:13 +0000362
Mark Slee3e5d2d72007-06-15 01:45:56 +0000363 } else if (serverType == "thread-pool") {
Marc Slemko3ea00332006-08-17 01:11:13 +0000364
Mark Slee3e5d2d72007-06-15 01:45:56 +0000365 } else if (serverType == "threaded") {
Mark Slee739dbe52007-02-01 22:55:30 +0000366
Marc Slemko3ea00332006-08-17 01:11:13 +0000367 } else {
368
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100369 throw invalid_argument("Unknown server type " + serverType);
Marc Slemko3ea00332006-08-17 01:11:13 +0000370 }
371 }
ben-craig02bade12015-07-17 08:40:48 -0500372 if (!args["client-type"].empty()) {
373 clientType = args["client-type"];
Marc Slemko3ea00332006-08-17 01:11:13 +0000374
ben-craig02bade12015-07-17 08:40:48 -0500375 if (clientType == "regular") {
376
377 } else if (clientType == "concurrent") {
378
379 } else {
380
381 throw invalid_argument("Unknown client type " + clientType);
382 }
383 }
Mark Slee3e5d2d72007-06-15 01:45:56 +0000384 if (!args["workers"].empty()) {
Marc Slemko3ea00332006-08-17 01:11:13 +0000385 workerCount = atoi(args["workers"].c_str());
386 }
387
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100388 } catch (std::exception& e) {
Marc Slemko3ea00332006-08-17 01:11:13 +0000389 cerr << e.what() << endl;
Jake Farrell5d02b802014-01-07 21:42:01 -0500390 cerr << usage.str();
Marc Slemko3ea00332006-08-17 01:11:13 +0000391 }
392
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100393 boost::shared_ptr<PlatformThreadFactory> threadFactory
394 = boost::shared_ptr<PlatformThreadFactory>(new PlatformThreadFactory());
Marc Slemko3ea00332006-08-17 01:11:13 +0000395
Mark Sleeb9ff32a2006-11-16 01:00:24 +0000396 // Dispatcher
Roger Meier611f90c2011-12-11 22:08:51 +0000397 boost::shared_ptr<Server> serviceHandler(new Server());
Marc Slemko3ea00332006-08-17 01:11:13 +0000398
Aditya Agarwale9ef8d72006-12-08 23:52:57 +0000399 if (replayRequests) {
Roger Meier611f90c2011-12-11 22:08:51 +0000400 boost::shared_ptr<Server> serviceHandler(new Server());
401 boost::shared_ptr<ServiceProcessor> serviceProcessor(new ServiceProcessor(serviceHandler));
David Reiss0c90f6f2008-02-06 22:18:40 +0000402
Aditya Agarwale9ef8d72006-12-08 23:52:57 +0000403 // Transports
Roger Meier611f90c2011-12-11 22:08:51 +0000404 boost::shared_ptr<TFileTransport> fileTransport(new TFileTransport(requestLogPath));
Aditya Agarwale9ef8d72006-12-08 23:52:57 +0000405 fileTransport->setChunkSize(2 * 1024 * 1024);
406 fileTransport->setMaxEventSize(1024 * 16);
407 fileTransport->seekToEnd();
408
409 // Protocol Factory
Roger Meier611f90c2011-12-11 22:08:51 +0000410 boost::shared_ptr<TProtocolFactory> protocolFactory(new TBinaryProtocolFactory());
Aditya Agarwale9ef8d72006-12-08 23:52:57 +0000411
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100412 TFileProcessor fileProcessor(serviceProcessor, protocolFactory, fileTransport);
Aditya Agarwale9ef8d72006-12-08 23:52:57 +0000413
David Reiss0c90f6f2008-02-06 22:18:40 +0000414 fileProcessor.process(0, true);
Aditya Agarwale9ef8d72006-12-08 23:52:57 +0000415 exit(0);
416 }
417
Mark Slee3e5d2d72007-06-15 01:45:56 +0000418 if (runServer) {
Marc Slemko3ea00332006-08-17 01:11:13 +0000419
Roger Meier611f90c2011-12-11 22:08:51 +0000420 boost::shared_ptr<ServiceProcessor> serviceProcessor(new ServiceProcessor(serviceHandler));
Marc Slemko3ea00332006-08-17 01:11:13 +0000421
Marc Slemkob09f5882006-08-23 22:03:34 +0000422 // Transport
Roger Meier611f90c2011-12-11 22:08:51 +0000423 boost::shared_ptr<TServerSocket> serverSocket(new TServerSocket(port));
Marc Slemko3ea00332006-08-17 01:11:13 +0000424
Aditya Agarwal3950f472006-10-11 02:50:15 +0000425 // Transport Factory
Roger Meier611f90c2011-12-11 22:08:51 +0000426 boost::shared_ptr<TTransportFactory> transportFactory(new TBufferedTransportFactory());
Aditya Agarwal3950f472006-10-11 02:50:15 +0000427
Mark Sleed7173472006-10-25 19:52:10 +0000428 // Protocol Factory
Roger Meier611f90c2011-12-11 22:08:51 +0000429 boost::shared_ptr<TProtocolFactory> protocolFactory(new TBinaryProtocolFactory());
Aditya Agarwal3950f472006-10-11 02:50:15 +0000430
431 if (logRequests) {
432 // initialize the log file
Roger Meier611f90c2011-12-11 22:08:51 +0000433 boost::shared_ptr<TFileTransport> fileTransport(new TFileTransport(requestLogPath));
Aditya Agarwale9ef8d72006-12-08 23:52:57 +0000434 fileTransport->setChunkSize(2 * 1024 * 1024);
435 fileTransport->setMaxEventSize(1024 * 16);
David Reiss0c90f6f2008-02-06 22:18:40 +0000436
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100437 transportFactory
438 = boost::shared_ptr<TTransportFactory>(new TPipedTransportFactory(fileTransport));
Aditya Agarwal3950f472006-10-11 02:50:15 +0000439 }
Marc Slemko3ea00332006-08-17 01:11:13 +0000440
Jake Farrell5d02b802014-01-07 21:42:01 -0500441 boost::shared_ptr<TServer> server;
Marc Slemko3ea00332006-08-17 01:11:13 +0000442
Mark Slee3e5d2d72007-06-15 01:45:56 +0000443 if (serverType == "simple") {
David Reiss0c90f6f2008-02-06 22:18:40 +0000444
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100445 server.reset(
446 new TSimpleServer(serviceProcessor, serverSocket, transportFactory, protocolFactory));
David Reiss0c90f6f2008-02-06 22:18:40 +0000447
Mark Slee739dbe52007-02-01 22:55:30 +0000448 } else if (serverType == "threaded") {
449
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100450 server.reset(
451 new TThreadedServer(serviceProcessor, serverSocket, transportFactory, protocolFactory));
David Reiss0c90f6f2008-02-06 22:18:40 +0000452
Mark Slee3e5d2d72007-06-15 01:45:56 +0000453 } else if (serverType == "thread-pool") {
Marc Slemkob09f5882006-08-23 22:03:34 +0000454
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100455 boost::shared_ptr<ThreadManager> threadManager
456 = ThreadManager::newSimpleThreadManager(workerCount);
Marc Slemkob09f5882006-08-23 22:03:34 +0000457
458 threadManager->threadFactory(threadFactory);
David Reiss0c90f6f2008-02-06 22:18:40 +0000459 threadManager->start();
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100460 server.reset(new TThreadPoolServer(serviceProcessor,
461 serverSocket,
462 transportFactory,
463 protocolFactory,
464 threadManager));
Marc Slemkob09f5882006-08-23 22:03:34 +0000465 }
466
Jake Farrell5d02b802014-01-07 21:42:01 -0500467 boost::shared_ptr<TStartObserver> observer(new TStartObserver);
468 server->setServerEventHandler(observer);
469 boost::shared_ptr<Thread> serverThread = threadFactory->newThread(server);
470
Marc Slemkob09f5882006-08-23 22:03:34 +0000471 cerr << "Starting the server on port " << port << endl;
472
473 serverThread->start();
Jake Farrell5d02b802014-01-07 21:42:01 -0500474 observer->waitForService();
David Reiss0c90f6f2008-02-06 22:18:40 +0000475
Marc Slemkob09f5882006-08-23 22:03:34 +0000476 // If we aren't running clients, just wait forever for external clients
Mark Sleed7173472006-10-25 19:52:10 +0000477 if (clientCount == 0) {
Marc Slemkob09f5882006-08-23 22:03:34 +0000478 serverThread->join();
479 }
Marc Slemko3ea00332006-08-17 01:11:13 +0000480 }
481
ben-craig02bade12015-07-17 08:40:48 -0500482 if (clientCount > 0) { //FIXME: start here for client type?
Marc Slemko3ea00332006-08-17 01:11:13 +0000483
Marc Slemkob09f5882006-08-23 22:03:34 +0000484 Monitor monitor;
Marc Slemko3ea00332006-08-17 01:11:13 +0000485
Marc Slemkob09f5882006-08-23 22:03:34 +0000486 size_t threadCount = 0;
Marc Slemko3ea00332006-08-17 01:11:13 +0000487
Roger Meier611f90c2011-12-11 22:08:51 +0000488 set<boost::shared_ptr<Thread> > clientThreads;
Marc Slemko3ea00332006-08-17 01:11:13 +0000489
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100490 if (callName == "echoVoid") {
491 loopType = T_VOID;
492 } else if (callName == "echoByte") {
493 loopType = T_BYTE;
494 } else if (callName == "echoI32") {
495 loopType = T_I32;
496 } else if (callName == "echoI64") {
497 loopType = T_I64;
498 } else if (callName == "echoString") {
499 loopType = T_STRING;
500 } else {
501 throw invalid_argument("Unknown service call " + callName);
502 }
Marc Slemkod97eb612006-08-24 23:37:36 +0000503
ben-craig02bade12015-07-17 08:40:48 -0500504 if(clientType == "regular") {
505 for (size_t ix = 0; ix < clientCount; ix++) {
David Reiss0c90f6f2008-02-06 22:18:40 +0000506
ben-craig02bade12015-07-17 08:40:48 -0500507 boost::shared_ptr<TSocket> socket(new TSocket("127.0.0.1", port));
508 boost::shared_ptr<TBufferedTransport> bufferedSocket(new TBufferedTransport(socket, 2048));
509 boost::shared_ptr<TProtocol> protocol(new TBinaryProtocol(bufferedSocket));
510 boost::shared_ptr<ServiceClient> serviceClient(new ServiceClient(protocol));
511
512 clientThreads.insert(threadFactory->newThread(boost::shared_ptr<ClientThread>(
513 new ClientThread(socket, serviceClient, monitor, threadCount, loopCount, loopType, OpenAndCloseTransportInThread))));
514 }
515 } else if(clientType == "concurrent") {
Roger Meier611f90c2011-12-11 22:08:51 +0000516 boost::shared_ptr<TSocket> socket(new TSocket("127.0.0.1", port));
517 boost::shared_ptr<TBufferedTransport> bufferedSocket(new TBufferedTransport(socket, 2048));
518 boost::shared_ptr<TProtocol> protocol(new TBinaryProtocol(bufferedSocket));
ben-craig02bade12015-07-17 08:40:48 -0500519 //boost::shared_ptr<ServiceClient> serviceClient(new ServiceClient(protocol));
520 boost::shared_ptr<ServiceConcurrentClient> serviceClient(new ServiceConcurrentClient(protocol));
521 socket->open();
522 for (size_t ix = 0; ix < clientCount; ix++) {
523 clientThreads.insert(threadFactory->newThread(boost::shared_ptr<ClientThread>(
524 new ClientThread(socket, serviceClient, monitor, threadCount, loopCount, loopType, DontOpenAndCloseTransportInThread))));
525 }
Marc Slemkob09f5882006-08-23 22:03:34 +0000526 }
David Reiss0c90f6f2008-02-06 22:18:40 +0000527
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100528 for (std::set<boost::shared_ptr<Thread> >::const_iterator thread = clientThreads.begin();
529 thread != clientThreads.end();
530 thread++) {
Marc Slemkob09f5882006-08-23 22:03:34 +0000531 (*thread)->start();
532 }
Marc Slemko3ea00332006-08-17 01:11:13 +0000533
Roger Meier5f9614c2010-11-21 16:59:05 +0000534 int64_t time00;
535 int64_t time01;
David Reiss0c90f6f2008-02-06 22:18:40 +0000536
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100537 {
538 Synchronized s(monitor);
Marc Slemkob09f5882006-08-23 22:03:34 +0000539 threadCount = clientCount;
David Reiss0c90f6f2008-02-06 22:18:40 +0000540
ben-craig02bade12015-07-17 08:40:48 -0500541 cerr << "Launch " << clientCount << " " << clientType << " client threads" << endl;
David Reiss0c90f6f2008-02-06 22:18:40 +0000542
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100543 time00 = Util::currentTime();
David Reiss0c90f6f2008-02-06 22:18:40 +0000544
Marc Slemkob09f5882006-08-23 22:03:34 +0000545 monitor.notifyAll();
David Reiss0c90f6f2008-02-06 22:18:40 +0000546
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100547 while (threadCount > 0) {
David Reiss0c90f6f2008-02-06 22:18:40 +0000548 monitor.wait();
Marc Slemkob09f5882006-08-23 22:03:34 +0000549 }
David Reiss0c90f6f2008-02-06 22:18:40 +0000550
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100551 time01 = Util::currentTime();
Marc Slemko3ea00332006-08-17 01:11:13 +0000552 }
David Reiss0c90f6f2008-02-06 22:18:40 +0000553
Roger Meier5f9614c2010-11-21 16:59:05 +0000554 int64_t firstTime = 9223372036854775807LL;
555 int64_t lastTime = 0;
Marc Slemko3ea00332006-08-17 01:11:13 +0000556
Marc Slemkob09f5882006-08-23 22:03:34 +0000557 double averageTime = 0;
Roger Meier5f9614c2010-11-21 16:59:05 +0000558 int64_t minTime = 9223372036854775807LL;
559 int64_t maxTime = 0;
David Reiss0c90f6f2008-02-06 22:18:40 +0000560
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100561 for (set<boost::shared_ptr<Thread> >::iterator ix = clientThreads.begin();
562 ix != clientThreads.end();
563 ix++) {
David Reiss0c90f6f2008-02-06 22:18:40 +0000564
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100565 boost::shared_ptr<ClientThread> client
566 = boost::dynamic_pointer_cast<ClientThread>((*ix)->runnable());
David Reiss0c90f6f2008-02-06 22:18:40 +0000567
Roger Meier5f9614c2010-11-21 16:59:05 +0000568 int64_t delta = client->_endTime - client->_startTime;
David Reiss0c90f6f2008-02-06 22:18:40 +0000569
Marc Slemkob09f5882006-08-23 22:03:34 +0000570 assert(delta > 0);
Marc Slemko056f9ba2006-08-17 02:59:05 +0000571
Mark Slee3e5d2d72007-06-15 01:45:56 +0000572 if (client->_startTime < firstTime) {
David Reiss0c90f6f2008-02-06 22:18:40 +0000573 firstTime = client->_startTime;
Marc Slemkob09f5882006-08-23 22:03:34 +0000574 }
David Reiss0c90f6f2008-02-06 22:18:40 +0000575
Mark Slee3e5d2d72007-06-15 01:45:56 +0000576 if (client->_endTime > lastTime) {
David Reiss0c90f6f2008-02-06 22:18:40 +0000577 lastTime = client->_endTime;
Marc Slemkob09f5882006-08-23 22:03:34 +0000578 }
David Reiss0c90f6f2008-02-06 22:18:40 +0000579
Mark Slee3e5d2d72007-06-15 01:45:56 +0000580 if (delta < minTime) {
David Reiss0c90f6f2008-02-06 22:18:40 +0000581 minTime = delta;
Marc Slemkob09f5882006-08-23 22:03:34 +0000582 }
David Reiss0c90f6f2008-02-06 22:18:40 +0000583
Mark Slee3e5d2d72007-06-15 01:45:56 +0000584 if (delta > maxTime) {
David Reiss0c90f6f2008-02-06 22:18:40 +0000585 maxTime = delta;
Marc Slemkob09f5882006-08-23 22:03:34 +0000586 }
David Reiss0c90f6f2008-02-06 22:18:40 +0000587
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100588 averageTime += delta;
Marc Slemkob09f5882006-08-23 22:03:34 +0000589 }
David Reiss0c90f6f2008-02-06 22:18:40 +0000590
Marc Slemkob09f5882006-08-23 22:03:34 +0000591 averageTime /= clientCount;
David Reiss0c90f6f2008-02-06 22:18:40 +0000592
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100593 cout << "workers :" << workerCount << ", client : " << clientCount << ", loops : " << loopCount
594 << ", rate : " << (clientCount * loopCount * 1000) / ((double)(time01 - time00)) << endl;
David Reiss0c90f6f2008-02-06 22:18:40 +0000595
Mark Sleeb9ff32a2006-11-16 01:00:24 +0000596 count_map count = serviceHandler->getCount();
597 count_map::iterator iter;
598 for (iter = count.begin(); iter != count.end(); ++iter) {
599 printf("%s => %d\n", iter->first, iter->second);
600 }
Marc Slemkob09f5882006-08-23 22:03:34 +0000601 cerr << "done." << endl;
Marc Slemko056f9ba2006-08-17 02:59:05 +0000602 }
Marc Slemko056f9ba2006-08-17 02:59:05 +0000603
Marc Slemko3ea00332006-08-17 01:11:13 +0000604 return 0;
605}