blob: bd6a2cff44415c3d563f24ceda115651a9d68773 [file] [log] [blame]
Marc Slemko6be374b2006-08-04 03:16:25 +00001#include <concurrency/ThreadManager.h>
2#include <concurrency/PosixThreadFactory.h>
3#include <protocol/TBinaryProtocol.h>
4#include <server/TSimpleServer.h>
5#include <server/TThreadPoolServer.h>
Mark Sleeb9acf982006-10-10 01:57:32 +00006#include <server/TNonblockingServer.h>
Marc Slemko6be374b2006-08-04 03:16:25 +00007#include <transport/TServerSocket.h>
Mark Sleea3302652006-10-25 19:03:32 +00008#include <transport/TTransportUtils.h>
Mark Slee95771002006-06-07 06:53:25 +00009#include "ThriftTest.h"
Marc Slemko6be374b2006-08-04 03:16:25 +000010
11#include <iostream>
12#include <stdexcept>
13#include <sstream>
14
Mark Sleee8540632006-05-30 09:24:40 +000015using namespace std;
16
Marc Slemko6be374b2006-08-04 03:16:25 +000017using namespace facebook::thrift;
18using namespace facebook::thrift::protocol;
19using namespace facebook::thrift::transport;
20using namespace facebook::thrift::server;
21
Marc Slemkobf4fd192006-08-15 21:29:39 +000022using namespace thrift::test;
23
Mark Sleed2655522006-09-05 22:09:57 +000024class TestHandler : public ThriftTestIf {
Mark Sleee8540632006-05-30 09:24:40 +000025 public:
Mark Sleed2655522006-09-05 22:09:57 +000026 TestHandler() {}
Mark Sleee8540632006-05-30 09:24:40 +000027
28 void testVoid() {
29 printf("testVoid()\n");
30 }
31
Mark Slee1921d202007-01-24 19:43:06 +000032 void testString(string& out, const string &thing) {
Mark Sleee8540632006-05-30 09:24:40 +000033 printf("testString(\"%s\")\n", thing.c_str());
Mark Slee1921d202007-01-24 19:43:06 +000034 out = thing;
Mark Sleee8540632006-05-30 09:24:40 +000035 }
36
Mark Slee1921d202007-01-24 19:43:06 +000037 int8_t testByte(const int8_t thing) {
Mark Sleee8540632006-05-30 09:24:40 +000038 printf("testByte(%d)\n", (int)thing);
39 return thing;
40 }
41
Mark Slee1921d202007-01-24 19:43:06 +000042 int32_t testI32(const int32_t thing) {
Mark Sleee8540632006-05-30 09:24:40 +000043 printf("testI32(%d)\n", thing);
44 return thing;
45 }
46
Mark Slee1921d202007-01-24 19:43:06 +000047 int64_t testI64(const int64_t thing) {
Mark Sleed3d733a2006-09-01 22:19:06 +000048 printf("testI64(%ld)\n", thing);
Mark Sleee8540632006-05-30 09:24:40 +000049 return thing;
50 }
51
Mark Slee1921d202007-01-24 19:43:06 +000052 double testDouble(const double thing) {
Mark Sleec98d0502006-09-06 02:42:25 +000053 printf("testDouble(%lf)\n", thing);
54 return thing;
55 }
56
Mark Slee1921d202007-01-24 19:43:06 +000057 void testStruct(Xtruct& out, const Xtruct &thing) {
Mark Sleed788b2e2006-09-07 01:26:35 +000058 printf("testStruct({\"%s\", %d, %d, %ld})\n", thing.string_thing.c_str(), (int)thing.byte_thing, thing.i32_thing, thing.i64_thing);
Mark Slee1921d202007-01-24 19:43:06 +000059 out = thing;
Mark Sleee8540632006-05-30 09:24:40 +000060 }
61
Mark Slee1921d202007-01-24 19:43:06 +000062 void testNest(Xtruct2& out, const Xtruct2& nest) {
63 const Xtruct &thing = nest.struct_thing;
Mark Sleed788b2e2006-09-07 01:26:35 +000064 printf("testNest({%d, {\"%s\", %d, %d, %ld}, %d})\n", (int)nest.byte_thing, thing.string_thing.c_str(), (int)thing.byte_thing, thing.i32_thing, thing.i64_thing, nest.i32_thing);
Mark Slee1921d202007-01-24 19:43:06 +000065 out = nest;
Mark Sleee8540632006-05-30 09:24:40 +000066 }
67
Mark Slee1921d202007-01-24 19:43:06 +000068 void testMap(map<int32_t, int32_t> &out, const map<int32_t, int32_t> &thing) {
Mark Sleee8540632006-05-30 09:24:40 +000069 printf("testMap({");
70 map<int32_t, int32_t>::const_iterator m_iter;
71 bool first = true;
72 for (m_iter = thing.begin(); m_iter != thing.end(); ++m_iter) {
73 if (first) {
74 first = false;
75 } else {
76 printf(", ");
77 }
78 printf("%d => %d", m_iter->first, m_iter->second);
79 }
80 printf("})\n");
Mark Slee1921d202007-01-24 19:43:06 +000081 out = thing;
Mark Sleee8540632006-05-30 09:24:40 +000082 }
83
Mark Slee1921d202007-01-24 19:43:06 +000084 void testSet(set<int32_t> &out, const set<int32_t> &thing) {
Mark Sleee8540632006-05-30 09:24:40 +000085 printf("testSet({");
86 set<int32_t>::const_iterator s_iter;
87 bool first = true;
88 for (s_iter = thing.begin(); s_iter != thing.end(); ++s_iter) {
89 if (first) {
90 first = false;
91 } else {
92 printf(", ");
93 }
94 printf("%d", *s_iter);
95 }
96 printf("})\n");
Mark Slee1921d202007-01-24 19:43:06 +000097 out = thing;
Mark Sleee8540632006-05-30 09:24:40 +000098 }
99
Mark Slee1921d202007-01-24 19:43:06 +0000100 void testList(vector<int32_t> &out, const vector<int32_t> &thing) {
Mark Sleee8540632006-05-30 09:24:40 +0000101 printf("testList({");
Mark Sleeb9acf982006-10-10 01:57:32 +0000102 vector<int32_t>::const_iterator l_iter;
Mark Sleee8540632006-05-30 09:24:40 +0000103 bool first = true;
104 for (l_iter = thing.begin(); l_iter != thing.end(); ++l_iter) {
105 if (first) {
106 first = false;
107 } else {
108 printf(", ");
109 }
110 printf("%d", *l_iter);
111 }
112 printf("})\n");
Mark Slee1921d202007-01-24 19:43:06 +0000113 out = thing;
Mark Sleee8540632006-05-30 09:24:40 +0000114 }
115
Mark Slee1921d202007-01-24 19:43:06 +0000116 Numberz testEnum(const Numberz thing) {
Mark Sleee8540632006-05-30 09:24:40 +0000117 printf("testEnum(%d)\n", thing);
118 return thing;
119 }
120
Mark Slee1921d202007-01-24 19:43:06 +0000121 UserId testTypedef(const UserId thing) {
Mark Sleed3d733a2006-09-01 22:19:06 +0000122 printf("testTypedef(%ld)\n", thing);
Mark Sleee8540632006-05-30 09:24:40 +0000123 return thing;
124 }
125
Mark Slee1921d202007-01-24 19:43:06 +0000126 void testMapMap(map<int32_t, map<int32_t,int32_t> > &mapmap, const int32_t hello) {
Mark Sleee8540632006-05-30 09:24:40 +0000127 printf("testMapMap(%d)\n", hello);
Mark Sleee8540632006-05-30 09:24:40 +0000128
129 map<int32_t,int32_t> pos;
130 map<int32_t,int32_t> neg;
131 for (int i = 1; i < 5; i++) {
132 pos.insert(make_pair(i,i));
133 neg.insert(make_pair(-i,-i));
134 }
135
136 mapmap.insert(make_pair(4, pos));
137 mapmap.insert(make_pair(-4, neg));
138
Mark Sleee8540632006-05-30 09:24:40 +0000139 }
140
Mark Slee1921d202007-01-24 19:43:06 +0000141 void testInsanity(map<UserId, map<Numberz,Insanity> > &insane, const Insanity &argument) {
Mark Sleee8540632006-05-30 09:24:40 +0000142 printf("testInsanity()\n");
143
144 Xtruct hello;
145 hello.string_thing = "Hello2";
146 hello.byte_thing = 2;
Mark Sleee8540632006-05-30 09:24:40 +0000147 hello.i32_thing = 2;
Mark Sleee8540632006-05-30 09:24:40 +0000148 hello.i64_thing = 2;
149
150 Xtruct goodbye;
151 goodbye.string_thing = "Goodbye4";
152 goodbye.byte_thing = 4;
Mark Sleee8540632006-05-30 09:24:40 +0000153 goodbye.i32_thing = 4;
Mark Sleee8540632006-05-30 09:24:40 +0000154 goodbye.i64_thing = 4;
155
156 Insanity crazy;
157 crazy.userMap.insert(make_pair(EIGHT, 8));
158 crazy.xtructs.push_back(goodbye);
159
160 Insanity looney;
161 crazy.userMap.insert(make_pair(FIVE, 5));
162 crazy.xtructs.push_back(hello);
163
164 map<Numberz, Insanity> first_map;
165 map<Numberz, Insanity> second_map;
166
167 first_map.insert(make_pair(TWO, crazy));
168 first_map.insert(make_pair(THREE, crazy));
169
170 second_map.insert(make_pair(SIX, looney));
171
Mark Sleee8540632006-05-30 09:24:40 +0000172 insane.insert(make_pair(1, first_map));
173 insane.insert(make_pair(2, second_map));
174
175 printf("return");
176 printf(" = {");
177 map<UserId, map<Numberz,Insanity> >::const_iterator i_iter;
178 for (i_iter = insane.begin(); i_iter != insane.end(); ++i_iter) {
Mark Sleed3d733a2006-09-01 22:19:06 +0000179 printf("%ld => {", i_iter->first);
Mark Sleee8540632006-05-30 09:24:40 +0000180 map<Numberz,Insanity>::const_iterator i2_iter;
181 for (i2_iter = i_iter->second.begin();
182 i2_iter != i_iter->second.end();
183 ++i2_iter) {
184 printf("%d => {", i2_iter->first);
185 map<Numberz, UserId> userMap = i2_iter->second.userMap;
186 map<Numberz, UserId>::const_iterator um;
187 printf("{");
188 for (um = userMap.begin(); um != userMap.end(); ++um) {
Mark Sleed3d733a2006-09-01 22:19:06 +0000189 printf("%d => %ld, ", um->first, um->second);
Mark Sleee8540632006-05-30 09:24:40 +0000190 }
191 printf("}, ");
192
Mark Sleeb9acf982006-10-10 01:57:32 +0000193 vector<Xtruct> xtructs = i2_iter->second.xtructs;
194 vector<Xtruct>::const_iterator x;
Mark Sleee8540632006-05-30 09:24:40 +0000195 printf("{");
196 for (x = xtructs.begin(); x != xtructs.end(); ++x) {
Mark Sleed788b2e2006-09-07 01:26:35 +0000197 printf("{\"%s\", %d, %d, %ld}, ", x->string_thing.c_str(), (int)x->byte_thing, x->i32_thing, x->i64_thing);
Mark Sleee8540632006-05-30 09:24:40 +0000198 }
199 printf("}");
200
201 printf("}, ");
202 }
203 printf("}, ");
204 }
205 printf("}\n");
206
Mark Slee1921d202007-01-24 19:43:06 +0000207
Mark Sleee8540632006-05-30 09:24:40 +0000208 }
Marc Slemkoe6889de2006-08-12 00:32:53 +0000209
Mark Slee1921d202007-01-24 19:43:06 +0000210 void testMulti(Xtruct &hello, const int8_t arg0, const int32_t arg1, const int64_t arg2, const std::map<int16_t, std::string> &arg3, const Numberz arg4, const UserId arg5) {
Marc Slemkoe6889de2006-08-12 00:32:53 +0000211 printf("testMulti()\n");
212
Marc Slemkoe6889de2006-08-12 00:32:53 +0000213 hello.string_thing = "Hello2";
214 hello.byte_thing = arg0;
215 hello.i32_thing = arg1;
216 hello.i64_thing = (int64_t)arg2;
Marc Slemkoe6889de2006-08-12 00:32:53 +0000217 }
Marc Slemkobf4fd192006-08-15 21:29:39 +0000218
Mark Slee1921d202007-01-24 19:43:06 +0000219 void testException(const std::string &arg) throw(Xception) {
Marc Slemkobf4fd192006-08-15 21:29:39 +0000220 printf("testException(%s)\n", arg.c_str());
Mark Sleed3d733a2006-09-01 22:19:06 +0000221 if (arg.compare("Xception") == 0) {
Marc Slemkobf4fd192006-08-15 21:29:39 +0000222 Xception e;
223 e.errorCode = 1001;
224 e.message = "This is an Xception";
225 throw e;
226 } else {
227 Xtruct result;
228 result.string_thing = arg;
229 return;
230 }
231 }
232
Mark Slee1921d202007-01-24 19:43:06 +0000233 void testMultiException(Xtruct &result, const std::string &arg0, const std::string &arg1) throw(Xception, Xception2) {
Marc Slemkobf4fd192006-08-15 21:29:39 +0000234
Marc Slemko71d4e472006-08-15 22:34:04 +0000235 printf("testMultiException(%s, %s)\n", arg0.c_str(), arg1.c_str());
Marc Slemkobf4fd192006-08-15 21:29:39 +0000236
Mark Sleef5f2be42006-09-05 21:05:31 +0000237 if (arg0.compare("Xception") == 0) {
Marc Slemkobf4fd192006-08-15 21:29:39 +0000238 Xception e;
239 e.errorCode = 1001;
240 e.message = "This is an Xception";
241 throw e;
Mark Sleef5f2be42006-09-05 21:05:31 +0000242 } else if (arg0.compare("Xception2") == 0) {
Marc Slemkobf4fd192006-08-15 21:29:39 +0000243 Xception2 e;
244 e.errorCode = 2002;
245 e.struct_thing.string_thing = "This is an Xception2";
246 throw e;
247 } else {
Marc Slemkobf4fd192006-08-15 21:29:39 +0000248 result.string_thing = arg1;
Mark Slee1921d202007-01-24 19:43:06 +0000249 return;
Marc Slemkobf4fd192006-08-15 21:29:39 +0000250 }
251 }
Mark Sleee8540632006-05-30 09:24:40 +0000252};
253
254int main(int argc, char **argv) {
Marc Slemko6be374b2006-08-04 03:16:25 +0000255
Mark Sleee8540632006-05-30 09:24:40 +0000256 int port = 9090;
Marc Slemko6be374b2006-08-04 03:16:25 +0000257 string serverType = "simple";
258 string protocolType = "binary";
259 size_t workerCount = 4;
Mark Sleea3302652006-10-25 19:03:32 +0000260 bool frameOutput = true;
Marc Slemko6be374b2006-08-04 03:16:25 +0000261
262 ostringstream usage;
263
264 usage <<
265 argv[0] << " [--port=<port number>] [--server-type=<server-type>] [--protocol-type=<protocol-type>] [--workers=<worker-count>]" << endl <<
266
Mark Sleea3302652006-10-25 19:03:32 +0000267 "\t\tserver-type\t\ttype of server, \"simple\", \"thread-pool\", or \"nonblocking\". Default is " << serverType << endl <<
Marc Slemko6be374b2006-08-04 03:16:25 +0000268
269 "\t\tprotocol-type\t\ttype of protocol, \"binary\", \"ascii\", or \"xml\". Default is " << protocolType << endl <<
270
271 "\t\tworkers\t\tNumber of thread pools workers. Only valid for thread-pool server type. Default is " << workerCount << endl;
272
273 map<string, string> args;
274
Mark Sleef5f2be42006-09-05 21:05:31 +0000275 for (int ix = 1; ix < argc; ix++) {
Marc Slemko6be374b2006-08-04 03:16:25 +0000276 string arg(argv[ix]);
Mark Sleef5f2be42006-09-05 21:05:31 +0000277 if (arg.compare(0,2, "--") == 0) {
Marc Slemko6be374b2006-08-04 03:16:25 +0000278 size_t end = arg.find_first_of("=", 2);
Mark Sleef5f2be42006-09-05 21:05:31 +0000279 if (end != string::npos) {
Marc Slemko6be374b2006-08-04 03:16:25 +0000280 args[string(arg, 2, end - 2)] = string(arg, end + 1);
281 } else {
Mark Sleea3302652006-10-25 19:03:32 +0000282 args[string(arg, 2)] = "true";
Marc Slemko6be374b2006-08-04 03:16:25 +0000283 }
Marc Slemko6be374b2006-08-04 03:16:25 +0000284 } else {
285 throw invalid_argument("Unexcepted command line token: "+arg);
286 }
Mark Sleee8540632006-05-30 09:24:40 +0000287 }
Marc Slemko6be374b2006-08-04 03:16:25 +0000288
289 try {
290
Mark Sleef5f2be42006-09-05 21:05:31 +0000291 if (!args["port"].empty()) {
Marc Slemko6be374b2006-08-04 03:16:25 +0000292 port = atoi(args["port"].c_str());
293 }
294
Mark Sleea3302652006-10-25 19:03:32 +0000295 if (!args["noframe"].empty()) {
296 frameOutput = false;
297 }
298
Mark Sleef5f2be42006-09-05 21:05:31 +0000299 if (!args["server-type"].empty()) {
300 serverType = args["server-type"];
301 if (serverType == "simple") {
302 } else if (serverType == "thread-pool") {
Mark Sleeb9acf982006-10-10 01:57:32 +0000303 } else if (serverType == "nonblocking") {
Marc Slemko6be374b2006-08-04 03:16:25 +0000304 } else {
Marc Slemko6be374b2006-08-04 03:16:25 +0000305 throw invalid_argument("Unknown server type "+serverType);
306 }
307 }
308
Mark Sleef5f2be42006-09-05 21:05:31 +0000309 if (!args["protocol-type"].empty()) {
Marc Slemko6be374b2006-08-04 03:16:25 +0000310 protocolType = args["protocol-type"];
Mark Sleef5f2be42006-09-05 21:05:31 +0000311 if (protocolType == "binary") {
312 } else if (protocolType == "ascii") {
Marc Slemko6be374b2006-08-04 03:16:25 +0000313 throw invalid_argument("ASCII protocol not supported");
Mark Sleef5f2be42006-09-05 21:05:31 +0000314 } else if (protocolType == "xml") {
Marc Slemko6be374b2006-08-04 03:16:25 +0000315 throw invalid_argument("XML protocol not supported");
316 } else {
317 throw invalid_argument("Unknown protocol type "+protocolType);
318 }
319 }
320
Mark Sleef5f2be42006-09-05 21:05:31 +0000321 if (!args["workers"].empty()) {
Marc Slemko6be374b2006-08-04 03:16:25 +0000322 workerCount = atoi(args["workers"].c_str());
323 }
Mark Sleef5f2be42006-09-05 21:05:31 +0000324 } catch (exception& e) {
Marc Slemko6be374b2006-08-04 03:16:25 +0000325 cerr << e.what() << endl;
326 cerr << usage;
327 }
328
Mark Sleee8540632006-05-30 09:24:40 +0000329 // Dispatcher
Mark Sleea3302652006-10-25 19:03:32 +0000330 shared_ptr<TProtocolFactory> protocolFactory(new TBinaryProtocolFactory());
Marc Slemko6be374b2006-08-04 03:16:25 +0000331
Mark Sleed2655522006-09-05 22:09:57 +0000332 shared_ptr<TestHandler> testHandler(new TestHandler());
333
Mark Sleea3302652006-10-25 19:03:32 +0000334 shared_ptr<ThriftTestProcessor> testProcessor(new ThriftTestProcessor(testHandler));
Mark Sleee8540632006-05-30 09:24:40 +0000335
Mark Sleee8540632006-05-30 09:24:40 +0000336 // Transport
Marc Slemko6be374b2006-08-04 03:16:25 +0000337 shared_ptr<TServerSocket> serverSocket(new TServerSocket(port));
Mark Sleee8540632006-05-30 09:24:40 +0000338
Mark Sleed788b2e2006-09-07 01:26:35 +0000339 // Factory
340 shared_ptr<TTransportFactory> transportFactory(new TBufferedTransportFactory());
341
Mark Sleed3d733a2006-09-01 22:19:06 +0000342 if (serverType == "simple") {
Mark Sleee8540632006-05-30 09:24:40 +0000343
Marc Slemko6be374b2006-08-04 03:16:25 +0000344 // Server
Mark Slee018b6992006-09-07 21:31:12 +0000345 TSimpleServer simpleServer(testProcessor,
Mark Sleed788b2e2006-09-07 01:26:35 +0000346 serverSocket,
347 transportFactory,
Mark Sleea3302652006-10-25 19:03:32 +0000348 protocolFactory);
Marc Slemko6be374b2006-08-04 03:16:25 +0000349
350 printf("Starting the server on port %d...\n", port);
Mark Slee794993d2006-09-20 01:56:10 +0000351 simpleServer.serve();
Marc Slemko6be374b2006-08-04 03:16:25 +0000352
Mark Sleed3d733a2006-09-01 22:19:06 +0000353 } else if (serverType == "thread-pool") {
Marc Slemko6be374b2006-08-04 03:16:25 +0000354
Mark Sleef5f2be42006-09-05 21:05:31 +0000355 shared_ptr<ThreadManager> threadManager =
356 ThreadManager::newSimpleThreadManager(workerCount);
Marc Slemko6be374b2006-08-04 03:16:25 +0000357
Mark Sleef5f2be42006-09-05 21:05:31 +0000358 shared_ptr<PosixThreadFactory> threadFactory =
359 shared_ptr<PosixThreadFactory>(new PosixThreadFactory());
Marc Slemko6be374b2006-08-04 03:16:25 +0000360
361 threadManager->threadFactory(threadFactory);
362
363 threadManager->start();
364
Mark Slee018b6992006-09-07 21:31:12 +0000365 TThreadPoolServer threadPoolServer(testProcessor,
Marc Slemko6be374b2006-08-04 03:16:25 +0000366 serverSocket,
Mark Sleed788b2e2006-09-07 01:26:35 +0000367 transportFactory,
Mark Sleea3302652006-10-25 19:03:32 +0000368 protocolFactory,
369 threadManager);
Marc Slemko6be374b2006-08-04 03:16:25 +0000370
371 printf("Starting the server on port %d...\n", port);
Mark Slee794993d2006-09-20 01:56:10 +0000372 threadPoolServer.serve();
Mark Sleeb9acf982006-10-10 01:57:32 +0000373
374 } else if (serverType == "nonblocking") {
375
Mark Sleea3302652006-10-25 19:03:32 +0000376 TNonblockingServer nonblockingServer(testProcessor, port);
377 nonblockingServer.setFrameResponses(frameOutput);
378 if (frameOutput) {
379 printf("Using framed output mode\n");
380 } else {
381 printf("Using non-framed output mode\n");
382 }
383
Mark Sleeb9acf982006-10-10 01:57:32 +0000384 printf("Starting the nonblocking server on port %d...\n", port);
385 nonblockingServer.serve();
386
Marc Slemko6be374b2006-08-04 03:16:25 +0000387 }
388
Mark Sleee8540632006-05-30 09:24:40 +0000389 printf("done.\n");
390 return 0;
391}