]> git.proxmox.com Git - ceph.git/blame - ceph/src/jaegertracing/thrift/lib/d/test/thrift_test_server.d
buildsys: switch source download to quincy
[ceph.git] / ceph / src / jaegertracing / thrift / lib / d / test / thrift_test_server.d
CommitLineData
f67539c2
TL
1/*
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
20module thrift_test_server;
21
22import core.stdc.errno : errno;
23import core.stdc.signal : signal, SIGINT, SIG_DFL, SIG_ERR;
24import core.thread : dur, Thread;
25import std.algorithm;
26import std.exception : enforce;
27import std.getopt;
28import std.parallelism : totalCPUs;
29import std.string;
30import std.stdio;
31import std.typetuple : TypeTuple, staticMap;
32import thrift.base;
33import thrift.codegen.processor;
34import thrift.protocol.base;
35import thrift.protocol.binary;
36import thrift.protocol.compact;
37import thrift.protocol.json;
38import thrift.server.base;
39import thrift.server.transport.socket;
40import thrift.server.transport.ssl;
41import thrift.transport.base;
42import thrift.transport.buffered;
43import thrift.transport.framed;
44import thrift.transport.http;
45import thrift.transport.ssl;
46import thrift.util.cancellation;
47import thrift.util.hashset;
48import test_utils;
49
50import thrift_test_common;
51import thrift.test.ThriftTest_types;
52import thrift.test.ThriftTest;
53
54class TestHandler : ThriftTest {
55 this(bool trace) {
56 trace_ = trace;
57 }
58
59 override void testVoid() {
60 if (trace_) writeln("testVoid()");
61 }
62
63 override string testString(string thing) {
64 if (trace_) writefln("testString(\"%s\")", thing);
65 return thing;
66 }
67
68 override byte testByte(byte thing) {
69 if (trace_) writefln("testByte(%s)", thing);
70 return thing;
71 }
72
73 override int testI32(int thing) {
74 if (trace_) writefln("testI32(%s)", thing);
75 return thing;
76 }
77
78 override long testI64(long thing) {
79 if (trace_) writefln("testI64(%s)", thing);
80 return thing;
81 }
82
83 override double testDouble(double thing) {
84 if (trace_) writefln("testDouble(%s)", thing);
85 return thing;
86 }
87
88 override string testBinary(string thing) {
89 if (trace_) writefln("testBinary(\"%s\")", thing);
90 return thing;
91 }
92
93 override bool testBool(bool thing) {
94 if (trace_) writefln("testBool(\"%s\")", thing);
95 return thing;
96 }
97
98 override Xtruct testStruct(ref const(Xtruct) thing) {
99 if (trace_) writefln("testStruct({\"%s\", %s, %s, %s})",
100 thing.string_thing, thing.byte_thing, thing.i32_thing, thing.i64_thing);
101 return thing;
102 }
103
104 override Xtruct2 testNest(ref const(Xtruct2) nest) {
105 auto thing = nest.struct_thing;
106 if (trace_) writefln("testNest({%s, {\"%s\", %s, %s, %s}, %s})",
107 nest.byte_thing, thing.string_thing, thing.byte_thing, thing.i32_thing,
108 thing.i64_thing, nest.i32_thing);
109 return nest;
110 }
111
112 override int[int] testMap(int[int] thing) {
113 if (trace_) writefln("testMap({%s})", thing);
114 return thing;
115 }
116
117 override HashSet!int testSet(HashSet!int thing) {
118 if (trace_) writefln("testSet({%s})",
119 join(map!`to!string(a)`(thing[]), ", "));
120 return thing;
121 }
122
123 override int[] testList(int[] thing) {
124 if (trace_) writefln("testList(%s)", thing);
125 return thing;
126 }
127
128 override Numberz testEnum(Numberz thing) {
129 if (trace_) writefln("testEnum(%s)", thing);
130 return thing;
131 }
132
133 override UserId testTypedef(UserId thing) {
134 if (trace_) writefln("testTypedef(%s)", thing);
135 return thing;
136 }
137
138 override string[string] testStringMap(string[string] thing) {
139 if (trace_) writefln("testStringMap(%s)", thing);
140 return thing;
141 }
142
143 override int[int][int] testMapMap(int hello) {
144 if (trace_) writefln("testMapMap(%s)", hello);
145 return testMapMapReturn;
146 }
147
148 override Insanity[Numberz][UserId] testInsanity(ref const(Insanity) argument) {
149 if (trace_) writeln("testInsanity()");
150 Insanity[Numberz][UserId] ret;
151 Insanity[Numberz] m1;
152 Insanity[Numberz] m2;
153 Insanity tmp;
154 tmp = cast(Insanity)argument;
155 m1[Numberz.TWO] = tmp;
156 m1[Numberz.THREE] = tmp;
157 m2[Numberz.SIX] = Insanity();
158 ret[1] = m1;
159 ret[2] = m2;
160 return ret;
161 }
162
163 override Xtruct testMulti(byte arg0, int arg1, long arg2, string[short] arg3,
164 Numberz arg4, UserId arg5)
165 {
166 if (trace_) writeln("testMulti()");
167 return Xtruct("Hello2", arg0, arg1, arg2);
168 }
169
170 override void testException(string arg) {
171 if (trace_) writefln("testException(%s)", arg);
172 if (arg == "Xception") {
173 auto e = new Xception();
174 e.errorCode = 1001;
175 e.message = arg;
176 throw e;
177 } else if (arg == "TException") {
178 throw new TException();
179 } else if (arg == "ApplicationException") {
180 throw new TException();
181 }
182 }
183
184 override Xtruct testMultiException(string arg0, string arg1) {
185 if (trace_) writefln("testMultiException(%s, %s)", arg0, arg1);
186
187 if (arg0 == "Xception") {
188 auto e = new Xception();
189 e.errorCode = 1001;
190 e.message = "This is an Xception";
191 throw e;
192 } else if (arg0 == "Xception2") {
193 auto e = new Xception2();
194 e.errorCode = 2002;
195 e.struct_thing.string_thing = "This is an Xception2";
196 throw e;
197 } else {
198 return Xtruct(arg1);
199 }
200 }
201
202 override void testOneway(int sleepFor) {
203 if (trace_) writefln("testOneway(%s): Sleeping...", sleepFor);
204 Thread.sleep(dur!"seconds"(sleepFor));
205 if (trace_) writefln("testOneway(%s): done sleeping!", sleepFor);
206 }
207
208private:
209 bool trace_;
210}
211
212shared(bool) gShutdown = false;
213
214nothrow @nogc extern(C) void handleSignal(int sig) {
215 gShutdown = true;
216}
217
218// Runs a thread that waits for shutdown to be
219// signaled and then triggers cancellation,
220// causing the server to stop. While we could
221// use a signalfd for this purpose, we are instead
222// opting for a busy waiting scheme for maximum
223// portability since signalfd is a linux thing.
224
225class ShutdownThread : Thread {
226 this(TCancellationOrigin cancellation) {
227 cancellation_ = cancellation;
228 super(&run);
229 }
230
231private:
232 void run() {
233 while (!gShutdown) {
234 Thread.sleep(dur!("msecs")(25));
235 }
236 cancellation_.trigger();
237 }
238
239 TCancellationOrigin cancellation_;
240}
241
242void main(string[] args) {
243 ushort port = 9090;
244 ServerType serverType;
245 ProtocolType protocolType;
246 size_t numIOThreads = 1;
247 TransportType transportType;
248 bool ssl = false;
249 bool trace = true;
250 size_t taskPoolSize = totalCPUs;
251
252 getopt(args, "port", &port, "protocol", &protocolType, "server-type",
253 &serverType, "ssl", &ssl, "num-io-threads", &numIOThreads,
254 "task-pool-size", &taskPoolSize, "trace", &trace,
255 "transport", &transportType);
256
257 if (serverType == ServerType.nonblocking ||
258 serverType == ServerType.pooledNonblocking
259 ) {
260 enforce(transportType == TransportType.framed,
261 "Need to use framed transport with non-blocking server.");
262 enforce(!ssl, "The non-blocking server does not support SSL yet.");
263
264 // Don't wrap the contents into another layer of framing.
265 transportType = TransportType.raw;
266 }
267
268 version (ThriftTestTemplates) {
269 // Only exercise the specialized template code paths if explicitly enabled
270 // to reduce memory consumption on regular test suite runs – there should
271 // not be much that can go wrong with that specifically anyway.
272 alias TypeTuple!(TBufferedTransport, TFramedTransport, TServerHttpTransport)
273 AvailableTransports;
274 alias TypeTuple!(
275 staticMap!(TBinaryProtocol, AvailableTransports),
276 staticMap!(TCompactProtocol, AvailableTransports)
277 ) AvailableProtocols;
278 } else {
279 alias TypeTuple!() AvailableTransports;
280 alias TypeTuple!() AvailableProtocols;
281 }
282
283 TProtocolFactory protocolFactory;
284 final switch (protocolType) {
285 case ProtocolType.binary:
286 protocolFactory = new TBinaryProtocolFactory!AvailableTransports;
287 break;
288 case ProtocolType.compact:
289 protocolFactory = new TCompactProtocolFactory!AvailableTransports;
290 break;
291 case ProtocolType.json:
292 protocolFactory = new TJsonProtocolFactory!AvailableTransports;
293 break;
294 }
295
296 auto processor = new TServiceProcessor!(ThriftTest, AvailableProtocols)(
297 new TestHandler(trace));
298
299 TServerSocket serverSocket;
300 if (ssl) {
301 auto sslContext = new TSSLContext();
302 sslContext.serverSide = true;
303 sslContext.loadCertificate("../../../test/keys/server.crt");
304 sslContext.loadPrivateKey("../../../test/keys/server.key");
305 sslContext.ciphers = "ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH";
306 serverSocket = new TSSLServerSocket(port, sslContext);
307 } else {
308 serverSocket = new TServerSocket(port);
309 }
310
311 auto transportFactory = createTransportFactory(transportType);
312
313 auto server = createServer(serverType, numIOThreads, taskPoolSize,
314 processor, serverSocket, transportFactory, protocolFactory);
315
316 // Set up SIGINT signal handling
317 enforce(signal(SIGINT, &handleSignal) != SIG_ERR,
318 "Could not replace the SIGINT signal handler: errno {0}".format(errno()));
319
320 // Set up a server cancellation trigger
321 auto cancel = new TCancellationOrigin();
322
323 // Set up a listener for the shutdown condition - this will
324 // wake up when the signal occurs and trigger cancellation.
325 auto shutdown = new ShutdownThread(cancel);
326 shutdown.start();
327
328 // Serve from this thread; the signal will stop the server
329 // and control will return here
330 writefln("Starting %s/%s %s ThriftTest server %son port %s...", protocolType,
331 transportType, serverType, ssl ? "(using SSL) ": "", port);
332 server.serve(cancel);
333 shutdown.join();
334 signal(SIGINT, SIG_DFL);
335
336 writeln("done.");
337}