gorealis v2 refactor (#5)

* Changing default timeout for start maintenance.

* Upgrading dependencies to gorealis v2 and thrift  0.12.0

* Refactored to update to gorealis v2.
This commit is contained in:
Renan DelValle 2018-12-27 11:31:51 -08:00 committed by GitHub
parent ad4dd9606e
commit 6ab5c9334d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
1335 changed files with 137431 additions and 61530 deletions

View file

@ -177,7 +177,7 @@ unittest/.directory:
touch $@
unittest/debug/%: src/%.d $(all_targets) unittest/emptymain.d
$(DMD) -gc -of$(subst /,$(DMD_OF_DIRSEP),$@) $(d_test_flags) $^
$(DMD) -g -of$(subst /,$(DMD_OF_DIRSEP),$@) $(d_test_flags) $^
unittest/release/%: src/%.d $(all_targets) unittest/emptymain.d
$(DMD) -O -release -of$(subst /,$(DMD_OF_DIRSEP),$@) $(d_test_flags) $^

View file

@ -18,6 +18,7 @@
*/
module thrift.async.socket;
import core.stdc.errno: ECONNRESET;
import core.thread : Fiber;
import core.time : dur, Duration;
import std.array : empty;

View file

@ -50,7 +50,7 @@ class TCompoundOperationException : TException {
/// The Thrift version string, used for informative purposes.
// Note: This is currently hardcoded, but will likely be filled in by the build
// system in future versions.
enum VERSION = "0.10.0";
enum VERSION = "0.12.0";
/**
* Functions used for logging inside Thrift.

View file

@ -73,7 +73,7 @@ private {
void setError(Exception e) nothrow {
ERR_put_error(ERR_LIB_D_EXCEPTION, ERR_F_D_EXCEPTION, ERR_R_D_EXCEPTION,
ERR_FILE_D_EXCEPTION, ERR_LINE_D_EXCEPTION);
try { GC.addRoot(cast(void*)e); } catch {}
try { GC.addRoot(cast(void*)e); } catch (Throwable) {}
ERR_set_error_data(cast(char*)e, ERR_FLAGS_D_EXCEPTION);
}

View file

@ -118,6 +118,38 @@ protected:
TTransportFactory outputTransportFactory_;
TProtocolFactory inputProtocolFactory_;
TProtocolFactory outputProtocolFactory_;
public:
@property TProcessorFactory processorFactory()
{
return processorFactory_;
}
@property TServerTransport serverTransport()
{
return serverTransport_;
}
@property TTransportFactory inputTransportFactory()
{
return inputTransportFactory_;
}
@property TTransportFactory outputTransportFactory()
{
return outputTransportFactory_;
}
@property TProtocolFactory inputProtocolFactory()
{
return inputProtocolFactory_;
}
@property TProtocolFactory outputProtocolFactory()
{
return outputProtocolFactory_;
}
}
/**

View file

@ -893,14 +893,14 @@ private {
callsSinceResize_ = 0;
factoryInputTransport_ =
server_.inputTransportFactory_.getTransport(inputTransport_);
server_.inputTransportFactory.getTransport(inputTransport_);
factoryOutputTransport_ =
server_.outputTransportFactory_.getTransport(outputTransport_);
server_.outputTransportFactory.getTransport(outputTransport_);
inputProtocol_ =
server_.inputProtocolFactory_.getProtocol(factoryInputTransport_);
server_.inputProtocolFactory.getProtocol(factoryInputTransport_);
outputProtocol_ =
server_.outputProtocolFactory_.getProtocol(factoryOutputTransport_);
server_.outputProtocolFactory.getProtocol(factoryOutputTransport_);
if (server_.eventHandler) {
connectionContext_ =
@ -908,7 +908,7 @@ private {
}
auto info = TConnectionInfo(inputProtocol_, outputProtocol_, socket_);
processor_ = server_.processorFactory_.getProcessor(info);
processor_ = server_.processorFactory.getProcessor(info);
}
~this() {

View file

@ -140,7 +140,9 @@ class TSimpleServer : TServer {
}
}
} catch (TTransportException ttx) {
logError("Client died: %s", ttx);
if (ttx.type() != TTransportException.Type.END_OF_FILE) {
logError("Client died unexpectedly: %s", ttx);
}
} catch (Exception e) {
logError("Uncaught exception: %s", e);
}

View file

@ -268,7 +268,9 @@ protected:
}
}
} catch (TTransportException ttx) {
logError("Client died: %s", ttx);
if (ttx.type() != TTransportException.Type.END_OF_FILE) {
logError("Client died unexpectedly: %s", ttx);
}
} catch (Exception e) {
logError("Uncaught exception: %s", e);
}

View file

@ -173,7 +173,9 @@ private class WorkerThread : Thread {
}
}
} catch (TTransportException ttx) {
logError("Client died: %s", ttx);
if (ttx.type() != TTransportException.Type.END_OF_FILE) {
logError("Client died unexpectedly: %s", ttx);
}
} catch (Exception e) {
logError("Uncaught exception: %s", e);
}

View file

@ -95,16 +95,7 @@ class TServerTransportException : TException {
///
this(Type type, string file = __FILE__, size_t line = __LINE__, Throwable next = null) {
string msg = "TTransportException: ";
switch (type) {
case Type.UNKNOWN: msg ~= "Unknown server transport exception"; break;
case Type.NOT_LISTENING: msg ~= "Server transport not listening"; break;
case Type.ALREADY_LISTENING: msg ~= "Server transport already listening"; break;
case Type.RESOURCE_FAILED: msg ~= "An underlying resource failed"; break;
default: msg ~= "(Invalid exception type)"; break;
}
this(msg, type, file, line, next);
this(errorMsg(type), type, file, line, next);
}
///
@ -129,5 +120,18 @@ class TServerTransportException : TException {
protected:
Type type_;
private:
string errorMsg(Type type) {
string msg = "TTransportException: ";
switch (type) {
case Type.UNKNOWN: msg ~= "Unknown server transport exception"; break;
case Type.NOT_LISTENING: msg ~= "Server transport not listening"; break;
case Type.ALREADY_LISTENING: msg ~= "Server transport already listening"; break;
case Type.RESOURCE_FAILED: msg ~= "An underlying resource failed"; break;
default: msg ~= "(Invalid exception type)"; break;
}
return msg;
}
}

View file

@ -37,7 +37,8 @@ import std.array : empty;
import std.algorithm : min, max;
import std.concurrency;
import std.conv : to;
import std.datetime : AutoStart, dur, Duration, StopWatch;
import std.datetime : dur, Duration;
import std.datetime.stopwatch : AutoStart, StopWatch;
import std.exception;
import std.stdio : File;
import thrift.base;
@ -637,7 +638,7 @@ final class TFileWriterTransport : TBaseTransport {
override void close() {
if (!isOpen) return;
prioritySend(writerThread_, ShutdownMessage(), thisTid); // FIXME: Should use normal send here.
send(writerThread_, ShutdownMessage(), thisTid);
receive((ShutdownMessage msg, Tid tid){});
isOpen_ = false;
}
@ -1076,15 +1077,15 @@ unittest {
// If any attempt takes more than 500ms, treat that as a fatal failure to
// avoid looping over a potentially very slow operation.
enforce(sw.peek().msecs < 1500,
text("close() took ", sw.peek().msecs, "ms."));
enforce(sw.peek().total!"msecs" < 1500,
text("close() took ", sw.peek().total!"msecs", "ms."));
// Normally, it takes less than 5ms on my dev box.
// However, if the box is heavily loaded, some of the test runs can take
// longer. Additionally, on a Windows Server 2008 instance running in
// a VirtualBox VM, it has been observed that about a quarter of the runs
// takes (217 ± 1) ms, for reasons not yet known.
if (sw.peek().msecs > 50) {
if (sw.peek().total!"msecs" > 50) {
++numOver;
}

View file

@ -330,7 +330,7 @@ protected:
"Host: " ~ host_ ~ "\r\n" ~
"Content-Type: application/x-thrift\r\n" ~
"Content-Length: " ~ to!string(dataLength) ~ "\r\n" ~
"Accept: application/x-thrift\r\n"
"Accept: application/x-thrift\r\n" ~
"User-Agent: Thrift/" ~ VERSION ~ " (D/TClientHttpTransport)\r\n" ~
"\r\n";
}

View file

@ -18,6 +18,7 @@
*/
module thrift.transport.socket;
import core.stdc.errno: ECONNRESET;
import core.thread : Thread;
import core.time : dur, Duration;
import std.array : empty;
@ -79,8 +80,8 @@ abstract class TSocketBase : TBaseTransport {
version (none) assert(written <= buf.length, text("Implementation wrote " ~
"more data than requested to?! (", written, " vs. ", buf.length, ")"));
} body {
assert(0, "DMD bug? Why would contracts work for interfaces, but not "
"for abstract methods? "
assert(0, "DMD bug? Why would contracts work for interfaces, but not " ~
"for abstract methods? " ~
"(Error: function […] in and out contracts require function body");
}
@ -256,7 +257,7 @@ class TSocket : TSocketBase {
new TCompoundOperationException(
text(
"All addresses tried failed (",
joiner(map!q{text(a._0, `: "`, a._1.msg, `"`)}(zip(addrs, errors)), ", "),
joiner(map!q{text(a[0], `: "`, a[1].msg, `"`)}(zip(addrs, errors)), ", "),
")."
),
errors

View file

@ -249,7 +249,13 @@ class TSSLContext {
}
count_++;
ctx_ = SSL_CTX_new(TLSv1_method());
static if (OPENSSL_VERSION_NUMBER >= 0x1010000f) { // OPENSSL_VERSION_AT_LEAST(1, 1)) {
ctx_ = SSL_CTX_new(TLS_method());
} else {
ctx_ = SSL_CTX_new(SSLv23_method());
SSL_CTX_set_options(ctx_, SSL_OP_NO_SSLv2);
}
SSL_CTX_set_options(ctx_, SSL_OP_NO_SSLv3); // THRIFT-3164
enforce(ctx_, getSSLException("SSL_CTX_new"));
SSL_CTX_set_mode(ctx_, SSL_MODE_AUTO_RETRY);
}
@ -446,6 +452,7 @@ private:
}
initialized_ = true;
static if (OPENSSL_VERSION_NUMBER < 0x1010000f) { // OPENSSL_VERSION_BEFORE(1, 1)) {
SSL_library_init();
SSL_load_error_strings();
@ -463,12 +470,14 @@ private:
CRYPTO_set_dynlock_create_callback(assumeNothrow(&dynlockCreateCallback));
CRYPTO_set_dynlock_lock_callback(assumeNothrow(&dynlockLockCallback));
CRYPTO_set_dynlock_destroy_callback(assumeNothrow(&dynlockDestroyCallback));
}
}
static void cleanupOpenSSL() {
if (!initialized_) return;
initialized_ = false;
static if (OPENSSL_VERSION_NUMBER < 0x1010000f) { // OPENSSL_VERSION_BEFORE(1, 1)) {
CRYPTO_set_locking_callback(null);
CRYPTO_set_dynlock_create_callback(null);
CRYPTO_set_dynlock_lock_callback(null);
@ -476,6 +485,7 @@ private:
CRYPTO_cleanup_all_ex_data();
ERR_free_strings();
ERR_remove_state(0);
}
}
static extern(C) {

View file

@ -24,8 +24,6 @@ BUILT_SOURCES = trusted-ca-certificate.pem server-certificate.pem
# Thrift compiler rules
THRIFT = $(top_builddir)/compiler/cpp/thrift
debug_proto_gen = $(addprefix gen-d/, DebugProtoTest_types.d)
$(debug_proto_gen): $(top_srcdir)/test/DebugProtoTest.thrift

View file

@ -18,6 +18,7 @@
*/
module client_pool_test;
import core.sync.semaphore : Semaphore;
import core.time : Duration, dur;
import core.thread : Thread;
import std.algorithm;
@ -28,6 +29,7 @@ import std.getopt;
import std.range;
import std.stdio;
import std.typecons;
import std.variant : Variant;
import thrift.base;
import thrift.async.libevent;
import thrift.async.socket;
@ -37,9 +39,12 @@ import thrift.codegen.async_client_pool;
import thrift.codegen.client;
import thrift.codegen.client_pool;
import thrift.codegen.processor;
import thrift.protocol.base;
import thrift.protocol.binary;
import thrift.server.base;
import thrift.server.simple;
import thrift.server.transport.socket;
import thrift.transport.base;
import thrift.transport.buffered;
import thrift.transport.socket;
import thrift.util.cancellation;
@ -108,11 +113,29 @@ private:
}
}
class ServerPreServeHandler : TServerEventHandler {
this(Semaphore sem) {
sem_ = sem;
}
override void preServe() {
sem_.notify();
}
Variant createContext(TProtocol input, TProtocol output) { return Variant.init; }
void deleteContext(Variant serverContext, TProtocol input, TProtocol output) {}
void preProcess(Variant serverContext, TTransport transport) {}
private:
Semaphore sem_;
}
class ServerThread : Thread {
this(ExTestHandler handler, TCancellation cancellation) {
this(ExTestHandler handler, ServerPreServeHandler serverHandler, TCancellation cancellation) {
super(&run);
handler_ = handler;
cancellation_ = cancellation;
serverHandler_ = serverHandler;
}
private:
void run() {
@ -123,16 +146,17 @@ private:
serverTransport.recvTimeout = dur!"seconds"(3);
auto transportFactory = new TBufferedTransportFactory;
auto server = new TSimpleServer(
processor, serverTransport, transportFactory, protocolFactory);
auto server = new TSimpleServer(processor, serverTransport, transportFactory, protocolFactory);
server.eventHandler = serverHandler_;
server.serve(cancellation_);
} catch (Exception e) {
writefln("Server thread on port %s failed: %s", handler_.port, e);
}
}
TCancellation cancellation_;
ExTestHandler handler_;
ServerPreServeHandler serverHandler_;
TCancellation cancellation_;
}
void main(string[] args) {
@ -145,6 +169,9 @@ void main(string[] args) {
immutable ports = cast(immutable)array(map!"cast(ushort)a"(iota(port, port + 6)));
// semaphore that will be incremented whenever each server thread has bound and started listening
Semaphore sem = new Semaphore(0);
version (none) {
// Cannot use this due to multiple DMD @@BUG@@s:
// 1. »function D main is a nested function and cannot be accessed from array«
@ -174,11 +201,10 @@ version (none) {
}
// Fire up the server threads.
foreach (h; handlers) (new ServerThread(h, serverCancellation)).start();
foreach (h; handlers) (new ServerThread(h, new ServerPreServeHandler(sem), serverCancellation)).start();
// Give the servers some time to get up. This should really be accomplished
// via a barrier here and in the preServe() hook.
Thread.sleep(dur!"msecs"(10));
// wait until all the handlers signal that they're ready to serve
foreach (h; handlers) (sem.wait(dur!`seconds`(1)));
syncClientPoolTest(ports, handlers);
asyncClientPoolTest(ports, handlers);
@ -409,8 +435,8 @@ void asyncAggregatorTest(const(ushort)[] ports, ExTestHandler[] handlers) {
)();
Thread.sleep(dur!"msecs"(20));
auto resultTuple = partialResult.finishGet();
enforce(resultTuple._0 == ports[0 .. 2]);
enforce(equal(map!"a.port"(cast(TestServiceException[])resultTuple._1),
enforce(resultTuple[0] == ports[0 .. 2]);
enforce(equal(map!"a.port"(cast(TestServiceException[])resultTuple[1]),
ports[3 .. $ - 1]));
}
}

View file

@ -13,7 +13,7 @@
*/
module serialization_benchmark;
import std.datetime : AutoStart, StopWatch;
import std.datetime.stopwatch : AutoStart, StopWatch;
import std.math : PI;
import std.stdio;
import thrift.protocol.binary;
@ -46,7 +46,7 @@ void main() {
}
sw.stop();
auto msecs = sw.peek().msecs;
auto msecs = sw.peek().total!"msecs";
writefln("Write: %s ms (%s kHz)", msecs, ITERATIONS / msecs);
}
@ -64,7 +64,7 @@ void main() {
}
sw.stop();
auto msecs = sw.peek().msecs;
auto msecs = sw.peek().total!"msecs";
writefln(" Read: %s ms (%s kHz)", msecs, ITERATIONS / msecs);
}
}

View file

@ -16,8 +16,11 @@
* specific language governing permissions and limitations
* under the License.
*/
module thrift_test_server;
import core.stdc.errno : errno;
import core.stdc.signal : signal, sigfn_t, SIGINT, SIG_DFL, SIG_ERR;
import core.thread : dur, Thread;
import std.algorithm;
import std.exception : enforce;
@ -40,6 +43,7 @@ import thrift.transport.buffered;
import thrift.transport.framed;
import thrift.transport.http;
import thrift.transport.ssl;
import thrift.util.cancellation;
import thrift.util.hashset;
import test_utils;
@ -205,14 +209,44 @@ private:
bool trace_;
}
shared(bool) gShutdown = false;
nothrow @nogc extern(C) void handleSignal(int sig) {
gShutdown = true;
}
// Runs a thread that waits for shutdown to be
// signaled and then triggers cancellation,
// causing the server to stop. While we could
// use a signalfd for this purpose, we are instead
// opting for a busy waiting scheme for maximum
// portability since signalfd is a linux thing.
class ShutdownThread : Thread {
this(TCancellationOrigin cancellation) {
cancellation_ = cancellation;
super(&run);
}
private:
void run() {
while (!gShutdown) {
Thread.sleep(dur!("msecs")(25));
}
cancellation_.trigger();
}
TCancellationOrigin cancellation_;
}
void main(string[] args) {
ushort port = 9090;
ServerType serverType;
ProtocolType protocolType;
size_t numIOThreads = 1;
TransportType transportType;
bool ssl;
bool trace;
bool ssl = false;
bool trace = true;
size_t taskPoolSize = totalCPUs;
getopt(args, "port", &port, "protocol", &protocolType, "server-type",
@ -279,8 +313,26 @@ void main(string[] args) {
auto server = createServer(serverType, numIOThreads, taskPoolSize,
processor, serverSocket, transportFactory, protocolFactory);
// Set up SIGINT signal handling
sigfn_t oldHandler = signal(SIGINT, &handleSignal);
enforce(oldHandler != SIG_ERR,
"Could not replace the SIGINT signal handler: errno {0}".format(errno()));
// Set up a server cancellation trigger
auto cancel = new TCancellationOrigin();
// Set up a listener for the shutdown condition - this will
// wake up when the signal occurs and trigger cancellation.
auto shutdown = new ShutdownThread(cancel);
shutdown.start();
// Serve from this thread; the signal will stop the server
// and control will return here
writefln("Starting %s/%s %s ThriftTest server %son port %s...", protocolType,
transportType, serverType, ssl ? "(using SSL) ": "", port);
server.serve();
server.serve(cancel);
shutdown.join();
signal(SIGINT, SIG_DFL);
writeln("done.");
}