blob: 930261e4611edd0198afdfa27899ae4e0ec61390 [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>
cyyca8af9b2019-01-11 22:13:12 +080021#include <thrift/concurrency/ThreadFactory.h>
Roger Meier49ff8b12012-04-13 09:12:31 +000022#include <thrift/concurrency/Monitor.h>
Roger Meier49ff8b12012-04-13 09:12:31 +000023#include <thrift/concurrency/Mutex.h>
24#include <thrift/protocol/TBinaryProtocol.h>
25#include <thrift/server/TSimpleServer.h>
26#include <thrift/server/TThreadPoolServer.h>
27#include <thrift/server/TThreadedServer.h>
28#include <thrift/transport/TServerSocket.h>
29#include <thrift/transport/TSocket.h>
30#include <thrift/transport/TTransportUtils.h>
31#include <thrift/transport/TFileTransport.h>
Roger Meier33eaa0f2012-04-13 09:13:13 +000032#include <thrift/TLogging.h>
Aditya Agarwal3950f472006-10-11 02:50:15 +000033
34#include "Service.h"
Marc Slemko3ea00332006-08-17 01:11:13 +000035#include <iostream>
36#include <set>
37#include <stdexcept>
38#include <sstream>
Mark Sleeb9ff32a2006-11-16 01:00:24 +000039#include <map>
Jake Farrell5d02b802014-01-07 21:42:01 -050040#if _WIN32
Konrad Grochowski16a23a62014-11-13 15:33:38 +010041#include <thrift/windows/TWinsockSingleton.h>
Jake Farrell5d02b802014-01-07 21:42:01 -050042#endif
Mark Sleeb9ff32a2006-11-16 01:00:24 +000043
Marc Slemko3ea00332006-08-17 01:11:13 +000044using namespace std;
45
T Jake Lucianib5e62212009-01-31 22:36:20 +000046using namespace apache::thrift;
47using namespace apache::thrift::protocol;
48using namespace apache::thrift::transport;
49using namespace apache::thrift::server;
50using namespace apache::thrift::concurrency;
Marc Slemko3ea00332006-08-17 01:11:13 +000051
52using namespace test::stress;
53
Mark Sleeb9ff32a2006-11-16 01:00:24 +000054struct eqstr {
Konrad Grochowski16a23a62014-11-13 15:33:38 +010055 bool operator()(const char* s1, const char* s2) const { return strcmp(s1, s2) == 0; }
Mark Sleeb9ff32a2006-11-16 01:00:24 +000056};
57
58struct ltstr {
Konrad Grochowski16a23a62014-11-13 15:33:38 +010059 bool operator()(const char* s1, const char* s2) const { return strcmp(s1, s2) < 0; }
Mark Sleeb9ff32a2006-11-16 01:00:24 +000060};
61
David Reiss0c90f6f2008-02-06 22:18:40 +000062// typedef hash_map<const char*, int, hash<const char*>, eqstr> count_map;
63typedef map<const char*, int, ltstr> count_map;
Mark Sleeb9ff32a2006-11-16 01:00:24 +000064
Aditya Agarwal3950f472006-10-11 02:50:15 +000065class Server : public ServiceIf {
Konrad Grochowski16a23a62014-11-13 15:33:38 +010066public:
Mark Sleeb9ff32a2006-11-16 01:00:24 +000067 Server() {}
68
69 void count(const char* method) {
David Reiss46379902008-02-04 19:23:57 +000070 Guard m(lock_);
Mark Sleeb9ff32a2006-11-16 01:00:24 +000071 int ct = counts_[method];
72 counts_[method] = ++ct;
73 }
74
75 void echoVoid() {
76 count("echoVoid");
77 return;
78 }
79
80 count_map getCount() {
David Reiss46379902008-02-04 19:23:57 +000081 Guard m(lock_);
Mark Sleeb9ff32a2006-11-16 01:00:24 +000082 return counts_;
83 }
84
Konrad Grochowski16a23a62014-11-13 15:33:38 +010085 int8_t echoByte(const int8_t arg) { return arg; }
86 int32_t echoI32(const int32_t arg) { return arg; }
87 int64_t echoI64(const int64_t arg) { return arg; }
88 void echoString(string& out, const string& arg) {
Aditya Agarwale9ef8d72006-12-08 23:52:57 +000089 if (arg != "hello") {
Roger Meiera8cef6e2011-07-17 18:55:59 +000090 T_ERROR_ABORT("WRONG STRING (%s)!!!!", arg.c_str());
Aditya Agarwale9ef8d72006-12-08 23:52:57 +000091 }
Mark Slee739dbe52007-02-01 22:55:30 +000092 out = arg;
Aditya Agarwale9ef8d72006-12-08 23:52:57 +000093 }
Konrad Grochowski16a23a62014-11-13 15:33:38 +010094 void echoList(vector<int8_t>& out, const vector<int8_t>& arg) { out = arg; }
95 void echoSet(set<int8_t>& out, const set<int8_t>& arg) { out = arg; }
96 void echoMap(map<int8_t, int8_t>& out, const map<int8_t, int8_t>& arg) { out = arg; }
Mark Sleeb9ff32a2006-11-16 01:00:24 +000097
98private:
99 count_map counts_;
100 Mutex lock_;
Marc Slemko3ea00332006-08-17 01:11:13 +0000101};
102
ben-craig02bade12015-07-17 08:40:48 -0500103enum TransportOpenCloseBehavior {
104 OpenAndCloseTransportInThread,
105 DontOpenAndCloseTransportInThread
106};
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100107class ClientThread : public Runnable {
Marc Slemko3ea00332006-08-17 01:11:13 +0000108public:
cyy316723a2019-01-05 16:35:14 +0800109 ClientThread(std::shared_ptr<TTransport> transport,
110 std::shared_ptr<ServiceIf> client,
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100111 Monitor& monitor,
112 size_t& workerCount,
113 size_t loopCount,
ben-craig02bade12015-07-17 08:40:48 -0500114 TType loopType,
115 TransportOpenCloseBehavior behavior)
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100116 : _transport(transport),
117 _client(client),
118 _monitor(monitor),
119 _workerCount(workerCount),
120 _loopCount(loopCount),
ben-craig02bade12015-07-17 08:40:48 -0500121 _loopType(loopType),
122 _behavior(behavior) {}
Marc Slemko3ea00332006-08-17 01:11:13 +0000123
124 void run() {
125
David Reiss0c90f6f2008-02-06 22:18:40 +0000126 // Wait for all worker threads to start
Marc Slemko3ea00332006-08-17 01:11:13 +0000127
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100128 {
129 Synchronized s(_monitor);
130 while (_workerCount == 0) {
David Reiss0c90f6f2008-02-06 22:18:40 +0000131 _monitor.wait();
132 }
Marc Slemko3ea00332006-08-17 01:11:13 +0000133 }
134
cyybfdbd032019-01-12 14:38:28 +0800135 _startTime = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now().time_since_epoch()).count();
ben-craig02bade12015-07-17 08:40:48 -0500136 if(_behavior == OpenAndCloseTransportInThread) {
137 _transport->open();
138 }
Marc Slemko3ea00332006-08-17 01:11:13 +0000139
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100140 switch (_loopType) {
141 case T_VOID:
142 loopEchoVoid();
143 break;
144 case T_BYTE:
145 loopEchoByte();
146 break;
147 case T_I32:
148 loopEchoI32();
149 break;
150 case T_I64:
151 loopEchoI64();
152 break;
153 case T_STRING:
154 loopEchoString();
155 break;
156 default:
157 cerr << "Unexpected loop type" << _loopType << endl;
158 break;
Marc Slemko3ea00332006-08-17 01:11:13 +0000159 }
David Reiss0c90f6f2008-02-06 22:18:40 +0000160
cyybfdbd032019-01-12 14:38:28 +0800161 _endTime = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now().time_since_epoch()).count();
Marc Slemko3ea00332006-08-17 01:11:13 +0000162
ben-craig02bade12015-07-17 08:40:48 -0500163 if(_behavior == OpenAndCloseTransportInThread) {
164 _transport->close();
165 }
David Reiss0c90f6f2008-02-06 22:18:40 +0000166
Marc Slemko3ea00332006-08-17 01:11:13 +0000167 _done = true;
David Reiss0c90f6f2008-02-06 22:18:40 +0000168
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100169 {
170 Synchronized s(_monitor);
Marc Slemko3ea00332006-08-17 01:11:13 +0000171
172 _workerCount--;
David Reiss0c90f6f2008-02-06 22:18:40 +0000173
Mark Slee3e5d2d72007-06-15 01:45:56 +0000174 if (_workerCount == 0) {
David Reiss0c90f6f2008-02-06 22:18:40 +0000175
176 _monitor.notify();
Marc Slemko3ea00332006-08-17 01:11:13 +0000177 }
178 }
179 }
Marc Slemkod97eb612006-08-24 23:37:36 +0000180
181 void loopEchoVoid() {
Mark Slee3e5d2d72007-06-15 01:45:56 +0000182 for (size_t ix = 0; ix < _loopCount; ix++) {
Marc Slemkod97eb612006-08-24 23:37:36 +0000183 _client->echoVoid();
184 }
185 }
186
187 void loopEchoByte() {
Mark Slee3e5d2d72007-06-15 01:45:56 +0000188 for (size_t ix = 0; ix < _loopCount; ix++) {
Aditya Agarwal3950f472006-10-11 02:50:15 +0000189 int8_t arg = 1;
190 int8_t result;
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100191 result = _client->echoByte(arg);
Jake Farrell5d02b802014-01-07 21:42:01 -0500192 (void)result;
Marc Slemkod97eb612006-08-24 23:37:36 +0000193 assert(result == arg);
194 }
195 }
David Reiss0c90f6f2008-02-06 22:18:40 +0000196
Marc Slemkod97eb612006-08-24 23:37:36 +0000197 void loopEchoI32() {
Mark Slee3e5d2d72007-06-15 01:45:56 +0000198 for (size_t ix = 0; ix < _loopCount; ix++) {
Aditya Agarwal3950f472006-10-11 02:50:15 +0000199 int32_t arg = 1;
200 int32_t result;
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100201 result = _client->echoI32(arg);
Jake Farrell5d02b802014-01-07 21:42:01 -0500202 (void)result;
Marc Slemkod97eb612006-08-24 23:37:36 +0000203 assert(result == arg);
204 }
205 }
206
207 void loopEchoI64() {
Mark Slee3e5d2d72007-06-15 01:45:56 +0000208 for (size_t ix = 0; ix < _loopCount; ix++) {
Aditya Agarwal3950f472006-10-11 02:50:15 +0000209 int64_t arg = 1;
210 int64_t result;
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100211 result = _client->echoI64(arg);
Jake Farrell5d02b802014-01-07 21:42:01 -0500212 (void)result;
Marc Slemkod97eb612006-08-24 23:37:36 +0000213 assert(result == arg);
214 }
215 }
David Reiss0c90f6f2008-02-06 22:18:40 +0000216
Marc Slemkod97eb612006-08-24 23:37:36 +0000217 void loopEchoString() {
Mark Slee3e5d2d72007-06-15 01:45:56 +0000218 for (size_t ix = 0; ix < _loopCount; ix++) {
Marc Slemkod97eb612006-08-24 23:37:36 +0000219 string arg = "hello";
220 string result;
Mark Slee739dbe52007-02-01 22:55:30 +0000221 _client->echoString(result, arg);
Marc Slemkod97eb612006-08-24 23:37:36 +0000222 assert(result == arg);
223 }
224 }
David Reiss0c90f6f2008-02-06 22:18:40 +0000225
cyy316723a2019-01-05 16:35:14 +0800226 std::shared_ptr<TTransport> _transport;
227 std::shared_ptr<ServiceIf> _client;
Marc Slemko3ea00332006-08-17 01:11:13 +0000228 Monitor& _monitor;
229 size_t& _workerCount;
230 size_t _loopCount;
Marc Slemkod97eb612006-08-24 23:37:36 +0000231 TType _loopType;
Roger Meier5f9614c2010-11-21 16:59:05 +0000232 int64_t _startTime;
233 int64_t _endTime;
Marc Slemko3ea00332006-08-17 01:11:13 +0000234 bool _done;
235 Monitor _sleep;
ben-craig02bade12015-07-17 08:40:48 -0500236 TransportOpenCloseBehavior _behavior;
Marc Slemko3ea00332006-08-17 01:11:13 +0000237};
Aditya Agarwale9ef8d72006-12-08 23:52:57 +0000238
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100239class TStartObserver : public apache::thrift::server::TServerEventHandler {
Jake Farrell5d02b802014-01-07 21:42:01 -0500240public:
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100241 TStartObserver() : awake_(false) {}
242 virtual void preServe() {
243 apache::thrift::concurrency::Synchronized s(m_);
244 awake_ = true;
245 m_.notifyAll();
246 }
247 void waitForService() {
248 apache::thrift::concurrency::Synchronized s(m_);
249 while (!awake_)
250 m_.waitForever();
251 }
252
253private:
254 apache::thrift::concurrency::Monitor m_;
255 bool awake_;
Jake Farrell5d02b802014-01-07 21:42:01 -0500256};
Aditya Agarwale9ef8d72006-12-08 23:52:57 +0000257
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100258int main(int argc, char** argv) {
Jake Farrell5d02b802014-01-07 21:42:01 -0500259#if _WIN32
260 transport::TWinsockSingleton::create();
261#endif
Marc Slemko3ea00332006-08-17 01:11:13 +0000262
Aditya Agarwale9ef8d72006-12-08 23:52:57 +0000263 int port = 9091;
ben-craig02bade12015-07-17 08:40:48 -0500264 string clientType = "regular";
Marc Slemko3ea00332006-08-17 01:11:13 +0000265 string serverType = "thread-pool";
266 string protocolType = "binary";
267 size_t workerCount = 4;
Aditya Agarwale9ef8d72006-12-08 23:52:57 +0000268 size_t clientCount = 20;
269 size_t loopCount = 50000;
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100270 TType loopType = T_VOID;
Marc Slemkod97eb612006-08-24 23:37:36 +0000271 string callName = "echoVoid";
Marc Slemkob09f5882006-08-23 22:03:34 +0000272 bool runServer = true;
Aditya Agarwal3950f472006-10-11 02:50:15 +0000273 bool logRequests = false;
274 string requestLogPath = "./requestlog.tlog";
Aditya Agarwale9ef8d72006-12-08 23:52:57 +0000275 bool replayRequests = false;
Marc Slemko3ea00332006-08-17 01:11:13 +0000276
Marc Slemkob09f5882006-08-23 22:03:34 +0000277 ostringstream usage;
Marc Slemko3ea00332006-08-17 01:11:13 +0000278
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100279 usage << argv[0] << " [--port=<port number>] [--server] [--server-type=<server-type>] "
280 "[--protocol-type=<protocol-type>] [--workers=<worker-count>] "
ben-craig02bade12015-07-17 08:40:48 -0500281 "[--clients=<client-count>] [--loop=<loop-count>] "
282 "[--client-type=<client-type>]" << endl
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100283 << "\tclients Number of client threads to create - 0 implies no clients, i.e. "
ben-craig02bade12015-07-17 08:40:48 -0500284 "server only. Default is " << clientCount << endl
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100285 << "\thelp Prints this help text." << endl
286 << "\tcall Service method to call. Default is " << callName << endl
James E. King, III82ae9572017-08-05 12:23:54 -0400287 << "\tloop The number of remote thrift calls each client makes. Default is " << loopCount << endl
ben-craig02bade12015-07-17 08:40:48 -0500288 << "\tport The port the server and clients should bind to "
289 "for thrift network connections. Default is " << port << endl
James E. King, III82ae9572017-08-05 12:23:54 -0400290 << "\tserver Run the Thrift server in this process. Default is " << runServer << endl
ben-craig02bade12015-07-17 08:40:48 -0500291 << "\tserver-type Type of server, \"simple\" or \"thread-pool\". Default is " << serverType << endl
292 << "\tprotocol-type Type of protocol, \"binary\", \"ascii\", or \"xml\". Default is " << protocolType << endl
James E. King, III82ae9572017-08-05 12:23:54 -0400293 << "\tlog-request Log all request to ./requestlog.tlog. Default is " << logRequests << endl
294 << "\treplay-request Replay requests from log file (./requestlog.tlog) Default is " << replayRequests << endl
ben-craig02bade12015-07-17 08:40:48 -0500295 << "\tworkers Number of thread pools workers. Only valid "
296 "for thread-pool server type. Default is " << workerCount << endl
297 << "\tclient-type Type of client, \"regular\" or \"concurrent\". Default is " << clientType << endl
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100298 << endl;
David Reiss0c90f6f2008-02-06 22:18:40 +0000299
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100300 map<string, string> args;
David Reiss0c90f6f2008-02-06 22:18:40 +0000301
Mark Slee3e5d2d72007-06-15 01:45:56 +0000302 for (int ix = 1; ix < argc; ix++) {
Marc Slemko3ea00332006-08-17 01:11:13 +0000303
304 string arg(argv[ix]);
305
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100306 if (arg.compare(0, 2, "--") == 0) {
Marc Slemko3ea00332006-08-17 01:11:13 +0000307
308 size_t end = arg.find_first_of("=", 2);
309
Marc Slemko056f9ba2006-08-17 02:59:05 +0000310 string key = string(arg, 2, end - 2);
311
Mark Slee3e5d2d72007-06-15 01:45:56 +0000312 if (end != string::npos) {
David Reiss0c90f6f2008-02-06 22:18:40 +0000313 args[key] = string(arg, end + 1);
Marc Slemko3ea00332006-08-17 01:11:13 +0000314 } else {
David Reiss0c90f6f2008-02-06 22:18:40 +0000315 args[key] = "true";
Marc Slemko3ea00332006-08-17 01:11:13 +0000316 }
Marc Slemko3ea00332006-08-17 01:11:13 +0000317 } else {
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100318 throw invalid_argument("Unexcepted command line token: " + arg);
Marc Slemko3ea00332006-08-17 01:11:13 +0000319 }
320 }
321
322 try {
323
Mark Slee3e5d2d72007-06-15 01:45:56 +0000324 if (!args["clients"].empty()) {
Marc Slemkob09f5882006-08-23 22:03:34 +0000325 clientCount = atoi(args["clients"].c_str());
326 }
327
Mark Slee3e5d2d72007-06-15 01:45:56 +0000328 if (!args["help"].empty()) {
Marc Slemkob09f5882006-08-23 22:03:34 +0000329 cerr << usage.str();
330 return 0;
331 }
332
Mark Slee3e5d2d72007-06-15 01:45:56 +0000333 if (!args["loop"].empty()) {
Marc Slemkob09f5882006-08-23 22:03:34 +0000334 loopCount = atoi(args["loop"].c_str());
335 }
336
Mark Slee3e5d2d72007-06-15 01:45:56 +0000337 if (!args["call"].empty()) {
Marc Slemkod97eb612006-08-24 23:37:36 +0000338 callName = args["call"];
339 }
340
Mark Slee3e5d2d72007-06-15 01:45:56 +0000341 if (!args["port"].empty()) {
Marc Slemko3ea00332006-08-17 01:11:13 +0000342 port = atoi(args["port"].c_str());
343 }
344
Mark Slee3e5d2d72007-06-15 01:45:56 +0000345 if (!args["server"].empty()) {
Marc Slemkob09f5882006-08-23 22:03:34 +0000346 runServer = args["server"] == "true";
347 }
348
Mark Slee3e5d2d72007-06-15 01:45:56 +0000349 if (!args["log-request"].empty()) {
Aditya Agarwal3950f472006-10-11 02:50:15 +0000350 logRequests = args["log-request"] == "true";
351 }
352
Mark Slee3e5d2d72007-06-15 01:45:56 +0000353 if (!args["replay-request"].empty()) {
Aditya Agarwale9ef8d72006-12-08 23:52:57 +0000354 replayRequests = args["replay-request"] == "true";
355 }
356
Mark Slee3e5d2d72007-06-15 01:45:56 +0000357 if (!args["server-type"].empty()) {
Marc Slemko3ea00332006-08-17 01:11:13 +0000358 serverType = args["server-type"];
David Reiss0c90f6f2008-02-06 22:18:40 +0000359
Mark Slee3e5d2d72007-06-15 01:45:56 +0000360 if (serverType == "simple") {
Marc Slemko3ea00332006-08-17 01:11:13 +0000361
Mark Slee3e5d2d72007-06-15 01:45:56 +0000362 } else if (serverType == "thread-pool") {
Marc Slemko3ea00332006-08-17 01:11:13 +0000363
Mark Slee3e5d2d72007-06-15 01:45:56 +0000364 } else if (serverType == "threaded") {
Mark Slee739dbe52007-02-01 22:55:30 +0000365
Marc Slemko3ea00332006-08-17 01:11:13 +0000366 } else {
367
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100368 throw invalid_argument("Unknown server type " + serverType);
Marc Slemko3ea00332006-08-17 01:11:13 +0000369 }
370 }
ben-craig02bade12015-07-17 08:40:48 -0500371 if (!args["client-type"].empty()) {
372 clientType = args["client-type"];
Marc Slemko3ea00332006-08-17 01:11:13 +0000373
ben-craig02bade12015-07-17 08:40:48 -0500374 if (clientType == "regular") {
375
376 } else if (clientType == "concurrent") {
377
378 } else {
379
380 throw invalid_argument("Unknown client type " + clientType);
381 }
382 }
Mark Slee3e5d2d72007-06-15 01:45:56 +0000383 if (!args["workers"].empty()) {
Marc Slemko3ea00332006-08-17 01:11:13 +0000384 workerCount = atoi(args["workers"].c_str());
385 }
386
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100387 } catch (std::exception& e) {
Marc Slemko3ea00332006-08-17 01:11:13 +0000388 cerr << e.what() << endl;
Jake Farrell5d02b802014-01-07 21:42:01 -0500389 cerr << usage.str();
Marc Slemko3ea00332006-08-17 01:11:13 +0000390 }
391
cyyca8af9b2019-01-11 22:13:12 +0800392 std::shared_ptr<ThreadFactory> threadFactory
393 = std::shared_ptr<ThreadFactory>(new ThreadFactory());
Marc Slemko3ea00332006-08-17 01:11:13 +0000394
Mark Sleeb9ff32a2006-11-16 01:00:24 +0000395 // Dispatcher
cyy316723a2019-01-05 16:35:14 +0800396 std::shared_ptr<Server> serviceHandler(new Server());
Marc Slemko3ea00332006-08-17 01:11:13 +0000397
Aditya Agarwale9ef8d72006-12-08 23:52:57 +0000398 if (replayRequests) {
cyy316723a2019-01-05 16:35:14 +0800399 std::shared_ptr<Server> serviceHandler(new Server());
400 std::shared_ptr<ServiceProcessor> serviceProcessor(new ServiceProcessor(serviceHandler));
David Reiss0c90f6f2008-02-06 22:18:40 +0000401
Aditya Agarwale9ef8d72006-12-08 23:52:57 +0000402 // Transports
cyy316723a2019-01-05 16:35:14 +0800403 std::shared_ptr<TFileTransport> fileTransport(new TFileTransport(requestLogPath));
Aditya Agarwale9ef8d72006-12-08 23:52:57 +0000404 fileTransport->setChunkSize(2 * 1024 * 1024);
405 fileTransport->setMaxEventSize(1024 * 16);
406 fileTransport->seekToEnd();
407
408 // Protocol Factory
cyy316723a2019-01-05 16:35:14 +0800409 std::shared_ptr<TProtocolFactory> protocolFactory(new TBinaryProtocolFactory());
Aditya Agarwale9ef8d72006-12-08 23:52:57 +0000410
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100411 TFileProcessor fileProcessor(serviceProcessor, protocolFactory, fileTransport);
Aditya Agarwale9ef8d72006-12-08 23:52:57 +0000412
David Reiss0c90f6f2008-02-06 22:18:40 +0000413 fileProcessor.process(0, true);
Aditya Agarwale9ef8d72006-12-08 23:52:57 +0000414 exit(0);
415 }
416
Mark Slee3e5d2d72007-06-15 01:45:56 +0000417 if (runServer) {
Marc Slemko3ea00332006-08-17 01:11:13 +0000418
cyy316723a2019-01-05 16:35:14 +0800419 std::shared_ptr<ServiceProcessor> serviceProcessor(new ServiceProcessor(serviceHandler));
Marc Slemko3ea00332006-08-17 01:11:13 +0000420
Marc Slemkob09f5882006-08-23 22:03:34 +0000421 // Transport
cyy316723a2019-01-05 16:35:14 +0800422 std::shared_ptr<TServerSocket> serverSocket(new TServerSocket(port));
Marc Slemko3ea00332006-08-17 01:11:13 +0000423
Aditya Agarwal3950f472006-10-11 02:50:15 +0000424 // Transport Factory
cyy316723a2019-01-05 16:35:14 +0800425 std::shared_ptr<TTransportFactory> transportFactory(new TBufferedTransportFactory());
Aditya Agarwal3950f472006-10-11 02:50:15 +0000426
Mark Sleed7173472006-10-25 19:52:10 +0000427 // Protocol Factory
cyy316723a2019-01-05 16:35:14 +0800428 std::shared_ptr<TProtocolFactory> protocolFactory(new TBinaryProtocolFactory());
Aditya Agarwal3950f472006-10-11 02:50:15 +0000429
430 if (logRequests) {
431 // initialize the log file
cyy316723a2019-01-05 16:35:14 +0800432 std::shared_ptr<TFileTransport> fileTransport(new TFileTransport(requestLogPath));
Aditya Agarwale9ef8d72006-12-08 23:52:57 +0000433 fileTransport->setChunkSize(2 * 1024 * 1024);
434 fileTransport->setMaxEventSize(1024 * 16);
David Reiss0c90f6f2008-02-06 22:18:40 +0000435
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100436 transportFactory
cyy316723a2019-01-05 16:35:14 +0800437 = std::shared_ptr<TTransportFactory>(new TPipedTransportFactory(fileTransport));
Aditya Agarwal3950f472006-10-11 02:50:15 +0000438 }
Marc Slemko3ea00332006-08-17 01:11:13 +0000439
cyy316723a2019-01-05 16:35:14 +0800440 std::shared_ptr<TServer> server;
Marc Slemko3ea00332006-08-17 01:11:13 +0000441
Mark Slee3e5d2d72007-06-15 01:45:56 +0000442 if (serverType == "simple") {
David Reiss0c90f6f2008-02-06 22:18:40 +0000443
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100444 server.reset(
445 new TSimpleServer(serviceProcessor, serverSocket, transportFactory, protocolFactory));
David Reiss0c90f6f2008-02-06 22:18:40 +0000446
Mark Slee739dbe52007-02-01 22:55:30 +0000447 } else if (serverType == "threaded") {
448
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100449 server.reset(
450 new TThreadedServer(serviceProcessor, serverSocket, transportFactory, protocolFactory));
David Reiss0c90f6f2008-02-06 22:18:40 +0000451
Mark Slee3e5d2d72007-06-15 01:45:56 +0000452 } else if (serverType == "thread-pool") {
Marc Slemkob09f5882006-08-23 22:03:34 +0000453
cyy316723a2019-01-05 16:35:14 +0800454 std::shared_ptr<ThreadManager> threadManager
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100455 = ThreadManager::newSimpleThreadManager(workerCount);
Marc Slemkob09f5882006-08-23 22:03:34 +0000456
457 threadManager->threadFactory(threadFactory);
David Reiss0c90f6f2008-02-06 22:18:40 +0000458 threadManager->start();
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100459 server.reset(new TThreadPoolServer(serviceProcessor,
460 serverSocket,
461 transportFactory,
462 protocolFactory,
463 threadManager));
Marc Slemkob09f5882006-08-23 22:03:34 +0000464 }
465
cyy316723a2019-01-05 16:35:14 +0800466 std::shared_ptr<TStartObserver> observer(new TStartObserver);
Jake Farrell5d02b802014-01-07 21:42:01 -0500467 server->setServerEventHandler(observer);
cyy316723a2019-01-05 16:35:14 +0800468 std::shared_ptr<Thread> serverThread = threadFactory->newThread(server);
Jake Farrell5d02b802014-01-07 21:42:01 -0500469
Marc Slemkob09f5882006-08-23 22:03:34 +0000470 cerr << "Starting the server on port " << port << endl;
471
472 serverThread->start();
Jake Farrell5d02b802014-01-07 21:42:01 -0500473 observer->waitForService();
David Reiss0c90f6f2008-02-06 22:18:40 +0000474
Marc Slemkob09f5882006-08-23 22:03:34 +0000475 // If we aren't running clients, just wait forever for external clients
Mark Sleed7173472006-10-25 19:52:10 +0000476 if (clientCount == 0) {
Marc Slemkob09f5882006-08-23 22:03:34 +0000477 serverThread->join();
478 }
Marc Slemko3ea00332006-08-17 01:11:13 +0000479 }
480
ben-craig02bade12015-07-17 08:40:48 -0500481 if (clientCount > 0) { //FIXME: start here for client type?
Marc Slemko3ea00332006-08-17 01:11:13 +0000482
Marc Slemkob09f5882006-08-23 22:03:34 +0000483 Monitor monitor;
Marc Slemko3ea00332006-08-17 01:11:13 +0000484
Marc Slemkob09f5882006-08-23 22:03:34 +0000485 size_t threadCount = 0;
Marc Slemko3ea00332006-08-17 01:11:13 +0000486
cyy316723a2019-01-05 16:35:14 +0800487 set<std::shared_ptr<Thread> > clientThreads;
Marc Slemko3ea00332006-08-17 01:11:13 +0000488
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100489 if (callName == "echoVoid") {
490 loopType = T_VOID;
491 } else if (callName == "echoByte") {
492 loopType = T_BYTE;
493 } else if (callName == "echoI32") {
494 loopType = T_I32;
495 } else if (callName == "echoI64") {
496 loopType = T_I64;
497 } else if (callName == "echoString") {
498 loopType = T_STRING;
499 } else {
500 throw invalid_argument("Unknown service call " + callName);
501 }
Marc Slemkod97eb612006-08-24 23:37:36 +0000502
ben-craig02bade12015-07-17 08:40:48 -0500503 if(clientType == "regular") {
504 for (size_t ix = 0; ix < clientCount; ix++) {
David Reiss0c90f6f2008-02-06 22:18:40 +0000505
cyy316723a2019-01-05 16:35:14 +0800506 std::shared_ptr<TSocket> socket(new TSocket("127.0.0.1", port));
507 std::shared_ptr<TBufferedTransport> bufferedSocket(new TBufferedTransport(socket, 2048));
508 std::shared_ptr<TProtocol> protocol(new TBinaryProtocol(bufferedSocket));
509 std::shared_ptr<ServiceClient> serviceClient(new ServiceClient(protocol));
ben-craig02bade12015-07-17 08:40:48 -0500510
cyy316723a2019-01-05 16:35:14 +0800511 clientThreads.insert(threadFactory->newThread(std::shared_ptr<ClientThread>(
ben-craig02bade12015-07-17 08:40:48 -0500512 new ClientThread(socket, serviceClient, monitor, threadCount, loopCount, loopType, OpenAndCloseTransportInThread))));
513 }
514 } else if(clientType == "concurrent") {
cyy316723a2019-01-05 16:35:14 +0800515 std::shared_ptr<TSocket> socket(new TSocket("127.0.0.1", port));
516 std::shared_ptr<TBufferedTransport> bufferedSocket(new TBufferedTransport(socket, 2048));
517 std::shared_ptr<TProtocol> protocol(new TBinaryProtocol(bufferedSocket));
518 //std::shared_ptr<ServiceClient> serviceClient(new ServiceClient(protocol));
519 std::shared_ptr<ServiceConcurrentClient> serviceClient(new ServiceConcurrentClient(protocol));
ben-craig02bade12015-07-17 08:40:48 -0500520 socket->open();
521 for (size_t ix = 0; ix < clientCount; ix++) {
cyy316723a2019-01-05 16:35:14 +0800522 clientThreads.insert(threadFactory->newThread(std::shared_ptr<ClientThread>(
ben-craig02bade12015-07-17 08:40:48 -0500523 new ClientThread(socket, serviceClient, monitor, threadCount, loopCount, loopType, DontOpenAndCloseTransportInThread))));
524 }
Marc Slemkob09f5882006-08-23 22:03:34 +0000525 }
David Reiss0c90f6f2008-02-06 22:18:40 +0000526
cyy316723a2019-01-05 16:35:14 +0800527 for (std::set<std::shared_ptr<Thread> >::const_iterator thread = clientThreads.begin();
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100528 thread != clientThreads.end();
529 thread++) {
Marc Slemkob09f5882006-08-23 22:03:34 +0000530 (*thread)->start();
531 }
Marc Slemko3ea00332006-08-17 01:11:13 +0000532
Roger Meier5f9614c2010-11-21 16:59:05 +0000533 int64_t time00;
534 int64_t time01;
David Reiss0c90f6f2008-02-06 22:18:40 +0000535
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100536 {
537 Synchronized s(monitor);
Marc Slemkob09f5882006-08-23 22:03:34 +0000538 threadCount = clientCount;
David Reiss0c90f6f2008-02-06 22:18:40 +0000539
ben-craig02bade12015-07-17 08:40:48 -0500540 cerr << "Launch " << clientCount << " " << clientType << " client threads" << endl;
David Reiss0c90f6f2008-02-06 22:18:40 +0000541
cyybfdbd032019-01-12 14:38:28 +0800542 time00 = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now().time_since_epoch()).count();
David Reiss0c90f6f2008-02-06 22:18:40 +0000543
Marc Slemkob09f5882006-08-23 22:03:34 +0000544 monitor.notifyAll();
David Reiss0c90f6f2008-02-06 22:18:40 +0000545
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100546 while (threadCount > 0) {
David Reiss0c90f6f2008-02-06 22:18:40 +0000547 monitor.wait();
Marc Slemkob09f5882006-08-23 22:03:34 +0000548 }
David Reiss0c90f6f2008-02-06 22:18:40 +0000549
cyybfdbd032019-01-12 14:38:28 +0800550 time01 = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now().time_since_epoch()).count();
Marc Slemko3ea00332006-08-17 01:11:13 +0000551 }
David Reiss0c90f6f2008-02-06 22:18:40 +0000552
Roger Meier5f9614c2010-11-21 16:59:05 +0000553 int64_t firstTime = 9223372036854775807LL;
554 int64_t lastTime = 0;
Marc Slemko3ea00332006-08-17 01:11:13 +0000555
Marc Slemkob09f5882006-08-23 22:03:34 +0000556 double averageTime = 0;
Roger Meier5f9614c2010-11-21 16:59:05 +0000557 int64_t minTime = 9223372036854775807LL;
558 int64_t maxTime = 0;
David Reiss0c90f6f2008-02-06 22:18:40 +0000559
cyy316723a2019-01-05 16:35:14 +0800560 for (set<std::shared_ptr<Thread> >::iterator ix = clientThreads.begin();
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100561 ix != clientThreads.end();
562 ix++) {
David Reiss0c90f6f2008-02-06 22:18:40 +0000563
cyy316723a2019-01-05 16:35:14 +0800564 std::shared_ptr<ClientThread> client
565 = std::dynamic_pointer_cast<ClientThread>((*ix)->runnable());
David Reiss0c90f6f2008-02-06 22:18:40 +0000566
Roger Meier5f9614c2010-11-21 16:59:05 +0000567 int64_t delta = client->_endTime - client->_startTime;
David Reiss0c90f6f2008-02-06 22:18:40 +0000568
Marc Slemkob09f5882006-08-23 22:03:34 +0000569 assert(delta > 0);
Marc Slemko056f9ba2006-08-17 02:59:05 +0000570
Mark Slee3e5d2d72007-06-15 01:45:56 +0000571 if (client->_startTime < firstTime) {
David Reiss0c90f6f2008-02-06 22:18:40 +0000572 firstTime = client->_startTime;
Marc Slemkob09f5882006-08-23 22:03:34 +0000573 }
David Reiss0c90f6f2008-02-06 22:18:40 +0000574
Mark Slee3e5d2d72007-06-15 01:45:56 +0000575 if (client->_endTime > lastTime) {
David Reiss0c90f6f2008-02-06 22:18:40 +0000576 lastTime = client->_endTime;
Marc Slemkob09f5882006-08-23 22:03:34 +0000577 }
David Reiss0c90f6f2008-02-06 22:18:40 +0000578
Mark Slee3e5d2d72007-06-15 01:45:56 +0000579 if (delta < minTime) {
David Reiss0c90f6f2008-02-06 22:18:40 +0000580 minTime = delta;
Marc Slemkob09f5882006-08-23 22:03:34 +0000581 }
David Reiss0c90f6f2008-02-06 22:18:40 +0000582
Mark Slee3e5d2d72007-06-15 01:45:56 +0000583 if (delta > maxTime) {
David Reiss0c90f6f2008-02-06 22:18:40 +0000584 maxTime = delta;
Marc Slemkob09f5882006-08-23 22:03:34 +0000585 }
David Reiss0c90f6f2008-02-06 22:18:40 +0000586
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100587 averageTime += delta;
Marc Slemkob09f5882006-08-23 22:03:34 +0000588 }
David Reiss0c90f6f2008-02-06 22:18:40 +0000589
Marc Slemkob09f5882006-08-23 22:03:34 +0000590 averageTime /= clientCount;
David Reiss0c90f6f2008-02-06 22:18:40 +0000591
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100592 cout << "workers :" << workerCount << ", client : " << clientCount << ", loops : " << loopCount
593 << ", rate : " << (clientCount * loopCount * 1000) / ((double)(time01 - time00)) << endl;
David Reiss0c90f6f2008-02-06 22:18:40 +0000594
Mark Sleeb9ff32a2006-11-16 01:00:24 +0000595 count_map count = serviceHandler->getCount();
596 count_map::iterator iter;
597 for (iter = count.begin(); iter != count.end(); ++iter) {
598 printf("%s => %d\n", iter->first, iter->second);
599 }
Marc Slemkob09f5882006-08-23 22:03:34 +0000600 cerr << "done." << endl;
Marc Slemko056f9ba2006-08-17 02:59:05 +0000601 }
Marc Slemko056f9ba2006-08-17 02:59:05 +0000602
Marc Slemko3ea00332006-08-17 01:11:13 +0000603 return 0;
604}