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

@ -33,8 +33,8 @@ namespace thrift {
template <class Protocol_>
class TDispatchProcessorT : public TProcessor {
public:
virtual bool process(boost::shared_ptr<protocol::TProtocol> in,
boost::shared_ptr<protocol::TProtocol> out,
virtual bool process(stdcxx::shared_ptr<protocol::TProtocol> in,
stdcxx::shared_ptr<protocol::TProtocol> out,
void* connectionContext) {
protocol::TProtocol* inRaw = in.get();
protocol::TProtocol* outRaw = out.get();
@ -105,8 +105,8 @@ protected:
*/
class TDispatchProcessor : public TProcessor {
public:
virtual bool process(boost::shared_ptr<protocol::TProtocol> in,
boost::shared_ptr<protocol::TProtocol> out,
virtual bool process(stdcxx::shared_ptr<protocol::TProtocol> in,
stdcxx::shared_ptr<protocol::TProtocol> out,
void* connectionContext) {
std::string fname;
protocol::TMessageType mtype;

View file

@ -18,9 +18,9 @@
*/
#include <thrift/Thrift.h>
#include <thrift/TToString.h>
#include <cstring>
#include <cstdlib>
#include <boost/lexical_cast.hpp>
#include <stdarg.h>
#include <stdio.h>
@ -94,13 +94,13 @@ void TOutput::errorTimeWrapper(const char* msg) {
}
void TOutput::perror(const char* message, int errno_copy) {
std::string out = message + strerror_s(errno_copy);
std::string out = message + std::string(": ") + strerror_s(errno_copy);
f_(out.c_str());
}
std::string TOutput::strerror_s(int errno_copy) {
#ifndef HAVE_STRERROR_R
return "errno = " + boost::lexical_cast<std::string>(errno_copy);
return "errno = " + to_string(errno_copy);
#else // HAVE_STRERROR_R
char b_errbuf[1024] = {'\0'};
@ -112,7 +112,7 @@ std::string TOutput::strerror_s(int errno_copy) {
if (rv == -1) {
// strerror_r failed. omgwtfbbq.
return "XSI-compliant strerror_r() failed with errno = "
+ boost::lexical_cast<std::string>(errno_copy);
+ to_string(errno_copy);
}
#endif
// Can anyone prove that explicit cast is probably not necessary

View file

@ -22,7 +22,7 @@
#include <string>
#include <thrift/protocol/TProtocol.h>
#include <boost/shared_ptr.hpp>
#include <thrift/stdcxx.h>
namespace apache {
namespace thrift {
@ -142,28 +142,28 @@ class TProcessor {
public:
virtual ~TProcessor() {}
virtual bool process(boost::shared_ptr<protocol::TProtocol> in,
boost::shared_ptr<protocol::TProtocol> out,
virtual bool process(stdcxx::shared_ptr<protocol::TProtocol> in,
stdcxx::shared_ptr<protocol::TProtocol> out,
void* connectionContext) = 0;
bool process(boost::shared_ptr<apache::thrift::protocol::TProtocol> io, void* connectionContext) {
bool process(stdcxx::shared_ptr<apache::thrift::protocol::TProtocol> io, void* connectionContext) {
return process(io, io, connectionContext);
}
boost::shared_ptr<TProcessorEventHandler> getEventHandler() const { return eventHandler_; }
stdcxx::shared_ptr<TProcessorEventHandler> getEventHandler() const { return eventHandler_; }
void setEventHandler(boost::shared_ptr<TProcessorEventHandler> eventHandler) {
void setEventHandler(stdcxx::shared_ptr<TProcessorEventHandler> eventHandler) {
eventHandler_ = eventHandler;
}
protected:
TProcessor() {}
boost::shared_ptr<TProcessorEventHandler> eventHandler_;
stdcxx::shared_ptr<TProcessorEventHandler> eventHandler_;
};
/**
* This is a helper class to allow boost::shared_ptr to be used with handler
* This is a helper class to allow stdcxx::shared_ptr to be used with handler
* pointers returned by the generated handler factories.
*
* The handler factory classes generated by the thrift compiler return raw
@ -177,7 +177,7 @@ protected:
template <typename HandlerFactory_>
class ReleaseHandler {
public:
ReleaseHandler(const boost::shared_ptr<HandlerFactory_>& handlerFactory)
ReleaseHandler(const stdcxx::shared_ptr<HandlerFactory_>& handlerFactory)
: handlerFactory_(handlerFactory) {}
void operator()(typename HandlerFactory_::Handler* handler) {
@ -187,18 +187,18 @@ public:
}
private:
boost::shared_ptr<HandlerFactory_> handlerFactory_;
stdcxx::shared_ptr<HandlerFactory_> handlerFactory_;
};
struct TConnectionInfo {
// The input and output protocols
boost::shared_ptr<protocol::TProtocol> input;
boost::shared_ptr<protocol::TProtocol> output;
stdcxx::shared_ptr<protocol::TProtocol> input;
stdcxx::shared_ptr<protocol::TProtocol> output;
// The underlying transport used for the connection
// This is the transport that was returned by TServerTransport::accept(),
// and it may be different than the transport pointed to by the input and
// output protocols.
boost::shared_ptr<transport::TTransport> transport;
stdcxx::shared_ptr<transport::TTransport> transport;
};
class TProcessorFactory {
@ -212,17 +212,17 @@ public:
* accepted on. This generally means that this call does not need to be
* thread safe, as it will always be invoked from a single thread.
*/
virtual boost::shared_ptr<TProcessor> getProcessor(const TConnectionInfo& connInfo) = 0;
virtual stdcxx::shared_ptr<TProcessor> getProcessor(const TConnectionInfo& connInfo) = 0;
};
class TSingletonProcessorFactory : public TProcessorFactory {
public:
TSingletonProcessorFactory(boost::shared_ptr<TProcessor> processor) : processor_(processor) {}
TSingletonProcessorFactory(stdcxx::shared_ptr<TProcessor> processor) : processor_(processor) {}
boost::shared_ptr<TProcessor> getProcessor(const TConnectionInfo&) { return processor_; }
stdcxx::shared_ptr<TProcessor> getProcessor(const TConnectionInfo&) { return processor_; }
private:
boost::shared_ptr<TProcessor> processor_;
stdcxx::shared_ptr<TProcessor> processor_;
};
}
} // apache::thrift

View file

@ -20,20 +20,45 @@
#ifndef _THRIFT_TOSTRING_H_
#define _THRIFT_TOSTRING_H_ 1
#include <boost/lexical_cast.hpp>
#include <vector>
#include <cmath>
#include <limits>
#include <map>
#include <set>
#include <string>
#include <sstream>
#include <string>
#include <vector>
namespace apache {
namespace thrift {
template <typename T>
std::string to_string(const T& t) {
return boost::lexical_cast<std::string>(t);
std::ostringstream o;
o << t;
return o.str();
}
// TODO: replace the computations below with std::numeric_limits::max_digits10 once C++11
// is enabled.
inline std::string to_string(const float& t) {
std::ostringstream o;
o.precision(static_cast<std::streamsize>(std::ceil(static_cast<double>(std::numeric_limits<float>::digits * std::log10(2.0f) + 1))));
o << t;
return o.str();
}
inline std::string to_string(const double& t) {
std::ostringstream o;
o.precision(static_cast<std::streamsize>(std::ceil(static_cast<double>(std::numeric_limits<double>::digits * std::log10(2.0f) + 1))));
o << t;
return o.str();
}
inline std::string to_string(const long double& t) {
std::ostringstream o;
o.precision(static_cast<std::streamsize>(std::ceil(static_cast<double>(std::numeric_limits<long double>::digits * std::log10(2.0f) + 1))));
o << t;
return o.str();
}
template <typename K, typename V>

View file

@ -20,9 +20,7 @@
#ifndef _THRIFT_TASYNC_BUFFER_PROCESSOR_H_
#define _THRIFT_TASYNC_BUFFER_PROCESSOR_H_ 1
#include <thrift/cxxfunctional.h>
#include <boost/shared_ptr.hpp>
#include <thrift/stdcxx.h>
#include <thrift/transport/TBufferTransports.h>
namespace apache {
@ -36,9 +34,9 @@ public:
// forcefully close the connection (if applicable).
// "in" and "out" should be TMemoryBuffer or similar,
// not a wrapper around a socket.
virtual void process(apache::thrift::stdcxx::function<void(bool healthy)> _return,
boost::shared_ptr<apache::thrift::transport::TBufferBase> ibuf,
boost::shared_ptr<apache::thrift::transport::TBufferBase> obuf) = 0;
virtual void process(stdcxx::function<void(bool healthy)> _return,
stdcxx::shared_ptr<transport::TBufferBase> ibuf,
stdcxx::shared_ptr<transport::TBufferBase> obuf) = 0;
virtual ~TAsyncBufferProcessor() {}
};
}

View file

@ -18,7 +18,7 @@
*/
#include <thrift/async/TAsyncChannel.h>
#include <thrift/cxxfunctional.h>
#include <thrift/stdcxx.h>
namespace apache {
namespace thrift {

View file

@ -20,7 +20,7 @@
#ifndef _THRIFT_ASYNC_TASYNCCHANNEL_H_
#define _THRIFT_ASYNC_TASYNCCHANNEL_H_ 1
#include <thrift/cxxfunctional.h>
#include <thrift/stdcxx.h>
#include <thrift/Thrift.h>
namespace apache {

View file

@ -35,8 +35,8 @@ template <class Protocol_>
class TAsyncDispatchProcessorT : public TAsyncProcessor {
public:
virtual void process(apache::thrift::stdcxx::function<void(bool success)> _return,
boost::shared_ptr<protocol::TProtocol> in,
boost::shared_ptr<protocol::TProtocol> out) {
stdcxx::shared_ptr<protocol::TProtocol> in,
stdcxx::shared_ptr<protocol::TProtocol> out) {
protocol::TProtocol* inRaw = in.get();
protocol::TProtocol* outRaw = out.get();
@ -107,8 +107,8 @@ public:
class TAsyncDispatchProcessor : public TAsyncProcessor {
public:
virtual void process(apache::thrift::stdcxx::function<void(bool success)> _return,
boost::shared_ptr<protocol::TProtocol> in,
boost::shared_ptr<protocol::TProtocol> out) {
stdcxx::shared_ptr<protocol::TProtocol> in,
stdcxx::shared_ptr<protocol::TProtocol> out) {
protocol::TProtocol* inRaw = in.get();
protocol::TProtocol* outRaw = out.get();

View file

@ -20,9 +20,8 @@
#ifndef _THRIFT_TASYNCPROCESSOR_H_
#define _THRIFT_TASYNCPROCESSOR_H_ 1
#include <thrift/cxxfunctional.h>
#include <boost/shared_ptr.hpp>
#include <thrift/protocol/TProtocol.h>
#include <thrift/stdcxx.h>
#include <thrift/TProcessor.h>
namespace apache {
@ -38,25 +37,25 @@ class TAsyncProcessor {
public:
virtual ~TAsyncProcessor() {}
virtual void process(apache::thrift::stdcxx::function<void(bool success)> _return,
boost::shared_ptr<protocol::TProtocol> in,
boost::shared_ptr<protocol::TProtocol> out) = 0;
virtual void process(stdcxx::function<void(bool success)> _return,
stdcxx::shared_ptr<protocol::TProtocol> in,
stdcxx::shared_ptr<protocol::TProtocol> out) = 0;
void process(apache::thrift::stdcxx::function<void(bool success)> _return,
boost::shared_ptr<apache::thrift::protocol::TProtocol> io) {
void process(stdcxx::function<void(bool success)> _return,
stdcxx::shared_ptr<protocol::TProtocol> io) {
return process(_return, io, io);
}
boost::shared_ptr<TProcessorEventHandler> getEventHandler() const { return eventHandler_; }
stdcxx::shared_ptr<TProcessorEventHandler> getEventHandler() const { return eventHandler_; }
void setEventHandler(boost::shared_ptr<TProcessorEventHandler> eventHandler) {
void setEventHandler(stdcxx::shared_ptr<TProcessorEventHandler> eventHandler) {
eventHandler_ = eventHandler;
}
protected:
TAsyncProcessor() {}
boost::shared_ptr<TProcessorEventHandler> eventHandler_;
stdcxx::shared_ptr<TProcessorEventHandler> eventHandler_;
};
class TAsyncProcessorFactory {
@ -70,16 +69,15 @@ public:
* accepted on. This generally means that this call does not need to be
* thread safe, as it will always be invoked from a single thread.
*/
virtual boost::shared_ptr<TAsyncProcessor> getProcessor(const TConnectionInfo& connInfo) = 0;
virtual stdcxx::shared_ptr<TAsyncProcessor> getProcessor(const TConnectionInfo& connInfo) = 0;
};
}
}
} // apache::thrift::async
// XXX I'm lazy for now
namespace apache {
namespace thrift {
using apache::thrift::async::TAsyncProcessor;
using apache::thrift::async::TAsyncProcessor;
}
}

View file

@ -27,10 +27,10 @@ namespace thrift {
namespace async {
void TAsyncProtocolProcessor::process(apache::thrift::stdcxx::function<void(bool healthy)> _return,
boost::shared_ptr<TBufferBase> ibuf,
boost::shared_ptr<TBufferBase> obuf) {
boost::shared_ptr<TProtocol> iprot(pfact_->getProtocol(ibuf));
boost::shared_ptr<TProtocol> oprot(pfact_->getProtocol(obuf));
stdcxx::shared_ptr<TBufferBase> ibuf,
stdcxx::shared_ptr<TBufferBase> obuf) {
stdcxx::shared_ptr<TProtocol> iprot(pfact_->getProtocol(ibuf));
stdcxx::shared_ptr<TProtocol> oprot(pfact_->getProtocol(obuf));
return underlying_
->process(apache::thrift::stdcxx::bind(&TAsyncProtocolProcessor::finish,
_return,
@ -42,7 +42,7 @@ void TAsyncProtocolProcessor::process(apache::thrift::stdcxx::function<void(bool
/* static */ void TAsyncProtocolProcessor::finish(
apache::thrift::stdcxx::function<void(bool healthy)> _return,
boost::shared_ptr<TProtocol> oprot,
stdcxx::shared_ptr<TProtocol> oprot,
bool healthy) {
(void)oprot;
// This is a stub function to hold a reference to oprot.

View file

@ -30,23 +30,23 @@ namespace async {
class TAsyncProtocolProcessor : public TAsyncBufferProcessor {
public:
TAsyncProtocolProcessor(boost::shared_ptr<TAsyncProcessor> underlying,
boost::shared_ptr<apache::thrift::protocol::TProtocolFactory> pfact)
TAsyncProtocolProcessor(stdcxx::shared_ptr<TAsyncProcessor> underlying,
stdcxx::shared_ptr<apache::thrift::protocol::TProtocolFactory> pfact)
: underlying_(underlying), pfact_(pfact) {}
virtual void process(apache::thrift::stdcxx::function<void(bool healthy)> _return,
boost::shared_ptr<apache::thrift::transport::TBufferBase> ibuf,
boost::shared_ptr<apache::thrift::transport::TBufferBase> obuf);
stdcxx::shared_ptr<apache::thrift::transport::TBufferBase> ibuf,
stdcxx::shared_ptr<apache::thrift::transport::TBufferBase> obuf);
virtual ~TAsyncProtocolProcessor() {}
private:
static void finish(apache::thrift::stdcxx::function<void(bool healthy)> _return,
boost::shared_ptr<apache::thrift::protocol::TProtocol> oprot,
stdcxx::shared_ptr<apache::thrift::protocol::TProtocol> oprot,
bool healthy);
boost::shared_ptr<TAsyncProcessor> underlying_;
boost::shared_ptr<apache::thrift::protocol::TProtocolFactory> pfact_;
stdcxx::shared_ptr<TAsyncProcessor> underlying_;
stdcxx::shared_ptr<apache::thrift::protocol::TProtocolFactory> pfact_;
};
}
}

View file

@ -22,7 +22,7 @@
#include <thrift/protocol/TProtocol.h>
#include <thrift/concurrency/Mutex.h>
#include <thrift/concurrency/Monitor.h>
#include <boost/shared_ptr.hpp>
#include <thrift/stdcxx.h>
#include <vector>
#include <string>
#include <map>
@ -60,7 +60,7 @@ private:
class TConcurrentClientSyncInfo {
private: // typedefs
typedef boost::shared_ptr< ::apache::thrift::concurrency::Monitor> MonitorPtr;
typedef stdcxx::shared_ptr< ::apache::thrift::concurrency::Monitor> MonitorPtr;
typedef std::map<int32_t, MonitorPtr> MonitorMap;
public:

View file

@ -38,13 +38,14 @@ TEvhttpClientChannel::TEvhttpClientChannel(const std::string& host,
const std::string& path,
const char* address,
int port,
struct event_base* eb)
struct event_base* eb,
struct evdns_base* dnsbase)
: host_(host), path_(path), conn_(NULL) {
conn_ = evhttp_connection_new(address, port);
conn_ = evhttp_connection_base_new(eb, dnsbase, address, port);
if (conn_ == NULL) {
throw TException("evhttp_connection_new failed");
}
evhttp_connection_set_base(conn_, eb);
}
TEvhttpClientChannel::~TEvhttpClientChannel() {

View file

@ -23,10 +23,11 @@
#include <queue>
#include <string>
#include <utility>
#include <boost/shared_ptr.hpp>
#include <thrift/stdcxx.h>
#include <thrift/async/TAsyncChannel.h>
struct event_base;
struct evdns_base;
struct evhttp_connection;
struct evhttp_request;
@ -50,7 +51,8 @@ public:
const std::string& path,
const char* address,
int port,
struct event_base* eb);
struct event_base* eb,
struct evdns_base *dnsbase = 0);
~TEvhttpClientChannel();
virtual void sendAndRecvMessage(const VoidCallback& cob,

View file

@ -20,10 +20,10 @@
#include <thrift/async/TEvhttpServer.h>
#include <thrift/async/TAsyncBufferProcessor.h>
#include <thrift/transport/TBufferTransports.h>
#include <thrift/stdcxx.h>
#include <evhttp.h>
#include <event2/buffer.h>
#include <event2/buffer_compat.h>
#include <iostream>
#ifndef HTTP_INTERNAL // libevent < 2
@ -31,6 +31,8 @@
#endif
using apache::thrift::transport::TMemoryBuffer;
using apache::thrift::stdcxx::scoped_ptr;
using apache::thrift::stdcxx::shared_ptr;
namespace apache {
namespace thrift {
@ -38,17 +40,17 @@ namespace async {
struct TEvhttpServer::RequestContext {
struct evhttp_request* req;
boost::shared_ptr<apache::thrift::transport::TMemoryBuffer> ibuf;
boost::shared_ptr<apache::thrift::transport::TMemoryBuffer> obuf;
stdcxx::shared_ptr<apache::thrift::transport::TMemoryBuffer> ibuf;
stdcxx::shared_ptr<apache::thrift::transport::TMemoryBuffer> obuf;
RequestContext(struct evhttp_request* req);
};
TEvhttpServer::TEvhttpServer(boost::shared_ptr<TAsyncBufferProcessor> processor)
TEvhttpServer::TEvhttpServer(stdcxx::shared_ptr<TAsyncBufferProcessor> processor)
: processor_(processor), eb_(NULL), eh_(NULL) {
}
TEvhttpServer::TEvhttpServer(boost::shared_ptr<TAsyncBufferProcessor> processor, int port)
TEvhttpServer::TEvhttpServer(stdcxx::shared_ptr<TAsyncBufferProcessor> processor, int port)
: processor_(processor), eb_(NULL), eh_(NULL) {
// Create event_base and evhttp.
eb_ = event_base_new();
@ -118,7 +120,7 @@ void TEvhttpServer::process(struct evhttp_request* req) {
void TEvhttpServer::complete(RequestContext* ctx, bool success) {
(void)success;
std::auto_ptr<RequestContext> ptr(ctx);
scoped_ptr<RequestContext> ptr(ctx);
int code = success ? 200 : 400;
const char* reason = success ? "OK" : "Bad Request";

View file

@ -20,7 +20,7 @@
#ifndef _THRIFT_TEVHTTP_SERVER_H_
#define _THRIFT_TEVHTTP_SERVER_H_ 1
#include <boost/shared_ptr.hpp>
#include <thrift/stdcxx.h>
struct event_base;
struct evhttp;
@ -41,14 +41,14 @@ public:
* address of the server as the extra arg.
* Do not call "serve" on this server.
*/
TEvhttpServer(boost::shared_ptr<TAsyncBufferProcessor> processor);
TEvhttpServer(stdcxx::shared_ptr<TAsyncBufferProcessor> processor);
/**
* Create a TEvhttpServer with an embedded event_base and evhttp,
* listening on port and responding on the endpoint "/".
* Call "serve" on this server to serve forever.
*/
TEvhttpServer(boost::shared_ptr<TAsyncBufferProcessor> processor, int port);
TEvhttpServer(stdcxx::shared_ptr<TAsyncBufferProcessor> processor, int port);
~TEvhttpServer();
@ -63,7 +63,7 @@ private:
void process(struct evhttp_request* req);
void complete(RequestContext* ctx, bool success);
boost::shared_ptr<TAsyncBufferProcessor> processor_;
stdcxx::shared_ptr<TAsyncBufferProcessor> processor_;
struct event_base* eb_;
struct evhttp* eh_;
};

View file

@ -23,9 +23,9 @@
#include <thrift/concurrency/Exception.h>
#include <thrift/concurrency/Util.h>
#include <thrift/transport/PlatformSocket.h>
#include <assert.h>
#include <thrift/stdcxx.h>
#include <boost/scoped_ptr.hpp>
#include <assert.h>
#include <boost/thread.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
@ -155,7 +155,7 @@ public:
private:
void init(Mutex* mutex) { mutex_ = mutex; }
boost::scoped_ptr<Mutex> ownedMutex_;
stdcxx::scoped_ptr<Mutex> ownedMutex_;
Mutex* mutex_;
};

View file

@ -33,7 +33,9 @@ namespace thrift {
namespace concurrency {
/**
* Implementation of Mutex class using boost interprocess mutex
* Implementation of Mutex class using boost::timed_mutex
*
* Methods throw boost::lock_error on error.
*
* @version $Id:$
*/

View file

@ -23,18 +23,20 @@
#include <thrift/concurrency/BoostThreadFactory.h>
#include <thrift/concurrency/Exception.h>
#include <thrift/stdcxx.h>
#include <cassert>
#include <boost/weak_ptr.hpp>
#include <boost/thread.hpp>
namespace apache {
namespace thrift {
namespace concurrency {
using boost::shared_ptr;
using boost::weak_ptr;
using stdcxx::bind;
using stdcxx::scoped_ptr;
using stdcxx::shared_ptr;
using stdcxx::weak_ptr;
namespace concurrency {
/**
* The boost thread class.
@ -48,7 +50,8 @@ public:
static void* threadMain(void* arg);
private:
std::auto_ptr<boost::thread> thread_;
scoped_ptr<boost::thread> thread_;
Monitor monitor_;
STATE state_;
weak_ptr<BoostThread> self_;
bool detached_;
@ -60,7 +63,7 @@ public:
}
~BoostThread() {
if (!detached_) {
if (!detached_ && thread_->joinable()) {
try {
join();
} catch (...) {
@ -69,26 +72,46 @@ public:
}
}
void start() {
if (state_ != uninitialized) {
return;
}
STATE getState() const
{
Synchronized sync(monitor_);
return state_;
}
void setState(STATE newState)
{
Synchronized sync(monitor_);
state_ = newState;
// unblock start() with the knowledge that the thread has actually
// started running, which avoids a race in detached threads.
if (newState == started) {
monitor_.notify();
}
}
void start() {
// Create reference
shared_ptr<BoostThread>* selfRef = new shared_ptr<BoostThread>();
*selfRef = self_.lock();
state_ = starting;
setState(starting);
thread_
= std::auto_ptr<boost::thread>(new boost::thread(boost::bind(threadMain, (void*)selfRef)));
Synchronized sync(monitor_);
thread_.reset(new boost::thread(bind(threadMain, (void*)selfRef)));
if (detached_)
thread_->detach();
// Wait for the thread to start and get far enough to grab everything
// that it needs from the calling context, thus absolving the caller
// from being required to hold on to runnable indefinitely.
monitor_.wait();
}
void join() {
if (!detached_ && state_ != uninitialized) {
if (!detached_ && getState() != uninitialized) {
thread_->join();
}
}
@ -109,19 +132,11 @@ void* BoostThread::threadMain(void* arg) {
shared_ptr<BoostThread> thread = *(shared_ptr<BoostThread>*)arg;
delete reinterpret_cast<shared_ptr<BoostThread>*>(arg);
if (!thread) {
return (void*)0;
}
if (thread->state_ != starting) {
return (void*)0;
}
thread->state_ = started;
thread->setState(started);
thread->runnable()->run();
if (thread->state_ != stopping && thread->state_ != stopped) {
thread->state_ = stopping;
if (thread->getState() != stopping && thread->getState() != stopped) {
thread->setState(stopping);
}
return (void*)0;
}

View file

@ -20,9 +20,9 @@
#ifndef _THRIFT_CONCURRENCY_BOOSTTHREADFACTORY_H_
#define _THRIFT_CONCURRENCY_BOOSTTHREADFACTORY_H_ 1
#include <thrift/concurrency/Monitor.h>
#include <thrift/concurrency/Thread.h>
#include <boost/shared_ptr.hpp>
#include <thrift/stdcxx.h>
namespace apache {
namespace thrift {
@ -38,9 +38,8 @@ class BoostThreadFactory : public ThreadFactory {
public:
/**
* Boost thread factory. All threads created by a factory are reference-counted
* via boost::shared_ptr and boost::weak_ptr. The factory guarantees that threads and
* the Runnable tasks they host will be properly cleaned up once the last strong reference
* to both is given up.
* via stdcxx::shared_ptr. The factory guarantees that threads and the Runnable tasks they
* host will be properly cleaned up once the last strong reference to both is given up.
*
* Threads are created with the specified boost policy, priority, stack-size. A detachable thread
* is not joinable.
@ -51,7 +50,7 @@ public:
BoostThreadFactory(bool detached = true);
// From ThreadFactory;
boost::shared_ptr<Thread> newThread(boost::shared_ptr<Runnable> runnable) const;
stdcxx::shared_ptr<Thread> newThread(stdcxx::shared_ptr<Runnable> runnable) const;
// From ThreadFactory;
Thread::id_t getCurrentThreadId() const;

View file

@ -20,8 +20,8 @@
#ifndef _THRIFT_CONCURRENCY_FUNCTION_RUNNER_H
#define _THRIFT_CONCURRENCY_FUNCTION_RUNNER_H 1
#include <thrift/cxxfunctional.h>
#include <thrift/concurrency/Thread.h>
#include <thrift/stdcxx.h>
namespace apache {
namespace thrift {
@ -53,20 +53,20 @@ public:
// This is the type of callback 'pthread_create()' expects.
typedef void* (*PthreadFuncPtr)(void* arg);
// This a fully-generic void(void) callback for custom bindings.
typedef apache::thrift::stdcxx::function<void()> VoidFunc;
typedef stdcxx::function<void()> VoidFunc;
typedef apache::thrift::stdcxx::function<bool()> BoolFunc;
typedef stdcxx::function<bool()> BoolFunc;
/**
* Syntactic sugar to make it easier to create new FunctionRunner
* objects wrapped in shared_ptr.
*/
static boost::shared_ptr<FunctionRunner> create(const VoidFunc& cob) {
return boost::shared_ptr<FunctionRunner>(new FunctionRunner(cob));
static stdcxx::shared_ptr<FunctionRunner> create(const VoidFunc& cob) {
return stdcxx::shared_ptr<FunctionRunner>(new FunctionRunner(cob));
}
static boost::shared_ptr<FunctionRunner> create(PthreadFuncPtr func, void* arg) {
return boost::shared_ptr<FunctionRunner>(new FunctionRunner(func, arg));
static stdcxx::shared_ptr<FunctionRunner> create(PthreadFuncPtr func, void* arg) {
return stdcxx::shared_ptr<FunctionRunner>(new FunctionRunner(func, arg));
}
private:
@ -81,7 +81,7 @@ public:
* execute the given callback. Note that the 'void*' return value is ignored.
*/
FunctionRunner(PthreadFuncPtr func, void* arg)
: func_(apache::thrift::stdcxx::bind(pthread_func_wrapper, func, arg)), intervalMs_(-1) {}
: func_(stdcxx::bind(pthread_func_wrapper, func, arg)), intervalMs_(-1) {}
/**
* Given a generic callback, this FunctionRunner will execute it.

View file

@ -23,8 +23,7 @@
#include <thrift/concurrency/Exception.h>
#include <thrift/concurrency/Util.h>
#include <thrift/transport/PlatformSocket.h>
#include <boost/scoped_ptr.hpp>
#include <thrift/stdcxx.h>
#include <assert.h>
@ -34,9 +33,11 @@
namespace apache {
namespace thrift {
namespace concurrency {
using boost::scoped_ptr;
using stdcxx::scoped_ptr;
using stdcxx::shared_ptr;
namespace concurrency {
/**
* Monitor implementation using the POSIX pthread library

View file

@ -17,25 +17,32 @@
* under the License.
*/
// needed to test for pthread implementation capabilities:
#define __USE_GNU
#include <thrift/thrift-config.h>
#include <thrift/Thrift.h>
#include <thrift/concurrency/Exception.h>
#include <thrift/concurrency/Mutex.h>
#include <thrift/concurrency/Util.h>
#include <assert.h>
#ifdef HAVE_PTHREAD_H
#include <stdlib.h>
#include <pthread.h>
#endif
#include <signal.h>
#include <string.h>
using boost::shared_ptr;
#include <boost/format.hpp>
namespace apache {
namespace thrift {
namespace concurrency {
#ifndef THRIFT_NO_CONTENTION_PROFILING
// Enable this to turn on mutex contention profiling support
// #define THRIFT_PTHREAD_MUTEX_CONTENTION_PROFILING
#ifdef THRIFT_PTHREAD_MUTEX_CONTENTION_PROFILING
static int32_t mutexProfilingCounter = 0;
static int32_t mutexProfilingSampleRate = 0;
@ -105,17 +112,25 @@ static inline int64_t maybeGetProfilingStartTime() {
#define PROFILE_MUTEX_LOCKED()
#define PROFILE_MUTEX_START_UNLOCK()
#define PROFILE_MUTEX_UNLOCKED()
#endif // THRIFT_NO_CONTENTION_PROFILING
#endif // THRIFT_PTHREAD_MUTEX_CONTENTION_PROFILING
#define EINTR_LOOP(_CALL) int ret; do { ret = _CALL; } while (ret == EINTR)
#define ABORT_ONFAIL(_CALL) { EINTR_LOOP(_CALL); if (ret) { abort(); } }
#define THROW_SRE(_CALLSTR, RET) { throw SystemResourceException(boost::str(boost::format("%1% returned %2% (%3%)") % _CALLSTR % RET % ::strerror(RET))); }
#define THROW_SRE_ONFAIL(_CALL) { EINTR_LOOP(_CALL); if (ret) { THROW_SRE(#_CALL, ret); } }
#define THROW_SRE_TRYFAIL(_CALL) { EINTR_LOOP(_CALL); if (ret == 0) { return true; } else if (ret == EBUSY) { return false; } THROW_SRE(#_CALL, ret); }
/**
* Implementation of Mutex class using POSIX mutex
*
* Throws apache::thrift::concurrency::SystemResourceException on error.
*
* @version $Id:$
*/
class Mutex::impl {
public:
impl(Initializer init) : initialized_(false) {
#ifndef THRIFT_NO_CONTENTION_PROFILING
#ifdef THRIFT_PTHREAD_MUTEX_CONTENTION_PROFILING
profileTime_ = 0;
#endif
init(&pthread_mutex_);
@ -125,19 +140,19 @@ public:
~impl() {
if (initialized_) {
initialized_ = false;
int ret = pthread_mutex_destroy(&pthread_mutex_);
THRIFT_UNUSED_VARIABLE(ret);
assert(ret == 0);
ABORT_ONFAIL(pthread_mutex_destroy(&pthread_mutex_));
}
}
void lock() const {
PROFILE_MUTEX_START_LOCK();
pthread_mutex_lock(&pthread_mutex_);
THROW_SRE_ONFAIL(pthread_mutex_lock(&pthread_mutex_));
PROFILE_MUTEX_LOCKED();
}
bool trylock() const { return (0 == pthread_mutex_trylock(&pthread_mutex_)); }
bool trylock() const {
THROW_SRE_TRYFAIL(pthread_mutex_trylock(&pthread_mutex_));
}
bool timedlock(int64_t milliseconds) const {
#if defined(_POSIX_TIMEOUTS) && _POSIX_TIMEOUTS >= 200112L
@ -145,14 +160,16 @@ public:
struct THRIFT_TIMESPEC ts;
Util::toTimespec(ts, milliseconds + Util::currentTime());
int ret = pthread_mutex_timedlock(&pthread_mutex_, &ts);
EINTR_LOOP(pthread_mutex_timedlock(&pthread_mutex_, &ts));
if (ret == 0) {
PROFILE_MUTEX_LOCKED();
return true;
} else if (ret == ETIMEDOUT) {
PROFILE_MUTEX_NOT_LOCKED();
return false;
}
PROFILE_MUTEX_NOT_LOCKED();
return false;
THROW_SRE("pthread_mutex_timedlock(&pthread_mutex_, &ts)", ret);
#else
/* Otherwise follow solution used by Mono for Android */
struct THRIFT_TIMESPEC sleepytime, now, to;
@ -177,7 +194,7 @@ public:
void unlock() const {
PROFILE_MUTEX_START_UNLOCK();
pthread_mutex_unlock(&pthread_mutex_);
THROW_SRE_ONFAIL(pthread_mutex_unlock(&pthread_mutex_));
PROFILE_MUTEX_UNLOCKED();
}
@ -186,7 +203,7 @@ public:
private:
mutable pthread_mutex_t pthread_mutex_;
mutable bool initialized_;
#ifndef THRIFT_NO_CONTENTION_PROFILING
#ifdef THRIFT_PTHREAD_MUTEX_CONTENTION_PROFILING
mutable int64_t profileTime_;
#endif
};
@ -216,28 +233,16 @@ void Mutex::unlock() const {
void Mutex::DEFAULT_INITIALIZER(void* arg) {
pthread_mutex_t* pthread_mutex = (pthread_mutex_t*)arg;
int ret = pthread_mutex_init(pthread_mutex, NULL);
THRIFT_UNUSED_VARIABLE(ret);
assert(ret == 0);
THROW_SRE_ONFAIL(pthread_mutex_init(pthread_mutex, NULL));
}
#if defined(PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP) \
|| defined(PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP)
#if defined(PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP) || defined(PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP) || defined(PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP)
static void init_with_kind(pthread_mutex_t* mutex, int kind) {
pthread_mutexattr_t mutexattr;
int ret = pthread_mutexattr_init(&mutexattr);
assert(ret == 0);
// Apparently, this can fail. Should we really be aborting?
ret = pthread_mutexattr_settype(&mutexattr, kind);
assert(ret == 0);
ret = pthread_mutex_init(mutex, &mutexattr);
assert(ret == 0);
ret = pthread_mutexattr_destroy(&mutexattr);
assert(ret == 0);
THRIFT_UNUSED_VARIABLE(ret);
THROW_SRE_ONFAIL(pthread_mutexattr_init(&mutexattr));
THROW_SRE_ONFAIL(pthread_mutexattr_settype(&mutexattr, kind));
THROW_SRE_ONFAIL(pthread_mutex_init(mutex, &mutexattr));
THROW_SRE_ONFAIL(pthread_mutexattr_destroy(&mutexattr));
}
#endif
@ -255,6 +260,12 @@ void Mutex::ADAPTIVE_INITIALIZER(void* arg) {
}
#endif
#ifdef PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP
void Mutex::ERRORCHECK_INITIALIZER(void* arg) {
init_with_kind((pthread_mutex_t*)arg, PTHREAD_MUTEX_ERRORCHECK);
}
#endif
#ifdef PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
void Mutex::RECURSIVE_INITIALIZER(void* arg) {
init_with_kind((pthread_mutex_t*)arg, PTHREAD_MUTEX_RECURSIVE_NP);
@ -269,50 +280,46 @@ void Mutex::RECURSIVE_INITIALIZER(void* arg) {
class ReadWriteMutex::impl {
public:
impl() : initialized_(false) {
#ifndef THRIFT_NO_CONTENTION_PROFILING
#ifdef THRIFT_PTHREAD_MUTEX_CONTENTION_PROFILING
profileTime_ = 0;
#endif
int ret = pthread_rwlock_init(&rw_lock_, NULL);
THRIFT_UNUSED_VARIABLE(ret);
assert(ret == 0);
THROW_SRE_ONFAIL(pthread_rwlock_init(&rw_lock_, NULL));
initialized_ = true;
}
~impl() {
if (initialized_) {
initialized_ = false;
int ret = pthread_rwlock_destroy(&rw_lock_);
THRIFT_UNUSED_VARIABLE(ret);
assert(ret == 0);
ABORT_ONFAIL(pthread_rwlock_destroy(&rw_lock_));
}
}
void acquireRead() const {
PROFILE_MUTEX_START_LOCK();
pthread_rwlock_rdlock(&rw_lock_);
THROW_SRE_ONFAIL(pthread_rwlock_rdlock(&rw_lock_));
PROFILE_MUTEX_NOT_LOCKED(); // not exclusive, so use not-locked path
}
void acquireWrite() const {
PROFILE_MUTEX_START_LOCK();
pthread_rwlock_wrlock(&rw_lock_);
THROW_SRE_ONFAIL(pthread_rwlock_wrlock(&rw_lock_));
PROFILE_MUTEX_LOCKED();
}
bool attemptRead() const { return !pthread_rwlock_tryrdlock(&rw_lock_); }
bool attemptRead() const { THROW_SRE_TRYFAIL(pthread_rwlock_tryrdlock(&rw_lock_)); }
bool attemptWrite() const { return !pthread_rwlock_trywrlock(&rw_lock_); }
bool attemptWrite() const { THROW_SRE_TRYFAIL(pthread_rwlock_trywrlock(&rw_lock_)); }
void release() const {
PROFILE_MUTEX_START_UNLOCK();
pthread_rwlock_unlock(&rw_lock_);
THROW_SRE_ONFAIL(pthread_rwlock_unlock(&rw_lock_));
PROFILE_MUTEX_UNLOCKED();
}
private:
mutable pthread_rwlock_t rw_lock_;
mutable bool initialized_;
#ifndef THRIFT_NO_CONTENTION_PROFILING
#ifdef THRIFT_PTHREAD_MUTEX_CONTENTION_PROFILING
mutable int64_t profileTime_;
#endif
};

View file

@ -20,7 +20,7 @@
#ifndef _THRIFT_CONCURRENCY_MUTEX_H_
#define _THRIFT_CONCURRENCY_MUTEX_H_ 1
#include <boost/shared_ptr.hpp>
#include <thrift/stdcxx.h>
#include <boost/noncopyable.hpp>
#include <stdint.h>
@ -53,6 +53,11 @@ void enableMutexProfiling(int32_t profilingSampleRate, MutexWaitCallback callbac
#endif
/**
* NOTE: All mutex implementations throw an exception on failure. See each
* specific implementation to understand the exception type(s) used.
*/
/**
* A simple mutex class
*
@ -64,6 +69,7 @@ public:
Mutex(Initializer init = DEFAULT_INITIALIZER);
virtual ~Mutex() {}
virtual void lock() const;
virtual bool trylock() const;
virtual bool timedlock(int64_t milliseconds) const;
@ -71,13 +77,16 @@ public:
void* getUnderlyingImpl() const;
static void DEFAULT_INITIALIZER(void*);
// If you attempt to use one of these and it fails to link, it means
// your version of pthreads does not support it - try another one.
static void ADAPTIVE_INITIALIZER(void*);
static void DEFAULT_INITIALIZER(void*);
static void ERRORCHECK_INITIALIZER(void*);
static void RECURSIVE_INITIALIZER(void*);
private:
class impl;
boost::shared_ptr<impl> impl_;
stdcxx::shared_ptr<impl> impl_;
};
class ReadWriteMutex {
@ -98,7 +107,7 @@ public:
private:
class impl;
boost::shared_ptr<impl> impl_;
stdcxx::shared_ptr<impl> impl_;
};
/**

View file

@ -19,8 +19,9 @@
#include <thrift/thrift-config.h>
#include <thrift/concurrency/PosixThreadFactory.h>
#include <thrift/concurrency/Exception.h>
#include <thrift/concurrency/Monitor.h>
#include <thrift/concurrency/PosixThreadFactory.h>
#if GOOGLE_PERFTOOLS_REGISTER_THREAD
#include <google/profiler.h>
@ -31,15 +32,12 @@
#include <iostream>
#include <boost/weak_ptr.hpp>
#include <thrift/stdcxx.h>
namespace apache {
namespace thrift {
namespace concurrency {
using boost::shared_ptr;
using boost::weak_ptr;
/**
* The POSIX thread class.
*
@ -55,11 +53,12 @@ public:
private:
pthread_t pthread_;
STATE state_;
Monitor monitor_; // guard to protect state_ and also notification
STATE state_; // to protect proper thread start behavior
int policy_;
int priority_;
int stackSize_;
weak_ptr<PthreadThread> self_;
stdcxx::weak_ptr<PthreadThread> self_;
bool detached_;
public:
@ -67,13 +66,12 @@ public:
int priority,
int stackSize,
bool detached,
shared_ptr<Runnable> runnable)
stdcxx::shared_ptr<Runnable> runnable)
:
#ifndef _WIN32
pthread_(0),
#endif // _WIN32
state_(uninitialized),
policy_(policy),
priority_(priority),
@ -96,8 +94,26 @@ public:
}
}
STATE getState() const
{
Synchronized sync(monitor_);
return state_;
}
void setState(STATE newState)
{
Synchronized sync(monitor_);
state_ = newState;
// unblock start() with the knowledge that the thread has actually
// started running, which avoids a race in detached threads.
if (newState == started) {
monitor_.notify();
}
}
void start() {
if (state_ != uninitialized) {
if (getState() != uninitialized) {
return;
}
@ -139,18 +155,27 @@ public:
}
// Create reference
shared_ptr<PthreadThread>* selfRef = new shared_ptr<PthreadThread>();
stdcxx::shared_ptr<PthreadThread>* selfRef = new stdcxx::shared_ptr<PthreadThread>();
*selfRef = self_.lock();
state_ = starting;
setState(starting);
Synchronized sync(monitor_);
if (pthread_create(&pthread_, &thread_attr, threadMain, (void*)selfRef) != 0) {
throw SystemResourceException("pthread_create failed");
}
// The caller may not choose to guarantee the scope of the Runnable
// being used in the thread, so we must actually wait until the thread
// starts before we return. If we do not wait, it would be possible
// for the caller to start destructing the Runnable and the Thread,
// and we would end up in a race. This was identified with valgrind.
monitor_.wait();
}
void join() {
if (!detached_ && state_ != uninitialized) {
if (!detached_ && getState() != uninitialized) {
void* ignore;
/* XXX
If join fails it is most likely due to the fact
@ -164,8 +189,6 @@ public:
if (res != 0) {
GlobalOutput.printf("PthreadThread::join(): fail with code %d", res);
}
} else {
GlobalOutput.printf("PthreadThread::join(): detached thread");
}
}
@ -178,36 +201,31 @@ public:
#endif // _WIN32
}
shared_ptr<Runnable> runnable() const { return Thread::runnable(); }
stdcxx::shared_ptr<Runnable> runnable() const { return Thread::runnable(); }
void runnable(shared_ptr<Runnable> value) { Thread::runnable(value); }
void runnable(stdcxx::shared_ptr<Runnable> value) { Thread::runnable(value); }
void weakRef(shared_ptr<PthreadThread> self) {
void weakRef(stdcxx::shared_ptr<PthreadThread> self) {
assert(self.get() == this);
self_ = weak_ptr<PthreadThread>(self);
self_ = stdcxx::weak_ptr<PthreadThread>(self);
}
};
void* PthreadThread::threadMain(void* arg) {
shared_ptr<PthreadThread> thread = *(shared_ptr<PthreadThread>*)arg;
delete reinterpret_cast<shared_ptr<PthreadThread>*>(arg);
if (thread == NULL) {
return (void*)0;
}
if (thread->state_ != starting) {
return (void*)0;
}
stdcxx::shared_ptr<PthreadThread> thread = *(stdcxx::shared_ptr<PthreadThread>*)arg;
delete reinterpret_cast<stdcxx::shared_ptr<PthreadThread>*>(arg);
#if GOOGLE_PERFTOOLS_REGISTER_THREAD
ProfilerRegisterThread();
#endif
thread->state_ = started;
thread->setState(started);
thread->runnable()->run();
if (thread->state_ != stopping && thread->state_ != stopped) {
thread->state_ = stopping;
STATE _s = thread->getState();
if (_s != stopping && _s != stopped) {
thread->setState(stopping);
}
return (void*)0;
@ -276,9 +294,9 @@ PosixThreadFactory::PosixThreadFactory(bool detached)
stackSize_(1) {
}
shared_ptr<Thread> PosixThreadFactory::newThread(shared_ptr<Runnable> runnable) const {
shared_ptr<PthreadThread> result
= shared_ptr<PthreadThread>(new PthreadThread(toPthreadPolicy(policy_),
stdcxx::shared_ptr<Thread> PosixThreadFactory::newThread(stdcxx::shared_ptr<Runnable> runnable) const {
stdcxx::shared_ptr<PthreadThread> result
= stdcxx::shared_ptr<PthreadThread>(new PthreadThread(toPthreadPolicy(policy_),
toPthreadPriority(policy_, priority_),
stackSize_,
isDetached(),

View file

@ -22,7 +22,7 @@
#include <thrift/concurrency/Thread.h>
#include <boost/shared_ptr.hpp>
#include <thrift/stdcxx.h>
namespace apache {
namespace thrift {
@ -63,9 +63,9 @@ public:
/**
* Posix thread (pthread) factory. All threads created by a factory are reference-counted
* via boost::shared_ptr and boost::weak_ptr. The factory guarantees that threads and
* the Runnable tasks they host will be properly cleaned up once the last strong reference
* to both is given up.
* via stdcxx::shared_ptr. The factory guarantees that threads and the Runnable tasks
* they host will be properly cleaned up once the last strong reference to both is
* given up.
*
* Threads are created with the specified policy, priority, stack-size and detachable-mode
* detached means the thread is free-running and will release all system resources the
@ -88,7 +88,7 @@ public:
PosixThreadFactory(bool detached);
// From ThreadFactory;
boost::shared_ptr<Thread> newThread(boost::shared_ptr<Runnable> runnable) const;
stdcxx::shared_ptr<Thread> newThread(stdcxx::shared_ptr<Runnable> runnable) const;
// From ThreadFactory;
Thread::id_t getCurrentThreadId() const;

View file

@ -33,11 +33,14 @@ namespace concurrency {
/**
* Implementation of Mutex class using C++11 std::timed_mutex
*
* Methods throw std::system_error on error.
*
* @version $Id:$
*/
class Mutex::impl : public std::timed_mutex {};
Mutex::Mutex(Initializer init) : impl_(new Mutex::impl()) {
((void)init);
}
void* Mutex::getUnderlyingImpl() const {
@ -61,6 +64,7 @@ void Mutex::unlock() const {
}
void Mutex::DEFAULT_INITIALIZER(void* arg) {
((void)arg);
}
}
}

View file

@ -21,13 +21,12 @@
#if USE_STD_THREAD
#include <thrift/concurrency/StdThreadFactory.h>
#include <thrift/concurrency/Exception.h>
#include <thrift/concurrency/Monitor.h>
#include <thrift/concurrency/StdThreadFactory.h>
#include <thrift/stdcxx.h>
#include <cassert>
#include <boost/enable_shared_from_this.hpp>
#include <boost/weak_ptr.hpp>
#include <thread>
namespace apache {
@ -43,25 +42,26 @@ namespace concurrency {
*
* @version $Id:$
*/
class StdThread : public Thread, public boost::enable_shared_from_this<StdThread> {
class StdThread : public Thread, public stdcxx::enable_shared_from_this<StdThread> {
public:
enum STATE { uninitialized, starting, started, stopping, stopped };
static void threadMain(boost::shared_ptr<StdThread> thread);
static void threadMain(stdcxx::shared_ptr<StdThread> thread);
private:
std::unique_ptr<std::thread> thread_;
Monitor monitor_;
STATE state_;
bool detached_;
public:
StdThread(bool detached, boost::shared_ptr<Runnable> runnable)
StdThread(bool detached, stdcxx::shared_ptr<Runnable> runnable)
: state_(uninitialized), detached_(detached) {
this->Thread::runnable(runnable);
}
~StdThread() {
if (!detached_) {
if (!detached_ && thread_->joinable()) {
try {
join();
} catch (...) {
@ -70,18 +70,42 @@ public:
}
}
STATE getState() const
{
Synchronized sync(monitor_);
return state_;
}
void setState(STATE newState)
{
Synchronized sync(monitor_);
state_ = newState;
// unblock start() with the knowledge that the thread has actually
// started running, which avoids a race in detached threads.
if (newState == started) {
monitor_.notify();
}
}
void start() {
if (state_ != uninitialized) {
if (getState() != uninitialized) {
return;
}
boost::shared_ptr<StdThread> selfRef = shared_from_this();
state_ = starting;
stdcxx::shared_ptr<StdThread> selfRef = shared_from_this();
setState(starting);
Synchronized sync(monitor_);
thread_ = std::unique_ptr<std::thread>(new std::thread(threadMain, selfRef));
if (detached_)
thread_->detach();
// Wait for the thread to start and get far enough to grab everything
// that it needs from the calling context, thus absolving the caller
// from being required to hold on to runnable indefinitely.
monitor_.wait();
}
void join() {
@ -92,35 +116,29 @@ public:
Thread::id_t getId() { return thread_.get() ? thread_->get_id() : std::thread::id(); }
boost::shared_ptr<Runnable> runnable() const { return Thread::runnable(); }
stdcxx::shared_ptr<Runnable> runnable() const { return Thread::runnable(); }
void runnable(boost::shared_ptr<Runnable> value) { Thread::runnable(value); }
void runnable(stdcxx::shared_ptr<Runnable> value) { Thread::runnable(value); }
};
void StdThread::threadMain(boost::shared_ptr<StdThread> thread) {
if (thread == NULL) {
return;
}
void StdThread::threadMain(stdcxx::shared_ptr<StdThread> thread) {
#if GOOGLE_PERFTOOLS_REGISTER_THREAD
ProfilerRegisterThread();
#endif
if (thread->state_ != starting) {
return;
}
thread->state_ = started;
thread->setState(started);
thread->runnable()->run();
if (thread->state_ != stopping && thread->state_ != stopped) {
thread->state_ = stopping;
if (thread->getState() != stopping && thread->getState() != stopped) {
thread->setState(stopping);
}
return;
}
StdThreadFactory::StdThreadFactory(bool detached) : ThreadFactory(detached) {
}
boost::shared_ptr<Thread> StdThreadFactory::newThread(boost::shared_ptr<Runnable> runnable) const {
boost::shared_ptr<StdThread> result = boost::shared_ptr<StdThread>(new StdThread(isDetached(), runnable));
stdcxx::shared_ptr<Thread> StdThreadFactory::newThread(stdcxx::shared_ptr<Runnable> runnable) const {
stdcxx::shared_ptr<StdThread> result = stdcxx::shared_ptr<StdThread>(new StdThread(isDetached(), runnable));
runnable->thread(result);
return result;
}

View file

@ -22,7 +22,7 @@
#include <thrift/concurrency/Thread.h>
#include <boost/shared_ptr.hpp>
#include <thrift/stdcxx.h>
namespace apache {
namespace thrift {
@ -38,8 +38,8 @@ class StdThreadFactory : public ThreadFactory {
public:
/**
* Std thread factory. All threads created by a factory are reference-counted
* via boost::shared_ptr and boost::weak_ptr. The factory guarantees that threads and
* the Runnable tasks they host will be properly cleaned up once the last strong reference
* via stdcxx::shared_ptr. The factory guarantees that threads and the Runnable tasks
* they host will be properly cleaned up once the last strong reference
* to both is given up.
*
* By default threads are not joinable.
@ -48,7 +48,7 @@ public:
StdThreadFactory(bool detached = true);
// From ThreadFactory;
boost::shared_ptr<Thread> newThread(boost::shared_ptr<Runnable> runnable) const;
stdcxx::shared_ptr<Thread> newThread(stdcxx::shared_ptr<Runnable> runnable) const;
// From ThreadFactory;
Thread::id_t getCurrentThreadId() const;

View file

@ -21,8 +21,7 @@
#define _THRIFT_CONCURRENCY_THREAD_H_ 1
#include <stdint.h>
#include <boost/shared_ptr.hpp>
#include <boost/weak_ptr.hpp>
#include <thrift/stdcxx.h>
#include <thrift/thrift-config.h>
@ -57,16 +56,16 @@ public:
* Gets the thread object that is hosting this runnable object - can return
* an empty boost::shared pointer if no references remain on that thread object
*/
virtual boost::shared_ptr<Thread> thread() { return thread_.lock(); }
virtual stdcxx::shared_ptr<Thread> thread() { return thread_.lock(); }
/**
* Sets the thread that is executing this object. This is only meant for
* use by concrete implementations of Thread.
*/
virtual void thread(boost::shared_ptr<Thread> value) { thread_ = value; }
virtual void thread(stdcxx::shared_ptr<Thread> value) { thread_ = value; }
private:
boost::weak_ptr<Thread> thread_;
stdcxx::weak_ptr<Thread> thread_;
};
/**
@ -122,13 +121,13 @@ public:
/**
* Gets the runnable object this thread is hosting
*/
virtual boost::shared_ptr<Runnable> runnable() const { return _runnable; }
virtual stdcxx::shared_ptr<Runnable> runnable() const { return _runnable; }
protected:
virtual void runnable(boost::shared_ptr<Runnable> value) { _runnable = value; }
virtual void runnable(stdcxx::shared_ptr<Runnable> value) { _runnable = value; }
private:
boost::shared_ptr<Runnable> _runnable;
stdcxx::shared_ptr<Runnable> _runnable;
};
/**
@ -155,7 +154,7 @@ public:
/**
* Create a new thread.
*/
virtual boost::shared_ptr<Thread> newThread(boost::shared_ptr<Runnable> runnable) const = 0;
virtual stdcxx::shared_ptr<Thread> newThread(stdcxx::shared_ptr<Runnable> runnable) const = 0;
/**
* Gets the current thread id or unknown_thread_id if the current thread is not a thrift thread

View file

@ -24,22 +24,18 @@
#include <thrift/concurrency/Monitor.h>
#include <thrift/concurrency/Util.h>
#include <boost/shared_ptr.hpp>
#include <thrift/stdcxx.h>
#include <stdexcept>
#include <deque>
#include <set>
#if defined(DEBUG)
#include <iostream>
#endif // defined(DEBUG)
namespace apache {
namespace thrift {
namespace concurrency {
using boost::shared_ptr;
using boost::dynamic_pointer_cast;
using stdcxx::shared_ptr;
using stdcxx::dynamic_pointer_cast;
/**
* ThreadManager class
@ -508,7 +504,7 @@ void ThreadManager::Impl::remove(shared_ptr<Runnable> task) {
}
}
boost::shared_ptr<Runnable> ThreadManager::Impl::removeNextPending() {
stdcxx::shared_ptr<Runnable> ThreadManager::Impl::removeNextPending() {
Guard g(mutex_);
if (state_ != ThreadManager::STARTED) {
throw IllegalStateException(
@ -517,7 +513,7 @@ boost::shared_ptr<Runnable> ThreadManager::Impl::removeNextPending() {
}
if (tasks_.empty()) {
return boost::shared_ptr<Runnable>();
return stdcxx::shared_ptr<Runnable>();
}
shared_ptr<ThreadManager::Task> task = tasks_.front();

View file

@ -20,10 +20,9 @@
#ifndef _THRIFT_CONCURRENCY_THREADMANAGER_H_
#define _THRIFT_CONCURRENCY_THREADMANAGER_H_ 1
#include <boost/shared_ptr.hpp>
#include <thrift/cxxfunctional.h>
#include <sys/types.h>
#include <thrift/concurrency/Thread.h>
#include <thrift/stdcxx.h>
namespace apache {
namespace thrift {
@ -59,7 +58,7 @@ protected:
ThreadManager() {}
public:
typedef apache::thrift::stdcxx::function<void(boost::shared_ptr<Runnable>)> ExpireCallback;
typedef apache::thrift::stdcxx::function<void(stdcxx::shared_ptr<Runnable>)> ExpireCallback;
virtual ~ThreadManager() {}
@ -88,14 +87,14 @@ public:
/**
* \returns the current thread factory
*/
virtual boost::shared_ptr<ThreadFactory> threadFactory() const = 0;
virtual stdcxx::shared_ptr<ThreadFactory> threadFactory() const = 0;
/**
* Set the thread factory.
* \throws InvalidArgumentException if the new thread factory has a different
* detached disposition than the one replacing it
*/
virtual void threadFactory(boost::shared_ptr<ThreadFactory> value) = 0;
virtual void threadFactory(stdcxx::shared_ptr<ThreadFactory> value) = 0;
/**
* Adds worker thread(s).
@ -162,21 +161,21 @@ public:
*
* @throws TooManyPendingTasksException Pending task count exceeds max pending task count
*/
virtual void add(boost::shared_ptr<Runnable> task,
virtual void add(stdcxx::shared_ptr<Runnable> task,
int64_t timeout = 0LL,
int64_t expiration = 0LL) = 0;
/**
* Removes a pending task
*/
virtual void remove(boost::shared_ptr<Runnable> task) = 0;
virtual void remove(stdcxx::shared_ptr<Runnable> task) = 0;
/**
* Remove the next pending task which would be run.
*
* @return the task removed.
*/
virtual boost::shared_ptr<Runnable> removeNextPending() = 0;
virtual stdcxx::shared_ptr<Runnable> removeNextPending() = 0;
/**
* Remove tasks from front of task queue that have expired.
@ -191,14 +190,14 @@ public:
*/
virtual void setExpireCallback(ExpireCallback expireCallback) = 0;
static boost::shared_ptr<ThreadManager> newThreadManager();
static stdcxx::shared_ptr<ThreadManager> newThreadManager();
/**
* Creates a simple thread manager the uses count number of worker threads and has
* a pendingTaskCountMax maximum pending tasks. The default, 0, specified no limit
* on pending tasks
*/
static boost::shared_ptr<ThreadManager> newSimpleThreadManager(size_t count = 4,
static stdcxx::shared_ptr<ThreadManager> newSimpleThreadManager(size_t count = 4,
size_t pendingTaskCountMax = 0);
class Task;

View file

@ -29,7 +29,8 @@ namespace apache {
namespace thrift {
namespace concurrency {
using boost::shared_ptr;
using stdcxx::shared_ptr;
using stdcxx::weak_ptr;
/**
* TimerManager class
@ -52,6 +53,10 @@ public:
}
}
bool operator==(const shared_ptr<Runnable> & runnable) const { return runnable_ == runnable; }
task_iterator it_;
private:
shared_ptr<Runnable> runnable_;
friend class TimerManager::Dispatcher;
@ -106,6 +111,7 @@ public:
for (task_iterator ix = manager_->taskMap_.begin(); ix != expiredTaskEnd; ix++) {
shared_ptr<TimerManager::Task> task = ix->second;
expiredTasks.insert(task);
task->it_ = manager_->taskMap_.end();
if (task->state_ == TimerManager::Task::WAITING) {
task->state_ = TimerManager::Task::EXECUTING;
}
@ -233,7 +239,7 @@ size_t TimerManager::taskCount() const {
return taskCount_;
}
void TimerManager::add(shared_ptr<Runnable> task, int64_t timeout) {
TimerManager::Timer TimerManager::add(shared_ptr<Runnable> task, int64_t timeout) {
int64_t now = Util::currentTime();
timeout += now;
@ -248,9 +254,9 @@ void TimerManager::add(shared_ptr<Runnable> task, int64_t timeout) {
// because the new task might insert at the front.
bool notifyRequired = (taskCount_ == 0) ? true : timeout < taskMap_.begin()->first;
shared_ptr<Task> timer(new Task(task));
taskCount_++;
taskMap_.insert(
std::pair<int64_t, shared_ptr<Task> >(timeout, shared_ptr<Task>(new Task(task))));
timer->it_ = taskMap_.insert(std::pair<int64_t, shared_ptr<Task> >(timeout, timer));
// If the task map was empty, or if we have an expiration that is earlier
// than any previously seen, kick the dispatcher so it can update its
@ -258,10 +264,13 @@ void TimerManager::add(shared_ptr<Runnable> task, int64_t timeout) {
if (notifyRequired) {
monitor_.notify();
}
return timer;
}
}
void TimerManager::add(shared_ptr<Runnable> task, const struct THRIFT_TIMESPEC& value) {
TimerManager::Timer TimerManager::add(shared_ptr<Runnable> task,
const struct THRIFT_TIMESPEC& value) {
int64_t expiration;
Util::toMilliseconds(expiration, value);
@ -272,10 +281,11 @@ void TimerManager::add(shared_ptr<Runnable> task, const struct THRIFT_TIMESPEC&
throw InvalidArgumentException();
}
add(task, expiration - now);
return add(task, expiration - now);
}
void TimerManager::add(shared_ptr<Runnable> task, const struct timeval& value) {
TimerManager::Timer TimerManager::add(shared_ptr<Runnable> task,
const struct timeval& value) {
int64_t expiration;
Util::toMilliseconds(expiration, value);
@ -286,15 +296,47 @@ void TimerManager::add(shared_ptr<Runnable> task, const struct timeval& value) {
throw InvalidArgumentException();
}
add(task, expiration - now);
return add(task, expiration - now);
}
void TimerManager::remove(shared_ptr<Runnable> task) {
(void)task;
Synchronized s(monitor_);
if (state_ != TimerManager::STARTED) {
throw IllegalStateException();
}
bool found = false;
for (task_iterator ix = taskMap_.begin(); ix != taskMap_.end();) {
if (*ix->second == task) {
found = true;
taskCount_--;
taskMap_.erase(ix++);
} else {
++ix;
}
}
if (!found) {
throw NoSuchTaskException();
}
}
void TimerManager::remove(Timer handle) {
Synchronized s(monitor_);
if (state_ != TimerManager::STARTED) {
throw IllegalStateException();
}
shared_ptr<Task> task = handle.lock();
if (!task) {
throw NoSuchTaskException();
}
if (task->it_ == taskMap_.end()) {
// Task is being executed
throw UncancellableTaskException();
}
taskMap_.erase(task->it_);
taskCount_--;
}
TimerManager::STATE TimerManager::state() const {

View file

@ -24,7 +24,7 @@
#include <thrift/concurrency/Monitor.h>
#include <thrift/concurrency/Thread.h>
#include <boost/shared_ptr.hpp>
#include <thrift/stdcxx.h>
#include <map>
#include <time.h>
@ -42,13 +42,16 @@ namespace concurrency {
class TimerManager {
public:
class Task;
typedef stdcxx::weak_ptr<Task> Timer;
TimerManager();
virtual ~TimerManager();
virtual boost::shared_ptr<const ThreadFactory> threadFactory() const;
virtual stdcxx::shared_ptr<const ThreadFactory> threadFactory() const;
virtual void threadFactory(boost::shared_ptr<const ThreadFactory> value);
virtual void threadFactory(stdcxx::shared_ptr<const ThreadFactory> value);
/**
* Starts the timer manager service
@ -69,28 +72,33 @@ public:
*
* @param task The task to execute
* @param timeout Time in milliseconds to delay before executing task
* @return Handle of the timer, which can be used to remove the timer.
*/
virtual void add(boost::shared_ptr<Runnable> task, int64_t timeout);
virtual Timer add(stdcxx::shared_ptr<Runnable> task, int64_t timeout);
/**
* Adds a task to be executed at some time in the future by a worker thread.
*
* @param task The task to execute
* @param timeout Absolute time in the future to execute task.
* @return Handle of the timer, which can be used to remove the timer.
*/
virtual void add(boost::shared_ptr<Runnable> task, const struct THRIFT_TIMESPEC& timeout);
virtual Timer add(stdcxx::shared_ptr<Runnable> task, const struct THRIFT_TIMESPEC& timeout);
/**
* Adds a task to be executed at some time in the future by a worker thread.
*
* @param task The task to execute
* @param timeout Absolute time in the future to execute task.
* @return Handle of the timer, which can be used to remove the timer.
*/
virtual void add(boost::shared_ptr<Runnable> task, const struct timeval& timeout);
virtual Timer add(stdcxx::shared_ptr<Runnable> task, const struct timeval& timeout);
/**
* Removes a pending task
*
* @param task The task to remove. All timers which execute this task will
* be removed.
* @throws NoSuchTaskException Specified task doesn't exist. It was either
* processed already or this call was made for a
* task that was never added to this timer
@ -98,25 +106,38 @@ public:
* @throws UncancellableTaskException Specified task is already being
* executed or has completed execution.
*/
virtual void remove(boost::shared_ptr<Runnable> task);
virtual void remove(stdcxx::shared_ptr<Runnable> task);
/**
* Removes a single pending task
*
* @param timer The timer to remove. The timer is returned when calling the
* add() method.
* @throws NoSuchTaskException Specified task doesn't exist. It was either
* processed already or this call was made for a
* task that was never added to this timer
*
* @throws UncancellableTaskException Specified task is already being
* executed or has completed execution.
*/
virtual void remove(Timer timer);
enum STATE { UNINITIALIZED, STARTING, STARTED, STOPPING, STOPPED };
virtual STATE state() const;
private:
boost::shared_ptr<const ThreadFactory> threadFactory_;
class Task;
stdcxx::shared_ptr<const ThreadFactory> threadFactory_;
friend class Task;
std::multimap<int64_t, boost::shared_ptr<Task> > taskMap_;
std::multimap<int64_t, stdcxx::shared_ptr<Task> > taskMap_;
size_t taskCount_;
Monitor monitor_;
STATE state_;
class Dispatcher;
friend class Dispatcher;
boost::shared_ptr<Dispatcher> dispatcher_;
boost::shared_ptr<Thread> dispatcherThread_;
typedef std::multimap<int64_t, boost::shared_ptr<TimerManager::Task> >::iterator task_iterator;
stdcxx::shared_ptr<Dispatcher> dispatcher_;
stdcxx::shared_ptr<Thread> dispatcherThread_;
typedef std::multimap<int64_t, stdcxx::shared_ptr<TimerManager::Task> >::iterator task_iterator;
typedef std::pair<task_iterator, task_iterator> task_range;
};
}

View file

@ -1,132 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
#ifndef _THRIFT_CXXFUNCTIONAL_H_
#define _THRIFT_CXXFUNCTIONAL_H_ 1
// clang-format off
/**
* Loads <functional> from the 'right' location, depending
* on compiler and whether or not it's using C++03 with TR1
* or C++11.
*/
/*
* MSVC 10 and 11 have the <functional> stuff at <functional>.
* In MSVC 10 all of the implementations live in std::tr1.
* In MSVC 11 all of the implementations live in std, with aliases
* in std::tr1 to point to the ones in std.
*/
#if defined(_WIN32) && !defined(__MINGW32__)
#define _THRIFT_USING_MICROSOFT_STDLIB 1
#endif
#ifdef __clang__
/* Clang has two options, depending on standard library:
* - no -stdlib or -stdlib=libstdc++ set; uses GNU libstdc++.
* <tr1/functional>
* - -stdlib=libc++; uses LLVM libc++.
* <functional>, no 'std::tr1'.
*
* The compiler itself doesn't define anything differently
* depending on the value of -stdlib, but the library headers
* will set different preprocessor options. In order to check,
* though, we have to pull in some library header.
*/
#include <utility>
/* With LLVM libc++, utility pulls in __config, which sets
_LIBCPP_VERSION. */
#if defined(_LIBCPP_VERSION)
#define _THRIFT_USING_CLANG_LIBCXX 1
/* With GNU libstdc++, utility pulls in bits/c++config.h,
which sets __GLIBCXX__. */
#elif defined(__GLIBCXX__)
#define _THRIFT_USING_GNU_LIBSTDCXX 1
/* No idea. */
#else
#error Unable to detect which C++ standard library is in use.
#endif
#elif __GNUC__
#define _THRIFT_USING_GNU_LIBSTDCXX 1
#endif
#if _THRIFT_USING_MICROSOFT_STDLIB
#include <functional>
namespace apache { namespace thrift { namespace stdcxx {
using ::std::tr1::function;
using ::std::tr1::bind;
namespace placeholders {
using ::std::tr1::placeholders::_1;
using ::std::tr1::placeholders::_2;
using ::std::tr1::placeholders::_3;
using ::std::tr1::placeholders::_4;
using ::std::tr1::placeholders::_5;
using ::std::tr1::placeholders::_6;
} // apache::thrift::stdcxx::placeholders
}}} // apache::thrift::stdcxx
#elif _THRIFT_USING_CLANG_LIBCXX
#include <functional>
namespace apache { namespace thrift { namespace stdcxx {
using ::std::function;
using ::std::bind;
namespace placeholders {
using ::std::placeholders::_1;
using ::std::placeholders::_2;
using ::std::placeholders::_3;
using ::std::placeholders::_4;
using ::std::placeholders::_5;
using ::std::placeholders::_6;
} // apache::thrift::stdcxx::placeholders
}}} // apache::thrift::stdcxx
#elif _THRIFT_USING_GNU_LIBSTDCXX
#ifdef USE_BOOST_THREAD
#include <boost/tr1/functional.hpp>
#else
#include <tr1/functional>
#endif
namespace apache { namespace thrift { namespace stdcxx {
using ::std::tr1::function;
using ::std::tr1::bind;
namespace placeholders {
using ::std::tr1::placeholders::_1;
using ::std::tr1::placeholders::_2;
using ::std::tr1::placeholders::_3;
using ::std::tr1::placeholders::_4;
using ::std::tr1::placeholders::_5;
using ::std::tr1::placeholders::_6;
} // apache::thrift::stdcxx::placeholders
}}} // apache::thrift::stdcxx
#endif
// Alias for thrift c++ compatibility namespace
namespace tcxx = apache::thrift::stdcxx;
#endif // #ifndef _THRIFT_CXXFUNCTIONAL_H_

View file

@ -34,26 +34,26 @@ PeekProcessor::PeekProcessor() {
PeekProcessor::~PeekProcessor() {
}
void PeekProcessor::initialize(boost::shared_ptr<TProcessor> actualProcessor,
boost::shared_ptr<TProtocolFactory> protocolFactory,
boost::shared_ptr<TPipedTransportFactory> transportFactory) {
void PeekProcessor::initialize(stdcxx::shared_ptr<TProcessor> actualProcessor,
stdcxx::shared_ptr<TProtocolFactory> protocolFactory,
stdcxx::shared_ptr<TPipedTransportFactory> transportFactory) {
actualProcessor_ = actualProcessor;
pipedProtocol_ = protocolFactory->getProtocol(targetTransport_);
transportFactory_ = transportFactory;
transportFactory_->initializeTargetTransport(targetTransport_);
}
boost::shared_ptr<TTransport> PeekProcessor::getPipedTransport(boost::shared_ptr<TTransport> in) {
stdcxx::shared_ptr<TTransport> PeekProcessor::getPipedTransport(stdcxx::shared_ptr<TTransport> in) {
return transportFactory_->getTransport(in);
}
void PeekProcessor::setTargetTransport(boost::shared_ptr<TTransport> targetTransport) {
void PeekProcessor::setTargetTransport(stdcxx::shared_ptr<TTransport> targetTransport) {
targetTransport_ = targetTransport;
if (boost::dynamic_pointer_cast<TMemoryBuffer>(targetTransport_)) {
memoryBuffer_ = boost::dynamic_pointer_cast<TMemoryBuffer>(targetTransport);
} else if (boost::dynamic_pointer_cast<TPipedTransport>(targetTransport_)) {
memoryBuffer_ = boost::dynamic_pointer_cast<TMemoryBuffer>(
boost::dynamic_pointer_cast<TPipedTransport>(targetTransport_)->getTargetTransport());
if (stdcxx::dynamic_pointer_cast<TMemoryBuffer>(targetTransport_)) {
memoryBuffer_ = stdcxx::dynamic_pointer_cast<TMemoryBuffer>(targetTransport);
} else if (stdcxx::dynamic_pointer_cast<TPipedTransport>(targetTransport_)) {
memoryBuffer_ = stdcxx::dynamic_pointer_cast<TMemoryBuffer>(
stdcxx::dynamic_pointer_cast<TPipedTransport>(targetTransport_)->getTargetTransport());
}
if (!memoryBuffer_) {
@ -62,8 +62,8 @@ void PeekProcessor::setTargetTransport(boost::shared_ptr<TTransport> targetTrans
}
}
bool PeekProcessor::process(boost::shared_ptr<TProtocol> in,
boost::shared_ptr<TProtocol> out,
bool PeekProcessor::process(stdcxx::shared_ptr<TProtocol> in,
stdcxx::shared_ptr<TProtocol> out,
void* connectionContext) {
std::string fname;
@ -120,7 +120,7 @@ void PeekProcessor::peekBuffer(uint8_t* buffer, uint32_t size) {
(void)size;
}
void PeekProcessor::peek(boost::shared_ptr<TProtocol> in, TType ftype, int16_t fid) {
void PeekProcessor::peek(stdcxx::shared_ptr<TProtocol> in, TType ftype, int16_t fid) {
(void)fid;
in->skip(ftype);
}

View file

@ -25,7 +25,7 @@
#include <thrift/transport/TTransport.h>
#include <thrift/transport/TTransportUtils.h>
#include <thrift/transport/TBufferTransports.h>
#include <boost/shared_ptr.hpp>
#include <thrift/stdcxx.h>
namespace apache {
namespace thrift {
@ -47,34 +47,34 @@ public:
// transportFactory - this TPipedTransportFactory is used to wrap the source transport
// via a call to getPipedTransport
void initialize(
boost::shared_ptr<apache::thrift::TProcessor> actualProcessor,
boost::shared_ptr<apache::thrift::protocol::TProtocolFactory> protocolFactory,
boost::shared_ptr<apache::thrift::transport::TPipedTransportFactory> transportFactory);
stdcxx::shared_ptr<apache::thrift::TProcessor> actualProcessor,
stdcxx::shared_ptr<apache::thrift::protocol::TProtocolFactory> protocolFactory,
stdcxx::shared_ptr<apache::thrift::transport::TPipedTransportFactory> transportFactory);
boost::shared_ptr<apache::thrift::transport::TTransport> getPipedTransport(
boost::shared_ptr<apache::thrift::transport::TTransport> in);
stdcxx::shared_ptr<apache::thrift::transport::TTransport> getPipedTransport(
stdcxx::shared_ptr<apache::thrift::transport::TTransport> in);
void setTargetTransport(boost::shared_ptr<apache::thrift::transport::TTransport> targetTransport);
void setTargetTransport(stdcxx::shared_ptr<apache::thrift::transport::TTransport> targetTransport);
virtual bool process(boost::shared_ptr<apache::thrift::protocol::TProtocol> in,
boost::shared_ptr<apache::thrift::protocol::TProtocol> out,
virtual bool process(stdcxx::shared_ptr<apache::thrift::protocol::TProtocol> in,
stdcxx::shared_ptr<apache::thrift::protocol::TProtocol> out,
void* connectionContext);
// The following three functions can be overloaded by child classes to
// achieve desired peeking behavior
virtual void peekName(const std::string& fname);
virtual void peekBuffer(uint8_t* buffer, uint32_t size);
virtual void peek(boost::shared_ptr<apache::thrift::protocol::TProtocol> in,
virtual void peek(stdcxx::shared_ptr<apache::thrift::protocol::TProtocol> in,
apache::thrift::protocol::TType ftype,
int16_t fid);
virtual void peekEnd();
private:
boost::shared_ptr<apache::thrift::TProcessor> actualProcessor_;
boost::shared_ptr<apache::thrift::protocol::TProtocol> pipedProtocol_;
boost::shared_ptr<apache::thrift::transport::TPipedTransportFactory> transportFactory_;
boost::shared_ptr<apache::thrift::transport::TMemoryBuffer> memoryBuffer_;
boost::shared_ptr<apache::thrift::transport::TTransport> targetTransport_;
stdcxx::shared_ptr<apache::thrift::TProcessor> actualProcessor_;
stdcxx::shared_ptr<apache::thrift::protocol::TProtocol> pipedProtocol_;
stdcxx::shared_ptr<apache::thrift::transport::TPipedTransportFactory> transportFactory_;
stdcxx::shared_ptr<apache::thrift::transport::TMemoryBuffer> memoryBuffer_;
stdcxx::shared_ptr<apache::thrift::transport::TTransport> targetTransport_;
};
}
}

View file

@ -20,7 +20,7 @@
#ifndef STATSPROCESSOR_H
#define STATSPROCESSOR_H
#include <boost/shared_ptr.hpp>
#include <thrift/stdcxx.h>
#include <thrift/transport/TTransport.h>
#include <thrift/protocol/TProtocol.h>
#include <TProcessor.h>
@ -38,8 +38,8 @@ public:
StatsProcessor(bool print, bool frequency) : print_(print), frequency_(frequency) {}
virtual ~StatsProcessor(){};
virtual bool process(boost::shared_ptr<apache::thrift::protocol::TProtocol> piprot,
boost::shared_ptr<apache::thrift::protocol::TProtocol> poprot,
virtual bool process(stdcxx::shared_ptr<apache::thrift::protocol::TProtocol> piprot,
stdcxx::shared_ptr<apache::thrift::protocol::TProtocol> poprot,
void* serverContext) {
piprot_ = piprot;
@ -229,7 +229,7 @@ protected:
}
}
boost::shared_ptr<apache::thrift::protocol::TProtocol> piprot_;
stdcxx::shared_ptr<apache::thrift::protocol::TProtocol> piprot_;
std::map<std::string, int64_t> frequency_map_;
bool print_;

View file

@ -27,8 +27,6 @@
namespace apache {
namespace thrift {
using boost::shared_ptr;
namespace protocol {
/**
@ -38,7 +36,7 @@ namespace protocol {
*/
class StoredMessageProtocol : public TProtocolDecorator {
public:
StoredMessageProtocol(shared_ptr<protocol::TProtocol> _protocol,
StoredMessageProtocol(stdcxx::shared_ptr<protocol::TProtocol> _protocol,
const std::string& _name,
const TMessageType _type,
const int32_t _seqid)
@ -67,19 +65,19 @@ public:
* processors with it, as shown in the following example:</p>
*
* <blockquote><code>
* shared_ptr<TMultiplexedProcessor> processor(new TMultiplexedProcessor());
* stdcxx::shared_ptr<TMultiplexedProcessor> processor(new TMultiplexedProcessor());
*
* processor->registerProcessor(
* "Calculator",
* shared_ptr<TProcessor>( new CalculatorProcessor(
* shared_ptr<CalculatorHandler>( new CalculatorHandler()))));
* stdcxx::shared_ptr<TProcessor>( new CalculatorProcessor(
* stdcxx::shared_ptr<CalculatorHandler>( new CalculatorHandler()))));
*
* processor->registerProcessor(
* "WeatherReport",
* shared_ptr<TProcessor>( new WeatherReportProcessor(
* shared_ptr<WeatherReportHandler>( new WeatherReportHandler()))));
* stdcxx::shared_ptr<TProcessor>( new WeatherReportProcessor(
* stdcxx::shared_ptr<WeatherReportHandler>( new WeatherReportHandler()))));
*
* shared_ptr<TServerTransport> transport(new TServerSocket(9090));
* stdcxx::shared_ptr<TServerTransport> transport(new TServerSocket(9090));
* TSimpleServer server(processor, transport);
*
* server.serve();
@ -87,7 +85,7 @@ public:
*/
class TMultiplexedProcessor : public TProcessor {
public:
typedef std::map<std::string, shared_ptr<TProcessor> > services_t;
typedef std::map<std::string, stdcxx::shared_ptr<TProcessor> > services_t;
/**
* 'Register' a service with this <code>TMultiplexedProcessor</code>. This
@ -100,10 +98,40 @@ public:
* as "handlers", e.g. WeatherReportHandler,
* implementing WeatherReportIf interface.
*/
void registerProcessor(const std::string& serviceName, shared_ptr<TProcessor> processor) {
void registerProcessor(const std::string& serviceName, stdcxx::shared_ptr<TProcessor> processor) {
services[serviceName] = processor;
}
/**
* Register a service to be called to process queries without service name
* \param [in] processor Implementation of a service.
*/
void registerDefault(const stdcxx::shared_ptr<TProcessor>& processor) {
defaultProcessor = processor;
}
/**
* Chew up invalid input and return an exception to throw.
*/
TException protocol_error(stdcxx::shared_ptr<protocol::TProtocol> in,
stdcxx::shared_ptr<protocol::TProtocol> out,
const std::string& name,
int32_t seqid,
const std::string& msg) const {
in->skip(::apache::thrift::protocol::T_STRUCT);
in->readMessageEnd();
in->getTransport()->readEnd();
::apache::thrift::TApplicationException
x(::apache::thrift::TApplicationException::PROTOCOL_ERROR,
"TMultiplexedProcessor: " + msg);
out->writeMessageBegin(name, ::apache::thrift::protocol::T_EXCEPTION, seqid);
x.write(out.get());
out->writeMessageEnd();
out->getTransport()->writeEnd();
out->getTransport()->flush();
return TException(msg);
}
/**
* This implementation of <code>process</code> performs the following steps:
*
@ -119,8 +147,8 @@ public:
* the service name was not found in the message, or if the service
* name was not found in the service map.
*/
bool process(shared_ptr<protocol::TProtocol> in,
shared_ptr<protocol::TProtocol> out,
bool process(stdcxx::shared_ptr<protocol::TProtocol> in,
stdcxx::shared_ptr<protocol::TProtocol> out,
void* connectionContext) {
std::string name;
protocol::TMessageType type;
@ -133,22 +161,10 @@ public:
if (type != protocol::T_CALL && type != protocol::T_ONEWAY) {
// Unexpected message type.
in->skip(::apache::thrift::protocol::T_STRUCT);
in->readMessageEnd();
in->getTransport()->readEnd();
const std::string msg("TMultiplexedProcessor: Unexpected message type");
::apache::thrift::TApplicationException
x(::apache::thrift::TApplicationException::PROTOCOL_ERROR, msg);
out->writeMessageBegin(name, ::apache::thrift::protocol::T_EXCEPTION, seqid);
x.write(out.get());
out->writeMessageEnd();
out->getTransport()->writeEnd();
out->getTransport()->flush();
throw TException(msg);
throw protocol_error(in, out, name, seqid, "Unexpected message type");
}
// Extract the service name
boost::tokenizer<boost::char_separator<char> > tok(name, boost::char_separator<char>(":"));
std::vector<std::string> tokens;
@ -161,39 +177,46 @@ public:
services_t::iterator it = services.find(tokens[0]);
if (it != services.end()) {
shared_ptr<TProcessor> processor = it->second;
stdcxx::shared_ptr<TProcessor> processor = it->second;
// Let the processor registered for this service name
// process the message.
return processor
->process(shared_ptr<protocol::TProtocol>(
->process(stdcxx::shared_ptr<protocol::TProtocol>(
new protocol::StoredMessageProtocol(in, tokens[1], type, seqid)),
out,
connectionContext);
} else {
// Unknown service.
in->skip(::apache::thrift::protocol::T_STRUCT);
in->readMessageEnd();
in->getTransport()->readEnd();
std::string msg("TMultiplexedProcessor: Unknown service: ");
msg += tokens[0];
::apache::thrift::TApplicationException
x(::apache::thrift::TApplicationException::PROTOCOL_ERROR, msg);
out->writeMessageBegin(name, ::apache::thrift::protocol::T_EXCEPTION, seqid);
x.write(out.get());
out->writeMessageEnd();
out->getTransport()->writeEnd();
out->getTransport()->flush();
msg += ". Did you forget to call registerProcessor()?";
throw TException(msg);
throw protocol_error(in, out, name, seqid,
"Unknown service: " + tokens[0] +
". Did you forget to call registerProcessor()?");
}
} else if (tokens.size() == 1) {
if (defaultProcessor) {
// non-multiplexed client forwards to default processor
return defaultProcessor
->process(stdcxx::shared_ptr<protocol::TProtocol>(
new protocol::StoredMessageProtocol(in, tokens[0], type, seqid)),
out,
connectionContext);
} else {
throw protocol_error(in, out, name, seqid,
"Non-multiplexed client request dropped. "
"Did you forget to call defaultProcessor()?");
}
} else {
throw protocol_error(in, out, name, seqid,
"Wrong number of tokens.");
}
return false;
}
private:
/** Map of service processor objects, indexed by service names. */
services_t services;
//! If a non-multi client requests something, it goes to the
//! default processor (if one is defined) for backwards compatibility.
stdcxx::shared_ptr<TProcessor> defaultProcessor;
};
}
}

View file

@ -23,7 +23,7 @@
#include <thrift/protocol/TProtocol.h>
#include <thrift/protocol/TVirtualProtocol.h>
#include <boost/shared_ptr.hpp>
#include <thrift/stdcxx.h>
namespace apache {
namespace thrift {
@ -41,7 +41,7 @@ public:
static const int32_t VERSION_1 = ((int32_t)0x80010000);
// VERSION_2 (0x80020000) was taken by TDenseProtocol (which has since been removed)
TBinaryProtocolT(boost::shared_ptr<Transport_> trans)
TBinaryProtocolT(stdcxx::shared_ptr<Transport_> trans)
: TVirtualProtocol<TBinaryProtocolT<Transport_, ByteOrder_> >(trans),
trans_(trans.get()),
string_limit_(0),
@ -49,7 +49,7 @@ public:
strict_read_(false),
strict_write_(true) {}
TBinaryProtocolT(boost::shared_ptr<Transport_> trans,
TBinaryProtocolT(stdcxx::shared_ptr<Transport_> trans,
int32_t string_limit,
int32_t container_limit,
bool strict_read,
@ -212,8 +212,8 @@ public:
strict_write_ = strict_write;
}
boost::shared_ptr<TProtocol> getProtocol(boost::shared_ptr<TTransport> trans) {
boost::shared_ptr<Transport_> specific_trans = boost::dynamic_pointer_cast<Transport_>(trans);
stdcxx::shared_ptr<TProtocol> getProtocol(stdcxx::shared_ptr<TTransport> trans) {
stdcxx::shared_ptr<Transport_> specific_trans = stdcxx::dynamic_pointer_cast<Transport_>(trans);
TProtocol* prot;
if (specific_trans) {
prot = new TBinaryProtocolT<Transport_, ByteOrder_>(specific_trans,
@ -229,7 +229,7 @@ public:
strict_write_);
}
return boost::shared_ptr<TProtocol>(prot);
return stdcxx::shared_ptr<TProtocol>(prot);
}
private:

View file

@ -23,7 +23,7 @@
#include <thrift/protocol/TVirtualProtocol.h>
#include <stack>
#include <boost/shared_ptr.hpp>
#include <thrift/stdcxx.h>
namespace apache {
namespace thrift {
@ -74,7 +74,7 @@ protected:
int16_t lastFieldId_;
public:
TCompactProtocolT(boost::shared_ptr<Transport_> trans)
TCompactProtocolT(stdcxx::shared_ptr<Transport_> trans)
: TVirtualProtocol<TCompactProtocolT<Transport_> >(trans),
trans_(trans.get()),
lastFieldId_(0),
@ -86,7 +86,7 @@ public:
boolValue_.hasBoolValue = false;
}
TCompactProtocolT(boost::shared_ptr<Transport_> trans,
TCompactProtocolT(stdcxx::shared_ptr<Transport_> trans,
int32_t string_limit,
int32_t container_limit)
: TVirtualProtocol<TCompactProtocolT<Transport_> >(trans),
@ -239,8 +239,8 @@ public:
void setContainerSizeLimit(int32_t container_limit) { container_limit_ = container_limit; }
boost::shared_ptr<TProtocol> getProtocol(boost::shared_ptr<TTransport> trans) {
boost::shared_ptr<Transport_> specific_trans = boost::dynamic_pointer_cast<Transport_>(trans);
stdcxx::shared_ptr<TProtocol> getProtocol(stdcxx::shared_ptr<TTransport> trans) {
stdcxx::shared_ptr<Transport_> specific_trans = stdcxx::dynamic_pointer_cast<Transport_>(trans);
TProtocol* prot;
if (specific_trans) {
prot = new TCompactProtocolT<Transport_>(specific_trans, string_limit_, container_limit_);
@ -248,7 +248,7 @@ public:
prot = new TCompactProtocol(trans, string_limit_, container_limit_);
}
return boost::shared_ptr<TProtocol>(prot);
return stdcxx::shared_ptr<TProtocol>(prot);
}
private:

View file

@ -387,7 +387,7 @@ uint32_t TCompactProtocolT<Transport_>::writeVarint64(uint64_t n) {
*/
template <class Transport_>
uint64_t TCompactProtocolT<Transport_>::i64ToZigzag(const int64_t l) {
return (l << 1) ^ (l >> 63);
return (static_cast<uint64_t>(l) << 1) ^ (l >> 63);
}
/**
@ -396,7 +396,7 @@ uint64_t TCompactProtocolT<Transport_>::i64ToZigzag(const int64_t l) {
*/
template <class Transport_>
uint32_t TCompactProtocolT<Transport_>::i32ToZigzag(const int32_t n) {
return (n << 1) ^ (n >> 31);
return (static_cast<uint32_t>(n) << 1) ^ (n >> 31);
}
/**

View file

@ -19,12 +19,12 @@
#include <thrift/protocol/TDebugProtocol.h>
#include <thrift/TToString.h>
#include <cassert>
#include <cctype>
#include <cstdio>
#include <stdexcept>
#include <boost/static_assert.hpp>
#include <boost/lexical_cast.hpp>
using std::string;
@ -129,7 +129,7 @@ uint32_t TDebugProtocol::startItem() {
case MAP_VALUE:
return writePlain(" -> ");
case LIST:
size = writeIndented("[" + boost::lexical_cast<string>(list_idx_.back()) + "] = ");
size = writeIndented("[" + to_string(list_idx_.back()) + "] = ");
list_idx_.back()++;
return size;
default:
@ -223,7 +223,7 @@ uint32_t TDebugProtocol::writeFieldBegin(const char* name,
const TType fieldType,
const int16_t fieldId) {
// sprintf(id_str, "%02d", fieldId);
string id_str = boost::lexical_cast<string>(fieldId);
string id_str = to_string(fieldId);
if (id_str.length() == 1)
id_str = '0' + id_str;
@ -248,7 +248,7 @@ uint32_t TDebugProtocol::writeMapBegin(const TType keyType,
bsize += startItem();
bsize += writePlain(
"map<" + fieldTypeName(keyType) + "," + fieldTypeName(valType) + ">"
"[" + boost::lexical_cast<string>(size) + "] {\n");
"[" + to_string(size) + "] {\n");
indentUp();
write_state_.push_back(MAP_KEY);
return bsize;
@ -269,7 +269,7 @@ uint32_t TDebugProtocol::writeListBegin(const TType elemType, const uint32_t siz
bsize += startItem();
bsize += writePlain(
"list<" + fieldTypeName(elemType) + ">"
"[" + boost::lexical_cast<string>(size) + "] {\n");
"[" + to_string(size) + "] {\n");
indentUp();
write_state_.push_back(LIST);
list_idx_.push_back(0);
@ -292,7 +292,7 @@ uint32_t TDebugProtocol::writeSetBegin(const TType elemType, const uint32_t size
bsize += startItem();
bsize += writePlain(
"set<" + fieldTypeName(elemType) + ">"
"[" + boost::lexical_cast<string>(size) + "] {\n");
"[" + to_string(size) + "] {\n");
indentUp();
write_state_.push_back(SET);
return bsize;
@ -316,19 +316,19 @@ uint32_t TDebugProtocol::writeByte(const int8_t byte) {
}
uint32_t TDebugProtocol::writeI16(const int16_t i16) {
return writeItem(boost::lexical_cast<string>(i16));
return writeItem(to_string(i16));
}
uint32_t TDebugProtocol::writeI32(const int32_t i32) {
return writeItem(boost::lexical_cast<string>(i32));
return writeItem(to_string(i32));
}
uint32_t TDebugProtocol::writeI64(const int64_t i64) {
return writeItem(boost::lexical_cast<string>(i64));
return writeItem(to_string(i64));
}
uint32_t TDebugProtocol::writeDouble(const double dub) {
return writeItem(boost::lexical_cast<string>(dub));
return writeItem(to_string(dub));
}
uint32_t TDebugProtocol::writeString(const string& str) {
@ -337,7 +337,7 @@ uint32_t TDebugProtocol::writeString(const string& str) {
string to_show = str;
if (to_show.length() > (string::size_type)string_limit_) {
to_show = str.substr(0, string_prefix_size_);
to_show += "[...](" + boost::lexical_cast<string>(str.length()) + ")";
to_show += "[...](" + to_string(str.length()) + ")";
}
string output = "\"";

View file

@ -22,7 +22,7 @@
#include <thrift/protocol/TVirtualProtocol.h>
#include <boost/shared_ptr.hpp>
#include <thrift/stdcxx.h>
namespace apache {
namespace thrift {
@ -51,7 +51,7 @@ private:
enum write_state_t { UNINIT, STRUCT, LIST, SET, MAP_KEY, MAP_VALUE };
public:
TDebugProtocol(boost::shared_ptr<TTransport> trans)
TDebugProtocol(stdcxx::shared_ptr<TTransport> trans)
: TVirtualProtocol<TDebugProtocol>(trans),
trans_(trans.get()),
string_limit_(DEFAULT_STRING_LIMIT),
@ -141,8 +141,8 @@ public:
TDebugProtocolFactory() {}
virtual ~TDebugProtocolFactory() {}
boost::shared_ptr<TProtocol> getProtocol(boost::shared_ptr<TTransport> trans) {
return boost::shared_ptr<TProtocol>(new TDebugProtocol(trans));
stdcxx::shared_ptr<TProtocol> getProtocol(stdcxx::shared_ptr<TTransport> trans) {
return stdcxx::shared_ptr<TProtocol>(new TDebugProtocol(trans));
}
};
}
@ -160,7 +160,7 @@ std::string ThriftDebugString(const ThriftStruct& ts) {
using namespace apache::thrift::transport;
using namespace apache::thrift::protocol;
TMemoryBuffer* buffer = new TMemoryBuffer;
boost::shared_ptr<TTransport> trans(buffer);
stdcxx::shared_ptr<TTransport> trans(buffer);
TDebugProtocol protocol(trans);
ts.write(&protocol);
@ -178,7 +178,7 @@ std::string DebugString(const std::vector<Object>& vec) {
using namespace apache::thrift::transport;
using namespace apache::thrift::protocol;
TMemoryBuffer* buffer = new TMemoryBuffer;
boost::shared_ptr<TTransport> trans(buffer);
stdcxx::shared_ptr<TTransport> trans(buffer);
TDebugProtocol protocol(trans);
// I am gross!

View file

@ -27,7 +27,7 @@
#include <limits>
#include <boost/static_assert.hpp>
#include <boost/make_shared.hpp>
#include <thrift/stdcxx.h>
namespace apache {
namespace thrift {
@ -42,11 +42,11 @@ void THeaderProtocol::resetProtocol() {
switch (protoId_) {
case T_BINARY_PROTOCOL:
proto_ = boost::make_shared<TBinaryProtocolT<THeaderTransport> >(trans_);
proto_ = stdcxx::make_shared<TBinaryProtocolT<THeaderTransport> >(trans_);
break;
case T_COMPACT_PROTOCOL:
proto_ = boost::make_shared<TCompactProtocolT<THeaderTransport> >(trans_);
proto_ = stdcxx::make_shared<TCompactProtocolT<THeaderTransport> >(trans_);
break;
default:

View file

@ -25,7 +25,7 @@
#include <thrift/protocol/TVirtualProtocol.h>
#include <thrift/transport/THeaderTransport.h>
#include <boost/shared_ptr.hpp>
#include <thrift/stdcxx.h>
using apache::thrift::transport::THeaderTransport;
@ -43,21 +43,21 @@ protected:
public:
void resetProtocol();
explicit THeaderProtocol(const boost::shared_ptr<TTransport>& trans,
explicit THeaderProtocol(const stdcxx::shared_ptr<TTransport>& trans,
uint16_t protoId = T_COMPACT_PROTOCOL)
: TVirtualProtocol<THeaderProtocol>(boost::shared_ptr<TTransport>(new THeaderTransport(trans))),
trans_(boost::dynamic_pointer_cast<THeaderTransport>(this->getTransport())),
: TVirtualProtocol<THeaderProtocol>(stdcxx::shared_ptr<TTransport>(new THeaderTransport(trans))),
trans_(stdcxx::dynamic_pointer_cast<THeaderTransport>(getTransport())),
protoId_(protoId) {
trans_->setProtocolId(protoId);
resetProtocol();
}
THeaderProtocol(const boost::shared_ptr<TTransport>& inTrans,
const boost::shared_ptr<TTransport>& outTrans,
THeaderProtocol(const stdcxx::shared_ptr<TTransport>& inTrans,
const stdcxx::shared_ptr<TTransport>& outTrans,
uint16_t protoId = T_COMPACT_PROTOCOL)
: TVirtualProtocol<THeaderProtocol>(
boost::shared_ptr<TTransport>(new THeaderTransport(inTrans, outTrans))),
trans_(boost::dynamic_pointer_cast<THeaderTransport>(this->getTransport())),
stdcxx::shared_ptr<TTransport>(new THeaderTransport(inTrans, outTrans))),
trans_(stdcxx::dynamic_pointer_cast<THeaderTransport>(getTransport())),
protoId_(protoId) {
trans_->setProtocolId(protoId);
resetProtocol();
@ -182,25 +182,25 @@ public:
uint32_t readBinary(std::string& binary);
protected:
boost::shared_ptr<THeaderTransport> trans_;
stdcxx::shared_ptr<THeaderTransport> trans_;
boost::shared_ptr<TProtocol> proto_;
stdcxx::shared_ptr<TProtocol> proto_;
uint32_t protoId_;
};
class THeaderProtocolFactory : public TProtocolFactory {
public:
virtual boost::shared_ptr<TProtocol> getProtocol(boost::shared_ptr<transport::TTransport> trans) {
virtual stdcxx::shared_ptr<TProtocol> getProtocol(stdcxx::shared_ptr<transport::TTransport> trans) {
THeaderProtocol* headerProtocol
= new THeaderProtocol(trans, boost::shared_ptr<transport::TTransport>(), T_BINARY_PROTOCOL);
return boost::shared_ptr<TProtocol>(headerProtocol);
= new THeaderProtocol(trans, trans, T_BINARY_PROTOCOL);
return stdcxx::shared_ptr<TProtocol>(headerProtocol);
}
virtual boost::shared_ptr<TProtocol> getProtocol(
boost::shared_ptr<transport::TTransport> inTrans,
boost::shared_ptr<transport::TTransport> outTrans) {
virtual stdcxx::shared_ptr<TProtocol> getProtocol(
stdcxx::shared_ptr<transport::TTransport> inTrans,
stdcxx::shared_ptr<transport::TTransport> outTrans) {
THeaderProtocol* headerProtocol = new THeaderProtocol(inTrans, outTrans, T_BINARY_PROTOCOL);
return boost::shared_ptr<TProtocol>(headerProtocol);
return stdcxx::shared_ptr<TProtocol>(headerProtocol);
}
};
}

View file

@ -19,9 +19,9 @@
#include <thrift/protocol/TJSONProtocol.h>
#include <boost/lexical_cast.hpp>
#include <boost/locale.hpp>
#include <boost/math/special_functions/fpclassify.hpp>
#include <boost/math/special_functions/sign.hpp>
#include <cmath>
#include <limits>
@ -31,6 +31,7 @@
#include <thrift/protocol/TBase64Utils.h>
#include <thrift/transport/TTransportException.h>
#include <thrift/TToString.h>
using namespace apache::thrift::transport;
@ -397,7 +398,7 @@ private:
bool first_;
};
TJSONProtocol::TJSONProtocol(boost::shared_ptr<TTransport> ptrans)
TJSONProtocol::TJSONProtocol(stdcxx::shared_ptr<TTransport> ptrans)
: TVirtualProtocol<TJSONProtocol>(ptrans),
trans_(ptrans.get()),
context_(new TJSONContext()),
@ -407,7 +408,7 @@ TJSONProtocol::TJSONProtocol(boost::shared_ptr<TTransport> ptrans)
TJSONProtocol::~TJSONProtocol() {
}
void TJSONProtocol::pushContext(boost::shared_ptr<TJSONContext> c) {
void TJSONProtocol::pushContext(stdcxx::shared_ptr<TJSONContext> c) {
contexts_.push(context_);
context_ = c;
}
@ -503,7 +504,7 @@ uint32_t TJSONProtocol::writeJSONBase64(const std::string& str) {
template <typename NumberType>
uint32_t TJSONProtocol::writeJSONInteger(NumberType num) {
uint32_t result = context_->write(*trans_);
std::string val(boost::lexical_cast<std::string>(num));
std::string val(to_string(num));
bool escapeNum = context_->escapeNum();
if (escapeNum) {
trans_->write(&kJSONStringDelimiter, 1);
@ -524,7 +525,7 @@ namespace {
std::string doubleToString(double d) {
std::ostringstream str;
str.imbue(std::locale::classic());
const int max_digits10 = 2 + std::numeric_limits<double>::digits10;
const std::streamsize max_digits10 = 2 + std::numeric_limits<double>::digits10;
str.precision(max_digits10);
str << d;
return str.str();
@ -575,7 +576,7 @@ uint32_t TJSONProtocol::writeJSONDouble(double num) {
uint32_t TJSONProtocol::writeJSONObjectStart() {
uint32_t result = context_->write(*trans_);
trans_->write(&kJSONObjectStart, 1);
pushContext(boost::shared_ptr<TJSONContext>(new JSONPairContext()));
pushContext(stdcxx::shared_ptr<TJSONContext>(new JSONPairContext()));
return result + 1;
}
@ -588,7 +589,7 @@ uint32_t TJSONProtocol::writeJSONObjectEnd() {
uint32_t TJSONProtocol::writeJSONArrayStart() {
uint32_t result = context_->write(*trans_);
trans_->write(&kJSONArrayStart, 1);
pushContext(boost::shared_ptr<TJSONContext>(new JSONListContext()));
pushContext(stdcxx::shared_ptr<TJSONContext>(new JSONListContext()));
return result + 1;
}
@ -684,7 +685,7 @@ uint32_t TJSONProtocol::writeBool(const bool value) {
}
uint32_t TJSONProtocol::writeByte(const int8_t byte) {
// writeByte() must be handled specially because boost::lexical cast sees
// writeByte() must be handled specially because to_string sees
// int8_t as a text type instead of an integer type
return writeJSONInteger((int16_t)byte);
}
@ -772,7 +773,7 @@ uint32_t TJSONProtocol::readJSONString(std::string& str, bool skipContext) {
continue;
} else {
size_t pos = kEscapeChars.find(ch);
if (pos == std::string::npos) {
if (pos == kEscapeChars.npos) {
throw TProtocolException(TProtocolException::INVALID_DATA,
"Expected control char, got '" + std::string((const char*)&ch, 1)
+ "'.");
@ -842,6 +843,19 @@ uint32_t TJSONProtocol::readJSONNumericChars(std::string& str) {
return result;
}
namespace {
template <typename T>
T fromString(const std::string& s) {
T t;
std::istringstream str(s);
str.imbue(std::locale::classic());
str >> t;
if (str.bad() || !str.eof())
throw std::runtime_error(s);
return t;
}
}
// Reads a sequence of characters and assembles them into a number,
// returning them via num
template <typename NumberType>
@ -853,10 +867,10 @@ uint32_t TJSONProtocol::readJSONInteger(NumberType& num) {
std::string str;
result += readJSONNumericChars(str);
try {
num = boost::lexical_cast<NumberType>(str);
} catch (boost::bad_lexical_cast e) {
num = fromString<NumberType>(str);
} catch (const std::runtime_error&) {
throw TProtocolException(TProtocolException::INVALID_DATA,
"Expected numeric value; got \"" + str + "\"");
"Expected numeric value; got \"" + str + "\"");
}
if (context_->escapeNum()) {
result += readJSONSyntaxChar(kJSONStringDelimiter);
@ -864,18 +878,6 @@ uint32_t TJSONProtocol::readJSONInteger(NumberType& num) {
return result;
}
namespace {
double stringToDouble(const std::string& s) {
double d;
std::istringstream str(s);
str.imbue(std::locale::classic());
str >> d;
if (str.bad() || !str.eof())
throw std::runtime_error(s);
return d;
}
}
// Reads a JSON number or string and interprets it as a double.
uint32_t TJSONProtocol::readJSONDouble(double& num) {
uint32_t result = context_->read(reader_);
@ -896,8 +898,8 @@ uint32_t TJSONProtocol::readJSONDouble(double& num) {
"Numeric data unexpectedly quoted");
}
try {
num = stringToDouble(str);
} catch (std::runtime_error e) {
num = fromString<double>(str);
} catch (std::runtime_error& e) {
throw TProtocolException(TProtocolException::INVALID_DATA,
"Expected numeric value; got \"" + str + "\"");
}
@ -909,8 +911,8 @@ uint32_t TJSONProtocol::readJSONDouble(double& num) {
}
result += readJSONNumericChars(str);
try {
num = stringToDouble(str);
} catch (std::runtime_error e) {
num = fromString<double>(str);
} catch (std::runtime_error& e) {
throw TProtocolException(TProtocolException::INVALID_DATA,
"Expected numeric value; got \"" + str + "\"");
}
@ -921,7 +923,7 @@ uint32_t TJSONProtocol::readJSONDouble(double& num) {
uint32_t TJSONProtocol::readJSONObjectStart() {
uint32_t result = context_->read(reader_);
result += readJSONSyntaxChar(kJSONObjectStart);
pushContext(boost::shared_ptr<TJSONContext>(new JSONPairContext()));
pushContext(stdcxx::shared_ptr<TJSONContext>(new JSONPairContext()));
return result;
}
@ -934,7 +936,7 @@ uint32_t TJSONProtocol::readJSONObjectEnd() {
uint32_t TJSONProtocol::readJSONArrayStart() {
uint32_t result = context_->read(reader_);
result += readJSONSyntaxChar(kJSONArrayStart);
pushContext(boost::shared_ptr<TJSONContext>(new JSONListContext()));
pushContext(stdcxx::shared_ptr<TJSONContext>(new JSONListContext()));
return result;
}

View file

@ -87,20 +87,21 @@ class TJSONContext;
* the current implementation is to match as closely as possible the behavior
* of Java's Double.toString(), which has no precision loss. Implementors in
* other languages should strive to achieve that where possible. I have not
* yet verified whether boost:lexical_cast, which is doing that work for me in
* C++, loses any precision, but I am leaving this as a future improvement. I
* may try to provide a C component for this, so that other languages could
* bind to the same underlying implementation for maximum consistency.
* yet verified whether std::istringstream::operator>>, which is doing that
* work for me in C++, loses any precision, but I am leaving this as a future
* improvement. I may try to provide a C component for this, so that other
* languages could bind to the same underlying implementation for maximum
* consistency.
*
*/
class TJSONProtocol : public TVirtualProtocol<TJSONProtocol> {
public:
TJSONProtocol(boost::shared_ptr<TTransport> ptrans);
TJSONProtocol(stdcxx::shared_ptr<TTransport> ptrans);
~TJSONProtocol();
private:
void pushContext(boost::shared_ptr<TJSONContext> c);
void pushContext(stdcxx::shared_ptr<TJSONContext> c);
void popContext();
@ -275,8 +276,8 @@ public:
private:
TTransport* trans_;
std::stack<boost::shared_ptr<TJSONContext> > contexts_;
boost::shared_ptr<TJSONContext> context_;
std::stack<stdcxx::shared_ptr<TJSONContext> > contexts_;
stdcxx::shared_ptr<TJSONContext> context_;
LookaheadReader reader_;
};
@ -289,8 +290,8 @@ public:
virtual ~TJSONProtocolFactory() {}
boost::shared_ptr<TProtocol> getProtocol(boost::shared_ptr<TTransport> trans) {
return boost::shared_ptr<TProtocol>(new TJSONProtocol(trans));
stdcxx::shared_ptr<TProtocol> getProtocol(stdcxx::shared_ptr<TTransport> trans) {
return stdcxx::shared_ptr<TProtocol>(new TJSONProtocol(trans));
}
};
}
@ -308,7 +309,7 @@ std::string ThriftJSONString(const ThriftStruct& ts) {
using namespace apache::thrift::transport;
using namespace apache::thrift::protocol;
TMemoryBuffer* buffer = new TMemoryBuffer;
boost::shared_ptr<TTransport> trans(buffer);
stdcxx::shared_ptr<TTransport> trans(buffer);
TJSONProtocol protocol(trans);
ts.write(&protocol);

View file

@ -25,7 +25,7 @@
namespace apache {
namespace thrift {
namespace protocol {
using boost::shared_ptr;
using stdcxx::shared_ptr;
/**
* <code>TMultiplexedProtocol</code> is a protocol-independent concrete decorator

View file

@ -28,7 +28,7 @@
#include <thrift/transport/TTransport.h>
#include <thrift/protocol/TProtocolException.h>
#include <boost/shared_ptr.hpp>
#include <thrift/stdcxx.h>
#include <boost/static_assert.hpp>
#ifdef HAVE_NETINET_IN_H
@ -550,12 +550,12 @@ public:
}
virtual uint32_t skip_virt(TType type);
inline boost::shared_ptr<TTransport> getTransport() { return ptrans_; }
inline stdcxx::shared_ptr<TTransport> getTransport() { return ptrans_; }
// TODO: remove these two calls, they are for backwards
// compatibility
inline boost::shared_ptr<TTransport> getInputTransport() { return ptrans_; }
inline boost::shared_ptr<TTransport> getOutputTransport() { return ptrans_; }
inline stdcxx::shared_ptr<TTransport> getInputTransport() { return ptrans_; }
inline stdcxx::shared_ptr<TTransport> getOutputTransport() { return ptrans_; }
// input and output recursion depth are kept separate so that one protocol
// can be used concurrently for both input and output.
@ -577,11 +577,11 @@ public:
void setRecurisionLimit(uint32_t depth) {recursion_limit_ = depth;}
protected:
TProtocol(boost::shared_ptr<TTransport> ptrans)
TProtocol(stdcxx::shared_ptr<TTransport> ptrans)
: ptrans_(ptrans), input_recursion_depth_(0), output_recursion_depth_(0), recursion_limit_(DEFAULT_RECURSION_LIMIT)
{}
boost::shared_ptr<TTransport> ptrans_;
stdcxx::shared_ptr<TTransport> ptrans_;
private:
TProtocol() {}
@ -599,9 +599,9 @@ public:
virtual ~TProtocolFactory();
virtual boost::shared_ptr<TProtocol> getProtocol(boost::shared_ptr<TTransport> trans) = 0;
virtual boost::shared_ptr<TProtocol> getProtocol(boost::shared_ptr<TTransport> inTrans,
boost::shared_ptr<TTransport> outTrans) {
virtual stdcxx::shared_ptr<TProtocol> getProtocol(stdcxx::shared_ptr<TTransport> trans) = 0;
virtual stdcxx::shared_ptr<TProtocol> getProtocol(stdcxx::shared_ptr<TTransport> inTrans,
stdcxx::shared_ptr<TTransport> outTrans) {
(void)outTrans;
return getProtocol(inTrans);
}
@ -672,7 +672,7 @@ uint32_t skip(Protocol_& prot, TType type) {
return prot.readBool(boolv);
}
case T_BYTE: {
int8_t bytev;
int8_t bytev = 0;
return prot.readByte(bytev);
}
case T_I16: {
@ -753,6 +753,8 @@ uint32_t skip(Protocol_& prot, TType type) {
case T_UTF8:
case T_UTF16:
break;
default:
throw TProtocolException(TProtocolException::INVALID_DATA);
}
return 0;
}

View file

@ -21,12 +21,12 @@
#define THRIFT_TPROTOCOLDECORATOR_H_ 1
#include <thrift/protocol/TProtocol.h>
#include <boost/shared_ptr.hpp>
#include <thrift/stdcxx.h>
namespace apache {
namespace thrift {
namespace protocol {
using boost::shared_ptr;
using stdcxx::shared_ptr;
/**
* <code>TProtocolDecorator</code> forwards all requests to an enclosed

View file

@ -36,7 +36,7 @@ using apache::thrift::transport::TTransport;
*/
class TProtocolTap : public TVirtualProtocol<TProtocolTap> {
public:
TProtocolTap(boost::shared_ptr<TProtocol> source, boost::shared_ptr<TProtocol> sink)
TProtocolTap(stdcxx::shared_ptr<TProtocol> source, stdcxx::shared_ptr<TProtocol> sink)
: TVirtualProtocol<TProtocolTap>(source->getTransport()), source_(source), sink_(sink) {}
uint32_t readMessageBegin(std::string& name, TMessageType& messageType, int32_t& seqid) {
@ -167,8 +167,8 @@ public:
}
private:
boost::shared_ptr<TProtocol> source_;
boost::shared_ptr<TProtocol> sink_;
stdcxx::shared_ptr<TProtocol> source_;
stdcxx::shared_ptr<TProtocol> sink_;
};
}
}

View file

@ -301,7 +301,7 @@ public:
uint32_t skip(TType type) { return ::apache::thrift::protocol::skip(*this, type); }
protected:
TProtocolDefaults(boost::shared_ptr<TTransport> ptrans) : TProtocol(ptrans) {}
TProtocolDefaults(stdcxx::shared_ptr<TTransport> ptrans) : TProtocol(ptrans) {}
};
/**
@ -504,7 +504,7 @@ public:
using Super_::readBool; // so we don't hide readBool(bool&)
protected:
TVirtualProtocol(boost::shared_ptr<TTransport> ptrans) : Super_(ptrans) {}
TVirtualProtocol(stdcxx::shared_ptr<TTransport> ptrans) : Super_(ptrans) {}
};
}
}

View file

@ -23,11 +23,13 @@
#include <QIODevice>
#include <thrift/transport/TBufferTransports.h>
using boost::shared_ptr;
#include <thrift/stdcxx.h>
namespace apache {
namespace thrift {
using stdcxx::shared_ptr;
namespace transport {
TQIODeviceTransport::TQIODeviceTransport(shared_ptr<QIODevice> dev) : dev_(dev) {
@ -89,7 +91,7 @@ uint32_t TQIODeviceTransport::read(uint8_t* buf, uint32_t len) {
"read(): underlying QIODevice is not open");
}
actualSize = (uint32_t)std::min((qint64)len, dev_->bytesAvailable());
actualSize = (uint32_t)(std::min)((qint64)len, dev_->bytesAvailable());
readSize = dev_->read(reinterpret_cast<char*>(buf), actualSize);
if (readSize < 0) {

View file

@ -20,7 +20,7 @@
#ifndef _THRIFT_ASYNC_TQIODEVICE_TRANSPORT_H_
#define _THRIFT_ASYNC_TQIODEVICE_TRANSPORT_H_ 1
#include <boost/shared_ptr.hpp>
#include <thrift/stdcxx.h>
#include <thrift/transport/TVirtualTransport.h>
@ -36,7 +36,7 @@ namespace transport {
class TQIODeviceTransport
: public apache::thrift::transport::TVirtualTransport<TQIODeviceTransport> {
public:
explicit TQIODeviceTransport(boost::shared_ptr<QIODevice> dev);
explicit TQIODeviceTransport(stdcxx::shared_ptr<QIODevice> dev);
virtual ~TQIODeviceTransport();
void open();
@ -59,7 +59,7 @@ private:
TQIODeviceTransport(const TQIODeviceTransport&);
TQIODeviceTransport& operator=(const TQIODeviceTransport&);
boost::shared_ptr<QIODevice> dev_;
stdcxx::shared_ptr<QIODevice> dev_;
};
}
}

View file

@ -23,19 +23,20 @@
#include <QMetaType>
#include <QTcpSocket>
#include <thrift/cxxfunctional.h>
#include <thrift/stdcxx.h>
#include <thrift/protocol/TProtocol.h>
#include <thrift/async/TAsyncProcessor.h>
using boost::shared_ptr;
using apache::thrift::protocol::TProtocol;
using apache::thrift::protocol::TProtocolFactory;
using apache::thrift::transport::TTransport;
using apache::thrift::transport::TTransportException;
using apache::thrift::transport::TQIODeviceTransport;
using apache::thrift::stdcxx::function;
using apache::thrift::stdcxx::bind;
using apache::thrift::stdcxx::function;
using apache::thrift::stdcxx::placeholders::_1;
using apache::thrift::stdcxx::shared_ptr;
QT_USE_NAMESPACE
@ -110,7 +111,7 @@ void TQTcpServer::beginDecode() {
try {
processor_
->process(bind(&TQTcpServer::finish, this, ctx, apache::thrift::stdcxx::placeholders::_1),
->process(bind(&TQTcpServer::finish, this, ctx, _1),
ctx->iprot_,
ctx->oprot_);
} catch (const TTransportException& ex) {

View file

@ -23,7 +23,7 @@
#include <QObject>
#include <QTcpServer>
#include <boost/shared_ptr.hpp>
#include <thrift/stdcxx.h>
namespace apache {
namespace thrift {
@ -47,9 +47,9 @@ class TAsyncProcessor;
class TQTcpServer : public QObject {
Q_OBJECT
public:
TQTcpServer(boost::shared_ptr<QTcpServer> server,
boost::shared_ptr<TAsyncProcessor> processor,
boost::shared_ptr<apache::thrift::protocol::TProtocolFactory> protocolFactory,
TQTcpServer(stdcxx::shared_ptr<QTcpServer> server,
stdcxx::shared_ptr<TAsyncProcessor> processor,
stdcxx::shared_ptr<apache::thrift::protocol::TProtocolFactory> protocolFactory,
QObject* parent = NULL);
virtual ~TQTcpServer();
@ -65,13 +65,13 @@ private:
struct ConnectionContext;
void scheduleDeleteConnectionContext(QTcpSocket* connection);
void finish(boost::shared_ptr<ConnectionContext> ctx, bool healthy);
void finish(stdcxx::shared_ptr<ConnectionContext> ctx, bool healthy);
boost::shared_ptr<QTcpServer> server_;
boost::shared_ptr<TAsyncProcessor> processor_;
boost::shared_ptr<apache::thrift::protocol::TProtocolFactory> pfact_;
stdcxx::shared_ptr<QTcpServer> server_;
stdcxx::shared_ptr<TAsyncProcessor> processor_;
stdcxx::shared_ptr<apache::thrift::protocol::TProtocolFactory> pfact_;
typedef std::map<QTcpSocket*, boost::shared_ptr<ConnectionContext> > ConnectionContextMap;
typedef std::map<QTcpSocket*, stdcxx::shared_ptr<ConnectionContext> > ConnectionContextMap;
ConnectionContextMap ctxMap_;
};
}

View file

@ -28,7 +28,7 @@ using apache::thrift::protocol::TProtocol;
using apache::thrift::server::TServerEventHandler;
using apache::thrift::transport::TTransport;
using apache::thrift::transport::TTransportException;
using boost::shared_ptr;
using stdcxx::shared_ptr;
using std::string;
TConnectedClient::TConnectedClient(const shared_ptr<TProcessor>& processor,

View file

@ -20,7 +20,7 @@
#ifndef _THRIFT_SERVER_TCONNECTEDCLIENT_H_
#define _THRIFT_SERVER_TCONNECTEDCLIENT_H_ 1
#include <boost/shared_ptr.hpp>
#include <thrift/stdcxx.h>
#include <thrift/TProcessor.h>
#include <thrift/protocol/TProtocol.h>
#include <thrift/server/TServer.h>
@ -49,11 +49,11 @@ public:
* @param[in] client the TTransport representing the client
*/
TConnectedClient(
const boost::shared_ptr<apache::thrift::TProcessor>& processor,
const boost::shared_ptr<apache::thrift::protocol::TProtocol>& inputProtocol,
const boost::shared_ptr<apache::thrift::protocol::TProtocol>& outputProtocol,
const boost::shared_ptr<apache::thrift::server::TServerEventHandler>& eventHandler,
const boost::shared_ptr<apache::thrift::transport::TTransport>& client);
const stdcxx::shared_ptr<apache::thrift::TProcessor>& processor,
const stdcxx::shared_ptr<apache::thrift::protocol::TProtocol>& inputProtocol,
const stdcxx::shared_ptr<apache::thrift::protocol::TProtocol>& outputProtocol,
const stdcxx::shared_ptr<apache::thrift::server::TServerEventHandler>& eventHandler,
const stdcxx::shared_ptr<apache::thrift::transport::TTransport>& client);
/**
* Destructor.
@ -92,11 +92,11 @@ protected:
virtual void cleanup();
private:
boost::shared_ptr<apache::thrift::TProcessor> processor_;
boost::shared_ptr<apache::thrift::protocol::TProtocol> inputProtocol_;
boost::shared_ptr<apache::thrift::protocol::TProtocol> outputProtocol_;
boost::shared_ptr<apache::thrift::server::TServerEventHandler> eventHandler_;
boost::shared_ptr<apache::thrift::transport::TTransport> client_;
stdcxx::shared_ptr<apache::thrift::TProcessor> processor_;
stdcxx::shared_ptr<apache::thrift::protocol::TProtocol> inputProtocol_;
stdcxx::shared_ptr<apache::thrift::protocol::TProtocol> outputProtocol_;
stdcxx::shared_ptr<apache::thrift::server::TServerEventHandler> eventHandler_;
stdcxx::shared_ptr<apache::thrift::transport::TTransport> client_;
/**
* Context acquired from the eventHandler_ if one exists.

View file

@ -17,8 +17,6 @@
* under the License.
*/
#define __STDC_FORMAT_MACROS
#include <thrift/thrift-config.h>
#include <thrift/server/TNonblockingServer.h>
@ -27,9 +25,14 @@
#include <thrift/concurrency/PlatformThreadFactory.h>
#include <thrift/transport/PlatformSocket.h>
#include <algorithm>
#include <iostream>
#ifdef HAVE_SYS_SELECT_H
#ifdef HAVE_POLL_H
#include <poll.h>
#elif HAVE_SYS_POLL_H
#include <sys/poll.h>
#elif HAVE_SYS_SELECT_H
#include <sys/select.h>
#endif
@ -64,13 +67,12 @@
#define AF_LOCAL AF_UNIX
#endif
#if !defined(PRIu32)
#define PRIu32 "I32u"
#define PRIu64 "I64u"
#ifdef HAVE_INTTYPES_H
#include <inttypes.h>
#endif
#if defined(_WIN32) && (_WIN32_WINNT < 0x0600)
#define AI_ADDRCONFIG 0x0400
#ifdef HAVE_STDINT_H
#include <stdint.h>
#endif
namespace apache {
@ -80,10 +82,9 @@ namespace server {
using namespace apache::thrift::protocol;
using namespace apache::thrift::transport;
using namespace apache::thrift::concurrency;
using namespace std;
using apache::thrift::transport::TSocket;
using apache::thrift::transport::TTransportException;
using boost::shared_ptr;
using stdcxx::shared_ptr;
/// Three states for sockets: recv frame size, recv data, and send mode
enum TSocketState { SOCKET_RECV_FRAMING, SOCKET_RECV, SOCKET_SEND };
@ -118,10 +119,10 @@ private:
TNonblockingServer* server_;
/// TProcessor
boost::shared_ptr<TProcessor> processor_;
stdcxx::shared_ptr<TProcessor> processor_;
/// Object wrapping network socket
boost::shared_ptr<TSocket> tSocket_;
stdcxx::shared_ptr<TSocket> tSocket_;
/// Libevent object
struct event event_;
@ -163,23 +164,23 @@ private:
int32_t callsForResize_;
/// Transport to read from
boost::shared_ptr<TMemoryBuffer> inputTransport_;
stdcxx::shared_ptr<TMemoryBuffer> inputTransport_;
/// Transport that processor writes to
boost::shared_ptr<TMemoryBuffer> outputTransport_;
stdcxx::shared_ptr<TMemoryBuffer> outputTransport_;
/// extra transport generated by transport factory (e.g. BufferedRouterTransport)
boost::shared_ptr<TTransport> factoryInputTransport_;
boost::shared_ptr<TTransport> factoryOutputTransport_;
stdcxx::shared_ptr<TTransport> factoryInputTransport_;
stdcxx::shared_ptr<TTransport> factoryOutputTransport_;
/// Protocol decoder
boost::shared_ptr<TProtocol> inputProtocol_;
stdcxx::shared_ptr<TProtocol> inputProtocol_;
/// Protocol encoder
boost::shared_ptr<TProtocol> outputProtocol_;
stdcxx::shared_ptr<TProtocol> outputProtocol_;
/// Server event handler, if any
boost::shared_ptr<TServerEventHandler> serverEventHandler_;
stdcxx::shared_ptr<TServerEventHandler> serverEventHandler_;
/// Thrift call context, if any
void* connectionContext_;
@ -212,10 +213,8 @@ public:
class Task;
/// Constructor
TConnection(THRIFT_SOCKET socket,
TNonblockingIOThread* ioThread,
const sockaddr* addr,
socklen_t addrLen) {
TConnection(stdcxx::shared_ptr<TSocket> socket,
TNonblockingIOThread* ioThread) {
readBuffer_ = NULL;
readBufferSize_ = 0;
@ -227,8 +226,10 @@ public:
inputTransport_.reset(new TMemoryBuffer(readBuffer_, readBufferSize_));
outputTransport_.reset(
new TMemoryBuffer(static_cast<uint32_t>(server_->getWriteBufferDefaultSize())));
tSocket_.reset(new TSocket());
init(socket, ioThread, addr, addrLen);
tSocket_ = socket;
init(ioThread);
}
~TConnection() { std::free(readBuffer_); }
@ -245,10 +246,10 @@ public:
void checkIdleBufferMemLimit(size_t readLimit, size_t writeLimit);
/// Initialize
void init(THRIFT_SOCKET socket,
TNonblockingIOThread* ioThread,
const sockaddr* addr,
socklen_t addrLen);
void init(TNonblockingIOThread* ioThread);
/// set socket for connection
void setSocket(stdcxx::shared_ptr<TSocket> socket);
/**
* This is called when the application transitions from one state into
@ -291,6 +292,7 @@ public:
void forceClose() {
appState_ = APP_CLOSE_CONNECTION;
if (!notifyIOThread()) {
server_->decrementActiveProcessors();
close();
throw TException("TConnection::forceClose: failed write on notify pipe");
}
@ -303,10 +305,10 @@ public:
TAppState getState() const { return appState_; }
/// return the TSocket transport wrapping this network connection
boost::shared_ptr<TSocket> getTSocket() const { return tSocket_; }
stdcxx::shared_ptr<TSocket> getTSocket() const { return tSocket_; }
/// return the server event handler if any
boost::shared_ptr<TServerEventHandler> getServerEventHandler() { return serverEventHandler_; }
stdcxx::shared_ptr<TServerEventHandler> getServerEventHandler() { return serverEventHandler_; }
/// return the Thrift connection context if any
void* getConnectionContext() { return connectionContext_; }
@ -314,9 +316,9 @@ public:
class TNonblockingServer::TConnection::Task : public Runnable {
public:
Task(boost::shared_ptr<TProcessor> processor,
boost::shared_ptr<TProtocol> input,
boost::shared_ptr<TProtocol> output,
Task(stdcxx::shared_ptr<TProcessor> processor,
stdcxx::shared_ptr<TProtocol> input,
stdcxx::shared_ptr<TProtocol> output,
TConnection* connection)
: processor_(processor),
input_(input),
@ -338,7 +340,7 @@ public:
}
} catch (const TTransportException& ttx) {
GlobalOutput.printf("TNonblockingServer: client died: %s", ttx.what());
} catch (const bad_alloc&) {
} catch (const std::bad_alloc&) {
GlobalOutput("TNonblockingServer: caught bad_alloc exception.");
exit(1);
} catch (const std::exception& x) {
@ -352,6 +354,7 @@ public:
// Signal completion back to the libevent thread via a pipe
if (!connection_->notifyIOThread()) {
GlobalOutput.printf("TNonblockingServer: failed to notifyIOThread, closing.");
connection_->server_->decrementActiveProcessors();
connection_->close();
throw TException("TNonblockingServer::Task::run: failed write on notify pipe");
}
@ -360,21 +363,15 @@ public:
TConnection* getTConnection() { return connection_; }
private:
boost::shared_ptr<TProcessor> processor_;
boost::shared_ptr<TProtocol> input_;
boost::shared_ptr<TProtocol> output_;
stdcxx::shared_ptr<TProcessor> processor_;
stdcxx::shared_ptr<TProtocol> input_;
stdcxx::shared_ptr<TProtocol> output_;
TConnection* connection_;
boost::shared_ptr<TServerEventHandler> serverEventHandler_;
stdcxx::shared_ptr<TServerEventHandler> serverEventHandler_;
void* connectionContext_;
};
void TNonblockingServer::TConnection::init(THRIFT_SOCKET socket,
TNonblockingIOThread* ioThread,
const sockaddr* addr,
socklen_t addrLen) {
tSocket_->setSocketFD(socket);
tSocket_->setCachedAddress(addr, addrLen);
void TNonblockingServer::TConnection::init(TNonblockingIOThread* ioThread) {
ioThread_ = ioThread;
server_ = ioThread->getServer();
appState_ = APP_INIT;
@ -417,6 +414,10 @@ void TNonblockingServer::TConnection::init(THRIFT_SOCKET socket,
processor_ = server_->getProcessor(inputProtocol_, outputProtocol_, tSocket_);
}
void TNonblockingServer::TConnection::setSocket(stdcxx::shared_ptr<TSocket> socket) {
tSocket_ = socket;
}
void TNonblockingServer::TConnection::workSocket() {
int got = 0, left = 0, sent = 0;
uint32_t fetch = 0;
@ -442,10 +443,14 @@ void TNonblockingServer::TConnection::workSocket() {
}
readBufferPos_ += fetch;
} catch (TTransportException& te) {
GlobalOutput.printf("TConnection::workSocket(): %s", te.what());
close();
//In Nonblocking SSLSocket some operations need to be retried again.
//Current approach is parsing exception message, but a better solution needs to be investigated.
if(!strstr(te.what(), "retry")) {
GlobalOutput.printf("TConnection::workSocket(): %s", te.what());
close();
return;
return;
}
}
if (readBufferPos_ < sizeof(framing.size)) {
@ -471,6 +476,18 @@ void TNonblockingServer::TConnection::workSocket() {
}
// size known; now get the rest of the frame
transition();
// If the socket has more data than the frame header, continue to work on it. This is not strictly necessary for
// regular sockets, because if there is more data, libevent will fire the event handler registered for read
// readiness, which will in turn call workSocket(). However, some socket types (such as TSSLSocket) may have the
// data sitting in their internal buffers and from libevent's perspective, there is no further data available. In
// that case, not having this workSocket() call here would result in a hang as we will never get to work the socket,
// despite having more data.
if (tSocket_->hasPendingDataToRead())
{
workSocket();
}
return;
case SOCKET_RECV:
@ -482,8 +499,12 @@ void TNonblockingServer::TConnection::workSocket() {
fetch = readWant_ - readBufferPos_;
got = tSocket_->read(readBuffer_ + readBufferPos_, fetch);
} catch (TTransportException& te) {
GlobalOutput.printf("TConnection::workSocket(): %s", te.what());
close();
//In Nonblocking SSLSocket some operations need to be retried again.
//Current approach is parsing exception message, but a better solution needs to be investigated.
if(!strstr(te.what(), "retry")) {
GlobalOutput.printf("TConnection::workSocket(): %s", te.what());
close();
}
return;
}
@ -513,7 +534,7 @@ void TNonblockingServer::TConnection::workSocket() {
// If there is no data to send, then let us move on
if (writeBufferPos_ == writeBufferSize_) {
GlobalOutput("WARNING: Send state with no data to send\n");
GlobalOutput("WARNING: Send state with no data to send");
transition();
return;
}
@ -589,26 +610,29 @@ void TNonblockingServer::TConnection::transition() {
// We are setting up a Task to do this work and we will wait on it
// Create task and dispatch to the thread manager
boost::shared_ptr<Runnable> task = boost::shared_ptr<Runnable>(
stdcxx::shared_ptr<Runnable> task = stdcxx::shared_ptr<Runnable>(
new Task(processor_, inputProtocol_, outputProtocol_, this));
// The application is now waiting on the task to finish
appState_ = APP_WAIT_TASK;
// Set this connection idle so that libevent doesn't process more
// data on it while we're still waiting for the threadmanager to
// finish this task
setIdle();
try {
server_->addTask(task);
} catch (IllegalStateException& ise) {
// The ThreadManager is not ready to handle any more tasks (it's probably shutting down).
GlobalOutput.printf("IllegalStateException: Server::process() %s", ise.what());
server_->decrementActiveProcessors();
close();
} catch (TimedOutException& to) {
GlobalOutput.printf("[ERROR] TimedOutException: Server::process() %s", to.what());
server_->decrementActiveProcessors();
close();
}
// Set this connection idle so that libevent doesn't process more
// data on it while we're still waiting for the threadmanager to
// finish this task
setIdle();
return;
} else {
try {
@ -639,6 +663,7 @@ void TNonblockingServer::TConnection::transition() {
return;
}
}
// fallthrough
// Intentionally fall through here, the call to process has written into
// the writeBuffer_
@ -669,9 +694,6 @@ void TNonblockingServer::TConnection::transition() {
appState_ = APP_SEND_RESULT;
setWrite();
// Try to work the socket immediately
// workSocket();
return;
}
@ -690,6 +712,7 @@ void TNonblockingServer::TConnection::transition() {
server_->getIdleWriteBufferLimit());
callsForResize_ = 0;
}
// fallthrough
// N.B.: We also intentionally fall through here into the INIT state!
@ -710,9 +733,6 @@ void TNonblockingServer::TConnection::transition() {
// Register read event
setRead();
// Try to work the socket right away
// workSocket();
return;
case APP_READ_FRAME_SIZE:
@ -745,9 +765,6 @@ void TNonblockingServer::TConnection::transition() {
socketState_ = SOCKET_RECV;
appState_ = APP_READ_REQUEST;
// Work the socket right away
// workSocket();
return;
case APP_CLOSE_CONNECTION:
@ -768,11 +785,9 @@ void TNonblockingServer::TConnection::setFlags(short eventFlags) {
}
// Delete a previously existing event
if (eventFlags_ != 0) {
if (event_del(&event_) == -1) {
GlobalOutput("TConnection::setFlags event_del");
return;
}
if (eventFlags_ && event_del(&event_) == -1) {
GlobalOutput.perror("TConnection::setFlags() event_del", THRIFT_GET_SOCKET_ERROR);
return;
}
// Update in memory structure
@ -815,7 +830,7 @@ void TNonblockingServer::TConnection::setFlags(short eventFlags) {
// Add the event
if (event_add(&event_, 0) == -1) {
GlobalOutput("TConnection::setFlags(): could not event_add");
GlobalOutput.perror("TConnection::setFlags(): could not event_add", THRIFT_GET_SOCKET_ERROR);
}
}
@ -823,10 +838,7 @@ void TNonblockingServer::TConnection::setFlags(short eventFlags) {
* Closes a connection
*/
void TNonblockingServer::TConnection::close() {
// Delete the registered libevent
if (event_del(&event_) == -1) {
GlobalOutput.perror("TConnection::close() event_del", THRIFT_GET_SOCKET_ERROR);
}
setIdle();
if (serverEventHandler_) {
serverEventHandler_->deleteContext(connectionContext_, inputProtocol_, outputProtocol_);
@ -876,9 +888,9 @@ TNonblockingServer::~TNonblockingServer() {
// objects and the Thread objects have shared_ptrs to the TNonblockingIOThread
// objects (as runnable) so these objects will never deallocate without help.
while (!ioThreads_.empty()) {
boost::shared_ptr<TNonblockingIOThread> iot = ioThreads_.back();
stdcxx::shared_ptr<TNonblockingIOThread> iot = ioThreads_.back();
ioThreads_.pop_back();
iot->setThread(boost::shared_ptr<Thread>());
iot->setThread(stdcxx::shared_ptr<Thread>());
}
}
@ -886,9 +898,7 @@ TNonblockingServer::~TNonblockingServer() {
* Creates a new connection either by reusing an object off the stack or
* by allocating a new one entirely
*/
TNonblockingServer::TConnection* TNonblockingServer::createConnection(THRIFT_SOCKET socket,
const sockaddr* addr,
socklen_t addrLen) {
TNonblockingServer::TConnection* TNonblockingServer::createConnection(stdcxx::shared_ptr<TSocket> socket) {
// Check the stack
Guard g(connMutex_);
@ -902,12 +912,13 @@ TNonblockingServer::TConnection* TNonblockingServer::createConnection(THRIFT_SOC
// Check the connection stack to see if we can re-use
TConnection* result = NULL;
if (connectionStack_.empty()) {
result = new TConnection(socket, ioThread, addr, addrLen);
result = new TConnection(socket, ioThread);
++numTConnections_;
} else {
result = connectionStack_.top();
connectionStack_.pop();
result->init(socket, ioThread, addr, addrLen);
result->setSocket(socket);
result->init(ioThread);
}
activeConnections_.push_back(result);
return result;
@ -942,53 +953,35 @@ void TNonblockingServer::handleEvent(THRIFT_SOCKET fd, short which) {
// Make sure that libevent didn't mess up the socket handles
assert(fd == serverSocket_);
// Server socket accepted a new connection
socklen_t addrLen;
sockaddr_storage addrStorage;
sockaddr* addrp = (sockaddr*)&addrStorage;
addrLen = sizeof(addrStorage);
// Going to accept a new client socket
THRIFT_SOCKET clientSocket;
stdcxx::shared_ptr<TSocket> clientSocket;
// Accept as many new clients as possible, even though libevent signaled only
// one, this helps us to avoid having to go back into the libevent engine so
// many times
while ((clientSocket = ::accept(fd, addrp, &addrLen)) != -1) {
clientSocket = serverTransport_->accept();
if (clientSocket) {
// If we're overloaded, take action here
if (overloadAction_ != T_OVERLOAD_NO_ACTION && serverOverloaded()) {
Guard g(connMutex_);
nConnectionsDropped_++;
nTotalConnectionsDropped_++;
if (overloadAction_ == T_OVERLOAD_CLOSE_ON_ACCEPT) {
::THRIFT_CLOSESOCKET(clientSocket);
clientSocket->close();
return;
} else if (overloadAction_ == T_OVERLOAD_DRAIN_TASK_QUEUE) {
if (!drainPendingTask()) {
// Nothing left to discard, so we drop connection instead.
::THRIFT_CLOSESOCKET(clientSocket);
clientSocket->close();
return;
}
}
}
// Explicitly set this socket to NONBLOCK mode
int flags;
if ((flags = THRIFT_FCNTL(clientSocket, THRIFT_F_GETFL, 0)) < 0
|| THRIFT_FCNTL(clientSocket, THRIFT_F_SETFL, flags | THRIFT_O_NONBLOCK) < 0) {
GlobalOutput.perror("thriftServerEventHandler: set THRIFT_O_NONBLOCK (THRIFT_FCNTL) ",
THRIFT_GET_SOCKET_ERROR);
::THRIFT_CLOSESOCKET(clientSocket);
return;
}
// Create a new TConnection for this client socket.
TConnection* clientConnection = createConnection(clientSocket, addrp, addrLen);
TConnection* clientConnection = createConnection(clientSocket);
// Fail fast if we could not create a TConnection object
if (clientConnection == NULL) {
GlobalOutput.printf("thriftServerEventHandler: failed TConnection factory");
::THRIFT_CLOSESOCKET(clientSocket);
clientSocket->close();
return;
}
@ -1009,18 +1002,9 @@ void TNonblockingServer::handleEvent(THRIFT_SOCKET fd, short which) {
} else {
if (!clientConnection->notifyIOThread()) {
GlobalOutput.perror("[ERROR] notifyIOThread failed on fresh connection, closing", errno);
returnConnection(clientConnection);
clientConnection->close();
}
}
// addrLen is written by the accept() call, so needs to be set before the next call.
addrLen = sizeof(addrStorage);
}
// Done looping accept, now we have to make sure the error is due to
// blocking. Any other error is a problem
if (THRIFT_GET_SOCKET_ERROR != THRIFT_EAGAIN && THRIFT_GET_SOCKET_ERROR != THRIFT_EWOULDBLOCK) {
GlobalOutput.perror("thriftServerEventHandler: accept() ", THRIFT_GET_SOCKET_ERROR);
}
}
@ -1028,132 +1012,12 @@ void TNonblockingServer::handleEvent(THRIFT_SOCKET fd, short which) {
* Creates a socket to listen on and binds it to the local port.
*/
void TNonblockingServer::createAndListenOnSocket() {
#ifdef _WIN32
TWinsockSingleton::create();
#endif // _WIN32
THRIFT_SOCKET s;
struct addrinfo hints, *res, *res0;
int error;
char port[sizeof("65536") + 1];
memset(&hints, 0, sizeof(hints));
hints.ai_family = PF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_PASSIVE | AI_ADDRCONFIG;
sprintf(port, "%d", port_);
// Wildcard address
error = getaddrinfo(NULL, port, &hints, &res0);
if (error) {
throw TException("TNonblockingServer::serve() getaddrinfo "
+ string(THRIFT_GAI_STRERROR(error)));
}
// Pick the ipv6 address first since ipv4 addresses can be mapped
// into ipv6 space.
for (res = res0; res; res = res->ai_next) {
if (res->ai_family == AF_INET6 || res->ai_next == NULL)
break;
}
// Create the server socket
s = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
if (s == -1) {
freeaddrinfo(res0);
throw TException("TNonblockingServer::serve() socket() -1");
}
#ifdef IPV6_V6ONLY
if (res->ai_family == AF_INET6) {
int zero = 0;
if (-1 == setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, const_cast_sockopt(&zero), sizeof(zero))) {
GlobalOutput("TServerSocket::listen() IPV6_V6ONLY");
}
}
#endif // #ifdef IPV6_V6ONLY
int one = 1;
// Set THRIFT_NO_SOCKET_CACHING to avoid 2MSL delay on server restart
setsockopt(s, SOL_SOCKET, THRIFT_NO_SOCKET_CACHING, const_cast_sockopt(&one), sizeof(one));
if (::bind(s, res->ai_addr, static_cast<int>(res->ai_addrlen)) == -1) {
::THRIFT_CLOSESOCKET(s);
freeaddrinfo(res0);
throw TTransportException(TTransportException::NOT_OPEN,
"TNonblockingServer::serve() bind",
THRIFT_GET_SOCKET_ERROR);
}
// Done with the addr info
freeaddrinfo(res0);
// Set up this file descriptor for listening
listenSocket(s);
serverTransport_->listen();
serverSocket_ = serverTransport_->getSocketFD();
}
/**
* Takes a socket created by listenSocket() and sets various options on it
* to prepare for use in the server.
*/
void TNonblockingServer::listenSocket(THRIFT_SOCKET s) {
// Set socket to nonblocking mode
int flags;
if ((flags = THRIFT_FCNTL(s, THRIFT_F_GETFL, 0)) < 0
|| THRIFT_FCNTL(s, THRIFT_F_SETFL, flags | THRIFT_O_NONBLOCK) < 0) {
::THRIFT_CLOSESOCKET(s);
throw TException("TNonblockingServer::serve() THRIFT_O_NONBLOCK");
}
int one = 1;
struct linger ling = {0, 0};
// Keepalive to ensure full result flushing
setsockopt(s, SOL_SOCKET, SO_KEEPALIVE, const_cast_sockopt(&one), sizeof(one));
// Turn linger off to avoid hung sockets
setsockopt(s, SOL_SOCKET, SO_LINGER, const_cast_sockopt(&ling), sizeof(ling));
// Set TCP nodelay if available, MAC OS X Hack
// See http://lists.danga.com/pipermail/memcached/2005-March/001240.html
#ifndef TCP_NOPUSH
setsockopt(s, IPPROTO_TCP, TCP_NODELAY, const_cast_sockopt(&one), sizeof(one));
#endif
#ifdef TCP_LOW_MIN_RTO
if (TSocket::getUseLowMinRto()) {
setsockopt(s, IPPROTO_TCP, TCP_LOW_MIN_RTO, const_cast_sockopt(&one), sizeof(one));
}
#endif
if (listen(s, LISTEN_BACKLOG) == -1) {
::THRIFT_CLOSESOCKET(s);
throw TTransportException(TTransportException::NOT_OPEN, "TNonblockingServer::serve() listen");
}
// Cool, this socket is good to go, set it as the serverSocket_
serverSocket_ = s;
if (!port_) {
struct sockaddr_storage addr;
socklen_t size = sizeof(addr);
if (!getsockname(serverSocket_, reinterpret_cast<sockaddr*>(&addr), &size)) {
if (addr.ss_family == AF_INET6) {
const struct sockaddr_in6* sin = reinterpret_cast<const struct sockaddr_in6*>(&addr);
listenPort_ = ntohs(sin->sin6_port);
} else {
const struct sockaddr_in* sin = reinterpret_cast<const struct sockaddr_in*>(&addr);
listenPort_ = ntohs(sin->sin_port);
}
} else {
GlobalOutput.perror("TNonblocking: failed to get listen port: ", THRIFT_GET_SOCKET_ERROR);
}
}
}
void TNonblockingServer::setThreadManager(boost::shared_ptr<ThreadManager> threadManager) {
void TNonblockingServer::setThreadManager(stdcxx::shared_ptr<ThreadManager> threadManager) {
threadManager_ = threadManager;
if (threadManager) {
threadManager->setExpireCallback(
@ -1191,7 +1055,7 @@ bool TNonblockingServer::serverOverloaded() {
bool TNonblockingServer::drainPendingTask() {
if (threadManager_) {
boost::shared_ptr<Runnable> task = threadManager_->removeNextPending();
stdcxx::shared_ptr<Runnable> task = threadManager_->removeNextPending();
if (task) {
TConnection* connection = static_cast<TConnection::Task*>(task.get())->getTConnection();
assert(connection && connection->getServer() && connection->getState() == APP_WAIT_TASK);
@ -1202,16 +1066,13 @@ bool TNonblockingServer::drainPendingTask() {
return false;
}
void TNonblockingServer::expireClose(boost::shared_ptr<Runnable> task) {
void TNonblockingServer::expireClose(stdcxx::shared_ptr<Runnable> task) {
TConnection* connection = static_cast<TConnection::Task*>(task.get())->getTConnection();
assert(connection && connection->getServer() && connection->getState() == APP_WAIT_TASK);
connection->forceClose();
}
void TNonblockingServer::stop() {
if (!port_) {
listenPort_ = 0;
}
// Breaks the event loop in all threads so that they end ASAP.
for (uint32_t i = 0; i < ioThreads_.size(); ++i) {
ioThreads_[i]->stop();
@ -1252,8 +1113,7 @@ void TNonblockingServer::registerEvents(event_base* user_event_base) {
assert(ioThreads_.size() == numIOThreads_);
assert(ioThreads_.size() > 0);
GlobalOutput.printf("TNonblockingServer: Serving on port %d, %d io threads.",
listenPort_,
GlobalOutput.printf("TNonblockingServer: Serving with %d io threads.",
ioThreads_.size());
// Launch all the secondary IO threads in separate threads
@ -1324,7 +1184,7 @@ TNonblockingIOThread::~TNonblockingIOThread() {
ownEventBase_ = false;
}
if (listenSocket_ >= 0) {
if (listenSocket_ != THRIFT_INVALID_SOCKET) {
if (0 != ::THRIFT_CLOSESOCKET(listenSocket_)) {
GlobalOutput.perror("TNonblockingIOThread listenSocket_ close(): ", THRIFT_GET_SOCKET_ERROR);
}
@ -1390,7 +1250,7 @@ void TNonblockingIOThread::registerEvents() {
event_base_get_method(eventBase_));
}
if (listenSocket_ >= 0) {
if (listenSocket_ != THRIFT_INVALID_SOCKET) {
// Register the server event
event_set(&serverEvent_,
listenSocket_,
@ -1435,10 +1295,44 @@ bool TNonblockingIOThread::notify(TNonblockingServer::TConnection* conn) {
return false;
}
fd_set wfds, efds;
long ret = -1;
int ret = -1;
long kSize = sizeof(conn);
const char* pos = reinterpret_cast<const char*>(&conn);
const char * pos = (const char *)const_cast_sockopt(&conn);
#if defined(HAVE_POLL_H) || defined(HAVE_SYS_POLL_H)
struct pollfd pfd = {fd, POLLOUT, 0};
while (kSize > 0) {
pfd.revents = 0;
ret = poll(&pfd, 1, -1);
if (ret < 0) {
return false;
} else if (ret == 0) {
continue;
}
if (pfd.revents & POLLHUP || pfd.revents & POLLERR) {
::THRIFT_CLOSESOCKET(fd);
return false;
}
if (pfd.revents & POLLOUT) {
ret = send(fd, pos, kSize, 0);
if (ret < 0) {
if (errno == EAGAIN) {
continue;
}
::THRIFT_CLOSESOCKET(fd);
return false;
}
kSize -= ret;
pos += ret;
}
}
#else
fd_set wfds, efds;
while (kSize > 0) {
FD_ZERO(&wfds);
@ -1472,6 +1366,7 @@ bool TNonblockingIOThread::notify(TNonblockingServer::TConnection* conn) {
pos += ret;
}
}
#endif
return true;
}
@ -1489,6 +1384,7 @@ void TNonblockingIOThread::notifyHandler(evutil_socket_t fd, short which, void*
if (nBytes == kSize) {
if (connection == NULL) {
// this is the command to stop our thread, exit the handler!
ioThread->breakLoop(false);
return;
}
connection->transition();
@ -1499,6 +1395,7 @@ void TNonblockingIOThread::notifyHandler(evutil_socket_t fd, short which, void*
return;
} else if (nBytes == 0) {
GlobalOutput.printf("notifyHandler: Notify socket closed!");
ioThread->breakLoop(false);
// exit the loop
break;
} else { // nBytes < 0
@ -1523,19 +1420,15 @@ void TNonblockingIOThread::breakLoop(bool error) {
::abort();
}
// sets a flag so that the loop exits on the next event
event_base_loopbreak(eventBase_);
// event_base_loopbreak() only causes the loop to exit the next time
// it wakes up. We need to force it to wake up, in case there are
// no real events it needs to process.
//
// If we're running in the same thread, we can't use the notify(0)
// mechanism to stop the thread, but happily if we're running in the
// same thread, this means the thread can't be blocking in the event
// loop either.
if (!Thread::is_current(threadId_)) {
notify(NULL);
} else {
// cause the loop to stop ASAP - even if it has things to do in it
event_base_loopbreak(eventBase_);
}
}
@ -1569,31 +1462,33 @@ void TNonblockingIOThread::setCurrentThreadHighPriority(bool value) {
}
void TNonblockingIOThread::run() {
if (eventBase_ == NULL)
if (eventBase_ == NULL) {
registerEvents();
GlobalOutput.printf("TNonblockingServer: IO thread #%d entering loop...", number_);
}
if (useHighPriority_) {
setCurrentThreadHighPriority(true);
}
// Run libevent engine, never returns, invokes calls to eventHandler
event_base_loop(eventBase_, 0);
if (eventBase_ != NULL)
{
GlobalOutput.printf("TNonblockingServer: IO thread #%d entering loop...", number_);
// Run libevent engine, never returns, invokes calls to eventHandler
event_base_loop(eventBase_, 0);
if (useHighPriority_) {
setCurrentThreadHighPriority(false);
if (useHighPriority_) {
setCurrentThreadHighPriority(false);
}
// cleans up our registered events
cleanupEvents();
}
// cleans up our registered events
cleanupEvents();
GlobalOutput.printf("TNonblockingServer: IO thread #%d run() done!", number_);
}
void TNonblockingIOThread::cleanupEvents() {
// stop the listen socket, if any
if (listenSocket_ >= 0) {
if (listenSocket_ != THRIFT_INVALID_SOCKET) {
if (event_del(&serverEvent_) == -1) {
GlobalOutput.perror("TNonblockingIOThread::stop() event_del: ", THRIFT_GET_SOCKET_ERROR);
}

View file

@ -21,10 +21,12 @@
#define _THRIFT_SERVER_TNONBLOCKINGSERVER_H_ 1
#include <thrift/Thrift.h>
#include <thrift/stdcxx.h>
#include <thrift/server/TServer.h>
#include <thrift/transport/PlatformSocket.h>
#include <thrift/transport/TBufferTransports.h>
#include <thrift/transport/TSocket.h>
#include <thrift/transport/TNonblockingServerTransport.h>
#include <thrift/concurrency/ThreadManager.h>
#include <climits>
#include <thrift/concurrency/Thread.h>
@ -47,6 +49,7 @@ namespace server {
using apache::thrift::transport::TMemoryBuffer;
using apache::thrift::transport::TSocket;
using apache::thrift::transport::TNonblockingServerTransport;
using apache::thrift::protocol::TProtocol;
using apache::thrift::concurrency::Runnable;
using apache::thrift::concurrency::ThreadManager;
@ -96,10 +99,6 @@ inline SOCKOPT_CAST_T* cast_sockopt(T* v) {
* operates a set of IO threads (by default only one). It assumes that
* all incoming requests are framed with a 4 byte length indicator and
* writes out responses using the same framing.
*
* It does not use the TServerTransport framework, but rather has socket
* operations hardcoded for use with select.
*
*/
/// Overload condition actions.
@ -157,26 +156,20 @@ private:
/// Server socket file descriptor
THRIFT_SOCKET serverSocket_;
/// Port server runs on. Zero when letting OS decide actual port
int port_;
/// Port server actually runs on
int listenPort_;
/// The optional user-provided event-base (for single-thread servers)
event_base* userEventBase_;
/// For processing via thread pool, may be NULL
boost::shared_ptr<ThreadManager> threadManager_;
stdcxx::shared_ptr<ThreadManager> threadManager_;
/// Is thread pool processing?
bool threadPoolProcessing_;
// Factory to create the IO threads
boost::shared_ptr<PlatformThreadFactory> ioThreadFactory_;
stdcxx::shared_ptr<PlatformThreadFactory> ioThreadFactory_;
// Vector of IOThread objects that will handle our IO
std::vector<boost::shared_ptr<TNonblockingIOThread> > ioThreads_;
std::vector<stdcxx::shared_ptr<TNonblockingIOThread> > ioThreads_;
// Index of next IO Thread to be used (for round-robin)
uint32_t nextIOThread_;
@ -269,23 +262,24 @@ private:
*/
std::vector<TConnection*> activeConnections_;
/*
*/
stdcxx::shared_ptr<TNonblockingServerTransport> serverTransport_;
/**
* Called when server socket had something happen. We accept all waiting
* client connections on listen socket fd and assign TConnection objects
* to handle those requests.
*
* @param fd the listen socket.
* @param which the event flag that triggered the handler.
*/
void handleEvent(THRIFT_SOCKET fd, short which);
void init(int port) {
void init() {
serverSocket_ = THRIFT_INVALID_SOCKET;
numIOThreads_ = DEFAULT_IO_THREADS;
nextIOThread_ = 0;
useHighPriorityIOThreads_ = false;
port_ = port;
listenPort_ = port;
userEventBase_ = NULL;
threadPoolProcessing_ = false;
numTConnections_ = 0;
@ -307,55 +301,55 @@ private:
}
public:
TNonblockingServer(const boost::shared_ptr<TProcessorFactory>& processorFactory, int port)
: TServer(processorFactory) {
init(port);
TNonblockingServer(const stdcxx::shared_ptr<TProcessorFactory>& processorFactory,
const stdcxx::shared_ptr<apache::thrift::transport::TNonblockingServerTransport>& serverTransport)
: TServer(processorFactory), serverTransport_(serverTransport) {
init();
}
TNonblockingServer(const boost::shared_ptr<TProcessor>& processor, int port)
: TServer(processor) {
init(port);
TNonblockingServer(const stdcxx::shared_ptr<TProcessor>& processor,
const stdcxx::shared_ptr<apache::thrift::transport::TNonblockingServerTransport>& serverTransport)
: TServer(processor), serverTransport_(serverTransport) {
init();
}
TNonblockingServer(const boost::shared_ptr<TProcessorFactory>& processorFactory,
const boost::shared_ptr<TProtocolFactory>& protocolFactory,
int port,
const boost::shared_ptr<ThreadManager>& threadManager
= boost::shared_ptr<ThreadManager>())
: TServer(processorFactory) {
init(port);
TNonblockingServer(const stdcxx::shared_ptr<TProcessorFactory>& processorFactory,
const stdcxx::shared_ptr<TProtocolFactory>& protocolFactory,
const stdcxx::shared_ptr<apache::thrift::transport::TNonblockingServerTransport>& serverTransport,
const stdcxx::shared_ptr<ThreadManager>& threadManager
= stdcxx::shared_ptr<ThreadManager>())
: TServer(processorFactory), serverTransport_(serverTransport) {
init();
setInputProtocolFactory(protocolFactory);
setOutputProtocolFactory(protocolFactory);
setThreadManager(threadManager);
}
TNonblockingServer(const boost::shared_ptr<TProcessor>& processor,
const boost::shared_ptr<TProtocolFactory>& protocolFactory,
int port,
const boost::shared_ptr<ThreadManager>& threadManager
= boost::shared_ptr<ThreadManager>())
: TServer(processor) {
init(port);
TNonblockingServer(const stdcxx::shared_ptr<TProcessor>& processor,
const stdcxx::shared_ptr<TProtocolFactory>& protocolFactory,
const stdcxx::shared_ptr<apache::thrift::transport::TNonblockingServerTransport>& serverTransport,
const stdcxx::shared_ptr<ThreadManager>& threadManager
= stdcxx::shared_ptr<ThreadManager>())
: TServer(processor), serverTransport_(serverTransport) {
init();
setInputProtocolFactory(protocolFactory);
setOutputProtocolFactory(protocolFactory);
setThreadManager(threadManager);
}
TNonblockingServer(const boost::shared_ptr<TProcessorFactory>& processorFactory,
const boost::shared_ptr<TTransportFactory>& inputTransportFactory,
const boost::shared_ptr<TTransportFactory>& outputTransportFactory,
const boost::shared_ptr<TProtocolFactory>& inputProtocolFactory,
const boost::shared_ptr<TProtocolFactory>& outputProtocolFactory,
int port,
const boost::shared_ptr<ThreadManager>& threadManager
= boost::shared_ptr<ThreadManager>())
: TServer(processorFactory) {
init(port);
TNonblockingServer(const stdcxx::shared_ptr<TProcessorFactory>& processorFactory,
const stdcxx::shared_ptr<TTransportFactory>& inputTransportFactory,
const stdcxx::shared_ptr<TTransportFactory>& outputTransportFactory,
const stdcxx::shared_ptr<TProtocolFactory>& inputProtocolFactory,
const stdcxx::shared_ptr<TProtocolFactory>& outputProtocolFactory,
const stdcxx::shared_ptr<apache::thrift::transport::TNonblockingServerTransport>& serverTransport,
const stdcxx::shared_ptr<ThreadManager>& threadManager
= stdcxx::shared_ptr<ThreadManager>())
: TServer(processorFactory), serverTransport_(serverTransport) {
init();
setInputTransportFactory(inputTransportFactory);
setOutputTransportFactory(outputTransportFactory);
@ -364,17 +358,16 @@ public:
setThreadManager(threadManager);
}
TNonblockingServer(const boost::shared_ptr<TProcessor>& processor,
const boost::shared_ptr<TTransportFactory>& inputTransportFactory,
const boost::shared_ptr<TTransportFactory>& outputTransportFactory,
const boost::shared_ptr<TProtocolFactory>& inputProtocolFactory,
const boost::shared_ptr<TProtocolFactory>& outputProtocolFactory,
int port,
const boost::shared_ptr<ThreadManager>& threadManager
= boost::shared_ptr<ThreadManager>())
: TServer(processor) {
init(port);
TNonblockingServer(const stdcxx::shared_ptr<TProcessor>& processor,
const stdcxx::shared_ptr<TTransportFactory>& inputTransportFactory,
const stdcxx::shared_ptr<TTransportFactory>& outputTransportFactory,
const stdcxx::shared_ptr<TProtocolFactory>& inputProtocolFactory,
const stdcxx::shared_ptr<TProtocolFactory>& outputProtocolFactory,
const stdcxx::shared_ptr<apache::thrift::transport::TNonblockingServerTransport>& serverTransport,
const stdcxx::shared_ptr<ThreadManager>& threadManager
= stdcxx::shared_ptr<ThreadManager>())
: TServer(processor), serverTransport_(serverTransport) {
init();
setInputTransportFactory(inputTransportFactory);
setOutputTransportFactory(outputTransportFactory);
@ -385,11 +378,11 @@ public:
~TNonblockingServer();
void setThreadManager(boost::shared_ptr<ThreadManager> threadManager);
void setThreadManager(stdcxx::shared_ptr<ThreadManager> threadManager);
int getListenPort() { return listenPort_; }
int getListenPort() { return serverTransport_->getListenPort(); }
boost::shared_ptr<ThreadManager> getThreadManager() { return threadManager_; }
stdcxx::shared_ptr<ThreadManager> getThreadManager() { return threadManager_; }
/**
* Sets the number of IO threads used by this server. Can only be used before
@ -428,7 +421,7 @@ public:
bool isThreadPoolProcessing() const { return threadPoolProcessing_; }
void addTask(boost::shared_ptr<Runnable> task) {
void addTask(stdcxx::shared_ptr<Runnable> task) {
threadManager_->add(task, 0LL, taskExpireTime_);
}
@ -688,14 +681,6 @@ public:
/// Creates a socket to listen on and binds it to the local port.
void createAndListenOnSocket();
/**
* Takes a socket created by createAndListenOnSocket() and sets various
* options on it to prepare for use in the server.
*
* @param fd descriptor of socket to be initialized/
*/
void listenSocket(THRIFT_SOCKET fd);
/**
* Register the optional user-provided event-base (for single-thread servers)
*
@ -724,7 +709,7 @@ private:
*
* @param task the runnable associated with the expired task.
*/
void expireClose(boost::shared_ptr<Runnable> task);
void expireClose(stdcxx::shared_ptr<Runnable> task);
/**
* Return an initialized connection object. Creates or recovers from
@ -736,7 +721,7 @@ private:
* @param addrLen the length of addr
* @return pointer to initialized TConnection object.
*/
TConnection* createConnection(THRIFT_SOCKET socket, const sockaddr* addr, socklen_t addrLen);
TConnection* createConnection(stdcxx::shared_ptr<TSocket> socket);
/**
* Returns a connection to pool or deletion. If the connection pool
@ -780,10 +765,10 @@ public:
evutil_socket_t getNotificationRecvFD() const { return notificationPipeFDs_[0]; }
// Returns the actual thread object associated with this IO thread.
boost::shared_ptr<Thread> getThread() const { return thread_; }
stdcxx::shared_ptr<Thread> getThread() const { return thread_; }
// Sets the actual thread object associated with this IO thread.
void setThread(const boost::shared_ptr<Thread>& t) { thread_ = t; }
void setThread(const stdcxx::shared_ptr<Thread>& t) { thread_ = t; }
// Used by TConnection objects to indicate processing has finished.
bool notify(TNonblockingServer::TConnection* conn);
@ -868,7 +853,7 @@ private:
evutil_socket_t notificationPipeFDs_[2];
/// Actual IO Thread
boost::shared_ptr<Thread> thread_;
stdcxx::shared_ptr<Thread> thread_;
};
}
}

View file

@ -25,7 +25,7 @@
#include <thrift/protocol/TBinaryProtocol.h>
#include <thrift/concurrency/Thread.h>
#include <boost/shared_ptr.hpp>
#include <thrift/stdcxx.h>
namespace apache {
namespace thrift {
@ -58,8 +58,8 @@ public:
/**
* Called when a new client has connected and is about to being processing.
*/
virtual void* createContext(boost::shared_ptr<TProtocol> input,
boost::shared_ptr<TProtocol> output) {
virtual void* createContext(stdcxx::shared_ptr<TProtocol> input,
stdcxx::shared_ptr<TProtocol> output) {
(void)input;
(void)output;
return NULL;
@ -70,8 +70,8 @@ public:
* context.
*/
virtual void deleteContext(void* serverContext,
boost::shared_ptr<TProtocol> input,
boost::shared_ptr<TProtocol> output) {
stdcxx::shared_ptr<TProtocol> input,
stdcxx::shared_ptr<TProtocol> output) {
(void)serverContext;
(void)input;
(void)output;
@ -80,7 +80,7 @@ public:
/**
* Called when a client is about to call the processor.
*/
virtual void processContext(void* serverContext, boost::shared_ptr<TTransport> transport) {
virtual void processContext(void* serverContext, stdcxx::shared_ptr<TTransport> transport) {
(void)serverContext;
(void)transport;
}
@ -107,62 +107,62 @@ public:
// Allows running the server as a Runnable thread
virtual void run() { serve(); }
boost::shared_ptr<TProcessorFactory> getProcessorFactory() { return processorFactory_; }
stdcxx::shared_ptr<TProcessorFactory> getProcessorFactory() { return processorFactory_; }
boost::shared_ptr<TServerTransport> getServerTransport() { return serverTransport_; }
stdcxx::shared_ptr<TServerTransport> getServerTransport() { return serverTransport_; }
boost::shared_ptr<TTransportFactory> getInputTransportFactory() { return inputTransportFactory_; }
stdcxx::shared_ptr<TTransportFactory> getInputTransportFactory() { return inputTransportFactory_; }
boost::shared_ptr<TTransportFactory> getOutputTransportFactory() {
stdcxx::shared_ptr<TTransportFactory> getOutputTransportFactory() {
return outputTransportFactory_;
}
boost::shared_ptr<TProtocolFactory> getInputProtocolFactory() { return inputProtocolFactory_; }
stdcxx::shared_ptr<TProtocolFactory> getInputProtocolFactory() { return inputProtocolFactory_; }
boost::shared_ptr<TProtocolFactory> getOutputProtocolFactory() { return outputProtocolFactory_; }
stdcxx::shared_ptr<TProtocolFactory> getOutputProtocolFactory() { return outputProtocolFactory_; }
boost::shared_ptr<TServerEventHandler> getEventHandler() { return eventHandler_; }
stdcxx::shared_ptr<TServerEventHandler> getEventHandler() { return eventHandler_; }
protected:
TServer(const boost::shared_ptr<TProcessorFactory>& processorFactory)
TServer(const stdcxx::shared_ptr<TProcessorFactory>& processorFactory)
: processorFactory_(processorFactory) {
setInputTransportFactory(boost::shared_ptr<TTransportFactory>(new TTransportFactory()));
setOutputTransportFactory(boost::shared_ptr<TTransportFactory>(new TTransportFactory()));
setInputProtocolFactory(boost::shared_ptr<TProtocolFactory>(new TBinaryProtocolFactory()));
setOutputProtocolFactory(boost::shared_ptr<TProtocolFactory>(new TBinaryProtocolFactory()));
setInputTransportFactory(stdcxx::shared_ptr<TTransportFactory>(new TTransportFactory()));
setOutputTransportFactory(stdcxx::shared_ptr<TTransportFactory>(new TTransportFactory()));
setInputProtocolFactory(stdcxx::shared_ptr<TProtocolFactory>(new TBinaryProtocolFactory()));
setOutputProtocolFactory(stdcxx::shared_ptr<TProtocolFactory>(new TBinaryProtocolFactory()));
}
TServer(const boost::shared_ptr<TProcessor>& processor)
TServer(const stdcxx::shared_ptr<TProcessor>& processor)
: processorFactory_(new TSingletonProcessorFactory(processor)) {
setInputTransportFactory(boost::shared_ptr<TTransportFactory>(new TTransportFactory()));
setOutputTransportFactory(boost::shared_ptr<TTransportFactory>(new TTransportFactory()));
setInputProtocolFactory(boost::shared_ptr<TProtocolFactory>(new TBinaryProtocolFactory()));
setOutputProtocolFactory(boost::shared_ptr<TProtocolFactory>(new TBinaryProtocolFactory()));
setInputTransportFactory(stdcxx::shared_ptr<TTransportFactory>(new TTransportFactory()));
setOutputTransportFactory(stdcxx::shared_ptr<TTransportFactory>(new TTransportFactory()));
setInputProtocolFactory(stdcxx::shared_ptr<TProtocolFactory>(new TBinaryProtocolFactory()));
setOutputProtocolFactory(stdcxx::shared_ptr<TProtocolFactory>(new TBinaryProtocolFactory()));
}
TServer(const boost::shared_ptr<TProcessorFactory>& processorFactory,
const boost::shared_ptr<TServerTransport>& serverTransport)
TServer(const stdcxx::shared_ptr<TProcessorFactory>& processorFactory,
const stdcxx::shared_ptr<TServerTransport>& serverTransport)
: processorFactory_(processorFactory), serverTransport_(serverTransport) {
setInputTransportFactory(boost::shared_ptr<TTransportFactory>(new TTransportFactory()));
setOutputTransportFactory(boost::shared_ptr<TTransportFactory>(new TTransportFactory()));
setInputProtocolFactory(boost::shared_ptr<TProtocolFactory>(new TBinaryProtocolFactory()));
setOutputProtocolFactory(boost::shared_ptr<TProtocolFactory>(new TBinaryProtocolFactory()));
setInputTransportFactory(stdcxx::shared_ptr<TTransportFactory>(new TTransportFactory()));
setOutputTransportFactory(stdcxx::shared_ptr<TTransportFactory>(new TTransportFactory()));
setInputProtocolFactory(stdcxx::shared_ptr<TProtocolFactory>(new TBinaryProtocolFactory()));
setOutputProtocolFactory(stdcxx::shared_ptr<TProtocolFactory>(new TBinaryProtocolFactory()));
}
TServer(const boost::shared_ptr<TProcessor>& processor,
const boost::shared_ptr<TServerTransport>& serverTransport)
TServer(const stdcxx::shared_ptr<TProcessor>& processor,
const stdcxx::shared_ptr<TServerTransport>& serverTransport)
: processorFactory_(new TSingletonProcessorFactory(processor)),
serverTransport_(serverTransport) {
setInputTransportFactory(boost::shared_ptr<TTransportFactory>(new TTransportFactory()));
setOutputTransportFactory(boost::shared_ptr<TTransportFactory>(new TTransportFactory()));
setInputProtocolFactory(boost::shared_ptr<TProtocolFactory>(new TBinaryProtocolFactory()));
setOutputProtocolFactory(boost::shared_ptr<TProtocolFactory>(new TBinaryProtocolFactory()));
setInputTransportFactory(stdcxx::shared_ptr<TTransportFactory>(new TTransportFactory()));
setOutputTransportFactory(stdcxx::shared_ptr<TTransportFactory>(new TTransportFactory()));
setInputProtocolFactory(stdcxx::shared_ptr<TProtocolFactory>(new TBinaryProtocolFactory()));
setOutputProtocolFactory(stdcxx::shared_ptr<TProtocolFactory>(new TBinaryProtocolFactory()));
}
TServer(const boost::shared_ptr<TProcessorFactory>& processorFactory,
const boost::shared_ptr<TServerTransport>& serverTransport,
const boost::shared_ptr<TTransportFactory>& transportFactory,
const boost::shared_ptr<TProtocolFactory>& protocolFactory)
TServer(const stdcxx::shared_ptr<TProcessorFactory>& processorFactory,
const stdcxx::shared_ptr<TServerTransport>& serverTransport,
const stdcxx::shared_ptr<TTransportFactory>& transportFactory,
const stdcxx::shared_ptr<TProtocolFactory>& protocolFactory)
: processorFactory_(processorFactory),
serverTransport_(serverTransport),
inputTransportFactory_(transportFactory),
@ -170,10 +170,10 @@ protected:
inputProtocolFactory_(protocolFactory),
outputProtocolFactory_(protocolFactory) {}
TServer(const boost::shared_ptr<TProcessor>& processor,
const boost::shared_ptr<TServerTransport>& serverTransport,
const boost::shared_ptr<TTransportFactory>& transportFactory,
const boost::shared_ptr<TProtocolFactory>& protocolFactory)
TServer(const stdcxx::shared_ptr<TProcessor>& processor,
const stdcxx::shared_ptr<TServerTransport>& serverTransport,
const stdcxx::shared_ptr<TTransportFactory>& transportFactory,
const stdcxx::shared_ptr<TProtocolFactory>& protocolFactory)
: processorFactory_(new TSingletonProcessorFactory(processor)),
serverTransport_(serverTransport),
inputTransportFactory_(transportFactory),
@ -181,12 +181,12 @@ protected:
inputProtocolFactory_(protocolFactory),
outputProtocolFactory_(protocolFactory) {}
TServer(const boost::shared_ptr<TProcessorFactory>& processorFactory,
const boost::shared_ptr<TServerTransport>& serverTransport,
const boost::shared_ptr<TTransportFactory>& inputTransportFactory,
const boost::shared_ptr<TTransportFactory>& outputTransportFactory,
const boost::shared_ptr<TProtocolFactory>& inputProtocolFactory,
const boost::shared_ptr<TProtocolFactory>& outputProtocolFactory)
TServer(const stdcxx::shared_ptr<TProcessorFactory>& processorFactory,
const stdcxx::shared_ptr<TServerTransport>& serverTransport,
const stdcxx::shared_ptr<TTransportFactory>& inputTransportFactory,
const stdcxx::shared_ptr<TTransportFactory>& outputTransportFactory,
const stdcxx::shared_ptr<TProtocolFactory>& inputProtocolFactory,
const stdcxx::shared_ptr<TProtocolFactory>& outputProtocolFactory)
: processorFactory_(processorFactory),
serverTransport_(serverTransport),
inputTransportFactory_(inputTransportFactory),
@ -194,12 +194,12 @@ protected:
inputProtocolFactory_(inputProtocolFactory),
outputProtocolFactory_(outputProtocolFactory) {}
TServer(const boost::shared_ptr<TProcessor>& processor,
const boost::shared_ptr<TServerTransport>& serverTransport,
const boost::shared_ptr<TTransportFactory>& inputTransportFactory,
const boost::shared_ptr<TTransportFactory>& outputTransportFactory,
const boost::shared_ptr<TProtocolFactory>& inputProtocolFactory,
const boost::shared_ptr<TProtocolFactory>& outputProtocolFactory)
TServer(const stdcxx::shared_ptr<TProcessor>& processor,
const stdcxx::shared_ptr<TServerTransport>& serverTransport,
const stdcxx::shared_ptr<TTransportFactory>& inputTransportFactory,
const stdcxx::shared_ptr<TTransportFactory>& outputTransportFactory,
const stdcxx::shared_ptr<TProtocolFactory>& inputProtocolFactory,
const stdcxx::shared_ptr<TProtocolFactory>& outputProtocolFactory)
: processorFactory_(new TSingletonProcessorFactory(processor)),
serverTransport_(serverTransport),
inputTransportFactory_(inputTransportFactory),
@ -214,9 +214,9 @@ protected:
* call). This allows the TProcessorFactory to return a different processor
* for each connection if it desires.
*/
boost::shared_ptr<TProcessor> getProcessor(boost::shared_ptr<TProtocol> inputProtocol,
boost::shared_ptr<TProtocol> outputProtocol,
boost::shared_ptr<TTransport> transport) {
stdcxx::shared_ptr<TProcessor> getProcessor(stdcxx::shared_ptr<TProtocol> inputProtocol,
stdcxx::shared_ptr<TProtocol> outputProtocol,
stdcxx::shared_ptr<TTransport> transport) {
TConnectionInfo connInfo;
connInfo.input = inputProtocol;
connInfo.output = outputProtocol;
@ -225,35 +225,35 @@ protected:
}
// Class variables
boost::shared_ptr<TProcessorFactory> processorFactory_;
boost::shared_ptr<TServerTransport> serverTransport_;
stdcxx::shared_ptr<TProcessorFactory> processorFactory_;
stdcxx::shared_ptr<TServerTransport> serverTransport_;
boost::shared_ptr<TTransportFactory> inputTransportFactory_;
boost::shared_ptr<TTransportFactory> outputTransportFactory_;
stdcxx::shared_ptr<TTransportFactory> inputTransportFactory_;
stdcxx::shared_ptr<TTransportFactory> outputTransportFactory_;
boost::shared_ptr<TProtocolFactory> inputProtocolFactory_;
boost::shared_ptr<TProtocolFactory> outputProtocolFactory_;
stdcxx::shared_ptr<TProtocolFactory> inputProtocolFactory_;
stdcxx::shared_ptr<TProtocolFactory> outputProtocolFactory_;
boost::shared_ptr<TServerEventHandler> eventHandler_;
stdcxx::shared_ptr<TServerEventHandler> eventHandler_;
public:
void setInputTransportFactory(boost::shared_ptr<TTransportFactory> inputTransportFactory) {
void setInputTransportFactory(stdcxx::shared_ptr<TTransportFactory> inputTransportFactory) {
inputTransportFactory_ = inputTransportFactory;
}
void setOutputTransportFactory(boost::shared_ptr<TTransportFactory> outputTransportFactory) {
void setOutputTransportFactory(stdcxx::shared_ptr<TTransportFactory> outputTransportFactory) {
outputTransportFactory_ = outputTransportFactory;
}
void setInputProtocolFactory(boost::shared_ptr<TProtocolFactory> inputProtocolFactory) {
void setInputProtocolFactory(stdcxx::shared_ptr<TProtocolFactory> inputProtocolFactory) {
inputProtocolFactory_ = inputProtocolFactory;
}
void setOutputProtocolFactory(boost::shared_ptr<TProtocolFactory> outputProtocolFactory) {
void setOutputProtocolFactory(stdcxx::shared_ptr<TProtocolFactory> outputProtocolFactory) {
outputProtocolFactory_ = outputProtocolFactory;
}
void setServerEventHandler(boost::shared_ptr<TServerEventHandler> eventHandler) {
void setServerEventHandler(stdcxx::shared_ptr<TServerEventHandler> eventHandler) {
eventHandler_ = eventHandler;
}
};

View file

@ -18,7 +18,6 @@
*/
#include <algorithm>
#include <boost/bind.hpp>
#include <stdexcept>
#include <stdint.h>
#include <thrift/server/TServerFramework.h>
@ -28,14 +27,14 @@ namespace thrift {
namespace server {
using apache::thrift::concurrency::Synchronized;
using apache::thrift::protocol::TProtocol;
using apache::thrift::protocol::TProtocolFactory;
using apache::thrift::stdcxx::bind;
using apache::thrift::stdcxx::shared_ptr;
using apache::thrift::transport::TServerTransport;
using apache::thrift::transport::TTransport;
using apache::thrift::transport::TTransportException;
using apache::thrift::transport::TTransportFactory;
using apache::thrift::protocol::TProtocol;
using apache::thrift::protocol::TProtocolFactory;
using boost::bind;
using boost::shared_ptr;
using std::string;
TServerFramework::TServerFramework(const shared_ptr<TProcessorFactory>& processorFactory,
@ -162,7 +161,7 @@ void TServerFramework::serve() {
outputProtocol,
eventHandler_,
client),
bind(&TServerFramework::disposeConnectedClient, this, _1)));
bind(&TServerFramework::disposeConnectedClient, this, stdcxx::placeholders::_1)));
} catch (TTransportException& ttx) {
releaseOneDescriptor("inputTransport", inputTransport);
@ -221,7 +220,7 @@ void TServerFramework::stop() {
serverTransport_->interrupt();
}
void TServerFramework::newlyConnectedClient(const boost::shared_ptr<TConnectedClient>& pClient) {
void TServerFramework::newlyConnectedClient(const shared_ptr<TConnectedClient>& pClient) {
{
Synchronized sync(mon_);
++clients_;

View file

@ -20,7 +20,7 @@
#ifndef _THRIFT_SERVER_TSERVERFRAMEWORK_H_
#define _THRIFT_SERVER_TSERVERFRAMEWORK_H_ 1
#include <boost/shared_ptr.hpp>
#include <thrift/stdcxx.h>
#include <stdint.h>
#include <thrift/TProcessor.h>
#include <thrift/concurrency/Monitor.h>
@ -48,32 +48,32 @@ namespace server {
class TServerFramework : public TServer {
public:
TServerFramework(
const boost::shared_ptr<apache::thrift::TProcessorFactory>& processorFactory,
const boost::shared_ptr<apache::thrift::transport::TServerTransport>& serverTransport,
const boost::shared_ptr<apache::thrift::transport::TTransportFactory>& transportFactory,
const boost::shared_ptr<apache::thrift::protocol::TProtocolFactory>& protocolFactory);
const stdcxx::shared_ptr<apache::thrift::TProcessorFactory>& processorFactory,
const stdcxx::shared_ptr<apache::thrift::transport::TServerTransport>& serverTransport,
const stdcxx::shared_ptr<apache::thrift::transport::TTransportFactory>& transportFactory,
const stdcxx::shared_ptr<apache::thrift::protocol::TProtocolFactory>& protocolFactory);
TServerFramework(
const boost::shared_ptr<apache::thrift::TProcessor>& processor,
const boost::shared_ptr<apache::thrift::transport::TServerTransport>& serverTransport,
const boost::shared_ptr<apache::thrift::transport::TTransportFactory>& transportFactory,
const boost::shared_ptr<apache::thrift::protocol::TProtocolFactory>& protocolFactory);
const stdcxx::shared_ptr<apache::thrift::TProcessor>& processor,
const stdcxx::shared_ptr<apache::thrift::transport::TServerTransport>& serverTransport,
const stdcxx::shared_ptr<apache::thrift::transport::TTransportFactory>& transportFactory,
const stdcxx::shared_ptr<apache::thrift::protocol::TProtocolFactory>& protocolFactory);
TServerFramework(
const boost::shared_ptr<apache::thrift::TProcessorFactory>& processorFactory,
const boost::shared_ptr<apache::thrift::transport::TServerTransport>& serverTransport,
const boost::shared_ptr<apache::thrift::transport::TTransportFactory>& inputTransportFactory,
const boost::shared_ptr<apache::thrift::transport::TTransportFactory>& outputTransportFactory,
const boost::shared_ptr<apache::thrift::protocol::TProtocolFactory>& inputProtocolFactory,
const boost::shared_ptr<apache::thrift::protocol::TProtocolFactory>& outputProtocolFactory);
const stdcxx::shared_ptr<apache::thrift::TProcessorFactory>& processorFactory,
const stdcxx::shared_ptr<apache::thrift::transport::TServerTransport>& serverTransport,
const stdcxx::shared_ptr<apache::thrift::transport::TTransportFactory>& inputTransportFactory,
const stdcxx::shared_ptr<apache::thrift::transport::TTransportFactory>& outputTransportFactory,
const stdcxx::shared_ptr<apache::thrift::protocol::TProtocolFactory>& inputProtocolFactory,
const stdcxx::shared_ptr<apache::thrift::protocol::TProtocolFactory>& outputProtocolFactory);
TServerFramework(
const boost::shared_ptr<apache::thrift::TProcessor>& processor,
const boost::shared_ptr<apache::thrift::transport::TServerTransport>& serverTransport,
const boost::shared_ptr<apache::thrift::transport::TTransportFactory>& inputTransportFactory,
const boost::shared_ptr<apache::thrift::transport::TTransportFactory>& outputTransportFactory,
const boost::shared_ptr<apache::thrift::protocol::TProtocolFactory>& inputProtocolFactory,
const boost::shared_ptr<apache::thrift::protocol::TProtocolFactory>& outputProtocolFactory);
const stdcxx::shared_ptr<apache::thrift::TProcessor>& processor,
const stdcxx::shared_ptr<apache::thrift::transport::TServerTransport>& serverTransport,
const stdcxx::shared_ptr<apache::thrift::transport::TTransportFactory>& inputTransportFactory,
const stdcxx::shared_ptr<apache::thrift::transport::TTransportFactory>& outputTransportFactory,
const stdcxx::shared_ptr<apache::thrift::protocol::TProtocolFactory>& inputProtocolFactory,
const stdcxx::shared_ptr<apache::thrift::protocol::TProtocolFactory>& outputProtocolFactory);
virtual ~TServerFramework();
@ -130,7 +130,7 @@ protected:
*
* \param[in] pClient the newly connected client
*/
virtual void onClientConnected(const boost::shared_ptr<TConnectedClient>& pClient) = 0;
virtual void onClientConnected(const stdcxx::shared_ptr<TConnectedClient>& pClient) = 0;
/**
* A client has disconnected.
@ -149,7 +149,7 @@ private:
* client rate limiting after onClientConnected returns by blocking the
* serve() thread if the limit has been reached.
*/
void newlyConnectedClient(const boost::shared_ptr<TConnectedClient>& pClient);
void newlyConnectedClient(const stdcxx::shared_ptr<TConnectedClient>& pClient);
/**
* Smart pointer client deletion.

View file

@ -29,7 +29,7 @@ using apache::thrift::transport::TServerTransport;
using apache::thrift::transport::TTransport;
using apache::thrift::transport::TTransportException;
using apache::thrift::transport::TTransportFactory;
using boost::shared_ptr;
using stdcxx::shared_ptr;
using std::string;
TSimpleServer::TSimpleServer(const shared_ptr<TProcessorFactory>& processorFactory,

View file

@ -34,37 +34,37 @@ namespace server {
class TSimpleServer : public TServerFramework {
public:
TSimpleServer(
const boost::shared_ptr<apache::thrift::TProcessorFactory>& processorFactory,
const boost::shared_ptr<apache::thrift::transport::TServerTransport>& serverTransport,
const boost::shared_ptr<apache::thrift::transport::TTransportFactory>& transportFactory,
const boost::shared_ptr<apache::thrift::protocol::TProtocolFactory>& protocolFactory);
const stdcxx::shared_ptr<apache::thrift::TProcessorFactory>& processorFactory,
const stdcxx::shared_ptr<apache::thrift::transport::TServerTransport>& serverTransport,
const stdcxx::shared_ptr<apache::thrift::transport::TTransportFactory>& transportFactory,
const stdcxx::shared_ptr<apache::thrift::protocol::TProtocolFactory>& protocolFactory);
TSimpleServer(
const boost::shared_ptr<apache::thrift::TProcessor>& processor,
const boost::shared_ptr<apache::thrift::transport::TServerTransport>& serverTransport,
const boost::shared_ptr<apache::thrift::transport::TTransportFactory>& transportFactory,
const boost::shared_ptr<apache::thrift::protocol::TProtocolFactory>& protocolFactory);
const stdcxx::shared_ptr<apache::thrift::TProcessor>& processor,
const stdcxx::shared_ptr<apache::thrift::transport::TServerTransport>& serverTransport,
const stdcxx::shared_ptr<apache::thrift::transport::TTransportFactory>& transportFactory,
const stdcxx::shared_ptr<apache::thrift::protocol::TProtocolFactory>& protocolFactory);
TSimpleServer(
const boost::shared_ptr<apache::thrift::TProcessorFactory>& processorFactory,
const boost::shared_ptr<apache::thrift::transport::TServerTransport>& serverTransport,
const boost::shared_ptr<apache::thrift::transport::TTransportFactory>& inputTransportFactory,
const boost::shared_ptr<apache::thrift::transport::TTransportFactory>& outputTransportFactory,
const boost::shared_ptr<apache::thrift::protocol::TProtocolFactory>& inputProtocolFactory,
const boost::shared_ptr<apache::thrift::protocol::TProtocolFactory>& outputProtocolFactory);
const stdcxx::shared_ptr<apache::thrift::TProcessorFactory>& processorFactory,
const stdcxx::shared_ptr<apache::thrift::transport::TServerTransport>& serverTransport,
const stdcxx::shared_ptr<apache::thrift::transport::TTransportFactory>& inputTransportFactory,
const stdcxx::shared_ptr<apache::thrift::transport::TTransportFactory>& outputTransportFactory,
const stdcxx::shared_ptr<apache::thrift::protocol::TProtocolFactory>& inputProtocolFactory,
const stdcxx::shared_ptr<apache::thrift::protocol::TProtocolFactory>& outputProtocolFactory);
TSimpleServer(
const boost::shared_ptr<apache::thrift::TProcessor>& processor,
const boost::shared_ptr<apache::thrift::transport::TServerTransport>& serverTransport,
const boost::shared_ptr<apache::thrift::transport::TTransportFactory>& inputTransportFactory,
const boost::shared_ptr<apache::thrift::transport::TTransportFactory>& outputTransportFactory,
const boost::shared_ptr<apache::thrift::protocol::TProtocolFactory>& inputProtocolFactory,
const boost::shared_ptr<apache::thrift::protocol::TProtocolFactory>& outputProtocolFactory);
const stdcxx::shared_ptr<apache::thrift::TProcessor>& processor,
const stdcxx::shared_ptr<apache::thrift::transport::TServerTransport>& serverTransport,
const stdcxx::shared_ptr<apache::thrift::transport::TTransportFactory>& inputTransportFactory,
const stdcxx::shared_ptr<apache::thrift::transport::TTransportFactory>& outputTransportFactory,
const stdcxx::shared_ptr<apache::thrift::protocol::TProtocolFactory>& inputProtocolFactory,
const stdcxx::shared_ptr<apache::thrift::protocol::TProtocolFactory>& outputProtocolFactory);
virtual ~TSimpleServer();
protected:
virtual void onClientConnected(const boost::shared_ptr<TConnectedClient>& pClient) /* override */;
virtual void onClientConnected(const stdcxx::shared_ptr<TConnectedClient>& pClient) /* override */;
virtual void onClientDisconnected(TConnectedClient* pClient) /* override */;
private:

View file

@ -30,7 +30,7 @@ using apache::thrift::transport::TServerTransport;
using apache::thrift::transport::TTransport;
using apache::thrift::transport::TTransportException;
using apache::thrift::transport::TTransportFactory;
using boost::shared_ptr;
using stdcxx::shared_ptr;
using std::string;
TThreadPoolServer::TThreadPoolServer(const shared_ptr<TProcessorFactory>& processorFactory,
@ -115,7 +115,7 @@ void TThreadPoolServer::setTaskExpiration(int64_t value) {
taskExpiration_ = value;
}
boost::shared_ptr<apache::thrift::concurrency::ThreadManager>
stdcxx::shared_ptr<apache::thrift::concurrency::ThreadManager>
TThreadPoolServer::getThreadManager() const {
return threadManager_;
}

View file

@ -34,39 +34,39 @@ namespace server {
class TThreadPoolServer : public TServerFramework {
public:
TThreadPoolServer(
const boost::shared_ptr<apache::thrift::TProcessorFactory>& processorFactory,
const boost::shared_ptr<apache::thrift::transport::TServerTransport>& serverTransport,
const boost::shared_ptr<apache::thrift::transport::TTransportFactory>& transportFactory,
const boost::shared_ptr<apache::thrift::protocol::TProtocolFactory>& protocolFactory,
const boost::shared_ptr<apache::thrift::concurrency::ThreadManager>& threadManager
const stdcxx::shared_ptr<apache::thrift::TProcessorFactory>& processorFactory,
const stdcxx::shared_ptr<apache::thrift::transport::TServerTransport>& serverTransport,
const stdcxx::shared_ptr<apache::thrift::transport::TTransportFactory>& transportFactory,
const stdcxx::shared_ptr<apache::thrift::protocol::TProtocolFactory>& protocolFactory,
const stdcxx::shared_ptr<apache::thrift::concurrency::ThreadManager>& threadManager
= apache::thrift::concurrency::ThreadManager::newSimpleThreadManager());
TThreadPoolServer(
const boost::shared_ptr<apache::thrift::TProcessor>& processor,
const boost::shared_ptr<apache::thrift::transport::TServerTransport>& serverTransport,
const boost::shared_ptr<apache::thrift::transport::TTransportFactory>& transportFactory,
const boost::shared_ptr<apache::thrift::protocol::TProtocolFactory>& protocolFactory,
const boost::shared_ptr<apache::thrift::concurrency::ThreadManager>& threadManager
const stdcxx::shared_ptr<apache::thrift::TProcessor>& processor,
const stdcxx::shared_ptr<apache::thrift::transport::TServerTransport>& serverTransport,
const stdcxx::shared_ptr<apache::thrift::transport::TTransportFactory>& transportFactory,
const stdcxx::shared_ptr<apache::thrift::protocol::TProtocolFactory>& protocolFactory,
const stdcxx::shared_ptr<apache::thrift::concurrency::ThreadManager>& threadManager
= apache::thrift::concurrency::ThreadManager::newSimpleThreadManager());
TThreadPoolServer(
const boost::shared_ptr<apache::thrift::TProcessorFactory>& processorFactory,
const boost::shared_ptr<apache::thrift::transport::TServerTransport>& serverTransport,
const boost::shared_ptr<apache::thrift::transport::TTransportFactory>& inputTransportFactory,
const boost::shared_ptr<apache::thrift::transport::TTransportFactory>& outputTransportFactory,
const boost::shared_ptr<apache::thrift::protocol::TProtocolFactory>& inputProtocolFactory,
const boost::shared_ptr<apache::thrift::protocol::TProtocolFactory>& outputProtocolFactory,
const boost::shared_ptr<apache::thrift::concurrency::ThreadManager>& threadManager
const stdcxx::shared_ptr<apache::thrift::TProcessorFactory>& processorFactory,
const stdcxx::shared_ptr<apache::thrift::transport::TServerTransport>& serverTransport,
const stdcxx::shared_ptr<apache::thrift::transport::TTransportFactory>& inputTransportFactory,
const stdcxx::shared_ptr<apache::thrift::transport::TTransportFactory>& outputTransportFactory,
const stdcxx::shared_ptr<apache::thrift::protocol::TProtocolFactory>& inputProtocolFactory,
const stdcxx::shared_ptr<apache::thrift::protocol::TProtocolFactory>& outputProtocolFactory,
const stdcxx::shared_ptr<apache::thrift::concurrency::ThreadManager>& threadManager
= apache::thrift::concurrency::ThreadManager::newSimpleThreadManager());
TThreadPoolServer(
const boost::shared_ptr<apache::thrift::TProcessor>& processor,
const boost::shared_ptr<apache::thrift::transport::TServerTransport>& serverTransport,
const boost::shared_ptr<apache::thrift::transport::TTransportFactory>& inputTransportFactory,
const boost::shared_ptr<apache::thrift::transport::TTransportFactory>& outputTransportFactory,
const boost::shared_ptr<apache::thrift::protocol::TProtocolFactory>& inputProtocolFactory,
const boost::shared_ptr<apache::thrift::protocol::TProtocolFactory>& outputProtocolFactory,
const boost::shared_ptr<apache::thrift::concurrency::ThreadManager>& threadManager
const stdcxx::shared_ptr<apache::thrift::TProcessor>& processor,
const stdcxx::shared_ptr<apache::thrift::transport::TServerTransport>& serverTransport,
const stdcxx::shared_ptr<apache::thrift::transport::TTransportFactory>& inputTransportFactory,
const stdcxx::shared_ptr<apache::thrift::transport::TTransportFactory>& outputTransportFactory,
const stdcxx::shared_ptr<apache::thrift::protocol::TProtocolFactory>& inputProtocolFactory,
const stdcxx::shared_ptr<apache::thrift::protocol::TProtocolFactory>& outputProtocolFactory,
const stdcxx::shared_ptr<apache::thrift::concurrency::ThreadManager>& threadManager
= apache::thrift::concurrency::ThreadManager::newSimpleThreadManager());
virtual ~TThreadPoolServer();
@ -83,13 +83,13 @@ public:
virtual int64_t getTaskExpiration() const;
virtual void setTaskExpiration(int64_t value);
virtual boost::shared_ptr<apache::thrift::concurrency::ThreadManager> getThreadManager() const;
virtual stdcxx::shared_ptr<apache::thrift::concurrency::ThreadManager> getThreadManager() const;
protected:
virtual void onClientConnected(const boost::shared_ptr<TConnectedClient>& pClient) /* override */;
virtual void onClientConnected(const stdcxx::shared_ptr<TConnectedClient>& pClient) /* override */;
virtual void onClientDisconnected(TConnectedClient* pClient) /* override */;
boost::shared_ptr<apache::thrift::concurrency::ThreadManager> threadManager_;
stdcxx::shared_ptr<apache::thrift::concurrency::ThreadManager> threadManager_;
boost::atomic<int64_t> timeout_;
boost::atomic<int64_t> taskExpiration_;
};

View file

@ -17,11 +17,8 @@
* under the License.
*/
#include <boost/bind.hpp>
#include <boost/function.hpp>
#include <boost/make_shared.hpp>
#include <boost/shared_ptr.hpp>
#include <string>
#include <thrift/stdcxx.h>
#include <thrift/concurrency/PlatformThreadFactory.h>
#include <thrift/server/TThreadedServer.h>
@ -35,11 +32,12 @@ using apache::thrift::concurrency::Thread;
using apache::thrift::concurrency::ThreadFactory;
using apache::thrift::protocol::TProtocol;
using apache::thrift::protocol::TProtocolFactory;
using apache::thrift::stdcxx::make_shared;
using apache::thrift::stdcxx::shared_ptr;
using apache::thrift::transport::TServerTransport;
using apache::thrift::transport::TTransport;
using apache::thrift::transport::TTransportException;
using apache::thrift::transport::TTransportFactory;
using boost::shared_ptr;
TThreadedServer::TThreadedServer(const shared_ptr<TProcessorFactory>& processorFactory,
const shared_ptr<TServerTransport>& serverTransport,
@ -117,8 +115,8 @@ void TThreadedServer::drainDeadClients() {
void TThreadedServer::onClientConnected(const shared_ptr<TConnectedClient>& pClient) {
Synchronized sync(clientMonitor_);
boost::shared_ptr<TConnectedClientRunner> pRunnable = boost::make_shared<TConnectedClientRunner>(pClient);
boost::shared_ptr<Thread> pThread = threadFactory_->newThread(pRunnable);
shared_ptr<TConnectedClientRunner> pRunnable = make_shared<TConnectedClientRunner>(pClient);
shared_ptr<Thread> pThread = threadFactory_->newThread(pRunnable);
pRunnable->thread(pThread);
activeClientMap_.insert(ClientMap::value_type(pClient.get(), pThread));
pThread->start();
@ -128,15 +126,17 @@ void TThreadedServer::onClientDisconnected(TConnectedClient* pClient) {
Synchronized sync(clientMonitor_);
drainDeadClients(); // use the outgoing thread to do some maintenance on our dead client backlog
ClientMap::iterator it = activeClientMap_.find(pClient);
ClientMap::iterator end = it;
deadClientMap_.insert(it, ++end);
activeClientMap_.erase(it);
if (it != activeClientMap_.end()) {
ClientMap::iterator end = it;
deadClientMap_.insert(it, ++end);
activeClientMap_.erase(it);
}
if (activeClientMap_.empty()) {
clientMonitor_.notify();
}
}
TThreadedServer::TConnectedClientRunner::TConnectedClientRunner(const boost::shared_ptr<TConnectedClient>& pClient)
TThreadedServer::TConnectedClientRunner::TConnectedClientRunner(const shared_ptr<TConnectedClient>& pClient)
: pClient_(pClient) {
}

View file

@ -38,43 +38,43 @@ namespace server {
class TThreadedServer : public TServerFramework {
public:
TThreadedServer(
const boost::shared_ptr<apache::thrift::TProcessorFactory>& processorFactory,
const boost::shared_ptr<apache::thrift::transport::TServerTransport>& serverTransport,
const boost::shared_ptr<apache::thrift::transport::TTransportFactory>& transportFactory,
const boost::shared_ptr<apache::thrift::protocol::TProtocolFactory>& protocolFactory,
const boost::shared_ptr<apache::thrift::concurrency::ThreadFactory>& threadFactory
= boost::shared_ptr<apache::thrift::concurrency::ThreadFactory>(
const stdcxx::shared_ptr<apache::thrift::TProcessorFactory>& processorFactory,
const stdcxx::shared_ptr<apache::thrift::transport::TServerTransport>& serverTransport,
const stdcxx::shared_ptr<apache::thrift::transport::TTransportFactory>& transportFactory,
const stdcxx::shared_ptr<apache::thrift::protocol::TProtocolFactory>& protocolFactory,
const stdcxx::shared_ptr<apache::thrift::concurrency::ThreadFactory>& threadFactory
= stdcxx::shared_ptr<apache::thrift::concurrency::ThreadFactory>(
new apache::thrift::concurrency::PlatformThreadFactory(false)));
TThreadedServer(
const boost::shared_ptr<apache::thrift::TProcessor>& processor,
const boost::shared_ptr<apache::thrift::transport::TServerTransport>& serverTransport,
const boost::shared_ptr<apache::thrift::transport::TTransportFactory>& transportFactory,
const boost::shared_ptr<apache::thrift::protocol::TProtocolFactory>& protocolFactory,
const boost::shared_ptr<apache::thrift::concurrency::ThreadFactory>& threadFactory
= boost::shared_ptr<apache::thrift::concurrency::ThreadFactory>(
const stdcxx::shared_ptr<apache::thrift::TProcessor>& processor,
const stdcxx::shared_ptr<apache::thrift::transport::TServerTransport>& serverTransport,
const stdcxx::shared_ptr<apache::thrift::transport::TTransportFactory>& transportFactory,
const stdcxx::shared_ptr<apache::thrift::protocol::TProtocolFactory>& protocolFactory,
const stdcxx::shared_ptr<apache::thrift::concurrency::ThreadFactory>& threadFactory
= stdcxx::shared_ptr<apache::thrift::concurrency::ThreadFactory>(
new apache::thrift::concurrency::PlatformThreadFactory(false)));
TThreadedServer(
const boost::shared_ptr<apache::thrift::TProcessorFactory>& processorFactory,
const boost::shared_ptr<apache::thrift::transport::TServerTransport>& serverTransport,
const boost::shared_ptr<apache::thrift::transport::TTransportFactory>& inputTransportFactory,
const boost::shared_ptr<apache::thrift::transport::TTransportFactory>& outputTransportFactory,
const boost::shared_ptr<apache::thrift::protocol::TProtocolFactory>& inputProtocolFactory,
const boost::shared_ptr<apache::thrift::protocol::TProtocolFactory>& outputProtocolFactory,
const boost::shared_ptr<apache::thrift::concurrency::ThreadFactory>& threadFactory
= boost::shared_ptr<apache::thrift::concurrency::ThreadFactory>(
const stdcxx::shared_ptr<apache::thrift::TProcessorFactory>& processorFactory,
const stdcxx::shared_ptr<apache::thrift::transport::TServerTransport>& serverTransport,
const stdcxx::shared_ptr<apache::thrift::transport::TTransportFactory>& inputTransportFactory,
const stdcxx::shared_ptr<apache::thrift::transport::TTransportFactory>& outputTransportFactory,
const stdcxx::shared_ptr<apache::thrift::protocol::TProtocolFactory>& inputProtocolFactory,
const stdcxx::shared_ptr<apache::thrift::protocol::TProtocolFactory>& outputProtocolFactory,
const stdcxx::shared_ptr<apache::thrift::concurrency::ThreadFactory>& threadFactory
= stdcxx::shared_ptr<apache::thrift::concurrency::ThreadFactory>(
new apache::thrift::concurrency::PlatformThreadFactory(false)));
TThreadedServer(
const boost::shared_ptr<apache::thrift::TProcessor>& processor,
const boost::shared_ptr<apache::thrift::transport::TServerTransport>& serverTransport,
const boost::shared_ptr<apache::thrift::transport::TTransportFactory>& inputTransportFactory,
const boost::shared_ptr<apache::thrift::transport::TTransportFactory>& outputTransportFactory,
const boost::shared_ptr<apache::thrift::protocol::TProtocolFactory>& inputProtocolFactory,
const boost::shared_ptr<apache::thrift::protocol::TProtocolFactory>& outputProtocolFactory,
const boost::shared_ptr<apache::thrift::concurrency::ThreadFactory>& threadFactory
= boost::shared_ptr<apache::thrift::concurrency::ThreadFactory>(
const stdcxx::shared_ptr<apache::thrift::TProcessor>& processor,
const stdcxx::shared_ptr<apache::thrift::transport::TServerTransport>& serverTransport,
const stdcxx::shared_ptr<apache::thrift::transport::TTransportFactory>& inputTransportFactory,
const stdcxx::shared_ptr<apache::thrift::transport::TTransportFactory>& outputTransportFactory,
const stdcxx::shared_ptr<apache::thrift::protocol::TProtocolFactory>& inputProtocolFactory,
const stdcxx::shared_ptr<apache::thrift::protocol::TProtocolFactory>& outputProtocolFactory,
const stdcxx::shared_ptr<apache::thrift::concurrency::ThreadFactory>& threadFactory
= stdcxx::shared_ptr<apache::thrift::concurrency::ThreadFactory>(
new apache::thrift::concurrency::PlatformThreadFactory(false)));
virtual ~TThreadedServer();
@ -95,14 +95,14 @@ protected:
/**
* Implementation of TServerFramework::onClientConnected
*/
virtual void onClientConnected(const boost::shared_ptr<TConnectedClient>& pClient) /* override */;
virtual void onClientConnected(const stdcxx::shared_ptr<TConnectedClient>& pClient) /* override */;
/**
* Implementation of TServerFramework::onClientDisconnected
*/
virtual void onClientDisconnected(TConnectedClient *pClient) /* override */;
boost::shared_ptr<apache::thrift::concurrency::ThreadFactory> threadFactory_;
stdcxx::shared_ptr<apache::thrift::concurrency::ThreadFactory> threadFactory_;
/**
* A helper wrapper used to wrap the client in something we can use to maintain
@ -114,16 +114,16 @@ protected:
class TConnectedClientRunner : public apache::thrift::concurrency::Runnable
{
public:
TConnectedClientRunner(const boost::shared_ptr<TConnectedClient>& pClient);
TConnectedClientRunner(const stdcxx::shared_ptr<TConnectedClient>& pClient);
virtual ~TConnectedClientRunner();
void run() /* override */;
private:
boost::shared_ptr<TConnectedClient> pClient_;
stdcxx::shared_ptr<TConnectedClient> pClient_;
};
apache::thrift::concurrency::Monitor clientMonitor_;
typedef std::map<TConnectedClient *, boost::shared_ptr<apache::thrift::concurrency::Thread> > ClientMap;
typedef std::map<TConnectedClient *, stdcxx::shared_ptr<apache::thrift::concurrency::Thread> > ClientMap;
/**
* A map of active clients

View file

@ -0,0 +1,129 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
#ifndef _THRIFT_STDCXX_H_
#define _THRIFT_STDCXX_H_ 1
#include <boost/config.hpp>
#include <boost/version.hpp>
///////////////////////////////////////////////////////////////////
//
// functional (function, bind)
//
///////////////////////////////////////////////////////////////////
#if defined(BOOST_NO_CXX11_HDR_FUNCTIONAL) || (defined(_MSC_VER) && _MSC_VER < 1800) || defined(FORCE_BOOST_FUNCTIONAL)
#if (BOOST_VERSION <= 106500)
#include <boost/tr1/functional.hpp>
#else
#include <tr1/functional>
#endif
#define _THRIFT_FUNCTIONAL_TR1_ 1
#endif
#if _THRIFT_FUNCTIONAL_TR1_
namespace apache { namespace thrift { namespace stdcxx {
using ::std::tr1::bind;
using ::std::tr1::function;
namespace placeholders {
using ::std::tr1::placeholders::_1;
using ::std::tr1::placeholders::_2;
using ::std::tr1::placeholders::_3;
using ::std::tr1::placeholders::_4;
using ::std::tr1::placeholders::_5;
using ::std::tr1::placeholders::_6;
using ::std::tr1::placeholders::_7;
using ::std::tr1::placeholders::_8;
using ::std::tr1::placeholders::_9;
} // apache::thrift::stdcxx::placeholders
}}} // apache::thrift::stdcxx
#else
#include <functional>
namespace apache { namespace thrift { namespace stdcxx {
using ::std::bind;
using ::std::function;
namespace placeholders {
using ::std::placeholders::_1;
using ::std::placeholders::_2;
using ::std::placeholders::_3;
using ::std::placeholders::_4;
using ::std::placeholders::_5;
using ::std::placeholders::_6;
using ::std::placeholders::_7;
using ::std::placeholders::_8;
using ::std::placeholders::_9;
} // apache::thrift::stdcxx::placeholders
}}} // apache::thrift::stdcxx
#endif
///////////////////////////////////////////////////////////////////
//
// Smart Pointers
//
///////////////////////////////////////////////////////////////////
// We can use std for memory functions only if the compiler supports template aliasing
// The macro BOOST_NO_CXX11_SMART_PTR is defined as 1 under Visual Studio 2010 and 2012
// which do not support the feature, so we must continue to use C++98 and boost on them.
// We cannot use __cplusplus to detect this either, since Microsoft advertises an older one.
#if defined(BOOST_NO_CXX11_SMART_PTR) || (defined(_MSC_VER) && _MSC_VER < 1800) || defined(FORCE_BOOST_SMART_PTR)
#include <boost/smart_ptr.hpp>
#else
#include <memory>
#endif
namespace apache { namespace thrift { namespace stdcxx {
#if defined(BOOST_NO_CXX11_SMART_PTR) || (defined(_MSC_VER) && _MSC_VER < 1800) || defined(FORCE_BOOST_SMART_PTR)
using ::boost::const_pointer_cast;
using ::boost::dynamic_pointer_cast;
using ::boost::enable_shared_from_this;
using ::boost::make_shared;
using ::boost::scoped_ptr;
using ::boost::shared_ptr;
using ::boost::static_pointer_cast;
using ::boost::weak_ptr;
#else
using ::std::const_pointer_cast;
using ::std::dynamic_pointer_cast;
using ::std::enable_shared_from_this;
using ::std::make_shared;
template <typename T> using scoped_ptr = std::unique_ptr<T>; // compiler must support template aliasing
using ::std::shared_ptr;
using ::std::static_pointer_cast;
using ::std::weak_ptr;
#endif
}}} // apache::thrift::stdcxx
#endif // #ifndef _THRIFT_STDCXX_H_

View file

@ -23,6 +23,7 @@
# define _THRIFT_TRANSPORT_PLATFORM_SOCKET_H_
#ifdef _WIN32
# include <winsock2.h>
# define THRIFT_GET_SOCKET_ERROR ::WSAGetLastError()
# define THRIFT_ERRNO (*_errno())
# define THRIFT_EINPROGRESS WSAEINPROGRESS
@ -50,6 +51,8 @@
# define THRIFT_LSEEK _lseek
# define THRIFT_WRITE _write
# define THRIFT_READ _read
# define THRIFT_IOCTL_SOCKET ioctlsocket
# define THRIFT_IOCTL_SOCKET_NUM_BYTES_TYPE u_long
# define THRIFT_FSTAT _fstat
# define THRIFT_STAT _stat
# ifdef _WIN32_WCE
@ -78,6 +81,9 @@
# define THRIFT_POLLOUT POLLOUT
# endif //WINVER
# define THRIFT_SHUT_RDWR SD_BOTH
# if !defined(AI_ADDRCONFIG)
# define AI_ADDRCONFIG 0x00000400
# endif
#else //not _WIN32
# include <errno.h>
# define THRIFT_GET_SOCKET_ERROR errno
@ -107,6 +113,8 @@
# define THRIFT_LSEEK lseek
# define THRIFT_WRITE write
# define THRIFT_READ read
# define THRIFT_IOCTL_SOCKET ioctl
# define THRIFT_IOCTL_SOCKET_NUM_BYTES_TYPE int
# define THRIFT_STAT stat
# define THRIFT_FSTAT fstat
# define THRIFT_GAI_STRERROR gai_strerror

View file

@ -361,10 +361,14 @@ void TMemoryBuffer::ensureCanWrite(uint32_t len) {
}
// Grow the buffer as necessary.
uint32_t new_size = bufferSize_;
uint64_t new_size = bufferSize_;
while (len > avail) {
new_size = new_size > 0 ? new_size * 2 : 1;
avail = available_write() + (new_size - bufferSize_);
if (new_size > maxBufferSize_) {
throw TTransportException(TTransportException::BAD_ARGS,
"Internal buffer size overflow");
}
avail = available_write() + (static_cast<uint32_t>(new_size) - bufferSize_);
}
// Allocate into a new pointer so we don't bork ours if it fails.
@ -378,7 +382,7 @@ void TMemoryBuffer::ensureCanWrite(uint32_t len) {
wBase_ = new_buffer + (wBase_ - buffer_);
wBound_ = new_buffer + new_size;
buffer_ = new_buffer;
bufferSize_ = new_size;
bufferSize_ = static_cast<uint32_t>(new_size);
}
void TMemoryBuffer::writeSlow(const uint8_t* buf, uint32_t len) {

View file

@ -186,7 +186,7 @@ public:
static const int DEFAULT_BUFFER_SIZE = 512;
/// Use default buffer sizes.
TBufferedTransport(boost::shared_ptr<TTransport> transport)
TBufferedTransport(stdcxx::shared_ptr<TTransport> transport)
: transport_(transport),
rBufSize_(DEFAULT_BUFFER_SIZE),
wBufSize_(DEFAULT_BUFFER_SIZE),
@ -196,7 +196,7 @@ public:
}
/// Use specified buffer sizes.
TBufferedTransport(boost::shared_ptr<TTransport> transport, uint32_t sz)
TBufferedTransport(stdcxx::shared_ptr<TTransport> transport, uint32_t sz)
: transport_(transport),
rBufSize_(sz),
wBufSize_(sz),
@ -206,7 +206,7 @@ public:
}
/// Use specified read and write buffer sizes.
TBufferedTransport(boost::shared_ptr<TTransport> transport, uint32_t rsz, uint32_t wsz)
TBufferedTransport(stdcxx::shared_ptr<TTransport> transport, uint32_t rsz, uint32_t wsz)
: transport_(transport),
rBufSize_(rsz),
wBufSize_(wsz),
@ -255,7 +255,7 @@ public:
*/
virtual const uint8_t* borrowSlow(uint8_t* buf, uint32_t* len);
boost::shared_ptr<TTransport> getUnderlyingTransport() { return transport_; }
stdcxx::shared_ptr<TTransport> getUnderlyingTransport() { return transport_; }
/*
* TVirtualTransport provides a default implementation of readAll().
@ -270,7 +270,7 @@ protected:
// Write size never changes.
}
boost::shared_ptr<TTransport> transport_;
stdcxx::shared_ptr<TTransport> transport_;
uint32_t rBufSize_;
uint32_t wBufSize_;
@ -291,8 +291,8 @@ public:
/**
* Wraps the transport into a buffered one.
*/
virtual boost::shared_ptr<TTransport> getTransport(boost::shared_ptr<TTransport> trans) {
return boost::shared_ptr<TTransport>(new TBufferedTransport(trans));
virtual stdcxx::shared_ptr<TTransport> getTransport(stdcxx::shared_ptr<TTransport> trans) {
return stdcxx::shared_ptr<TTransport>(new TBufferedTransport(trans));
}
};
@ -319,7 +319,7 @@ public:
initPointers();
}
TFramedTransport(boost::shared_ptr<TTransport> transport)
TFramedTransport(stdcxx::shared_ptr<TTransport> transport)
: transport_(transport),
rBufSize_(0),
wBufSize_(DEFAULT_BUFFER_SIZE),
@ -330,7 +330,7 @@ public:
initPointers();
}
TFramedTransport(boost::shared_ptr<TTransport> transport,
TFramedTransport(stdcxx::shared_ptr<TTransport> transport,
uint32_t sz,
uint32_t bufReclaimThresh = (std::numeric_limits<uint32_t>::max)())
: transport_(transport),
@ -366,7 +366,7 @@ public:
const uint8_t* borrowSlow(uint8_t* buf, uint32_t* len);
boost::shared_ptr<TTransport> getUnderlyingTransport() { return transport_; }
stdcxx::shared_ptr<TTransport> getUnderlyingTransport() { return transport_; }
/*
* TVirtualTransport provides a default implementation of readAll().
@ -407,7 +407,7 @@ protected:
this->write((uint8_t*)&pad, sizeof(pad));
}
boost::shared_ptr<TTransport> transport_;
stdcxx::shared_ptr<TTransport> transport_;
uint32_t rBufSize_;
uint32_t wBufSize_;
@ -430,8 +430,8 @@ public:
/**
* Wraps the transport into a framed one.
*/
virtual boost::shared_ptr<TTransport> getTransport(boost::shared_ptr<TTransport> trans) {
return boost::shared_ptr<TTransport>(new TFramedTransport(trans));
virtual stdcxx::shared_ptr<TTransport> getTransport(stdcxx::shared_ptr<TTransport> trans) {
return stdcxx::shared_ptr<TTransport>(new TFramedTransport(trans));
}
};
@ -448,11 +448,14 @@ class TMemoryBuffer : public TVirtualTransport<TMemoryBuffer, TBufferBase> {
private:
// Common initialization done by all constructors.
void initCommon(uint8_t* buf, uint32_t size, bool owner, uint32_t wPos) {
maxBufferSize_ = (std::numeric_limits<uint32_t>::max)();
if (buf == NULL && size != 0) {
assert(owner);
buf = (uint8_t*)std::malloc(size);
if (buf == NULL) {
throw std::bad_alloc();
throw std::bad_alloc();
}
}
@ -673,6 +676,29 @@ public:
*/
uint32_t readAll(uint8_t* buf, uint32_t len) { return TBufferBase::readAll(buf, len); }
//! \brief Get the current buffer size
//! \returns the current buffer size
uint32_t getBufferSize() const {
return bufferSize_;
}
//! \brief Get the current maximum buffer size
//! \returns the current maximum buffer size
uint32_t getMaxBufferSize() const {
return maxBufferSize_;
}
//! \brief Change the maximum buffer size
//! \param[in] maxSize the new maximum buffer size allowed to grow to
//! \throws TTransportException(BAD_ARGS) if maxSize is less than the current buffer size
void setMaxBufferSize(uint32_t maxSize) {
if (maxSize < bufferSize_) {
throw TTransportException(TTransportException::BAD_ARGS,
"Maximum buffer size would be less than current buffer size");
}
maxBufferSize_ = maxSize;
}
protected:
void swap(TMemoryBuffer& that) {
using std::swap;
@ -705,6 +731,9 @@ protected:
// Allocated buffer size
uint32_t bufferSize_;
// Maximum allowed size
uint32_t maxBufferSize_;
// Is this object the owner of the buffer?
bool owner_;

View file

@ -31,7 +31,7 @@
#include <io.h>
#endif
using namespace std;
using std::string;
namespace apache {
namespace thrift {

View file

@ -24,6 +24,15 @@
#include <thrift/transport/PlatformSocket.h>
#include <thrift/concurrency/FunctionRunner.h>
#include <boost/version.hpp>
#if (BOOST_VERSION >= 105700)
#include <boost/move/unique_ptr.hpp>
using boost::movelib::unique_ptr;
#else
#include <boost/interprocess/smart_ptr/unique_ptr.hpp>
using boost::interprocess::unique_ptr;
#endif
#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
#else
@ -52,9 +61,11 @@ namespace apache {
namespace thrift {
namespace transport {
using boost::scoped_ptr;
using boost::shared_ptr;
using namespace std;
using stdcxx::shared_ptr;
using std::cerr;
using std::cout;
using std::endl;
using std::string;
using namespace apache::thrift::protocol;
using namespace apache::thrift::concurrency;
@ -192,6 +203,14 @@ void TFileTransport::write(const uint8_t* buf, uint32_t len) {
enqueueEvent(buf, len);
}
// this is needed until boost 1.57 as the older unique_ptr implementation
// has no default deleter in interprocess
template <class _T>
struct uniqueDeleter
{
void operator()(_T *ptr) const { delete ptr; }
};
void TFileTransport::enqueueEvent(const uint8_t* buf, uint32_t eventLen) {
// can't enqueue more events if file is going to close
if (closing_) {
@ -209,7 +228,7 @@ void TFileTransport::enqueueEvent(const uint8_t* buf, uint32_t eventLen) {
return;
}
std::auto_ptr<eventInfo> toEnqueue(new eventInfo());
unique_ptr<eventInfo, uniqueDeleter<eventInfo> > toEnqueue(new eventInfo());
toEnqueue->eventBuff_ = new uint8_t[(sizeof(uint8_t) * eventLen) + 4];
// first 4 bytes is the event length
@ -363,7 +382,7 @@ void TFileTransport::writerThread() {
while (hasIOError) {
T_ERROR(
"TFileTransport: writer thread going to sleep for %d microseconds due to IO errors",
"TFileTransport: writer thread going to sleep for %u microseconds due to IO errors",
writerThreadIOErrorSleepTime_);
THRIFT_SLEEP_USEC(writerThreadIOErrorSleepTime_);
if (closing_) {
@ -685,8 +704,8 @@ eventInfo* TFileTransport::readEvent() {
readState_.event_->eventBuffPos_ = 0;
}
// take either the entire event or the remaining bytes in the buffer
int reclaimBuffer = min((uint32_t)(readState_.bufferLen_ - readState_.bufferPtr_),
readState_.event_->eventSize_ - readState_.event_->eventBuffPos_);
int reclaimBuffer = (std::min)((uint32_t)(readState_.bufferLen_ - readState_.bufferPtr_),
readState_.event_->eventSize_ - readState_.event_->eventBuffPos_);
// copy data from read buffer into event buffer
memcpy(readState_.event_->eventBuff_ + readState_.event_->eventBuffPos_,
@ -832,7 +851,7 @@ void TFileTransport::seekToChunk(int32_t chunk) {
uint32_t oldReadTimeout = getReadTimeout();
setReadTimeout(NO_TAIL_READ_TIMEOUT);
// keep on reading unti the last event at point of seekChunk call
boost::scoped_ptr<eventInfo> event;
shared_ptr<eventInfo> event;
while ((offset_ + readState_.bufferPtr_) < minEndOffset) {
event.reset(readEvent());
if (event.get() == NULL) {

View file

@ -28,8 +28,7 @@
#include <stdio.h>
#include <boost/atomic.hpp>
#include <boost/scoped_ptr.hpp>
#include <boost/shared_ptr.hpp>
#include <thrift/stdcxx.h>
#include <thrift/concurrency/Mutex.h>
#include <thrift/concurrency/Monitor.h>
@ -340,7 +339,7 @@ private:
// writer thread
apache::thrift::concurrency::PlatformThreadFactory threadFactory_;
boost::shared_ptr<apache::thrift::concurrency::Thread> writerThread_;
stdcxx::shared_ptr<apache::thrift::concurrency::Thread> writerThread_;
// buffers to hold data before it is flushed. Each element of the buffer stores a msg that
// needs to be written to the file. The buffers are swapped by the writer thread.
@ -349,7 +348,7 @@ private:
// conditions used to block when the buffer is full or empty
Monitor notFull_, notEmpty_;
bool closing_;
boost::atomic<bool> closing_;
// To keep track of whether the buffer has been flushed
Monitor flushed_;
@ -391,14 +390,14 @@ public:
* @param protocolFactory protocol factory
* @param inputTransport file transport
*/
TFileProcessor(boost::shared_ptr<TProcessor> processor,
boost::shared_ptr<TProtocolFactory> protocolFactory,
boost::shared_ptr<TFileReaderTransport> inputTransport);
TFileProcessor(stdcxx::shared_ptr<TProcessor> processor,
stdcxx::shared_ptr<TProtocolFactory> protocolFactory,
stdcxx::shared_ptr<TFileReaderTransport> inputTransport);
TFileProcessor(boost::shared_ptr<TProcessor> processor,
boost::shared_ptr<TProtocolFactory> inputProtocolFactory,
boost::shared_ptr<TProtocolFactory> outputProtocolFactory,
boost::shared_ptr<TFileReaderTransport> inputTransport);
TFileProcessor(stdcxx::shared_ptr<TProcessor> processor,
stdcxx::shared_ptr<TProtocolFactory> inputProtocolFactory,
stdcxx::shared_ptr<TProtocolFactory> outputProtocolFactory,
stdcxx::shared_ptr<TFileReaderTransport> inputTransport);
/**
* Constructor
@ -408,10 +407,10 @@ public:
* @param inputTransport input file transport
* @param output output transport
*/
TFileProcessor(boost::shared_ptr<TProcessor> processor,
boost::shared_ptr<TProtocolFactory> protocolFactory,
boost::shared_ptr<TFileReaderTransport> inputTransport,
boost::shared_ptr<TTransport> outputTransport);
TFileProcessor(stdcxx::shared_ptr<TProcessor> processor,
stdcxx::shared_ptr<TProtocolFactory> protocolFactory,
stdcxx::shared_ptr<TFileReaderTransport> inputTransport,
stdcxx::shared_ptr<TTransport> outputTransport);
/**
* processes events from the file
@ -428,11 +427,11 @@ public:
void processChunk();
private:
boost::shared_ptr<TProcessor> processor_;
boost::shared_ptr<TProtocolFactory> inputProtocolFactory_;
boost::shared_ptr<TProtocolFactory> outputProtocolFactory_;
boost::shared_ptr<TFileReaderTransport> inputTransport_;
boost::shared_ptr<TTransport> outputTransport_;
stdcxx::shared_ptr<TProcessor> processor_;
stdcxx::shared_ptr<TProtocolFactory> inputProtocolFactory_;
stdcxx::shared_ptr<TProtocolFactory> outputProtocolFactory_;
stdcxx::shared_ptr<TFileReaderTransport> inputTransport_;
stdcxx::shared_ptr<TTransport> outputTransport_;
};
}
}

View file

@ -22,20 +22,23 @@
#include <thrift/protocol/TProtocolTypes.h>
#include <thrift/protocol/TBinaryProtocol.h>
#include <thrift/protocol/TCompactProtocol.h>
#include <thrift/stdcxx.h>
#include <limits>
#include <utility>
#include <cassert>
#include <string>
#include <zlib.h>
#include <string.h>
#include <zlib.h>
using std::map;
using boost::shared_ptr;
using std::string;
using std::vector;
namespace apache {
namespace thrift {
using stdcxx::shared_ptr;
namespace transport {
using namespace apache::thrift::protocol;
@ -172,7 +175,7 @@ bool THeaderTransport::readFrame() {
* Reads a string from ptr, taking care not to reach headerBoundary
* Advances ptr on success
*
* @param str output string
* @param str output string
* @throws CORRUPTED_DATA if size of string exceeds boundary
*/
void THeaderTransport::readString(uint8_t*& ptr,
@ -198,7 +201,10 @@ void THeaderTransport::readHeaderFormat(uint16_t headerSize, uint32_t sz) {
uint8_t* ptr = reinterpret_cast<uint8_t*>(rBuf_.get() + 10);
// Catch integer overflow, check for reasonable header size
assert(headerSize < 16384);
if (headerSize >= 16384) {
throw TTransportException(TTransportException::CORRUPTED_DATA,
"Header size is unreasonable");
}
headerSize *= 4;
const uint8_t* const headerBoundary = ptr + headerSize;
if (headerSize > sz) {
@ -252,7 +258,7 @@ void THeaderTransport::readHeaderFormat(uint16_t headerSize, uint32_t sz) {
}
// Untransform the data section. rBuf will contain result.
untransform(data, sz - (data - rBuf_.get())); // ignore header in size calc
untransform(data, safe_numeric_cast<uint32_t>(static_cast<ptrdiff_t>(sz) - (data - rBuf_.get())));
}
void THeaderTransport::untransform(uint8_t* ptr, uint32_t sz) {
@ -375,7 +381,7 @@ void THeaderTransport::resetProtocol() {
}
uint32_t THeaderTransport::getWriteBytes() {
return wBase_ - wBuf_.get();
return safe_numeric_cast<uint32_t>(wBase_ - wBuf_.get());
}
/**
@ -384,7 +390,7 @@ uint32_t THeaderTransport::getWriteBytes() {
* Automatically advances ptr to after the written portion
*/
void THeaderTransport::writeString(uint8_t*& ptr, const string& str) {
uint32_t strLen = str.length();
int32_t strLen = safe_numeric_cast<int32_t>(str.length());
ptr += writeVarint32(strLen, ptr);
memcpy(ptr, str.c_str(), strLen); // no need to write \0
ptr += strLen;
@ -394,7 +400,7 @@ void THeaderTransport::setHeader(const string& key, const string& value) {
writeHeaders_[key] = value;
}
size_t THeaderTransport::getMaxWriteHeadersSize() const {
uint32_t THeaderTransport::getMaxWriteHeadersSize() const {
size_t maxWriteHeadersSize = 0;
THeaderTransport::StringToStringMap::const_iterator it;
for (it = writeHeaders_.begin(); it != writeHeaders_.end(); ++it) {
@ -402,7 +408,7 @@ size_t THeaderTransport::getMaxWriteHeadersSize() const {
// 2 varints32 + the strings themselves
maxWriteHeadersSize += 5 + 5 + (it->first).length() + (it->second).length();
}
return maxWriteHeadersSize;
return safe_numeric_cast<uint32_t>(maxWriteHeadersSize);
}
void THeaderTransport::clearHeaders() {
@ -431,7 +437,7 @@ void THeaderTransport::flush() {
if (clientType == THRIFT_HEADER_CLIENT_TYPE) {
// header size will need to be updated at the end because of varints.
// Make it big enough here for max varint size, plus 4 for padding.
int headerSize = (2 + getNumTransforms()) * THRIFT_MAX_VARINT32_BYTES + 4;
uint32_t headerSize = (2 + getNumTransforms()) * THRIFT_MAX_VARINT32_BYTES + 4;
// add approximate size of info headers
headerSize += getMaxWriteHeadersSize();
@ -479,11 +485,11 @@ void THeaderTransport::flush() {
// write info headers
// for now only write kv-headers
uint16_t headerCount = writeHeaders_.size();
int32_t headerCount = safe_numeric_cast<int32_t>(writeHeaders_.size());
if (headerCount > 0) {
pkt += writeVarint32(infoIdType::KEYVALUE, pkt);
// Write key-value headers count
pkt += writeVarint32(headerCount, pkt);
pkt += writeVarint32(static_cast<int32_t>(headerCount), pkt);
// Write info headers
map<string, string>::const_iterator it;
for (it = writeHeaders_.begin(); it != writeHeaders_.end(); ++it) {
@ -494,7 +500,7 @@ void THeaderTransport::flush() {
}
// Fixups after varint size calculations
headerSize = (pkt - headerStart);
headerSize = safe_numeric_cast<uint32_t>(pkt - headerStart);
uint8_t padding = 4 - (headerSize % 4);
headerSize += padding;
@ -504,8 +510,13 @@ void THeaderTransport::flush() {
}
// Pkt size
ptrdiff_t szHbp = (headerStart - pktStart - 4);
if (static_cast<uint64_t>(szHbp) > static_cast<uint64_t>((std::numeric_limits<uint32_t>().max)()) - (headerSize + haveBytes)) {
throw TTransportException(TTransportException::CORRUPTED_DATA,
"Header section size is unreasonable");
}
szHbo = headerSize + haveBytes // thrift header + payload
+ (headerStart - pktStart - 4); // common header section
+ static_cast<uint32_t>(szHbp); // common header section
headerSizeN = htons(headerSize / 4);
memcpy(headerSizePtr, &headerSizeN, sizeof(headerSizeN));

View file

@ -21,13 +21,20 @@
#define THRIFT_TRANSPORT_THEADERTRANSPORT_H_ 1
#include <bitset>
#include <limits>
#include <vector>
#include <stdexcept>
#include <string>
#include <map>
#ifdef HAVE_STDINT_H
#include <stdint.h>
#elif HAVE_INTTYPES_H
#include <inttypes.h>
#endif
#include <boost/scoped_array.hpp>
#include <boost/shared_ptr.hpp>
#include <thrift/stdcxx.h>
#include <thrift/protocol/TProtocolTypes.h>
#include <thrift/transport/TBufferTransports.h>
@ -68,7 +75,7 @@ public:
static const int THRIFT_MAX_VARINT32_BYTES = 5;
/// Use default buffer sizes.
explicit THeaderTransport(const boost::shared_ptr<TTransport>& transport)
explicit THeaderTransport(const stdcxx::shared_ptr<TTransport>& transport)
: TVirtualTransport(transport),
outTransport_(transport),
protoId(T_COMPACT_PROTOCOL),
@ -81,8 +88,8 @@ public:
initBuffers();
}
THeaderTransport(const boost::shared_ptr<TTransport> inTransport,
const boost::shared_ptr<TTransport> outTransport)
THeaderTransport(const stdcxx::shared_ptr<TTransport> inTransport,
const stdcxx::shared_ptr<TTransport> outTransport)
: TVirtualTransport(inTransport),
outTransport_(outTransport),
protoId(T_COMPACT_PROTOCOL),
@ -135,8 +142,7 @@ public:
void transform(uint8_t* ptr, uint32_t sz);
uint16_t getNumTransforms() const {
int trans = writeTrans_.size();
return trans;
return safe_numeric_cast<uint16_t>(writeTrans_.size());
}
void setTransform(uint16_t transId) { writeTrans_.push_back(transId); }
@ -180,7 +186,7 @@ protected:
setWriteBuffer(wBuf_.get(), wBufSize_);
}
boost::shared_ptr<TTransport> outTransport_;
stdcxx::shared_ptr<TTransport> outTransport_;
// 0 and 16th bits must be 0 to differentiate from framed & unframed
static const uint32_t HEADER_MAGIC = 0x0FFF0000;
@ -204,7 +210,7 @@ protected:
/**
* Returns the maximum number of bytes that write k/v headers can take
*/
size_t getMaxWriteHeadersSize() const;
uint32_t getMaxWriteHeadersSize() const;
struct infoIdType {
enum idType {
@ -259,8 +265,8 @@ public:
/**
* Wraps the transport into a header one.
*/
virtual boost::shared_ptr<TTransport> getTransport(boost::shared_ptr<TTransport> trans) {
return boost::shared_ptr<TTransport>(new THeaderTransport(trans));
virtual stdcxx::shared_ptr<TTransport> getTransport(stdcxx::shared_ptr<TTransport> trans) {
return stdcxx::shared_ptr<TTransport>(new THeaderTransport(trans));
}
};
}

View file

@ -22,23 +22,24 @@
#include <sstream>
#include <boost/algorithm/string.hpp>
#include <thrift/config.h>
#include <thrift/transport/THttpClient.h>
#include <thrift/transport/TSocket.h>
using std::string;
namespace apache {
namespace thrift {
namespace transport {
using namespace std;
THttpClient::THttpClient(boost::shared_ptr<TTransport> transport,
THttpClient::THttpClient(stdcxx::shared_ptr<TTransport> transport,
std::string host,
std::string path)
: THttpTransport(transport), host_(host), path_(path) {
}
THttpClient::THttpClient(string host, int port, string path)
: THttpTransport(boost::shared_ptr<TTransport>(new TSocket(host, port))),
: THttpTransport(stdcxx::shared_ptr<TTransport>(new TSocket(host, port))),
host_(host),
path_(path) {
}
@ -102,7 +103,7 @@ void THttpClient::flush() {
std::ostringstream h;
h << "POST " << path_ << " HTTP/1.1" << CRLF << "Host: " << host_ << CRLF
<< "Content-Type: application/x-thrift" << CRLF << "Content-Length: " << len << CRLF
<< "Accept: application/x-thrift" << CRLF << "User-Agent: Thrift/" << VERSION
<< "Accept: application/x-thrift" << CRLF << "User-Agent: Thrift/" << PACKAGE_VERSION
<< " (C++/THttpClient)" << CRLF << CRLF;
string header = h.str();

View file

@ -28,7 +28,7 @@ namespace transport {
class THttpClient : public THttpTransport {
public:
THttpClient(boost::shared_ptr<TTransport> transport, std::string host, std::string path = "");
THttpClient(stdcxx::shared_ptr<TTransport> transport, std::string host, std::string path = "");
THttpClient(std::string host, int port, std::string path = "");

View file

@ -21,28 +21,31 @@
#include <sstream>
#include <iostream>
#include <thrift/config.h>
#include <thrift/transport/THttpServer.h>
#include <thrift/transport/TSocket.h>
#if defined(_MSC_VER) || defined(__MINGW32__)
#include <Shlwapi.h>
#endif
using std::string;
namespace apache {
namespace thrift {
namespace transport {
using namespace std;
THttpServer::THttpServer(boost::shared_ptr<TTransport> transport) : THttpTransport(transport) {
THttpServer::THttpServer(stdcxx::shared_ptr<TTransport> transport) : THttpTransport(transport) {
}
THttpServer::~THttpServer() {
}
#if defined(_MSC_VER) || defined(__MINGW32__)
#define THRIFT_GMTIME(TM, TIME) gmtime_s(&TM, &TIME)
#define THRIFT_strncasecmp(str1, str2, len) _strnicmp(str1, str2, len)
#define THRIFT_strcasestr(haystack, needle) StrStrIA(haystack, needle)
#else
#define THRIFT_GMTIME(TM, TIME) gmtime_r(&TIME, &TM)
#define THRIFT_strncasecmp(str1, str2, len) strncasecmp(str1, str2, len)
#define THRIFT_strcasestr(haystack, needle) strcasestr(haystack, needle)
#endif
@ -124,7 +127,7 @@ void THttpServer::flush() {
// Construct the HTTP header
std::ostringstream h;
h << "HTTP/1.1 200 OK" << CRLF << "Date: " << getTimeRFC1123() << CRLF << "Server: Thrift/"
<< VERSION << CRLF << "Access-Control-Allow-Origin: *" << CRLF
<< PACKAGE_VERSION << CRLF << "Access-Control-Allow-Origin: *" << CRLF
<< "Content-Type: application/x-thrift" << CRLF << "Content-Length: " << len << CRLF
<< "Connection: Keep-Alive" << CRLF << CRLF;
string header = h.str();
@ -145,18 +148,20 @@ std::string THttpServer::getTimeRFC1123() {
static const char* Months[]
= {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
char buff[128];
time_t t = time(NULL);
tm* broken_t = gmtime(&t);
struct tm tmb;
THRIFT_GMTIME(tmb, t);
sprintf(buff,
"%s, %d %s %d %d:%d:%d GMT",
Days[broken_t->tm_wday],
broken_t->tm_mday,
Months[broken_t->tm_mon],
broken_t->tm_year + 1900,
broken_t->tm_hour,
broken_t->tm_min,
broken_t->tm_sec);
Days[tmb.tm_wday],
tmb.tm_mday,
Months[tmb.tm_mon],
tmb.tm_year + 1900,
tmb.tm_hour,
tmb.tm_min,
tmb.tm_sec);
return std::string(buff);
}
}

View file

@ -28,7 +28,7 @@ namespace transport {
class THttpServer : public THttpTransport {
public:
THttpServer(boost::shared_ptr<TTransport> transport);
THttpServer(stdcxx::shared_ptr<TTransport> transport);
virtual ~THttpServer();
@ -53,8 +53,8 @@ public:
/**
* Wraps the transport into a buffered one.
*/
virtual boost::shared_ptr<TTransport> getTransport(boost::shared_ptr<TTransport> trans) {
return boost::shared_ptr<TTransport>(new THttpServer(trans));
virtual stdcxx::shared_ptr<TTransport> getTransport(stdcxx::shared_ptr<TTransport> trans) {
return stdcxx::shared_ptr<TTransport>(new THttpServer(trans));
}
};
}

View file

@ -21,17 +21,17 @@
#include <thrift/transport/THttpTransport.h>
using std::string;
namespace apache {
namespace thrift {
namespace transport {
using namespace std;
// Yeah, yeah, hacky to put these here, I know.
const char* THttpTransport::CRLF = "\r\n";
const int THttpTransport::CRLF_LEN = 2;
THttpTransport::THttpTransport(boost::shared_ptr<TTransport> transport)
THttpTransport::THttpTransport(stdcxx::shared_ptr<TTransport> transport)
: transport_(transport),
origin_(""),
readHeaders_(true),
@ -84,8 +84,10 @@ uint32_t THttpTransport::readEnd() {
uint32_t THttpTransport::readMoreData() {
uint32_t size;
// Get more data!
refill();
if (httpPos_ == httpBufLen_) {
// Get more data!
refill();
}
if (readHeaders_) {
readHeaders();
@ -200,10 +202,11 @@ void THttpTransport::refill() {
uint32_t avail = httpBufSize_ - httpBufLen_;
if (avail <= (httpBufSize_ / 4)) {
httpBufSize_ *= 2;
httpBuf_ = (char*)std::realloc(httpBuf_, httpBufSize_ + 1);
if (httpBuf_ == NULL) {
char* tmpBuf = (char*)std::realloc(httpBuf_, httpBufSize_ + 1);
if (tmpBuf == NULL) {
throw std::bad_alloc();
}
httpBuf_ = tmpBuf;
}
// Read more data

View file

@ -36,7 +36,7 @@ namespace transport {
*/
class THttpTransport : public TVirtualTransport<THttpTransport> {
public:
THttpTransport(boost::shared_ptr<TTransport> transport);
THttpTransport(stdcxx::shared_ptr<TTransport> transport);
virtual ~THttpTransport();
@ -59,7 +59,7 @@ public:
virtual const std::string getOrigin();
protected:
boost::shared_ptr<TTransport> transport_;
stdcxx::shared_ptr<TTransport> transport_;
std::string origin_;
TMemoryBuffer writeBuffer_;

View file

@ -0,0 +1,58 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
#include <thrift/transport/TNonblockingSSLServerSocket.h>
#include <thrift/transport/TSSLSocket.h>
namespace apache {
namespace thrift {
namespace transport {
/**
* Nonblocking SSL server socket implementation.
*/
TNonblockingSSLServerSocket::TNonblockingSSLServerSocket(int port, stdcxx::shared_ptr<TSSLSocketFactory> factory)
: TNonblockingServerSocket(port), factory_(factory) {
factory_->server(true);
}
TNonblockingSSLServerSocket::TNonblockingSSLServerSocket(const std::string& address,
int port,
stdcxx::shared_ptr<TSSLSocketFactory> factory)
: TNonblockingServerSocket(address, port), factory_(factory) {
factory_->server(true);
}
TNonblockingSSLServerSocket::TNonblockingSSLServerSocket(int port,
int sendTimeout,
int recvTimeout,
stdcxx::shared_ptr<TSSLSocketFactory> factory)
: TNonblockingServerSocket(port, sendTimeout, recvTimeout), factory_(factory) {
factory_->server(true);
}
stdcxx::shared_ptr<TSocket> TNonblockingSSLServerSocket::createSocket(THRIFT_SOCKET client) {
stdcxx::shared_ptr<TSSLSocket> tSSLSocket;
tSSLSocket = factory_->createSocket(client);
tSSLSocket->setLibeventSafe();
return tSSLSocket;
}
}
}
}

View file

@ -0,0 +1,77 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
#ifndef _THRIFT_TRANSPORT_TNONBLOCKINGSSLSERVERSOCKET_H_
#define _THRIFT_TRANSPORT_TNONBLOCKINGSSLSERVERSOCKET_H_ 1
#include <thrift/transport/TNonblockingServerSocket.h>
#include <thrift/stdcxx.h>
namespace apache {
namespace thrift {
namespace transport {
class TSSLSocketFactory;
/**
* Nonblocking Server socket that accepts SSL connections.
*/
class TNonblockingSSLServerSocket : public TNonblockingServerSocket {
public:
/**
* Constructor. Binds to all interfaces.
*
* @param port Listening port
* @param factory SSL socket factory implementation
*/
TNonblockingSSLServerSocket(int port, stdcxx::shared_ptr<TSSLSocketFactory> factory);
/**
* Constructor. Binds to the specified address.
*
* @param address Address to bind to
* @param port Listening port
* @param factory SSL socket factory implementation
*/
TNonblockingSSLServerSocket(const std::string& address,
int port,
stdcxx::shared_ptr<TSSLSocketFactory> factory);
/**
* Constructor. Binds to all interfaces.
*
* @param port Listening port
* @param sendTimeout Socket send timeout
* @param recvTimeout Socket receive timeout
* @param factory SSL socket factory implementation
*/
TNonblockingSSLServerSocket(int port,
int sendTimeout,
int recvTimeout,
stdcxx::shared_ptr<TSSLSocketFactory> factory);
protected:
stdcxx::shared_ptr<TSocket> createSocket(THRIFT_SOCKET socket);
stdcxx::shared_ptr<TSSLSocketFactory> factory_;
};
}
}
}
#endif

View file

@ -0,0 +1,548 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
#include <thrift/thrift-config.h>
#include <cstring>
#include <stdexcept>
#include <sys/types.h>
#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif
#ifdef HAVE_SYS_UN_H
#include <sys/un.h>
#endif
#ifdef HAVE_SYS_POLL_H
#include <sys/poll.h>
#endif
#ifdef HAVE_NETINET_IN_H
#include <netinet/in.h>
#include <netinet/tcp.h>
#endif
#ifdef HAVE_NETDB_H
#include <netdb.h>
#endif
#include <fcntl.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <thrift/transport/TSocket.h>
#include <thrift/transport/TNonblockingServerSocket.h>
#include <thrift/transport/PlatformSocket.h>
#ifndef AF_LOCAL
#define AF_LOCAL AF_UNIX
#endif
#ifndef SOCKOPT_CAST_T
#ifndef _WIN32
#define SOCKOPT_CAST_T void
#else
#define SOCKOPT_CAST_T char
#endif // _WIN32
#endif
template <class T>
inline const SOCKOPT_CAST_T* const_cast_sockopt(const T* v) {
return reinterpret_cast<const SOCKOPT_CAST_T*>(v);
}
template <class T>
inline SOCKOPT_CAST_T* cast_sockopt(T* v) {
return reinterpret_cast<SOCKOPT_CAST_T*>(v);
}
namespace apache {
namespace thrift {
namespace transport {
using std::string;
using stdcxx::shared_ptr;
TNonblockingServerSocket::TNonblockingServerSocket(int port)
: port_(port),
listenPort_(port),
serverSocket_(THRIFT_INVALID_SOCKET),
acceptBacklog_(DEFAULT_BACKLOG),
sendTimeout_(0),
recvTimeout_(0),
retryLimit_(0),
retryDelay_(0),
tcpSendBuffer_(0),
tcpRecvBuffer_(0),
keepAlive_(false),
listening_(false) {
}
TNonblockingServerSocket::TNonblockingServerSocket(int port, int sendTimeout, int recvTimeout)
: port_(port),
listenPort_(port),
serverSocket_(THRIFT_INVALID_SOCKET),
acceptBacklog_(DEFAULT_BACKLOG),
sendTimeout_(sendTimeout),
recvTimeout_(recvTimeout),
retryLimit_(0),
retryDelay_(0),
tcpSendBuffer_(0),
tcpRecvBuffer_(0),
keepAlive_(false),
listening_(false) {
}
TNonblockingServerSocket::TNonblockingServerSocket(const string& address, int port)
: port_(port),
listenPort_(port),
address_(address),
serverSocket_(THRIFT_INVALID_SOCKET),
acceptBacklog_(DEFAULT_BACKLOG),
sendTimeout_(0),
recvTimeout_(0),
retryLimit_(0),
retryDelay_(0),
tcpSendBuffer_(0),
tcpRecvBuffer_(0),
keepAlive_(false),
listening_(false) {
}
TNonblockingServerSocket::TNonblockingServerSocket(const string& path)
: port_(0),
listenPort_(0),
path_(path),
serverSocket_(THRIFT_INVALID_SOCKET),
acceptBacklog_(DEFAULT_BACKLOG),
sendTimeout_(0),
recvTimeout_(0),
retryLimit_(0),
retryDelay_(0),
tcpSendBuffer_(0),
tcpRecvBuffer_(0),
keepAlive_(false),
listening_(false) {
}
TNonblockingServerSocket::~TNonblockingServerSocket() {
close();
}
void TNonblockingServerSocket::setSendTimeout(int sendTimeout) {
sendTimeout_ = sendTimeout;
}
void TNonblockingServerSocket::setRecvTimeout(int recvTimeout) {
recvTimeout_ = recvTimeout;
}
void TNonblockingServerSocket::setAcceptBacklog(int accBacklog) {
acceptBacklog_ = accBacklog;
}
void TNonblockingServerSocket::setRetryLimit(int retryLimit) {
retryLimit_ = retryLimit;
}
void TNonblockingServerSocket::setRetryDelay(int retryDelay) {
retryDelay_ = retryDelay;
}
void TNonblockingServerSocket::setTcpSendBuffer(int tcpSendBuffer) {
tcpSendBuffer_ = tcpSendBuffer;
}
void TNonblockingServerSocket::setTcpRecvBuffer(int tcpRecvBuffer) {
tcpRecvBuffer_ = tcpRecvBuffer;
}
void TNonblockingServerSocket::listen() {
listening_ = true;
#ifdef _WIN32
TWinsockSingleton::create();
#endif // _WIN32
// Validate port number
if (port_ < 0 || port_ > 0xFFFF) {
throw TTransportException(TTransportException::BAD_ARGS, "Specified port is invalid");
}
const struct addrinfo *res;
int error;
char port[sizeof("65535")];
THRIFT_SNPRINTF(port, sizeof(port), "%d", port_);
struct addrinfo hints;
std::memset(&hints, 0, sizeof(hints));
hints.ai_family = PF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_PASSIVE | AI_ADDRCONFIG;
// If address is not specified use wildcard address (NULL)
TGetAddrInfoWrapper info(address_.empty() ? NULL : &address_[0], port, &hints);
error = info.init();
if (error) {
GlobalOutput.printf("getaddrinfo %d: %s", error, THRIFT_GAI_STRERROR(error));
close();
throw TTransportException(TTransportException::NOT_OPEN,
"Could not resolve host for server socket.");
}
// Pick the ipv6 address first since ipv4 addresses can be mapped
// into ipv6 space.
for (res = info.res(); res; res = res->ai_next) {
if (res->ai_family == AF_INET6 || res->ai_next == NULL)
break;
}
if (!path_.empty()) {
serverSocket_ = socket(PF_UNIX, SOCK_STREAM, IPPROTO_IP);
} else if (res != NULL) {
serverSocket_ = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
}
if (serverSocket_ == THRIFT_INVALID_SOCKET) {
int errno_copy = THRIFT_GET_SOCKET_ERROR;
GlobalOutput.perror("TNonblockingServerSocket::listen() socket() ", errno_copy);
close();
throw TTransportException(TTransportException::NOT_OPEN,
"Could not create server socket.",
errno_copy);
}
// Set THRIFT_NO_SOCKET_CACHING to prevent 2MSL delay on accept
int one = 1;
if (-1 == setsockopt(serverSocket_,
SOL_SOCKET,
THRIFT_NO_SOCKET_CACHING,
cast_sockopt(&one),
sizeof(one))) {
// ignore errors coming out of this setsockopt on Windows. This is because
// SO_EXCLUSIVEADDRUSE requires admin privileges on WinXP, but we don't
// want to force servers to be an admin.
#ifndef _WIN32
int errno_copy = THRIFT_GET_SOCKET_ERROR;
GlobalOutput.perror("TNonblockingServerSocket::listen() setsockopt() THRIFT_NO_SOCKET_CACHING ",
errno_copy);
close();
throw TTransportException(TTransportException::NOT_OPEN,
"Could not set THRIFT_NO_SOCKET_CACHING",
errno_copy);
#endif
}
// Set TCP buffer sizes
if (tcpSendBuffer_ > 0) {
if (-1 == setsockopt(serverSocket_,
SOL_SOCKET,
SO_SNDBUF,
cast_sockopt(&tcpSendBuffer_),
sizeof(tcpSendBuffer_))) {
int errno_copy = THRIFT_GET_SOCKET_ERROR;
GlobalOutput.perror("TNonblockingServerSocket::listen() setsockopt() SO_SNDBUF ", errno_copy);
close();
throw TTransportException(TTransportException::NOT_OPEN,
"Could not set SO_SNDBUF",
errno_copy);
}
}
if (tcpRecvBuffer_ > 0) {
if (-1 == setsockopt(serverSocket_,
SOL_SOCKET,
SO_RCVBUF,
cast_sockopt(&tcpRecvBuffer_),
sizeof(tcpRecvBuffer_))) {
int errno_copy = THRIFT_GET_SOCKET_ERROR;
GlobalOutput.perror("TNonblockingServerSocket::listen() setsockopt() SO_RCVBUF ", errno_copy);
close();
throw TTransportException(TTransportException::NOT_OPEN,
"Could not set SO_RCVBUF",
errno_copy);
}
}
#ifdef IPV6_V6ONLY
if (res->ai_family == AF_INET6 && path_.empty()) {
int zero = 0;
if (-1 == setsockopt(serverSocket_,
IPPROTO_IPV6,
IPV6_V6ONLY,
cast_sockopt(&zero),
sizeof(zero))) {
GlobalOutput.perror("TNonblockingServerSocket::listen() IPV6_V6ONLY ", THRIFT_GET_SOCKET_ERROR);
}
}
#endif // #ifdef IPV6_V6ONLY
// Turn linger off, don't want to block on calls to close
struct linger ling = {0, 0};
if (-1 == setsockopt(serverSocket_, SOL_SOCKET, SO_LINGER, cast_sockopt(&ling), sizeof(ling))) {
int errno_copy = THRIFT_GET_SOCKET_ERROR;
GlobalOutput.perror("TNonblockingServerSocket::listen() setsockopt() SO_LINGER ", errno_copy);
close();
throw TTransportException(TTransportException::NOT_OPEN, "Could not set SO_LINGER", errno_copy);
}
// Keepalive to ensure full result flushing
if (-1 == setsockopt(serverSocket_, SOL_SOCKET, SO_KEEPALIVE, const_cast_sockopt(&one), sizeof(one))) {
int errno_copy = THRIFT_GET_SOCKET_ERROR;
GlobalOutput.perror("TNonblockingServerSocket::listen() setsockopt() SO_KEEPALIVE ", errno_copy);
close();
throw TTransportException(TTransportException::NOT_OPEN,
"Could not set TCP_NODELAY",
errno_copy);
}
// Set TCP nodelay if available, MAC OS X Hack
// See http://lists.danga.com/pipermail/memcached/2005-March/001240.html
#ifndef TCP_NOPUSH
// Unix Sockets do not need that
if (path_.empty()) {
// TCP Nodelay, speed over bandwidth
if (-1
== setsockopt(serverSocket_, IPPROTO_TCP, TCP_NODELAY, cast_sockopt(&one), sizeof(one))) {
int errno_copy = THRIFT_GET_SOCKET_ERROR;
GlobalOutput.perror("TNonblockingServerSocket::listen() setsockopt() TCP_NODELAY ", errno_copy);
close();
throw TTransportException(TTransportException::NOT_OPEN,
"Could not set TCP_NODELAY",
errno_copy);
}
}
#endif
// Set NONBLOCK on the accept socket
int flags = THRIFT_FCNTL(serverSocket_, THRIFT_F_GETFL, 0);
if (flags == -1) {
int errno_copy = THRIFT_GET_SOCKET_ERROR;
GlobalOutput.perror("TNonblockingServerSocket::listen() THRIFT_FCNTL() THRIFT_F_GETFL ", errno_copy);
close();
throw TTransportException(TTransportException::NOT_OPEN,
"THRIFT_FCNTL() THRIFT_F_GETFL failed",
errno_copy);
}
if (-1 == THRIFT_FCNTL(serverSocket_, THRIFT_F_SETFL, flags | THRIFT_O_NONBLOCK)) {
int errno_copy = THRIFT_GET_SOCKET_ERROR;
GlobalOutput.perror("TNonblockingServerSocket::listen() THRIFT_FCNTL() THRIFT_O_NONBLOCK ", errno_copy);
close();
throw TTransportException(TTransportException::NOT_OPEN,
"THRIFT_FCNTL() THRIFT_F_SETFL THRIFT_O_NONBLOCK failed",
errno_copy);
}
#ifdef TCP_LOW_MIN_RTO
if (TSocket::getUseLowMinRto()) {
if (-1 == setsockopt(s, IPPROTO_TCP, TCP_LOW_MIN_RTO, const_cast_sockopt(&one), sizeof(one))) {
int errno_copy = THRIFT_GET_SOCKET_ERROR;
GlobalOutput.perror("TNonblockingServerSocket::listen() setsockopt() TCP_LOW_MIN_RTO ", errno_copy);
close();
throw TTransportException(TTransportException::NOT_OPEN,
"Could not set TCP_NODELAY",
errno_copy);
}
}
#endif
// prepare the port information
// we may want to try to bind more than once, since THRIFT_NO_SOCKET_CACHING doesn't
// always seem to work. The client can configure the retry variables.
int retries = 0;
int errno_copy = 0;
if (!path_.empty()) {
#ifndef _WIN32
// Unix Domain Socket
size_t len = path_.size() + 1;
if (len > sizeof(((sockaddr_un*)NULL)->sun_path)) {
errno_copy = THRIFT_GET_SOCKET_ERROR;
GlobalOutput.perror("TSocket::listen() Unix Domain socket path too long", errno_copy);
throw TTransportException(TTransportException::NOT_OPEN,
"Unix Domain socket path too long",
errno_copy);
}
struct sockaddr_un address;
address.sun_family = AF_UNIX;
memcpy(address.sun_path, path_.c_str(), len);
socklen_t structlen = static_cast<socklen_t>(sizeof(address));
if (!address.sun_path[0]) { // abstract namespace socket
#ifdef __linux__
// sun_path is not null-terminated in this case and structlen determines its length
structlen -= sizeof(address.sun_path) - len;
#else
GlobalOutput.perror("TSocket::open() Abstract Namespace Domain sockets only supported on linux: ", -99);
throw TTransportException(TTransportException::NOT_OPEN,
" Abstract Namespace Domain socket path not supported");
#endif
}
do {
if (0 == ::bind(serverSocket_, (struct sockaddr*)&address, structlen)) {
break;
}
errno_copy = THRIFT_GET_SOCKET_ERROR;
// use short circuit evaluation here to only sleep if we need to
} while ((retries++ < retryLimit_) && (THRIFT_SLEEP_SEC(retryDelay_) == 0));
#else
GlobalOutput.perror("TSocket::open() Unix Domain socket path not supported on windows", -99);
throw TTransportException(TTransportException::NOT_OPEN,
" Unix Domain socket path not supported");
#endif
} else {
do {
if (0 == ::bind(serverSocket_, res->ai_addr, static_cast<int>(res->ai_addrlen))) {
break;
}
errno_copy = THRIFT_GET_SOCKET_ERROR;
// use short circuit evaluation here to only sleep if we need to
} while ((retries++ < retryLimit_) && (THRIFT_SLEEP_SEC(retryDelay_) == 0));
// retrieve bind info
if (port_ == 0 && retries <= retryLimit_) {
struct sockaddr_storage sa;
socklen_t len = sizeof(sa);
std::memset(&sa, 0, len);
if (::getsockname(serverSocket_, reinterpret_cast<struct sockaddr*>(&sa), &len) < 0) {
errno_copy = THRIFT_GET_SOCKET_ERROR;
GlobalOutput.perror("TNonblockingServerSocket::getPort() getsockname() ", errno_copy);
} else {
if (sa.ss_family == AF_INET6) {
const struct sockaddr_in6* sin = reinterpret_cast<const struct sockaddr_in6*>(&sa);
listenPort_ = ntohs(sin->sin6_port);
} else {
const struct sockaddr_in* sin = reinterpret_cast<const struct sockaddr_in*>(&sa);
listenPort_ = ntohs(sin->sin_port);
}
}
}
}
// throw an error if we failed to bind properly
if (retries > retryLimit_) {
char errbuf[1024];
if (!path_.empty()) {
THRIFT_SNPRINTF(errbuf, sizeof(errbuf), "TNonblockingServerSocket::listen() PATH %s", path_.c_str());
} else {
THRIFT_SNPRINTF(errbuf, sizeof(errbuf), "TNonblockingServerSocket::listen() BIND %d", port_);
}
GlobalOutput(errbuf);
close();
throw TTransportException(TTransportException::NOT_OPEN,
"Could not bind",
errno_copy);
}
if (listenCallback_)
listenCallback_(serverSocket_);
// Call listen
if (-1 == ::listen(serverSocket_, acceptBacklog_)) {
errno_copy = THRIFT_GET_SOCKET_ERROR;
GlobalOutput.perror("TNonblockingServerSocket::listen() listen() ", errno_copy);
close();
throw TTransportException(TTransportException::NOT_OPEN, "Could not listen", errno_copy);
}
// The socket is now listening!
}
int TNonblockingServerSocket::getPort() {
return port_;
}
int TNonblockingServerSocket::getListenPort() {
return listenPort_;
}
shared_ptr<TSocket> TNonblockingServerSocket::acceptImpl() {
if (serverSocket_ == THRIFT_INVALID_SOCKET) {
throw TTransportException(TTransportException::NOT_OPEN, "TNonblockingServerSocket not listening");
}
struct sockaddr_storage clientAddress;
int size = sizeof(clientAddress);
THRIFT_SOCKET clientSocket
= ::accept(serverSocket_, (struct sockaddr*)&clientAddress, (socklen_t*)&size);
if (clientSocket == THRIFT_INVALID_SOCKET) {
int errno_copy = THRIFT_GET_SOCKET_ERROR;
GlobalOutput.perror("TNonblockingServerSocket::acceptImpl() ::accept() ", errno_copy);
throw TTransportException(TTransportException::UNKNOWN, "accept()", errno_copy);
}
// Explicitly set this socket to NONBLOCK mode
int flags = THRIFT_FCNTL(clientSocket, THRIFT_F_GETFL, 0);
if (flags == -1) {
int errno_copy = THRIFT_GET_SOCKET_ERROR;
::THRIFT_CLOSESOCKET(clientSocket);
GlobalOutput.perror("TNonblockingServerSocket::acceptImpl() THRIFT_FCNTL() THRIFT_F_GETFL ", errno_copy);
throw TTransportException(TTransportException::UNKNOWN,
"THRIFT_FCNTL(THRIFT_F_GETFL)",
errno_copy);
}
if (-1 == THRIFT_FCNTL(clientSocket, THRIFT_F_SETFL, flags | THRIFT_O_NONBLOCK)) {
int errno_copy = THRIFT_GET_SOCKET_ERROR;
::THRIFT_CLOSESOCKET(clientSocket);
GlobalOutput
.perror("TNonblockingServerSocket::acceptImpl() THRIFT_FCNTL() THRIFT_F_SETFL ~THRIFT_O_NONBLOCK ",
errno_copy);
throw TTransportException(TTransportException::UNKNOWN,
"THRIFT_FCNTL(THRIFT_F_SETFL)",
errno_copy);
}
shared_ptr<TSocket> client = createSocket(clientSocket);
if (sendTimeout_ > 0) {
client->setSendTimeout(sendTimeout_);
}
if (recvTimeout_ > 0) {
client->setRecvTimeout(recvTimeout_);
}
if (keepAlive_) {
client->setKeepAlive(keepAlive_);
}
client->setCachedAddress((sockaddr*)&clientAddress, size);
if (acceptCallback_)
acceptCallback_(clientSocket);
return client;
}
shared_ptr<TSocket> TNonblockingServerSocket::createSocket(THRIFT_SOCKET clientSocket) {
return shared_ptr<TSocket>(new TSocket(clientSocket));
}
void TNonblockingServerSocket::close() {
if (serverSocket_ != THRIFT_INVALID_SOCKET) {
shutdown(serverSocket_, THRIFT_SHUT_RDWR);
::THRIFT_CLOSESOCKET(serverSocket_);
}
serverSocket_ = THRIFT_INVALID_SOCKET;
listening_ = false;
}
}
}
} // apache::thrift::transport

View file

@ -0,0 +1,137 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
#ifndef _THRIFT_TRANSPORT_TNONBLOCKINGSERVERSOCKET_H_
#define _THRIFT_TRANSPORT_TNONBLOCKINGSERVERSOCKET_H_ 1
#include <thrift/transport/TNonblockingServerTransport.h>
#include <thrift/transport/PlatformSocket.h>
#include <thrift/stdcxx.h>
namespace apache {
namespace thrift {
namespace transport {
class TSocket;
/**
* Nonblocking Server socket implementation of TNonblockingServerTransport. Wrapper around a unix
* socket listen and accept calls.
*
*/
class TNonblockingServerSocket : public TNonblockingServerTransport {
public:
typedef apache::thrift::stdcxx::function<void(THRIFT_SOCKET fd)> socket_func_t;
const static int DEFAULT_BACKLOG = 1024;
/**
* Constructor.
*
* @param port Port number to bind to
*/
TNonblockingServerSocket(int port);
/**
* Constructor.
*
* @param port Port number to bind to
* @param sendTimeout Socket send timeout
* @param recvTimeout Socket receive timeout
*/
TNonblockingServerSocket(int port, int sendTimeout, int recvTimeout);
/**
* Constructor.
*
* @param address Address to bind to
* @param port Port number to bind to
*/
TNonblockingServerSocket(const std::string& address, int port);
/**
* Constructor used for unix sockets.
*
* @param path Pathname for unix socket.
*/
TNonblockingServerSocket(const std::string& path);
virtual ~TNonblockingServerSocket();
void setSendTimeout(int sendTimeout);
void setRecvTimeout(int recvTimeout);
void setAcceptBacklog(int accBacklog);
void setRetryLimit(int retryLimit);
void setRetryDelay(int retryDelay);
void setKeepAlive(bool keepAlive) { keepAlive_ = keepAlive; }
void setTcpSendBuffer(int tcpSendBuffer);
void setTcpRecvBuffer(int tcpRecvBuffer);
// listenCallback gets called just before listen, and after all Thrift
// setsockopt calls have been made. If you have custom setsockopt
// things that need to happen on the listening socket, this is the place to do it.
void setListenCallback(const socket_func_t& listenCallback) { listenCallback_ = listenCallback; }
// acceptCallback gets called after each accept call, on the newly created socket.
// It is called after all Thrift setsockopt calls have been made. If you have
// custom setsockopt things that need to happen on the accepted
// socket, this is the place to do it.
void setAcceptCallback(const socket_func_t& acceptCallback) { acceptCallback_ = acceptCallback; }
THRIFT_SOCKET getSocketFD() { return serverSocket_; }
int getPort();
int getListenPort();
void listen();
void close();
protected:
apache::thrift::stdcxx::shared_ptr<TSocket> acceptImpl();
virtual apache::thrift::stdcxx::shared_ptr<TSocket> createSocket(THRIFT_SOCKET client);
private:
int port_;
int listenPort_;
std::string address_;
std::string path_;
THRIFT_SOCKET serverSocket_;
int acceptBacklog_;
int sendTimeout_;
int recvTimeout_;
int retryLimit_;
int retryDelay_;
int tcpSendBuffer_;
int tcpRecvBuffer_;
bool keepAlive_;
bool listening_;
socket_func_t listenCallback_;
socket_func_t acceptCallback_;
};
}
}
} // apache::thrift::transport
#endif // #ifndef _THRIFT_TRANSPORT_TNONBLOCKINGSERVERSOCKET_H_

View file

@ -0,0 +1,101 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
#ifndef _THRIFT_TRANSPORT_TNONBLOCKINGSERVERTRANSPORT_H_
#define _THRIFT_TRANSPORT_TNONBLOCKINGSERVERTRANSPORT_H_ 1
#include <thrift/transport/TSocket.h>
#include <thrift/transport/TTransportException.h>
#include <thrift/stdcxx.h>
namespace apache {
namespace thrift {
namespace transport {
/**
* Server transport framework. A server needs to have some facility for
* creating base transports to read/write from. The server is expected
* to keep track of TTransport children that it creates for purposes of
* controlling their lifetime.
*/
class TNonblockingServerTransport {
public:
virtual ~TNonblockingServerTransport() {}
/**
* Starts the server transport listening for new connections. Prior to this
* call most transports will not return anything when accept is called.
*
* @throws TTransportException if we were unable to listen
*/
virtual void listen() {}
/**
* Gets a new dynamically allocated transport object and passes it to the
* caller. Note that it is the explicit duty of the caller to free the
* allocated object. The returned TTransport object must always be in the
* opened state. NULL should never be returned, instead an Exception should
* always be thrown.
*
* @return A new TTransport object
* @throws TTransportException if there is an error
*/
stdcxx::shared_ptr<TSocket> accept() {
stdcxx::shared_ptr<TSocket> result = acceptImpl();
if (!result) {
throw TTransportException("accept() may not return NULL");
}
return result;
}
/**
* Utility method
*
* @return server socket file descriptor
* @throw TTransportException If an error occurs
*/
virtual THRIFT_SOCKET getSocketFD() = 0;
virtual int getPort() = 0;
virtual int getListenPort() = 0;
/**
* Closes this transport such that future calls to accept will do nothing.
*/
virtual void close() = 0;
protected:
TNonblockingServerTransport() {}
/**
* Subclasses should implement this function for accept.
*
* @return A newly allocated TTransport object
* @throw TTransportException If an error occurs
*/
virtual stdcxx::shared_ptr<TSocket> acceptImpl() = 0;
};
}
}
} // apache::thrift::transport
#endif // #ifndef _THRIFT_TRANSPORT_TNONBLOCKINGSERVERTRANSPORT_H_

View file

@ -28,8 +28,6 @@ namespace apache {
namespace thrift {
namespace transport {
using namespace std;
/**
* TPipe implementation.
*/
@ -160,7 +158,8 @@ uint32_t TWaitableNamedPipeImpl::read(uint8_t* buf, uint32_t len) {
end_unread_idx_ = endAsyncRead();
}
uint32_t bytes_to_copy = (std::min)(len, end_unread_idx_ - begin_unread_idx_);
uint32_t __idxsize = end_unread_idx_ - begin_unread_idx_;
uint32_t bytes_to_copy = (len < __idxsize) ? len : __idxsize;
memcpy(buf, &buffer_[begin_unread_idx_], bytes_to_copy);
begin_unread_idx_ += bytes_to_copy;
if (begin_unread_idx_ != end_unread_idx_) {
@ -341,12 +340,12 @@ void pipe_write(HANDLE pipe, const uint8_t* buf, uint32_t len) {
// Accessors
//---------------------------------------------------------
string TPipe::getPipename() {
std::string TPipe::getPipename() {
return pipename_;
}
void TPipe::setPipename(const std::string& pipename) {
if (pipename.find("\\\\") == -1)
if (pipename.find("\\\\") == std::string::npos)
pipename_ = "\\\\.\\pipe\\" + pipename;
else
pipename_ = pipename;

View file

@ -95,7 +95,7 @@ public:
HANDLE getNativeWaitHandle();
private:
boost::shared_ptr<TPipeImpl> impl_;
stdcxx::shared_ptr<TPipeImpl> impl_;
std::string pipename_;

View file

@ -22,7 +22,7 @@
#include <thrift/transport/TPipe.h>
#include <thrift/transport/TPipeServer.h>
#include <boost/shared_ptr.hpp>
#include <thrift/stdcxx.h>
#include <boost/noncopyable.hpp>
#ifdef _WIN32
@ -37,15 +37,14 @@ namespace transport {
#ifdef _WIN32
using namespace std;
using boost::shared_ptr;
using stdcxx::shared_ptr;
class TPipeServerImpl : boost::noncopyable {
public:
TPipeServerImpl() {}
virtual ~TPipeServerImpl() {}
virtual void interrupt() = 0;
virtual boost::shared_ptr<TTransport> acceptImpl() = 0;
virtual stdcxx::shared_ptr<TTransport> acceptImpl() = 0;
virtual HANDLE getPipeHandle() = 0;
virtual HANDLE getWrtPipeHandle() = 0;
@ -76,7 +75,7 @@ public:
virtual void interrupt() {} // not currently implemented
virtual boost::shared_ptr<TTransport> acceptImpl();
virtual stdcxx::shared_ptr<TTransport> acceptImpl();
virtual HANDLE getPipeHandle() { return PipeR_.h; }
virtual HANDLE getWrtPipeHandle() { return PipeW_.h; }
@ -118,7 +117,7 @@ public:
}
}
virtual boost::shared_ptr<TTransport> acceptImpl();
virtual stdcxx::shared_ptr<TTransport> acceptImpl();
virtual HANDLE getPipeHandle() { return Pipe_.h; }
virtual HANDLE getWrtPipeHandle() { return INVALID_HANDLE_VALUE; }
@ -142,7 +141,7 @@ private:
TCriticalSection pipe_protect_;
// only read or write these variables underneath a locked pipe_protect_
boost::shared_ptr<TPipe> cached_client_;
stdcxx::shared_ptr<TPipe> cached_client_;
TAutoHandle Pipe_;
};
@ -297,6 +296,10 @@ shared_ptr<TTransport> TNamedPipeServer::acceptImpl() {
// if we got here, then we are in an error / shutdown case
DWORD gle = GetLastError(); // save error before doing cleanup
GlobalOutput.perror("TPipeServer ConnectNamedPipe GLE=", gle);
if(gle == ERROR_OPERATION_ABORTED) {
TAutoCrit lock(pipe_protect_); // Needed to insure concurrent thread to be out of interrupt.
throw TTransportException(TTransportException::INTERRUPTED, "TPipeServer: server interupted");
}
throw TTransportException(TTransportException::NOT_OPEN, "TPipeServer: client connection failed");
}
@ -361,7 +364,7 @@ bool TNamedPipeServer::createNamedPipe(const TAutoCrit & /*lockProof*/) {
GlobalOutput.perror("TPipeServer::TCreateNamedPipe() GLE=", lastError);
throw TTransportException(TTransportException::NOT_OPEN,
"TCreateNamedPipe() failed",
lastError);
lastError);
return false;
}
@ -404,12 +407,12 @@ bool TAnonPipeServer::createAnonPipe() {
//---------------------------------------------------------
// Accessors
//---------------------------------------------------------
string TPipeServer::getPipename() {
std::string TPipeServer::getPipename() {
return pipename_;
}
void TPipeServer::setPipename(const std::string& pipename) {
if (pipename.find("\\\\") == -1)
if (pipename.find("\\\\") == std::string::npos)
pipename_ = "\\\\.\\pipe\\" + pipename;
else
pipename_ = pipename;

View file

@ -21,7 +21,7 @@
#define _THRIFT_TRANSPORT_TSERVERWINPIPES_H_ 1
#include <thrift/transport/TServerTransport.h>
#include <boost/shared_ptr.hpp>
#include <thrift/stdcxx.h>
#ifndef _WIN32
#include <thrift/transport/TServerSocket.h>
#endif
@ -82,10 +82,10 @@ public:
HANDLE getNativeWaitHandle();
protected:
virtual boost::shared_ptr<TTransport> acceptImpl();
virtual stdcxx::shared_ptr<TTransport> acceptImpl();
private:
boost::shared_ptr<TPipeServerImpl> impl_;
stdcxx::shared_ptr<TPipeServerImpl> impl_;
std::string pipename_;
uint32_t bufsize_;

View file

@ -27,14 +27,14 @@ namespace transport {
/**
* SSL server socket implementation.
*/
TSSLServerSocket::TSSLServerSocket(int port, boost::shared_ptr<TSSLSocketFactory> factory)
TSSLServerSocket::TSSLServerSocket(int port, stdcxx::shared_ptr<TSSLSocketFactory> factory)
: TServerSocket(port), factory_(factory) {
factory_->server(true);
}
TSSLServerSocket::TSSLServerSocket(const std::string& address,
int port,
boost::shared_ptr<TSSLSocketFactory> factory)
stdcxx::shared_ptr<TSSLSocketFactory> factory)
: TServerSocket(address, port), factory_(factory) {
factory_->server(true);
}
@ -42,12 +42,12 @@ TSSLServerSocket::TSSLServerSocket(const std::string& address,
TSSLServerSocket::TSSLServerSocket(int port,
int sendTimeout,
int recvTimeout,
boost::shared_ptr<TSSLSocketFactory> factory)
stdcxx::shared_ptr<TSSLSocketFactory> factory)
: TServerSocket(port, sendTimeout, recvTimeout), factory_(factory) {
factory_->server(true);
}
boost::shared_ptr<TSocket> TSSLServerSocket::createSocket(THRIFT_SOCKET client) {
stdcxx::shared_ptr<TSocket> TSSLServerSocket::createSocket(THRIFT_SOCKET client) {
if (interruptableChildren_) {
return factory_->createSocket(client, pChildInterruptSockReader_);

View file

@ -20,7 +20,7 @@
#ifndef _THRIFT_TRANSPORT_TSSLSERVERSOCKET_H_
#define _THRIFT_TRANSPORT_TSSLSERVERSOCKET_H_ 1
#include <boost/shared_ptr.hpp>
#include <thrift/stdcxx.h>
#include <thrift/transport/TServerSocket.h>
namespace apache {
@ -40,7 +40,7 @@ public:
* @param port Listening port
* @param factory SSL socket factory implementation
*/
TSSLServerSocket(int port, boost::shared_ptr<TSSLSocketFactory> factory);
TSSLServerSocket(int port, stdcxx::shared_ptr<TSSLSocketFactory> factory);
/**
* Constructor. Binds to the specified address.
@ -51,7 +51,7 @@ public:
*/
TSSLServerSocket(const std::string& address,
int port,
boost::shared_ptr<TSSLSocketFactory> factory);
stdcxx::shared_ptr<TSSLSocketFactory> factory);
/**
* Constructor. Binds to all interfaces.
@ -64,11 +64,11 @@ public:
TSSLServerSocket(int port,
int sendTimeout,
int recvTimeout,
boost::shared_ptr<TSSLSocketFactory> factory);
stdcxx::shared_ptr<TSSLSocketFactory> factory);
protected:
boost::shared_ptr<TSocket> createSocket(THRIFT_SOCKET socket);
boost::shared_ptr<TSSLSocketFactory> factory_;
stdcxx::shared_ptr<TSocket> createSocket(THRIFT_SOCKET socket);
stdcxx::shared_ptr<TSSLSocketFactory> factory_;
};
}
}

View file

@ -21,6 +21,7 @@
#include <errno.h>
#include <string>
#include <cstring>
#ifdef HAVE_ARPA_INET_H
#include <arpa/inet.h>
#endif
@ -35,9 +36,14 @@
#include <fcntl.h>
#endif
#define OPENSSL_VERSION_NO_THREAD_ID_BEFORE 0x10000000L
#define OPENSSL_ENGINE_CLEANUP_REQUIRED_BEFORE 0x10100000L
#include <boost/lexical_cast.hpp>
#include <boost/shared_array.hpp>
#include <openssl/opensslv.h>
#if (OPENSSL_VERSION_NUMBER < OPENSSL_ENGINE_CLEANUP_REQUIRED_BEFORE)
#include <openssl/engine.h>
#endif
#include <openssl/err.h>
#include <openssl/rand.h>
#include <openssl/ssl.h>
@ -45,11 +51,10 @@
#include <thrift/concurrency/Mutex.h>
#include <thrift/transport/TSSLSocket.h>
#include <thrift/transport/PlatformSocket.h>
#include <thrift/TToString.h>
#define OPENSSL_VERSION_NO_THREAD_ID 0x10000000L
using namespace std;
using namespace apache::thrift::concurrency;
using std::string;
struct CRYPTO_dynlock_value {
Mutex mutex;
@ -66,13 +71,16 @@ static boost::shared_array<Mutex> mutexes;
static void callbackLocking(int mode, int n, const char*, int) {
if (mode & CRYPTO_LOCK) {
// assertion of (px != 0) here typically means that a TSSLSocket's lifetime
// exceeded the lifetime of the TSSLSocketFactory that created it, and the
// TSSLSocketFactory already ran cleanupOpenSSL(), which deleted "mutexes".
mutexes[n].lock();
} else {
mutexes[n].unlock();
}
}
#if (OPENSSL_VERSION_NUMBER < OPENSSL_VERSION_NO_THREAD_ID)
#if (OPENSSL_VERSION_NUMBER < OPENSSL_VERSION_NO_THREAD_ID_BEFORE)
static unsigned long callbackThreadID() {
#ifdef _WIN32
return (unsigned long)GetCurrentThreadId();
@ -107,6 +115,8 @@ void initializeOpenSSL() {
openSSLInitialized = true;
SSL_library_init();
SSL_load_error_strings();
ERR_load_crypto_strings();
// static locking
// newer versions of OpenSSL changed CRYPTO_num_locks - see THRIFT-3878
#ifdef CRYPTO_num_locks
@ -114,15 +124,13 @@ void initializeOpenSSL() {
#else
mutexes = boost::shared_array<Mutex>(new Mutex[ ::CRYPTO_num_locks()]);
#endif
if (mutexes == NULL) {
throw TTransportException(TTransportException::INTERNAL_ERROR,
"initializeOpenSSL() failed, "
"out of memory while creating mutex array");
}
#if (OPENSSL_VERSION_NUMBER < OPENSSL_VERSION_NO_THREAD_ID)
#if (OPENSSL_VERSION_NUMBER < OPENSSL_VERSION_NO_THREAD_ID_BEFORE)
CRYPTO_set_id_callback(callbackThreadID);
#endif
CRYPTO_set_locking_callback(callbackLocking);
// dynamic locking
CRYPTO_set_dynlock_create_callback(dyn_create);
CRYPTO_set_dynlock_lock_callback(dyn_lock);
@ -134,21 +142,22 @@ void cleanupOpenSSL() {
return;
}
openSSLInitialized = false;
#if (OPENSSL_VERSION_NUMBER < OPENSSL_VERSION_NO_THREAD_ID)
CRYPTO_set_id_callback(NULL);
// https://wiki.openssl.org/index.php/Library_Initialization#Cleanup
// we purposefully do NOT call FIPS_mode_set(0) and leave it up to the enclosing application to manage FIPS entirely
#if (OPENSSL_VERSION_NUMBER < OPENSSL_ENGINE_CLEANUP_REQUIRED_BEFORE)
ENGINE_cleanup(); // https://www.openssl.org/docs/man1.1.0/crypto/ENGINE_cleanup.html - cleanup call is needed before 1.1.0
#endif
CRYPTO_set_locking_callback(NULL);
CRYPTO_set_dynlock_create_callback(NULL);
CRYPTO_set_dynlock_lock_callback(NULL);
CRYPTO_set_dynlock_destroy_callback(NULL);
ERR_free_strings();
CONF_modules_unload(1);
EVP_cleanup();
CRYPTO_cleanup_all_ex_data();
ERR_remove_state(0);
ERR_free_strings();
mutexes.reset();
}
static void buildErrors(string& message, int error = 0);
static void buildErrors(string& message, int errno_copy = 0, int sslerrno = 0);
static bool matchName(const char* host, const char* pattern, int size);
static char uppercase(char c);
@ -204,29 +213,35 @@ SSL* SSLContext::createSSL() {
}
// TSSLSocket implementation
TSSLSocket::TSSLSocket(boost::shared_ptr<SSLContext> ctx)
TSSLSocket::TSSLSocket(stdcxx::shared_ptr<SSLContext> ctx)
: TSocket(), server_(false), ssl_(NULL), ctx_(ctx) {
init();
}
TSSLSocket::TSSLSocket(boost::shared_ptr<SSLContext> ctx, boost::shared_ptr<THRIFT_SOCKET> interruptListener)
TSSLSocket::TSSLSocket(stdcxx::shared_ptr<SSLContext> ctx, stdcxx::shared_ptr<THRIFT_SOCKET> interruptListener)
: TSocket(), server_(false), ssl_(NULL), ctx_(ctx) {
init();
interruptListener_ = interruptListener;
}
TSSLSocket::TSSLSocket(boost::shared_ptr<SSLContext> ctx, THRIFT_SOCKET socket)
TSSLSocket::TSSLSocket(stdcxx::shared_ptr<SSLContext> ctx, THRIFT_SOCKET socket)
: TSocket(socket), server_(false), ssl_(NULL), ctx_(ctx) {
init();
}
TSSLSocket::TSSLSocket(boost::shared_ptr<SSLContext> ctx, THRIFT_SOCKET socket, boost::shared_ptr<THRIFT_SOCKET> interruptListener)
TSSLSocket::TSSLSocket(stdcxx::shared_ptr<SSLContext> ctx, THRIFT_SOCKET socket, stdcxx::shared_ptr<THRIFT_SOCKET> interruptListener)
: TSocket(socket, interruptListener), server_(false), ssl_(NULL), ctx_(ctx) {
init();
}
TSSLSocket::TSSLSocket(boost::shared_ptr<SSLContext> ctx, string host, int port)
TSSLSocket::TSSLSocket(stdcxx::shared_ptr<SSLContext> ctx, string host, int port)
: TSocket(host, port), server_(false), ssl_(NULL), ctx_(ctx) {
init();
}
TSSLSocket::TSSLSocket(boost::shared_ptr<SSLContext> ctx, string host, int port, boost::shared_ptr<THRIFT_SOCKET> interruptListener)
TSSLSocket::TSSLSocket(stdcxx::shared_ptr<SSLContext> ctx, string host, int port, stdcxx::shared_ptr<THRIFT_SOCKET> interruptListener)
: TSocket(host, port), server_(false), ssl_(NULL), ctx_(ctx) {
init();
interruptListener_ = interruptListener;
}
@ -234,6 +249,23 @@ TSSLSocket::~TSSLSocket() {
close();
}
bool TSSLSocket::hasPendingDataToRead() {
if (!isOpen()) {
return false;
}
initializeHandshake();
if (!checkHandshake())
throw TSSLException("TSSLSocket::hasPendingDataToRead: Handshake is not completed");
// data may be available in SSL buffers (note: SSL_pending does not have a failure mode)
return SSL_pending(ssl_) > 0 || TSocket::hasPendingDataToRead();
}
void TSSLSocket::init() {
handshakeCompleted_ = false;
readRetryCount_ = 0;
eventSafe_ = false;
}
bool TSSLSocket::isOpen() {
if (ssl_ == NULL || !TSocket::isOpen()) {
return false;
@ -248,11 +280,16 @@ bool TSSLSocket::isOpen() {
return true;
}
/*
* Note: This method is not libevent safe.
*/
bool TSSLSocket::peek() {
if (!isOpen()) {
return false;
}
checkHandshake();
initializeHandshake();
if (!checkHandshake())
throw TSSLException("SSL_peek: Handshake is not completed");
int rc;
uint8_t byte;
do {
@ -267,14 +304,16 @@ bool TSSLSocket::peek() {
&& (errno_copy != THRIFT_EAGAIN)) {
break;
}
// fallthrough
case SSL_ERROR_WANT_READ:
case SSL_ERROR_WANT_WRITE:
waitForEvent(error == SSL_ERROR_WANT_READ);
continue;
// in the case of SSL_ERROR_SYSCALL we want to wait for an read event again
waitForEvent(error != SSL_ERROR_WANT_WRITE);
continue;
default:;// do nothing
}
string errors;
buildErrors(errors, errno_copy);
buildErrors(errors, errno_copy, error);
throw TSSLException("SSL_peek: " + errors);
} else if (rc == 0) {
ERR_clear_error();
@ -291,24 +330,31 @@ void TSSLSocket::open() {
TSocket::open();
}
/*
* Note: This method is not libevent safe.
*/
void TSSLSocket::close() {
if (ssl_ != NULL) {
try {
int rc;
int errno_copy = 0;
int error = 0;
do {
rc = SSL_shutdown(ssl_);
if (rc <= 0) {
int errno_copy = THRIFT_GET_SOCKET_ERROR;
int error = SSL_get_error(ssl_, rc);
errno_copy = THRIFT_GET_SOCKET_ERROR;
error = SSL_get_error(ssl_, rc);
switch (error) {
case SSL_ERROR_SYSCALL:
if ((errno_copy != THRIFT_EINTR)
&& (errno_copy != THRIFT_EAGAIN)) {
break;
}
// fallthrough
case SSL_ERROR_WANT_READ:
case SSL_ERROR_WANT_WRITE:
// in the case of SSL_ERROR_SYSCALL we want to wait for an write/read event again
waitForEvent(error == SSL_ERROR_WANT_READ);
rc = 2;
default:;// do nothing
@ -317,9 +363,8 @@ void TSSLSocket::close() {
} while (rc == 2);
if (rc < 0) {
int errno_copy = THRIFT_GET_SOCKET_ERROR;
string errors;
buildErrors(errors, errno_copy);
buildErrors(errors, errno_copy, error);
GlobalOutput(("SSL_shutdown: " + errors).c_str());
}
} catch (TTransportException& te) {
@ -331,55 +376,99 @@ void TSSLSocket::close() {
}
SSL_free(ssl_);
ssl_ = NULL;
handshakeCompleted_ = false;
ERR_remove_state(0);
}
TSocket::close();
}
/*
* Returns number of bytes read in SSL Socket.
* If eventSafe is set, and it may returns 0 bytes then read method
* needs to be called again until it is successfull or it throws
* exception incase of failure.
*/
uint32_t TSSLSocket::read(uint8_t* buf, uint32_t len) {
checkHandshake();
initializeHandshake();
if (!checkHandshake())
throw TTransportException(TTransportException::UNKNOWN, "retry again");
int32_t bytes = 0;
for (int32_t retries = 0; retries < maxRecvRetries_; retries++) {
ERR_clear_error();
while (readRetryCount_ < maxRecvRetries_) {
bytes = SSL_read(ssl_, buf, len);
if (bytes >= 0)
break;
int32_t errno_copy = THRIFT_GET_SOCKET_ERROR;
int32_t error = SSL_get_error(ssl_, bytes);
readRetryCount_++;
if (error == SSL_ERROR_NONE) {
readRetryCount_ = 0;
break;
}
unsigned int waitEventReturn;
bool breakout = false;
switch (error) {
case SSL_ERROR_ZERO_RETURN:
throw TTransportException(TTransportException::END_OF_FILE, "client disconnected");
case SSL_ERROR_SYSCALL:
if (errno_copy == 0 && ERR_peek_error() == 0) {
breakout = true;
break;
}
if ((errno_copy != THRIFT_EINTR)
&& (errno_copy != THRIFT_EAGAIN)) {
break;
}
if (retries++ >= maxRecvRetries_) {
if (readRetryCount_ >= maxRecvRetries_) {
// THRIFT_EINTR needs to be handled manually and we can tolerate
// a certain number
break;
}
// fallthrough
case SSL_ERROR_WANT_READ:
case SSL_ERROR_WANT_WRITE:
if (waitForEvent(error == SSL_ERROR_WANT_READ) == TSSL_EINTR ) {
if (isLibeventSafe()) {
if (readRetryCount_ < maxRecvRetries_) {
// THRIFT_EINTR needs to be handled manually and we can tolerate
// a certain number
throw TTransportException(TTransportException::UNKNOWN, "retry again");
}
throw TTransportException(TTransportException::INTERNAL_ERROR, "too much recv retries");
}
// in the case of SSL_ERROR_SYSCALL we want to wait for an read event again
else if ((waitEventReturn = waitForEvent(error != SSL_ERROR_WANT_WRITE)) == TSSL_EINTR ) {
// repeat operation
if (retries++ < maxRecvRetries_) {
if (readRetryCount_ < maxRecvRetries_) {
// THRIFT_EINTR needs to be handled manually and we can tolerate
// a certain number
continue;
}
throw TTransportException(TTransportException::INTERNAL_ERROR, "too much recv retries");
}
continue;
else if (waitEventReturn == TSSL_DATA) {
// in case of SSL and huge thrift packets, there may be a number of
// socket operations, before any data becomes available by SSL_read().
// Therefore the number of retries should not be increased and
// the operation should be repeated.
readRetryCount_--;
continue;
}
throw TTransportException(TTransportException::INTERNAL_ERROR, "unkown waitForEvent return value");
default:;// do nothing
}
if (breakout) {
break;
}
string errors;
buildErrors(errors, errno_copy);
buildErrors(errors, errno_copy, error);
throw TSSLException("SSL_read: " + errors);
}
return bytes;
}
void TSSLSocket::write(const uint8_t* buf, uint32_t len) {
checkHandshake();
initializeHandshake();
if (!checkHandshake())
return;
// loop in case SSL_MODE_ENABLE_PARTIAL_WRITE is set in SSL_CTX.
uint32_t written = 0;
while (written < len) {
@ -394,26 +483,81 @@ void TSSLSocket::write(const uint8_t* buf, uint32_t len) {
&& (errno_copy != THRIFT_EAGAIN)) {
break;
}
// fallthrough
case SSL_ERROR_WANT_READ:
case SSL_ERROR_WANT_WRITE:
waitForEvent(error == SSL_ERROR_WANT_READ);
continue;
if (isLibeventSafe()) {
return;
}
else {
// in the case of SSL_ERROR_SYSCALL we want to wait for an write event again
waitForEvent(error == SSL_ERROR_WANT_READ);
continue;
}
default:;// do nothing
}
string errors;
buildErrors(errors, errno_copy);
buildErrors(errors, errno_copy, error);
throw TSSLException("SSL_write: " + errors);
}
written += bytes;
}
}
/*
* Returns number of bytes written in SSL Socket.
* If eventSafe is set, and it may returns 0 bytes then write method
* needs to be called again until it is successfull or it throws
* exception incase of failure.
*/
uint32_t TSSLSocket::write_partial(const uint8_t* buf, uint32_t len) {
initializeHandshake();
if (!checkHandshake())
return 0;
// loop in case SSL_MODE_ENABLE_PARTIAL_WRITE is set in SSL_CTX.
uint32_t written = 0;
while (written < len) {
ERR_clear_error();
int32_t bytes = SSL_write(ssl_, &buf[written], len - written);
if (bytes <= 0) {
int errno_copy = THRIFT_GET_SOCKET_ERROR;
int error = SSL_get_error(ssl_, bytes);
switch (error) {
case SSL_ERROR_SYSCALL:
if ((errno_copy != THRIFT_EINTR)
&& (errno_copy != THRIFT_EAGAIN)) {
break;
}
// fallthrough
case SSL_ERROR_WANT_READ:
case SSL_ERROR_WANT_WRITE:
if (isLibeventSafe()) {
return 0;
}
else {
// in the case of SSL_ERROR_SYSCALL we want to wait for an write event again
waitForEvent(error == SSL_ERROR_WANT_READ);
continue;
}
default:;// do nothing
}
string errors;
buildErrors(errors, errno_copy, error);
throw TSSLException("SSL_write: " + errors);
}
written += bytes;
}
return written;
}
void TSSLSocket::flush() {
// Don't throw exception if not open. Thrift servers close socket twice.
if (ssl_ == NULL) {
return;
}
checkHandshake();
initializeHandshake();
if (!checkHandshake())
throw TSSLException("BIO_flush: Handshake is not completed");
BIO* bio = SSL_get_wbio(ssl_);
if (bio == NULL) {
throw TSSLException("SSL_get_wbio returns NULL");
@ -426,14 +570,7 @@ void TSSLSocket::flush() {
}
}
void TSSLSocket::checkHandshake() {
if (!TSocket::isOpen()) {
throw TTransportException(TTransportException::NOT_OPEN);
}
if (ssl_ != NULL) {
return;
}
void TSSLSocket::initializeHandshakeParams() {
// set underlying socket to non-blocking
int flags;
if ((flags = THRIFT_FCNTL(socket_, THRIFT_F_GETFL, 0)) < 0
@ -443,77 +580,100 @@ void TSSLSocket::checkHandshake() {
::THRIFT_CLOSESOCKET(socket_);
return;
}
ssl_ = ctx_->createSSL();
//set read and write bios to non-blocking
BIO* wbio = BIO_new(BIO_s_mem());
if (wbio == NULL) {
throw TSSLException("SSL_get_wbio returns NULL");
}
BIO_set_nbio(wbio, 1);
BIO* rbio = BIO_new(BIO_s_mem());
if (rbio == NULL) {
throw TSSLException("SSL_get_rbio returns NULL");
}
BIO_set_nbio(rbio, 1);
SSL_set_bio(ssl_, rbio, wbio);
SSL_set_fd(ssl_, static_cast<int>(socket_));
}
bool TSSLSocket::checkHandshake() {
return handshakeCompleted_;
}
void TSSLSocket::initializeHandshake() {
if (!TSocket::isOpen()) {
throw TTransportException(TTransportException::NOT_OPEN);
}
if (checkHandshake()) {
return;
}
if (ssl_ == NULL) {
initializeHandshakeParams();
}
int rc;
int errno_copy = 0;
int error = 0;
if (server()) {
do {
rc = SSL_accept(ssl_);
if (rc <= 0) {
int errno_copy = THRIFT_GET_SOCKET_ERROR;
int error = SSL_get_error(ssl_, rc);
errno_copy = THRIFT_GET_SOCKET_ERROR;
error = SSL_get_error(ssl_, rc);
switch (error) {
case SSL_ERROR_SYSCALL:
if ((errno_copy != THRIFT_EINTR)
&& (errno_copy != THRIFT_EAGAIN)) {
break;
}
// fallthrough
case SSL_ERROR_WANT_READ:
case SSL_ERROR_WANT_WRITE:
waitForEvent(error == SSL_ERROR_WANT_READ);
rc = 2;
if (isLibeventSafe()) {
return;
}
else {
// repeat operation
// in the case of SSL_ERROR_SYSCALL we want to wait for an write/read event again
waitForEvent(error == SSL_ERROR_WANT_READ);
rc = 2;
}
default:;// do nothing
}
}
} while (rc == 2);
} else {
// set the SNI hostname
SSL_set_tlsext_host_name(ssl_, getHost().c_str());
// OpenSSL < 0.9.8f does not have SSL_set_tlsext_host_name()
#if defined(SSL_set_tlsext_host_name)
// set the SNI hostname
SSL_set_tlsext_host_name(ssl_, getHost().c_str());
#endif
do {
rc = SSL_connect(ssl_);
if (rc <= 0) {
int errno_copy = THRIFT_GET_SOCKET_ERROR;
int error = SSL_get_error(ssl_, rc);
errno_copy = THRIFT_GET_SOCKET_ERROR;
error = SSL_get_error(ssl_, rc);
switch (error) {
case SSL_ERROR_SYSCALL:
if ((errno_copy != THRIFT_EINTR)
&& (errno_copy != THRIFT_EAGAIN)) {
break;
}
// fallthrough
case SSL_ERROR_WANT_READ:
case SSL_ERROR_WANT_WRITE:
waitForEvent(error == SSL_ERROR_WANT_READ);
rc = 2;
if (isLibeventSafe()) {
return;
}
else {
// repeat operation
// in the case of SSL_ERROR_SYSCALL we want to wait for an write/read event again
waitForEvent(error == SSL_ERROR_WANT_READ);
rc = 2;
}
default:;// do nothing
}
}
} while (rc == 2);
}
if (rc <= 0) {
int errno_copy = THRIFT_GET_SOCKET_ERROR;
string fname(server() ? "SSL_accept" : "SSL_connect");
string errors;
buildErrors(errors, errno_copy);
buildErrors(errors, errno_copy, error);
throw TSSLException(fname + ": " + errors);
}
authorize();
handshakeCompleted_ = true;
}
void TSSLSocket::authorize() {
@ -622,6 +782,9 @@ void TSSLSocket::authorize() {
}
}
/*
* Note: This method is not libevent safe.
*/
unsigned int TSSLSocket::waitForEvent(bool wantRead) {
int fdSocket;
BIO* bio;
@ -641,9 +804,11 @@ unsigned int TSSLSocket::waitForEvent(bool wantRead) {
}
struct THRIFT_POLLFD fds[2];
std::memset(fds, 0, sizeof(fds));
memset(fds, 0, sizeof(fds));
fds[0].fd = fdSocket;
fds[0].events = wantRead ? THRIFT_POLLIN : THRIFT_POLLOUT;
// use POLLIN also on write operations too, this is needed for operations
// which requires read and write on the socket.
fds[0].events = wantRead ? THRIFT_POLLIN : THRIFT_POLLIN | THRIFT_POLLOUT;
if (interruptListener_) {
fds[1].fd = *(interruptListener_.get());
@ -692,7 +857,7 @@ TSSLSocketFactory::TSSLSocketFactory(SSLProtocol protocol) : server_(false) {
randomize();
}
count_++;
ctx_ = boost::shared_ptr<SSLContext>(new SSLContext(protocol));
ctx_ = stdcxx::shared_ptr<SSLContext>(new SSLContext(protocol));
}
TSSLSocketFactory::~TSSLSocketFactory() {
@ -704,47 +869,47 @@ TSSLSocketFactory::~TSSLSocketFactory() {
}
}
boost::shared_ptr<TSSLSocket> TSSLSocketFactory::createSocket() {
boost::shared_ptr<TSSLSocket> ssl(new TSSLSocket(ctx_));
stdcxx::shared_ptr<TSSLSocket> TSSLSocketFactory::createSocket() {
stdcxx::shared_ptr<TSSLSocket> ssl(new TSSLSocket(ctx_));
setup(ssl);
return ssl;
}
boost::shared_ptr<TSSLSocket> TSSLSocketFactory::createSocket(boost::shared_ptr<THRIFT_SOCKET> interruptListener) {
boost::shared_ptr<TSSLSocket> ssl(new TSSLSocket(ctx_, interruptListener));
stdcxx::shared_ptr<TSSLSocket> TSSLSocketFactory::createSocket(stdcxx::shared_ptr<THRIFT_SOCKET> interruptListener) {
stdcxx::shared_ptr<TSSLSocket> ssl(new TSSLSocket(ctx_, interruptListener));
setup(ssl);
return ssl;
}
boost::shared_ptr<TSSLSocket> TSSLSocketFactory::createSocket(THRIFT_SOCKET socket) {
boost::shared_ptr<TSSLSocket> ssl(new TSSLSocket(ctx_, socket));
stdcxx::shared_ptr<TSSLSocket> TSSLSocketFactory::createSocket(THRIFT_SOCKET socket) {
stdcxx::shared_ptr<TSSLSocket> ssl(new TSSLSocket(ctx_, socket));
setup(ssl);
return ssl;
}
boost::shared_ptr<TSSLSocket> TSSLSocketFactory::createSocket(THRIFT_SOCKET socket, boost::shared_ptr<THRIFT_SOCKET> interruptListener) {
boost::shared_ptr<TSSLSocket> ssl(new TSSLSocket(ctx_, socket, interruptListener));
stdcxx::shared_ptr<TSSLSocket> TSSLSocketFactory::createSocket(THRIFT_SOCKET socket, stdcxx::shared_ptr<THRIFT_SOCKET> interruptListener) {
stdcxx::shared_ptr<TSSLSocket> ssl(new TSSLSocket(ctx_, socket, interruptListener));
setup(ssl);
return ssl;
}
boost::shared_ptr<TSSLSocket> TSSLSocketFactory::createSocket(const string& host, int port) {
boost::shared_ptr<TSSLSocket> ssl(new TSSLSocket(ctx_, host, port));
stdcxx::shared_ptr<TSSLSocket> TSSLSocketFactory::createSocket(const string& host, int port) {
stdcxx::shared_ptr<TSSLSocket> ssl(new TSSLSocket(ctx_, host, port));
setup(ssl);
return ssl;
}
boost::shared_ptr<TSSLSocket> TSSLSocketFactory::createSocket(const string& host, int port, boost::shared_ptr<THRIFT_SOCKET> interruptListener) {
boost::shared_ptr<TSSLSocket> ssl(new TSSLSocket(ctx_, host, port, interruptListener));
stdcxx::shared_ptr<TSSLSocket> TSSLSocketFactory::createSocket(const string& host, int port, stdcxx::shared_ptr<THRIFT_SOCKET> interruptListener) {
stdcxx::shared_ptr<TSSLSocket> ssl(new TSSLSocket(ctx_, host, port, interruptListener));
setup(ssl);
return ssl;
}
void TSSLSocketFactory::setup(boost::shared_ptr<TSSLSocket> ssl) {
void TSSLSocketFactory::setup(stdcxx::shared_ptr<TSSLSocket> ssl) {
ssl->server(server());
if (access_ == NULL && !server()) {
access_ = boost::shared_ptr<AccessManager>(new DefaultClientAccessManager);
access_ = stdcxx::shared_ptr<AccessManager>(new DefaultClientAccessManager);
}
if (access_ != NULL) {
ssl->access(access_);
@ -805,12 +970,12 @@ void TSSLSocketFactory::loadPrivateKey(const char* path, const char* format) {
}
}
void TSSLSocketFactory::loadTrustedCertificates(const char* path) {
void TSSLSocketFactory::loadTrustedCertificates(const char* path, const char* capath) {
if (path == NULL) {
throw TTransportException(TTransportException::BAD_ARGS,
"loadTrustedCertificates: <path> is NULL");
}
if (SSL_CTX_load_verify_locations(ctx_->get(), path, NULL) == 0) {
if (SSL_CTX_load_verify_locations(ctx_->get(), path, capath) == 0) {
int errno_copy = THRIFT_GET_SOCKET_ERROR;
string errors;
buildErrors(errors, errno_copy);
@ -841,7 +1006,7 @@ int TSSLSocketFactory::passwordCallback(char* password, int size, int, void* dat
}
// extract error messages from error queue
void buildErrors(string& errors, int errno_copy) {
void buildErrors(string& errors, int errno_copy, int sslerrno) {
unsigned long errorCode;
char message[256];
@ -863,7 +1028,18 @@ void buildErrors(string& errors, int errno_copy) {
}
}
if (errors.empty()) {
errors = "error code: " + boost::lexical_cast<string>(errno_copy);
errors = "error code: " + to_string(errno_copy);
}
if (sslerrno) {
errors += " (SSL_error_code = " + to_string(sslerrno) + ")";
if (sslerrno == SSL_ERROR_SYSCALL) {
char buf[4096];
int err;
while ((err = ERR_get_error()) != 0) {
errors += " ";
errors += ERR_error_string(err, buf);
}
}
}
}

View file

@ -22,10 +22,11 @@
// Put this first to avoid WIN32 build failure
#include <thrift/transport/TSocket.h>
#include <string>
#include <boost/shared_ptr.hpp>
#include <openssl/ssl.h>
#include <string>
#include <thrift/concurrency/Mutex.h>
#include <thrift/stdcxx.h>
namespace apache {
namespace thrift {
@ -77,8 +78,10 @@ public:
bool peek();
void open();
void close();
bool hasPendingDataToRead();
uint32_t read(uint8_t* buf, uint32_t len);
void write(const uint8_t* buf, uint32_t len);
uint32_t write_partial(const uint8_t* buf, uint32_t len);
void flush();
/**
* Set whether to use client or server side SSL handshake protocol.
@ -95,43 +98,51 @@ public:
*
* @param manager Instance of AccessManager
*/
virtual void access(boost::shared_ptr<AccessManager> manager) { access_ = manager; }
virtual void access(stdcxx::shared_ptr<AccessManager> manager) { access_ = manager; }
/**
* Set eventSafe flag if libevent is used.
*/
void setLibeventSafe() { eventSafe_ = true; }
/**
* Determines whether SSL Socket is libevent safe or not.
*/
bool isLibeventSafe() const { return eventSafe_; }
protected:
/**
* Constructor.
*/
TSSLSocket(boost::shared_ptr<SSLContext> ctx);
TSSLSocket(stdcxx::shared_ptr<SSLContext> ctx);
/**
* Constructor with an interrupt signal.
*/
TSSLSocket(boost::shared_ptr<SSLContext> ctx, boost::shared_ptr<THRIFT_SOCKET> interruptListener);
TSSLSocket(stdcxx::shared_ptr<SSLContext> ctx, stdcxx::shared_ptr<THRIFT_SOCKET> interruptListener);
/**
* Constructor, create an instance of TSSLSocket given an existing socket.
*
* @param socket An existing socket
*/
TSSLSocket(boost::shared_ptr<SSLContext> ctx, THRIFT_SOCKET socket);
TSSLSocket(stdcxx::shared_ptr<SSLContext> ctx, THRIFT_SOCKET socket);
/**
* Constructor, create an instance of TSSLSocket given an existing socket that can be interrupted.
*
* @param socket An existing socket
*/
TSSLSocket(boost::shared_ptr<SSLContext> ctx, THRIFT_SOCKET socket, boost::shared_ptr<THRIFT_SOCKET> interruptListener);
TSSLSocket(stdcxx::shared_ptr<SSLContext> ctx, THRIFT_SOCKET socket, stdcxx::shared_ptr<THRIFT_SOCKET> interruptListener);
/**
* Constructor.
*
* @param host Remote host name
* @param port Remote port number
*/
TSSLSocket(boost::shared_ptr<SSLContext> ctx, std::string host, int port);
TSSLSocket(stdcxx::shared_ptr<SSLContext> ctx, std::string host, int port);
/**
* Constructor with an interrupt signal.
*
* @param host Remote host name
* @param port Remote port number
*/
TSSLSocket(boost::shared_ptr<SSLContext> ctx, std::string host, int port, boost::shared_ptr<THRIFT_SOCKET> interruptListener);
* Constructor with an interrupt signal.
*
* @param host Remote host name
* @param port Remote port number
*/
TSSLSocket(stdcxx::shared_ptr<SSLContext> ctx, std::string host, int port, stdcxx::shared_ptr<THRIFT_SOCKET> interruptListener);
/**
* Authorize peer access after SSL handshake completes.
*/
@ -139,7 +150,15 @@ protected:
/**
* Initiate SSL handshake if not already initiated.
*/
void checkHandshake();
void initializeHandshake();
/**
* Initiate SSL handshake params.
*/
void initializeHandshakeParams();
/**
* Check if SSL handshake is completed or not.
*/
bool checkHandshake();
/**
* Waits for an socket or shutdown event.
*
@ -152,13 +171,34 @@ protected:
bool server_;
SSL* ssl_;
boost::shared_ptr<SSLContext> ctx_;
boost::shared_ptr<AccessManager> access_;
stdcxx::shared_ptr<SSLContext> ctx_;
stdcxx::shared_ptr<AccessManager> access_;
friend class TSSLSocketFactory;
private:
bool handshakeCompleted_;
int readRetryCount_;
bool eventSafe_;
void init();
};
/**
* SSL socket factory. SSL sockets should be created via SSL factory.
* The factory will automatically initialize and cleanup openssl as long as
* there is a TSSLSocketFactory instantiated, and as long as the static
* boolean manualOpenSSLInitialization_ is set to false, the default.
*
* If you would like to initialize and cleanup openssl yourself, set
* manualOpenSSLInitialization_ to true and TSSLSocketFactory will no
* longer be responsible for openssl initialization and teardown.
*
* It is the responsibility of the code using TSSLSocketFactory to
* ensure that the factory lifetime exceeds the lifetime of any sockets
* it might create. If this is not guaranteed, a socket may call into
* openssl after the socket factory has cleaned up openssl! This
* guarantee is unnecessary if manualOpenSSLInitialization_ is true,
* however, since it would be up to the consuming application instead.
*/
class TSSLSocketFactory {
public:
@ -172,37 +212,37 @@ public:
/**
* Create an instance of TSSLSocket with a fresh new socket.
*/
virtual boost::shared_ptr<TSSLSocket> createSocket();
virtual stdcxx::shared_ptr<TSSLSocket> createSocket();
/**
* Create an instance of TSSLSocket with a fresh new socket, which is interruptable.
*/
virtual boost::shared_ptr<TSSLSocket> createSocket(boost::shared_ptr<THRIFT_SOCKET> interruptListener);
virtual stdcxx::shared_ptr<TSSLSocket> createSocket(stdcxx::shared_ptr<THRIFT_SOCKET> interruptListener);
/**
* Create an instance of TSSLSocket with the given socket.
*
* @param socket An existing socket.
*/
virtual boost::shared_ptr<TSSLSocket> createSocket(THRIFT_SOCKET socket);
virtual stdcxx::shared_ptr<TSSLSocket> createSocket(THRIFT_SOCKET socket);
/**
* Create an instance of TSSLSocket with the given socket which is interruptable.
*
* @param socket An existing socket.
*/
virtual boost::shared_ptr<TSSLSocket> createSocket(THRIFT_SOCKET socket, boost::shared_ptr<THRIFT_SOCKET> interruptListener);
virtual stdcxx::shared_ptr<TSSLSocket> createSocket(THRIFT_SOCKET socket, stdcxx::shared_ptr<THRIFT_SOCKET> interruptListener);
/**
* Create an instance of TSSLSocket.
*
* @param host Remote host to be connected to
* @param port Remote port to be connected to
*/
virtual boost::shared_ptr<TSSLSocket> createSocket(const std::string& host, int port);
virtual stdcxx::shared_ptr<TSSLSocket> createSocket(const std::string& host, int port);
/**
* Create an instance of TSSLSocket.
*
* @param host Remote host to be connected to
* @param port Remote port to be connected to
*/
virtual boost::shared_ptr<TSSLSocket> createSocket(const std::string& host, int port, boost::shared_ptr<THRIFT_SOCKET> interruptListener);
virtual stdcxx::shared_ptr<TSSLSocket> createSocket(const std::string& host, int port, stdcxx::shared_ptr<THRIFT_SOCKET> interruptListener);
/**
* Set ciphers to be used in SSL handshake process.
*
@ -234,7 +274,7 @@ public:
*
* @param path Path to trusted certificate file
*/
virtual void loadTrustedCertificates(const char* path);
virtual void loadTrustedCertificates(const char* path, const char* capath = NULL);
/**
* Default randomize method.
*/
@ -260,13 +300,13 @@ public:
*
* @param manager The AccessManager instance
*/
virtual void access(boost::shared_ptr<AccessManager> manager) { access_ = manager; }
virtual void access(stdcxx::shared_ptr<AccessManager> manager) { access_ = manager; }
static void setManualOpenSSLInitialization(bool manualOpenSSLInitialization) {
manualOpenSSLInitialization_ = manualOpenSSLInitialization;
}
protected:
boost::shared_ptr<SSLContext> ctx_;
stdcxx::shared_ptr<SSLContext> ctx_;
/**
* Override this method for custom password callback. It may be called
@ -279,11 +319,11 @@ protected:
private:
bool server_;
boost::shared_ptr<AccessManager> access_;
stdcxx::shared_ptr<AccessManager> access_;
static concurrency::Mutex mutex_;
static uint64_t count_;
static bool manualOpenSSLInitialization_;
void setup(boost::shared_ptr<TSSLSocket> ssl);
void setup(stdcxx::shared_ptr<TSSLSocket> ssl);
static int passwordCallback(char* password, int size, int, void* data);
};

View file

@ -46,7 +46,7 @@
#include <thrift/transport/TSocket.h>
#include <thrift/transport/TServerSocket.h>
#include <thrift/transport/PlatformSocket.h>
#include <boost/shared_ptr.hpp>
#include <thrift/stdcxx.h>
#ifndef AF_LOCAL
#define AF_LOCAL AF_UNIX
@ -60,10 +60,6 @@
#endif // _WIN32
#endif
#if defined(_WIN32) && (_WIN32_WINNT < 0x0600)
#define AI_ADDRCONFIG 0x0400
#endif
template <class T>
inline const SOCKOPT_CAST_T* const_cast_sockopt(const T* v) {
return reinterpret_cast<const SOCKOPT_CAST_T*>(v);
@ -79,21 +75,13 @@ void destroyer_of_fine_sockets(THRIFT_SOCKET* ssock) {
delete ssock;
}
class TGetAddrInfoWrapper {
public:
TGetAddrInfoWrapper(const char* node, const char* service, const struct addrinfo* hints);
using std::string;
virtual ~TGetAddrInfoWrapper();
namespace apache {
namespace thrift {
namespace transport {
int init();
const struct addrinfo* res();
private:
const char* node_;
const char* service_;
const struct addrinfo* hints_;
struct addrinfo* res_;
};
using stdcxx::shared_ptr;
TGetAddrInfoWrapper::TGetAddrInfoWrapper(const char* node,
const char* service,
@ -115,13 +103,6 @@ const struct addrinfo* TGetAddrInfoWrapper::res() {
return this->res_;
}
namespace apache {
namespace thrift {
namespace transport {
using namespace std;
using boost::shared_ptr;
TServerSocket::TServerSocket(int port)
: interruptableChildren_(true),
port_(port),
@ -268,7 +249,7 @@ void TServerSocket::listen() {
} else {
childInterruptSockWriter_ = sv[1];
pChildInterruptSockReader_
= boost::shared_ptr<THRIFT_SOCKET>(new THRIFT_SOCKET(sv[0]), destroyer_of_fine_sockets);
= stdcxx::shared_ptr<THRIFT_SOCKET>(new THRIFT_SOCKET(sv[0]), destroyer_of_fine_sockets);
}
// Validate port number
@ -307,7 +288,7 @@ void TServerSocket::listen() {
if (!path_.empty()) {
serverSocket_ = socket(PF_UNIX, SOCK_STREAM, IPPROTO_IP);
} else {
} else if (res != NULL) {
serverSocket_ = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
}
@ -613,7 +594,7 @@ shared_ptr<TTransport> TServerSocket::acceptImpl() {
THRIFT_SOCKET clientSocket
= ::accept(serverSocket_, (struct sockaddr*)&clientAddress, (socklen_t*)&size);
if (clientSocket == -1) {
if (clientSocket == THRIFT_INVALID_SOCKET) {
int errno_copy = THRIFT_GET_SOCKET_ERROR;
GlobalOutput.perror("TServerSocket::acceptImpl() ::accept() ", errno_copy);
throw TTransportException(TTransportException::UNKNOWN, "accept()", errno_copy);
@ -677,14 +658,21 @@ void TServerSocket::notify(THRIFT_SOCKET notifySocket) {
}
void TServerSocket::interrupt() {
notify(interruptSockWriter_);
concurrency::Guard g(rwMutex_);
if (interruptSockWriter_ != THRIFT_INVALID_SOCKET) {
notify(interruptSockWriter_);
}
}
void TServerSocket::interruptChildren() {
notify(childInterruptSockWriter_);
concurrency::Guard g(rwMutex_);
if (childInterruptSockWriter_ != THRIFT_INVALID_SOCKET) {
notify(childInterruptSockWriter_);
}
}
void TServerSocket::close() {
concurrency::Guard g(rwMutex_);
if (serverSocket_ != THRIFT_INVALID_SOCKET) {
shutdown(serverSocket_, THRIFT_SHUT_RDWR);
::THRIFT_CLOSESOCKET(serverSocket_);

View file

@ -20,10 +20,18 @@
#ifndef _THRIFT_TRANSPORT_TSERVERSOCKET_H_
#define _THRIFT_TRANSPORT_TSERVERSOCKET_H_ 1
#include <thrift/transport/TServerTransport.h>
#include <thrift/concurrency/Mutex.h>
#include <thrift/stdcxx.h>
#include <thrift/transport/PlatformSocket.h>
#include <thrift/cxxfunctional.h>
#include <boost/shared_ptr.hpp>
#include <thrift/transport/TServerTransport.h>
#include <sys/types.h>
#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif
#ifdef HAVE_NETDB_H
#include <netdb.h>
#endif
namespace apache {
namespace thrift {
@ -31,6 +39,22 @@ namespace transport {
class TSocket;
class TGetAddrInfoWrapper {
public:
TGetAddrInfoWrapper(const char* node, const char* service, const struct addrinfo* hints);
virtual ~TGetAddrInfoWrapper();
int init();
const struct addrinfo* res();
private:
const char* node_;
const char* service_;
const struct addrinfo* hints_;
struct addrinfo* res_;
};
/**
* Server socket implementation of TServerTransport. Wrapper around a unix
* socket listen and accept calls.
@ -113,6 +137,8 @@ public:
// \throws std::logic_error if listen() has been called
void setInterruptableChildren(bool enable);
THRIFT_SOCKET getSocketFD() { return serverSocket_; }
int getPort();
void listen();
@ -121,10 +147,10 @@ public:
void close();
protected:
boost::shared_ptr<TTransport> acceptImpl();
virtual boost::shared_ptr<TSocket> createSocket(THRIFT_SOCKET client);
stdcxx::shared_ptr<TTransport> acceptImpl();
virtual stdcxx::shared_ptr<TSocket> createSocket(THRIFT_SOCKET client);
bool interruptableChildren_;
boost::shared_ptr<THRIFT_SOCKET> pChildInterruptSockReader_; // if interruptableChildren_ this is shared with child TSockets
stdcxx::shared_ptr<THRIFT_SOCKET> pChildInterruptSockReader_; // if interruptableChildren_ this is shared with child TSockets
private:
void notify(THRIFT_SOCKET notifySock);
@ -144,6 +170,7 @@ private:
bool keepAlive_;
bool listening_;
concurrency::Mutex rwMutex_; // thread-safe interrupt
THRIFT_SOCKET interruptSockWriter_; // is notified on interrupt()
THRIFT_SOCKET interruptSockReader_; // is used in select/poll with serverSocket_ for interruptability
THRIFT_SOCKET childInterruptSockWriter_; // is notified on interruptChildren()

Some files were not shown because too many files have changed in this diff Show more