You've already forked mariadb-columnstore-engine
mirror of
https://github.com/mariadb-corporation/mariadb-columnstore-engine.git
synced 2025-11-22 20:42:36 +03:00
remove commited old thrift, replace with static lib build from exterrnal project
This commit is contained in:
@@ -118,6 +118,7 @@ SET (ENGINE_SRC_DIR ${CMAKE_CURRENT_SOURCE_DIR})
|
|||||||
INCLUDE(columnstore_version)
|
INCLUDE(columnstore_version)
|
||||||
INCLUDE(misc)
|
INCLUDE(misc)
|
||||||
INCLUDE(boost)
|
INCLUDE(boost)
|
||||||
|
INCLUDE(thrift)
|
||||||
|
|
||||||
FIND_PACKAGE(BISON)
|
FIND_PACKAGE(BISON)
|
||||||
IF (NOT BISON_FOUND)
|
IF (NOT BISON_FOUND)
|
||||||
@@ -245,7 +246,7 @@ SET (ENGINE_DT_LIB datatypes)
|
|||||||
SET (ENGINE_COMMON_LIBS messageqcpp loggingcpp configcpp idbboot boost_thread xml2 pthread rt ${ENGINE_DT_LIB})
|
SET (ENGINE_COMMON_LIBS messageqcpp loggingcpp configcpp idbboot boost_thread xml2 pthread rt ${ENGINE_DT_LIB})
|
||||||
SET (ENGINE_OAM_LIBS oamcpp)
|
SET (ENGINE_OAM_LIBS oamcpp)
|
||||||
SET (ENGINE_BRM_LIBS brm idbdatafile cacheutils rwlock ${ENGINE_OAM_LIBS} ${ENGINE_COMMON_LIBS})
|
SET (ENGINE_BRM_LIBS brm idbdatafile cacheutils rwlock ${ENGINE_OAM_LIBS} ${ENGINE_COMMON_LIBS})
|
||||||
SET (PLUGIN_EXEC_LIBS execplan windowfunction joiner rowgroup funcexp udfsdk regr dataconvert common compress querytele thrift threadpool ${ENGINE_BRM_LIBS})
|
SET (PLUGIN_EXEC_LIBS execplan windowfunction joiner rowgroup funcexp udfsdk regr dataconvert common compress querytele threadpool ${ENGINE_BRM_LIBS})
|
||||||
SET (ENGINE_EXEC_LIBS joblist querystats libmysql_client ${PLUGIN_EXEC_LIBS})
|
SET (ENGINE_EXEC_LIBS joblist querystats libmysql_client ${PLUGIN_EXEC_LIBS})
|
||||||
SET (PLUGIN_WRITE_LIBS ddlpackageproc ddlpackage dmlpackageproc dmlpackage writeengine writeengineclient idbdatafile cacheutils)
|
SET (PLUGIN_WRITE_LIBS ddlpackageproc ddlpackage dmlpackageproc dmlpackage writeengine writeengineclient idbdatafile cacheutils)
|
||||||
SET (ENGINE_WRITE_LIBS ${PLUGIN_WRITE_LIBS} ${ENGINE_EXEC_LIBS})
|
SET (ENGINE_WRITE_LIBS ${PLUGIN_WRITE_LIBS} ${ENGINE_EXEC_LIBS})
|
||||||
@@ -327,7 +328,6 @@ SET (ENGINE_DBCON_DMLPKGPROC_INCLUDE "${CMAKE_CURRENT_SOURCE_DIR}/dbcon/dmlpack
|
|||||||
SET (ENGINE_UTILS_CACHEUTILS_INCLUDE "${CMAKE_CURRENT_SOURCE_DIR}/utils/cacheutils")
|
SET (ENGINE_UTILS_CACHEUTILS_INCLUDE "${CMAKE_CURRENT_SOURCE_DIR}/utils/cacheutils")
|
||||||
SET (ENGINE_UTILS_MYSQLCL_INCLUDE "${CMAKE_CURRENT_SOURCE_DIR}/utils/mysqlcl_idb")
|
SET (ENGINE_UTILS_MYSQLCL_INCLUDE "${CMAKE_CURRENT_SOURCE_DIR}/utils/mysqlcl_idb")
|
||||||
SET (ENGINE_UTILS_QUERYTELE_INCLUDE "${CMAKE_CURRENT_SOURCE_DIR}/utils/querytele")
|
SET (ENGINE_UTILS_QUERYTELE_INCLUDE "${CMAKE_CURRENT_SOURCE_DIR}/utils/querytele")
|
||||||
SET (ENGINE_UTILS_THRIFT_INCLUDE "${CMAKE_CURRENT_SOURCE_DIR}/utils/thrift")
|
|
||||||
SET (ENGINE_UTILS_JOINER_INCLUDE "${CMAKE_CURRENT_SOURCE_DIR}/utils/joiner")
|
SET (ENGINE_UTILS_JOINER_INCLUDE "${CMAKE_CURRENT_SOURCE_DIR}/utils/joiner")
|
||||||
SET (ENGINE_UTILS_THREADPOOL_INCLUDE "${CMAKE_CURRENT_SOURCE_DIR}/utils/threadpool")
|
SET (ENGINE_UTILS_THREADPOOL_INCLUDE "${CMAKE_CURRENT_SOURCE_DIR}/utils/threadpool")
|
||||||
SET (ENGINE_UTILS_BATCHLDR_INCLUDE "${CMAKE_CURRENT_SOURCE_DIR}/utils/batchloader")
|
SET (ENGINE_UTILS_BATCHLDR_INCLUDE "${CMAKE_CURRENT_SOURCE_DIR}/utils/batchloader")
|
||||||
|
|||||||
29
cmake/thrift.cmake
Normal file
29
cmake/thrift.cmake
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
include(ExternalProject)
|
||||||
|
|
||||||
|
set(INSTALL_LOCATION ${CMAKE_CURRENT_BINARY_DIR}/external/thrift)
|
||||||
|
SET(THRIFT_INCLUDE_DIRS "${INSTALL_LOCATION}/include")
|
||||||
|
SET(THRIFT_LIBRARY_DIRS "${INSTALL_LOCATION}/lib")
|
||||||
|
set(THRIFT_LIBRARY ${THRIFT_LIBRARY_DIRS}/${CMAKE_STATIC_LIBRARY_PREFIX}thrift${CMAKE_STATIC_LIBRARY_SUFFIX})
|
||||||
|
|
||||||
|
|
||||||
|
ExternalProject_Add(external_thrift
|
||||||
|
URL https://github.com/apache/thrift/archive/refs/tags/v0.17.0.tar.gz
|
||||||
|
URL_HASH SHA256=f5888bcd3b8de40c2c2ab86896867ad9b18510deb412cba3e5da76fb4c604c29
|
||||||
|
PREFIX ${INSTALL_LOCATION}
|
||||||
|
CMAKE_ARGS -DCMAKE_INSTALL_PREFIX:PATH=${INSTALL_LOCATION}
|
||||||
|
-DBUILD_COMPILER=YES
|
||||||
|
-DBUILD_CPP=YES
|
||||||
|
-DBUILD_C_GLIB=YES
|
||||||
|
-DBUILD_JAVA=NO
|
||||||
|
-DBUILD_JAVASCRIPT=NO
|
||||||
|
-DBUILD_KOTLIN=NO
|
||||||
|
-DBUILD_NODEJS=NO
|
||||||
|
-DBUILD_PYTHON=NO
|
||||||
|
-DBUILD_TESTING=NO
|
||||||
|
-DBUILD_SHARED_LIBS=NO
|
||||||
|
-DCMAKE_CXX_FLAGS:STRING="-fPIC"
|
||||||
|
-DBOOST_INCLUDEDIR=${Boost_INCLUDE_DIRS}
|
||||||
|
-DBOOST_LIBRARYDIR=${Boost_LIBRARY_DIRS}
|
||||||
|
)
|
||||||
|
|
||||||
|
add_dependencies(external_thrift external_boost)
|
||||||
1
debian/mariadb-plugin-columnstore.install
vendored
1
debian/mariadb-plugin-columnstore.install
vendored
@@ -79,7 +79,6 @@ usr/lib/*/librowgroup.so
|
|||||||
usr/lib/*/librwlock.so
|
usr/lib/*/librwlock.so
|
||||||
usr/lib/*/libstoragemanager.so
|
usr/lib/*/libstoragemanager.so
|
||||||
usr/lib/*/libthreadpool.so
|
usr/lib/*/libthreadpool.so
|
||||||
usr/lib/*/libthrift.so
|
|
||||||
usr/lib/*/libudfsdk.so
|
usr/lib/*/libudfsdk.so
|
||||||
usr/lib/*/libwindowfunction.so
|
usr/lib/*/libwindowfunction.so
|
||||||
usr/lib/*/libwriteengine.so
|
usr/lib/*/libwriteengine.so
|
||||||
|
|||||||
@@ -20,7 +20,6 @@ add_subdirectory(querystats)
|
|||||||
add_subdirectory(windowfunction)
|
add_subdirectory(windowfunction)
|
||||||
add_subdirectory(idbdatafile)
|
add_subdirectory(idbdatafile)
|
||||||
add_subdirectory(winport)
|
add_subdirectory(winport)
|
||||||
add_subdirectory(thrift)
|
|
||||||
add_subdirectory(querytele)
|
add_subdirectory(querytele)
|
||||||
add_subdirectory(libmysql_client)
|
add_subdirectory(libmysql_client)
|
||||||
add_subdirectory(regr)
|
add_subdirectory(regr)
|
||||||
|
|||||||
@@ -13,7 +13,9 @@ set(querytele_LIB_SRCS
|
|||||||
queryteleprotoimpl.cpp)
|
queryteleprotoimpl.cpp)
|
||||||
|
|
||||||
add_library(querytele SHARED ${querytele_LIB_SRCS})
|
add_library(querytele SHARED ${querytele_LIB_SRCS})
|
||||||
add_dependencies(querytele external_boost)
|
add_dependencies(querytele external_boost external_thrift)
|
||||||
|
|
||||||
|
target_include_directories(querytele PRIVATE ${THRIFT_INCLUDE_DIRS})
|
||||||
|
target_link_libraries(querytele ${THRIFT_LIBRARY})
|
||||||
install(TARGETS querytele DESTINATION ${ENGINE_LIBDIR} COMPONENT columnstore-engine)
|
install(TARGETS querytele DESTINATION ${ENGINE_LIBDIR} COMPONENT columnstore-engine)
|
||||||
|
|
||||||
|
|||||||
@@ -844,12 +844,12 @@ void QueryTeleServiceProcessor::process_postImport(int32_t seqid,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
::boost::shared_ptr< ::apache::thrift::TProcessor> QueryTeleServiceProcessorFactory::getProcessor(
|
::std::shared_ptr< ::apache::thrift::TProcessor> QueryTeleServiceProcessorFactory::getProcessor(
|
||||||
const ::apache::thrift::TConnectionInfo& connInfo)
|
const ::apache::thrift::TConnectionInfo& connInfo)
|
||||||
{
|
{
|
||||||
::apache::thrift::ReleaseHandler<QueryTeleServiceIfFactory> cleanup(handlerFactory_);
|
::apache::thrift::ReleaseHandler<QueryTeleServiceIfFactory> cleanup(handlerFactory_);
|
||||||
::boost::shared_ptr<QueryTeleServiceIf> handler(handlerFactory_->getHandler(connInfo), cleanup);
|
::std::shared_ptr<QueryTeleServiceIf> handler(handlerFactory_->getHandler(connInfo), cleanup);
|
||||||
::boost::shared_ptr< ::apache::thrift::TProcessor> processor(new QueryTeleServiceProcessor(handler));
|
::std::shared_ptr< ::apache::thrift::TProcessor> processor(new QueryTeleServiceProcessor(handler));
|
||||||
return processor;
|
return processor;
|
||||||
}
|
}
|
||||||
} // namespace querytele
|
} // namespace querytele
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
#include <thrift/TDispatchProcessor.h>
|
#include <thrift/TDispatchProcessor.h>
|
||||||
#include "querytele_types.h"
|
#include "querytele_types.h"
|
||||||
|
|
||||||
|
|
||||||
namespace querytele
|
namespace querytele
|
||||||
{
|
{
|
||||||
class QueryTeleServiceIf
|
class QueryTeleServiceIf
|
||||||
@@ -38,7 +39,7 @@ class QueryTeleServiceIfFactory
|
|||||||
class QueryTeleServiceIfSingletonFactory : virtual public QueryTeleServiceIfFactory
|
class QueryTeleServiceIfSingletonFactory : virtual public QueryTeleServiceIfFactory
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
QueryTeleServiceIfSingletonFactory(const boost::shared_ptr<QueryTeleServiceIf>& iface) : iface_(iface)
|
QueryTeleServiceIfSingletonFactory(const std::shared_ptr<QueryTeleServiceIf>& iface) : iface_(iface)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
virtual ~QueryTeleServiceIfSingletonFactory()
|
virtual ~QueryTeleServiceIfSingletonFactory()
|
||||||
@@ -54,7 +55,7 @@ class QueryTeleServiceIfSingletonFactory : virtual public QueryTeleServiceIfFact
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
boost::shared_ptr<QueryTeleServiceIf> iface_;
|
std::shared_ptr<QueryTeleServiceIf> iface_;
|
||||||
};
|
};
|
||||||
|
|
||||||
class QueryTeleServiceNull : virtual public QueryTeleServiceIf
|
class QueryTeleServiceNull : virtual public QueryTeleServiceIf
|
||||||
@@ -362,24 +363,24 @@ class QueryTeleService_postImport_presult
|
|||||||
class QueryTeleServiceClient : virtual public QueryTeleServiceIf
|
class QueryTeleServiceClient : virtual public QueryTeleServiceIf
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
QueryTeleServiceClient(boost::shared_ptr< ::apache::thrift::protocol::TProtocol> prot)
|
QueryTeleServiceClient(std::shared_ptr< ::apache::thrift::protocol::TProtocol> prot)
|
||||||
: piprot_(prot), poprot_(prot)
|
: piprot_(prot), poprot_(prot)
|
||||||
{
|
{
|
||||||
iprot_ = prot.get();
|
iprot_ = prot.get();
|
||||||
oprot_ = prot.get();
|
oprot_ = prot.get();
|
||||||
}
|
}
|
||||||
QueryTeleServiceClient(boost::shared_ptr< ::apache::thrift::protocol::TProtocol> iprot,
|
QueryTeleServiceClient(std::shared_ptr< ::apache::thrift::protocol::TProtocol> iprot,
|
||||||
boost::shared_ptr< ::apache::thrift::protocol::TProtocol> oprot)
|
std::shared_ptr< ::apache::thrift::protocol::TProtocol> oprot)
|
||||||
: piprot_(iprot), poprot_(oprot)
|
: piprot_(iprot), poprot_(oprot)
|
||||||
{
|
{
|
||||||
iprot_ = iprot.get();
|
iprot_ = iprot.get();
|
||||||
oprot_ = oprot.get();
|
oprot_ = oprot.get();
|
||||||
}
|
}
|
||||||
boost::shared_ptr< ::apache::thrift::protocol::TProtocol> getInputProtocol()
|
std::shared_ptr< ::apache::thrift::protocol::TProtocol> getInputProtocol()
|
||||||
{
|
{
|
||||||
return piprot_;
|
return piprot_;
|
||||||
}
|
}
|
||||||
boost::shared_ptr< ::apache::thrift::protocol::TProtocol> getOutputProtocol()
|
std::shared_ptr< ::apache::thrift::protocol::TProtocol> getOutputProtocol()
|
||||||
{
|
{
|
||||||
return poprot_;
|
return poprot_;
|
||||||
}
|
}
|
||||||
@@ -394,8 +395,8 @@ class QueryTeleServiceClient : virtual public QueryTeleServiceIf
|
|||||||
void recv_postImport();
|
void recv_postImport();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
boost::shared_ptr< ::apache::thrift::protocol::TProtocol> piprot_;
|
std::shared_ptr< ::apache::thrift::protocol::TProtocol> piprot_;
|
||||||
boost::shared_ptr< ::apache::thrift::protocol::TProtocol> poprot_;
|
std::shared_ptr< ::apache::thrift::protocol::TProtocol> poprot_;
|
||||||
::apache::thrift::protocol::TProtocol* iprot_;
|
::apache::thrift::protocol::TProtocol* iprot_;
|
||||||
::apache::thrift::protocol::TProtocol* oprot_;
|
::apache::thrift::protocol::TProtocol* oprot_;
|
||||||
};
|
};
|
||||||
@@ -403,7 +404,7 @@ class QueryTeleServiceClient : virtual public QueryTeleServiceIf
|
|||||||
class QueryTeleServiceProcessor : public ::apache::thrift::TDispatchProcessor
|
class QueryTeleServiceProcessor : public ::apache::thrift::TDispatchProcessor
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
boost::shared_ptr<QueryTeleServiceIf> iface_;
|
std::shared_ptr<QueryTeleServiceIf> iface_;
|
||||||
virtual bool dispatchCall(::apache::thrift::protocol::TProtocol* iprot,
|
virtual bool dispatchCall(::apache::thrift::protocol::TProtocol* iprot,
|
||||||
::apache::thrift::protocol::TProtocol* oprot, const std::string& fname,
|
::apache::thrift::protocol::TProtocol* oprot, const std::string& fname,
|
||||||
int32_t seqid, void* callContext);
|
int32_t seqid, void* callContext);
|
||||||
@@ -421,7 +422,7 @@ class QueryTeleServiceProcessor : public ::apache::thrift::TDispatchProcessor
|
|||||||
::apache::thrift::protocol::TProtocol* oprot, void* callContext);
|
::apache::thrift::protocol::TProtocol* oprot, void* callContext);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
QueryTeleServiceProcessor(boost::shared_ptr<QueryTeleServiceIf> iface) : iface_(iface)
|
QueryTeleServiceProcessor(std::shared_ptr<QueryTeleServiceIf> iface) : iface_(iface)
|
||||||
{
|
{
|
||||||
processMap_["postQuery"] = &QueryTeleServiceProcessor::process_postQuery;
|
processMap_["postQuery"] = &QueryTeleServiceProcessor::process_postQuery;
|
||||||
processMap_["postStep"] = &QueryTeleServiceProcessor::process_postStep;
|
processMap_["postStep"] = &QueryTeleServiceProcessor::process_postStep;
|
||||||
@@ -436,22 +437,22 @@ class QueryTeleServiceProcessor : public ::apache::thrift::TDispatchProcessor
|
|||||||
class QueryTeleServiceProcessorFactory : public ::apache::thrift::TProcessorFactory
|
class QueryTeleServiceProcessorFactory : public ::apache::thrift::TProcessorFactory
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
QueryTeleServiceProcessorFactory(const ::boost::shared_ptr<QueryTeleServiceIfFactory>& handlerFactory)
|
QueryTeleServiceProcessorFactory(const ::std::shared_ptr<QueryTeleServiceIfFactory>& handlerFactory)
|
||||||
: handlerFactory_(handlerFactory)
|
: handlerFactory_(handlerFactory)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
::boost::shared_ptr< ::apache::thrift::TProcessor> getProcessor(
|
::std::shared_ptr< ::apache::thrift::TProcessor> getProcessor(
|
||||||
const ::apache::thrift::TConnectionInfo& connInfo);
|
const ::apache::thrift::TConnectionInfo& connInfo);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
::boost::shared_ptr<QueryTeleServiceIfFactory> handlerFactory_;
|
::std::shared_ptr<QueryTeleServiceIfFactory> handlerFactory_;
|
||||||
};
|
};
|
||||||
|
|
||||||
class QueryTeleServiceMultiface : virtual public QueryTeleServiceIf
|
class QueryTeleServiceMultiface : virtual public QueryTeleServiceIf
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
QueryTeleServiceMultiface(std::vector<boost::shared_ptr<QueryTeleServiceIf> >& ifaces) : ifaces_(ifaces)
|
QueryTeleServiceMultiface(std::vector<std::shared_ptr<QueryTeleServiceIf> >& ifaces) : ifaces_(ifaces)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
virtual ~QueryTeleServiceMultiface()
|
virtual ~QueryTeleServiceMultiface()
|
||||||
@@ -459,11 +460,11 @@ class QueryTeleServiceMultiface : virtual public QueryTeleServiceIf
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
std::vector<boost::shared_ptr<QueryTeleServiceIf> > ifaces_;
|
std::vector<std::shared_ptr<QueryTeleServiceIf> > ifaces_;
|
||||||
QueryTeleServiceMultiface()
|
QueryTeleServiceMultiface()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
void add(boost::shared_ptr<QueryTeleServiceIf> iface)
|
void add(std::shared_ptr<QueryTeleServiceIf> iface)
|
||||||
{
|
{
|
||||||
ifaces_.push_back(iface);
|
ifaces_.push_back(iface);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,7 +11,6 @@
|
|||||||
#include <thrift/protocol/TProtocol.h>
|
#include <thrift/protocol/TProtocol.h>
|
||||||
#include <thrift/transport/TTransport.h>
|
#include <thrift/transport/TTransport.h>
|
||||||
|
|
||||||
#include <thrift/cxxfunctional.h>
|
|
||||||
|
|
||||||
namespace querytele
|
namespace querytele
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -22,7 +22,6 @@ using namespace std;
|
|||||||
|
|
||||||
#define BOOST_DISABLE_ASSERTS
|
#define BOOST_DISABLE_ASSERTS
|
||||||
#include <boost/thread.hpp>
|
#include <boost/thread.hpp>
|
||||||
#include <boost/shared_ptr.hpp>
|
|
||||||
|
|
||||||
#include "thrift/transport/TSocket.h"
|
#include "thrift/transport/TSocket.h"
|
||||||
#include "thrift/transport/TBufferTransports.h"
|
#include "thrift/transport/TBufferTransports.h"
|
||||||
@@ -59,9 +58,9 @@ TsTeleQueue<querytele::ImportTele> itQueue;
|
|||||||
volatile bool isInited = false;
|
volatile bool isInited = false;
|
||||||
boost::mutex initMux;
|
boost::mutex initMux;
|
||||||
|
|
||||||
boost::shared_ptr<att::TSocket> fSocket;
|
std::shared_ptr<att::TSocket> fSocket;
|
||||||
boost::shared_ptr<att::TBufferedTransport> fTransport;
|
std::shared_ptr<att::TBufferedTransport> fTransport;
|
||||||
boost::shared_ptr<atp::TBinaryProtocol> fProtocol;
|
std::shared_ptr<atp::TBinaryProtocol> fProtocol;
|
||||||
|
|
||||||
querytele::StepTele gLastStep;
|
querytele::StepTele gLastStep;
|
||||||
|
|
||||||
|
|||||||
@@ -1,21 +0,0 @@
|
|||||||
|
|
||||||
include_directories( ${ENGINE_COMMON_INCLUDES} )
|
|
||||||
|
|
||||||
|
|
||||||
########### next target ###############
|
|
||||||
|
|
||||||
set(thrift_LIB_SRCS
|
|
||||||
thrift/Thrift.cpp
|
|
||||||
thrift/server/TSimpleServer.cpp
|
|
||||||
thrift/transport/TSocket.cpp
|
|
||||||
thrift/transport/TServerSocket.cpp
|
|
||||||
thrift/transport/TBufferTransports.cpp
|
|
||||||
thrift/TApplicationException.cpp)
|
|
||||||
|
|
||||||
add_definitions(-DTHRIFT_SQUELCH_CONSOLE_OUTPUT)
|
|
||||||
|
|
||||||
add_library(thrift SHARED ${thrift_LIB_SRCS})
|
|
||||||
add_dependencies(thrift external_boost)
|
|
||||||
|
|
||||||
install(TARGETS thrift DESTINATION ${ENGINE_LIBDIR} COMPONENT columnstore-engine)
|
|
||||||
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
This is Apache Thrift 0.9.1
|
|
||||||
|
|
||||||
Actually, this is just the bits and pieces of the API necessary to work
|
|
||||||
with InfiniDB. It is provided as a convenience to source builders so
|
|
||||||
that they don't have to find and install Thrift
|
|
||||||
|
|
||||||
@@ -1,102 +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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <thrift/TApplicationException.h>
|
|
||||||
#include <thrift/protocol/TProtocol.h>
|
|
||||||
|
|
||||||
namespace apache
|
|
||||||
{
|
|
||||||
namespace thrift
|
|
||||||
{
|
|
||||||
|
|
||||||
uint32_t TApplicationException::read(apache::thrift::protocol::TProtocol* iprot)
|
|
||||||
{
|
|
||||||
uint32_t xfer = 0;
|
|
||||||
std::string fname;
|
|
||||||
apache::thrift::protocol::TType ftype;
|
|
||||||
int16_t fid;
|
|
||||||
|
|
||||||
xfer += iprot->readStructBegin(fname);
|
|
||||||
|
|
||||||
while (true)
|
|
||||||
{
|
|
||||||
xfer += iprot->readFieldBegin(fname, ftype, fid);
|
|
||||||
|
|
||||||
if (ftype == apache::thrift::protocol::T_STOP)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (fid)
|
|
||||||
{
|
|
||||||
case 1:
|
|
||||||
if (ftype == apache::thrift::protocol::T_STRING)
|
|
||||||
{
|
|
||||||
xfer += iprot->readString(message_);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
xfer += iprot->skip(ftype);
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 2:
|
|
||||||
if (ftype == apache::thrift::protocol::T_I32)
|
|
||||||
{
|
|
||||||
int32_t type;
|
|
||||||
xfer += iprot->readI32(type);
|
|
||||||
type_ = (TApplicationExceptionType)type;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
xfer += iprot->skip(ftype);
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
xfer += iprot->skip(ftype);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
xfer += iprot->readFieldEnd();
|
|
||||||
}
|
|
||||||
|
|
||||||
xfer += iprot->readStructEnd();
|
|
||||||
return xfer;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t TApplicationException::write(apache::thrift::protocol::TProtocol* oprot) const
|
|
||||||
{
|
|
||||||
uint32_t xfer = 0;
|
|
||||||
xfer += oprot->writeStructBegin("TApplicationException");
|
|
||||||
xfer += oprot->writeFieldBegin("message", apache::thrift::protocol::T_STRING, 1);
|
|
||||||
xfer += oprot->writeString(message_);
|
|
||||||
xfer += oprot->writeFieldEnd();
|
|
||||||
xfer += oprot->writeFieldBegin("type", apache::thrift::protocol::T_I32, 2);
|
|
||||||
xfer += oprot->writeI32(type_);
|
|
||||||
xfer += oprot->writeFieldEnd();
|
|
||||||
xfer += oprot->writeFieldStop();
|
|
||||||
xfer += oprot->writeStructEnd();
|
|
||||||
return xfer;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
} // apache::thrift
|
|
||||||
@@ -1,149 +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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <thrift/Thrift.h>
|
|
||||||
|
|
||||||
|
|
||||||
namespace apache
|
|
||||||
{
|
|
||||||
namespace thrift
|
|
||||||
{
|
|
||||||
|
|
||||||
namespace protocol
|
|
||||||
{
|
|
||||||
class TProtocol;
|
|
||||||
}
|
|
||||||
|
|
||||||
class TApplicationException : public TException
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Error codes for the various types of exceptions.
|
|
||||||
*/
|
|
||||||
enum TApplicationExceptionType
|
|
||||||
{
|
|
||||||
UNKNOWN = 0,
|
|
||||||
UNKNOWN_METHOD = 1,
|
|
||||||
INVALID_MESSAGE_TYPE = 2,
|
|
||||||
WRONG_METHOD_NAME = 3,
|
|
||||||
BAD_SEQUENCE_ID = 4,
|
|
||||||
MISSING_RESULT = 5,
|
|
||||||
INTERNAL_ERROR = 6,
|
|
||||||
PROTOCOL_ERROR = 7,
|
|
||||||
INVALID_TRANSFORM = 8,
|
|
||||||
INVALID_PROTOCOL = 9,
|
|
||||||
UNSUPPORTED_CLIENT_TYPE = 10
|
|
||||||
};
|
|
||||||
|
|
||||||
TApplicationException() :
|
|
||||||
TException(),
|
|
||||||
type_(UNKNOWN) {}
|
|
||||||
|
|
||||||
TApplicationException(TApplicationExceptionType type) :
|
|
||||||
TException(),
|
|
||||||
type_(type) {}
|
|
||||||
|
|
||||||
TApplicationException(const std::string& message) :
|
|
||||||
TException(message),
|
|
||||||
type_(UNKNOWN) {}
|
|
||||||
|
|
||||||
TApplicationException(TApplicationExceptionType type,
|
|
||||||
const std::string& message) :
|
|
||||||
TException(message),
|
|
||||||
type_(type) {}
|
|
||||||
|
|
||||||
virtual ~TApplicationException() throw() {}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns an error code that provides information about the type of error
|
|
||||||
* that has occurred.
|
|
||||||
*
|
|
||||||
* @return Error code
|
|
||||||
*/
|
|
||||||
TApplicationExceptionType getType()
|
|
||||||
{
|
|
||||||
return type_;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual const char* what() const throw()
|
|
||||||
{
|
|
||||||
if (message_.empty())
|
|
||||||
{
|
|
||||||
switch (type_)
|
|
||||||
{
|
|
||||||
case UNKNOWN :
|
|
||||||
return "TApplicationException: Unknown application exception";
|
|
||||||
|
|
||||||
case UNKNOWN_METHOD :
|
|
||||||
return "TApplicationException: Unknown method";
|
|
||||||
|
|
||||||
case INVALID_MESSAGE_TYPE :
|
|
||||||
return "TApplicationException: Invalid message type";
|
|
||||||
|
|
||||||
case WRONG_METHOD_NAME :
|
|
||||||
return "TApplicationException: Wrong method name";
|
|
||||||
|
|
||||||
case BAD_SEQUENCE_ID :
|
|
||||||
return "TApplicationException: Bad sequence identifier";
|
|
||||||
|
|
||||||
case MISSING_RESULT :
|
|
||||||
return "TApplicationException: Missing result";
|
|
||||||
|
|
||||||
case INTERNAL_ERROR :
|
|
||||||
return "TApplicationException: Internal error";
|
|
||||||
|
|
||||||
case PROTOCOL_ERROR :
|
|
||||||
return "TApplicationException: Protocol error";
|
|
||||||
|
|
||||||
case INVALID_TRANSFORM :
|
|
||||||
return "TApplicationException: Invalid transform";
|
|
||||||
|
|
||||||
case INVALID_PROTOCOL :
|
|
||||||
return "TApplicationException: Invalid protocol";
|
|
||||||
|
|
||||||
case UNSUPPORTED_CLIENT_TYPE :
|
|
||||||
return "TApplicationException: Unsupported client type";
|
|
||||||
|
|
||||||
default :
|
|
||||||
return "TApplicationException: (Invalid exception type)";
|
|
||||||
};
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return message_.c_str();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t read(protocol::TProtocol* iprot);
|
|
||||||
uint32_t write(protocol::TProtocol* oprot) const;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
/**
|
|
||||||
* Error code
|
|
||||||
*/
|
|
||||||
TApplicationExceptionType type_;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
} // apache::thrift
|
|
||||||
|
|
||||||
@@ -1,154 +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.
|
|
||||||
*/
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <thrift/TProcessor.h>
|
|
||||||
|
|
||||||
namespace apache
|
|
||||||
{
|
|
||||||
namespace thrift
|
|
||||||
{
|
|
||||||
|
|
||||||
/**
|
|
||||||
* TDispatchProcessor is a helper class to parse the message header then call
|
|
||||||
* another function to dispatch based on the function name.
|
|
||||||
*
|
|
||||||
* Subclasses must implement dispatchCall() to dispatch on the function name.
|
|
||||||
*/
|
|
||||||
template <class Protocol_>
|
|
||||||
class TDispatchProcessorT : public TProcessor
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
virtual bool process(boost::shared_ptr<protocol::TProtocol> in,
|
|
||||||
boost::shared_ptr<protocol::TProtocol> out,
|
|
||||||
void* connectionContext)
|
|
||||||
{
|
|
||||||
protocol::TProtocol* inRaw = in.get();
|
|
||||||
protocol::TProtocol* outRaw = out.get();
|
|
||||||
|
|
||||||
// Try to dynamic cast to the template protocol type
|
|
||||||
Protocol_* specificIn = dynamic_cast<Protocol_*>(inRaw);
|
|
||||||
Protocol_* specificOut = dynamic_cast<Protocol_*>(outRaw);
|
|
||||||
|
|
||||||
if (specificIn && specificOut)
|
|
||||||
{
|
|
||||||
return processFast(specificIn, specificOut, connectionContext);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Log the fact that we have to use the slow path
|
|
||||||
T_GENERIC_PROTOCOL(this, inRaw, specificIn);
|
|
||||||
T_GENERIC_PROTOCOL(this, outRaw, specificOut);
|
|
||||||
|
|
||||||
std::string fname;
|
|
||||||
protocol::TMessageType mtype;
|
|
||||||
int32_t seqid;
|
|
||||||
inRaw->readMessageBegin(fname, mtype, seqid);
|
|
||||||
|
|
||||||
// If this doesn't look like a valid call, log an error and return false so
|
|
||||||
// that the server will close the connection.
|
|
||||||
//
|
|
||||||
// (The old generated processor code used to try to skip a T_STRUCT and
|
|
||||||
// continue. However, that seems unsafe.)
|
|
||||||
if (mtype != protocol::T_CALL && mtype != protocol::T_ONEWAY)
|
|
||||||
{
|
|
||||||
GlobalOutput.printf("received invalid message type %d from client",
|
|
||||||
mtype);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return this->dispatchCall(inRaw, outRaw, fname, seqid, connectionContext);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
bool processFast(Protocol_* in, Protocol_* out, void* connectionContext)
|
|
||||||
{
|
|
||||||
std::string fname;
|
|
||||||
protocol::TMessageType mtype;
|
|
||||||
int32_t seqid;
|
|
||||||
in->readMessageBegin(fname, mtype, seqid);
|
|
||||||
|
|
||||||
if (mtype != protocol::T_CALL && mtype != protocol::T_ONEWAY)
|
|
||||||
{
|
|
||||||
GlobalOutput.printf("received invalid message type %d from client",
|
|
||||||
mtype);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return this->dispatchCallTemplated(in, out, fname,
|
|
||||||
seqid, connectionContext);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* dispatchCall() methods must be implemented by subclasses
|
|
||||||
*/
|
|
||||||
virtual bool dispatchCall(apache::thrift::protocol::TProtocol* in,
|
|
||||||
apache::thrift::protocol::TProtocol* out,
|
|
||||||
const std::string& fname, int32_t seqid,
|
|
||||||
void* callContext) = 0;
|
|
||||||
|
|
||||||
virtual bool dispatchCallTemplated(Protocol_* in, Protocol_* out,
|
|
||||||
const std::string& fname, int32_t seqid,
|
|
||||||
void* callContext) = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Non-templatized version of TDispatchProcessor, that doesn't bother trying to
|
|
||||||
* perform a dynamic_cast.
|
|
||||||
*/
|
|
||||||
class TDispatchProcessor : public TProcessor
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
virtual bool process(boost::shared_ptr<protocol::TProtocol> in,
|
|
||||||
boost::shared_ptr<protocol::TProtocol> out,
|
|
||||||
void* connectionContext)
|
|
||||||
{
|
|
||||||
std::string fname;
|
|
||||||
protocol::TMessageType mtype;
|
|
||||||
int32_t seqid;
|
|
||||||
in->readMessageBegin(fname, mtype, seqid);
|
|
||||||
|
|
||||||
if (mtype != protocol::T_CALL && mtype != protocol::T_ONEWAY)
|
|
||||||
{
|
|
||||||
GlobalOutput.printf("received invalid message type %d from client",
|
|
||||||
mtype);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return dispatchCall(in.get(), out.get(), fname, seqid, connectionContext);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
virtual bool dispatchCall(apache::thrift::protocol::TProtocol* in,
|
|
||||||
apache::thrift::protocol::TProtocol* out,
|
|
||||||
const std::string& fname, int32_t seqid,
|
|
||||||
void* callContext) = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Specialize TDispatchProcessorT for TProtocol and TDummyProtocol just to use
|
|
||||||
// the generic TDispatchProcessor.
|
|
||||||
template <>
|
|
||||||
class TDispatchProcessorT<protocol::TDummyProtocol> :
|
|
||||||
public TDispatchProcessor {};
|
|
||||||
template <>
|
|
||||||
class TDispatchProcessorT<protocol::TProtocol> :
|
|
||||||
public TDispatchProcessor {};
|
|
||||||
|
|
||||||
}
|
|
||||||
} // apache::thrift
|
|
||||||
|
|
||||||
@@ -1,191 +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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <thrift/thrift-config.h>
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Contains utility macros for debugging and logging.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <time.h>
|
|
||||||
|
|
||||||
#ifdef HAVE_STDINT_H
|
|
||||||
#include <stdint.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/**
|
|
||||||
* T_GLOBAL_DEBUGGING_LEVEL = 0: all debugging turned off, debug macros undefined
|
|
||||||
* T_GLOBAL_DEBUGGING_LEVEL = 1: all debugging turned on
|
|
||||||
*/
|
|
||||||
#define T_GLOBAL_DEBUGGING_LEVEL 0
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* T_GLOBAL_LOGGING_LEVEL = 0: all logging turned off, logging macros undefined
|
|
||||||
* T_GLOBAL_LOGGING_LEVEL = 1: all logging turned on
|
|
||||||
*/
|
|
||||||
#define T_GLOBAL_LOGGING_LEVEL 1
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Standard wrapper around fprintf what will prefix the file name and line
|
|
||||||
* number to the line. Uses T_GLOBAL_DEBUGGING_LEVEL to control whether it is
|
|
||||||
* turned on or off.
|
|
||||||
*
|
|
||||||
* @param format_string
|
|
||||||
*/
|
|
||||||
#if T_GLOBAL_DEBUGGING_LEVEL > 0
|
|
||||||
#define T_DEBUG(format_string,...) \
|
|
||||||
if (T_GLOBAL_DEBUGGING_LEVEL > 0) { \
|
|
||||||
fprintf(stderr,"[%s,%d] " format_string " \n", __FILE__, __LINE__,##__VA_ARGS__); \
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
#define T_DEBUG(format_string,...)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* analagous to T_DEBUG but also prints the time
|
|
||||||
*
|
|
||||||
* @param string format_string input: printf style format string
|
|
||||||
*/
|
|
||||||
#if T_GLOBAL_DEBUGGING_LEVEL > 0
|
|
||||||
#define T_DEBUG_T(format_string,...) \
|
|
||||||
{ \
|
|
||||||
if (T_GLOBAL_DEBUGGING_LEVEL > 0) { \
|
|
||||||
time_t now; \
|
|
||||||
char dbgtime[26] ; \
|
|
||||||
time(&now); \
|
|
||||||
THRIFT_CTIME_R(&now, dbgtime); \
|
|
||||||
dbgtime[24] = '\0'; \
|
|
||||||
fprintf(stderr,"[%s,%d] [%s] " format_string " \n", __FILE__, __LINE__,dbgtime,##__VA_ARGS__); \
|
|
||||||
} \
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
#define T_DEBUG_T(format_string,...)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* analagous to T_DEBUG but uses input level to determine whether or not the string
|
|
||||||
* should be logged.
|
|
||||||
*
|
|
||||||
* @param int level: specified debug level
|
|
||||||
* @param string format_string input: format string
|
|
||||||
*/
|
|
||||||
#define T_DEBUG_L(level, format_string,...) \
|
|
||||||
if ((level) > 0) { \
|
|
||||||
fprintf(stderr,"[%s,%d] " format_string " \n", __FILE__, __LINE__,##__VA_ARGS__); \
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Explicit error logging. Prints time, file name and line number
|
|
||||||
*
|
|
||||||
* @param string format_string input: printf style format string
|
|
||||||
*/
|
|
||||||
#define T_ERROR(format_string,...) \
|
|
||||||
{ \
|
|
||||||
time_t now; \
|
|
||||||
char dbgtime[26] ; \
|
|
||||||
time(&now); \
|
|
||||||
THRIFT_CTIME_R(&now, dbgtime); \
|
|
||||||
dbgtime[24] = '\0'; \
|
|
||||||
fprintf(stderr,"[%s,%d] [%s] ERROR: " format_string " \n", __FILE__, __LINE__,dbgtime,##__VA_ARGS__); \
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Analagous to T_ERROR, additionally aborting the process.
|
|
||||||
* WARNING: macro calls abort(), ending program execution
|
|
||||||
*
|
|
||||||
* @param string format_string input: printf style format string
|
|
||||||
*/
|
|
||||||
#define T_ERROR_ABORT(format_string,...) \
|
|
||||||
{ \
|
|
||||||
time_t now; \
|
|
||||||
char dbgtime[26] ; \
|
|
||||||
time(&now); \
|
|
||||||
THRIFT_CTIME_R(&now, dbgtime); \
|
|
||||||
dbgtime[24] = '\0'; \
|
|
||||||
fprintf(stderr,"[%s,%d] [%s] ERROR: Going to abort " format_string " \n", __FILE__, __LINE__,dbgtime,##__VA_ARGS__); \
|
|
||||||
exit(1); \
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Log input message
|
|
||||||
*
|
|
||||||
* @param string format_string input: printf style format string
|
|
||||||
*/
|
|
||||||
#if T_GLOBAL_LOGGING_LEVEL > 0
|
|
||||||
#define T_LOG_OPER(format_string,...) \
|
|
||||||
{ \
|
|
||||||
if (T_GLOBAL_LOGGING_LEVEL > 0) { \
|
|
||||||
time_t now; \
|
|
||||||
char dbgtime[26] ; \
|
|
||||||
time(&now); \
|
|
||||||
THRIFT_CTIME_R(&now, dbgtime); \
|
|
||||||
dbgtime[24] = '\0'; \
|
|
||||||
fprintf(stderr,"[%s] " format_string " \n", dbgtime,##__VA_ARGS__); \
|
|
||||||
} \
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
#define T_LOG_OPER(format_string,...)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* T_GLOBAL_DEBUG_VIRTUAL = 0 or unset: normal operation,
|
|
||||||
* virtual call debug messages disabled
|
|
||||||
* T_GLOBAL_DEBUG_VIRTUAL = 1: log a debug messages whenever an
|
|
||||||
* avoidable virtual call is made
|
|
||||||
* T_GLOBAL_DEBUG_VIRTUAL = 2: record detailed info that can be
|
|
||||||
* printed by calling
|
|
||||||
* apache::thrift::profile_print_info()
|
|
||||||
*/
|
|
||||||
#if T_GLOBAL_DEBUG_VIRTUAL > 1
|
|
||||||
#define T_VIRTUAL_CALL() \
|
|
||||||
::apache::thrift::profile_virtual_call(typeid(*this))
|
|
||||||
#define T_GENERIC_PROTOCOL(template_class, generic_prot, specific_prot) \
|
|
||||||
do { \
|
|
||||||
if (!(specific_prot)) { \
|
|
||||||
::apache::thrift::profile_generic_protocol( \
|
|
||||||
typeid(*template_class), typeid(*generic_prot)); \
|
|
||||||
} \
|
|
||||||
} while (0)
|
|
||||||
#elif T_GLOBAL_DEBUG_VIRTUAL == 1
|
|
||||||
#define T_VIRTUAL_CALL() \
|
|
||||||
fprintf(stderr,"[%s,%d] virtual call\n", __FILE__, __LINE__)
|
|
||||||
#define T_GENERIC_PROTOCOL(template_class, generic_prot, specific_prot) \
|
|
||||||
do { \
|
|
||||||
if (!(specific_prot)) { \
|
|
||||||
fprintf(stderr, \
|
|
||||||
"[%s,%d] failed to cast to specific protocol type\n", \
|
|
||||||
__FILE__, __LINE__); \
|
|
||||||
} \
|
|
||||||
} while (0)
|
|
||||||
#else
|
|
||||||
#define T_VIRTUAL_CALL()
|
|
||||||
#define T_GENERIC_PROTOCOL(template_class, generic_prot, specific_prot)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
@@ -1,262 +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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include <thrift/protocol/TProtocol.h>
|
|
||||||
#include <boost/shared_ptr.hpp>
|
|
||||||
|
|
||||||
namespace apache
|
|
||||||
{
|
|
||||||
namespace thrift
|
|
||||||
{
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Virtual interface class that can handle events from the processor. To
|
|
||||||
* use this you should subclass it and implement the methods that you care
|
|
||||||
* about. Your subclass can also store local data that you may care about,
|
|
||||||
* such as additional "arguments" to these methods (stored in the object
|
|
||||||
* instance's state).
|
|
||||||
*/
|
|
||||||
class TProcessorEventHandler
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
virtual ~TProcessorEventHandler() {}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called before calling other callback methods.
|
|
||||||
* Expected to return some sort of context object.
|
|
||||||
* The return value is passed to all other callbacks
|
|
||||||
* for that function invocation.
|
|
||||||
*/
|
|
||||||
virtual void* getContext(const char* fn_name, void* serverContext)
|
|
||||||
{
|
|
||||||
(void) fn_name;
|
|
||||||
(void) serverContext;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Expected to free resources associated with a context.
|
|
||||||
*/
|
|
||||||
virtual void freeContext(void* ctx, const char* fn_name)
|
|
||||||
{
|
|
||||||
(void) ctx;
|
|
||||||
(void) fn_name;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called before reading arguments.
|
|
||||||
*/
|
|
||||||
virtual void preRead(void* ctx, const char* fn_name)
|
|
||||||
{
|
|
||||||
(void) ctx;
|
|
||||||
(void) fn_name;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called between reading arguments and calling the handler.
|
|
||||||
*/
|
|
||||||
virtual void postRead(void* ctx, const char* fn_name, uint32_t bytes)
|
|
||||||
{
|
|
||||||
(void) ctx;
|
|
||||||
(void) fn_name;
|
|
||||||
(void) bytes;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called between calling the handler and writing the response.
|
|
||||||
*/
|
|
||||||
virtual void preWrite(void* ctx, const char* fn_name)
|
|
||||||
{
|
|
||||||
(void) ctx;
|
|
||||||
(void) fn_name;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called after writing the response.
|
|
||||||
*/
|
|
||||||
virtual void postWrite(void* ctx, const char* fn_name, uint32_t bytes)
|
|
||||||
{
|
|
||||||
(void) ctx;
|
|
||||||
(void) fn_name;
|
|
||||||
(void) bytes;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called when an async function call completes successfully.
|
|
||||||
*/
|
|
||||||
virtual void asyncComplete(void* ctx, const char* fn_name)
|
|
||||||
{
|
|
||||||
(void) ctx;
|
|
||||||
(void) fn_name;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called if the handler throws an undeclared exception.
|
|
||||||
*/
|
|
||||||
virtual void handlerError(void* ctx, const char* fn_name)
|
|
||||||
{
|
|
||||||
(void) ctx;
|
|
||||||
(void) fn_name;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
TProcessorEventHandler() {}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A helper class used by the generated code to free each context.
|
|
||||||
*/
|
|
||||||
class TProcessorContextFreer
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
TProcessorContextFreer(TProcessorEventHandler* handler, void* context, const char* method) :
|
|
||||||
handler_(handler), context_(context), method_(method) {}
|
|
||||||
~TProcessorContextFreer()
|
|
||||||
{
|
|
||||||
if (handler_ != NULL) handler_->freeContext(context_, method_);
|
|
||||||
}
|
|
||||||
void unregister()
|
|
||||||
{
|
|
||||||
handler_ = NULL;
|
|
||||||
}
|
|
||||||
private:
|
|
||||||
apache::thrift::TProcessorEventHandler* handler_;
|
|
||||||
void* context_;
|
|
||||||
const char* method_;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A processor is a generic object that acts upon two streams of data, one
|
|
||||||
* an input and the other an output. The definition of this object is loose,
|
|
||||||
* though the typical case is for some sort of server that either generates
|
|
||||||
* responses to an input stream or forwards data from one pipe onto another.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
class TProcessor
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
virtual ~TProcessor() {}
|
|
||||||
|
|
||||||
virtual bool process(boost::shared_ptr<protocol::TProtocol> in,
|
|
||||||
boost::shared_ptr<protocol::TProtocol> out,
|
|
||||||
void* connectionContext) = 0;
|
|
||||||
|
|
||||||
bool process(boost::shared_ptr<apache::thrift::protocol::TProtocol> io,
|
|
||||||
void* connectionContext)
|
|
||||||
{
|
|
||||||
return process(io, io, connectionContext);
|
|
||||||
}
|
|
||||||
|
|
||||||
boost::shared_ptr<TProcessorEventHandler> getEventHandler()
|
|
||||||
{
|
|
||||||
return eventHandler_;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setEventHandler(boost::shared_ptr<TProcessorEventHandler> eventHandler)
|
|
||||||
{
|
|
||||||
eventHandler_ = eventHandler;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
TProcessor() {}
|
|
||||||
|
|
||||||
boost::shared_ptr<TProcessorEventHandler> eventHandler_;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This is a helper class to allow boost::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
|
|
||||||
* pointers, and factory->releaseHandler() must be called when the handler is
|
|
||||||
* no longer needed.
|
|
||||||
*
|
|
||||||
* A ReleaseHandler object can be instantiated and passed as the second
|
|
||||||
* parameter to a shared_ptr, so that factory->releaseHandler() will be called
|
|
||||||
* when the object is no longer needed, instead of deleting the pointer.
|
|
||||||
*/
|
|
||||||
template<typename HandlerFactory_>
|
|
||||||
class ReleaseHandler
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
ReleaseHandler(const boost::shared_ptr<HandlerFactory_>& handlerFactory) :
|
|
||||||
handlerFactory_(handlerFactory) {}
|
|
||||||
|
|
||||||
void operator()(typename HandlerFactory_::Handler* handler)
|
|
||||||
{
|
|
||||||
if (handler)
|
|
||||||
{
|
|
||||||
handlerFactory_->releaseHandler(handler);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
boost::shared_ptr<HandlerFactory_> handlerFactory_;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct TConnectionInfo
|
|
||||||
{
|
|
||||||
// The input and output protocols
|
|
||||||
boost::shared_ptr<protocol::TProtocol> input;
|
|
||||||
boost::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;
|
|
||||||
};
|
|
||||||
|
|
||||||
class TProcessorFactory
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
virtual ~TProcessorFactory() {}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the TProcessor to use for a particular connection.
|
|
||||||
*
|
|
||||||
* This method is always invoked in the same thread that the connection was
|
|
||||||
* 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;
|
|
||||||
};
|
|
||||||
|
|
||||||
class TSingletonProcessorFactory : public TProcessorFactory
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
TSingletonProcessorFactory(boost::shared_ptr<TProcessor> processor) :
|
|
||||||
processor_(processor) {}
|
|
||||||
|
|
||||||
boost::shared_ptr<TProcessor> getProcessor(const TConnectionInfo&)
|
|
||||||
{
|
|
||||||
return processor_;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
boost::shared_ptr<TProcessor> processor_;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
} // apache::thrift
|
|
||||||
|
|
||||||
@@ -1,110 +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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <cstring>
|
|
||||||
#include <thrift/protocol/TProtocol.h>
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Local Reflection is a blanket term referring to the the structure
|
|
||||||
* and generation of this particular representation of Thrift types.
|
|
||||||
* (It is called local because it cannot be serialized by Thrift).
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace apache
|
|
||||||
{
|
|
||||||
namespace thrift
|
|
||||||
{
|
|
||||||
namespace reflection
|
|
||||||
{
|
|
||||||
namespace local
|
|
||||||
{
|
|
||||||
|
|
||||||
using apache::thrift::protocol::TType;
|
|
||||||
|
|
||||||
// We include this many bytes of the structure's fingerprint when serializing
|
|
||||||
// a top-level structure. Long enough to make collisions unlikely, short
|
|
||||||
// enough to not significantly affect the amount of memory used.
|
|
||||||
const int FP_PREFIX_LEN = 4;
|
|
||||||
|
|
||||||
struct FieldMeta
|
|
||||||
{
|
|
||||||
int16_t tag;
|
|
||||||
bool is_optional;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct TypeSpec
|
|
||||||
{
|
|
||||||
TType ttype;
|
|
||||||
uint8_t fp_prefix[FP_PREFIX_LEN];
|
|
||||||
|
|
||||||
// Use an anonymous union here so we can fit two TypeSpecs in one cache line.
|
|
||||||
union
|
|
||||||
{
|
|
||||||
struct
|
|
||||||
{
|
|
||||||
// Use parallel arrays here for denser packing (of the arrays).
|
|
||||||
FieldMeta* metas;
|
|
||||||
TypeSpec** specs;
|
|
||||||
} tstruct;
|
|
||||||
struct
|
|
||||||
{
|
|
||||||
TypeSpec* subtype1;
|
|
||||||
TypeSpec* subtype2;
|
|
||||||
} tcontainer;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Static initialization of unions isn't really possible,
|
|
||||||
// so take the plunge and use constructors.
|
|
||||||
// Hopefully they'll be evaluated at compile time.
|
|
||||||
|
|
||||||
TypeSpec(TType ttype) : ttype(ttype)
|
|
||||||
{
|
|
||||||
std::memset(fp_prefix, 0, FP_PREFIX_LEN);
|
|
||||||
}
|
|
||||||
|
|
||||||
TypeSpec(TType ttype,
|
|
||||||
const uint8_t* fingerprint,
|
|
||||||
FieldMeta* metas,
|
|
||||||
TypeSpec** specs) :
|
|
||||||
ttype(ttype)
|
|
||||||
{
|
|
||||||
std::memcpy(fp_prefix, fingerprint, FP_PREFIX_LEN);
|
|
||||||
tstruct.metas = metas;
|
|
||||||
tstruct.specs = specs;
|
|
||||||
}
|
|
||||||
|
|
||||||
TypeSpec(TType ttype, TypeSpec* subtype1, TypeSpec* subtype2) :
|
|
||||||
ttype(ttype)
|
|
||||||
{
|
|
||||||
std::memset(fp_prefix, 0, FP_PREFIX_LEN);
|
|
||||||
tcontainer.subtype1 = subtype1;
|
|
||||||
tcontainer.subtype2 = subtype2;
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} // apache::thrift::reflection::local
|
|
||||||
|
|
||||||
@@ -1,145 +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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <thrift/Thrift.h>
|
|
||||||
#include <cstring>
|
|
||||||
#include <cstdlib>
|
|
||||||
#include <boost/lexical_cast.hpp>
|
|
||||||
#include <stdarg.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
namespace apache
|
|
||||||
{
|
|
||||||
namespace thrift
|
|
||||||
{
|
|
||||||
|
|
||||||
TOutput GlobalOutput;
|
|
||||||
|
|
||||||
void TOutput::printf(const char* message, ...)
|
|
||||||
{
|
|
||||||
#ifndef THRIFT_SQUELCH_CONSOLE_OUTPUT
|
|
||||||
// Try to reduce heap usage, even if printf is called rarely.
|
|
||||||
static const int STACK_BUF_SIZE = 256;
|
|
||||||
char stack_buf[STACK_BUF_SIZE];
|
|
||||||
va_list ap;
|
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
|
||||||
va_start(ap, message);
|
|
||||||
int need = _vscprintf(message, ap);
|
|
||||||
va_end(ap);
|
|
||||||
|
|
||||||
if (need < STACK_BUF_SIZE)
|
|
||||||
{
|
|
||||||
va_start(ap, message);
|
|
||||||
vsnprintf_s(stack_buf, STACK_BUF_SIZE, _TRUNCATE, message, ap);
|
|
||||||
va_end(ap);
|
|
||||||
f_(stack_buf);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
#else
|
|
||||||
va_start(ap, message);
|
|
||||||
int need = vsnprintf(stack_buf, STACK_BUF_SIZE, message, ap);
|
|
||||||
va_end(ap);
|
|
||||||
|
|
||||||
if (need < STACK_BUF_SIZE)
|
|
||||||
{
|
|
||||||
f_(stack_buf);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
char* heap_buf = (char*)malloc((need + 1) * sizeof(char));
|
|
||||||
|
|
||||||
if (heap_buf == NULL)
|
|
||||||
{
|
|
||||||
#ifdef _MSC_VER
|
|
||||||
va_start(ap, message);
|
|
||||||
vsnprintf_s(stack_buf, STACK_BUF_SIZE, _TRUNCATE, message, ap);
|
|
||||||
va_end(ap);
|
|
||||||
#endif
|
|
||||||
// Malloc failed. We might as well print the stack buffer.
|
|
||||||
f_(stack_buf);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
va_start(ap, message);
|
|
||||||
int rval = vsnprintf(heap_buf, need + 1, message, ap);
|
|
||||||
va_end(ap);
|
|
||||||
|
|
||||||
// TODO(shigin): inform user
|
|
||||||
if (rval != -1)
|
|
||||||
{
|
|
||||||
f_(heap_buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
free(heap_buf);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void TOutput::errorTimeWrapper(const char* msg)
|
|
||||||
{
|
|
||||||
#ifndef THRIFT_SQUELCH_CONSOLE_OUTPUT
|
|
||||||
time_t now;
|
|
||||||
char dbgtime[26];
|
|
||||||
time(&now);
|
|
||||||
THRIFT_CTIME_R(&now, dbgtime);
|
|
||||||
dbgtime[24] = 0;
|
|
||||||
fprintf(stderr, "Thrift: %s %s\n", dbgtime, msg);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void TOutput::perror(const char* message, int errno_copy)
|
|
||||||
{
|
|
||||||
std::string out = message + 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);
|
|
||||||
#else // HAVE_STRERROR_R
|
|
||||||
|
|
||||||
char b_errbuf[1024] = { '\0' };
|
|
||||||
#ifdef STRERROR_R_CHAR_P
|
|
||||||
char* b_error = strerror_r(errno_copy, b_errbuf, sizeof(b_errbuf));
|
|
||||||
#else
|
|
||||||
char* b_error = b_errbuf;
|
|
||||||
int rv = strerror_r(errno_copy, b_errbuf, sizeof(b_errbuf));
|
|
||||||
|
|
||||||
if (rv == -1)
|
|
||||||
{
|
|
||||||
// strerror_r failed. omgwtfbbq.
|
|
||||||
return "XSI-compliant strerror_r() failed with errno = " +
|
|
||||||
boost::lexical_cast<std::string>(errno_copy);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
// Can anyone prove that explicit cast is probably not necessary
|
|
||||||
// to ensure that the string object is constructed before
|
|
||||||
// b_error becomes invalid?
|
|
||||||
return std::string(b_error);
|
|
||||||
|
|
||||||
#endif // HAVE_STRERROR_R
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
} // apache::thrift
|
|
||||||
@@ -1,226 +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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <thrift/transport/PlatformSocket.h>
|
|
||||||
|
|
||||||
#include <thrift/thrift-config.h>
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <assert.h>
|
|
||||||
|
|
||||||
#include <sys/types.h>
|
|
||||||
#ifdef HAVE_NETINET_IN_H
|
|
||||||
#include <netinet/in.h>
|
|
||||||
#endif
|
|
||||||
#ifdef HAVE_INTTYPES_H
|
|
||||||
#include <inttypes.h>
|
|
||||||
#endif
|
|
||||||
#include <string>
|
|
||||||
#include <map>
|
|
||||||
#include <list>
|
|
||||||
#include <set>
|
|
||||||
#include <vector>
|
|
||||||
#include <exception>
|
|
||||||
#include <typeinfo>
|
|
||||||
|
|
||||||
#include <boost/utility/enable_if.hpp>
|
|
||||||
#include <boost/type_traits/is_convertible.hpp>
|
|
||||||
|
|
||||||
#include <thrift/TLogging.h>
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Helper macros to allow function overloading even when using
|
|
||||||
* boost::shared_ptr.
|
|
||||||
*
|
|
||||||
* shared_ptr makes overloading really annoying, since shared_ptr defines
|
|
||||||
* constructor methods to allow one shared_ptr type to be constructed from any
|
|
||||||
* other shared_ptr type. (Even if it would be a compile error to actually try
|
|
||||||
* to instantiate the constructor.) These macros add an extra argument to the
|
|
||||||
* function to cause it to only be instantiated if a pointer of type T is
|
|
||||||
* convertible to a pointer of type U.
|
|
||||||
*
|
|
||||||
* THRIFT_OVERLOAD_IF should be used in function declarations.
|
|
||||||
* THRIFT_OVERLOAD_IF_DEFN should be used in the function definition, if it is
|
|
||||||
* defined separately from where it is declared.
|
|
||||||
*/
|
|
||||||
#define THRIFT_OVERLOAD_IF_DEFN(T, Y) \
|
|
||||||
typename ::boost::enable_if<typename ::boost::is_convertible<T*, Y*>::type, \
|
|
||||||
void*>::type
|
|
||||||
|
|
||||||
#define THRIFT_OVERLOAD_IF(T, Y) \
|
|
||||||
THRIFT_OVERLOAD_IF_DEFN(T, Y) = NULL
|
|
||||||
|
|
||||||
#define THRIFT_UNUSED_VARIABLE(x) ((x)=(x))
|
|
||||||
|
|
||||||
namespace apache
|
|
||||||
{
|
|
||||||
namespace thrift
|
|
||||||
{
|
|
||||||
|
|
||||||
class TEnumIterator : public std::iterator<std::forward_iterator_tag, std::pair<int, const char*> >
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
TEnumIterator(int n,
|
|
||||||
int* enums,
|
|
||||||
const char** names) :
|
|
||||||
ii_(0), n_(n), enums_(enums), names_(names)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
int operator ++()
|
|
||||||
{
|
|
||||||
return ++ii_;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator !=(const TEnumIterator& end)
|
|
||||||
{
|
|
||||||
assert(end.n_ == -1);
|
|
||||||
return (ii_ != n_);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::pair<int, const char*> operator*() const
|
|
||||||
{
|
|
||||||
return std::make_pair(enums_[ii_], names_[ii_]);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
int ii_;
|
|
||||||
const int n_;
|
|
||||||
int* enums_;
|
|
||||||
const char** names_;
|
|
||||||
};
|
|
||||||
|
|
||||||
class TOutput
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
TOutput() : f_(&errorTimeWrapper) {}
|
|
||||||
|
|
||||||
inline void setOutputFunction(void (*function)(const char*))
|
|
||||||
{
|
|
||||||
f_ = function;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void operator()(const char* message)
|
|
||||||
{
|
|
||||||
f_(message);
|
|
||||||
}
|
|
||||||
|
|
||||||
// It is important to have a const char* overload here instead of
|
|
||||||
// just the string version, otherwise errno could be corrupted
|
|
||||||
// if there is some problem allocating memory when constructing
|
|
||||||
// the string.
|
|
||||||
void perror(const char* message, int errno_copy);
|
|
||||||
inline void perror(const std::string& message, int errno_copy)
|
|
||||||
{
|
|
||||||
perror(message.c_str(), errno_copy);
|
|
||||||
}
|
|
||||||
|
|
||||||
void printf(const char* message, ...);
|
|
||||||
|
|
||||||
static void errorTimeWrapper(const char* msg);
|
|
||||||
|
|
||||||
/** Just like strerror_r but returns a C++ string object. */
|
|
||||||
static std::string strerror_s(int errno_copy);
|
|
||||||
|
|
||||||
private:
|
|
||||||
void (*f_)(const char*);
|
|
||||||
};
|
|
||||||
|
|
||||||
extern TOutput GlobalOutput;
|
|
||||||
|
|
||||||
class TException : public std::exception
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
TException():
|
|
||||||
message_() {}
|
|
||||||
|
|
||||||
TException(const std::string& message) :
|
|
||||||
message_(message) {}
|
|
||||||
|
|
||||||
virtual ~TException() throw() {}
|
|
||||||
|
|
||||||
virtual const char* what() const throw()
|
|
||||||
{
|
|
||||||
if (message_.empty())
|
|
||||||
{
|
|
||||||
return "Default TException.";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return message_.c_str();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
std::string message_;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
// Forward declare this structure used by TDenseProtocol
|
|
||||||
namespace reflection
|
|
||||||
{
|
|
||||||
namespace local
|
|
||||||
{
|
|
||||||
struct TypeSpec;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class TDelayedException
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
template <class E> static TDelayedException* delayException(const E& e);
|
|
||||||
virtual void throw_it() = 0;
|
|
||||||
virtual ~TDelayedException() {};
|
|
||||||
};
|
|
||||||
|
|
||||||
template <class E> class TExceptionWrapper : public TDelayedException
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
TExceptionWrapper(const E& e) : e_(e) {}
|
|
||||||
virtual void throw_it()
|
|
||||||
{
|
|
||||||
E temp(e_);
|
|
||||||
delete this;
|
|
||||||
throw temp;
|
|
||||||
}
|
|
||||||
private:
|
|
||||||
E e_;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <class E>
|
|
||||||
TDelayedException* TDelayedException::delayException(const E& e)
|
|
||||||
{
|
|
||||||
return new TExceptionWrapper<E>(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
#if T_GLOBAL_DEBUG_VIRTUAL > 1
|
|
||||||
void profile_virtual_call(const std::type_info& info);
|
|
||||||
void profile_generic_protocol(const std::type_info& template_type,
|
|
||||||
const std::type_info& prot_type);
|
|
||||||
void profile_print_info(FILE* f);
|
|
||||||
void profile_print_info();
|
|
||||||
void profile_write_pprof(FILE* gen_calls_f, FILE* virtual_calls_f);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
}
|
|
||||||
} // apache::thrift
|
|
||||||
|
|
||||||
@@ -1,52 +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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <thrift/cxxfunctional.h>
|
|
||||||
#include <boost/shared_ptr.hpp>
|
|
||||||
|
|
||||||
#include <thrift/transport/TBufferTransports.h>
|
|
||||||
|
|
||||||
namespace apache
|
|
||||||
{
|
|
||||||
namespace thrift
|
|
||||||
{
|
|
||||||
namespace async
|
|
||||||
{
|
|
||||||
|
|
||||||
class TAsyncBufferProcessor
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
// Process data in "in", putting the result in "out".
|
|
||||||
// Call _return(true) when done, or _return(false) to
|
|
||||||
// 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 ~TAsyncBufferProcessor() {}
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} // apache::thrift::async
|
|
||||||
|
|
||||||
@@ -1,79 +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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <thrift/cxxfunctional.h>
|
|
||||||
#include <thrift/Thrift.h>
|
|
||||||
|
|
||||||
namespace apache
|
|
||||||
{
|
|
||||||
namespace thrift
|
|
||||||
{
|
|
||||||
namespace transport
|
|
||||||
{
|
|
||||||
class TMemoryBuffer;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace apache
|
|
||||||
{
|
|
||||||
namespace thrift
|
|
||||||
{
|
|
||||||
namespace async
|
|
||||||
{
|
|
||||||
using apache::thrift::transport::TMemoryBuffer;
|
|
||||||
|
|
||||||
class TAsyncChannel
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
typedef apache::thrift::stdcxx::function<void()> VoidCallback;
|
|
||||||
|
|
||||||
virtual ~TAsyncChannel() {}
|
|
||||||
|
|
||||||
// is the channel in a good state?
|
|
||||||
virtual bool good() const = 0;
|
|
||||||
virtual bool error() const = 0;
|
|
||||||
virtual bool timedOut() const = 0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Send a message over the channel.
|
|
||||||
*/
|
|
||||||
virtual void sendMessage(const VoidCallback& cob,
|
|
||||||
apache::thrift::transport::TMemoryBuffer* message) = 0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Receive a message from the channel.
|
|
||||||
*/
|
|
||||||
virtual void recvMessage(const VoidCallback& cob,
|
|
||||||
apache::thrift::transport::TMemoryBuffer* message) = 0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Send a message over the channel and receive a response.
|
|
||||||
*/
|
|
||||||
virtual void sendAndRecvMessage(const VoidCallback& cob,
|
|
||||||
apache::thrift::transport::TMemoryBuffer* sendBuf,
|
|
||||||
apache::thrift::transport::TMemoryBuffer* recvBuf);
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} // apache::thrift::async
|
|
||||||
|
|
||||||
@@ -1,164 +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.
|
|
||||||
*/
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <thrift/async/TAsyncProcessor.h>
|
|
||||||
|
|
||||||
namespace apache
|
|
||||||
{
|
|
||||||
namespace thrift
|
|
||||||
{
|
|
||||||
namespace async
|
|
||||||
{
|
|
||||||
|
|
||||||
/**
|
|
||||||
* TAsyncDispatchProcessor is a helper class to parse the message header then
|
|
||||||
* call another function to dispatch based on the function name.
|
|
||||||
*
|
|
||||||
* Subclasses must implement dispatchCall() to dispatch on the function name.
|
|
||||||
*/
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
protocol::TProtocol* inRaw = in.get();
|
|
||||||
protocol::TProtocol* outRaw = out.get();
|
|
||||||
|
|
||||||
// Try to dynamic cast to the template protocol type
|
|
||||||
Protocol_* specificIn = dynamic_cast<Protocol_*>(inRaw);
|
|
||||||
Protocol_* specificOut = dynamic_cast<Protocol_*>(outRaw);
|
|
||||||
|
|
||||||
if (specificIn && specificOut)
|
|
||||||
{
|
|
||||||
return processFast(_return, specificIn, specificOut);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Log the fact that we have to use the slow path
|
|
||||||
T_GENERIC_PROTOCOL(this, inRaw, specificIn);
|
|
||||||
T_GENERIC_PROTOCOL(this, outRaw, specificOut);
|
|
||||||
|
|
||||||
std::string fname;
|
|
||||||
protocol::TMessageType mtype;
|
|
||||||
int32_t seqid;
|
|
||||||
inRaw->readMessageBegin(fname, mtype, seqid);
|
|
||||||
|
|
||||||
// If this doesn't look like a valid call, log an error and return false so
|
|
||||||
// that the server will close the connection.
|
|
||||||
//
|
|
||||||
// (The old generated processor code used to try to skip a T_STRUCT and
|
|
||||||
// continue. However, that seems unsafe.)
|
|
||||||
if (mtype != protocol::T_CALL && mtype != protocol::T_ONEWAY)
|
|
||||||
{
|
|
||||||
GlobalOutput.printf("received invalid message type %d from client",
|
|
||||||
mtype);
|
|
||||||
_return(false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
return this->dispatchCall(_return, inRaw, outRaw, fname, seqid);
|
|
||||||
}
|
|
||||||
|
|
||||||
void processFast(apache::thrift::stdcxx::function<void(bool success)> _return,
|
|
||||||
Protocol_* in, Protocol_* out)
|
|
||||||
{
|
|
||||||
std::string fname;
|
|
||||||
protocol::TMessageType mtype;
|
|
||||||
int32_t seqid;
|
|
||||||
in->readMessageBegin(fname, mtype, seqid);
|
|
||||||
|
|
||||||
if (mtype != protocol::T_CALL && mtype != protocol::T_ONEWAY)
|
|
||||||
{
|
|
||||||
GlobalOutput.printf("received invalid message type %d from client",
|
|
||||||
mtype);
|
|
||||||
_return(false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
return this->dispatchCallTemplated(_return, in, out, fname, seqid);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void dispatchCall(apache::thrift::stdcxx::function<void(bool ok)> _return,
|
|
||||||
apache::thrift::protocol::TProtocol* in,
|
|
||||||
apache::thrift::protocol::TProtocol* out,
|
|
||||||
const std::string& fname, int32_t seqid) = 0;
|
|
||||||
|
|
||||||
virtual void dispatchCallTemplated(apache::thrift::stdcxx::function<void(bool ok)> _return,
|
|
||||||
Protocol_* in, Protocol_* out,
|
|
||||||
const std::string& fname,
|
|
||||||
int32_t seqid) = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Non-templatized version of TAsyncDispatchProcessor,
|
|
||||||
* that doesn't bother trying to perform a dynamic_cast.
|
|
||||||
*/
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
protocol::TProtocol* inRaw = in.get();
|
|
||||||
protocol::TProtocol* outRaw = out.get();
|
|
||||||
|
|
||||||
std::string fname;
|
|
||||||
protocol::TMessageType mtype;
|
|
||||||
int32_t seqid;
|
|
||||||
inRaw->readMessageBegin(fname, mtype, seqid);
|
|
||||||
|
|
||||||
// If this doesn't look like a valid call, log an error and return false so
|
|
||||||
// that the server will close the connection.
|
|
||||||
//
|
|
||||||
// (The old generated processor code used to try to skip a T_STRUCT and
|
|
||||||
// continue. However, that seems unsafe.)
|
|
||||||
if (mtype != protocol::T_CALL && mtype != protocol::T_ONEWAY)
|
|
||||||
{
|
|
||||||
GlobalOutput.printf("received invalid message type %d from client",
|
|
||||||
mtype);
|
|
||||||
_return(false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
return dispatchCall(_return, inRaw, outRaw, fname, seqid);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void dispatchCall(apache::thrift::stdcxx::function<void(bool ok)> _return,
|
|
||||||
apache::thrift::protocol::TProtocol* in,
|
|
||||||
apache::thrift::protocol::TProtocol* out,
|
|
||||||
const std::string& fname, int32_t seqid) = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Specialize TAsyncDispatchProcessorT for TProtocol and TDummyProtocol just to
|
|
||||||
// use the generic TDispatchProcessor.
|
|
||||||
template <>
|
|
||||||
class TAsyncDispatchProcessorT<protocol::TDummyProtocol> :
|
|
||||||
public TAsyncDispatchProcessor {};
|
|
||||||
template <>
|
|
||||||
class TAsyncDispatchProcessorT<protocol::TProtocol> :
|
|
||||||
public TAsyncDispatchProcessor {};
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} // apache::thrift::async
|
|
||||||
|
|
||||||
@@ -1,113 +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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <thrift/cxxfunctional.h>
|
|
||||||
#include <boost/shared_ptr.hpp>
|
|
||||||
#include <thrift/protocol/TProtocol.h>
|
|
||||||
#include <thrift/TProcessor.h>
|
|
||||||
|
|
||||||
namespace apache
|
|
||||||
{
|
|
||||||
namespace thrift
|
|
||||||
{
|
|
||||||
namespace async
|
|
||||||
{
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Async version of a TProcessor. It is not expected to complete by the time
|
|
||||||
* the call to process returns. Instead, it calls a cob to signal completion.
|
|
||||||
*/
|
|
||||||
|
|
||||||
class TEventServer; // forward declaration
|
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
void process(apache::thrift::stdcxx::function<void(bool success)> _return,
|
|
||||||
boost::shared_ptr<apache::thrift::protocol::TProtocol> io)
|
|
||||||
{
|
|
||||||
return process(_return, io, io);
|
|
||||||
}
|
|
||||||
|
|
||||||
boost::shared_ptr<TProcessorEventHandler> getEventHandler()
|
|
||||||
{
|
|
||||||
return eventHandler_;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setEventHandler(boost::shared_ptr<TProcessorEventHandler> eventHandler)
|
|
||||||
{
|
|
||||||
eventHandler_ = eventHandler;
|
|
||||||
}
|
|
||||||
|
|
||||||
const TEventServer* getAsyncServer()
|
|
||||||
{
|
|
||||||
return asyncServer_;
|
|
||||||
}
|
|
||||||
protected:
|
|
||||||
TAsyncProcessor() {}
|
|
||||||
|
|
||||||
boost::shared_ptr<TProcessorEventHandler> eventHandler_;
|
|
||||||
const TEventServer* asyncServer_;
|
|
||||||
private:
|
|
||||||
friend class TEventServer;
|
|
||||||
void setAsyncServer(const TEventServer* server)
|
|
||||||
{
|
|
||||||
asyncServer_ = server;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
class TAsyncProcessorFactory
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
virtual ~TAsyncProcessorFactory() {}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the TAsyncProcessor to use for a particular connection.
|
|
||||||
*
|
|
||||||
* This method is always invoked in the same thread that the connection was
|
|
||||||
* 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;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} // apache::thrift::async
|
|
||||||
|
|
||||||
// XXX I'm lazy for now
|
|
||||||
namespace apache
|
|
||||||
{
|
|
||||||
namespace thrift
|
|
||||||
{
|
|
||||||
using apache::thrift::async::TAsyncProcessor;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,63 +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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <thrift/async/TAsyncProcessor.h>
|
|
||||||
#include <thrift/async/TAsyncBufferProcessor.h>
|
|
||||||
#include <thrift/protocol/TProtocol.h>
|
|
||||||
|
|
||||||
namespace apache
|
|
||||||
{
|
|
||||||
namespace thrift
|
|
||||||
{
|
|
||||||
namespace async
|
|
||||||
{
|
|
||||||
|
|
||||||
class TAsyncProtocolProcessor : public TAsyncBufferProcessor
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
TAsyncProtocolProcessor(
|
|
||||||
boost::shared_ptr<TAsyncProcessor> underlying,
|
|
||||||
boost::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);
|
|
||||||
|
|
||||||
virtual ~TAsyncProtocolProcessor() {}
|
|
||||||
|
|
||||||
private:
|
|
||||||
static void finish(
|
|
||||||
apache::thrift::stdcxx::function<void(bool healthy)> _return,
|
|
||||||
boost::shared_ptr<apache::thrift::protocol::TProtocol> oprot,
|
|
||||||
bool healthy);
|
|
||||||
|
|
||||||
boost::shared_ptr<TAsyncProcessor> underlying_;
|
|
||||||
boost::shared_ptr<apache::thrift::protocol::TProtocolFactory> pfact_;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} // apache::thrift::async
|
|
||||||
|
|
||||||
@@ -1,98 +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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include <boost/shared_ptr.hpp>
|
|
||||||
#include <thrift/async/TAsyncChannel.h>
|
|
||||||
|
|
||||||
struct event_base;
|
|
||||||
struct evhttp_connection;
|
|
||||||
struct evhttp_request;
|
|
||||||
|
|
||||||
namespace apache
|
|
||||||
{
|
|
||||||
namespace thrift
|
|
||||||
{
|
|
||||||
namespace transport
|
|
||||||
{
|
|
||||||
class TMemoryBuffer;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace apache
|
|
||||||
{
|
|
||||||
namespace thrift
|
|
||||||
{
|
|
||||||
namespace async
|
|
||||||
{
|
|
||||||
|
|
||||||
class TEvhttpClientChannel : public TAsyncChannel
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
using TAsyncChannel::VoidCallback;
|
|
||||||
|
|
||||||
TEvhttpClientChannel(
|
|
||||||
const std::string& host,
|
|
||||||
const std::string& path,
|
|
||||||
const char* address,
|
|
||||||
int port,
|
|
||||||
struct event_base* eb);
|
|
||||||
~TEvhttpClientChannel();
|
|
||||||
|
|
||||||
virtual void sendAndRecvMessage(const VoidCallback& cob,
|
|
||||||
apache::thrift::transport::TMemoryBuffer* sendBuf,
|
|
||||||
apache::thrift::transport::TMemoryBuffer* recvBuf);
|
|
||||||
|
|
||||||
virtual void sendMessage(const VoidCallback& cob, apache::thrift::transport::TMemoryBuffer* message);
|
|
||||||
virtual void recvMessage(const VoidCallback& cob, apache::thrift::transport::TMemoryBuffer* message);
|
|
||||||
|
|
||||||
void finish(struct evhttp_request* req);
|
|
||||||
|
|
||||||
//XXX
|
|
||||||
virtual bool good() const
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
virtual bool error() const
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
virtual bool timedOut() const
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
static void response(struct evhttp_request* req, void* arg);
|
|
||||||
|
|
||||||
std::string host_;
|
|
||||||
std::string path_;
|
|
||||||
VoidCallback cob_;
|
|
||||||
apache::thrift::transport::TMemoryBuffer* recvBuf_;
|
|
||||||
struct evhttp_connection* conn_;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} // apache::thrift::async
|
|
||||||
|
|
||||||
@@ -1,77 +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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <boost/shared_ptr.hpp>
|
|
||||||
|
|
||||||
struct event_base;
|
|
||||||
struct evhttp;
|
|
||||||
struct evhttp_request;
|
|
||||||
|
|
||||||
namespace apache
|
|
||||||
{
|
|
||||||
namespace thrift
|
|
||||||
{
|
|
||||||
namespace async
|
|
||||||
{
|
|
||||||
|
|
||||||
class TAsyncBufferProcessor;
|
|
||||||
|
|
||||||
class TEvhttpServer
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
/**
|
|
||||||
* Create a TEvhttpServer for use with an external evhttp instance.
|
|
||||||
* Must be manually installed with evhttp_set_cb, using
|
|
||||||
* TEvhttpServer::request as the callback and the
|
|
||||||
* address of the server as the extra arg.
|
|
||||||
* Do not call "serve" on this server.
|
|
||||||
*/
|
|
||||||
TEvhttpServer(boost::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();
|
|
||||||
|
|
||||||
static void request(struct evhttp_request* req, void* self);
|
|
||||||
int serve();
|
|
||||||
|
|
||||||
struct event_base* getEventBase();
|
|
||||||
|
|
||||||
private:
|
|
||||||
struct RequestContext;
|
|
||||||
|
|
||||||
void process(struct evhttp_request* req);
|
|
||||||
void complete(RequestContext* ctx, bool success);
|
|
||||||
|
|
||||||
boost::shared_ptr<TAsyncBufferProcessor> processor_;
|
|
||||||
struct event_base* eb_;
|
|
||||||
struct evhttp* eh_;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} // apache::thrift::async
|
|
||||||
|
|
||||||
@@ -1,81 +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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <thrift/concurrency/Thread.h>
|
|
||||||
|
|
||||||
#include <boost/shared_ptr.hpp>
|
|
||||||
|
|
||||||
namespace apache
|
|
||||||
{
|
|
||||||
namespace thrift
|
|
||||||
{
|
|
||||||
namespace concurrency
|
|
||||||
{
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A thread factory to create posix threads
|
|
||||||
*
|
|
||||||
* @version $Id:$
|
|
||||||
*/
|
|
||||||
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.
|
|
||||||
*
|
|
||||||
* Threads are created with the specified boost policy, priority, stack-size. A detachable thread is not
|
|
||||||
* joinable.
|
|
||||||
*
|
|
||||||
* By default threads are not joinable.
|
|
||||||
*/
|
|
||||||
|
|
||||||
BoostThreadFactory(bool detached = true);
|
|
||||||
|
|
||||||
// From ThreadFactory;
|
|
||||||
boost::shared_ptr<Thread> newThread(boost::shared_ptr<Runnable> runnable) const;
|
|
||||||
|
|
||||||
// From ThreadFactory;
|
|
||||||
Thread::id_t getCurrentThreadId() const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets detached mode of threads
|
|
||||||
*/
|
|
||||||
virtual void setDetached(bool detached);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets current detached mode
|
|
||||||
*/
|
|
||||||
virtual bool isDetached() const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
class Impl;
|
|
||||||
boost::shared_ptr<Impl> impl_;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} // apache::thrift::concurrency
|
|
||||||
|
|
||||||
@@ -1,73 +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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <exception>
|
|
||||||
#include <thrift/Thrift.h>
|
|
||||||
|
|
||||||
namespace apache
|
|
||||||
{
|
|
||||||
namespace thrift
|
|
||||||
{
|
|
||||||
namespace concurrency
|
|
||||||
{
|
|
||||||
|
|
||||||
class NoSuchTaskException : public apache::thrift::TException {};
|
|
||||||
|
|
||||||
class UncancellableTaskException : public apache::thrift::TException {};
|
|
||||||
|
|
||||||
class InvalidArgumentException : public apache::thrift::TException {};
|
|
||||||
|
|
||||||
class IllegalStateException : public apache::thrift::TException
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
IllegalStateException() {}
|
|
||||||
IllegalStateException(const std::string& message) : TException(message) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
class TimedOutException : public apache::thrift::TException
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
TimedOutException(): TException("TimedOutException") {};
|
|
||||||
TimedOutException(const std::string& message ) :
|
|
||||||
TException(message) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
class TooManyPendingTasksException : public apache::thrift::TException
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
TooManyPendingTasksException(): TException("TooManyPendingTasksException") {};
|
|
||||||
TooManyPendingTasksException(const std::string& message ) :
|
|
||||||
TException(message) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
class SystemResourceException : public apache::thrift::TException
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
SystemResourceException() {}
|
|
||||||
|
|
||||||
SystemResourceException(const std::string& message) :
|
|
||||||
TException(message) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} // apache::thrift::concurrency
|
|
||||||
|
|
||||||
@@ -1,134 +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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <thrift/cxxfunctional.h>
|
|
||||||
#include <thrift/concurrency/Thread.h>
|
|
||||||
|
|
||||||
namespace apache
|
|
||||||
{
|
|
||||||
namespace thrift
|
|
||||||
{
|
|
||||||
namespace concurrency
|
|
||||||
{
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Convenient implementation of Runnable that will execute arbitrary callbacks.
|
|
||||||
* Interfaces are provided to accept both a generic 'void(void)' callback, and
|
|
||||||
* a 'void* (void*)' pthread_create-style callback.
|
|
||||||
*
|
|
||||||
* Example use:
|
|
||||||
* void* my_thread_main(void* arg);
|
|
||||||
* shared_ptr<ThreadFactory> factory = ...;
|
|
||||||
* // To create a thread that executes my_thread_main once:
|
|
||||||
* shared_ptr<Thread> thread = factory->newThread(
|
|
||||||
* FunctionRunner::create(my_thread_main, some_argument));
|
|
||||||
* thread->start();
|
|
||||||
*
|
|
||||||
* bool A::foo();
|
|
||||||
* A* a = new A();
|
|
||||||
* // To create a thread that executes a.foo() every 100 milliseconds:
|
|
||||||
* factory->newThread(FunctionRunner::create(
|
|
||||||
* apache::thrift::stdcxx::bind(&A::foo, a), 100))->start();
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
class FunctionRunner : public Runnable
|
|
||||||
{
|
|
||||||
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 apache::thrift::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 boost::shared_ptr<FunctionRunner> create(PthreadFuncPtr func,
|
|
||||||
void* arg)
|
|
||||||
{
|
|
||||||
return boost::shared_ptr<FunctionRunner>(new FunctionRunner(func, arg));
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
static void pthread_func_wrapper(PthreadFuncPtr func, void* arg)
|
|
||||||
{
|
|
||||||
//discard return value
|
|
||||||
func(arg);
|
|
||||||
}
|
|
||||||
public:
|
|
||||||
/**
|
|
||||||
* Given a 'pthread_create' style callback, this FunctionRunner will
|
|
||||||
* 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))
|
|
||||||
{ }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Given a generic callback, this FunctionRunner will execute it.
|
|
||||||
*/
|
|
||||||
FunctionRunner(const VoidFunc& cob)
|
|
||||||
: func_(cob)
|
|
||||||
{ }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Given a bool foo(...) type callback, FunctionRunner will execute
|
|
||||||
* the callback repeatedly with 'intervalMs' milliseconds between the calls,
|
|
||||||
* until it returns false. Note that the actual interval between calls will
|
|
||||||
* be intervalMs plus execution time of the callback.
|
|
||||||
*/
|
|
||||||
FunctionRunner(const BoolFunc& cob, int intervalMs)
|
|
||||||
: repFunc_(cob), intervalMs_(intervalMs)
|
|
||||||
{ }
|
|
||||||
|
|
||||||
void run()
|
|
||||||
{
|
|
||||||
if (repFunc_)
|
|
||||||
{
|
|
||||||
while (repFunc_())
|
|
||||||
{
|
|
||||||
THRIFT_SLEEP_USEC(intervalMs_ * 1000);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
func_();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
VoidFunc func_;
|
|
||||||
BoolFunc repFunc_;
|
|
||||||
int intervalMs_;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} // apache::thrift::concurrency
|
|
||||||
|
|
||||||
@@ -1,137 +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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <thrift/concurrency/Exception.h>
|
|
||||||
#include <thrift/concurrency/Mutex.h>
|
|
||||||
|
|
||||||
#include <boost/utility.hpp>
|
|
||||||
|
|
||||||
|
|
||||||
namespace apache
|
|
||||||
{
|
|
||||||
namespace thrift
|
|
||||||
{
|
|
||||||
namespace concurrency
|
|
||||||
{
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A monitor is a combination mutex and condition-event. Waiting and
|
|
||||||
* notifying condition events requires that the caller own the mutex. Mutex
|
|
||||||
* lock and unlock operations can be performed independently of condition
|
|
||||||
* events. This is more or less analogous to java.lang.Object multi-thread
|
|
||||||
* operations.
|
|
||||||
*
|
|
||||||
* Note the Monitor can create a new, internal mutex; alternatively, a
|
|
||||||
* separate Mutex can be passed in and the Monitor will re-use it without
|
|
||||||
* taking ownership. It's the user's responsibility to make sure that the
|
|
||||||
* Mutex is not deallocated before the Monitor.
|
|
||||||
*
|
|
||||||
* Note that all methods are const. Monitors implement logical constness, not
|
|
||||||
* bit constness. This allows const methods to call monitor methods without
|
|
||||||
* needing to cast away constness or change to non-const signatures.
|
|
||||||
*
|
|
||||||
* @version $Id:$
|
|
||||||
*/
|
|
||||||
class Monitor : boost::noncopyable
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
/** Creates a new mutex, and takes ownership of it. */
|
|
||||||
Monitor();
|
|
||||||
|
|
||||||
/** Uses the provided mutex without taking ownership. */
|
|
||||||
explicit Monitor(Mutex* mutex);
|
|
||||||
|
|
||||||
/** Uses the mutex inside the provided Monitor without taking ownership. */
|
|
||||||
explicit Monitor(Monitor* monitor);
|
|
||||||
|
|
||||||
/** Deallocates the mutex only if we own it. */
|
|
||||||
virtual ~Monitor();
|
|
||||||
|
|
||||||
Mutex& mutex() const;
|
|
||||||
|
|
||||||
virtual void lock() const;
|
|
||||||
|
|
||||||
virtual void unlock() const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Waits a maximum of the specified timeout in milliseconds for the condition
|
|
||||||
* to occur, or waits forever if timeout_ms == 0.
|
|
||||||
*
|
|
||||||
* Returns 0 if condition occurs, THRIFT_ETIMEDOUT on timeout, or an error code.
|
|
||||||
*/
|
|
||||||
int waitForTimeRelative(int64_t timeout_ms) const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Waits until the absolute time specified using struct THRIFT_TIMESPEC.
|
|
||||||
* Returns 0 if condition occurs, THRIFT_ETIMEDOUT on timeout, or an error code.
|
|
||||||
*/
|
|
||||||
int waitForTime(const THRIFT_TIMESPEC* abstime) const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Waits until the absolute time specified using struct timeval.
|
|
||||||
* Returns 0 if condition occurs, THRIFT_ETIMEDOUT on timeout, or an error code.
|
|
||||||
*/
|
|
||||||
int waitForTime(const struct timeval* abstime) const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Waits forever until the condition occurs.
|
|
||||||
* Returns 0 if condition occurs, or an error code otherwise.
|
|
||||||
*/
|
|
||||||
int waitForever() const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Exception-throwing version of waitForTimeRelative(), called simply
|
|
||||||
* wait(int64) for historical reasons. Timeout is in milliseconds.
|
|
||||||
*
|
|
||||||
* If the condition occurs, this function returns cleanly; on timeout or
|
|
||||||
* error an exception is thrown.
|
|
||||||
*/
|
|
||||||
void wait(int64_t timeout_ms = 0LL) const;
|
|
||||||
|
|
||||||
|
|
||||||
/** Wakes up one thread waiting on this monitor. */
|
|
||||||
virtual void notify() const;
|
|
||||||
|
|
||||||
/** Wakes up all waiting threads on this monitor. */
|
|
||||||
virtual void notifyAll() const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
class Impl;
|
|
||||||
|
|
||||||
Impl* impl_;
|
|
||||||
};
|
|
||||||
|
|
||||||
class Synchronized
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
Synchronized(const Monitor* monitor) : g(monitor->mutex()) { }
|
|
||||||
Synchronized(const Monitor& monitor) : g(monitor.mutex()) { }
|
|
||||||
|
|
||||||
private:
|
|
||||||
Guard g;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} // apache::thrift::concurrency
|
|
||||||
|
|
||||||
@@ -1,219 +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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <boost/shared_ptr.hpp>
|
|
||||||
#include <boost/noncopyable.hpp>
|
|
||||||
|
|
||||||
namespace apache
|
|
||||||
{
|
|
||||||
namespace thrift
|
|
||||||
{
|
|
||||||
namespace concurrency
|
|
||||||
{
|
|
||||||
|
|
||||||
#ifndef THRIFT_NO_CONTENTION_PROFILING
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Determines if the Thrift Mutex and ReadWriteMutex classes will attempt to
|
|
||||||
* profile their blocking acquire methods. If this value is set to non-zero,
|
|
||||||
* Thrift will attempt to invoke the callback once every profilingSampleRate
|
|
||||||
* times. However, as the sampling is not synchronized the rate is not
|
|
||||||
* guranateed, and could be subject to big bursts and swings. Please ensure
|
|
||||||
* your sampling callback is as performant as your application requires.
|
|
||||||
*
|
|
||||||
* The callback will get called with the wait time taken to lock the mutex in
|
|
||||||
* usec and a (void*) that uniquely identifies the Mutex (or ReadWriteMutex)
|
|
||||||
* being locked.
|
|
||||||
*
|
|
||||||
* The enableMutexProfiling() function is unsynchronized; calling this function
|
|
||||||
* while profiling is already enabled may result in race conditions. On
|
|
||||||
* architectures where a pointer assignment is atomic, this is safe but there
|
|
||||||
* is no guarantee threads will agree on a single callback within any
|
|
||||||
* particular time period.
|
|
||||||
*/
|
|
||||||
typedef void (*MutexWaitCallback)(const void* id, int64_t waitTimeMicros);
|
|
||||||
void enableMutexProfiling(int32_t profilingSampleRate,
|
|
||||||
MutexWaitCallback callback);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A simple mutex class
|
|
||||||
*
|
|
||||||
* @version $Id:$
|
|
||||||
*/
|
|
||||||
class Mutex
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
typedef void (*Initializer)(void*);
|
|
||||||
|
|
||||||
Mutex(Initializer init = DEFAULT_INITIALIZER);
|
|
||||||
virtual ~Mutex() {}
|
|
||||||
virtual void lock() const;
|
|
||||||
virtual bool trylock() const;
|
|
||||||
virtual bool timedlock(int64_t milliseconds) const;
|
|
||||||
virtual void unlock() const;
|
|
||||||
|
|
||||||
void* getUnderlyingImpl() const;
|
|
||||||
|
|
||||||
static void DEFAULT_INITIALIZER(void*);
|
|
||||||
static void ADAPTIVE_INITIALIZER(void*);
|
|
||||||
static void RECURSIVE_INITIALIZER(void*);
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
class impl;
|
|
||||||
boost::shared_ptr<impl> impl_;
|
|
||||||
};
|
|
||||||
|
|
||||||
class ReadWriteMutex
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
ReadWriteMutex();
|
|
||||||
virtual ~ReadWriteMutex() {}
|
|
||||||
|
|
||||||
// these get the lock and block until it is done successfully
|
|
||||||
virtual void acquireRead() const;
|
|
||||||
virtual void acquireWrite() const;
|
|
||||||
|
|
||||||
// these attempt to get the lock, returning false immediately if they fail
|
|
||||||
virtual bool attemptRead() const;
|
|
||||||
virtual bool attemptWrite() const;
|
|
||||||
|
|
||||||
// this releases both read and write locks
|
|
||||||
virtual void release() const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
class impl;
|
|
||||||
boost::shared_ptr<impl> impl_;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A ReadWriteMutex that guarantees writers will not be starved by readers:
|
|
||||||
* When a writer attempts to acquire the mutex, all new readers will be
|
|
||||||
* blocked from acquiring the mutex until the writer has acquired and
|
|
||||||
* released it. In some operating systems, this may already be guaranteed
|
|
||||||
* by a regular ReadWriteMutex.
|
|
||||||
*/
|
|
||||||
class NoStarveReadWriteMutex : public ReadWriteMutex
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
NoStarveReadWriteMutex();
|
|
||||||
|
|
||||||
virtual void acquireRead() const;
|
|
||||||
virtual void acquireWrite() const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
Mutex mutex_;
|
|
||||||
mutable volatile bool writerWaiting_;
|
|
||||||
};
|
|
||||||
|
|
||||||
class Guard : boost::noncopyable
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
Guard(const Mutex& value, int64_t timeout = 0) : mutex_(&value)
|
|
||||||
{
|
|
||||||
if (timeout == 0)
|
|
||||||
{
|
|
||||||
value.lock();
|
|
||||||
}
|
|
||||||
else if (timeout < 0)
|
|
||||||
{
|
|
||||||
if (!value.trylock())
|
|
||||||
{
|
|
||||||
mutex_ = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (!value.timedlock(timeout))
|
|
||||||
{
|
|
||||||
mutex_ = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
~Guard()
|
|
||||||
{
|
|
||||||
if (mutex_)
|
|
||||||
{
|
|
||||||
mutex_->unlock();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
operator bool() const
|
|
||||||
{
|
|
||||||
return (mutex_ != NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
const Mutex* mutex_;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Can be used as second argument to RWGuard to make code more readable
|
|
||||||
// as to whether we're doing acquireRead() or acquireWrite().
|
|
||||||
enum RWGuardType
|
|
||||||
{
|
|
||||||
RW_READ = 0,
|
|
||||||
RW_WRITE = 1
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
class RWGuard : boost::noncopyable
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
RWGuard(const ReadWriteMutex& value, bool write = false)
|
|
||||||
: rw_mutex_(value)
|
|
||||||
{
|
|
||||||
if (write)
|
|
||||||
{
|
|
||||||
rw_mutex_.acquireWrite();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
rw_mutex_.acquireRead();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
RWGuard(const ReadWriteMutex& value, RWGuardType type)
|
|
||||||
: rw_mutex_(value)
|
|
||||||
{
|
|
||||||
if (type == RW_WRITE)
|
|
||||||
{
|
|
||||||
rw_mutex_.acquireWrite();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
rw_mutex_.acquireRead();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
~RWGuard()
|
|
||||||
{
|
|
||||||
rw_mutex_.release();
|
|
||||||
}
|
|
||||||
private:
|
|
||||||
const ReadWriteMutex& rw_mutex_;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} // apache::thrift::concurrency
|
|
||||||
|
|
||||||
@@ -1,49 +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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <thrift/thrift-config.h>
|
|
||||||
#if USE_BOOST_THREAD
|
|
||||||
# include <thrift/concurrency/BoostThreadFactory.h>
|
|
||||||
#elif USE_STD_THREAD
|
|
||||||
# include <thrift/concurrency/StdThreadFactory.h>
|
|
||||||
#else
|
|
||||||
# include <thrift/concurrency/PosixThreadFactory.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace apache
|
|
||||||
{
|
|
||||||
namespace thrift
|
|
||||||
{
|
|
||||||
namespace concurrency
|
|
||||||
{
|
|
||||||
|
|
||||||
#ifdef USE_BOOST_THREAD
|
|
||||||
typedef BoostThreadFactory PlatformThreadFactory;
|
|
||||||
#elif USE_STD_THREAD
|
|
||||||
typedef StdThreadFactory PlatformThreadFactory;
|
|
||||||
#else
|
|
||||||
typedef PosixThreadFactory PlatformThreadFactory;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} // apache::thrift::concurrency
|
|
||||||
|
|
||||||
@@ -1,138 +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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <thrift/concurrency/Thread.h>
|
|
||||||
|
|
||||||
#include <boost/shared_ptr.hpp>
|
|
||||||
|
|
||||||
namespace apache
|
|
||||||
{
|
|
||||||
namespace thrift
|
|
||||||
{
|
|
||||||
namespace concurrency
|
|
||||||
{
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A thread factory to create posix threads
|
|
||||||
*
|
|
||||||
* @version $Id:$
|
|
||||||
*/
|
|
||||||
class PosixThreadFactory : public ThreadFactory
|
|
||||||
{
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
/**
|
|
||||||
* POSIX Thread scheduler policies
|
|
||||||
*/
|
|
||||||
enum POLICY
|
|
||||||
{
|
|
||||||
OTHER,
|
|
||||||
FIFO,
|
|
||||||
ROUND_ROBIN
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* POSIX Thread scheduler relative priorities,
|
|
||||||
*
|
|
||||||
* Absolute priority is determined by scheduler policy and OS. This
|
|
||||||
* enumeration specifies relative priorities such that one can specify a
|
|
||||||
* priority withing a giving scheduler policy without knowing the absolute
|
|
||||||
* value of the priority.
|
|
||||||
*/
|
|
||||||
enum PRIORITY
|
|
||||||
{
|
|
||||||
LOWEST = 0,
|
|
||||||
LOWER = 1,
|
|
||||||
LOW = 2,
|
|
||||||
NORMAL = 3,
|
|
||||||
HIGH = 4,
|
|
||||||
HIGHER = 5,
|
|
||||||
HIGHEST = 6,
|
|
||||||
INCREMENT = 7,
|
|
||||||
DECREMENT = 8
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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.
|
|
||||||
*
|
|
||||||
* 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
|
|
||||||
* when it completes. A detachable thread is not joinable. The join method
|
|
||||||
* of a detachable thread will return immediately with no error.
|
|
||||||
*
|
|
||||||
* By default threads are not joinable.
|
|
||||||
*/
|
|
||||||
|
|
||||||
PosixThreadFactory(POLICY policy = ROUND_ROBIN, PRIORITY priority = NORMAL, int stackSize = 1, bool detached = true);
|
|
||||||
|
|
||||||
// From ThreadFactory;
|
|
||||||
boost::shared_ptr<Thread> newThread(boost::shared_ptr<Runnable> runnable) const;
|
|
||||||
|
|
||||||
// From ThreadFactory;
|
|
||||||
Thread::id_t getCurrentThreadId() const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets stack size for created threads
|
|
||||||
*
|
|
||||||
* @return int size in megabytes
|
|
||||||
*/
|
|
||||||
virtual int getStackSize() const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets stack size for created threads
|
|
||||||
*
|
|
||||||
* @param value size in megabytes
|
|
||||||
*/
|
|
||||||
virtual void setStackSize(int value);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets priority relative to current policy
|
|
||||||
*/
|
|
||||||
virtual PRIORITY getPriority() const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets priority relative to current policy
|
|
||||||
*/
|
|
||||||
virtual void setPriority(PRIORITY priority);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets detached mode of threads
|
|
||||||
*/
|
|
||||||
virtual void setDetached(bool detached);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets current detached mode
|
|
||||||
*/
|
|
||||||
virtual bool isDetached() const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
class Impl;
|
|
||||||
boost::shared_ptr<Impl> impl_;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} // apache::thrift::concurrency
|
|
||||||
|
|
||||||
@@ -1,78 +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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <thrift/concurrency/Thread.h>
|
|
||||||
|
|
||||||
#include <boost/shared_ptr.hpp>
|
|
||||||
|
|
||||||
namespace apache
|
|
||||||
{
|
|
||||||
namespace thrift
|
|
||||||
{
|
|
||||||
namespace concurrency
|
|
||||||
{
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A thread factory to create std::threads.
|
|
||||||
*
|
|
||||||
* @version $Id:$
|
|
||||||
*/
|
|
||||||
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
|
|
||||||
* to both is given up.
|
|
||||||
*
|
|
||||||
* By default threads are not joinable.
|
|
||||||
*/
|
|
||||||
|
|
||||||
StdThreadFactory(bool detached = true);
|
|
||||||
|
|
||||||
// From ThreadFactory;
|
|
||||||
boost::shared_ptr<Thread> newThread(boost::shared_ptr<Runnable> runnable) const;
|
|
||||||
|
|
||||||
// From ThreadFactory;
|
|
||||||
Thread::id_t getCurrentThreadId() const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets detached mode of threads
|
|
||||||
*/
|
|
||||||
virtual void setDetached(bool detached);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets current detached mode
|
|
||||||
*/
|
|
||||||
virtual bool isDetached() const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
class Impl;
|
|
||||||
boost::shared_ptr<Impl> impl_;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} // apache::thrift::concurrency
|
|
||||||
|
|
||||||
@@ -1,190 +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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <boost/shared_ptr.hpp>
|
|
||||||
#include <boost/weak_ptr.hpp>
|
|
||||||
|
|
||||||
#include <thrift/thrift-config.h>
|
|
||||||
|
|
||||||
#if USE_BOOST_THREAD
|
|
||||||
# include <boost/thread.hpp>
|
|
||||||
#elif USE_STD_THREAD
|
|
||||||
# include <thread>
|
|
||||||
#else
|
|
||||||
# ifdef HAVE_PTHREAD_H
|
|
||||||
# include <pthread.h>
|
|
||||||
# endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace apache
|
|
||||||
{
|
|
||||||
namespace thrift
|
|
||||||
{
|
|
||||||
namespace concurrency
|
|
||||||
{
|
|
||||||
|
|
||||||
class Thread;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Minimal runnable class. More or less analogous to java.lang.Runnable.
|
|
||||||
*
|
|
||||||
* @version $Id:$
|
|
||||||
*/
|
|
||||||
class Runnable
|
|
||||||
{
|
|
||||||
|
|
||||||
public:
|
|
||||||
virtual ~Runnable() {};
|
|
||||||
virtual void run() = 0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the thread object that is hosting this runnable object - can return
|
|
||||||
* an empty boost::shared pointer if no references remain on thet thread object
|
|
||||||
*/
|
|
||||||
virtual boost::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;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
boost::weak_ptr<Thread> thread_;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Minimal thread class. Returned by thread factory bound to a Runnable object
|
|
||||||
* and ready to start execution. More or less analogous to java.lang.Thread
|
|
||||||
* (minus all the thread group, priority, mode and other baggage, since that
|
|
||||||
* is difficult to abstract across platforms and is left for platform-specific
|
|
||||||
* ThreadFactory implemtations to deal with
|
|
||||||
*
|
|
||||||
* @see apache::thrift::concurrency::ThreadFactory)
|
|
||||||
*/
|
|
||||||
class Thread
|
|
||||||
{
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
#if USE_BOOST_THREAD
|
|
||||||
typedef boost::thread::id id_t;
|
|
||||||
|
|
||||||
static inline bool is_current(id_t t)
|
|
||||||
{
|
|
||||||
return t == boost::this_thread::get_id();
|
|
||||||
}
|
|
||||||
static inline id_t get_current()
|
|
||||||
{
|
|
||||||
return boost::this_thread::get_id();
|
|
||||||
}
|
|
||||||
#elif USE_STD_THREAD
|
|
||||||
typedef std::thread::id id_t;
|
|
||||||
|
|
||||||
static inline bool is_current(id_t t)
|
|
||||||
{
|
|
||||||
return t == std::this_thread::get_id();
|
|
||||||
}
|
|
||||||
static inline id_t get_current()
|
|
||||||
{
|
|
||||||
return std::this_thread::get_id();
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
typedef pthread_t id_t;
|
|
||||||
|
|
||||||
static inline bool is_current(id_t t)
|
|
||||||
{
|
|
||||||
return pthread_equal(pthread_self(), t);
|
|
||||||
}
|
|
||||||
static inline id_t get_current()
|
|
||||||
{
|
|
||||||
return pthread_self();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
virtual ~Thread() {};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Starts the thread. Does platform specific thread creation and
|
|
||||||
* configuration then invokes the run method of the Runnable object bound
|
|
||||||
* to this thread.
|
|
||||||
*/
|
|
||||||
virtual void start() = 0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Join this thread. Current thread blocks until this target thread
|
|
||||||
* completes.
|
|
||||||
*/
|
|
||||||
virtual void join() = 0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the thread's platform-specific ID
|
|
||||||
*/
|
|
||||||
virtual id_t getId() = 0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the runnable object this thread is hosting
|
|
||||||
*/
|
|
||||||
virtual boost::shared_ptr<Runnable> runnable() const
|
|
||||||
{
|
|
||||||
return _runnable;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
virtual void runnable(boost::shared_ptr<Runnable> value)
|
|
||||||
{
|
|
||||||
_runnable = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
boost::shared_ptr<Runnable> _runnable;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Factory to create platform-specific thread object and bind them to Runnable
|
|
||||||
* object for execution
|
|
||||||
*/
|
|
||||||
class ThreadFactory
|
|
||||||
{
|
|
||||||
|
|
||||||
public:
|
|
||||||
virtual ~ThreadFactory() {}
|
|
||||||
virtual boost::shared_ptr<Thread> newThread(boost::shared_ptr<Runnable> runnable) const = 0;
|
|
||||||
|
|
||||||
/** Gets the current thread id or unknown_thread_id if the current thread is not a thrift thread */
|
|
||||||
|
|
||||||
static const Thread::id_t unknown_thread_id;
|
|
||||||
|
|
||||||
virtual Thread::id_t getCurrentThreadId() const = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} // apache::thrift::concurrency
|
|
||||||
|
|
||||||
@@ -1,209 +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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <boost/shared_ptr.hpp>
|
|
||||||
#include <thrift/cxxfunctional.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <thrift/concurrency/Thread.h>
|
|
||||||
|
|
||||||
namespace apache
|
|
||||||
{
|
|
||||||
namespace thrift
|
|
||||||
{
|
|
||||||
namespace concurrency
|
|
||||||
{
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Thread Pool Manager and related classes
|
|
||||||
*
|
|
||||||
* @version $Id:$
|
|
||||||
*/
|
|
||||||
class ThreadManager;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* ThreadManager class
|
|
||||||
*
|
|
||||||
* This class manages a pool of threads. It uses a ThreadFactory to create
|
|
||||||
* threads. It never actually creates or destroys worker threads, rather
|
|
||||||
* It maintains statistics on number of idle threads, number of active threads,
|
|
||||||
* task backlog, and average wait and service times and informs the PoolPolicy
|
|
||||||
* object bound to instances of this manager of interesting transitions. It is
|
|
||||||
* then up the PoolPolicy object to decide if the thread pool size needs to be
|
|
||||||
* adjusted and call this object addWorker and removeWorker methods to make
|
|
||||||
* changes.
|
|
||||||
*
|
|
||||||
* This design allows different policy implementations to used this code to
|
|
||||||
* handle basic worker thread management and worker task execution and focus on
|
|
||||||
* policy issues. The simplest policy, StaticPolicy, does nothing other than
|
|
||||||
* create a fixed number of threads.
|
|
||||||
*/
|
|
||||||
class ThreadManager
|
|
||||||
{
|
|
||||||
|
|
||||||
protected:
|
|
||||||
ThreadManager() {}
|
|
||||||
|
|
||||||
public:
|
|
||||||
class Task;
|
|
||||||
typedef apache::thrift::stdcxx::function<void(boost::shared_ptr<Runnable>)> ExpireCallback;
|
|
||||||
|
|
||||||
virtual ~ThreadManager() {}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Starts the thread manager. Verifies all attributes have been properly
|
|
||||||
* initialized, then allocates necessary resources to begin operation
|
|
||||||
*/
|
|
||||||
virtual void start() = 0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Stops the thread manager. Aborts all remaining unprocessed task, shuts
|
|
||||||
* down all created worker threads, and realeases all allocated resources.
|
|
||||||
* This method blocks for all worker threads to complete, thus it can
|
|
||||||
* potentially block forever if a worker thread is running a task that
|
|
||||||
* won't terminate.
|
|
||||||
*/
|
|
||||||
virtual void stop() = 0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Joins the thread manager. This is the same as stop, except that it will
|
|
||||||
* block until all the workers have finished their work. At that point
|
|
||||||
* the ThreadManager will transition into the STOPPED state.
|
|
||||||
*/
|
|
||||||
virtual void join() = 0;
|
|
||||||
|
|
||||||
enum STATE
|
|
||||||
{
|
|
||||||
UNINITIALIZED,
|
|
||||||
STARTING,
|
|
||||||
STARTED,
|
|
||||||
JOINING,
|
|
||||||
STOPPING,
|
|
||||||
STOPPED
|
|
||||||
};
|
|
||||||
|
|
||||||
virtual STATE state() const = 0;
|
|
||||||
|
|
||||||
virtual boost::shared_ptr<ThreadFactory> threadFactory() const = 0;
|
|
||||||
|
|
||||||
virtual void threadFactory(boost::shared_ptr<ThreadFactory> value) = 0;
|
|
||||||
|
|
||||||
virtual void addWorker(size_t value = 1) = 0;
|
|
||||||
|
|
||||||
virtual void removeWorker(size_t value = 1) = 0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the current number of idle worker threads
|
|
||||||
*/
|
|
||||||
virtual size_t idleWorkerCount() const = 0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the current number of total worker threads
|
|
||||||
*/
|
|
||||||
virtual size_t workerCount() const = 0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the current number of pending tasks
|
|
||||||
*/
|
|
||||||
virtual size_t pendingTaskCount() const = 0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the current number of pending and executing tasks
|
|
||||||
*/
|
|
||||||
virtual size_t totalTaskCount() const = 0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the maximum pending task count. 0 indicates no maximum
|
|
||||||
*/
|
|
||||||
virtual size_t pendingTaskCountMax() const = 0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the number of tasks which have been expired without being run.
|
|
||||||
*/
|
|
||||||
virtual size_t expiredTaskCount() = 0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds a task to be executed at some time in the future by a worker thread.
|
|
||||||
*
|
|
||||||
* This method will block if pendingTaskCountMax() in not zero and pendingTaskCount()
|
|
||||||
* is greater than or equalt to pendingTaskCountMax(). If this method is called in the
|
|
||||||
* context of a ThreadManager worker thread it will throw a
|
|
||||||
* TooManyPendingTasksException
|
|
||||||
*
|
|
||||||
* @param task The task to queue for execution
|
|
||||||
*
|
|
||||||
* @param timeout Time to wait in milliseconds to add a task when a pending-task-count
|
|
||||||
* is specified. Specific cases:
|
|
||||||
* timeout = 0 : Wait forever to queue task.
|
|
||||||
* timeout = -1 : Return immediately if pending task count exceeds specified max
|
|
||||||
* @param expiration when nonzero, the number of milliseconds the task is valid
|
|
||||||
* to be run; if exceeded, the task will be dropped off the queue and not run.
|
|
||||||
*
|
|
||||||
* @throws TooManyPendingTasksException Pending task count exceeds max pending task count
|
|
||||||
*/
|
|
||||||
virtual void add(boost::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;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove the next pending task which would be run.
|
|
||||||
*
|
|
||||||
* @return the task removed.
|
|
||||||
*/
|
|
||||||
virtual boost::shared_ptr<Runnable> removeNextPending() = 0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove tasks from front of task queue that have expired.
|
|
||||||
*/
|
|
||||||
virtual void removeExpiredTasks() = 0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set a callback to be called when a task is expired and not run.
|
|
||||||
*
|
|
||||||
* @param expireCallback a function called with the shared_ptr<Runnable> for
|
|
||||||
* the expired task.
|
|
||||||
*/
|
|
||||||
virtual void setExpireCallback(ExpireCallback expireCallback) = 0;
|
|
||||||
|
|
||||||
static boost::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, size_t pendingTaskCountMax = 0);
|
|
||||||
|
|
||||||
class Task;
|
|
||||||
|
|
||||||
class Worker;
|
|
||||||
|
|
||||||
class Impl;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} // apache::thrift::concurrency
|
|
||||||
|
|
||||||
@@ -1,137 +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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <thrift/concurrency/Exception.h>
|
|
||||||
#include <thrift/concurrency/Monitor.h>
|
|
||||||
#include <thrift/concurrency/Thread.h>
|
|
||||||
|
|
||||||
#include <boost/shared_ptr.hpp>
|
|
||||||
#include <map>
|
|
||||||
#include <time.h>
|
|
||||||
|
|
||||||
namespace apache
|
|
||||||
{
|
|
||||||
namespace thrift
|
|
||||||
{
|
|
||||||
namespace concurrency
|
|
||||||
{
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Timer Manager
|
|
||||||
*
|
|
||||||
* This class dispatches timer tasks when they fall due.
|
|
||||||
*
|
|
||||||
* @version $Id:$
|
|
||||||
*/
|
|
||||||
class TimerManager
|
|
||||||
{
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
TimerManager();
|
|
||||||
|
|
||||||
virtual ~TimerManager();
|
|
||||||
|
|
||||||
virtual boost::shared_ptr<const ThreadFactory> threadFactory() const;
|
|
||||||
|
|
||||||
virtual void threadFactory(boost::shared_ptr<const ThreadFactory> value);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Starts the timer manager service
|
|
||||||
*
|
|
||||||
* @throws IllegalArgumentException Missing thread factory attribute
|
|
||||||
*/
|
|
||||||
virtual void start();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Stops the timer manager service
|
|
||||||
*/
|
|
||||||
virtual void stop();
|
|
||||||
|
|
||||||
virtual size_t taskCount() const ;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds a task to be executed at some time in the future by a worker thread.
|
|
||||||
*
|
|
||||||
* @param task The task to execute
|
|
||||||
* @param timeout Time in milliseconds to delay before executing task
|
|
||||||
*/
|
|
||||||
virtual void add(boost::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.
|
|
||||||
*/
|
|
||||||
virtual void add(boost::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.
|
|
||||||
*/
|
|
||||||
virtual void add(boost::shared_ptr<Runnable> task, const struct timeval& timeout);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Removes a pending task
|
|
||||||
*
|
|
||||||
* @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(boost::shared_ptr<Runnable> task);
|
|
||||||
|
|
||||||
enum STATE
|
|
||||||
{
|
|
||||||
UNINITIALIZED,
|
|
||||||
STARTING,
|
|
||||||
STARTED,
|
|
||||||
STOPPING,
|
|
||||||
STOPPED
|
|
||||||
};
|
|
||||||
|
|
||||||
virtual STATE state() const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
boost::shared_ptr<const ThreadFactory> threadFactory_;
|
|
||||||
class Task;
|
|
||||||
friend class Task;
|
|
||||||
std::multimap<int64_t, boost::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;
|
|
||||||
typedef std::pair<task_iterator, task_iterator> task_range;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} // apache::thrift::concurrency
|
|
||||||
|
|
||||||
@@ -1,175 +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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <assert.h>
|
|
||||||
#include <stddef.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <time.h>
|
|
||||||
|
|
||||||
#ifdef HAVE_SYS_TIME_H
|
|
||||||
#include <sys/time.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <thrift/transport/PlatformSocket.h>
|
|
||||||
|
|
||||||
namespace apache
|
|
||||||
{
|
|
||||||
namespace thrift
|
|
||||||
{
|
|
||||||
namespace concurrency
|
|
||||||
{
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Utility methods
|
|
||||||
*
|
|
||||||
* This class contains basic utility methods for converting time formats,
|
|
||||||
* and other common platform-dependent concurrency operations.
|
|
||||||
* It should not be included in API headers for other concurrency library
|
|
||||||
* headers, since it will, by definition, pull in all sorts of horrid
|
|
||||||
* platform dependent stuff. Rather it should be inluded directly in
|
|
||||||
* concurrency library implementation source.
|
|
||||||
*
|
|
||||||
* @version $Id:$
|
|
||||||
*/
|
|
||||||
class Util
|
|
||||||
{
|
|
||||||
|
|
||||||
static const int64_t NS_PER_S = 1000000000LL;
|
|
||||||
static const int64_t US_PER_S = 1000000LL;
|
|
||||||
static const int64_t MS_PER_S = 1000LL;
|
|
||||||
|
|
||||||
static const int64_t NS_PER_MS = NS_PER_S / MS_PER_S;
|
|
||||||
static const int64_t NS_PER_US = NS_PER_S / US_PER_S;
|
|
||||||
static const int64_t US_PER_MS = US_PER_S / MS_PER_S;
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Converts millisecond timestamp into a THRIFT_TIMESPEC struct
|
|
||||||
*
|
|
||||||
* @param struct THRIFT_TIMESPEC& result
|
|
||||||
* @param time or duration in milliseconds
|
|
||||||
*/
|
|
||||||
static void toTimespec(struct THRIFT_TIMESPEC& result, int64_t value)
|
|
||||||
{
|
|
||||||
result.tv_sec = value / MS_PER_S; // ms to s
|
|
||||||
result.tv_nsec = (value % MS_PER_S) * NS_PER_MS; // ms to ns
|
|
||||||
}
|
|
||||||
|
|
||||||
static void toTimeval(struct timeval& result, int64_t value)
|
|
||||||
{
|
|
||||||
result.tv_sec = static_cast<uint32_t>(value / MS_PER_S); // ms to s
|
|
||||||
result.tv_usec = static_cast<uint32_t>((value % MS_PER_S) * US_PER_MS); // ms to us
|
|
||||||
}
|
|
||||||
|
|
||||||
static void toTicks(int64_t& result, int64_t secs, int64_t oldTicks,
|
|
||||||
int64_t oldTicksPerSec, int64_t newTicksPerSec)
|
|
||||||
{
|
|
||||||
result = secs * newTicksPerSec;
|
|
||||||
result += oldTicks * newTicksPerSec / oldTicksPerSec;
|
|
||||||
|
|
||||||
int64_t oldPerNew = oldTicksPerSec / newTicksPerSec;
|
|
||||||
|
|
||||||
if (oldPerNew && ((oldTicks % oldPerNew) >= (oldPerNew / 2)))
|
|
||||||
{
|
|
||||||
++result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Converts struct THRIFT_TIMESPEC to arbitrary-sized ticks since epoch
|
|
||||||
*/
|
|
||||||
static void toTicks(int64_t& result,
|
|
||||||
const struct THRIFT_TIMESPEC& value,
|
|
||||||
int64_t ticksPerSec)
|
|
||||||
{
|
|
||||||
return toTicks(result, value.tv_sec, value.tv_nsec, NS_PER_S, ticksPerSec);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Converts struct timeval to arbitrary-sized ticks since epoch
|
|
||||||
*/
|
|
||||||
static void toTicks(int64_t& result,
|
|
||||||
const struct timeval& value,
|
|
||||||
int64_t ticksPerSec)
|
|
||||||
{
|
|
||||||
return toTicks(result, value.tv_sec, value.tv_usec, US_PER_S, ticksPerSec);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Converts struct THRIFT_TIMESPEC to milliseconds
|
|
||||||
*/
|
|
||||||
static void toMilliseconds(int64_t& result,
|
|
||||||
const struct THRIFT_TIMESPEC& value)
|
|
||||||
{
|
|
||||||
return toTicks(result, value, MS_PER_S);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Converts struct timeval to milliseconds
|
|
||||||
*/
|
|
||||||
static void toMilliseconds(int64_t& result,
|
|
||||||
const struct timeval& value)
|
|
||||||
{
|
|
||||||
return toTicks(result, value, MS_PER_S);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Converts struct THRIFT_TIMESPEC to microseconds
|
|
||||||
*/
|
|
||||||
static void toUsec(int64_t& result, const struct THRIFT_TIMESPEC& value)
|
|
||||||
{
|
|
||||||
return toTicks(result, value, US_PER_S);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Converts struct timeval to microseconds
|
|
||||||
*/
|
|
||||||
static void toUsec(int64_t& result, const struct timeval& value)
|
|
||||||
{
|
|
||||||
return toTicks(result, value, US_PER_S);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get current time as a number of arbitrary-size ticks from epoch
|
|
||||||
*/
|
|
||||||
static int64_t currentTimeTicks(int64_t ticksPerSec);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get current time as milliseconds from epoch
|
|
||||||
*/
|
|
||||||
static int64_t currentTime()
|
|
||||||
{
|
|
||||||
return currentTimeTicks(MS_PER_S);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get current time as micros from epoch
|
|
||||||
*/
|
|
||||||
static int64_t currentTimeUsec()
|
|
||||||
{
|
|
||||||
return currentTimeTicks(US_PER_S);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} // apache::thrift::concurrency
|
|
||||||
|
|
||||||
@@ -1,148 +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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
#ifdef _WIN32
|
|
||||||
#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
|
|
||||||
#include <tr1/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
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Alias for thrift c++ compatibility namespace
|
|
||||||
namespace tcxx = apache::thrift::stdcxx;
|
|
||||||
|
|
||||||
@@ -1,84 +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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include <thrift/TProcessor.h>
|
|
||||||
#include <thrift/transport/TTransport.h>
|
|
||||||
#include <thrift/transport/TTransportUtils.h>
|
|
||||||
#include <thrift/transport/TBufferTransports.h>
|
|
||||||
#include <boost/shared_ptr.hpp>
|
|
||||||
|
|
||||||
namespace apache
|
|
||||||
{
|
|
||||||
namespace thrift
|
|
||||||
{
|
|
||||||
namespace processor
|
|
||||||
{
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Class for peeking at the raw data that is being processed by another processor
|
|
||||||
* and gives the derived class a chance to change behavior accordingly
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
class PeekProcessor : public apache::thrift::TProcessor
|
|
||||||
{
|
|
||||||
|
|
||||||
public:
|
|
||||||
PeekProcessor();
|
|
||||||
virtual ~PeekProcessor();
|
|
||||||
|
|
||||||
// Input here: actualProcessor - the underlying processor
|
|
||||||
// protocolFactory - the protocol factory used to wrap the memory buffer
|
|
||||||
// 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);
|
|
||||||
|
|
||||||
boost::shared_ptr<apache::thrift::transport::TTransport> getPipedTransport(boost::shared_ptr<apache::thrift::transport::TTransport> in);
|
|
||||||
|
|
||||||
void setTargetTransport(boost::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,
|
|
||||||
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,
|
|
||||||
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_;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} // apache::thrift::processor
|
|
||||||
|
|
||||||
@@ -1,362 +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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <boost/shared_ptr.hpp>
|
|
||||||
#include <thrift/transport/TTransport.h>
|
|
||||||
#include <thrift/protocol/TProtocol.h>
|
|
||||||
#include <TProcessor.h>
|
|
||||||
|
|
||||||
namespace apache
|
|
||||||
{
|
|
||||||
namespace thrift
|
|
||||||
{
|
|
||||||
namespace processor
|
|
||||||
{
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Class for keeping track of function call statistics and printing them if desired
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
class StatsProcessor : public apache::thrift::TProcessor
|
|
||||||
{
|
|
||||||
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,
|
|
||||||
void* serverContext)
|
|
||||||
{
|
|
||||||
|
|
||||||
piprot_ = piprot;
|
|
||||||
|
|
||||||
std::string fname;
|
|
||||||
apache::thrift::protocol::TMessageType mtype;
|
|
||||||
int32_t seqid;
|
|
||||||
|
|
||||||
piprot_->readMessageBegin(fname, mtype, seqid);
|
|
||||||
|
|
||||||
if (mtype != apache::thrift::protocol::T_CALL)
|
|
||||||
{
|
|
||||||
if (print_)
|
|
||||||
{
|
|
||||||
printf("Unknown message type\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
throw apache::thrift::TException("Unexpected message type");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (print_)
|
|
||||||
{
|
|
||||||
printf("%s (", fname.c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (frequency_)
|
|
||||||
{
|
|
||||||
if (frequency_map_.find(fname) != frequency_map_.end())
|
|
||||||
{
|
|
||||||
frequency_map_[fname]++;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
frequency_map_[fname] = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
apache::thrift::protocol::TType ftype;
|
|
||||||
int16_t fid;
|
|
||||||
|
|
||||||
while (true)
|
|
||||||
{
|
|
||||||
piprot_->readFieldBegin(fname, ftype, fid);
|
|
||||||
|
|
||||||
if (ftype == apache::thrift::protocol::T_STOP)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
printAndPassToBuffer(ftype);
|
|
||||||
|
|
||||||
if (print_)
|
|
||||||
{
|
|
||||||
printf(", ");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (print_)
|
|
||||||
{
|
|
||||||
printf("\b\b)\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
const std::map<std::string, int64_t>& get_frequency_map()
|
|
||||||
{
|
|
||||||
return frequency_map_;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
void printAndPassToBuffer(apache::thrift::protocol::TType ftype)
|
|
||||||
{
|
|
||||||
switch (ftype)
|
|
||||||
{
|
|
||||||
case apache::thrift::protocol::T_BOOL:
|
|
||||||
{
|
|
||||||
bool boolv;
|
|
||||||
piprot_->readBool(boolv);
|
|
||||||
|
|
||||||
if (print_)
|
|
||||||
{
|
|
||||||
printf("%d", boolv);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case apache::thrift::protocol::T_BYTE:
|
|
||||||
{
|
|
||||||
int8_t bytev;
|
|
||||||
piprot_->readByte(bytev);
|
|
||||||
|
|
||||||
if (print_)
|
|
||||||
{
|
|
||||||
printf("%d", bytev);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case apache::thrift::protocol::T_I16:
|
|
||||||
{
|
|
||||||
int16_t i16;
|
|
||||||
piprot_->readI16(i16);
|
|
||||||
|
|
||||||
if (print_)
|
|
||||||
{
|
|
||||||
printf("%d", i16);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case apache::thrift::protocol::T_I32:
|
|
||||||
{
|
|
||||||
int32_t i32;
|
|
||||||
piprot_->readI32(i32);
|
|
||||||
|
|
||||||
if (print_)
|
|
||||||
{
|
|
||||||
printf("%d", i32);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case apache::thrift::protocol::T_I64:
|
|
||||||
{
|
|
||||||
int64_t i64;
|
|
||||||
piprot_->readI64(i64);
|
|
||||||
|
|
||||||
if (print_)
|
|
||||||
{
|
|
||||||
printf("%ld", i64);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case apache::thrift::protocol::T_DOUBLE:
|
|
||||||
{
|
|
||||||
double dub;
|
|
||||||
piprot_->readDouble(dub);
|
|
||||||
|
|
||||||
if (print_)
|
|
||||||
{
|
|
||||||
printf("%f", dub);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case apache::thrift::protocol::T_STRING:
|
|
||||||
{
|
|
||||||
std::string str;
|
|
||||||
piprot_->readString(str);
|
|
||||||
|
|
||||||
if (print_)
|
|
||||||
{
|
|
||||||
printf("%s", str.c_str());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case apache::thrift::protocol::T_STRUCT:
|
|
||||||
{
|
|
||||||
std::string name;
|
|
||||||
int16_t fid;
|
|
||||||
apache::thrift::protocol::TType ftype;
|
|
||||||
piprot_->readStructBegin(name);
|
|
||||||
|
|
||||||
if (print_)
|
|
||||||
{
|
|
||||||
printf("<");
|
|
||||||
}
|
|
||||||
|
|
||||||
while (true)
|
|
||||||
{
|
|
||||||
piprot_->readFieldBegin(name, ftype, fid);
|
|
||||||
|
|
||||||
if (ftype == apache::thrift::protocol::T_STOP)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
printAndPassToBuffer(ftype);
|
|
||||||
|
|
||||||
if (print_)
|
|
||||||
{
|
|
||||||
printf(",");
|
|
||||||
}
|
|
||||||
|
|
||||||
piprot_->readFieldEnd();
|
|
||||||
}
|
|
||||||
|
|
||||||
piprot_->readStructEnd();
|
|
||||||
|
|
||||||
if (print_)
|
|
||||||
{
|
|
||||||
printf("\b>");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case apache::thrift::protocol::T_MAP:
|
|
||||||
{
|
|
||||||
apache::thrift::protocol::TType keyType;
|
|
||||||
apache::thrift::protocol::TType valType;
|
|
||||||
uint32_t i, size;
|
|
||||||
piprot_->readMapBegin(keyType, valType, size);
|
|
||||||
|
|
||||||
if (print_)
|
|
||||||
{
|
|
||||||
printf("{");
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < size; i++)
|
|
||||||
{
|
|
||||||
printAndPassToBuffer(keyType);
|
|
||||||
|
|
||||||
if (print_)
|
|
||||||
{
|
|
||||||
printf("=>");
|
|
||||||
}
|
|
||||||
|
|
||||||
printAndPassToBuffer(valType);
|
|
||||||
|
|
||||||
if (print_)
|
|
||||||
{
|
|
||||||
printf(",");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
piprot_->readMapEnd();
|
|
||||||
|
|
||||||
if (print_)
|
|
||||||
{
|
|
||||||
printf("\b}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case apache::thrift::protocol::T_SET:
|
|
||||||
{
|
|
||||||
apache::thrift::protocol::TType elemType;
|
|
||||||
uint32_t i, size;
|
|
||||||
piprot_->readSetBegin(elemType, size);
|
|
||||||
|
|
||||||
if (print_)
|
|
||||||
{
|
|
||||||
printf("{");
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < size; i++)
|
|
||||||
{
|
|
||||||
printAndPassToBuffer(elemType);
|
|
||||||
|
|
||||||
if (print_)
|
|
||||||
{
|
|
||||||
printf(",");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
piprot_->readSetEnd();
|
|
||||||
|
|
||||||
if (print_)
|
|
||||||
{
|
|
||||||
printf("\b}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case apache::thrift::protocol::T_LIST:
|
|
||||||
{
|
|
||||||
apache::thrift::protocol::TType elemType;
|
|
||||||
uint32_t i, size;
|
|
||||||
piprot_->readListBegin(elemType, size);
|
|
||||||
|
|
||||||
if (print_)
|
|
||||||
{
|
|
||||||
printf("[");
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < size; i++)
|
|
||||||
{
|
|
||||||
printAndPassToBuffer(elemType);
|
|
||||||
|
|
||||||
if (print_)
|
|
||||||
{
|
|
||||||
printf(",");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
piprot_->readListEnd();
|
|
||||||
|
|
||||||
if (print_)
|
|
||||||
{
|
|
||||||
printf("\b]");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
boost::shared_ptr<apache::thrift::protocol::TProtocol> piprot_;
|
|
||||||
std::map<std::string, int64_t> frequency_map_;
|
|
||||||
|
|
||||||
bool print_;
|
|
||||||
bool frequency_;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} // apache::thrift::processor
|
|
||||||
|
|
||||||
@@ -1,219 +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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <thrift/protocol/TProtocolDecorator.h>
|
|
||||||
#include <thrift/TApplicationException.h>
|
|
||||||
#include <thrift/TProcessor.h>
|
|
||||||
#include <boost/tokenizer.hpp>
|
|
||||||
|
|
||||||
namespace apache
|
|
||||||
{
|
|
||||||
namespace thrift
|
|
||||||
{
|
|
||||||
using boost::shared_ptr;
|
|
||||||
|
|
||||||
namespace protocol
|
|
||||||
{
|
|
||||||
|
|
||||||
/**
|
|
||||||
* To be able to work with any protocol, we needed
|
|
||||||
* to allow them to call readMessageBegin() and get a TMessage in exactly
|
|
||||||
* the standard format, without the service name prepended to TMessage.name.
|
|
||||||
*/
|
|
||||||
class StoredMessageProtocol : public TProtocolDecorator
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
StoredMessageProtocol( shared_ptr<protocol::TProtocol> _protocol,
|
|
||||||
const std::string& _name, const TMessageType _type,
|
|
||||||
const int32_t _seqid) :
|
|
||||||
TProtocolDecorator(_protocol),
|
|
||||||
name(_name),
|
|
||||||
type(_type),
|
|
||||||
seqid(_seqid)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t readMessageBegin_virt(std::string& _name, TMessageType& _type, int32_t& _seqid)
|
|
||||||
{
|
|
||||||
|
|
||||||
_name = name;
|
|
||||||
_type = type;
|
|
||||||
_seqid = seqid;
|
|
||||||
|
|
||||||
return 0; // (Normal TProtocol read functions return number of bytes read)
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string name;
|
|
||||||
TMessageType type;
|
|
||||||
int32_t seqid;
|
|
||||||
};
|
|
||||||
} //namespace protocol
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <code>TMultiplexedProcessor</code> is a <code>TProcessor</code> allowing
|
|
||||||
* a single <code>TServer</code> to provide multiple services.
|
|
||||||
*
|
|
||||||
* <p>To do so, you instantiate the processor and then register additional
|
|
||||||
* processors with it, as shown in the following example:</p>
|
|
||||||
*
|
|
||||||
* <blockquote><code>
|
|
||||||
* shared_ptr<TMultiplexedProcessor> processor(new TMultiplexedProcessor());
|
|
||||||
*
|
|
||||||
* processor->registerProcessor(
|
|
||||||
* "Calculator",
|
|
||||||
* shared_ptr<TProcessor>( new CalculatorProcessor(
|
|
||||||
* shared_ptr<CalculatorHandler>( new CalculatorHandler()))));
|
|
||||||
*
|
|
||||||
* processor->registerProcessor(
|
|
||||||
* "WeatherReport",
|
|
||||||
* shared_ptr<TProcessor>( new WeatherReportProcessor(
|
|
||||||
* shared_ptr<WeatherReportHandler>( new WeatherReportHandler()))));
|
|
||||||
*
|
|
||||||
* shared_ptr<TServerTransport> transport(new TServerSocket(9090));
|
|
||||||
* TSimpleServer server(processor, transport);
|
|
||||||
*
|
|
||||||
* server.serve();
|
|
||||||
* </code></blockquote>
|
|
||||||
*/
|
|
||||||
class TMultiplexedProcessor : public TProcessor
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
typedef std::map< std::string, shared_ptr<TProcessor> > services_t;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 'Register' a service with this <code>TMultiplexedProcessor</code>. This
|
|
||||||
* allows us to broker requests to individual services by using the service
|
|
||||||
* name to select them at request time.
|
|
||||||
*
|
|
||||||
* \param [in] serviceName Name of a service, has to be identical to the name
|
|
||||||
* declared in the Thrift IDL, e.g. "WeatherReport".
|
|
||||||
* \param [in] processor Implementation of a service, ususally referred to
|
|
||||||
* as "handlers", e.g. WeatherReportHandler,
|
|
||||||
* implementing WeatherReportIf interface.
|
|
||||||
*/
|
|
||||||
void registerProcessor( const std::string& serviceName,
|
|
||||||
shared_ptr<TProcessor> processor )
|
|
||||||
{
|
|
||||||
services[serviceName] = processor;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This implementation of <code>process</code> performs the following steps:
|
|
||||||
*
|
|
||||||
* <ol>
|
|
||||||
* <li>Read the beginning of the message.</li>
|
|
||||||
* <li>Extract the service name from the message.</li>
|
|
||||||
* <li>Using the service name to locate the appropriate processor.</li>
|
|
||||||
* <li>Dispatch to the processor, with a decorated instance of TProtocol
|
|
||||||
* that allows readMessageBegin() to return the original TMessage.</li>
|
|
||||||
* </ol>
|
|
||||||
*
|
|
||||||
* \throws TException If the message type is not T_CALL or T_ONEWAY, if
|
|
||||||
* 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,
|
|
||||||
void* connectionContext)
|
|
||||||
{
|
|
||||||
std::string name;
|
|
||||||
protocol::TMessageType type;
|
|
||||||
int32_t seqid;
|
|
||||||
|
|
||||||
// Use the actual underlying protocol (e.g. TBinaryProtocol) to read the
|
|
||||||
// message header. This pulls the message "off the wire", which we'll
|
|
||||||
// deal with at the end of this method.
|
|
||||||
in->readMessageBegin(name, type, seqid);
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Extract the service name
|
|
||||||
|
|
||||||
boost::tokenizer<boost::char_separator<char> > tok( name, boost::char_separator<char>(":") );
|
|
||||||
|
|
||||||
std::vector<std::string> tokens;
|
|
||||||
std::copy( tok.begin(), tok.end(), std::back_inserter(tokens) );
|
|
||||||
|
|
||||||
// A valid message should consist of two tokens: the service
|
|
||||||
// name and the name of the method to call.
|
|
||||||
if ( tokens.size() == 2 )
|
|
||||||
{
|
|
||||||
// Search for a processor associated with this service name.
|
|
||||||
services_t::iterator it = services.find(tokens[0]);
|
|
||||||
|
|
||||||
if ( it != services.end() )
|
|
||||||
{
|
|
||||||
shared_ptr<TProcessor> processor = it->second;
|
|
||||||
// Let the processor registered for this service name
|
|
||||||
// process the message.
|
|
||||||
return processor->process(
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
/** Map of service processor objects, indexed by service names. */
|
|
||||||
services_t services;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,47 +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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
namespace apache
|
|
||||||
{
|
|
||||||
namespace thrift
|
|
||||||
{
|
|
||||||
namespace protocol
|
|
||||||
{
|
|
||||||
|
|
||||||
// in must be at least len bytes
|
|
||||||
// len must be 1, 2, or 3
|
|
||||||
// buf must be a buffer of at least 4 bytes and may not overlap in
|
|
||||||
// the data is not padded with '='; the caller can do this if desired
|
|
||||||
void base64_encode(const uint8_t* in, uint32_t len, uint8_t* buf);
|
|
||||||
|
|
||||||
// buf must be a buffer of at least 4 bytes and contain base64 encoded values
|
|
||||||
// buf will be changed to contain output bytes
|
|
||||||
// len is number of bytes to consume from input (must be 2, 3, or 4)
|
|
||||||
// no '=' padding should be included in the input
|
|
||||||
void base64_decode(uint8_t* buf, uint32_t len);
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} // apache::thrift::protocol
|
|
||||||
|
|
||||||
@@ -1,302 +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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <thrift/protocol/TProtocol.h>
|
|
||||||
#include <thrift/protocol/TVirtualProtocol.h>
|
|
||||||
|
|
||||||
#include <boost/shared_ptr.hpp>
|
|
||||||
|
|
||||||
namespace apache
|
|
||||||
{
|
|
||||||
namespace thrift
|
|
||||||
{
|
|
||||||
namespace protocol
|
|
||||||
{
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The default binary protocol for thrift. Writes all data in a very basic
|
|
||||||
* binary format, essentially just spitting out the raw bytes.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
template <class Transport_>
|
|
||||||
class TBinaryProtocolT
|
|
||||||
: public TVirtualProtocol< TBinaryProtocolT<Transport_> >
|
|
||||||
{
|
|
||||||
protected:
|
|
||||||
static const int32_t VERSION_MASK = ((int32_t)0xffff0000);
|
|
||||||
static const int32_t VERSION_1 = ((int32_t)0x80010000);
|
|
||||||
// VERSION_2 (0x80020000) is taken by TDenseProtocol.
|
|
||||||
|
|
||||||
public:
|
|
||||||
TBinaryProtocolT(boost::shared_ptr<Transport_> trans) :
|
|
||||||
TVirtualProtocol< TBinaryProtocolT<Transport_> >(trans),
|
|
||||||
trans_(trans.get()),
|
|
||||||
string_limit_(0),
|
|
||||||
container_limit_(0),
|
|
||||||
strict_read_(false),
|
|
||||||
strict_write_(true),
|
|
||||||
string_buf_(NULL),
|
|
||||||
string_buf_size_(0) {}
|
|
||||||
|
|
||||||
TBinaryProtocolT(boost::shared_ptr<Transport_> trans,
|
|
||||||
int32_t string_limit,
|
|
||||||
int32_t container_limit,
|
|
||||||
bool strict_read,
|
|
||||||
bool strict_write) :
|
|
||||||
TVirtualProtocol< TBinaryProtocolT<Transport_> >(trans),
|
|
||||||
trans_(trans.get()),
|
|
||||||
string_limit_(string_limit),
|
|
||||||
container_limit_(container_limit),
|
|
||||||
strict_read_(strict_read),
|
|
||||||
strict_write_(strict_write),
|
|
||||||
string_buf_(NULL),
|
|
||||||
string_buf_size_(0) {}
|
|
||||||
|
|
||||||
~TBinaryProtocolT()
|
|
||||||
{
|
|
||||||
if (string_buf_ != NULL)
|
|
||||||
{
|
|
||||||
std::free(string_buf_);
|
|
||||||
string_buf_size_ = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void setStringSizeLimit(int32_t string_limit)
|
|
||||||
{
|
|
||||||
string_limit_ = string_limit;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setContainerSizeLimit(int32_t container_limit)
|
|
||||||
{
|
|
||||||
container_limit_ = container_limit;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setStrict(bool strict_read, bool strict_write)
|
|
||||||
{
|
|
||||||
strict_read_ = strict_read;
|
|
||||||
strict_write_ = strict_write;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Writing functions.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*ol*/ uint32_t writeMessageBegin(const std::string& name,
|
|
||||||
const TMessageType messageType,
|
|
||||||
const int32_t seqid);
|
|
||||||
|
|
||||||
/*ol*/ uint32_t writeMessageEnd();
|
|
||||||
|
|
||||||
|
|
||||||
inline uint32_t writeStructBegin(const char* name);
|
|
||||||
|
|
||||||
inline uint32_t writeStructEnd();
|
|
||||||
|
|
||||||
inline uint32_t writeFieldBegin(const char* name,
|
|
||||||
const TType fieldType,
|
|
||||||
const int16_t fieldId);
|
|
||||||
|
|
||||||
inline uint32_t writeFieldEnd();
|
|
||||||
|
|
||||||
inline uint32_t writeFieldStop();
|
|
||||||
|
|
||||||
inline uint32_t writeMapBegin(const TType keyType,
|
|
||||||
const TType valType,
|
|
||||||
const uint32_t size);
|
|
||||||
|
|
||||||
inline uint32_t writeMapEnd();
|
|
||||||
|
|
||||||
inline uint32_t writeListBegin(const TType elemType, const uint32_t size);
|
|
||||||
|
|
||||||
inline uint32_t writeListEnd();
|
|
||||||
|
|
||||||
inline uint32_t writeSetBegin(const TType elemType, const uint32_t size);
|
|
||||||
|
|
||||||
inline uint32_t writeSetEnd();
|
|
||||||
|
|
||||||
inline uint32_t writeBool(const bool value);
|
|
||||||
|
|
||||||
inline uint32_t writeByte(const int8_t byte);
|
|
||||||
|
|
||||||
inline uint32_t writeI16(const int16_t i16);
|
|
||||||
|
|
||||||
inline uint32_t writeI32(const int32_t i32);
|
|
||||||
|
|
||||||
inline uint32_t writeI64(const int64_t i64);
|
|
||||||
|
|
||||||
inline uint32_t writeDouble(const double dub);
|
|
||||||
|
|
||||||
template <typename StrType>
|
|
||||||
inline uint32_t writeString(const StrType& str);
|
|
||||||
|
|
||||||
inline uint32_t writeBinary(const std::string& str);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reading functions
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
/*ol*/ uint32_t readMessageBegin(std::string& name,
|
|
||||||
TMessageType& messageType,
|
|
||||||
int32_t& seqid);
|
|
||||||
|
|
||||||
/*ol*/ uint32_t readMessageEnd();
|
|
||||||
|
|
||||||
inline uint32_t readStructBegin(std::string& name);
|
|
||||||
|
|
||||||
inline uint32_t readStructEnd();
|
|
||||||
|
|
||||||
inline uint32_t readFieldBegin(std::string& name,
|
|
||||||
TType& fieldType,
|
|
||||||
int16_t& fieldId);
|
|
||||||
|
|
||||||
inline uint32_t readFieldEnd();
|
|
||||||
|
|
||||||
inline uint32_t readMapBegin(TType& keyType,
|
|
||||||
TType& valType,
|
|
||||||
uint32_t& size);
|
|
||||||
|
|
||||||
inline uint32_t readMapEnd();
|
|
||||||
|
|
||||||
inline uint32_t readListBegin(TType& elemType, uint32_t& size);
|
|
||||||
|
|
||||||
inline uint32_t readListEnd();
|
|
||||||
|
|
||||||
inline uint32_t readSetBegin(TType& elemType, uint32_t& size);
|
|
||||||
|
|
||||||
inline uint32_t readSetEnd();
|
|
||||||
|
|
||||||
inline uint32_t readBool(bool& value);
|
|
||||||
// Provide the default readBool() implementation for std::vector<bool>
|
|
||||||
using TVirtualProtocol< TBinaryProtocolT<Transport_> >::readBool;
|
|
||||||
|
|
||||||
inline uint32_t readByte(int8_t& byte);
|
|
||||||
|
|
||||||
inline uint32_t readI16(int16_t& i16);
|
|
||||||
|
|
||||||
inline uint32_t readI32(int32_t& i32);
|
|
||||||
|
|
||||||
inline uint32_t readI64(int64_t& i64);
|
|
||||||
|
|
||||||
inline uint32_t readDouble(double& dub);
|
|
||||||
|
|
||||||
template<typename StrType>
|
|
||||||
inline uint32_t readString(StrType& str);
|
|
||||||
|
|
||||||
inline uint32_t readBinary(std::string& str);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
template<typename StrType>
|
|
||||||
uint32_t readStringBody(StrType& str, int32_t sz);
|
|
||||||
|
|
||||||
Transport_* trans_;
|
|
||||||
|
|
||||||
int32_t string_limit_;
|
|
||||||
int32_t container_limit_;
|
|
||||||
|
|
||||||
// Enforce presence of version identifier
|
|
||||||
bool strict_read_;
|
|
||||||
bool strict_write_;
|
|
||||||
|
|
||||||
// Buffer for reading strings, save for the lifetime of the protocol to
|
|
||||||
// avoid memory churn allocating memory on every string read
|
|
||||||
uint8_t* string_buf_;
|
|
||||||
int32_t string_buf_size_;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef TBinaryProtocolT<TTransport> TBinaryProtocol;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructs binary protocol handlers
|
|
||||||
*/
|
|
||||||
template <class Transport_>
|
|
||||||
class TBinaryProtocolFactoryT : public TProtocolFactory
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
TBinaryProtocolFactoryT() :
|
|
||||||
string_limit_(0),
|
|
||||||
container_limit_(0),
|
|
||||||
strict_read_(false),
|
|
||||||
strict_write_(true) {}
|
|
||||||
|
|
||||||
TBinaryProtocolFactoryT(int32_t string_limit, int32_t container_limit,
|
|
||||||
bool strict_read, bool strict_write) :
|
|
||||||
string_limit_(string_limit),
|
|
||||||
container_limit_(container_limit),
|
|
||||||
strict_read_(strict_read),
|
|
||||||
strict_write_(strict_write) {}
|
|
||||||
|
|
||||||
virtual ~TBinaryProtocolFactoryT() {}
|
|
||||||
|
|
||||||
void setStringSizeLimit(int32_t string_limit)
|
|
||||||
{
|
|
||||||
string_limit_ = string_limit;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setContainerSizeLimit(int32_t container_limit)
|
|
||||||
{
|
|
||||||
container_limit_ = container_limit;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setStrict(bool strict_read, bool strict_write)
|
|
||||||
{
|
|
||||||
strict_read_ = strict_read;
|
|
||||||
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);
|
|
||||||
TProtocol* prot;
|
|
||||||
|
|
||||||
if (specific_trans)
|
|
||||||
{
|
|
||||||
prot = new TBinaryProtocolT<Transport_>(specific_trans, string_limit_,
|
|
||||||
container_limit_, strict_read_,
|
|
||||||
strict_write_);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
prot = new TBinaryProtocol(trans, string_limit_, container_limit_,
|
|
||||||
strict_read_, strict_write_);
|
|
||||||
}
|
|
||||||
|
|
||||||
return boost::shared_ptr<TProtocol>(prot);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
int32_t string_limit_;
|
|
||||||
int32_t container_limit_;
|
|
||||||
bool strict_read_;
|
|
||||||
bool strict_write_;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef TBinaryProtocolFactoryT<TTransport> TBinaryProtocolFactory;
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} // apache::thrift::protocol
|
|
||||||
|
|
||||||
#include <thrift/protocol/TBinaryProtocol.tcc>
|
|
||||||
|
|
||||||
@@ -1,465 +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_PROTOCOL_TBINARYPROTOCOL_TCC_
|
|
||||||
#define _THRIFT_PROTOCOL_TBINARYPROTOCOL_TCC_ 1
|
|
||||||
|
|
||||||
#include <thrift/protocol/TBinaryProtocol.h>
|
|
||||||
|
|
||||||
#include <limits>
|
|
||||||
|
|
||||||
|
|
||||||
namespace apache { namespace thrift { namespace protocol {
|
|
||||||
|
|
||||||
template <class Transport_>
|
|
||||||
uint32_t TBinaryProtocolT<Transport_>::writeMessageBegin(const std::string& name,
|
|
||||||
const TMessageType messageType,
|
|
||||||
const int32_t seqid) {
|
|
||||||
if (this->strict_write_) {
|
|
||||||
int32_t version = (VERSION_1) | ((int32_t)messageType);
|
|
||||||
uint32_t wsize = 0;
|
|
||||||
wsize += writeI32(version);
|
|
||||||
wsize += writeString(name);
|
|
||||||
wsize += writeI32(seqid);
|
|
||||||
return wsize;
|
|
||||||
} else {
|
|
||||||
uint32_t wsize = 0;
|
|
||||||
wsize += writeString(name);
|
|
||||||
wsize += writeByte((int8_t)messageType);
|
|
||||||
wsize += writeI32(seqid);
|
|
||||||
return wsize;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class Transport_>
|
|
||||||
uint32_t TBinaryProtocolT<Transport_>::writeMessageEnd() {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class Transport_>
|
|
||||||
uint32_t TBinaryProtocolT<Transport_>::writeStructBegin(const char* name) {
|
|
||||||
(void) name;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class Transport_>
|
|
||||||
uint32_t TBinaryProtocolT<Transport_>::writeStructEnd() {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class Transport_>
|
|
||||||
uint32_t TBinaryProtocolT<Transport_>::writeFieldBegin(const char* name,
|
|
||||||
const TType fieldType,
|
|
||||||
const int16_t fieldId) {
|
|
||||||
(void) name;
|
|
||||||
uint32_t wsize = 0;
|
|
||||||
wsize += writeByte((int8_t)fieldType);
|
|
||||||
wsize += writeI16(fieldId);
|
|
||||||
return wsize;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class Transport_>
|
|
||||||
uint32_t TBinaryProtocolT<Transport_>::writeFieldEnd() {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class Transport_>
|
|
||||||
uint32_t TBinaryProtocolT<Transport_>::writeFieldStop() {
|
|
||||||
return
|
|
||||||
writeByte((int8_t)T_STOP);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class Transport_>
|
|
||||||
uint32_t TBinaryProtocolT<Transport_>::writeMapBegin(const TType keyType,
|
|
||||||
const TType valType,
|
|
||||||
const uint32_t size) {
|
|
||||||
uint32_t wsize = 0;
|
|
||||||
wsize += writeByte((int8_t)keyType);
|
|
||||||
wsize += writeByte((int8_t)valType);
|
|
||||||
wsize += writeI32((int32_t)size);
|
|
||||||
return wsize;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class Transport_>
|
|
||||||
uint32_t TBinaryProtocolT<Transport_>::writeMapEnd() {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class Transport_>
|
|
||||||
uint32_t TBinaryProtocolT<Transport_>::writeListBegin(const TType elemType,
|
|
||||||
const uint32_t size) {
|
|
||||||
uint32_t wsize = 0;
|
|
||||||
wsize += writeByte((int8_t) elemType);
|
|
||||||
wsize += writeI32((int32_t)size);
|
|
||||||
return wsize;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class Transport_>
|
|
||||||
uint32_t TBinaryProtocolT<Transport_>::writeListEnd() {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class Transport_>
|
|
||||||
uint32_t TBinaryProtocolT<Transport_>::writeSetBegin(const TType elemType,
|
|
||||||
const uint32_t size) {
|
|
||||||
uint32_t wsize = 0;
|
|
||||||
wsize += writeByte((int8_t)elemType);
|
|
||||||
wsize += writeI32((int32_t)size);
|
|
||||||
return wsize;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class Transport_>
|
|
||||||
uint32_t TBinaryProtocolT<Transport_>::writeSetEnd() {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class Transport_>
|
|
||||||
uint32_t TBinaryProtocolT<Transport_>::writeBool(const bool value) {
|
|
||||||
uint8_t tmp = value ? 1 : 0;
|
|
||||||
this->trans_->write(&tmp, 1);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class Transport_>
|
|
||||||
uint32_t TBinaryProtocolT<Transport_>::writeByte(const int8_t byte) {
|
|
||||||
this->trans_->write((uint8_t*)&byte, 1);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class Transport_>
|
|
||||||
uint32_t TBinaryProtocolT<Transport_>::writeI16(const int16_t i16) {
|
|
||||||
int16_t net = (int16_t)htons(i16);
|
|
||||||
this->trans_->write((uint8_t*)&net, 2);
|
|
||||||
return 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class Transport_>
|
|
||||||
uint32_t TBinaryProtocolT<Transport_>::writeI32(const int32_t i32) {
|
|
||||||
int32_t net = (int32_t)htonl(i32);
|
|
||||||
this->trans_->write((uint8_t*)&net, 4);
|
|
||||||
return 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class Transport_>
|
|
||||||
uint32_t TBinaryProtocolT<Transport_>::writeI64(const int64_t i64) {
|
|
||||||
int64_t net = (int64_t)htonll(i64);
|
|
||||||
this->trans_->write((uint8_t*)&net, 8);
|
|
||||||
return 8;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class Transport_>
|
|
||||||
uint32_t TBinaryProtocolT<Transport_>::writeDouble(const double dub) {
|
|
||||||
BOOST_STATIC_ASSERT(sizeof(double) == sizeof(uint64_t));
|
|
||||||
BOOST_STATIC_ASSERT(std::numeric_limits<double>::is_iec559);
|
|
||||||
|
|
||||||
uint64_t bits = bitwise_cast<uint64_t>(dub);
|
|
||||||
bits = htonll(bits);
|
|
||||||
this->trans_->write((uint8_t*)&bits, 8);
|
|
||||||
return 8;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template <class Transport_>
|
|
||||||
template<typename StrType>
|
|
||||||
uint32_t TBinaryProtocolT<Transport_>::writeString(const StrType& str) {
|
|
||||||
if(str.size() > static_cast<size_t>((std::numeric_limits<int32_t>::max)()))
|
|
||||||
throw TProtocolException(TProtocolException::SIZE_LIMIT);
|
|
||||||
uint32_t size = static_cast<uint32_t>(str.size());
|
|
||||||
uint32_t result = writeI32((int32_t)size);
|
|
||||||
if (size > 0) {
|
|
||||||
this->trans_->write((uint8_t*)str.data(), size);
|
|
||||||
}
|
|
||||||
return result + size;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class Transport_>
|
|
||||||
uint32_t TBinaryProtocolT<Transport_>::writeBinary(const std::string& str) {
|
|
||||||
return TBinaryProtocolT<Transport_>::writeString(str);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reading functions
|
|
||||||
*/
|
|
||||||
|
|
||||||
template <class Transport_>
|
|
||||||
uint32_t TBinaryProtocolT<Transport_>::readMessageBegin(std::string& name,
|
|
||||||
TMessageType& messageType,
|
|
||||||
int32_t& seqid) {
|
|
||||||
uint32_t result = 0;
|
|
||||||
int32_t sz;
|
|
||||||
result += readI32(sz);
|
|
||||||
|
|
||||||
if (sz < 0) {
|
|
||||||
// Check for correct version number
|
|
||||||
int32_t version = sz & VERSION_MASK;
|
|
||||||
if (version != VERSION_1) {
|
|
||||||
throw TProtocolException(TProtocolException::BAD_VERSION, "Bad version identifier");
|
|
||||||
}
|
|
||||||
messageType = (TMessageType)(sz & 0x000000ff);
|
|
||||||
result += readString(name);
|
|
||||||
result += readI32(seqid);
|
|
||||||
} else {
|
|
||||||
if (this->strict_read_) {
|
|
||||||
throw TProtocolException(TProtocolException::BAD_VERSION, "No version identifier... old protocol client in strict mode?");
|
|
||||||
} else {
|
|
||||||
// Handle pre-versioned input
|
|
||||||
int8_t type;
|
|
||||||
result += readStringBody(name, sz);
|
|
||||||
result += readByte(type);
|
|
||||||
messageType = (TMessageType)type;
|
|
||||||
result += readI32(seqid);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class Transport_>
|
|
||||||
uint32_t TBinaryProtocolT<Transport_>::readMessageEnd() {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class Transport_>
|
|
||||||
uint32_t TBinaryProtocolT<Transport_>::readStructBegin(std::string& name) {
|
|
||||||
name = "";
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class Transport_>
|
|
||||||
uint32_t TBinaryProtocolT<Transport_>::readStructEnd() {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class Transport_>
|
|
||||||
uint32_t TBinaryProtocolT<Transport_>::readFieldBegin(std::string& name,
|
|
||||||
TType& fieldType,
|
|
||||||
int16_t& fieldId) {
|
|
||||||
(void) name;
|
|
||||||
uint32_t result = 0;
|
|
||||||
int8_t type;
|
|
||||||
result += readByte(type);
|
|
||||||
fieldType = (TType)type;
|
|
||||||
if (fieldType == T_STOP) {
|
|
||||||
fieldId = 0;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
result += readI16(fieldId);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class Transport_>
|
|
||||||
uint32_t TBinaryProtocolT<Transport_>::readFieldEnd() {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class Transport_>
|
|
||||||
uint32_t TBinaryProtocolT<Transport_>::readMapBegin(TType& keyType,
|
|
||||||
TType& valType,
|
|
||||||
uint32_t& size) {
|
|
||||||
int8_t k, v;
|
|
||||||
uint32_t result = 0;
|
|
||||||
int32_t sizei;
|
|
||||||
result += readByte(k);
|
|
||||||
keyType = (TType)k;
|
|
||||||
result += readByte(v);
|
|
||||||
valType = (TType)v;
|
|
||||||
result += readI32(sizei);
|
|
||||||
if (sizei < 0) {
|
|
||||||
throw TProtocolException(TProtocolException::NEGATIVE_SIZE);
|
|
||||||
} else if (this->container_limit_ && sizei > this->container_limit_) {
|
|
||||||
throw TProtocolException(TProtocolException::SIZE_LIMIT);
|
|
||||||
}
|
|
||||||
size = (uint32_t)sizei;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class Transport_>
|
|
||||||
uint32_t TBinaryProtocolT<Transport_>::readMapEnd() {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class Transport_>
|
|
||||||
uint32_t TBinaryProtocolT<Transport_>::readListBegin(TType& elemType,
|
|
||||||
uint32_t& size) {
|
|
||||||
int8_t e;
|
|
||||||
uint32_t result = 0;
|
|
||||||
int32_t sizei;
|
|
||||||
result += readByte(e);
|
|
||||||
elemType = (TType)e;
|
|
||||||
result += readI32(sizei);
|
|
||||||
if (sizei < 0) {
|
|
||||||
throw TProtocolException(TProtocolException::NEGATIVE_SIZE);
|
|
||||||
} else if (this->container_limit_ && sizei > this->container_limit_) {
|
|
||||||
throw TProtocolException(TProtocolException::SIZE_LIMIT);
|
|
||||||
}
|
|
||||||
size = (uint32_t)sizei;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class Transport_>
|
|
||||||
uint32_t TBinaryProtocolT<Transport_>::readListEnd() {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class Transport_>
|
|
||||||
uint32_t TBinaryProtocolT<Transport_>::readSetBegin(TType& elemType,
|
|
||||||
uint32_t& size) {
|
|
||||||
int8_t e;
|
|
||||||
uint32_t result = 0;
|
|
||||||
int32_t sizei;
|
|
||||||
result += readByte(e);
|
|
||||||
elemType = (TType)e;
|
|
||||||
result += readI32(sizei);
|
|
||||||
if (sizei < 0) {
|
|
||||||
throw TProtocolException(TProtocolException::NEGATIVE_SIZE);
|
|
||||||
} else if (this->container_limit_ && sizei > this->container_limit_) {
|
|
||||||
throw TProtocolException(TProtocolException::SIZE_LIMIT);
|
|
||||||
}
|
|
||||||
size = (uint32_t)sizei;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class Transport_>
|
|
||||||
uint32_t TBinaryProtocolT<Transport_>::readSetEnd() {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class Transport_>
|
|
||||||
uint32_t TBinaryProtocolT<Transport_>::readBool(bool& value) {
|
|
||||||
uint8_t b[1];
|
|
||||||
this->trans_->readAll(b, 1);
|
|
||||||
value = *(int8_t*)b != 0;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class Transport_>
|
|
||||||
uint32_t TBinaryProtocolT<Transport_>::readByte(int8_t& byte) {
|
|
||||||
uint8_t b[1];
|
|
||||||
this->trans_->readAll(b, 1);
|
|
||||||
byte = *(int8_t*)b;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class Transport_>
|
|
||||||
uint32_t TBinaryProtocolT<Transport_>::readI16(int16_t& i16) {
|
|
||||||
union bytes {
|
|
||||||
uint8_t b[2];
|
|
||||||
int16_t all;
|
|
||||||
} theBytes;
|
|
||||||
this->trans_->readAll(theBytes.b, 2);
|
|
||||||
i16 = (int16_t)ntohs(theBytes.all);
|
|
||||||
return 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class Transport_>
|
|
||||||
uint32_t TBinaryProtocolT<Transport_>::readI32(int32_t& i32) {
|
|
||||||
union bytes {
|
|
||||||
uint8_t b[4];
|
|
||||||
int32_t all;
|
|
||||||
} theBytes;
|
|
||||||
this->trans_->readAll(theBytes.b, 4);
|
|
||||||
i32 = (int32_t)ntohl(theBytes.all);
|
|
||||||
return 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class Transport_>
|
|
||||||
uint32_t TBinaryProtocolT<Transport_>::readI64(int64_t& i64) {
|
|
||||||
union bytes {
|
|
||||||
uint8_t b[8];
|
|
||||||
int64_t all;
|
|
||||||
} theBytes;
|
|
||||||
this->trans_->readAll(theBytes.b, 8);
|
|
||||||
i64 = (int64_t)ntohll(theBytes.all);
|
|
||||||
return 8;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class Transport_>
|
|
||||||
uint32_t TBinaryProtocolT<Transport_>::readDouble(double& dub) {
|
|
||||||
BOOST_STATIC_ASSERT(sizeof(double) == sizeof(uint64_t));
|
|
||||||
BOOST_STATIC_ASSERT(std::numeric_limits<double>::is_iec559);
|
|
||||||
|
|
||||||
union bytes {
|
|
||||||
uint8_t b[8];
|
|
||||||
uint64_t all;
|
|
||||||
} theBytes;
|
|
||||||
this->trans_->readAll(theBytes.b, 8);
|
|
||||||
theBytes.all = ntohll(theBytes.all);
|
|
||||||
dub = bitwise_cast<double>(theBytes.all);
|
|
||||||
return 8;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class Transport_>
|
|
||||||
template<typename StrType>
|
|
||||||
uint32_t TBinaryProtocolT<Transport_>::readString(StrType& str) {
|
|
||||||
uint32_t result;
|
|
||||||
int32_t size;
|
|
||||||
result = readI32(size);
|
|
||||||
return result + readStringBody(str, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class Transport_>
|
|
||||||
uint32_t TBinaryProtocolT<Transport_>::readBinary(std::string& str) {
|
|
||||||
return TBinaryProtocolT<Transport_>::readString(str);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class Transport_>
|
|
||||||
template<typename StrType>
|
|
||||||
uint32_t TBinaryProtocolT<Transport_>::readStringBody(StrType& str,
|
|
||||||
int32_t size) {
|
|
||||||
uint32_t result = 0;
|
|
||||||
|
|
||||||
// Catch error cases
|
|
||||||
if (size < 0) {
|
|
||||||
throw TProtocolException(TProtocolException::NEGATIVE_SIZE);
|
|
||||||
}
|
|
||||||
if (this->string_limit_ > 0 && size > this->string_limit_) {
|
|
||||||
throw TProtocolException(TProtocolException::SIZE_LIMIT);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Catch empty string case
|
|
||||||
if (size == 0) {
|
|
||||||
str.clear();
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Try to borrow first
|
|
||||||
const uint8_t* borrow_buf;
|
|
||||||
uint32_t got = size;
|
|
||||||
if ((borrow_buf = this->trans_->borrow(NULL, &got))) {
|
|
||||||
str.assign((const char*)borrow_buf, size);
|
|
||||||
this->trans_->consume(size);
|
|
||||||
return size;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Use the heap here to prevent stack overflow for v. large strings
|
|
||||||
if (size > this->string_buf_size_ || this->string_buf_ == NULL) {
|
|
||||||
void* new_string_buf = std::realloc(this->string_buf_, (uint32_t)size);
|
|
||||||
if (new_string_buf == NULL) {
|
|
||||||
throw std::bad_alloc();
|
|
||||||
}
|
|
||||||
this->string_buf_ = (uint8_t*)new_string_buf;
|
|
||||||
this->string_buf_size_ = size;
|
|
||||||
}
|
|
||||||
this->trans_->readAll(this->string_buf_, size);
|
|
||||||
str.assign((char*)this->string_buf_, size);
|
|
||||||
return (uint32_t)size;
|
|
||||||
}
|
|
||||||
|
|
||||||
}}} // apache::thrift::protocol
|
|
||||||
|
|
||||||
#endif // #ifndef _THRIFT_PROTOCOL_TBINARYPROTOCOL_TCC_
|
|
||||||
@@ -1,338 +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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <thrift/protocol/TVirtualProtocol.h>
|
|
||||||
|
|
||||||
#include <stack>
|
|
||||||
#include <boost/shared_ptr.hpp>
|
|
||||||
|
|
||||||
namespace apache
|
|
||||||
{
|
|
||||||
namespace thrift
|
|
||||||
{
|
|
||||||
namespace protocol
|
|
||||||
{
|
|
||||||
|
|
||||||
/**
|
|
||||||
* C++ Implementation of the Compact Protocol as described in THRIFT-110
|
|
||||||
*/
|
|
||||||
template <class Transport_>
|
|
||||||
class TCompactProtocolT
|
|
||||||
: public TVirtualProtocol< TCompactProtocolT<Transport_> >
|
|
||||||
{
|
|
||||||
|
|
||||||
protected:
|
|
||||||
static const int8_t PROTOCOL_ID = (int8_t)0x82u;
|
|
||||||
static const int8_t VERSION_N = 1;
|
|
||||||
static const int8_t VERSION_MASK = 0x1f; // 0001 1111
|
|
||||||
static const int8_t TYPE_MASK = (int8_t)0xE0u; // 1110 0000
|
|
||||||
static const int32_t TYPE_SHIFT_AMOUNT = 5;
|
|
||||||
|
|
||||||
Transport_* trans_;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* (Writing) If we encounter a boolean field begin, save the TField here
|
|
||||||
* so it can have the value incorporated.
|
|
||||||
*/
|
|
||||||
struct
|
|
||||||
{
|
|
||||||
const char* name;
|
|
||||||
TType fieldType;
|
|
||||||
int16_t fieldId;
|
|
||||||
} booleanField_;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* (Reading) If we read a field header, and it's a boolean field, save
|
|
||||||
* the boolean value here so that readBool can use it.
|
|
||||||
*/
|
|
||||||
struct
|
|
||||||
{
|
|
||||||
bool hasBoolValue;
|
|
||||||
bool boolValue;
|
|
||||||
} boolValue_;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Used to keep track of the last field for the current and previous structs,
|
|
||||||
* so we can do the delta stuff.
|
|
||||||
*/
|
|
||||||
|
|
||||||
std::stack<int16_t> lastField_;
|
|
||||||
int16_t lastFieldId_;
|
|
||||||
|
|
||||||
public:
|
|
||||||
TCompactProtocolT(boost::shared_ptr<Transport_> trans) :
|
|
||||||
TVirtualProtocol< TCompactProtocolT<Transport_> >(trans),
|
|
||||||
trans_(trans.get()),
|
|
||||||
lastFieldId_(0),
|
|
||||||
string_limit_(0),
|
|
||||||
string_buf_(NULL),
|
|
||||||
string_buf_size_(0),
|
|
||||||
container_limit_(0)
|
|
||||||
{
|
|
||||||
booleanField_.name = NULL;
|
|
||||||
boolValue_.hasBoolValue = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
TCompactProtocolT(boost::shared_ptr<Transport_> trans,
|
|
||||||
int32_t string_limit,
|
|
||||||
int32_t container_limit) :
|
|
||||||
TVirtualProtocol< TCompactProtocolT<Transport_> >(trans),
|
|
||||||
trans_(trans.get()),
|
|
||||||
lastFieldId_(0),
|
|
||||||
string_limit_(string_limit),
|
|
||||||
string_buf_(NULL),
|
|
||||||
string_buf_size_(0),
|
|
||||||
container_limit_(container_limit)
|
|
||||||
{
|
|
||||||
booleanField_.name = NULL;
|
|
||||||
boolValue_.hasBoolValue = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
~TCompactProtocolT()
|
|
||||||
{
|
|
||||||
free(string_buf_);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Writing functions
|
|
||||||
*/
|
|
||||||
|
|
||||||
virtual uint32_t writeMessageBegin(const std::string& name,
|
|
||||||
const TMessageType messageType,
|
|
||||||
const int32_t seqid);
|
|
||||||
|
|
||||||
uint32_t writeStructBegin(const char* name);
|
|
||||||
|
|
||||||
uint32_t writeStructEnd();
|
|
||||||
|
|
||||||
uint32_t writeFieldBegin(const char* name,
|
|
||||||
const TType fieldType,
|
|
||||||
const int16_t fieldId);
|
|
||||||
|
|
||||||
uint32_t writeFieldStop();
|
|
||||||
|
|
||||||
uint32_t writeListBegin(const TType elemType,
|
|
||||||
const uint32_t size);
|
|
||||||
|
|
||||||
uint32_t writeSetBegin(const TType elemType,
|
|
||||||
const uint32_t size);
|
|
||||||
|
|
||||||
virtual uint32_t writeMapBegin(const TType keyType,
|
|
||||||
const TType valType,
|
|
||||||
const uint32_t size);
|
|
||||||
|
|
||||||
uint32_t writeBool(const bool value);
|
|
||||||
|
|
||||||
uint32_t writeByte(const int8_t byte);
|
|
||||||
|
|
||||||
uint32_t writeI16(const int16_t i16);
|
|
||||||
|
|
||||||
uint32_t writeI32(const int32_t i32);
|
|
||||||
|
|
||||||
uint32_t writeI64(const int64_t i64);
|
|
||||||
|
|
||||||
uint32_t writeDouble(const double dub);
|
|
||||||
|
|
||||||
uint32_t writeString(const std::string& str);
|
|
||||||
|
|
||||||
uint32_t writeBinary(const std::string& str);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* These methods are called by structs, but don't actually have any wired
|
|
||||||
* output or purpose
|
|
||||||
*/
|
|
||||||
virtual uint32_t writeMessageEnd()
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
uint32_t writeMapEnd()
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
uint32_t writeListEnd()
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
uint32_t writeSetEnd()
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
uint32_t writeFieldEnd()
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
int32_t writeFieldBeginInternal(const char* name,
|
|
||||||
const TType fieldType,
|
|
||||||
const int16_t fieldId,
|
|
||||||
int8_t typeOverride);
|
|
||||||
uint32_t writeCollectionBegin(const TType elemType, int32_t size);
|
|
||||||
uint32_t writeVarint32(uint32_t n);
|
|
||||||
uint32_t writeVarint64(uint64_t n);
|
|
||||||
uint64_t i64ToZigzag(const int64_t l);
|
|
||||||
uint32_t i32ToZigzag(const int32_t n);
|
|
||||||
inline int8_t getCompactType(const TType ttype);
|
|
||||||
|
|
||||||
public:
|
|
||||||
uint32_t readMessageBegin(std::string& name,
|
|
||||||
TMessageType& messageType,
|
|
||||||
int32_t& seqid);
|
|
||||||
|
|
||||||
uint32_t readStructBegin(std::string& name);
|
|
||||||
|
|
||||||
uint32_t readStructEnd();
|
|
||||||
|
|
||||||
uint32_t readFieldBegin(std::string& name,
|
|
||||||
TType& fieldType,
|
|
||||||
int16_t& fieldId);
|
|
||||||
|
|
||||||
uint32_t readMapBegin(TType& keyType,
|
|
||||||
TType& valType,
|
|
||||||
uint32_t& size);
|
|
||||||
|
|
||||||
uint32_t readListBegin(TType& elemType,
|
|
||||||
uint32_t& size);
|
|
||||||
|
|
||||||
uint32_t readSetBegin(TType& elemType,
|
|
||||||
uint32_t& size);
|
|
||||||
|
|
||||||
uint32_t readBool(bool& value);
|
|
||||||
// Provide the default readBool() implementation for std::vector<bool>
|
|
||||||
using TVirtualProtocol< TCompactProtocolT<Transport_> >::readBool;
|
|
||||||
|
|
||||||
uint32_t readByte(int8_t& byte);
|
|
||||||
|
|
||||||
uint32_t readI16(int16_t& i16);
|
|
||||||
|
|
||||||
uint32_t readI32(int32_t& i32);
|
|
||||||
|
|
||||||
uint32_t readI64(int64_t& i64);
|
|
||||||
|
|
||||||
uint32_t readDouble(double& dub);
|
|
||||||
|
|
||||||
uint32_t readString(std::string& str);
|
|
||||||
|
|
||||||
uint32_t readBinary(std::string& str);
|
|
||||||
|
|
||||||
/*
|
|
||||||
*These methods are here for the struct to call, but don't have any wire
|
|
||||||
* encoding.
|
|
||||||
*/
|
|
||||||
uint32_t readMessageEnd()
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
uint32_t readFieldEnd()
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
uint32_t readMapEnd()
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
uint32_t readListEnd()
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
uint32_t readSetEnd()
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
uint32_t readVarint32(int32_t& i32);
|
|
||||||
uint32_t readVarint64(int64_t& i64);
|
|
||||||
int32_t zigzagToI32(uint32_t n);
|
|
||||||
int64_t zigzagToI64(uint64_t n);
|
|
||||||
TType getTType(int8_t type);
|
|
||||||
|
|
||||||
// Buffer for reading strings, save for the lifetime of the protocol to
|
|
||||||
// avoid memory churn allocating memory on every string read
|
|
||||||
int32_t string_limit_;
|
|
||||||
uint8_t* string_buf_;
|
|
||||||
int32_t string_buf_size_;
|
|
||||||
int32_t container_limit_;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef TCompactProtocolT<TTransport> TCompactProtocol;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructs compact protocol handlers
|
|
||||||
*/
|
|
||||||
template <class Transport_>
|
|
||||||
class TCompactProtocolFactoryT : public TProtocolFactory
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
TCompactProtocolFactoryT() :
|
|
||||||
string_limit_(0),
|
|
||||||
container_limit_(0) {}
|
|
||||||
|
|
||||||
TCompactProtocolFactoryT(int32_t string_limit, int32_t container_limit) :
|
|
||||||
string_limit_(string_limit),
|
|
||||||
container_limit_(container_limit) {}
|
|
||||||
|
|
||||||
virtual ~TCompactProtocolFactoryT() {}
|
|
||||||
|
|
||||||
void setStringSizeLimit(int32_t string_limit)
|
|
||||||
{
|
|
||||||
string_limit_ = string_limit;
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
TProtocol* prot;
|
|
||||||
|
|
||||||
if (specific_trans)
|
|
||||||
{
|
|
||||||
prot = new TCompactProtocolT<Transport_>(specific_trans, string_limit_,
|
|
||||||
container_limit_);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
prot = new TCompactProtocol(trans, string_limit_, container_limit_);
|
|
||||||
}
|
|
||||||
|
|
||||||
return boost::shared_ptr<TProtocol>(prot);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
int32_t string_limit_;
|
|
||||||
int32_t container_limit_;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef TCompactProtocolFactoryT<TTransport> TCompactProtocolFactory;
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} // apache::thrift::protocol
|
|
||||||
|
|
||||||
#include <thrift/protocol/TCompactProtocol.tcc>
|
|
||||||
|
|
||||||
@@ -1,818 +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_PROTOCOL_TCOMPACTPROTOCOL_TCC_
|
|
||||||
#define _THRIFT_PROTOCOL_TCOMPACTPROTOCOL_TCC_ 1
|
|
||||||
|
|
||||||
#include <limits>
|
|
||||||
|
|
||||||
/*
|
|
||||||
* TCompactProtocol::i*ToZigzag depend on the fact that the right shift
|
|
||||||
* operator on a signed integer is an arithmetic (sign-extending) shift.
|
|
||||||
* If this is not the case, the current implementation will not work.
|
|
||||||
* If anyone encounters this error, we can try to figure out the best
|
|
||||||
* way to implement an arithmetic right shift on their platform.
|
|
||||||
*/
|
|
||||||
#if !defined(SIGNED_RIGHT_SHIFT_IS) || !defined(ARITHMETIC_RIGHT_SHIFT)
|
|
||||||
# error "Unable to determine the behavior of a signed right shift"
|
|
||||||
#endif
|
|
||||||
#if SIGNED_RIGHT_SHIFT_IS != ARITHMETIC_RIGHT_SHIFT
|
|
||||||
# error "TCompactProtocol currently only works if a signed right shift is arithmetic"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef __GNUC__
|
|
||||||
#define UNLIKELY(val) (__builtin_expect((val), 0))
|
|
||||||
#else
|
|
||||||
#define UNLIKELY(val) (val)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace apache { namespace thrift { namespace protocol {
|
|
||||||
|
|
||||||
namespace detail { namespace compact {
|
|
||||||
|
|
||||||
enum Types {
|
|
||||||
CT_STOP = 0x00,
|
|
||||||
CT_BOOLEAN_TRUE = 0x01,
|
|
||||||
CT_BOOLEAN_FALSE = 0x02,
|
|
||||||
CT_BYTE = 0x03,
|
|
||||||
CT_I16 = 0x04,
|
|
||||||
CT_I32 = 0x05,
|
|
||||||
CT_I64 = 0x06,
|
|
||||||
CT_DOUBLE = 0x07,
|
|
||||||
CT_BINARY = 0x08,
|
|
||||||
CT_LIST = 0x09,
|
|
||||||
CT_SET = 0x0A,
|
|
||||||
CT_MAP = 0x0B,
|
|
||||||
CT_STRUCT = 0x0C
|
|
||||||
};
|
|
||||||
|
|
||||||
const int8_t TTypeToCType[16] = {
|
|
||||||
CT_STOP, // T_STOP
|
|
||||||
0, // unused
|
|
||||||
CT_BOOLEAN_TRUE, // T_BOOL
|
|
||||||
CT_BYTE, // T_BYTE
|
|
||||||
CT_DOUBLE, // T_DOUBLE
|
|
||||||
0, // unused
|
|
||||||
CT_I16, // T_I16
|
|
||||||
0, // unused
|
|
||||||
CT_I32, // T_I32
|
|
||||||
0, // unused
|
|
||||||
CT_I64, // T_I64
|
|
||||||
CT_BINARY, // T_STRING
|
|
||||||
CT_STRUCT, // T_STRUCT
|
|
||||||
CT_MAP, // T_MAP
|
|
||||||
CT_SET, // T_SET
|
|
||||||
CT_LIST, // T_LIST
|
|
||||||
};
|
|
||||||
|
|
||||||
}} // end detail::compact namespace
|
|
||||||
|
|
||||||
|
|
||||||
template <class Transport_>
|
|
||||||
uint32_t TCompactProtocolT<Transport_>::writeMessageBegin(
|
|
||||||
const std::string& name,
|
|
||||||
const TMessageType messageType,
|
|
||||||
const int32_t seqid) {
|
|
||||||
uint32_t wsize = 0;
|
|
||||||
wsize += writeByte(PROTOCOL_ID);
|
|
||||||
wsize += writeByte((VERSION_N & VERSION_MASK) | (((int32_t)messageType << TYPE_SHIFT_AMOUNT) & TYPE_MASK));
|
|
||||||
wsize += writeVarint32(seqid);
|
|
||||||
wsize += writeString(name);
|
|
||||||
return wsize;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Write a field header containing the field id and field type. If the
|
|
||||||
* difference between the current field id and the last one is small (< 15),
|
|
||||||
* then the field id will be encoded in the 4 MSB as a delta. Otherwise, the
|
|
||||||
* field id will follow the type header as a zigzag varint.
|
|
||||||
*/
|
|
||||||
template <class Transport_>
|
|
||||||
uint32_t TCompactProtocolT<Transport_>::writeFieldBegin(const char* name,
|
|
||||||
const TType fieldType,
|
|
||||||
const int16_t fieldId) {
|
|
||||||
if (fieldType == T_BOOL) {
|
|
||||||
booleanField_.name = name;
|
|
||||||
booleanField_.fieldType = fieldType;
|
|
||||||
booleanField_.fieldId = fieldId;
|
|
||||||
} else {
|
|
||||||
return writeFieldBeginInternal(name, fieldType, fieldId, -1);
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Write the STOP symbol so we know there are no more fields in this struct.
|
|
||||||
*/
|
|
||||||
template <class Transport_>
|
|
||||||
uint32_t TCompactProtocolT<Transport_>::writeFieldStop() {
|
|
||||||
return writeByte(T_STOP);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Write a struct begin. This doesn't actually put anything on the wire. We
|
|
||||||
* use it as an opportunity to put special placeholder markers on the field
|
|
||||||
* stack so we can get the field id deltas correct.
|
|
||||||
*/
|
|
||||||
template <class Transport_>
|
|
||||||
uint32_t TCompactProtocolT<Transport_>::writeStructBegin(const char* name) {
|
|
||||||
(void) name;
|
|
||||||
lastField_.push(lastFieldId_);
|
|
||||||
lastFieldId_ = 0;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Write a struct end. This doesn't actually put anything on the wire. We use
|
|
||||||
* this as an opportunity to pop the last field from the current struct off
|
|
||||||
* of the field stack.
|
|
||||||
*/
|
|
||||||
template <class Transport_>
|
|
||||||
uint32_t TCompactProtocolT<Transport_>::writeStructEnd() {
|
|
||||||
lastFieldId_ = lastField_.top();
|
|
||||||
lastField_.pop();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Write a List header.
|
|
||||||
*/
|
|
||||||
template <class Transport_>
|
|
||||||
uint32_t TCompactProtocolT<Transport_>::writeListBegin(const TType elemType,
|
|
||||||
const uint32_t size) {
|
|
||||||
return writeCollectionBegin(elemType, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Write a set header.
|
|
||||||
*/
|
|
||||||
template <class Transport_>
|
|
||||||
uint32_t TCompactProtocolT<Transport_>::writeSetBegin(const TType elemType,
|
|
||||||
const uint32_t size) {
|
|
||||||
return writeCollectionBegin(elemType, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Write a map header. If the map is empty, omit the key and value type
|
|
||||||
* headers, as we don't need any additional information to skip it.
|
|
||||||
*/
|
|
||||||
template <class Transport_>
|
|
||||||
uint32_t TCompactProtocolT<Transport_>::writeMapBegin(const TType keyType,
|
|
||||||
const TType valType,
|
|
||||||
const uint32_t size) {
|
|
||||||
uint32_t wsize = 0;
|
|
||||||
|
|
||||||
if (size == 0) {
|
|
||||||
wsize += writeByte(0);
|
|
||||||
} else {
|
|
||||||
wsize += writeVarint32(size);
|
|
||||||
wsize += writeByte(getCompactType(keyType) << 4 | getCompactType(valType));
|
|
||||||
}
|
|
||||||
return wsize;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Write a boolean value. Potentially, this could be a boolean field, in
|
|
||||||
* which case the field header info isn't written yet. If so, decide what the
|
|
||||||
* right type header is for the value and then write the field header.
|
|
||||||
* Otherwise, write a single byte.
|
|
||||||
*/
|
|
||||||
template <class Transport_>
|
|
||||||
uint32_t TCompactProtocolT<Transport_>::writeBool(const bool value) {
|
|
||||||
uint32_t wsize = 0;
|
|
||||||
|
|
||||||
if (booleanField_.name != NULL) {
|
|
||||||
// we haven't written the field header yet
|
|
||||||
wsize
|
|
||||||
+= writeFieldBeginInternal(booleanField_.name,
|
|
||||||
booleanField_.fieldType,
|
|
||||||
booleanField_.fieldId,
|
|
||||||
static_cast<int8_t>(value
|
|
||||||
? detail::compact::CT_BOOLEAN_TRUE
|
|
||||||
: detail::compact::CT_BOOLEAN_FALSE));
|
|
||||||
booleanField_.name = NULL;
|
|
||||||
} else {
|
|
||||||
// we're not part of a field, so just write the value
|
|
||||||
wsize
|
|
||||||
+= writeByte(static_cast<int8_t>(value
|
|
||||||
? detail::compact::CT_BOOLEAN_TRUE
|
|
||||||
: detail::compact::CT_BOOLEAN_FALSE));
|
|
||||||
}
|
|
||||||
return wsize;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class Transport_>
|
|
||||||
uint32_t TCompactProtocolT<Transport_>::writeByte(const int8_t byte) {
|
|
||||||
trans_->write((uint8_t*)&byte, 1);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Write an i16 as a zigzag varint.
|
|
||||||
*/
|
|
||||||
template <class Transport_>
|
|
||||||
uint32_t TCompactProtocolT<Transport_>::writeI16(const int16_t i16) {
|
|
||||||
return writeVarint32(i32ToZigzag(i16));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Write an i32 as a zigzag varint.
|
|
||||||
*/
|
|
||||||
template <class Transport_>
|
|
||||||
uint32_t TCompactProtocolT<Transport_>::writeI32(const int32_t i32) {
|
|
||||||
return writeVarint32(i32ToZigzag(i32));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Write an i64 as a zigzag varint.
|
|
||||||
*/
|
|
||||||
template <class Transport_>
|
|
||||||
uint32_t TCompactProtocolT<Transport_>::writeI64(const int64_t i64) {
|
|
||||||
return writeVarint64(i64ToZigzag(i64));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Write a double to the wire as 8 bytes.
|
|
||||||
*/
|
|
||||||
template <class Transport_>
|
|
||||||
uint32_t TCompactProtocolT<Transport_>::writeDouble(const double dub) {
|
|
||||||
BOOST_STATIC_ASSERT(sizeof(double) == sizeof(uint64_t));
|
|
||||||
BOOST_STATIC_ASSERT(std::numeric_limits<double>::is_iec559);
|
|
||||||
|
|
||||||
uint64_t bits = bitwise_cast<uint64_t>(dub);
|
|
||||||
bits = htolell(bits);
|
|
||||||
trans_->write((uint8_t*)&bits, 8);
|
|
||||||
return 8;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Write a string to the wire with a varint size preceeding.
|
|
||||||
*/
|
|
||||||
template <class Transport_>
|
|
||||||
uint32_t TCompactProtocolT<Transport_>::writeString(const std::string& str) {
|
|
||||||
return writeBinary(str);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class Transport_>
|
|
||||||
uint32_t TCompactProtocolT<Transport_>::writeBinary(const std::string& str) {
|
|
||||||
uint32_t ssize = str.size();
|
|
||||||
uint32_t wsize = writeVarint32(ssize) + ssize;
|
|
||||||
trans_->write((uint8_t*)str.data(), ssize);
|
|
||||||
return wsize;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Internal Writing methods
|
|
||||||
//
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The workhorse of writeFieldBegin. It has the option of doing a
|
|
||||||
* 'type override' of the type header. This is used specifically in the
|
|
||||||
* boolean field case.
|
|
||||||
*/
|
|
||||||
template <class Transport_>
|
|
||||||
int32_t TCompactProtocolT<Transport_>::writeFieldBeginInternal(
|
|
||||||
const char* name,
|
|
||||||
const TType fieldType,
|
|
||||||
const int16_t fieldId,
|
|
||||||
int8_t typeOverride) {
|
|
||||||
(void) name;
|
|
||||||
uint32_t wsize = 0;
|
|
||||||
|
|
||||||
// if there's a type override, use that.
|
|
||||||
int8_t typeToWrite = (typeOverride == -1 ? getCompactType(fieldType) : typeOverride);
|
|
||||||
|
|
||||||
// check if we can use delta encoding for the field id
|
|
||||||
if (fieldId > lastFieldId_ && fieldId - lastFieldId_ <= 15) {
|
|
||||||
// write them together
|
|
||||||
wsize += writeByte(static_cast<int8_t>((fieldId - lastFieldId_)
|
|
||||||
<< 4 | typeToWrite));
|
|
||||||
} else {
|
|
||||||
// write them separate
|
|
||||||
wsize += writeByte(typeToWrite);
|
|
||||||
wsize += writeI16(fieldId);
|
|
||||||
}
|
|
||||||
|
|
||||||
lastFieldId_ = fieldId;
|
|
||||||
return wsize;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Abstract method for writing the start of lists and sets. List and sets on
|
|
||||||
* the wire differ only by the type indicator.
|
|
||||||
*/
|
|
||||||
template <class Transport_>
|
|
||||||
uint32_t TCompactProtocolT<Transport_>::writeCollectionBegin(const TType elemType,
|
|
||||||
int32_t size) {
|
|
||||||
uint32_t wsize = 0;
|
|
||||||
if (size <= 14) {
|
|
||||||
wsize += writeByte(static_cast<int8_t>(size
|
|
||||||
<< 4 | getCompactType(elemType)));
|
|
||||||
} else {
|
|
||||||
wsize += writeByte(0xf0 | getCompactType(elemType));
|
|
||||||
wsize += writeVarint32(size);
|
|
||||||
}
|
|
||||||
return wsize;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Write an i32 as a varint. Results in 1-5 bytes on the wire.
|
|
||||||
*/
|
|
||||||
template <class Transport_>
|
|
||||||
uint32_t TCompactProtocolT<Transport_>::writeVarint32(uint32_t n) {
|
|
||||||
uint8_t buf[5];
|
|
||||||
uint32_t wsize = 0;
|
|
||||||
|
|
||||||
while (true) {
|
|
||||||
if ((n & ~0x7F) == 0) {
|
|
||||||
buf[wsize++] = (int8_t)n;
|
|
||||||
break;
|
|
||||||
} else {
|
|
||||||
buf[wsize++] = (int8_t)((n & 0x7F) | 0x80);
|
|
||||||
n >>= 7;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
trans_->write(buf, wsize);
|
|
||||||
return wsize;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Write an i64 as a varint. Results in 1-10 bytes on the wire.
|
|
||||||
*/
|
|
||||||
template <class Transport_>
|
|
||||||
uint32_t TCompactProtocolT<Transport_>::writeVarint64(uint64_t n) {
|
|
||||||
uint8_t buf[10];
|
|
||||||
uint32_t wsize = 0;
|
|
||||||
|
|
||||||
while (true) {
|
|
||||||
if ((n & ~0x7FL) == 0) {
|
|
||||||
buf[wsize++] = (int8_t)n;
|
|
||||||
break;
|
|
||||||
} else {
|
|
||||||
buf[wsize++] = (int8_t)((n & 0x7F) | 0x80);
|
|
||||||
n >>= 7;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
trans_->write(buf, wsize);
|
|
||||||
return wsize;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Convert l into a zigzag long. This allows negative numbers to be
|
|
||||||
* represented compactly as a varint.
|
|
||||||
*/
|
|
||||||
template <class Transport_>
|
|
||||||
uint64_t TCompactProtocolT<Transport_>::i64ToZigzag(const int64_t l) {
|
|
||||||
return (l << 1) ^ (l >> 63);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Convert n into a zigzag int. This allows negative numbers to be
|
|
||||||
* represented compactly as a varint.
|
|
||||||
*/
|
|
||||||
template <class Transport_>
|
|
||||||
uint32_t TCompactProtocolT<Transport_>::i32ToZigzag(const int32_t n) {
|
|
||||||
return (n << 1) ^ (n >> 31);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Given a TType value, find the appropriate detail::compact::Types value
|
|
||||||
*/
|
|
||||||
template <class Transport_>
|
|
||||||
int8_t TCompactProtocolT<Transport_>::getCompactType(const TType ttype) {
|
|
||||||
return detail::compact::TTypeToCType[ttype];
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Reading Methods
|
|
||||||
//
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Read a message header.
|
|
||||||
*/
|
|
||||||
template <class Transport_>
|
|
||||||
uint32_t TCompactProtocolT<Transport_>::readMessageBegin(
|
|
||||||
std::string& name,
|
|
||||||
TMessageType& messageType,
|
|
||||||
int32_t& seqid) {
|
|
||||||
uint32_t rsize = 0;
|
|
||||||
int8_t protocolId;
|
|
||||||
int8_t versionAndType;
|
|
||||||
int8_t version;
|
|
||||||
|
|
||||||
rsize += readByte(protocolId);
|
|
||||||
if (protocolId != PROTOCOL_ID) {
|
|
||||||
throw TProtocolException(TProtocolException::BAD_VERSION, "Bad protocol identifier");
|
|
||||||
}
|
|
||||||
|
|
||||||
rsize += readByte(versionAndType);
|
|
||||||
version = (int8_t)(versionAndType & VERSION_MASK);
|
|
||||||
if (version != VERSION_N) {
|
|
||||||
throw TProtocolException(TProtocolException::BAD_VERSION, "Bad protocol version");
|
|
||||||
}
|
|
||||||
|
|
||||||
messageType = (TMessageType)((versionAndType >> TYPE_SHIFT_AMOUNT) & 0x03);
|
|
||||||
rsize += readVarint32(seqid);
|
|
||||||
rsize += readString(name);
|
|
||||||
|
|
||||||
return rsize;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Read a struct begin. There's nothing on the wire for this, but it is our
|
|
||||||
* opportunity to push a new struct begin marker on the field stack.
|
|
||||||
*/
|
|
||||||
template <class Transport_>
|
|
||||||
uint32_t TCompactProtocolT<Transport_>::readStructBegin(std::string& name) {
|
|
||||||
name = "";
|
|
||||||
lastField_.push(lastFieldId_);
|
|
||||||
lastFieldId_ = 0;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Doesn't actually consume any wire data, just removes the last field for
|
|
||||||
* this struct from the field stack.
|
|
||||||
*/
|
|
||||||
template <class Transport_>
|
|
||||||
uint32_t TCompactProtocolT<Transport_>::readStructEnd() {
|
|
||||||
lastFieldId_ = lastField_.top();
|
|
||||||
lastField_.pop();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Read a field header off the wire.
|
|
||||||
*/
|
|
||||||
template <class Transport_>
|
|
||||||
uint32_t TCompactProtocolT<Transport_>::readFieldBegin(std::string& name,
|
|
||||||
TType& fieldType,
|
|
||||||
int16_t& fieldId) {
|
|
||||||
(void) name;
|
|
||||||
uint32_t rsize = 0;
|
|
||||||
int8_t byte;
|
|
||||||
int8_t type;
|
|
||||||
|
|
||||||
rsize += readByte(byte);
|
|
||||||
type = (byte & 0x0f);
|
|
||||||
|
|
||||||
// if it's a stop, then we can return immediately, as the struct is over.
|
|
||||||
if (type == T_STOP) {
|
|
||||||
fieldType = T_STOP;
|
|
||||||
fieldId = 0;
|
|
||||||
return rsize;
|
|
||||||
}
|
|
||||||
|
|
||||||
// mask off the 4 MSB of the type header. it could contain a field id delta.
|
|
||||||
int16_t modifier = (int16_t)(((uint8_t)byte & 0xf0) >> 4);
|
|
||||||
if (modifier == 0) {
|
|
||||||
// not a delta, look ahead for the zigzag varint field id.
|
|
||||||
rsize += readI16(fieldId);
|
|
||||||
} else {
|
|
||||||
fieldId = (int16_t)(lastFieldId_ + modifier);
|
|
||||||
}
|
|
||||||
fieldType = getTType(type);
|
|
||||||
|
|
||||||
// if this happens to be a boolean field, the value is encoded in the type
|
|
||||||
if (type == detail::compact::CT_BOOLEAN_TRUE ||
|
|
||||||
type == detail::compact::CT_BOOLEAN_FALSE) {
|
|
||||||
// save the boolean value in a special instance variable.
|
|
||||||
boolValue_.hasBoolValue = true;
|
|
||||||
boolValue_.boolValue =
|
|
||||||
(type == detail::compact::CT_BOOLEAN_TRUE ? true : false);
|
|
||||||
}
|
|
||||||
|
|
||||||
// push the new field onto the field stack so we can keep the deltas going.
|
|
||||||
lastFieldId_ = fieldId;
|
|
||||||
return rsize;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Read a map header off the wire. If the size is zero, skip reading the key
|
|
||||||
* and value type. This means that 0-length maps will yield TMaps without the
|
|
||||||
* "correct" types.
|
|
||||||
*/
|
|
||||||
template <class Transport_>
|
|
||||||
uint32_t TCompactProtocolT<Transport_>::readMapBegin(TType& keyType,
|
|
||||||
TType& valType,
|
|
||||||
uint32_t& size) {
|
|
||||||
uint32_t rsize = 0;
|
|
||||||
int8_t kvType = 0;
|
|
||||||
int32_t msize = 0;
|
|
||||||
|
|
||||||
rsize += readVarint32(msize);
|
|
||||||
if (msize != 0)
|
|
||||||
rsize += readByte(kvType);
|
|
||||||
|
|
||||||
if (msize < 0) {
|
|
||||||
throw TProtocolException(TProtocolException::NEGATIVE_SIZE);
|
|
||||||
} else if (container_limit_ && msize > container_limit_) {
|
|
||||||
throw TProtocolException(TProtocolException::SIZE_LIMIT);
|
|
||||||
}
|
|
||||||
|
|
||||||
keyType = getTType((int8_t)((uint8_t)kvType >> 4));
|
|
||||||
valType = getTType((int8_t)((uint8_t)kvType & 0xf));
|
|
||||||
size = (uint32_t)msize;
|
|
||||||
|
|
||||||
return rsize;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Read a list header off the wire. If the list size is 0-14, the size will
|
|
||||||
* be packed into the element type header. If it's a longer list, the 4 MSB
|
|
||||||
* of the element type header will be 0xF, and a varint will follow with the
|
|
||||||
* true size.
|
|
||||||
*/
|
|
||||||
template <class Transport_>
|
|
||||||
uint32_t TCompactProtocolT<Transport_>::readListBegin(TType& elemType,
|
|
||||||
uint32_t& size) {
|
|
||||||
int8_t size_and_type;
|
|
||||||
uint32_t rsize = 0;
|
|
||||||
int32_t lsize;
|
|
||||||
|
|
||||||
rsize += readByte(size_and_type);
|
|
||||||
|
|
||||||
lsize = ((uint8_t)size_and_type >> 4) & 0x0f;
|
|
||||||
if (lsize == 15) {
|
|
||||||
rsize += readVarint32(lsize);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (lsize < 0) {
|
|
||||||
throw TProtocolException(TProtocolException::NEGATIVE_SIZE);
|
|
||||||
} else if (container_limit_ && lsize > container_limit_) {
|
|
||||||
throw TProtocolException(TProtocolException::SIZE_LIMIT);
|
|
||||||
}
|
|
||||||
|
|
||||||
elemType = getTType((int8_t)(size_and_type & 0x0f));
|
|
||||||
size = (uint32_t)lsize;
|
|
||||||
|
|
||||||
return rsize;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Read a set header off the wire. If the set size is 0-14, the size will
|
|
||||||
* be packed into the element type header. If it's a longer set, the 4 MSB
|
|
||||||
* of the element type header will be 0xF, and a varint will follow with the
|
|
||||||
* true size.
|
|
||||||
*/
|
|
||||||
template <class Transport_>
|
|
||||||
uint32_t TCompactProtocolT<Transport_>::readSetBegin(TType& elemType,
|
|
||||||
uint32_t& size) {
|
|
||||||
return readListBegin(elemType, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Read a boolean off the wire. If this is a boolean field, the value should
|
|
||||||
* already have been read during readFieldBegin, so we'll just consume the
|
|
||||||
* pre-stored value. Otherwise, read a byte.
|
|
||||||
*/
|
|
||||||
template <class Transport_>
|
|
||||||
uint32_t TCompactProtocolT<Transport_>::readBool(bool& value) {
|
|
||||||
if (boolValue_.hasBoolValue == true) {
|
|
||||||
value = boolValue_.boolValue;
|
|
||||||
boolValue_.hasBoolValue = false;
|
|
||||||
return 0;
|
|
||||||
} else {
|
|
||||||
int8_t val;
|
|
||||||
readByte(val);
|
|
||||||
value = (val == detail::compact::CT_BOOLEAN_TRUE);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Read a single byte off the wire. Nothing interesting here.
|
|
||||||
*/
|
|
||||||
template <class Transport_>
|
|
||||||
uint32_t TCompactProtocolT<Transport_>::readByte(int8_t& byte) {
|
|
||||||
uint8_t b[1];
|
|
||||||
trans_->readAll(b, 1);
|
|
||||||
byte = *(int8_t*)b;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Read an i16 from the wire as a zigzag varint.
|
|
||||||
*/
|
|
||||||
template <class Transport_>
|
|
||||||
uint32_t TCompactProtocolT<Transport_>::readI16(int16_t& i16) {
|
|
||||||
int32_t value;
|
|
||||||
uint32_t rsize = readVarint32(value);
|
|
||||||
i16 = (int16_t)zigzagToI32(value);
|
|
||||||
return rsize;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Read an i32 from the wire as a zigzag varint.
|
|
||||||
*/
|
|
||||||
template <class Transport_>
|
|
||||||
uint32_t TCompactProtocolT<Transport_>::readI32(int32_t& i32) {
|
|
||||||
int32_t value;
|
|
||||||
uint32_t rsize = readVarint32(value);
|
|
||||||
i32 = zigzagToI32(value);
|
|
||||||
return rsize;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Read an i64 from the wire as a zigzag varint.
|
|
||||||
*/
|
|
||||||
template <class Transport_>
|
|
||||||
uint32_t TCompactProtocolT<Transport_>::readI64(int64_t& i64) {
|
|
||||||
int64_t value;
|
|
||||||
uint32_t rsize = readVarint64(value);
|
|
||||||
i64 = zigzagToI64(value);
|
|
||||||
return rsize;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* No magic here - just read a double off the wire.
|
|
||||||
*/
|
|
||||||
template <class Transport_>
|
|
||||||
uint32_t TCompactProtocolT<Transport_>::readDouble(double& dub) {
|
|
||||||
BOOST_STATIC_ASSERT(sizeof(double) == sizeof(uint64_t));
|
|
||||||
BOOST_STATIC_ASSERT(std::numeric_limits<double>::is_iec559);
|
|
||||||
|
|
||||||
union {
|
|
||||||
uint64_t bits;
|
|
||||||
uint8_t b[8];
|
|
||||||
} u;
|
|
||||||
trans_->readAll(u.b, 8);
|
|
||||||
u.bits = letohll(u.bits);
|
|
||||||
dub = bitwise_cast<double>(u.bits);
|
|
||||||
return 8;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class Transport_>
|
|
||||||
uint32_t TCompactProtocolT<Transport_>::readString(std::string& str) {
|
|
||||||
return readBinary(str);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Read a byte[] from the wire.
|
|
||||||
*/
|
|
||||||
template <class Transport_>
|
|
||||||
uint32_t TCompactProtocolT<Transport_>::readBinary(std::string& str) {
|
|
||||||
int32_t rsize = 0;
|
|
||||||
int32_t size;
|
|
||||||
|
|
||||||
rsize += readVarint32(size);
|
|
||||||
// Catch empty string case
|
|
||||||
if (size == 0) {
|
|
||||||
str = "";
|
|
||||||
return rsize;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Catch error cases
|
|
||||||
if (size < 0) {
|
|
||||||
throw TProtocolException(TProtocolException::NEGATIVE_SIZE);
|
|
||||||
}
|
|
||||||
if (string_limit_ > 0 && size > string_limit_) {
|
|
||||||
throw TProtocolException(TProtocolException::SIZE_LIMIT);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Use the heap here to prevent stack overflow for v. large strings
|
|
||||||
if (size > string_buf_size_ || string_buf_ == NULL) {
|
|
||||||
void* new_string_buf = std::realloc(string_buf_, (uint32_t)size);
|
|
||||||
if (new_string_buf == NULL) {
|
|
||||||
throw std::bad_alloc();
|
|
||||||
}
|
|
||||||
string_buf_ = (uint8_t*)new_string_buf;
|
|
||||||
string_buf_size_ = size;
|
|
||||||
}
|
|
||||||
trans_->readAll(string_buf_, size);
|
|
||||||
str.assign((char*)string_buf_, size);
|
|
||||||
|
|
||||||
return rsize + (uint32_t)size;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Read an i32 from the wire as a varint. The MSB of each byte is set
|
|
||||||
* if there is another byte to follow. This can read up to 5 bytes.
|
|
||||||
*/
|
|
||||||
template <class Transport_>
|
|
||||||
uint32_t TCompactProtocolT<Transport_>::readVarint32(int32_t& i32) {
|
|
||||||
int64_t val;
|
|
||||||
uint32_t rsize = readVarint64(val);
|
|
||||||
i32 = (int32_t)val;
|
|
||||||
return rsize;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Read an i64 from the wire as a proper varint. The MSB of each byte is set
|
|
||||||
* if there is another byte to follow. This can read up to 10 bytes.
|
|
||||||
*/
|
|
||||||
template <class Transport_>
|
|
||||||
uint32_t TCompactProtocolT<Transport_>::readVarint64(int64_t& i64) {
|
|
||||||
uint32_t rsize = 0;
|
|
||||||
uint64_t val = 0;
|
|
||||||
int shift = 0;
|
|
||||||
uint8_t buf[10]; // 64 bits / (7 bits/byte) = 10 bytes.
|
|
||||||
uint32_t buf_size = sizeof(buf);
|
|
||||||
const uint8_t* borrowed = trans_->borrow(buf, &buf_size);
|
|
||||||
|
|
||||||
// Fast path.
|
|
||||||
if (borrowed != NULL) {
|
|
||||||
while (true) {
|
|
||||||
uint8_t byte = borrowed[rsize];
|
|
||||||
rsize++;
|
|
||||||
val |= (uint64_t)(byte & 0x7f) << shift;
|
|
||||||
shift += 7;
|
|
||||||
if (!(byte & 0x80)) {
|
|
||||||
i64 = val;
|
|
||||||
trans_->consume(rsize);
|
|
||||||
return rsize;
|
|
||||||
}
|
|
||||||
// Have to check for invalid data so we don't crash.
|
|
||||||
if (UNLIKELY(rsize == sizeof(buf))) {
|
|
||||||
throw TProtocolException(TProtocolException::INVALID_DATA, "Variable-length int over 10 bytes.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Slow path.
|
|
||||||
else {
|
|
||||||
while (true) {
|
|
||||||
uint8_t byte;
|
|
||||||
rsize += trans_->readAll(&byte, 1);
|
|
||||||
val |= (uint64_t)(byte & 0x7f) << shift;
|
|
||||||
shift += 7;
|
|
||||||
if (!(byte & 0x80)) {
|
|
||||||
i64 = val;
|
|
||||||
return rsize;
|
|
||||||
}
|
|
||||||
// Might as well check for invalid data on the slow path too.
|
|
||||||
if (UNLIKELY(rsize >= sizeof(buf))) {
|
|
||||||
throw TProtocolException(TProtocolException::INVALID_DATA, "Variable-length int over 10 bytes.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Convert from zigzag int to int.
|
|
||||||
*/
|
|
||||||
template <class Transport_>
|
|
||||||
int32_t TCompactProtocolT<Transport_>::zigzagToI32(uint32_t n) {
|
|
||||||
return (n >> 1) ^ -static_cast<int32_t>(n & 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Convert from zigzag long to long.
|
|
||||||
*/
|
|
||||||
template <class Transport_>
|
|
||||||
int64_t TCompactProtocolT<Transport_>::zigzagToI64(uint64_t n) {
|
|
||||||
return (n >> 1) ^ -static_cast<int32_t>(n & 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class Transport_>
|
|
||||||
TType TCompactProtocolT<Transport_>::getTType(int8_t type) {
|
|
||||||
switch (type) {
|
|
||||||
case T_STOP:
|
|
||||||
return T_STOP;
|
|
||||||
case detail::compact::CT_BOOLEAN_FALSE:
|
|
||||||
case detail::compact::CT_BOOLEAN_TRUE:
|
|
||||||
return T_BOOL;
|
|
||||||
case detail::compact::CT_BYTE:
|
|
||||||
return T_BYTE;
|
|
||||||
case detail::compact::CT_I16:
|
|
||||||
return T_I16;
|
|
||||||
case detail::compact::CT_I32:
|
|
||||||
return T_I32;
|
|
||||||
case detail::compact::CT_I64:
|
|
||||||
return T_I64;
|
|
||||||
case detail::compact::CT_DOUBLE:
|
|
||||||
return T_DOUBLE;
|
|
||||||
case detail::compact::CT_BINARY:
|
|
||||||
return T_STRING;
|
|
||||||
case detail::compact::CT_LIST:
|
|
||||||
return T_LIST;
|
|
||||||
case detail::compact::CT_SET:
|
|
||||||
return T_SET;
|
|
||||||
case detail::compact::CT_MAP:
|
|
||||||
return T_MAP;
|
|
||||||
case detail::compact::CT_STRUCT:
|
|
||||||
return T_STRUCT;
|
|
||||||
default:
|
|
||||||
throw TException(std::string("don't know what type: ") + (char)type);
|
|
||||||
}
|
|
||||||
return T_STOP;
|
|
||||||
}
|
|
||||||
|
|
||||||
}}} // apache::thrift::protocol
|
|
||||||
|
|
||||||
#endif // _THRIFT_PROTOCOL_TCOMPACTPROTOCOL_TCC_
|
|
||||||
@@ -1,247 +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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <thrift/protocol/TVirtualProtocol.h>
|
|
||||||
|
|
||||||
#include <boost/shared_ptr.hpp>
|
|
||||||
|
|
||||||
namespace apache
|
|
||||||
{
|
|
||||||
namespace thrift
|
|
||||||
{
|
|
||||||
namespace protocol
|
|
||||||
{
|
|
||||||
|
|
||||||
/*
|
|
||||||
|
|
||||||
!!! EXPERIMENTAL CODE !!!
|
|
||||||
|
|
||||||
This protocol is very much a work in progress.
|
|
||||||
It doesn't handle many cases properly.
|
|
||||||
It throws exceptions in many cases.
|
|
||||||
It probably segfaults in many cases.
|
|
||||||
Bug reports and feature requests are welcome.
|
|
||||||
Complaints are not. :R
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Protocol that prints the payload in a nice human-readable format.
|
|
||||||
* Reading from this protocol is not supported.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
class TDebugProtocol : public TVirtualProtocol<TDebugProtocol>
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
enum write_state_t
|
|
||||||
{
|
|
||||||
UNINIT
|
|
||||||
, STRUCT
|
|
||||||
, LIST
|
|
||||||
, SET
|
|
||||||
, MAP_KEY
|
|
||||||
, MAP_VALUE
|
|
||||||
};
|
|
||||||
|
|
||||||
public:
|
|
||||||
TDebugProtocol(boost::shared_ptr<TTransport> trans)
|
|
||||||
: TVirtualProtocol<TDebugProtocol>(trans)
|
|
||||||
, trans_(trans.get())
|
|
||||||
, string_limit_(DEFAULT_STRING_LIMIT)
|
|
||||||
, string_prefix_size_(DEFAULT_STRING_PREFIX_SIZE)
|
|
||||||
{
|
|
||||||
write_state_.push_back(UNINIT);
|
|
||||||
}
|
|
||||||
|
|
||||||
static const int32_t DEFAULT_STRING_LIMIT = 256;
|
|
||||||
static const int32_t DEFAULT_STRING_PREFIX_SIZE = 16;
|
|
||||||
|
|
||||||
void setStringSizeLimit(int32_t string_limit)
|
|
||||||
{
|
|
||||||
string_limit_ = string_limit;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setStringPrefixSize(int32_t string_prefix_size)
|
|
||||||
{
|
|
||||||
string_prefix_size_ = string_prefix_size;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
uint32_t writeMessageBegin(const std::string& name,
|
|
||||||
const TMessageType messageType,
|
|
||||||
const int32_t seqid);
|
|
||||||
|
|
||||||
uint32_t writeMessageEnd();
|
|
||||||
|
|
||||||
|
|
||||||
uint32_t writeStructBegin(const char* name);
|
|
||||||
|
|
||||||
uint32_t writeStructEnd();
|
|
||||||
|
|
||||||
uint32_t writeFieldBegin(const char* name,
|
|
||||||
const TType fieldType,
|
|
||||||
const int16_t fieldId);
|
|
||||||
|
|
||||||
uint32_t writeFieldEnd();
|
|
||||||
|
|
||||||
uint32_t writeFieldStop();
|
|
||||||
|
|
||||||
uint32_t writeMapBegin(const TType keyType,
|
|
||||||
const TType valType,
|
|
||||||
const uint32_t size);
|
|
||||||
|
|
||||||
uint32_t writeMapEnd();
|
|
||||||
|
|
||||||
uint32_t writeListBegin(const TType elemType,
|
|
||||||
const uint32_t size);
|
|
||||||
|
|
||||||
uint32_t writeListEnd();
|
|
||||||
|
|
||||||
uint32_t writeSetBegin(const TType elemType,
|
|
||||||
const uint32_t size);
|
|
||||||
|
|
||||||
uint32_t writeSetEnd();
|
|
||||||
|
|
||||||
uint32_t writeBool(const bool value);
|
|
||||||
|
|
||||||
uint32_t writeByte(const int8_t byte);
|
|
||||||
|
|
||||||
uint32_t writeI16(const int16_t i16);
|
|
||||||
|
|
||||||
uint32_t writeI32(const int32_t i32);
|
|
||||||
|
|
||||||
uint32_t writeI64(const int64_t i64);
|
|
||||||
|
|
||||||
uint32_t writeDouble(const double dub);
|
|
||||||
|
|
||||||
uint32_t writeString(const std::string& str);
|
|
||||||
|
|
||||||
uint32_t writeBinary(const std::string& str);
|
|
||||||
|
|
||||||
|
|
||||||
private:
|
|
||||||
void indentUp();
|
|
||||||
void indentDown();
|
|
||||||
uint32_t writePlain(const std::string& str);
|
|
||||||
uint32_t writeIndented(const std::string& str);
|
|
||||||
uint32_t startItem();
|
|
||||||
uint32_t endItem();
|
|
||||||
uint32_t writeItem(const std::string& str);
|
|
||||||
|
|
||||||
static std::string fieldTypeName(TType type);
|
|
||||||
|
|
||||||
TTransport* trans_;
|
|
||||||
|
|
||||||
int32_t string_limit_;
|
|
||||||
int32_t string_prefix_size_;
|
|
||||||
|
|
||||||
std::string indent_str_;
|
|
||||||
static const int indent_inc = 2;
|
|
||||||
|
|
||||||
std::vector<write_state_t> write_state_;
|
|
||||||
std::vector<int> list_idx_;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructs debug protocol handlers
|
|
||||||
*/
|
|
||||||
class TDebugProtocolFactory : public TProtocolFactory
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
TDebugProtocolFactory() {}
|
|
||||||
virtual ~TDebugProtocolFactory() {}
|
|
||||||
|
|
||||||
boost::shared_ptr<TProtocol> getProtocol(boost::shared_ptr<TTransport> trans)
|
|
||||||
{
|
|
||||||
return boost::shared_ptr<TProtocol>(new TDebugProtocol(trans));
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} // apache::thrift::protocol
|
|
||||||
|
|
||||||
|
|
||||||
// TODO(dreiss): Move (part of) ThriftDebugString into a .cpp file and remove this.
|
|
||||||
#include <thrift/transport/TBufferTransports.h>
|
|
||||||
|
|
||||||
namespace apache
|
|
||||||
{
|
|
||||||
namespace thrift
|
|
||||||
{
|
|
||||||
|
|
||||||
template<typename ThriftStruct>
|
|
||||||
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);
|
|
||||||
TDebugProtocol protocol(trans);
|
|
||||||
|
|
||||||
ts.write(&protocol);
|
|
||||||
|
|
||||||
uint8_t* buf;
|
|
||||||
uint32_t size;
|
|
||||||
buffer->getBuffer(&buf, &size);
|
|
||||||
return std::string((char*)buf, (unsigned int)size);
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO(dreiss): This is badly broken. Don't use it unless you are me.
|
|
||||||
#if 0
|
|
||||||
template<typename Object>
|
|
||||||
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);
|
|
||||||
TDebugProtocol protocol(trans);
|
|
||||||
|
|
||||||
// I am gross!
|
|
||||||
protocol.writeStructBegin("SomeRandomVector");
|
|
||||||
|
|
||||||
// TODO: Fix this with a trait.
|
|
||||||
protocol.writeListBegin((TType)99, vec.size());
|
|
||||||
typename std::vector<Object>::const_iterator it;
|
|
||||||
|
|
||||||
for (it = vec.begin(); it != vec.end(); ++it)
|
|
||||||
{
|
|
||||||
it->write(&protocol);
|
|
||||||
}
|
|
||||||
|
|
||||||
protocol.writeListEnd();
|
|
||||||
|
|
||||||
uint8_t* buf;
|
|
||||||
uint32_t size;
|
|
||||||
buffer->getBuffer(&buf, &size);
|
|
||||||
return std::string((char*)buf, (unsigned int)size);
|
|
||||||
}
|
|
||||||
#endif // 0
|
|
||||||
|
|
||||||
}
|
|
||||||
} // apache::thrift
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,265 +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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <thrift/protocol/TBinaryProtocol.h>
|
|
||||||
|
|
||||||
namespace apache
|
|
||||||
{
|
|
||||||
namespace thrift
|
|
||||||
{
|
|
||||||
namespace protocol
|
|
||||||
{
|
|
||||||
|
|
||||||
/**
|
|
||||||
* !!!WARNING!!!
|
|
||||||
* This class is still highly experimental. Incompatible changes
|
|
||||||
* WILL be made to it without notice. DO NOT USE IT YET unless
|
|
||||||
* you are coordinating your testing with the author.
|
|
||||||
*
|
|
||||||
* The dense protocol is designed to use as little space as possible.
|
|
||||||
*
|
|
||||||
* There are two types of dense protocol instances. Standalone instances
|
|
||||||
* are not used for RPC and just encoded and decode structures of
|
|
||||||
* a predetermined type. Non-standalone instances are used for RPC.
|
|
||||||
* Currently, only standalone instances exist.
|
|
||||||
*
|
|
||||||
* To use a standalone dense protocol object, you must set the type_spec
|
|
||||||
* property (either in the constructor, or with setTypeSpec) to the local
|
|
||||||
* reflection TypeSpec of the structures you will write to (or read from) the
|
|
||||||
* protocol instance.
|
|
||||||
*
|
|
||||||
* BEST PRACTICES:
|
|
||||||
* - Never use optional for primitives or containers.
|
|
||||||
* - Only use optional for structures if they are very big and very rarely set.
|
|
||||||
* - All integers are variable-length, so you can use i64 without bloating.
|
|
||||||
* - NEVER EVER change the struct definitions IN ANY WAY without either
|
|
||||||
* changing your cache keys or talking to dreiss.
|
|
||||||
*
|
|
||||||
* TODO(dreiss): New class write with old meta.
|
|
||||||
*
|
|
||||||
* We override all of TBinaryProtocol's methods.
|
|
||||||
* We inherit so that we can can explicitly call TBPs's primitive-writing
|
|
||||||
* methods within our versions.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
class TDenseProtocol
|
|
||||||
: public TVirtualProtocol<TDenseProtocol, TBinaryProtocol>
|
|
||||||
{
|
|
||||||
protected:
|
|
||||||
static const int32_t VERSION_MASK = ((int32_t)0xffff0000);
|
|
||||||
// VERSION_1 (0x80010000) is taken by TBinaryProtocol.
|
|
||||||
static const int32_t VERSION_2 = ((int32_t)0x80020000);
|
|
||||||
|
|
||||||
public:
|
|
||||||
typedef apache::thrift::reflection::local::TypeSpec TypeSpec;
|
|
||||||
static const int FP_PREFIX_LEN;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param tran The transport to use.
|
|
||||||
* @param type_spec The TypeSpec of the structures using this protocol.
|
|
||||||
*/
|
|
||||||
TDenseProtocol(boost::shared_ptr<TTransport> trans,
|
|
||||||
TypeSpec* type_spec = NULL) :
|
|
||||||
TVirtualProtocol<TDenseProtocol, TBinaryProtocol>(trans),
|
|
||||||
type_spec_(type_spec),
|
|
||||||
standalone_(true)
|
|
||||||
{}
|
|
||||||
|
|
||||||
void setTypeSpec(TypeSpec* type_spec)
|
|
||||||
{
|
|
||||||
type_spec_ = type_spec;
|
|
||||||
}
|
|
||||||
TypeSpec* getTypeSpec()
|
|
||||||
{
|
|
||||||
return type_spec_;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Writing functions.
|
|
||||||
*/
|
|
||||||
|
|
||||||
uint32_t writeMessageBegin(const std::string& name,
|
|
||||||
const TMessageType messageType,
|
|
||||||
const int32_t seqid);
|
|
||||||
|
|
||||||
uint32_t writeMessageEnd();
|
|
||||||
|
|
||||||
|
|
||||||
uint32_t writeStructBegin(const char* name);
|
|
||||||
|
|
||||||
uint32_t writeStructEnd();
|
|
||||||
|
|
||||||
uint32_t writeFieldBegin(const char* name,
|
|
||||||
const TType fieldType,
|
|
||||||
const int16_t fieldId);
|
|
||||||
|
|
||||||
uint32_t writeFieldEnd();
|
|
||||||
|
|
||||||
uint32_t writeFieldStop();
|
|
||||||
|
|
||||||
uint32_t writeMapBegin(const TType keyType,
|
|
||||||
const TType valType,
|
|
||||||
const uint32_t size);
|
|
||||||
|
|
||||||
uint32_t writeMapEnd();
|
|
||||||
|
|
||||||
uint32_t writeListBegin(const TType elemType, const uint32_t size);
|
|
||||||
|
|
||||||
uint32_t writeListEnd();
|
|
||||||
|
|
||||||
uint32_t writeSetBegin(const TType elemType, const uint32_t size);
|
|
||||||
|
|
||||||
uint32_t writeSetEnd();
|
|
||||||
|
|
||||||
uint32_t writeBool(const bool value);
|
|
||||||
|
|
||||||
uint32_t writeByte(const int8_t byte);
|
|
||||||
|
|
||||||
uint32_t writeI16(const int16_t i16);
|
|
||||||
|
|
||||||
uint32_t writeI32(const int32_t i32);
|
|
||||||
|
|
||||||
uint32_t writeI64(const int64_t i64);
|
|
||||||
|
|
||||||
uint32_t writeDouble(const double dub);
|
|
||||||
|
|
||||||
uint32_t writeString(const std::string& str);
|
|
||||||
|
|
||||||
uint32_t writeBinary(const std::string& str);
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Helper writing functions (don't do state transitions).
|
|
||||||
*/
|
|
||||||
inline uint32_t subWriteI32(const int32_t i32);
|
|
||||||
|
|
||||||
inline uint32_t subWriteString(const std::string& str);
|
|
||||||
|
|
||||||
uint32_t subWriteBool(const bool value)
|
|
||||||
{
|
|
||||||
return TBinaryProtocol::writeBool(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Reading functions
|
|
||||||
*/
|
|
||||||
|
|
||||||
uint32_t readMessageBegin(std::string& name,
|
|
||||||
TMessageType& messageType,
|
|
||||||
int32_t& seqid);
|
|
||||||
|
|
||||||
uint32_t readMessageEnd();
|
|
||||||
|
|
||||||
uint32_t readStructBegin(std::string& name);
|
|
||||||
|
|
||||||
uint32_t readStructEnd();
|
|
||||||
|
|
||||||
uint32_t readFieldBegin(std::string& name,
|
|
||||||
TType& fieldType,
|
|
||||||
int16_t& fieldId);
|
|
||||||
|
|
||||||
uint32_t readFieldEnd();
|
|
||||||
|
|
||||||
uint32_t readMapBegin(TType& keyType,
|
|
||||||
TType& valType,
|
|
||||||
uint32_t& size);
|
|
||||||
|
|
||||||
uint32_t readMapEnd();
|
|
||||||
|
|
||||||
uint32_t readListBegin(TType& elemType,
|
|
||||||
uint32_t& size);
|
|
||||||
|
|
||||||
uint32_t readListEnd();
|
|
||||||
|
|
||||||
uint32_t readSetBegin(TType& elemType,
|
|
||||||
uint32_t& size);
|
|
||||||
|
|
||||||
uint32_t readSetEnd();
|
|
||||||
|
|
||||||
uint32_t readBool(bool& value);
|
|
||||||
// Provide the default readBool() implementation for std::vector<bool>
|
|
||||||
using TVirtualProtocol<TDenseProtocol, TBinaryProtocol>::readBool;
|
|
||||||
|
|
||||||
uint32_t readByte(int8_t& byte);
|
|
||||||
|
|
||||||
uint32_t readI16(int16_t& i16);
|
|
||||||
|
|
||||||
uint32_t readI32(int32_t& i32);
|
|
||||||
|
|
||||||
uint32_t readI64(int64_t& i64);
|
|
||||||
|
|
||||||
uint32_t readDouble(double& dub);
|
|
||||||
|
|
||||||
uint32_t readString(std::string& str);
|
|
||||||
|
|
||||||
uint32_t readBinary(std::string& str);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Helper reading functions (don't do state transitions).
|
|
||||||
*/
|
|
||||||
inline uint32_t subReadI32(int32_t& i32);
|
|
||||||
|
|
||||||
inline uint32_t subReadString(std::string& str);
|
|
||||||
|
|
||||||
uint32_t subReadBool(bool& value)
|
|
||||||
{
|
|
||||||
return TBinaryProtocol::readBool(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
// Implementation functions, documented in the .cpp.
|
|
||||||
inline void checkTType(const TType ttype);
|
|
||||||
inline void stateTransition();
|
|
||||||
|
|
||||||
// Read and write variable-length integers.
|
|
||||||
// Uses the same technique as the MIDI file format.
|
|
||||||
inline uint32_t vlqRead(uint64_t& vlq);
|
|
||||||
inline uint32_t vlqWrite(uint64_t vlq);
|
|
||||||
|
|
||||||
// Called before throwing an exception to make the object reusable.
|
|
||||||
void resetState()
|
|
||||||
{
|
|
||||||
ts_stack_.clear();
|
|
||||||
idx_stack_.clear();
|
|
||||||
mkv_stack_.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
// TypeSpec of the top-level structure to write,
|
|
||||||
// for standalone protocol objects.
|
|
||||||
TypeSpec* type_spec_;
|
|
||||||
|
|
||||||
std::vector<TypeSpec*> ts_stack_; // TypeSpec stack.
|
|
||||||
std::vector<int> idx_stack_; // InDeX stack.
|
|
||||||
std::vector<bool> mkv_stack_; // Map Key/Vlue stack.
|
|
||||||
// True = key, False = value.
|
|
||||||
|
|
||||||
// True iff this is a standalone instance (no RPC).
|
|
||||||
bool standalone_;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} // apache::thrift::protocol
|
|
||||||
|
|
||||||
@@ -1,361 +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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <thrift/protocol/TVirtualProtocol.h>
|
|
||||||
|
|
||||||
#include <stack>
|
|
||||||
|
|
||||||
namespace apache
|
|
||||||
{
|
|
||||||
namespace thrift
|
|
||||||
{
|
|
||||||
namespace protocol
|
|
||||||
{
|
|
||||||
|
|
||||||
// Forward declaration
|
|
||||||
class TJSONContext;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* JSON protocol for Thrift.
|
|
||||||
*
|
|
||||||
* Implements a protocol which uses JSON as the wire-format.
|
|
||||||
*
|
|
||||||
* Thrift types are represented as described below:
|
|
||||||
*
|
|
||||||
* 1. Every Thrift integer type is represented as a JSON number.
|
|
||||||
*
|
|
||||||
* 2. Thrift doubles are represented as JSON numbers. Some special values are
|
|
||||||
* represented as strings:
|
|
||||||
* a. "NaN" for not-a-number values
|
|
||||||
* b. "Infinity" for postive infinity
|
|
||||||
* c. "-Infinity" for negative infinity
|
|
||||||
*
|
|
||||||
* 3. Thrift string values are emitted as JSON strings, with appropriate
|
|
||||||
* escaping.
|
|
||||||
*
|
|
||||||
* 4. Thrift binary values are encoded into Base64 and emitted as JSON strings.
|
|
||||||
* The readBinary() method is written such that it will properly skip if
|
|
||||||
* called on a Thrift string (although it will decode garbage data).
|
|
||||||
*
|
|
||||||
* 5. Thrift structs are represented as JSON objects, with the field ID as the
|
|
||||||
* key, and the field value represented as a JSON object with a single
|
|
||||||
* key-value pair. The key is a short string identifier for that type,
|
|
||||||
* followed by the value. The valid type identifiers are: "tf" for bool,
|
|
||||||
* "i8" for byte, "i16" for 16-bit integer, "i32" for 32-bit integer, "i64"
|
|
||||||
* for 64-bit integer, "dbl" for double-precision loating point, "str" for
|
|
||||||
* string (including binary), "rec" for struct ("records"), "map" for map,
|
|
||||||
* "lst" for list, "set" for set.
|
|
||||||
*
|
|
||||||
* 6. Thrift lists and sets are represented as JSON arrays, with the first
|
|
||||||
* element of the JSON array being the string identifier for the Thrift
|
|
||||||
* element type and the second element of the JSON array being the count of
|
|
||||||
* the Thrift elements. The Thrift elements then follow.
|
|
||||||
*
|
|
||||||
* 7. Thrift maps are represented as JSON arrays, with the first two elements
|
|
||||||
* of the JSON array being the string identifiers for the Thrift key type
|
|
||||||
* and value type, followed by the count of the Thrift pairs, followed by a
|
|
||||||
* JSON object containing the key-value pairs. Note that JSON keys can only
|
|
||||||
* be strings, which means that the key type of the Thrift map should be
|
|
||||||
* restricted to numeric or string types -- in the case of numerics, they
|
|
||||||
* are serialized as strings.
|
|
||||||
*
|
|
||||||
* 8. Thrift messages are represented as JSON arrays, with the protocol
|
|
||||||
* version #, the message name, the message type, and the sequence ID as
|
|
||||||
* the first 4 elements.
|
|
||||||
*
|
|
||||||
* More discussion of the double handling is probably warranted. The aim of
|
|
||||||
* 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.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
class TJSONProtocol : public TVirtualProtocol<TJSONProtocol>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
TJSONProtocol(boost::shared_ptr<TTransport> ptrans);
|
|
||||||
|
|
||||||
~TJSONProtocol();
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
void pushContext(boost::shared_ptr<TJSONContext> c);
|
|
||||||
|
|
||||||
void popContext();
|
|
||||||
|
|
||||||
uint32_t writeJSONEscapeChar(uint8_t ch);
|
|
||||||
|
|
||||||
uint32_t writeJSONChar(uint8_t ch);
|
|
||||||
|
|
||||||
uint32_t writeJSONString(const std::string& str);
|
|
||||||
|
|
||||||
uint32_t writeJSONBase64(const std::string& str);
|
|
||||||
|
|
||||||
template <typename NumberType>
|
|
||||||
uint32_t writeJSONInteger(NumberType num);
|
|
||||||
|
|
||||||
uint32_t writeJSONDouble(double num);
|
|
||||||
|
|
||||||
uint32_t writeJSONObjectStart() ;
|
|
||||||
|
|
||||||
uint32_t writeJSONObjectEnd();
|
|
||||||
|
|
||||||
uint32_t writeJSONArrayStart();
|
|
||||||
|
|
||||||
uint32_t writeJSONArrayEnd();
|
|
||||||
|
|
||||||
uint32_t readJSONSyntaxChar(uint8_t ch);
|
|
||||||
|
|
||||||
uint32_t readJSONEscapeChar(uint8_t* out);
|
|
||||||
|
|
||||||
uint32_t readJSONString(std::string& str, bool skipContext = false);
|
|
||||||
|
|
||||||
uint32_t readJSONBase64(std::string& str);
|
|
||||||
|
|
||||||
uint32_t readJSONNumericChars(std::string& str);
|
|
||||||
|
|
||||||
template <typename NumberType>
|
|
||||||
uint32_t readJSONInteger(NumberType& num);
|
|
||||||
|
|
||||||
uint32_t readJSONDouble(double& num);
|
|
||||||
|
|
||||||
uint32_t readJSONObjectStart();
|
|
||||||
|
|
||||||
uint32_t readJSONObjectEnd();
|
|
||||||
|
|
||||||
uint32_t readJSONArrayStart();
|
|
||||||
|
|
||||||
uint32_t readJSONArrayEnd();
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Writing functions.
|
|
||||||
*/
|
|
||||||
|
|
||||||
uint32_t writeMessageBegin(const std::string& name,
|
|
||||||
const TMessageType messageType,
|
|
||||||
const int32_t seqid);
|
|
||||||
|
|
||||||
uint32_t writeMessageEnd();
|
|
||||||
|
|
||||||
uint32_t writeStructBegin(const char* name);
|
|
||||||
|
|
||||||
uint32_t writeStructEnd();
|
|
||||||
|
|
||||||
uint32_t writeFieldBegin(const char* name,
|
|
||||||
const TType fieldType,
|
|
||||||
const int16_t fieldId);
|
|
||||||
|
|
||||||
uint32_t writeFieldEnd();
|
|
||||||
|
|
||||||
uint32_t writeFieldStop();
|
|
||||||
|
|
||||||
uint32_t writeMapBegin(const TType keyType,
|
|
||||||
const TType valType,
|
|
||||||
const uint32_t size);
|
|
||||||
|
|
||||||
uint32_t writeMapEnd();
|
|
||||||
|
|
||||||
uint32_t writeListBegin(const TType elemType,
|
|
||||||
const uint32_t size);
|
|
||||||
|
|
||||||
uint32_t writeListEnd();
|
|
||||||
|
|
||||||
uint32_t writeSetBegin(const TType elemType,
|
|
||||||
const uint32_t size);
|
|
||||||
|
|
||||||
uint32_t writeSetEnd();
|
|
||||||
|
|
||||||
uint32_t writeBool(const bool value);
|
|
||||||
|
|
||||||
uint32_t writeByte(const int8_t byte);
|
|
||||||
|
|
||||||
uint32_t writeI16(const int16_t i16);
|
|
||||||
|
|
||||||
uint32_t writeI32(const int32_t i32);
|
|
||||||
|
|
||||||
uint32_t writeI64(const int64_t i64);
|
|
||||||
|
|
||||||
uint32_t writeDouble(const double dub);
|
|
||||||
|
|
||||||
uint32_t writeString(const std::string& str);
|
|
||||||
|
|
||||||
uint32_t writeBinary(const std::string& str);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reading functions
|
|
||||||
*/
|
|
||||||
|
|
||||||
uint32_t readMessageBegin(std::string& name,
|
|
||||||
TMessageType& messageType,
|
|
||||||
int32_t& seqid);
|
|
||||||
|
|
||||||
uint32_t readMessageEnd();
|
|
||||||
|
|
||||||
uint32_t readStructBegin(std::string& name);
|
|
||||||
|
|
||||||
uint32_t readStructEnd();
|
|
||||||
|
|
||||||
uint32_t readFieldBegin(std::string& name,
|
|
||||||
TType& fieldType,
|
|
||||||
int16_t& fieldId);
|
|
||||||
|
|
||||||
uint32_t readFieldEnd();
|
|
||||||
|
|
||||||
uint32_t readMapBegin(TType& keyType,
|
|
||||||
TType& valType,
|
|
||||||
uint32_t& size);
|
|
||||||
|
|
||||||
uint32_t readMapEnd();
|
|
||||||
|
|
||||||
uint32_t readListBegin(TType& elemType,
|
|
||||||
uint32_t& size);
|
|
||||||
|
|
||||||
uint32_t readListEnd();
|
|
||||||
|
|
||||||
uint32_t readSetBegin(TType& elemType,
|
|
||||||
uint32_t& size);
|
|
||||||
|
|
||||||
uint32_t readSetEnd();
|
|
||||||
|
|
||||||
uint32_t readBool(bool& value);
|
|
||||||
|
|
||||||
// Provide the default readBool() implementation for std::vector<bool>
|
|
||||||
using TVirtualProtocol<TJSONProtocol>::readBool;
|
|
||||||
|
|
||||||
uint32_t readByte(int8_t& byte);
|
|
||||||
|
|
||||||
uint32_t readI16(int16_t& i16);
|
|
||||||
|
|
||||||
uint32_t readI32(int32_t& i32);
|
|
||||||
|
|
||||||
uint32_t readI64(int64_t& i64);
|
|
||||||
|
|
||||||
uint32_t readDouble(double& dub);
|
|
||||||
|
|
||||||
uint32_t readString(std::string& str);
|
|
||||||
|
|
||||||
uint32_t readBinary(std::string& str);
|
|
||||||
|
|
||||||
class LookaheadReader
|
|
||||||
{
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
LookaheadReader(TTransport& trans) :
|
|
||||||
trans_(&trans),
|
|
||||||
hasData_(false)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t read()
|
|
||||||
{
|
|
||||||
if (hasData_)
|
|
||||||
{
|
|
||||||
hasData_ = false;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
trans_->readAll(&data_, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
return data_;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t peek()
|
|
||||||
{
|
|
||||||
if (!hasData_)
|
|
||||||
{
|
|
||||||
trans_->readAll(&data_, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
hasData_ = true;
|
|
||||||
return data_;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
TTransport* trans_;
|
|
||||||
bool hasData_;
|
|
||||||
uint8_t data_;
|
|
||||||
};
|
|
||||||
|
|
||||||
private:
|
|
||||||
TTransport* trans_;
|
|
||||||
|
|
||||||
std::stack<boost::shared_ptr<TJSONContext> > contexts_;
|
|
||||||
boost::shared_ptr<TJSONContext> context_;
|
|
||||||
LookaheadReader reader_;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructs input and output protocol objects given transports.
|
|
||||||
*/
|
|
||||||
class TJSONProtocolFactory : public TProtocolFactory
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
TJSONProtocolFactory() {}
|
|
||||||
|
|
||||||
virtual ~TJSONProtocolFactory() {}
|
|
||||||
|
|
||||||
boost::shared_ptr<TProtocol> getProtocol(boost::shared_ptr<TTransport> trans)
|
|
||||||
{
|
|
||||||
return boost::shared_ptr<TProtocol>(new TJSONProtocol(trans));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} // apache::thrift::protocol
|
|
||||||
|
|
||||||
|
|
||||||
// TODO(dreiss): Move part of ThriftJSONString into a .cpp file and remove this.
|
|
||||||
#include <thrift/transport/TBufferTransports.h>
|
|
||||||
|
|
||||||
namespace apache
|
|
||||||
{
|
|
||||||
namespace thrift
|
|
||||||
{
|
|
||||||
|
|
||||||
template<typename ThriftStruct>
|
|
||||||
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);
|
|
||||||
TJSONProtocol protocol(trans);
|
|
||||||
|
|
||||||
ts.write(&protocol);
|
|
||||||
|
|
||||||
uint8_t* buf;
|
|
||||||
uint32_t size;
|
|
||||||
buffer->getBuffer(&buf, &size);
|
|
||||||
return std::string((char*)buf, (unsigned int)size);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
} // apache::thrift
|
|
||||||
|
|
||||||
@@ -1,101 +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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <thrift/protocol/TProtocolDecorator.h>
|
|
||||||
|
|
||||||
namespace apache
|
|
||||||
{
|
|
||||||
namespace thrift
|
|
||||||
{
|
|
||||||
namespace protocol
|
|
||||||
{
|
|
||||||
using boost::shared_ptr;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <code>TMultiplexedProtocol</code> is a protocol-independent concrete decorator
|
|
||||||
* that allows a Thrift client to communicate with a multiplexing Thrift server,
|
|
||||||
* by prepending the service name to the function name during function calls.
|
|
||||||
*
|
|
||||||
* \note THIS IS NOT USED BY SERVERS. On the server, use
|
|
||||||
* {@link apache::thrift::TMultiplexedProcessor TMultiplexedProcessor} to handle requests
|
|
||||||
* from a multiplexing client.
|
|
||||||
*
|
|
||||||
* This example uses a single socket transport to invoke two services:
|
|
||||||
*
|
|
||||||
* <blockquote><code>
|
|
||||||
* shared_ptr<TSocket> transport(new TSocket("localhost", 9090));
|
|
||||||
* transport->open();
|
|
||||||
*
|
|
||||||
* shared_ptr<TBinaryProtocol> protocol(new TBinaryProtocol(transport));
|
|
||||||
*
|
|
||||||
* shared_ptr<TMultiplexedProtocol> mp1(new TMultiplexedProtocol(protocol, "Calculator"));
|
|
||||||
* shared_ptr<CalculatorClient> service1(new CalculatorClient(mp1));
|
|
||||||
*
|
|
||||||
* shared_ptr<TMultiplexedProtocol> mp2(new TMultiplexedProtocol(protocol, "WeatherReport"));
|
|
||||||
* shared_ptr<WeatherReportClient> service2(new WeatherReportClient(mp2));
|
|
||||||
*
|
|
||||||
* service1->add(2,2);
|
|
||||||
* int temp = service2->getTemperature();
|
|
||||||
* </code></blockquote>
|
|
||||||
*
|
|
||||||
* @see apache::thrift::protocol::TProtocolDecorator
|
|
||||||
*/
|
|
||||||
class TMultiplexedProtocol : public TProtocolDecorator
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
/**
|
|
||||||
* Wrap the specified protocol, allowing it to be used to communicate with a
|
|
||||||
* multiplexing server. The <code>serviceName</code> is required as it is
|
|
||||||
* prepended to the message header so that the multiplexing server can broker
|
|
||||||
* the function call to the proper service.
|
|
||||||
*
|
|
||||||
* \param _protocol Your communication protocol of choice, e.g. <code>TBinaryProtocol</code>.
|
|
||||||
* \param _serviceName The service name of the service communicating via this protocol.
|
|
||||||
*/
|
|
||||||
TMultiplexedProtocol( shared_ptr<TProtocol> _protocol, const std::string& _serviceName )
|
|
||||||
: TProtocolDecorator(_protocol),
|
|
||||||
serviceName(_serviceName),
|
|
||||||
separator(":")
|
|
||||||
{ }
|
|
||||||
virtual ~TMultiplexedProtocol() {}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Prepends the service name to the function name, separated by TMultiplexedProtocol::SEPARATOR.
|
|
||||||
*
|
|
||||||
* \param [in] _name The name of the method to be called in the service.
|
|
||||||
* \param [in] _type The type of message
|
|
||||||
* \param [in] _name The sequential id of the message
|
|
||||||
*
|
|
||||||
* \throws TException Passed through from wrapped <code>TProtocol</code> instance.
|
|
||||||
*/
|
|
||||||
uint32_t writeMessageBegin_virt(
|
|
||||||
const std::string& _name,
|
|
||||||
const TMessageType _type,
|
|
||||||
const int32_t _seqid);
|
|
||||||
private:
|
|
||||||
const std::string serviceName;
|
|
||||||
const std::string separator;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,790 +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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <thrift/transport/TTransport.h>
|
|
||||||
#include <thrift/protocol/TProtocolException.h>
|
|
||||||
|
|
||||||
#include <boost/shared_ptr.hpp>
|
|
||||||
#include <boost/static_assert.hpp>
|
|
||||||
|
|
||||||
#ifdef HAVE_NETINET_IN_H
|
|
||||||
#include <netinet/in.h>
|
|
||||||
#endif
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <string>
|
|
||||||
#include <map>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
|
|
||||||
// Use this to get around strict aliasing rules.
|
|
||||||
// For example, uint64_t i = bitwise_cast<uint64_t>(returns_double());
|
|
||||||
// The most obvious implementation is to just cast a pointer,
|
|
||||||
// but that doesn't work.
|
|
||||||
// For a pretty in-depth explanation of the problem, see
|
|
||||||
// http://www.cellperformance.com/mike_acton/2006/06/ (...)
|
|
||||||
// understanding_strict_aliasing.html
|
|
||||||
template <typename To, typename From>
|
|
||||||
static inline To bitwise_cast(From from)
|
|
||||||
{
|
|
||||||
BOOST_STATIC_ASSERT(sizeof(From) == sizeof(To));
|
|
||||||
|
|
||||||
// BAD!!! These are all broken with -O2.
|
|
||||||
//return *reinterpret_cast<To*>(&from); // BAD!!!
|
|
||||||
//return *static_cast<To*>(static_cast<void*>(&from)); // BAD!!!
|
|
||||||
//return *(To*)(void*)&from; // BAD!!!
|
|
||||||
|
|
||||||
// Super clean and paritally blessed by section 3.9 of the standard.
|
|
||||||
//unsigned char c[sizeof(from)];
|
|
||||||
//memcpy(c, &from, sizeof(from));
|
|
||||||
//To to;
|
|
||||||
//memcpy(&to, c, sizeof(c));
|
|
||||||
//return to;
|
|
||||||
|
|
||||||
// Slightly more questionable.
|
|
||||||
// Same code emitted by GCC.
|
|
||||||
//To to;
|
|
||||||
//memcpy(&to, &from, sizeof(from));
|
|
||||||
//return to;
|
|
||||||
|
|
||||||
// Technically undefined, but almost universally supported,
|
|
||||||
// and the most efficient implementation.
|
|
||||||
union
|
|
||||||
{
|
|
||||||
From f;
|
|
||||||
To t;
|
|
||||||
} u;
|
|
||||||
u.f = from;
|
|
||||||
return u.t;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef HAVE_SYS_PARAM_H
|
|
||||||
#include <sys/param.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef __THRIFT_BYTE_ORDER
|
|
||||||
# if defined(BYTE_ORDER) && defined(LITTLE_ENDIAN) && defined(BIG_ENDIAN)
|
|
||||||
# define __THRIFT_BYTE_ORDER BYTE_ORDER
|
|
||||||
# define __THRIFT_LITTLE_ENDIAN LITTLE_ENDIAN
|
|
||||||
# define __THRIFT_BIG_ENDIAN BIG_ENDIAN
|
|
||||||
# else
|
|
||||||
# include <boost/config.hpp>
|
|
||||||
# include <boost/detail/endian.hpp>
|
|
||||||
# define __THRIFT_BYTE_ORDER BOOST_BYTE_ORDER
|
|
||||||
# ifdef BOOST_LITTLE_ENDIAN
|
|
||||||
# define __THRIFT_LITTLE_ENDIAN __THRIFT_BYTE_ORDER
|
|
||||||
# define __THRIFT_BIG_ENDIAN 0
|
|
||||||
# else
|
|
||||||
# define __THRIFT_LITTLE_ENDIAN 0
|
|
||||||
# define __THRIFT_BIG_ENDIAN __THRIFT_BYTE_ORDER
|
|
||||||
# endif
|
|
||||||
# endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if __THRIFT_BYTE_ORDER == __THRIFT_BIG_ENDIAN
|
|
||||||
# define ntohll(n) (n)
|
|
||||||
# define htonll(n) (n)
|
|
||||||
# if defined(__GNUC__) && defined(__GLIBC__)
|
|
||||||
# include <byteswap.h>
|
|
||||||
# define htolell(n) bswap_64(n)
|
|
||||||
# define letohll(n) bswap_64(n)
|
|
||||||
# else /* GNUC & GLIBC */
|
|
||||||
# define bswap_64(n) \
|
|
||||||
( (((n) & 0xff00000000000000ull) >> 56) \
|
|
||||||
| (((n) & 0x00ff000000000000ull) >> 40) \
|
|
||||||
| (((n) & 0x0000ff0000000000ull) >> 24) \
|
|
||||||
| (((n) & 0x000000ff00000000ull) >> 8) \
|
|
||||||
| (((n) & 0x00000000ff000000ull) << 8) \
|
|
||||||
| (((n) & 0x0000000000ff0000ull) << 24) \
|
|
||||||
| (((n) & 0x000000000000ff00ull) << 40) \
|
|
||||||
| (((n) & 0x00000000000000ffull) << 56) )
|
|
||||||
# define htolell(n) bswap_64(n)
|
|
||||||
# define letohll(n) bswap_64(n)
|
|
||||||
# endif /* GNUC & GLIBC */
|
|
||||||
#elif __THRIFT_BYTE_ORDER == __THRIFT_LITTLE_ENDIAN
|
|
||||||
# define htolell(n) (n)
|
|
||||||
# define letohll(n) (n)
|
|
||||||
# if defined(__GNUC__) && defined(__GLIBC__)
|
|
||||||
# include <byteswap.h>
|
|
||||||
# define ntohll(n) bswap_64(n)
|
|
||||||
# define htonll(n) bswap_64(n)
|
|
||||||
# elif defined(_MSC_VER) /* Microsoft Visual C++ */
|
|
||||||
# define ntohll(n) ( _byteswap_uint64((uint64_t)n) )
|
|
||||||
# define htonll(n) ( _byteswap_uint64((uint64_t)n) )
|
|
||||||
# else /* Not GNUC/GLIBC or MSVC */
|
|
||||||
# define ntohll(n) ( (((uint64_t)ntohl((uint32_t)n)) << 32) + ntohl((uint32_t)(n >> 32)) )
|
|
||||||
# define htonll(n) ( (((uint64_t)htonl((uint32_t)n)) << 32) + htonl((uint32_t)(n >> 32)) )
|
|
||||||
# endif /* GNUC/GLIBC or MSVC or something else */
|
|
||||||
#else /* __THRIFT_BYTE_ORDER */
|
|
||||||
# error "Can't define htonll or ntohll!"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace apache
|
|
||||||
{
|
|
||||||
namespace thrift
|
|
||||||
{
|
|
||||||
namespace protocol
|
|
||||||
{
|
|
||||||
|
|
||||||
using apache::thrift::transport::TTransport;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Enumerated definition of the types that the Thrift protocol supports.
|
|
||||||
* Take special note of the T_END type which is used specifically to mark
|
|
||||||
* the end of a sequence of fields.
|
|
||||||
*/
|
|
||||||
enum TType
|
|
||||||
{
|
|
||||||
T_STOP = 0,
|
|
||||||
T_VOID = 1,
|
|
||||||
T_BOOL = 2,
|
|
||||||
T_BYTE = 3,
|
|
||||||
T_I08 = 3,
|
|
||||||
T_I16 = 6,
|
|
||||||
T_I32 = 8,
|
|
||||||
T_U64 = 9,
|
|
||||||
T_I64 = 10,
|
|
||||||
T_DOUBLE = 4,
|
|
||||||
T_STRING = 11,
|
|
||||||
T_UTF7 = 11,
|
|
||||||
T_STRUCT = 12,
|
|
||||||
T_MAP = 13,
|
|
||||||
T_SET = 14,
|
|
||||||
T_LIST = 15,
|
|
||||||
T_UTF8 = 16,
|
|
||||||
T_UTF16 = 17
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Enumerated definition of the message types that the Thrift protocol
|
|
||||||
* supports.
|
|
||||||
*/
|
|
||||||
enum TMessageType
|
|
||||||
{
|
|
||||||
T_CALL = 1,
|
|
||||||
T_REPLY = 2,
|
|
||||||
T_EXCEPTION = 3,
|
|
||||||
T_ONEWAY = 4
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Helper template for implementing TProtocol::skip().
|
|
||||||
*
|
|
||||||
* Templatized to avoid having to make virtual function calls.
|
|
||||||
*/
|
|
||||||
template <class Protocol_>
|
|
||||||
uint32_t skip(Protocol_& prot, TType type)
|
|
||||||
{
|
|
||||||
switch (type)
|
|
||||||
{
|
|
||||||
case T_BOOL:
|
|
||||||
{
|
|
||||||
bool boolv;
|
|
||||||
return prot.readBool(boolv);
|
|
||||||
}
|
|
||||||
|
|
||||||
case T_BYTE:
|
|
||||||
{
|
|
||||||
int8_t bytev;
|
|
||||||
return prot.readByte(bytev);
|
|
||||||
}
|
|
||||||
|
|
||||||
case T_I16:
|
|
||||||
{
|
|
||||||
int16_t i16;
|
|
||||||
return prot.readI16(i16);
|
|
||||||
}
|
|
||||||
|
|
||||||
case T_I32:
|
|
||||||
{
|
|
||||||
int32_t i32;
|
|
||||||
return prot.readI32(i32);
|
|
||||||
}
|
|
||||||
|
|
||||||
case T_I64:
|
|
||||||
{
|
|
||||||
int64_t i64;
|
|
||||||
return prot.readI64(i64);
|
|
||||||
}
|
|
||||||
|
|
||||||
case T_DOUBLE:
|
|
||||||
{
|
|
||||||
double dub;
|
|
||||||
return prot.readDouble(dub);
|
|
||||||
}
|
|
||||||
|
|
||||||
case T_STRING:
|
|
||||||
{
|
|
||||||
std::string str;
|
|
||||||
return prot.readBinary(str);
|
|
||||||
}
|
|
||||||
|
|
||||||
case T_STRUCT:
|
|
||||||
{
|
|
||||||
uint32_t result = 0;
|
|
||||||
std::string name;
|
|
||||||
int16_t fid;
|
|
||||||
TType ftype;
|
|
||||||
result += prot.readStructBegin(name);
|
|
||||||
|
|
||||||
while (true)
|
|
||||||
{
|
|
||||||
result += prot.readFieldBegin(name, ftype, fid);
|
|
||||||
|
|
||||||
if (ftype == T_STOP)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
result += skip(prot, ftype);
|
|
||||||
result += prot.readFieldEnd();
|
|
||||||
}
|
|
||||||
|
|
||||||
result += prot.readStructEnd();
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
case T_MAP:
|
|
||||||
{
|
|
||||||
uint32_t result = 0;
|
|
||||||
TType keyType;
|
|
||||||
TType valType;
|
|
||||||
uint32_t i, size;
|
|
||||||
result += prot.readMapBegin(keyType, valType, size);
|
|
||||||
|
|
||||||
for (i = 0; i < size; i++)
|
|
||||||
{
|
|
||||||
result += skip(prot, keyType);
|
|
||||||
result += skip(prot, valType);
|
|
||||||
}
|
|
||||||
|
|
||||||
result += prot.readMapEnd();
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
case T_SET:
|
|
||||||
{
|
|
||||||
uint32_t result = 0;
|
|
||||||
TType elemType;
|
|
||||||
uint32_t i, size;
|
|
||||||
result += prot.readSetBegin(elemType, size);
|
|
||||||
|
|
||||||
for (i = 0; i < size; i++)
|
|
||||||
{
|
|
||||||
result += skip(prot, elemType);
|
|
||||||
}
|
|
||||||
|
|
||||||
result += prot.readSetEnd();
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
case T_LIST:
|
|
||||||
{
|
|
||||||
uint32_t result = 0;
|
|
||||||
TType elemType;
|
|
||||||
uint32_t i, size;
|
|
||||||
result += prot.readListBegin(elemType, size);
|
|
||||||
|
|
||||||
for (i = 0; i < size; i++)
|
|
||||||
{
|
|
||||||
result += skip(prot, elemType);
|
|
||||||
}
|
|
||||||
|
|
||||||
result += prot.readListEnd();
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
case T_STOP:
|
|
||||||
case T_VOID:
|
|
||||||
case T_U64:
|
|
||||||
case T_UTF8:
|
|
||||||
case T_UTF16:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Abstract class for a thrift protocol driver. These are all the methods that
|
|
||||||
* a protocol must implement. Essentially, there must be some way of reading
|
|
||||||
* and writing all the base types, plus a mechanism for writing out structs
|
|
||||||
* with indexed fields.
|
|
||||||
*
|
|
||||||
* TProtocol objects should not be shared across multiple encoding contexts,
|
|
||||||
* as they may need to maintain internal state in some protocols (i.e. XML).
|
|
||||||
* Note that is is acceptable for the TProtocol module to do its own internal
|
|
||||||
* buffered reads/writes to the underlying TTransport where appropriate (i.e.
|
|
||||||
* when parsing an input XML stream, reading should be batched rather than
|
|
||||||
* looking ahead character by character for a close tag).
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
class TProtocol
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
virtual ~TProtocol() {}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Writing functions.
|
|
||||||
*/
|
|
||||||
|
|
||||||
virtual uint32_t writeMessageBegin_virt(const std::string& name,
|
|
||||||
const TMessageType messageType,
|
|
||||||
const int32_t seqid) = 0;
|
|
||||||
|
|
||||||
virtual uint32_t writeMessageEnd_virt() = 0;
|
|
||||||
|
|
||||||
|
|
||||||
virtual uint32_t writeStructBegin_virt(const char* name) = 0;
|
|
||||||
|
|
||||||
virtual uint32_t writeStructEnd_virt() = 0;
|
|
||||||
|
|
||||||
virtual uint32_t writeFieldBegin_virt(const char* name,
|
|
||||||
const TType fieldType,
|
|
||||||
const int16_t fieldId) = 0;
|
|
||||||
|
|
||||||
virtual uint32_t writeFieldEnd_virt() = 0;
|
|
||||||
|
|
||||||
virtual uint32_t writeFieldStop_virt() = 0;
|
|
||||||
|
|
||||||
virtual uint32_t writeMapBegin_virt(const TType keyType,
|
|
||||||
const TType valType,
|
|
||||||
const uint32_t size) = 0;
|
|
||||||
|
|
||||||
virtual uint32_t writeMapEnd_virt() = 0;
|
|
||||||
|
|
||||||
virtual uint32_t writeListBegin_virt(const TType elemType,
|
|
||||||
const uint32_t size) = 0;
|
|
||||||
|
|
||||||
virtual uint32_t writeListEnd_virt() = 0;
|
|
||||||
|
|
||||||
virtual uint32_t writeSetBegin_virt(const TType elemType,
|
|
||||||
const uint32_t size) = 0;
|
|
||||||
|
|
||||||
virtual uint32_t writeSetEnd_virt() = 0;
|
|
||||||
|
|
||||||
virtual uint32_t writeBool_virt(const bool value) = 0;
|
|
||||||
|
|
||||||
virtual uint32_t writeByte_virt(const int8_t byte) = 0;
|
|
||||||
|
|
||||||
virtual uint32_t writeI16_virt(const int16_t i16) = 0;
|
|
||||||
|
|
||||||
virtual uint32_t writeI32_virt(const int32_t i32) = 0;
|
|
||||||
|
|
||||||
virtual uint32_t writeI64_virt(const int64_t i64) = 0;
|
|
||||||
|
|
||||||
virtual uint32_t writeDouble_virt(const double dub) = 0;
|
|
||||||
|
|
||||||
virtual uint32_t writeString_virt(const std::string& str) = 0;
|
|
||||||
|
|
||||||
virtual uint32_t writeBinary_virt(const std::string& str) = 0;
|
|
||||||
|
|
||||||
uint32_t writeMessageBegin(const std::string& name,
|
|
||||||
const TMessageType messageType,
|
|
||||||
const int32_t seqid)
|
|
||||||
{
|
|
||||||
T_VIRTUAL_CALL();
|
|
||||||
return writeMessageBegin_virt(name, messageType, seqid);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t writeMessageEnd()
|
|
||||||
{
|
|
||||||
T_VIRTUAL_CALL();
|
|
||||||
return writeMessageEnd_virt();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
uint32_t writeStructBegin(const char* name)
|
|
||||||
{
|
|
||||||
T_VIRTUAL_CALL();
|
|
||||||
return writeStructBegin_virt(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t writeStructEnd()
|
|
||||||
{
|
|
||||||
T_VIRTUAL_CALL();
|
|
||||||
return writeStructEnd_virt();
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t writeFieldBegin(const char* name,
|
|
||||||
const TType fieldType,
|
|
||||||
const int16_t fieldId)
|
|
||||||
{
|
|
||||||
T_VIRTUAL_CALL();
|
|
||||||
return writeFieldBegin_virt(name, fieldType, fieldId);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t writeFieldEnd()
|
|
||||||
{
|
|
||||||
T_VIRTUAL_CALL();
|
|
||||||
return writeFieldEnd_virt();
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t writeFieldStop()
|
|
||||||
{
|
|
||||||
T_VIRTUAL_CALL();
|
|
||||||
return writeFieldStop_virt();
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t writeMapBegin(const TType keyType,
|
|
||||||
const TType valType,
|
|
||||||
const uint32_t size)
|
|
||||||
{
|
|
||||||
T_VIRTUAL_CALL();
|
|
||||||
return writeMapBegin_virt(keyType, valType, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t writeMapEnd()
|
|
||||||
{
|
|
||||||
T_VIRTUAL_CALL();
|
|
||||||
return writeMapEnd_virt();
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t writeListBegin(const TType elemType, const uint32_t size)
|
|
||||||
{
|
|
||||||
T_VIRTUAL_CALL();
|
|
||||||
return writeListBegin_virt(elemType, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t writeListEnd()
|
|
||||||
{
|
|
||||||
T_VIRTUAL_CALL();
|
|
||||||
return writeListEnd_virt();
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t writeSetBegin(const TType elemType, const uint32_t size)
|
|
||||||
{
|
|
||||||
T_VIRTUAL_CALL();
|
|
||||||
return writeSetBegin_virt(elemType, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t writeSetEnd()
|
|
||||||
{
|
|
||||||
T_VIRTUAL_CALL();
|
|
||||||
return writeSetEnd_virt();
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t writeBool(const bool value)
|
|
||||||
{
|
|
||||||
T_VIRTUAL_CALL();
|
|
||||||
return writeBool_virt(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t writeByte(const int8_t byte)
|
|
||||||
{
|
|
||||||
T_VIRTUAL_CALL();
|
|
||||||
return writeByte_virt(byte);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t writeI16(const int16_t i16)
|
|
||||||
{
|
|
||||||
T_VIRTUAL_CALL();
|
|
||||||
return writeI16_virt(i16);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t writeI32(const int32_t i32)
|
|
||||||
{
|
|
||||||
T_VIRTUAL_CALL();
|
|
||||||
return writeI32_virt(i32);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t writeI64(const int64_t i64)
|
|
||||||
{
|
|
||||||
T_VIRTUAL_CALL();
|
|
||||||
return writeI64_virt(i64);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t writeDouble(const double dub)
|
|
||||||
{
|
|
||||||
T_VIRTUAL_CALL();
|
|
||||||
return writeDouble_virt(dub);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t writeString(const std::string& str)
|
|
||||||
{
|
|
||||||
T_VIRTUAL_CALL();
|
|
||||||
return writeString_virt(str);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t writeBinary(const std::string& str)
|
|
||||||
{
|
|
||||||
T_VIRTUAL_CALL();
|
|
||||||
return writeBinary_virt(str);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reading functions
|
|
||||||
*/
|
|
||||||
|
|
||||||
virtual uint32_t readMessageBegin_virt(std::string& name,
|
|
||||||
TMessageType& messageType,
|
|
||||||
int32_t& seqid) = 0;
|
|
||||||
|
|
||||||
virtual uint32_t readMessageEnd_virt() = 0;
|
|
||||||
|
|
||||||
virtual uint32_t readStructBegin_virt(std::string& name) = 0;
|
|
||||||
|
|
||||||
virtual uint32_t readStructEnd_virt() = 0;
|
|
||||||
|
|
||||||
virtual uint32_t readFieldBegin_virt(std::string& name,
|
|
||||||
TType& fieldType,
|
|
||||||
int16_t& fieldId) = 0;
|
|
||||||
|
|
||||||
virtual uint32_t readFieldEnd_virt() = 0;
|
|
||||||
|
|
||||||
virtual uint32_t readMapBegin_virt(TType& keyType,
|
|
||||||
TType& valType,
|
|
||||||
uint32_t& size) = 0;
|
|
||||||
|
|
||||||
virtual uint32_t readMapEnd_virt() = 0;
|
|
||||||
|
|
||||||
virtual uint32_t readListBegin_virt(TType& elemType,
|
|
||||||
uint32_t& size) = 0;
|
|
||||||
|
|
||||||
virtual uint32_t readListEnd_virt() = 0;
|
|
||||||
|
|
||||||
virtual uint32_t readSetBegin_virt(TType& elemType,
|
|
||||||
uint32_t& size) = 0;
|
|
||||||
|
|
||||||
virtual uint32_t readSetEnd_virt() = 0;
|
|
||||||
|
|
||||||
virtual uint32_t readBool_virt(bool& value) = 0;
|
|
||||||
|
|
||||||
virtual uint32_t readBool_virt(std::vector<bool>::reference value) = 0;
|
|
||||||
|
|
||||||
virtual uint32_t readByte_virt(int8_t& byte) = 0;
|
|
||||||
|
|
||||||
virtual uint32_t readI16_virt(int16_t& i16) = 0;
|
|
||||||
|
|
||||||
virtual uint32_t readI32_virt(int32_t& i32) = 0;
|
|
||||||
|
|
||||||
virtual uint32_t readI64_virt(int64_t& i64) = 0;
|
|
||||||
|
|
||||||
virtual uint32_t readDouble_virt(double& dub) = 0;
|
|
||||||
|
|
||||||
virtual uint32_t readString_virt(std::string& str) = 0;
|
|
||||||
|
|
||||||
virtual uint32_t readBinary_virt(std::string& str) = 0;
|
|
||||||
|
|
||||||
uint32_t readMessageBegin(std::string& name,
|
|
||||||
TMessageType& messageType,
|
|
||||||
int32_t& seqid)
|
|
||||||
{
|
|
||||||
T_VIRTUAL_CALL();
|
|
||||||
return readMessageBegin_virt(name, messageType, seqid);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t readMessageEnd()
|
|
||||||
{
|
|
||||||
T_VIRTUAL_CALL();
|
|
||||||
return readMessageEnd_virt();
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t readStructBegin(std::string& name)
|
|
||||||
{
|
|
||||||
T_VIRTUAL_CALL();
|
|
||||||
return readStructBegin_virt(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t readStructEnd()
|
|
||||||
{
|
|
||||||
T_VIRTUAL_CALL();
|
|
||||||
return readStructEnd_virt();
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t readFieldBegin(std::string& name,
|
|
||||||
TType& fieldType,
|
|
||||||
int16_t& fieldId)
|
|
||||||
{
|
|
||||||
T_VIRTUAL_CALL();
|
|
||||||
return readFieldBegin_virt(name, fieldType, fieldId);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t readFieldEnd()
|
|
||||||
{
|
|
||||||
T_VIRTUAL_CALL();
|
|
||||||
return readFieldEnd_virt();
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t readMapBegin(TType& keyType, TType& valType, uint32_t& size)
|
|
||||||
{
|
|
||||||
T_VIRTUAL_CALL();
|
|
||||||
return readMapBegin_virt(keyType, valType, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t readMapEnd()
|
|
||||||
{
|
|
||||||
T_VIRTUAL_CALL();
|
|
||||||
return readMapEnd_virt();
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t readListBegin(TType& elemType, uint32_t& size)
|
|
||||||
{
|
|
||||||
T_VIRTUAL_CALL();
|
|
||||||
return readListBegin_virt(elemType, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t readListEnd()
|
|
||||||
{
|
|
||||||
T_VIRTUAL_CALL();
|
|
||||||
return readListEnd_virt();
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t readSetBegin(TType& elemType, uint32_t& size)
|
|
||||||
{
|
|
||||||
T_VIRTUAL_CALL();
|
|
||||||
return readSetBegin_virt(elemType, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t readSetEnd()
|
|
||||||
{
|
|
||||||
T_VIRTUAL_CALL();
|
|
||||||
return readSetEnd_virt();
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t readBool(bool& value)
|
|
||||||
{
|
|
||||||
T_VIRTUAL_CALL();
|
|
||||||
return readBool_virt(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t readByte(int8_t& byte)
|
|
||||||
{
|
|
||||||
T_VIRTUAL_CALL();
|
|
||||||
return readByte_virt(byte);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t readI16(int16_t& i16)
|
|
||||||
{
|
|
||||||
T_VIRTUAL_CALL();
|
|
||||||
return readI16_virt(i16);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t readI32(int32_t& i32)
|
|
||||||
{
|
|
||||||
T_VIRTUAL_CALL();
|
|
||||||
return readI32_virt(i32);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t readI64(int64_t& i64)
|
|
||||||
{
|
|
||||||
T_VIRTUAL_CALL();
|
|
||||||
return readI64_virt(i64);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t readDouble(double& dub)
|
|
||||||
{
|
|
||||||
T_VIRTUAL_CALL();
|
|
||||||
return readDouble_virt(dub);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t readString(std::string& str)
|
|
||||||
{
|
|
||||||
T_VIRTUAL_CALL();
|
|
||||||
return readString_virt(str);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t readBinary(std::string& str)
|
|
||||||
{
|
|
||||||
T_VIRTUAL_CALL();
|
|
||||||
return readBinary_virt(str);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* std::vector is specialized for bool, and its elements are individual bits
|
|
||||||
* rather than bools. We need to define a different version of readBool()
|
|
||||||
* to work with std::vector<bool>.
|
|
||||||
*/
|
|
||||||
uint32_t readBool(std::vector<bool>::reference value)
|
|
||||||
{
|
|
||||||
T_VIRTUAL_CALL();
|
|
||||||
return readBool_virt(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Method to arbitrarily skip over data.
|
|
||||||
*/
|
|
||||||
uint32_t skip(TType type)
|
|
||||||
{
|
|
||||||
T_VIRTUAL_CALL();
|
|
||||||
return skip_virt(type);
|
|
||||||
}
|
|
||||||
virtual uint32_t skip_virt(TType type)
|
|
||||||
{
|
|
||||||
return ::apache::thrift::protocol::skip(*this, type);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline boost::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_;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
TProtocol(boost::shared_ptr<TTransport> ptrans):
|
|
||||||
ptrans_(ptrans)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
boost::shared_ptr<TTransport> ptrans_;
|
|
||||||
|
|
||||||
private:
|
|
||||||
TProtocol() {}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructs input and output protocol objects given transports.
|
|
||||||
*/
|
|
||||||
class TProtocolFactory
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
TProtocolFactory() {}
|
|
||||||
|
|
||||||
virtual ~TProtocolFactory() {}
|
|
||||||
|
|
||||||
virtual boost::shared_ptr<TProtocol> getProtocol(boost::shared_ptr<TTransport> trans) = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Dummy protocol class.
|
|
||||||
*
|
|
||||||
* This class does nothing, and should never be instantiated.
|
|
||||||
* It is used only by the generator code.
|
|
||||||
*/
|
|
||||||
class TDummyProtocol : public TProtocol
|
|
||||||
{
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} // apache::thrift::protocol
|
|
||||||
|
|
||||||
@@ -1,254 +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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <thrift/protocol/TProtocol.h>
|
|
||||||
#include <boost/shared_ptr.hpp>
|
|
||||||
|
|
||||||
namespace apache
|
|
||||||
{
|
|
||||||
namespace thrift
|
|
||||||
{
|
|
||||||
namespace protocol
|
|
||||||
{
|
|
||||||
using boost::shared_ptr;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <code>TProtocolDecorator</code> forwards all requests to an enclosed
|
|
||||||
* <code>TProtocol</code> instance, providing a way to author concise
|
|
||||||
* concrete decorator subclasses.
|
|
||||||
*
|
|
||||||
* <p>See p.175 of Design Patterns (by Gamma et al.)</p>
|
|
||||||
*
|
|
||||||
* @see apache::thrift::protocol::TMultiplexedProtocol
|
|
||||||
*/
|
|
||||||
class TProtocolDecorator : public TProtocol
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
virtual ~TProtocolDecorator() {}
|
|
||||||
|
|
||||||
// Desc: Initializes the protocol decorator object.
|
|
||||||
TProtocolDecorator( shared_ptr<TProtocol> proto )
|
|
||||||
: TProtocol(proto->getTransport()), protocol(proto)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual uint32_t writeMessageBegin_virt(
|
|
||||||
const std::string& name,
|
|
||||||
const TMessageType messageType,
|
|
||||||
const int32_t seqid)
|
|
||||||
{
|
|
||||||
return protocol->writeMessageBegin(name, messageType, seqid);
|
|
||||||
}
|
|
||||||
virtual uint32_t writeMessageEnd_virt()
|
|
||||||
{
|
|
||||||
return protocol->writeMessageEnd();
|
|
||||||
}
|
|
||||||
virtual uint32_t writeStructBegin_virt(const char* name)
|
|
||||||
{
|
|
||||||
return protocol->writeStructBegin(name);
|
|
||||||
}
|
|
||||||
virtual uint32_t writeStructEnd_virt()
|
|
||||||
{
|
|
||||||
return protocol->writeStructEnd();
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual uint32_t writeFieldBegin_virt(const char* name,
|
|
||||||
const TType fieldType,
|
|
||||||
const int16_t fieldId)
|
|
||||||
{
|
|
||||||
return protocol->writeFieldBegin(name, fieldType, fieldId);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual uint32_t writeFieldEnd_virt()
|
|
||||||
{
|
|
||||||
return protocol->writeFieldEnd();
|
|
||||||
}
|
|
||||||
virtual uint32_t writeFieldStop_virt()
|
|
||||||
{
|
|
||||||
return protocol->writeFieldStop();
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual uint32_t writeMapBegin_virt(const TType keyType,
|
|
||||||
const TType valType,
|
|
||||||
const uint32_t size)
|
|
||||||
{
|
|
||||||
return protocol->writeMapBegin(keyType, valType, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual uint32_t writeMapEnd_virt()
|
|
||||||
{
|
|
||||||
return protocol->writeMapEnd();
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual uint32_t writeListBegin_virt(const TType elemType, const uint32_t size)
|
|
||||||
{
|
|
||||||
return protocol->writeListBegin(elemType, size);
|
|
||||||
}
|
|
||||||
virtual uint32_t writeListEnd_virt()
|
|
||||||
{
|
|
||||||
return protocol->writeListEnd();
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual uint32_t writeSetBegin_virt(const TType elemType, const uint32_t size)
|
|
||||||
{
|
|
||||||
return protocol->writeSetBegin(elemType, size);
|
|
||||||
}
|
|
||||||
virtual uint32_t writeSetEnd_virt()
|
|
||||||
{
|
|
||||||
return protocol->writeSetEnd();
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual uint32_t writeBool_virt(const bool value)
|
|
||||||
{
|
|
||||||
return protocol->writeBool(value);
|
|
||||||
}
|
|
||||||
virtual uint32_t writeByte_virt(const int8_t byte)
|
|
||||||
{
|
|
||||||
return protocol->writeByte(byte);
|
|
||||||
}
|
|
||||||
virtual uint32_t writeI16_virt(const int16_t i16)
|
|
||||||
{
|
|
||||||
return protocol->writeI16(i16);
|
|
||||||
}
|
|
||||||
virtual uint32_t writeI32_virt(const int32_t i32)
|
|
||||||
{
|
|
||||||
return protocol->writeI32(i32);
|
|
||||||
}
|
|
||||||
virtual uint32_t writeI64_virt(const int64_t i64)
|
|
||||||
{
|
|
||||||
return protocol->writeI64(i64);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual uint32_t writeDouble_virt(const double dub)
|
|
||||||
{
|
|
||||||
return protocol->writeDouble(dub);
|
|
||||||
}
|
|
||||||
virtual uint32_t writeString_virt(const std::string& str)
|
|
||||||
{
|
|
||||||
return protocol->writeString(str);
|
|
||||||
}
|
|
||||||
virtual uint32_t writeBinary_virt(const std::string& str)
|
|
||||||
{
|
|
||||||
return protocol->writeBinary(str);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual uint32_t readMessageBegin_virt(std::string& name, TMessageType& messageType, int32_t& seqid)
|
|
||||||
{
|
|
||||||
return protocol->readMessageBegin(name, messageType, seqid);
|
|
||||||
}
|
|
||||||
virtual uint32_t readMessageEnd_virt()
|
|
||||||
{
|
|
||||||
return protocol->readMessageEnd();
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual uint32_t readStructBegin_virt(std::string& name)
|
|
||||||
{
|
|
||||||
return protocol->readStructBegin(name);
|
|
||||||
}
|
|
||||||
virtual uint32_t readStructEnd_virt()
|
|
||||||
{
|
|
||||||
return protocol->readStructEnd();
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual uint32_t readFieldBegin_virt(std::string& name, TType& fieldType, int16_t& fieldId)
|
|
||||||
{
|
|
||||||
return protocol->readFieldBegin(name, fieldType, fieldId);
|
|
||||||
}
|
|
||||||
virtual uint32_t readFieldEnd_virt()
|
|
||||||
{
|
|
||||||
return protocol->readFieldEnd();
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual uint32_t readMapBegin_virt(TType& keyType, TType& valType, uint32_t& size)
|
|
||||||
{
|
|
||||||
return protocol->readMapBegin(keyType, valType, size);
|
|
||||||
}
|
|
||||||
virtual uint32_t readMapEnd_virt()
|
|
||||||
{
|
|
||||||
return protocol->readMapEnd();
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual uint32_t readListBegin_virt(TType& elemType, uint32_t& size)
|
|
||||||
{
|
|
||||||
return protocol->readListBegin(elemType, size);
|
|
||||||
}
|
|
||||||
virtual uint32_t readListEnd_virt()
|
|
||||||
{
|
|
||||||
return protocol->readListEnd();
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual uint32_t readSetBegin_virt(TType& elemType, uint32_t& size)
|
|
||||||
{
|
|
||||||
return protocol->readSetBegin(elemType, size);
|
|
||||||
}
|
|
||||||
virtual uint32_t readSetEnd_virt()
|
|
||||||
{
|
|
||||||
return protocol->readSetEnd();
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual uint32_t readBool_virt(bool& value)
|
|
||||||
{
|
|
||||||
return protocol->readBool(value);
|
|
||||||
}
|
|
||||||
virtual uint32_t readBool_virt(std::vector<bool>::reference value)
|
|
||||||
{
|
|
||||||
return protocol->readBool(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual uint32_t readByte_virt(int8_t& byte)
|
|
||||||
{
|
|
||||||
return protocol->readByte(byte);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual uint32_t readI16_virt(int16_t& i16)
|
|
||||||
{
|
|
||||||
return protocol->readI16(i16);
|
|
||||||
}
|
|
||||||
virtual uint32_t readI32_virt(int32_t& i32)
|
|
||||||
{
|
|
||||||
return protocol->readI32(i32);
|
|
||||||
}
|
|
||||||
virtual uint32_t readI64_virt(int64_t& i64)
|
|
||||||
{
|
|
||||||
return protocol->readI64(i64);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual uint32_t readDouble_virt(double& dub)
|
|
||||||
{
|
|
||||||
return protocol->readDouble(dub);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual uint32_t readString_virt(std::string& str)
|
|
||||||
{
|
|
||||||
return protocol->readString(str);
|
|
||||||
}
|
|
||||||
virtual uint32_t readBinary_virt(std::string& str)
|
|
||||||
{
|
|
||||||
return protocol->readBinary(str);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
shared_ptr<TProtocol> protocol;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,130 +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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
namespace apache
|
|
||||||
{
|
|
||||||
namespace thrift
|
|
||||||
{
|
|
||||||
namespace protocol
|
|
||||||
{
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class to encapsulate all the possible types of protocol errors that may
|
|
||||||
* occur in various protocol systems. This provides a sort of generic
|
|
||||||
* wrapper around the vague UNIX E_ error codes that lets a common code
|
|
||||||
* base of error handling to be used for various types of protocols, i.e.
|
|
||||||
* pipes etc.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
class TProtocolException : public apache::thrift::TException
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Error codes for the various types of exceptions.
|
|
||||||
*/
|
|
||||||
enum TProtocolExceptionType
|
|
||||||
{
|
|
||||||
UNKNOWN = 0
|
|
||||||
, INVALID_DATA = 1
|
|
||||||
, NEGATIVE_SIZE = 2
|
|
||||||
, SIZE_LIMIT = 3
|
|
||||||
, BAD_VERSION = 4
|
|
||||||
, NOT_IMPLEMENTED = 5
|
|
||||||
};
|
|
||||||
|
|
||||||
TProtocolException() :
|
|
||||||
apache::thrift::TException(),
|
|
||||||
type_(UNKNOWN) {}
|
|
||||||
|
|
||||||
TProtocolException(TProtocolExceptionType type) :
|
|
||||||
apache::thrift::TException(),
|
|
||||||
type_(type) {}
|
|
||||||
|
|
||||||
TProtocolException(const std::string& message) :
|
|
||||||
apache::thrift::TException(message),
|
|
||||||
type_(UNKNOWN) {}
|
|
||||||
|
|
||||||
TProtocolException(TProtocolExceptionType type, const std::string& message) :
|
|
||||||
apache::thrift::TException(message),
|
|
||||||
type_(type) {}
|
|
||||||
|
|
||||||
virtual ~TProtocolException() throw() {}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns an error code that provides information about the type of error
|
|
||||||
* that has occurred.
|
|
||||||
*
|
|
||||||
* @return Error code
|
|
||||||
*/
|
|
||||||
TProtocolExceptionType getType()
|
|
||||||
{
|
|
||||||
return type_;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual const char* what() const throw()
|
|
||||||
{
|
|
||||||
if (message_.empty())
|
|
||||||
{
|
|
||||||
switch (type_)
|
|
||||||
{
|
|
||||||
case UNKNOWN :
|
|
||||||
return "TProtocolException: Unknown protocol exception";
|
|
||||||
|
|
||||||
case INVALID_DATA :
|
|
||||||
return "TProtocolException: Invalid data";
|
|
||||||
|
|
||||||
case NEGATIVE_SIZE :
|
|
||||||
return "TProtocolException: Negative size";
|
|
||||||
|
|
||||||
case SIZE_LIMIT :
|
|
||||||
return "TProtocolException: Exceeded size limit";
|
|
||||||
|
|
||||||
case BAD_VERSION :
|
|
||||||
return "TProtocolException: Invalid version";
|
|
||||||
|
|
||||||
case NOT_IMPLEMENTED :
|
|
||||||
return "TProtocolException: Not implemented";
|
|
||||||
|
|
||||||
default :
|
|
||||||
return "TProtocolException: (Invalid exception type)";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return message_.c_str();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
/**
|
|
||||||
* Error code
|
|
||||||
*/
|
|
||||||
TProtocolExceptionType type_;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} // apache::thrift::protocol
|
|
||||||
|
|
||||||
@@ -1,219 +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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <thrift/protocol/TVirtualProtocol.h>
|
|
||||||
|
|
||||||
namespace apache
|
|
||||||
{
|
|
||||||
namespace thrift
|
|
||||||
{
|
|
||||||
namespace protocol
|
|
||||||
{
|
|
||||||
|
|
||||||
using apache::thrift::transport::TTransport;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Puts a wiretap on a protocol object. Any reads to this class are passed
|
|
||||||
* through to an enclosed protocol object, but also mirrored as write to a
|
|
||||||
* second protocol object.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
class TProtocolTap : public TVirtualProtocol<TProtocolTap>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
TProtocolTap(boost::shared_ptr<TProtocol> source,
|
|
||||||
boost::shared_ptr<TProtocol> sink)
|
|
||||||
: TVirtualProtocol<TProtocolTap>(source->getTransport())
|
|
||||||
, source_(source)
|
|
||||||
, sink_(sink)
|
|
||||||
{}
|
|
||||||
|
|
||||||
uint32_t readMessageBegin(std::string& name,
|
|
||||||
TMessageType& messageType,
|
|
||||||
int32_t& seqid)
|
|
||||||
{
|
|
||||||
uint32_t rv = source_->readMessageBegin(name, messageType, seqid);
|
|
||||||
sink_->writeMessageBegin(name, messageType, seqid);
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t readMessageEnd()
|
|
||||||
{
|
|
||||||
uint32_t rv = source_->readMessageEnd();
|
|
||||||
sink_->writeMessageEnd();
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t readStructBegin(std::string& name)
|
|
||||||
{
|
|
||||||
uint32_t rv = source_->readStructBegin(name);
|
|
||||||
sink_->writeStructBegin(name.c_str());
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t readStructEnd()
|
|
||||||
{
|
|
||||||
uint32_t rv = source_->readStructEnd();
|
|
||||||
sink_->writeStructEnd();
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t readFieldBegin(std::string& name,
|
|
||||||
TType& fieldType,
|
|
||||||
int16_t& fieldId)
|
|
||||||
{
|
|
||||||
uint32_t rv = source_->readFieldBegin(name, fieldType, fieldId);
|
|
||||||
|
|
||||||
if (fieldType == T_STOP)
|
|
||||||
{
|
|
||||||
sink_->writeFieldStop();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
sink_->writeFieldBegin(name.c_str(), fieldType, fieldId);
|
|
||||||
}
|
|
||||||
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
uint32_t readFieldEnd()
|
|
||||||
{
|
|
||||||
uint32_t rv = source_->readFieldEnd();
|
|
||||||
sink_->writeFieldEnd();
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t readMapBegin(TType& keyType,
|
|
||||||
TType& valType,
|
|
||||||
uint32_t& size)
|
|
||||||
{
|
|
||||||
uint32_t rv = source_->readMapBegin(keyType, valType, size);
|
|
||||||
sink_->writeMapBegin(keyType, valType, size);
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
uint32_t readMapEnd()
|
|
||||||
{
|
|
||||||
uint32_t rv = source_->readMapEnd();
|
|
||||||
sink_->writeMapEnd();
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t readListBegin(TType& elemType, uint32_t& size)
|
|
||||||
{
|
|
||||||
uint32_t rv = source_->readListBegin(elemType, size);
|
|
||||||
sink_->writeListBegin(elemType, size);
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
uint32_t readListEnd()
|
|
||||||
{
|
|
||||||
uint32_t rv = source_->readListEnd();
|
|
||||||
sink_->writeListEnd();
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t readSetBegin(TType& elemType, uint32_t& size)
|
|
||||||
{
|
|
||||||
uint32_t rv = source_->readSetBegin(elemType, size);
|
|
||||||
sink_->writeSetBegin(elemType, size);
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
uint32_t readSetEnd()
|
|
||||||
{
|
|
||||||
uint32_t rv = source_->readSetEnd();
|
|
||||||
sink_->writeSetEnd();
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t readBool(bool& value)
|
|
||||||
{
|
|
||||||
uint32_t rv = source_->readBool(value);
|
|
||||||
sink_->writeBool(value);
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Provide the default readBool() implementation for std::vector<bool>
|
|
||||||
using TVirtualProtocol<TProtocolTap>::readBool;
|
|
||||||
|
|
||||||
uint32_t readByte(int8_t& byte)
|
|
||||||
{
|
|
||||||
uint32_t rv = source_->readByte(byte);
|
|
||||||
sink_->writeByte(byte);
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t readI16(int16_t& i16)
|
|
||||||
{
|
|
||||||
uint32_t rv = source_->readI16(i16);
|
|
||||||
sink_->writeI16(i16);
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t readI32(int32_t& i32)
|
|
||||||
{
|
|
||||||
uint32_t rv = source_->readI32(i32);
|
|
||||||
sink_->writeI32(i32);
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t readI64(int64_t& i64)
|
|
||||||
{
|
|
||||||
uint32_t rv = source_->readI64(i64);
|
|
||||||
sink_->writeI64(i64);
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t readDouble(double& dub)
|
|
||||||
{
|
|
||||||
uint32_t rv = source_->readDouble(dub);
|
|
||||||
sink_->writeDouble(dub);
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t readString(std::string& str)
|
|
||||||
{
|
|
||||||
uint32_t rv = source_->readString(str);
|
|
||||||
sink_->writeString(str);
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t readBinary(std::string& str)
|
|
||||||
{
|
|
||||||
uint32_t rv = source_->readBinary(str);
|
|
||||||
sink_->writeBinary(str);
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
boost::shared_ptr<TProtocol> source_;
|
|
||||||
boost::shared_ptr<TProtocol> sink_;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} // apache::thrift::protocol
|
|
||||||
|
|
||||||
@@ -1,659 +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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <thrift/protocol/TProtocol.h>
|
|
||||||
|
|
||||||
namespace apache
|
|
||||||
{
|
|
||||||
namespace thrift
|
|
||||||
{
|
|
||||||
namespace protocol
|
|
||||||
{
|
|
||||||
|
|
||||||
using apache::thrift::transport::TTransport;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Helper class that provides default implementations of TProtocol methods.
|
|
||||||
*
|
|
||||||
* This class provides default implementations of the non-virtual TProtocol
|
|
||||||
* methods. It exists primarily so TVirtualProtocol can derive from it. It
|
|
||||||
* prevents TVirtualProtocol methods from causing infinite recursion if the
|
|
||||||
* non-virtual methods are not overridden by the TVirtualProtocol subclass.
|
|
||||||
*
|
|
||||||
* You probably don't want to use this class directly. Use TVirtualProtocol
|
|
||||||
* instead.
|
|
||||||
*/
|
|
||||||
class TProtocolDefaults : public TProtocol
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
uint32_t readMessageBegin(std::string& name,
|
|
||||||
TMessageType& messageType,
|
|
||||||
int32_t& seqid)
|
|
||||||
{
|
|
||||||
(void) name;
|
|
||||||
(void) messageType;
|
|
||||||
(void) seqid;
|
|
||||||
throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
|
|
||||||
"this protocol does not support reading (yet).");
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t readMessageEnd()
|
|
||||||
{
|
|
||||||
throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
|
|
||||||
"this protocol does not support reading (yet).");
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t readStructBegin(std::string& name)
|
|
||||||
{
|
|
||||||
(void) name;
|
|
||||||
throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
|
|
||||||
"this protocol does not support reading (yet).");
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t readStructEnd()
|
|
||||||
{
|
|
||||||
throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
|
|
||||||
"this protocol does not support reading (yet).");
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t readFieldBegin(std::string& name,
|
|
||||||
TType& fieldType,
|
|
||||||
int16_t& fieldId)
|
|
||||||
{
|
|
||||||
(void) name;
|
|
||||||
(void) fieldType;
|
|
||||||
(void) fieldId;
|
|
||||||
throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
|
|
||||||
"this protocol does not support reading (yet).");
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t readFieldEnd()
|
|
||||||
{
|
|
||||||
throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
|
|
||||||
"this protocol does not support reading (yet).");
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t readMapBegin(TType& keyType, TType& valType, uint32_t& size)
|
|
||||||
{
|
|
||||||
(void) keyType;
|
|
||||||
(void) valType;
|
|
||||||
(void) size;
|
|
||||||
throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
|
|
||||||
"this protocol does not support reading (yet).");
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t readMapEnd()
|
|
||||||
{
|
|
||||||
throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
|
|
||||||
"this protocol does not support reading (yet).");
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t readListBegin(TType& elemType, uint32_t& size)
|
|
||||||
{
|
|
||||||
(void) elemType;
|
|
||||||
(void) size;
|
|
||||||
throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
|
|
||||||
"this protocol does not support reading (yet).");
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t readListEnd()
|
|
||||||
{
|
|
||||||
throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
|
|
||||||
"this protocol does not support reading (yet).");
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t readSetBegin(TType& elemType, uint32_t& size)
|
|
||||||
{
|
|
||||||
(void) elemType;
|
|
||||||
(void) size;
|
|
||||||
throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
|
|
||||||
"this protocol does not support reading (yet).");
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t readSetEnd()
|
|
||||||
{
|
|
||||||
throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
|
|
||||||
"this protocol does not support reading (yet).");
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t readBool(bool& value)
|
|
||||||
{
|
|
||||||
(void) value;
|
|
||||||
throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
|
|
||||||
"this protocol does not support reading (yet).");
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t readBool(std::vector<bool>::reference value)
|
|
||||||
{
|
|
||||||
(void) value;
|
|
||||||
throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
|
|
||||||
"this protocol does not support reading (yet).");
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t readByte(int8_t& byte)
|
|
||||||
{
|
|
||||||
(void) byte;
|
|
||||||
throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
|
|
||||||
"this protocol does not support reading (yet).");
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t readI16(int16_t& i16)
|
|
||||||
{
|
|
||||||
(void) i16;
|
|
||||||
throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
|
|
||||||
"this protocol does not support reading (yet).");
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t readI32(int32_t& i32)
|
|
||||||
{
|
|
||||||
(void) i32;
|
|
||||||
throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
|
|
||||||
"this protocol does not support reading (yet).");
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t readI64(int64_t& i64)
|
|
||||||
{
|
|
||||||
(void) i64;
|
|
||||||
throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
|
|
||||||
"this protocol does not support reading (yet).");
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t readDouble(double& dub)
|
|
||||||
{
|
|
||||||
(void) dub;
|
|
||||||
throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
|
|
||||||
"this protocol does not support reading (yet).");
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t readString(std::string& str)
|
|
||||||
{
|
|
||||||
(void) str;
|
|
||||||
throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
|
|
||||||
"this protocol does not support reading (yet).");
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t readBinary(std::string& str)
|
|
||||||
{
|
|
||||||
(void) str;
|
|
||||||
throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
|
|
||||||
"this protocol does not support reading (yet).");
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t writeMessageBegin(const std::string& name,
|
|
||||||
const TMessageType messageType,
|
|
||||||
const int32_t seqid)
|
|
||||||
{
|
|
||||||
(void) name;
|
|
||||||
(void) messageType;
|
|
||||||
(void) seqid;
|
|
||||||
throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
|
|
||||||
"this protocol does not support writing (yet).");
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t writeMessageEnd()
|
|
||||||
{
|
|
||||||
throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
|
|
||||||
"this protocol does not support writing (yet).");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
uint32_t writeStructBegin(const char* name)
|
|
||||||
{
|
|
||||||
(void) name;
|
|
||||||
throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
|
|
||||||
"this protocol does not support writing (yet).");
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t writeStructEnd()
|
|
||||||
{
|
|
||||||
throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
|
|
||||||
"this protocol does not support writing (yet).");
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t writeFieldBegin(const char* name,
|
|
||||||
const TType fieldType,
|
|
||||||
const int16_t fieldId)
|
|
||||||
{
|
|
||||||
(void) name;
|
|
||||||
(void) fieldType;
|
|
||||||
(void) fieldId;
|
|
||||||
throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
|
|
||||||
"this protocol does not support writing (yet).");
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t writeFieldEnd()
|
|
||||||
{
|
|
||||||
throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
|
|
||||||
"this protocol does not support writing (yet).");
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t writeFieldStop()
|
|
||||||
{
|
|
||||||
throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
|
|
||||||
"this protocol does not support writing (yet).");
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t writeMapBegin(const TType keyType,
|
|
||||||
const TType valType,
|
|
||||||
const uint32_t size)
|
|
||||||
{
|
|
||||||
(void) keyType;
|
|
||||||
(void) valType;
|
|
||||||
(void) size;
|
|
||||||
throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
|
|
||||||
"this protocol does not support writing (yet).");
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t writeMapEnd()
|
|
||||||
{
|
|
||||||
throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
|
|
||||||
"this protocol does not support writing (yet).");
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t writeListBegin(const TType elemType, const uint32_t size)
|
|
||||||
{
|
|
||||||
(void) elemType;
|
|
||||||
(void) size;
|
|
||||||
throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
|
|
||||||
"this protocol does not support writing (yet).");
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t writeListEnd()
|
|
||||||
{
|
|
||||||
throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
|
|
||||||
"this protocol does not support writing (yet).");
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t writeSetBegin(const TType elemType, const uint32_t size)
|
|
||||||
{
|
|
||||||
(void) elemType;
|
|
||||||
(void) size;
|
|
||||||
throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
|
|
||||||
"this protocol does not support writing (yet).");
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t writeSetEnd()
|
|
||||||
{
|
|
||||||
throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
|
|
||||||
"this protocol does not support writing (yet).");
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t writeBool(const bool value)
|
|
||||||
{
|
|
||||||
(void) value;
|
|
||||||
throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
|
|
||||||
"this protocol does not support writing (yet).");
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t writeByte(const int8_t byte)
|
|
||||||
{
|
|
||||||
(void) byte;
|
|
||||||
throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
|
|
||||||
"this protocol does not support writing (yet).");
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t writeI16(const int16_t i16)
|
|
||||||
{
|
|
||||||
(void) i16;
|
|
||||||
throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
|
|
||||||
"this protocol does not support writing (yet).");
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t writeI32(const int32_t i32)
|
|
||||||
{
|
|
||||||
(void) i32;
|
|
||||||
throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
|
|
||||||
"this protocol does not support writing (yet).");
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t writeI64(const int64_t i64)
|
|
||||||
{
|
|
||||||
(void) i64;
|
|
||||||
throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
|
|
||||||
"this protocol does not support writing (yet).");
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t writeDouble(const double dub)
|
|
||||||
{
|
|
||||||
(void) dub;
|
|
||||||
throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
|
|
||||||
"this protocol does not support writing (yet).");
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t writeString(const std::string& str)
|
|
||||||
{
|
|
||||||
(void) str;
|
|
||||||
throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
|
|
||||||
"this protocol does not support writing (yet).");
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t writeBinary(const std::string& str)
|
|
||||||
{
|
|
||||||
(void) str;
|
|
||||||
throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
|
|
||||||
"this protocol does not support writing (yet).");
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t skip(TType type)
|
|
||||||
{
|
|
||||||
return ::apache::thrift::protocol::skip(*this, type);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
TProtocolDefaults(boost::shared_ptr<TTransport> ptrans)
|
|
||||||
: TProtocol(ptrans)
|
|
||||||
{}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Concrete TProtocol classes should inherit from TVirtualProtocol
|
|
||||||
* so they don't have to manually override virtual methods.
|
|
||||||
*/
|
|
||||||
template <class Protocol_, class Super_ = TProtocolDefaults>
|
|
||||||
class TVirtualProtocol : public Super_
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
/**
|
|
||||||
* Writing functions.
|
|
||||||
*/
|
|
||||||
|
|
||||||
virtual uint32_t writeMessageBegin_virt(const std::string& name,
|
|
||||||
const TMessageType messageType,
|
|
||||||
const int32_t seqid)
|
|
||||||
{
|
|
||||||
return static_cast<Protocol_*>(this)->writeMessageBegin(name, messageType,
|
|
||||||
seqid);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual uint32_t writeMessageEnd_virt()
|
|
||||||
{
|
|
||||||
return static_cast<Protocol_*>(this)->writeMessageEnd();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
virtual uint32_t writeStructBegin_virt(const char* name)
|
|
||||||
{
|
|
||||||
return static_cast<Protocol_*>(this)->writeStructBegin(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual uint32_t writeStructEnd_virt()
|
|
||||||
{
|
|
||||||
return static_cast<Protocol_*>(this)->writeStructEnd();
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual uint32_t writeFieldBegin_virt(const char* name,
|
|
||||||
const TType fieldType,
|
|
||||||
const int16_t fieldId)
|
|
||||||
{
|
|
||||||
return static_cast<Protocol_*>(this)->writeFieldBegin(name, fieldType,
|
|
||||||
fieldId);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual uint32_t writeFieldEnd_virt()
|
|
||||||
{
|
|
||||||
return static_cast<Protocol_*>(this)->writeFieldEnd();
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual uint32_t writeFieldStop_virt()
|
|
||||||
{
|
|
||||||
return static_cast<Protocol_*>(this)->writeFieldStop();
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual uint32_t writeMapBegin_virt(const TType keyType,
|
|
||||||
const TType valType,
|
|
||||||
const uint32_t size)
|
|
||||||
{
|
|
||||||
return static_cast<Protocol_*>(this)->writeMapBegin(keyType, valType, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual uint32_t writeMapEnd_virt()
|
|
||||||
{
|
|
||||||
return static_cast<Protocol_*>(this)->writeMapEnd();
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual uint32_t writeListBegin_virt(const TType elemType,
|
|
||||||
const uint32_t size)
|
|
||||||
{
|
|
||||||
return static_cast<Protocol_*>(this)->writeListBegin(elemType, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual uint32_t writeListEnd_virt()
|
|
||||||
{
|
|
||||||
return static_cast<Protocol_*>(this)->writeListEnd();
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual uint32_t writeSetBegin_virt(const TType elemType,
|
|
||||||
const uint32_t size)
|
|
||||||
{
|
|
||||||
return static_cast<Protocol_*>(this)->writeSetBegin(elemType, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual uint32_t writeSetEnd_virt()
|
|
||||||
{
|
|
||||||
return static_cast<Protocol_*>(this)->writeSetEnd();
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual uint32_t writeBool_virt(const bool value)
|
|
||||||
{
|
|
||||||
return static_cast<Protocol_*>(this)->writeBool(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual uint32_t writeByte_virt(const int8_t byte)
|
|
||||||
{
|
|
||||||
return static_cast<Protocol_*>(this)->writeByte(byte);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual uint32_t writeI16_virt(const int16_t i16)
|
|
||||||
{
|
|
||||||
return static_cast<Protocol_*>(this)->writeI16(i16);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual uint32_t writeI32_virt(const int32_t i32)
|
|
||||||
{
|
|
||||||
return static_cast<Protocol_*>(this)->writeI32(i32);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual uint32_t writeI64_virt(const int64_t i64)
|
|
||||||
{
|
|
||||||
return static_cast<Protocol_*>(this)->writeI64(i64);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual uint32_t writeDouble_virt(const double dub)
|
|
||||||
{
|
|
||||||
return static_cast<Protocol_*>(this)->writeDouble(dub);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual uint32_t writeString_virt(const std::string& str)
|
|
||||||
{
|
|
||||||
return static_cast<Protocol_*>(this)->writeString(str);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual uint32_t writeBinary_virt(const std::string& str)
|
|
||||||
{
|
|
||||||
return static_cast<Protocol_*>(this)->writeBinary(str);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reading functions
|
|
||||||
*/
|
|
||||||
|
|
||||||
virtual uint32_t readMessageBegin_virt(std::string& name,
|
|
||||||
TMessageType& messageType,
|
|
||||||
int32_t& seqid)
|
|
||||||
{
|
|
||||||
return static_cast<Protocol_*>(this)->readMessageBegin(name, messageType,
|
|
||||||
seqid);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual uint32_t readMessageEnd_virt()
|
|
||||||
{
|
|
||||||
return static_cast<Protocol_*>(this)->readMessageEnd();
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual uint32_t readStructBegin_virt(std::string& name)
|
|
||||||
{
|
|
||||||
return static_cast<Protocol_*>(this)->readStructBegin(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual uint32_t readStructEnd_virt()
|
|
||||||
{
|
|
||||||
return static_cast<Protocol_*>(this)->readStructEnd();
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual uint32_t readFieldBegin_virt(std::string& name,
|
|
||||||
TType& fieldType,
|
|
||||||
int16_t& fieldId)
|
|
||||||
{
|
|
||||||
return static_cast<Protocol_*>(this)->readFieldBegin(name, fieldType,
|
|
||||||
fieldId);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual uint32_t readFieldEnd_virt()
|
|
||||||
{
|
|
||||||
return static_cast<Protocol_*>(this)->readFieldEnd();
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual uint32_t readMapBegin_virt(TType& keyType,
|
|
||||||
TType& valType,
|
|
||||||
uint32_t& size)
|
|
||||||
{
|
|
||||||
return static_cast<Protocol_*>(this)->readMapBegin(keyType, valType, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual uint32_t readMapEnd_virt()
|
|
||||||
{
|
|
||||||
return static_cast<Protocol_*>(this)->readMapEnd();
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual uint32_t readListBegin_virt(TType& elemType,
|
|
||||||
uint32_t& size)
|
|
||||||
{
|
|
||||||
return static_cast<Protocol_*>(this)->readListBegin(elemType, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual uint32_t readListEnd_virt()
|
|
||||||
{
|
|
||||||
return static_cast<Protocol_*>(this)->readListEnd();
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual uint32_t readSetBegin_virt(TType& elemType,
|
|
||||||
uint32_t& size)
|
|
||||||
{
|
|
||||||
return static_cast<Protocol_*>(this)->readSetBegin(elemType, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual uint32_t readSetEnd_virt()
|
|
||||||
{
|
|
||||||
return static_cast<Protocol_*>(this)->readSetEnd();
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual uint32_t readBool_virt(bool& value)
|
|
||||||
{
|
|
||||||
return static_cast<Protocol_*>(this)->readBool(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual uint32_t readBool_virt(std::vector<bool>::reference value)
|
|
||||||
{
|
|
||||||
return static_cast<Protocol_*>(this)->readBool(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual uint32_t readByte_virt(int8_t& byte)
|
|
||||||
{
|
|
||||||
return static_cast<Protocol_*>(this)->readByte(byte);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual uint32_t readI16_virt(int16_t& i16)
|
|
||||||
{
|
|
||||||
return static_cast<Protocol_*>(this)->readI16(i16);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual uint32_t readI32_virt(int32_t& i32)
|
|
||||||
{
|
|
||||||
return static_cast<Protocol_*>(this)->readI32(i32);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual uint32_t readI64_virt(int64_t& i64)
|
|
||||||
{
|
|
||||||
return static_cast<Protocol_*>(this)->readI64(i64);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual uint32_t readDouble_virt(double& dub)
|
|
||||||
{
|
|
||||||
return static_cast<Protocol_*>(this)->readDouble(dub);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual uint32_t readString_virt(std::string& str)
|
|
||||||
{
|
|
||||||
return static_cast<Protocol_*>(this)->readString(str);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual uint32_t readBinary_virt(std::string& str)
|
|
||||||
{
|
|
||||||
return static_cast<Protocol_*>(this)->readBinary(str);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual uint32_t skip_virt(TType type)
|
|
||||||
{
|
|
||||||
return static_cast<Protocol_*>(this)->skip(type);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Provide a default skip() implementation that uses non-virtual read
|
|
||||||
* methods.
|
|
||||||
*
|
|
||||||
* Note: subclasses that use TVirtualProtocol to derive from another protocol
|
|
||||||
* implementation (i.e., not TProtocolDefaults) should beware that this may
|
|
||||||
* override any non-default skip() implementation provided by the parent
|
|
||||||
* transport class. They may need to explicitly redefine skip() to call the
|
|
||||||
* correct parent implementation, if desired.
|
|
||||||
*/
|
|
||||||
uint32_t skip(TType type)
|
|
||||||
{
|
|
||||||
Protocol_* const prot = static_cast<Protocol_*>(this);
|
|
||||||
return ::apache::thrift::protocol::skip(*prot, type);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Provide a default readBool() implementation for use with
|
|
||||||
* std::vector<bool>, that behaves the same as reading into a normal bool.
|
|
||||||
*
|
|
||||||
* Subclasses can override this if desired, but there normally shouldn't
|
|
||||||
* be a need to.
|
|
||||||
*/
|
|
||||||
uint32_t readBool(std::vector<bool>::reference value)
|
|
||||||
{
|
|
||||||
bool b = false;
|
|
||||||
uint32_t ret = static_cast<Protocol_*>(this)->readBool(b);
|
|
||||||
value = b;
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
using Super_::readBool; // so we don't hide readBool(bool&)
|
|
||||||
|
|
||||||
protected:
|
|
||||||
TVirtualProtocol(boost::shared_ptr<TTransport> ptrans)
|
|
||||||
: Super_(ptrans)
|
|
||||||
{}
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} // apache::thrift::protocol
|
|
||||||
|
|
||||||
@@ -1,70 +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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <boost/shared_ptr.hpp>
|
|
||||||
|
|
||||||
#include <thrift/transport/TVirtualTransport.h>
|
|
||||||
|
|
||||||
class QIODevice;
|
|
||||||
|
|
||||||
namespace apache
|
|
||||||
{
|
|
||||||
namespace thrift
|
|
||||||
{
|
|
||||||
namespace transport
|
|
||||||
{
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Transport that operates on a QIODevice (socket, file, etc).
|
|
||||||
*/
|
|
||||||
class TQIODeviceTransport : public apache::thrift::transport::TVirtualTransport<TQIODeviceTransport>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
explicit TQIODeviceTransport(boost::shared_ptr<QIODevice> dev);
|
|
||||||
virtual ~TQIODeviceTransport();
|
|
||||||
|
|
||||||
void open();
|
|
||||||
bool isOpen();
|
|
||||||
bool peek();
|
|
||||||
void close();
|
|
||||||
|
|
||||||
uint32_t readAll(uint8_t* buf, uint32_t len);
|
|
||||||
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();
|
|
||||||
|
|
||||||
uint8_t* borrow(uint8_t* buf, uint32_t* len);
|
|
||||||
void consume(uint32_t len);
|
|
||||||
|
|
||||||
private:
|
|
||||||
TQIODeviceTransport(const TQIODeviceTransport&);
|
|
||||||
TQIODeviceTransport& operator=(const TQIODeviceTransport&);
|
|
||||||
|
|
||||||
boost::shared_ptr<QIODevice> dev_;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} // apache::thrift::transport
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,85 +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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <QObject>
|
|
||||||
#include <QTcpServer>
|
|
||||||
|
|
||||||
#include <boost/shared_ptr.hpp>
|
|
||||||
|
|
||||||
namespace apache
|
|
||||||
{
|
|
||||||
namespace thrift
|
|
||||||
{
|
|
||||||
namespace protocol
|
|
||||||
{
|
|
||||||
class TProtocolFactory;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} // apache::thrift::protocol
|
|
||||||
|
|
||||||
namespace apache
|
|
||||||
{
|
|
||||||
namespace thrift
|
|
||||||
{
|
|
||||||
namespace async
|
|
||||||
{
|
|
||||||
|
|
||||||
class TAsyncProcessor;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Server that uses Qt to listen for connections.
|
|
||||||
* Simply give it a QTcpServer that is listening, along with an async
|
|
||||||
* processor and a protocol factory, and then run the Qt event loop.
|
|
||||||
*/
|
|
||||||
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,
|
|
||||||
QT_PREPEND_NAMESPACE(QObject)* parent = NULL);
|
|
||||||
virtual ~TQTcpServer();
|
|
||||||
|
|
||||||
private Q_SLOTS:
|
|
||||||
void processIncoming();
|
|
||||||
void beginDecode();
|
|
||||||
void socketClosed();
|
|
||||||
|
|
||||||
private:
|
|
||||||
TQTcpServer(const TQTcpServer&);
|
|
||||||
TQTcpServer& operator=(const TQTcpServer&);
|
|
||||||
|
|
||||||
class ConnectionContext;
|
|
||||||
|
|
||||||
void finish(boost::shared_ptr<ConnectionContext> ctx, bool healthy);
|
|
||||||
|
|
||||||
boost::shared_ptr<QTcpServer> server_;
|
|
||||||
boost::shared_ptr<TAsyncProcessor> processor_;
|
|
||||||
boost::shared_ptr<apache::thrift::protocol::TProtocolFactory> pfact_;
|
|
||||||
|
|
||||||
std::map<QT_PREPEND_NAMESPACE(QTcpSocket)*, boost::shared_ptr<ConnectionContext> > ctxMap_;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} // apache::thrift::async
|
|
||||||
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,343 +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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <thrift/TProcessor.h>
|
|
||||||
#include <thrift/transport/TServerTransport.h>
|
|
||||||
#include <thrift/protocol/TBinaryProtocol.h>
|
|
||||||
#include <thrift/concurrency/Thread.h>
|
|
||||||
|
|
||||||
#include <boost/shared_ptr.hpp>
|
|
||||||
|
|
||||||
namespace apache
|
|
||||||
{
|
|
||||||
namespace thrift
|
|
||||||
{
|
|
||||||
namespace server
|
|
||||||
{
|
|
||||||
|
|
||||||
using apache::thrift::TProcessor;
|
|
||||||
using apache::thrift::protocol::TBinaryProtocolFactory;
|
|
||||||
using apache::thrift::protocol::TProtocol;
|
|
||||||
using apache::thrift::protocol::TProtocolFactory;
|
|
||||||
using apache::thrift::transport::TServerTransport;
|
|
||||||
using apache::thrift::transport::TTransport;
|
|
||||||
using apache::thrift::transport::TTransportFactory;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Virtual interface class that can handle events from the server core. To
|
|
||||||
* use this you should subclass it and implement the methods that you care
|
|
||||||
* about. Your subclass can also store local data that you may care about,
|
|
||||||
* such as additional "arguments" to these methods (stored in the object
|
|
||||||
* instance's state).
|
|
||||||
*/
|
|
||||||
class TServerEventHandler
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
virtual ~TServerEventHandler() {}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called before the server begins.
|
|
||||||
*/
|
|
||||||
virtual void preServe() {}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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)
|
|
||||||
{
|
|
||||||
(void)input;
|
|
||||||
(void)output;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called when a client has finished request-handling to delete server
|
|
||||||
* context.
|
|
||||||
*/
|
|
||||||
virtual void deleteContext(void* serverContext,
|
|
||||||
boost::shared_ptr<TProtocol>input,
|
|
||||||
boost::shared_ptr<TProtocol>output)
|
|
||||||
{
|
|
||||||
(void)serverContext;
|
|
||||||
(void)input;
|
|
||||||
(void)output;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called when a client is about to call the processor.
|
|
||||||
*/
|
|
||||||
virtual void processContext(void* serverContext,
|
|
||||||
boost::shared_ptr<TTransport> transport)
|
|
||||||
{
|
|
||||||
(void)serverContext;
|
|
||||||
(void)transport;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Prevent direct instantiation.
|
|
||||||
*/
|
|
||||||
TServerEventHandler() {}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Thrift server.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
class TServer : public concurrency::Runnable
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
virtual ~TServer() {}
|
|
||||||
|
|
||||||
virtual void serve() = 0;
|
|
||||||
|
|
||||||
virtual void stop() {}
|
|
||||||
|
|
||||||
// Allows running the server as a Runnable thread
|
|
||||||
virtual void run()
|
|
||||||
{
|
|
||||||
serve();
|
|
||||||
}
|
|
||||||
|
|
||||||
boost::shared_ptr<TProcessorFactory> getProcessorFactory()
|
|
||||||
{
|
|
||||||
return processorFactory_;
|
|
||||||
}
|
|
||||||
|
|
||||||
boost::shared_ptr<TServerTransport> getServerTransport()
|
|
||||||
{
|
|
||||||
return serverTransport_;
|
|
||||||
}
|
|
||||||
|
|
||||||
boost::shared_ptr<TTransportFactory> getInputTransportFactory()
|
|
||||||
{
|
|
||||||
return inputTransportFactory_;
|
|
||||||
}
|
|
||||||
|
|
||||||
boost::shared_ptr<TTransportFactory> getOutputTransportFactory()
|
|
||||||
{
|
|
||||||
return outputTransportFactory_;
|
|
||||||
}
|
|
||||||
|
|
||||||
boost::shared_ptr<TProtocolFactory> getInputProtocolFactory()
|
|
||||||
{
|
|
||||||
return inputProtocolFactory_;
|
|
||||||
}
|
|
||||||
|
|
||||||
boost::shared_ptr<TProtocolFactory> getOutputProtocolFactory()
|
|
||||||
{
|
|
||||||
return outputProtocolFactory_;
|
|
||||||
}
|
|
||||||
|
|
||||||
boost::shared_ptr<TServerEventHandler> getEventHandler()
|
|
||||||
{
|
|
||||||
return eventHandler_;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
template<typename ProcessorFactory>
|
|
||||||
TServer(const boost::shared_ptr<ProcessorFactory>& processorFactory,
|
|
||||||
THRIFT_OVERLOAD_IF(ProcessorFactory, TProcessorFactory)):
|
|
||||||
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()));
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename Processor>
|
|
||||||
TServer(const boost::shared_ptr<Processor>& processor,
|
|
||||||
THRIFT_OVERLOAD_IF(Processor, TProcessor)):
|
|
||||||
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()));
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename ProcessorFactory>
|
|
||||||
TServer(const boost::shared_ptr<ProcessorFactory>& processorFactory,
|
|
||||||
const boost::shared_ptr<TServerTransport>& serverTransport,
|
|
||||||
THRIFT_OVERLOAD_IF(ProcessorFactory, TProcessorFactory)):
|
|
||||||
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()));
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename Processor>
|
|
||||||
TServer(const boost::shared_ptr<Processor>& processor,
|
|
||||||
const boost::shared_ptr<TServerTransport>& serverTransport,
|
|
||||||
THRIFT_OVERLOAD_IF(Processor, TProcessor)):
|
|
||||||
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()));
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename ProcessorFactory>
|
|
||||||
TServer(const boost::shared_ptr<ProcessorFactory>& processorFactory,
|
|
||||||
const boost::shared_ptr<TServerTransport>& serverTransport,
|
|
||||||
const boost::shared_ptr<TTransportFactory>& transportFactory,
|
|
||||||
const boost::shared_ptr<TProtocolFactory>& protocolFactory,
|
|
||||||
THRIFT_OVERLOAD_IF(ProcessorFactory, TProcessorFactory)):
|
|
||||||
processorFactory_(processorFactory),
|
|
||||||
serverTransport_(serverTransport),
|
|
||||||
inputTransportFactory_(transportFactory),
|
|
||||||
outputTransportFactory_(transportFactory),
|
|
||||||
inputProtocolFactory_(protocolFactory),
|
|
||||||
outputProtocolFactory_(protocolFactory) {}
|
|
||||||
|
|
||||||
template<typename Processor>
|
|
||||||
TServer(const boost::shared_ptr<Processor>& processor,
|
|
||||||
const boost::shared_ptr<TServerTransport>& serverTransport,
|
|
||||||
const boost::shared_ptr<TTransportFactory>& transportFactory,
|
|
||||||
const boost::shared_ptr<TProtocolFactory>& protocolFactory,
|
|
||||||
THRIFT_OVERLOAD_IF(Processor, TProcessor)):
|
|
||||||
processorFactory_(new TSingletonProcessorFactory(processor)),
|
|
||||||
serverTransport_(serverTransport),
|
|
||||||
inputTransportFactory_(transportFactory),
|
|
||||||
outputTransportFactory_(transportFactory),
|
|
||||||
inputProtocolFactory_(protocolFactory),
|
|
||||||
outputProtocolFactory_(protocolFactory) {}
|
|
||||||
|
|
||||||
template<typename ProcessorFactory>
|
|
||||||
TServer(const boost::shared_ptr<ProcessorFactory>& 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,
|
|
||||||
THRIFT_OVERLOAD_IF(ProcessorFactory, TProcessorFactory)):
|
|
||||||
processorFactory_(processorFactory),
|
|
||||||
serverTransport_(serverTransport),
|
|
||||||
inputTransportFactory_(inputTransportFactory),
|
|
||||||
outputTransportFactory_(outputTransportFactory),
|
|
||||||
inputProtocolFactory_(inputProtocolFactory),
|
|
||||||
outputProtocolFactory_(outputProtocolFactory) {}
|
|
||||||
|
|
||||||
template<typename Processor>
|
|
||||||
TServer(const boost::shared_ptr<Processor>& 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,
|
|
||||||
THRIFT_OVERLOAD_IF(Processor, TProcessor)):
|
|
||||||
processorFactory_(new TSingletonProcessorFactory(processor)),
|
|
||||||
serverTransport_(serverTransport),
|
|
||||||
inputTransportFactory_(inputTransportFactory),
|
|
||||||
outputTransportFactory_(outputTransportFactory),
|
|
||||||
inputProtocolFactory_(inputProtocolFactory),
|
|
||||||
outputProtocolFactory_(outputProtocolFactory) {}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get a TProcessor to handle calls on a particular connection.
|
|
||||||
*
|
|
||||||
* This method should only be called once per connection (never once per
|
|
||||||
* 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)
|
|
||||||
{
|
|
||||||
TConnectionInfo connInfo;
|
|
||||||
connInfo.input = inputProtocol;
|
|
||||||
connInfo.output = outputProtocol;
|
|
||||||
connInfo.transport = transport;
|
|
||||||
return processorFactory_->getProcessor(connInfo);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Class variables
|
|
||||||
boost::shared_ptr<TProcessorFactory> processorFactory_;
|
|
||||||
boost::shared_ptr<TServerTransport> serverTransport_;
|
|
||||||
|
|
||||||
boost::shared_ptr<TTransportFactory> inputTransportFactory_;
|
|
||||||
boost::shared_ptr<TTransportFactory> outputTransportFactory_;
|
|
||||||
|
|
||||||
boost::shared_ptr<TProtocolFactory> inputProtocolFactory_;
|
|
||||||
boost::shared_ptr<TProtocolFactory> outputProtocolFactory_;
|
|
||||||
|
|
||||||
boost::shared_ptr<TServerEventHandler> eventHandler_;
|
|
||||||
|
|
||||||
public:
|
|
||||||
void setInputTransportFactory(boost::shared_ptr<TTransportFactory> inputTransportFactory)
|
|
||||||
{
|
|
||||||
inputTransportFactory_ = inputTransportFactory;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setOutputTransportFactory(boost::shared_ptr<TTransportFactory> outputTransportFactory)
|
|
||||||
{
|
|
||||||
outputTransportFactory_ = outputTransportFactory;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setInputProtocolFactory(boost::shared_ptr<TProtocolFactory> inputProtocolFactory)
|
|
||||||
{
|
|
||||||
inputProtocolFactory_ = inputProtocolFactory;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setOutputProtocolFactory(boost::shared_ptr<TProtocolFactory> outputProtocolFactory)
|
|
||||||
{
|
|
||||||
outputProtocolFactory_ = outputProtocolFactory;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setServerEventHandler(boost::shared_ptr<TServerEventHandler> eventHandler)
|
|
||||||
{
|
|
||||||
eventHandler_ = eventHandler;
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Helper function to increase the max file descriptors limit
|
|
||||||
* for the current process and all of its children.
|
|
||||||
* By default, tries to increase it to as much as 2^24.
|
|
||||||
*/
|
|
||||||
int increase_max_fds(int max_fds = (1 << 24));
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} // apache::thrift::server
|
|
||||||
|
|
||||||
@@ -1,240 +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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <thrift/server/TSimpleServer.h>
|
|
||||||
#include <thrift/transport/TTransportException.h>
|
|
||||||
#include <string>
|
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
namespace apache
|
|
||||||
{
|
|
||||||
namespace thrift
|
|
||||||
{
|
|
||||||
namespace server
|
|
||||||
{
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
using namespace apache::thrift;
|
|
||||||
using namespace apache::thrift::protocol;
|
|
||||||
using namespace apache::thrift::transport;
|
|
||||||
using boost::shared_ptr;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A simple single-threaded application server. Perfect for unit tests!
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
void TSimpleServer::serve()
|
|
||||||
{
|
|
||||||
|
|
||||||
shared_ptr<TTransport> client;
|
|
||||||
shared_ptr<TTransport> inputTransport;
|
|
||||||
shared_ptr<TTransport> outputTransport;
|
|
||||||
shared_ptr<TProtocol> inputProtocol;
|
|
||||||
shared_ptr<TProtocol> outputProtocol;
|
|
||||||
|
|
||||||
// Start the server listening
|
|
||||||
serverTransport_->listen();
|
|
||||||
|
|
||||||
// Run the preServe event
|
|
||||||
if (eventHandler_)
|
|
||||||
{
|
|
||||||
eventHandler_->preServe();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fetch client from server
|
|
||||||
while (!stop_)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
client = serverTransport_->accept();
|
|
||||||
inputTransport = inputTransportFactory_->getTransport(client);
|
|
||||||
outputTransport = outputTransportFactory_->getTransport(client);
|
|
||||||
inputProtocol = inputProtocolFactory_->getProtocol(inputTransport);
|
|
||||||
outputProtocol = outputProtocolFactory_->getProtocol(outputTransport);
|
|
||||||
}
|
|
||||||
catch (TTransportException& ttx)
|
|
||||||
{
|
|
||||||
if (inputTransport)
|
|
||||||
{
|
|
||||||
inputTransport->close();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (outputTransport)
|
|
||||||
{
|
|
||||||
outputTransport->close();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (client)
|
|
||||||
{
|
|
||||||
client->close();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!stop_ || ttx.getType() != TTransportException::INTERRUPTED)
|
|
||||||
{
|
|
||||||
string errStr = string("TServerTransport died on accept: ") + ttx.what();
|
|
||||||
GlobalOutput(errStr.c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
catch (TException& tx)
|
|
||||||
{
|
|
||||||
if (inputTransport)
|
|
||||||
{
|
|
||||||
inputTransport->close();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (outputTransport)
|
|
||||||
{
|
|
||||||
outputTransport->close();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (client)
|
|
||||||
{
|
|
||||||
client->close();
|
|
||||||
}
|
|
||||||
|
|
||||||
string errStr = string("Some kind of accept exception: ") + tx.what();
|
|
||||||
GlobalOutput(errStr.c_str());
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
catch (string s)
|
|
||||||
{
|
|
||||||
if (inputTransport)
|
|
||||||
{
|
|
||||||
inputTransport->close();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (outputTransport)
|
|
||||||
{
|
|
||||||
outputTransport->close();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (client)
|
|
||||||
{
|
|
||||||
client->close();
|
|
||||||
}
|
|
||||||
|
|
||||||
string errStr = string("Some kind of accept exception: ") + s;
|
|
||||||
GlobalOutput(errStr.c_str());
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the processor
|
|
||||||
shared_ptr<TProcessor> processor = getProcessor(inputProtocol,
|
|
||||||
outputProtocol, client);
|
|
||||||
|
|
||||||
void* connectionContext = NULL;
|
|
||||||
|
|
||||||
if (eventHandler_)
|
|
||||||
{
|
|
||||||
connectionContext = eventHandler_->createContext(inputProtocol, outputProtocol);
|
|
||||||
}
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
for (;;)
|
|
||||||
{
|
|
||||||
if (eventHandler_)
|
|
||||||
{
|
|
||||||
eventHandler_->processContext(connectionContext, client);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!processor->process(inputProtocol, outputProtocol,
|
|
||||||
connectionContext) ||
|
|
||||||
// Peek ahead, is the remote side closed?
|
|
||||||
!inputProtocol->getTransport()->peek())
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (const TTransportException& ttx)
|
|
||||||
{
|
|
||||||
string errStr = string("TSimpleServer client died: ") + ttx.what();
|
|
||||||
GlobalOutput(errStr.c_str());
|
|
||||||
}
|
|
||||||
catch (const std::exception& x)
|
|
||||||
{
|
|
||||||
GlobalOutput.printf("TSimpleServer exception: %s: %s",
|
|
||||||
typeid(x).name(), x.what());
|
|
||||||
}
|
|
||||||
catch (...)
|
|
||||||
{
|
|
||||||
GlobalOutput("TSimpleServer uncaught exception.");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (eventHandler_)
|
|
||||||
{
|
|
||||||
eventHandler_->deleteContext(connectionContext, inputProtocol, outputProtocol);
|
|
||||||
}
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
inputTransport->close();
|
|
||||||
}
|
|
||||||
catch (const TTransportException& ttx)
|
|
||||||
{
|
|
||||||
string errStr = string("TSimpleServer input close failed: ")
|
|
||||||
+ ttx.what();
|
|
||||||
GlobalOutput(errStr.c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
outputTransport->close();
|
|
||||||
}
|
|
||||||
catch (const TTransportException& ttx)
|
|
||||||
{
|
|
||||||
string errStr = string("TSimpleServer output close failed: ")
|
|
||||||
+ ttx.what();
|
|
||||||
GlobalOutput(errStr.c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
client->close();
|
|
||||||
}
|
|
||||||
catch (const TTransportException& ttx)
|
|
||||||
{
|
|
||||||
string errStr = string("TSimpleServer client close failed: ")
|
|
||||||
+ ttx.what();
|
|
||||||
GlobalOutput(errStr.c_str());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (stop_)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
serverTransport_->close();
|
|
||||||
}
|
|
||||||
catch (TTransportException& ttx)
|
|
||||||
{
|
|
||||||
string errStr = string("TServerTransport failed on close: ") + ttx.what();
|
|
||||||
GlobalOutput(errStr.c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
stop_ = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} // apache::thrift::server
|
|
||||||
@@ -1,109 +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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <thrift/server/TServer.h>
|
|
||||||
#include <thrift/transport/TServerTransport.h>
|
|
||||||
|
|
||||||
namespace apache
|
|
||||||
{
|
|
||||||
namespace thrift
|
|
||||||
{
|
|
||||||
namespace server
|
|
||||||
{
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This is the most basic simple server. It is single-threaded and runs a
|
|
||||||
* continuous loop of accepting a single connection, processing requests on
|
|
||||||
* that connection until it closes, and then repeating. It is a good example
|
|
||||||
* of how to extend the TServer interface.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
class TSimpleServer : public TServer
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
template<typename ProcessorFactory>
|
|
||||||
TSimpleServer(
|
|
||||||
const boost::shared_ptr<ProcessorFactory>& processorFactory,
|
|
||||||
const boost::shared_ptr<TServerTransport>& serverTransport,
|
|
||||||
const boost::shared_ptr<TTransportFactory>& transportFactory,
|
|
||||||
const boost::shared_ptr<TProtocolFactory>& protocolFactory,
|
|
||||||
THRIFT_OVERLOAD_IF(ProcessorFactory, TProcessorFactory)) :
|
|
||||||
TServer(processorFactory, serverTransport, transportFactory,
|
|
||||||
protocolFactory),
|
|
||||||
stop_(false) {}
|
|
||||||
|
|
||||||
template<typename Processor>
|
|
||||||
TSimpleServer(
|
|
||||||
const boost::shared_ptr<Processor>& processor,
|
|
||||||
const boost::shared_ptr<TServerTransport>& serverTransport,
|
|
||||||
const boost::shared_ptr<TTransportFactory>& transportFactory,
|
|
||||||
const boost::shared_ptr<TProtocolFactory>& protocolFactory,
|
|
||||||
THRIFT_OVERLOAD_IF(Processor, TProcessor)) :
|
|
||||||
TServer(processor, serverTransport, transportFactory, protocolFactory),
|
|
||||||
stop_(false) {}
|
|
||||||
|
|
||||||
template<typename ProcessorFactory>
|
|
||||||
TSimpleServer(
|
|
||||||
const boost::shared_ptr<ProcessorFactory>& 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,
|
|
||||||
THRIFT_OVERLOAD_IF(ProcessorFactory, TProcessorFactory)) :
|
|
||||||
TServer(processorFactory, serverTransport,
|
|
||||||
inputTransportFactory, outputTransportFactory,
|
|
||||||
inputProtocolFactory, outputProtocolFactory),
|
|
||||||
stop_(false) {}
|
|
||||||
|
|
||||||
template<typename Processor>
|
|
||||||
TSimpleServer(
|
|
||||||
const boost::shared_ptr<Processor>& 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,
|
|
||||||
THRIFT_OVERLOAD_IF(Processor, TProcessor)) :
|
|
||||||
TServer(processor, serverTransport,
|
|
||||||
inputTransportFactory, outputTransportFactory,
|
|
||||||
inputProtocolFactory, outputProtocolFactory),
|
|
||||||
stop_(false) {}
|
|
||||||
|
|
||||||
~TSimpleServer() {}
|
|
||||||
|
|
||||||
void serve();
|
|
||||||
|
|
||||||
void stop()
|
|
||||||
{
|
|
||||||
stop_ = true;
|
|
||||||
serverTransport_->interrupt();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
bool stop_;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} // apache::thrift::server
|
|
||||||
|
|
||||||
@@ -1,143 +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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <thrift/concurrency/ThreadManager.h>
|
|
||||||
#include <thrift/server/TServer.h>
|
|
||||||
#include <thrift/transport/TServerTransport.h>
|
|
||||||
|
|
||||||
#include <boost/shared_ptr.hpp>
|
|
||||||
|
|
||||||
namespace apache
|
|
||||||
{
|
|
||||||
namespace thrift
|
|
||||||
{
|
|
||||||
namespace server
|
|
||||||
{
|
|
||||||
|
|
||||||
using apache::thrift::concurrency::ThreadManager;
|
|
||||||
using apache::thrift::protocol::TProtocolFactory;
|
|
||||||
using apache::thrift::transport::TServerTransport;
|
|
||||||
using apache::thrift::transport::TTransportFactory;
|
|
||||||
|
|
||||||
class TThreadPoolServer : public TServer
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
class Task;
|
|
||||||
|
|
||||||
template<typename ProcessorFactory>
|
|
||||||
TThreadPoolServer(
|
|
||||||
const boost::shared_ptr<ProcessorFactory>& processorFactory,
|
|
||||||
const boost::shared_ptr<TServerTransport>& serverTransport,
|
|
||||||
const boost::shared_ptr<TTransportFactory>& transportFactory,
|
|
||||||
const boost::shared_ptr<TProtocolFactory>& protocolFactory,
|
|
||||||
const boost::shared_ptr<ThreadManager>& threadManager,
|
|
||||||
THRIFT_OVERLOAD_IF(ProcessorFactory, TProcessorFactory)) :
|
|
||||||
TServer(processorFactory, serverTransport, transportFactory,
|
|
||||||
protocolFactory),
|
|
||||||
threadManager_(threadManager),
|
|
||||||
stop_(false),
|
|
||||||
timeout_(0),
|
|
||||||
taskExpiration_(0) {}
|
|
||||||
|
|
||||||
template<typename Processor>
|
|
||||||
TThreadPoolServer(
|
|
||||||
const boost::shared_ptr<Processor>& processor,
|
|
||||||
const boost::shared_ptr<TServerTransport>& serverTransport,
|
|
||||||
const boost::shared_ptr<TTransportFactory>& transportFactory,
|
|
||||||
const boost::shared_ptr<TProtocolFactory>& protocolFactory,
|
|
||||||
const boost::shared_ptr<ThreadManager>& threadManager,
|
|
||||||
THRIFT_OVERLOAD_IF(Processor, TProcessor)) :
|
|
||||||
TServer(processor, serverTransport, transportFactory, protocolFactory),
|
|
||||||
threadManager_(threadManager),
|
|
||||||
stop_(false),
|
|
||||||
timeout_(0),
|
|
||||||
taskExpiration_(0) {}
|
|
||||||
|
|
||||||
template<typename ProcessorFactory>
|
|
||||||
TThreadPoolServer(
|
|
||||||
const boost::shared_ptr<ProcessorFactory>& 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,
|
|
||||||
const boost::shared_ptr<ThreadManager>& threadManager,
|
|
||||||
THRIFT_OVERLOAD_IF(ProcessorFactory, TProcessorFactory)) :
|
|
||||||
TServer(processorFactory, serverTransport,
|
|
||||||
inputTransportFactory, outputTransportFactory,
|
|
||||||
inputProtocolFactory, outputProtocolFactory),
|
|
||||||
threadManager_(threadManager),
|
|
||||||
stop_(false),
|
|
||||||
timeout_(0),
|
|
||||||
taskExpiration_(0) {}
|
|
||||||
|
|
||||||
template<typename Processor>
|
|
||||||
TThreadPoolServer(
|
|
||||||
const boost::shared_ptr<Processor>& 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,
|
|
||||||
const boost::shared_ptr<ThreadManager>& threadManager,
|
|
||||||
THRIFT_OVERLOAD_IF(Processor, TProcessor)) :
|
|
||||||
TServer(processor, serverTransport,
|
|
||||||
inputTransportFactory, outputTransportFactory,
|
|
||||||
inputProtocolFactory, outputProtocolFactory),
|
|
||||||
threadManager_(threadManager),
|
|
||||||
stop_(false),
|
|
||||||
timeout_(0),
|
|
||||||
taskExpiration_(0) {}
|
|
||||||
|
|
||||||
virtual ~TThreadPoolServer();
|
|
||||||
|
|
||||||
virtual void serve();
|
|
||||||
|
|
||||||
virtual int64_t getTimeout() const;
|
|
||||||
|
|
||||||
virtual void setTimeout(int64_t value);
|
|
||||||
|
|
||||||
virtual void stop()
|
|
||||||
{
|
|
||||||
stop_ = true;
|
|
||||||
serverTransport_->interrupt();
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual int64_t getTaskExpiration() const;
|
|
||||||
|
|
||||||
virtual void setTaskExpiration(int64_t value);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
|
|
||||||
boost::shared_ptr<ThreadManager> threadManager_;
|
|
||||||
|
|
||||||
volatile bool stop_;
|
|
||||||
|
|
||||||
volatile int64_t timeout_;
|
|
||||||
|
|
||||||
volatile int64_t taskExpiration_;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} // apache::thrift::server
|
|
||||||
|
|
||||||
@@ -1,156 +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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <thrift/server/TServer.h>
|
|
||||||
#include <thrift/transport/TServerTransport.h>
|
|
||||||
#include <thrift/concurrency/Monitor.h>
|
|
||||||
#include <thrift/concurrency/Thread.h>
|
|
||||||
|
|
||||||
#include <boost/shared_ptr.hpp>
|
|
||||||
|
|
||||||
namespace apache
|
|
||||||
{
|
|
||||||
namespace thrift
|
|
||||||
{
|
|
||||||
namespace server
|
|
||||||
{
|
|
||||||
|
|
||||||
using apache::thrift::TProcessor;
|
|
||||||
using apache::thrift::transport::TServerTransport;
|
|
||||||
using apache::thrift::transport::TTransportFactory;
|
|
||||||
using apache::thrift::concurrency::Monitor;
|
|
||||||
using apache::thrift::concurrency::ThreadFactory;
|
|
||||||
|
|
||||||
class TThreadedServer : public TServer
|
|
||||||
{
|
|
||||||
|
|
||||||
public:
|
|
||||||
class Task;
|
|
||||||
|
|
||||||
template<typename ProcessorFactory>
|
|
||||||
TThreadedServer(const boost::shared_ptr<ProcessorFactory>& processorFactory,
|
|
||||||
const boost::shared_ptr<TServerTransport>& serverTransport,
|
|
||||||
const boost::shared_ptr<TTransportFactory>& transportFactory,
|
|
||||||
const boost::shared_ptr<TProtocolFactory>& protocolFactory,
|
|
||||||
THRIFT_OVERLOAD_IF(ProcessorFactory, TProcessorFactory));
|
|
||||||
|
|
||||||
template<typename ProcessorFactory>
|
|
||||||
TThreadedServer(const boost::shared_ptr<ProcessorFactory>& processorFactory,
|
|
||||||
const boost::shared_ptr<TServerTransport>& serverTransport,
|
|
||||||
const boost::shared_ptr<TTransportFactory>& transportFactory,
|
|
||||||
const boost::shared_ptr<TProtocolFactory>& protocolFactory,
|
|
||||||
const boost::shared_ptr<ThreadFactory>& threadFactory,
|
|
||||||
THRIFT_OVERLOAD_IF(ProcessorFactory, TProcessorFactory));
|
|
||||||
|
|
||||||
template<typename Processor>
|
|
||||||
TThreadedServer(const boost::shared_ptr<Processor>& processor,
|
|
||||||
const boost::shared_ptr<TServerTransport>& serverTransport,
|
|
||||||
const boost::shared_ptr<TTransportFactory>& transportFactory,
|
|
||||||
const boost::shared_ptr<TProtocolFactory>& protocolFactory,
|
|
||||||
THRIFT_OVERLOAD_IF(Processor, TProcessor));
|
|
||||||
|
|
||||||
template<typename Processor>
|
|
||||||
TThreadedServer(const boost::shared_ptr<Processor>& processor,
|
|
||||||
const boost::shared_ptr<TServerTransport>& serverTransport,
|
|
||||||
const boost::shared_ptr<TTransportFactory>& transportFactory,
|
|
||||||
const boost::shared_ptr<TProtocolFactory>& protocolFactory,
|
|
||||||
const boost::shared_ptr<ThreadFactory>& threadFactory,
|
|
||||||
THRIFT_OVERLOAD_IF(Processor, TProcessor));
|
|
||||||
|
|
||||||
virtual ~TThreadedServer();
|
|
||||||
|
|
||||||
virtual void serve();
|
|
||||||
|
|
||||||
void stop()
|
|
||||||
{
|
|
||||||
stop_ = true;
|
|
||||||
serverTransport_->interrupt();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
void init();
|
|
||||||
|
|
||||||
boost::shared_ptr<ThreadFactory> threadFactory_;
|
|
||||||
volatile bool stop_;
|
|
||||||
|
|
||||||
Monitor tasksMonitor_;
|
|
||||||
std::set<Task*> tasks_;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename ProcessorFactory>
|
|
||||||
TThreadedServer::TThreadedServer(
|
|
||||||
const boost::shared_ptr<ProcessorFactory>& processorFactory,
|
|
||||||
const boost::shared_ptr<TServerTransport>& serverTransport,
|
|
||||||
const boost::shared_ptr<TTransportFactory>& transportFactory,
|
|
||||||
const boost::shared_ptr<TProtocolFactory>& protocolFactory,
|
|
||||||
THRIFT_OVERLOAD_IF_DEFN(ProcessorFactory, TProcessorFactory)) :
|
|
||||||
TServer(processorFactory, serverTransport, transportFactory,
|
|
||||||
protocolFactory)
|
|
||||||
{
|
|
||||||
init();
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename ProcessorFactory>
|
|
||||||
TThreadedServer::TThreadedServer(
|
|
||||||
const boost::shared_ptr<ProcessorFactory>& processorFactory,
|
|
||||||
const boost::shared_ptr<TServerTransport>& serverTransport,
|
|
||||||
const boost::shared_ptr<TTransportFactory>& transportFactory,
|
|
||||||
const boost::shared_ptr<TProtocolFactory>& protocolFactory,
|
|
||||||
const boost::shared_ptr<ThreadFactory>& threadFactory,
|
|
||||||
THRIFT_OVERLOAD_IF_DEFN(ProcessorFactory, TProcessorFactory)) :
|
|
||||||
TServer(processorFactory, serverTransport, transportFactory,
|
|
||||||
protocolFactory),
|
|
||||||
threadFactory_(threadFactory)
|
|
||||||
{
|
|
||||||
init();
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename Processor>
|
|
||||||
TThreadedServer::TThreadedServer(
|
|
||||||
const boost::shared_ptr<Processor>& processor,
|
|
||||||
const boost::shared_ptr<TServerTransport>& serverTransport,
|
|
||||||
const boost::shared_ptr<TTransportFactory>& transportFactory,
|
|
||||||
const boost::shared_ptr<TProtocolFactory>& protocolFactory,
|
|
||||||
THRIFT_OVERLOAD_IF_DEFN(Processor, TProcessor)) :
|
|
||||||
TServer(processor, serverTransport, transportFactory, protocolFactory)
|
|
||||||
{
|
|
||||||
init();
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename Processor>
|
|
||||||
TThreadedServer::TThreadedServer(
|
|
||||||
const boost::shared_ptr<Processor>& processor,
|
|
||||||
const boost::shared_ptr<TServerTransport>& serverTransport,
|
|
||||||
const boost::shared_ptr<TTransportFactory>& transportFactory,
|
|
||||||
const boost::shared_ptr<TProtocolFactory>& protocolFactory,
|
|
||||||
const boost::shared_ptr<ThreadFactory>& threadFactory,
|
|
||||||
THRIFT_OVERLOAD_IF_DEFN(Processor, TProcessor)) :
|
|
||||||
TServer(processor, serverTransport, transportFactory, protocolFactory),
|
|
||||||
threadFactory_(threadFactory)
|
|
||||||
{
|
|
||||||
init();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} // apache::thrift::server
|
|
||||||
|
|
||||||
@@ -1,425 +0,0 @@
|
|||||||
/* lib/cpp/src/thrift/config.h. Generated from config.hin by configure. */
|
|
||||||
/* config.hin. Generated from configure.ac by autoheader. */
|
|
||||||
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
|
|
||||||
/* Define if the AI_ADDRCONFIG symbol is unavailable */
|
|
||||||
/* #undef AI_ADDRCONFIG */
|
|
||||||
|
|
||||||
/* Possible value for SIGNED_RIGHT_SHIFT_IS */
|
|
||||||
#define ARITHMETIC_RIGHT_SHIFT 1
|
|
||||||
|
|
||||||
/* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP
|
|
||||||
systems. This function is required for `alloca.c' support on those systems.
|
|
||||||
*/
|
|
||||||
/* #undef CRAY_STACKSEG_END */
|
|
||||||
|
|
||||||
/* Define to 1 if using `alloca.c'. */
|
|
||||||
/* #undef C_ALLOCA */
|
|
||||||
|
|
||||||
/* Define to 1 if you have the `alarm' function. */
|
|
||||||
#define HAVE_ALARM 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have `alloca', as a function or macro. */
|
|
||||||
#define HAVE_ALLOCA 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have <alloca.h> and it should be used (not on Ultrix).
|
|
||||||
*/
|
|
||||||
#define HAVE_ALLOCA_H 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <arpa/inet.h> header file. */
|
|
||||||
#define HAVE_ARPA_INET_H 1
|
|
||||||
|
|
||||||
/* define if the Boost library is available */
|
|
||||||
#define HAVE_BOOST /**/
|
|
||||||
|
|
||||||
/* Define to 1 if you have the `bzero' function. */
|
|
||||||
#define HAVE_BZERO 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the `clock_gettime' function. */
|
|
||||||
#define HAVE_CLOCK_GETTIME 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the declaration of `strerror_r', and to 0 if you
|
|
||||||
don't. */
|
|
||||||
#define HAVE_DECL_STRERROR_R 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <dlfcn.h> header file. */
|
|
||||||
#define HAVE_DLFCN_H 1
|
|
||||||
|
|
||||||
/* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */
|
|
||||||
/* #undef HAVE_DOPRNT */
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <fcntl.h> header file. */
|
|
||||||
#define HAVE_FCNTL_H 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the `fork' function. */
|
|
||||||
#define HAVE_FORK 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the `ftruncate' function. */
|
|
||||||
#define HAVE_FTRUNCATE 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the `gethostbyname' function. */
|
|
||||||
#define HAVE_GETHOSTBYNAME 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the `gettimeofday' function. */
|
|
||||||
#define HAVE_GETTIMEOFDAY 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <inttypes.h> header file. */
|
|
||||||
#define HAVE_INTTYPES_H 1
|
|
||||||
|
|
||||||
/* define if libevent is available */
|
|
||||||
/* #undef HAVE_LIBEVENT */
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <libintl.h> header file. */
|
|
||||||
#define HAVE_LIBINTL_H 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the `pthread' library (-lpthread). */
|
|
||||||
#define HAVE_LIBPTHREAD 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the `rt' library (-lrt). */
|
|
||||||
#define HAVE_LIBRT 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the `socket' library (-lsocket). */
|
|
||||||
/* #undef HAVE_LIBSOCKET */
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <limits.h> header file. */
|
|
||||||
#define HAVE_LIMITS_H 1
|
|
||||||
|
|
||||||
/* Define to 1 if your system has a GNU libc compatible `malloc' function, and
|
|
||||||
to 0 otherwise. */
|
|
||||||
#define HAVE_MALLOC 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <malloc.h> header file. */
|
|
||||||
#define HAVE_MALLOC_H 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the `memmove' function. */
|
|
||||||
#define HAVE_MEMMOVE 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <memory.h> header file. */
|
|
||||||
#define HAVE_MEMORY_H 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the `memset' function. */
|
|
||||||
#define HAVE_MEMSET 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the `mkdir' function. */
|
|
||||||
#define HAVE_MKDIR 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <netdb.h> header file. */
|
|
||||||
#define HAVE_NETDB_H 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <netinet/in.h> header file. */
|
|
||||||
#define HAVE_NETINET_IN_H 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <openssl/rand.h> header file. */
|
|
||||||
#define HAVE_OPENSSL_RAND_H 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <openssl/ssl.h> header file. */
|
|
||||||
#define HAVE_OPENSSL_SSL_H 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <openssl/x509v3.h> header file. */
|
|
||||||
#define HAVE_OPENSSL_X509V3_H 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <pthread.h> header file. */
|
|
||||||
#define HAVE_PTHREAD_H 1
|
|
||||||
|
|
||||||
/* Define to 1 if the system has the type `ptrdiff_t'. */
|
|
||||||
#define HAVE_PTRDIFF_T 1
|
|
||||||
|
|
||||||
/* Define to 1 if your system has a GNU libc compatible `realloc' function,
|
|
||||||
and to 0 otherwise. */
|
|
||||||
#define HAVE_REALLOC 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the `realpath' function. */
|
|
||||||
#define HAVE_REALPATH 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the `sched_get_priority_max' function. */
|
|
||||||
#define HAVE_SCHED_GET_PRIORITY_MAX 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the `sched_get_priority_min' function. */
|
|
||||||
#define HAVE_SCHED_GET_PRIORITY_MIN 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <sched.h> header file. */
|
|
||||||
#define HAVE_SCHED_H 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the `select' function. */
|
|
||||||
#define HAVE_SELECT 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the `socket' function. */
|
|
||||||
#define HAVE_SOCKET 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the `sqrt' function. */
|
|
||||||
#define HAVE_SQRT 1
|
|
||||||
|
|
||||||
/* Define to 1 if `stat' has the bug that it succeeds when given the
|
|
||||||
zero-length file name argument. */
|
|
||||||
/* #undef HAVE_STAT_EMPTY_STRING_BUG */
|
|
||||||
|
|
||||||
/* Define to 1 if stdbool.h conforms to C99. */
|
|
||||||
#define HAVE_STDBOOL_H 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <stddef.h> header file. */
|
|
||||||
#define HAVE_STDDEF_H 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <stdint.h> header file. */
|
|
||||||
#define HAVE_STDINT_H 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <stdlib.h> header file. */
|
|
||||||
#define HAVE_STDLIB_H 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the `strchr' function. */
|
|
||||||
#define HAVE_STRCHR 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the `strdup' function. */
|
|
||||||
#define HAVE_STRDUP 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the `strerror' function. */
|
|
||||||
#define HAVE_STRERROR 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the `strerror_r' function. */
|
|
||||||
#define HAVE_STRERROR_R 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the `strftime' function. */
|
|
||||||
#define HAVE_STRFTIME 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <strings.h> header file. */
|
|
||||||
#define HAVE_STRINGS_H 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <string.h> header file. */
|
|
||||||
#define HAVE_STRING_H 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the `strstr' function. */
|
|
||||||
#define HAVE_STRSTR 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the `strtol' function. */
|
|
||||||
#define HAVE_STRTOL 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the `strtoul' function. */
|
|
||||||
#define HAVE_STRTOUL 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <sys/param.h> header file. */
|
|
||||||
#define HAVE_SYS_PARAM_H 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <sys/poll.h> header file. */
|
|
||||||
#define HAVE_SYS_POLL_H 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <sys/resource.h> header file. */
|
|
||||||
#define HAVE_SYS_RESOURCE_H 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <sys/select.h> header file. */
|
|
||||||
#define HAVE_SYS_SELECT_H 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <sys/socket.h> header file. */
|
|
||||||
#define HAVE_SYS_SOCKET_H 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <sys/stat.h> header file. */
|
|
||||||
#define HAVE_SYS_STAT_H 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <sys/time.h> header file. */
|
|
||||||
#define HAVE_SYS_TIME_H 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <sys/types.h> header file. */
|
|
||||||
#define HAVE_SYS_TYPES_H 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <sys/un.h> header file. */
|
|
||||||
#define HAVE_SYS_UN_H 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have <sys/wait.h> that is POSIX.1 compatible. */
|
|
||||||
#define HAVE_SYS_WAIT_H 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <unistd.h> header file. */
|
|
||||||
#define HAVE_UNISTD_H 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the `vfork' function. */
|
|
||||||
#define HAVE_VFORK 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <vfork.h> header file. */
|
|
||||||
/* #undef HAVE_VFORK_H */
|
|
||||||
|
|
||||||
/* Define to 1 if you have the `vprintf' function. */
|
|
||||||
#define HAVE_VPRINTF 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <wchar.h> header file. */
|
|
||||||
#define HAVE_WCHAR_H 1
|
|
||||||
|
|
||||||
/* Define to 1 if `fork' works. */
|
|
||||||
#define HAVE_WORKING_FORK 1
|
|
||||||
|
|
||||||
/* Define to 1 if `vfork' works. */
|
|
||||||
#define HAVE_WORKING_VFORK 1
|
|
||||||
|
|
||||||
/* define if zlib is available */
|
|
||||||
#define HAVE_ZLIB /**/
|
|
||||||
|
|
||||||
/* Define to 1 if the system has the type `_Bool'. */
|
|
||||||
/* #undef HAVE__BOOL */
|
|
||||||
|
|
||||||
/* Possible value for SIGNED_RIGHT_SHIFT_IS */
|
|
||||||
#define LOGICAL_RIGHT_SHIFT 2
|
|
||||||
|
|
||||||
/* Define to 1 if `lstat' dereferences a symlink specified with a trailing
|
|
||||||
slash. */
|
|
||||||
#define LSTAT_FOLLOWS_SLASHED_SYMLINK 1
|
|
||||||
|
|
||||||
/* Define to the sub-directory in which libtool stores uninstalled libraries.
|
|
||||||
*/
|
|
||||||
#define LT_OBJDIR ".libs/"
|
|
||||||
|
|
||||||
/* Name of package */
|
|
||||||
#define PACKAGE "thrift"
|
|
||||||
|
|
||||||
/* Define to the address where bug reports for this package should be sent. */
|
|
||||||
#define PACKAGE_BUGREPORT ""
|
|
||||||
|
|
||||||
/* Define to the full name of this package. */
|
|
||||||
#define PACKAGE_NAME "thrift"
|
|
||||||
|
|
||||||
/* Define to the full name and version of this package. */
|
|
||||||
#define PACKAGE_STRING "thrift 0.9.1"
|
|
||||||
|
|
||||||
/* Define to the one symbol short name of this package. */
|
|
||||||
#define PACKAGE_TARNAME "thrift"
|
|
||||||
|
|
||||||
/* Define to the home page for this package. */
|
|
||||||
#define PACKAGE_URL ""
|
|
||||||
|
|
||||||
/* Define to the version of this package. */
|
|
||||||
#define PACKAGE_VERSION "0.9.1"
|
|
||||||
|
|
||||||
/* Define as the return type of signal handlers (`int' or `void'). */
|
|
||||||
#define RETSIGTYPE void
|
|
||||||
|
|
||||||
/* Define to the type of arg 1 for `select'. */
|
|
||||||
#define SELECT_TYPE_ARG1 int
|
|
||||||
|
|
||||||
/* Define to the type of args 2, 3 and 4 for `select'. */
|
|
||||||
#define SELECT_TYPE_ARG234 (fd_set *)
|
|
||||||
|
|
||||||
/* Define to the type of arg 5 for `select'. */
|
|
||||||
#define SELECT_TYPE_ARG5 (struct timeval *)
|
|
||||||
|
|
||||||
/* Indicates the effect of the right shift operator on negative signed
|
|
||||||
integers */
|
|
||||||
#define SIGNED_RIGHT_SHIFT_IS 1
|
|
||||||
|
|
||||||
/* If using the C implementation of alloca, define if you know the
|
|
||||||
direction of stack growth for your system; otherwise it will be
|
|
||||||
automatically deduced at runtime.
|
|
||||||
STACK_DIRECTION > 0 => grows toward higher addresses
|
|
||||||
STACK_DIRECTION < 0 => grows toward lower addresses
|
|
||||||
STACK_DIRECTION = 0 => direction of growth unknown */
|
|
||||||
/* #undef STACK_DIRECTION */
|
|
||||||
|
|
||||||
/* Define to 1 if you have the ANSI C header files. */
|
|
||||||
#define STDC_HEADERS 1
|
|
||||||
|
|
||||||
/* Define to 1 if strerror_r returns char *. */
|
|
||||||
#define STRERROR_R_CHAR_P 1
|
|
||||||
|
|
||||||
/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */
|
|
||||||
#define TIME_WITH_SYS_TIME 1
|
|
||||||
|
|
||||||
/* Define to 1 if your <sys/time.h> declares `struct tm'. */
|
|
||||||
/* #undef TM_IN_SYS_TIME */
|
|
||||||
|
|
||||||
/* Possible value for SIGNED_RIGHT_SHIFT_IS */
|
|
||||||
#define UNKNOWN_RIGHT_SHIFT 3
|
|
||||||
|
|
||||||
/* experimental --enable-boostthreads that replaces POSIX pthread by
|
|
||||||
boost::thread */
|
|
||||||
/* #undef USE_BOOST_THREAD */
|
|
||||||
|
|
||||||
/* Version number of package */
|
|
||||||
#define VERSION "0.9.1"
|
|
||||||
|
|
||||||
/* Define to 1 if `lex' declares `yytext' as a `char *' by default, not a
|
|
||||||
`char[]'. */
|
|
||||||
#define YYTEXT_POINTER 1
|
|
||||||
|
|
||||||
/* Define for Solaris 2.5.1 so the uint32_t typedef from <sys/synch.h>,
|
|
||||||
<pthread.h>, or <semaphore.h> is not used. If the typedef were allowed, the
|
|
||||||
#define below would cause a syntax error. */
|
|
||||||
/* #undef _UINT32_T */
|
|
||||||
|
|
||||||
/* Define for Solaris 2.5.1 so the uint64_t typedef from <sys/synch.h>,
|
|
||||||
<pthread.h>, or <semaphore.h> is not used. If the typedef were allowed, the
|
|
||||||
#define below would cause a syntax error. */
|
|
||||||
/* #undef _UINT64_T */
|
|
||||||
|
|
||||||
/* Define for Solaris 2.5.1 so the uint8_t typedef from <sys/synch.h>,
|
|
||||||
<pthread.h>, or <semaphore.h> is not used. If the typedef were allowed, the
|
|
||||||
#define below would cause a syntax error. */
|
|
||||||
/* #undef _UINT8_T */
|
|
||||||
|
|
||||||
/* Define to empty if `const' does not conform to ANSI C. */
|
|
||||||
/* #undef const */
|
|
||||||
|
|
||||||
/* Define to `__inline__' or `__inline' if that's what the C compiler
|
|
||||||
calls it, or to nothing if 'inline' is not supported under any name. */
|
|
||||||
#ifndef __cplusplus
|
|
||||||
/* #undef inline */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Define to the type of a signed integer type of width exactly 16 bits if
|
|
||||||
such a type exists and the standard includes do not define it. */
|
|
||||||
/* #undef int16_t */
|
|
||||||
|
|
||||||
/* Define to the type of a signed integer type of width exactly 32 bits if
|
|
||||||
such a type exists and the standard includes do not define it. */
|
|
||||||
/* #undef int32_t */
|
|
||||||
|
|
||||||
/* Define to the type of a signed integer type of width exactly 64 bits if
|
|
||||||
such a type exists and the standard includes do not define it. */
|
|
||||||
/* #undef int64_t */
|
|
||||||
|
|
||||||
/* Define to the type of a signed integer type of width exactly 8 bits if such
|
|
||||||
a type exists and the standard includes do not define it. */
|
|
||||||
/* #undef int8_t */
|
|
||||||
|
|
||||||
/* Define to rpl_malloc if the replacement function should be used. */
|
|
||||||
/* #undef malloc */
|
|
||||||
|
|
||||||
/* Define to `int' if <sys/types.h> does not define. */
|
|
||||||
/* #undef mode_t */
|
|
||||||
|
|
||||||
/* Define to `long int' if <sys/types.h> does not define. */
|
|
||||||
/* #undef off_t */
|
|
||||||
|
|
||||||
/* Define to `int' if <sys/types.h> does not define. */
|
|
||||||
/* #undef pid_t */
|
|
||||||
|
|
||||||
/* Define to rpl_realloc if the replacement function should be used. */
|
|
||||||
/* #undef realloc */
|
|
||||||
|
|
||||||
/* Define to `unsigned int' if <sys/types.h> does not define. */
|
|
||||||
/* #undef size_t */
|
|
||||||
|
|
||||||
/* Define to `int' if <sys/types.h> does not define. */
|
|
||||||
/* #undef ssize_t */
|
|
||||||
|
|
||||||
/* Define to the type of an unsigned integer type of width exactly 16 bits if
|
|
||||||
such a type exists and the standard includes do not define it. */
|
|
||||||
/* #undef uint16_t */
|
|
||||||
|
|
||||||
/* Define to the type of an unsigned integer type of width exactly 32 bits if
|
|
||||||
such a type exists and the standard includes do not define it. */
|
|
||||||
/* #undef uint32_t */
|
|
||||||
|
|
||||||
/* Define to the type of an unsigned integer type of width exactly 64 bits if
|
|
||||||
such a type exists and the standard includes do not define it. */
|
|
||||||
/* #undef uint64_t */
|
|
||||||
|
|
||||||
/* Define to the type of an unsigned integer type of width exactly 8 bits if
|
|
||||||
such a type exists and the standard includes do not define it. */
|
|
||||||
/* #undef uint8_t */
|
|
||||||
|
|
||||||
/* Define as `fork' if `vfork' does not work. */
|
|
||||||
/* #undef vfork */
|
|
||||||
|
|
||||||
/* Define to empty if the keyword `volatile' does not work. Warning: valid
|
|
||||||
code using `volatile' can become incorrect without. Disable with care. */
|
|
||||||
/* #undef volatile */
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,94 +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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
# define THRIFT_GET_SOCKET_ERROR ::WSAGetLastError()
|
|
||||||
# define THRIFT_EINPROGRESS WSAEINPROGRESS
|
|
||||||
# define THRIFT_EAGAIN WSAEWOULDBLOCK
|
|
||||||
# define THRIFT_EINTR WSAEINTR
|
|
||||||
# define THRIFT_ECONNRESET WSAECONNRESET
|
|
||||||
# define THRIFT_ENOTCONN WSAENOTCONN
|
|
||||||
# define THRIFT_ETIMEDOUT WSAETIMEDOUT
|
|
||||||
# define THRIFT_EWOULDBLOCK WSAEWOULDBLOCK
|
|
||||||
# define THRIFT_EPIPE WSAECONNRESET
|
|
||||||
# define THRIFT_NO_SOCKET_CACHING SO_EXCLUSIVEADDRUSE
|
|
||||||
# define THRIFT_SOCKET SOCKET
|
|
||||||
# define THRIFT_INVALID_SOCKET INVALID_SOCKET
|
|
||||||
# define THRIFT_SOCKETPAIR thrift_socketpair
|
|
||||||
# define THRIFT_FCNTL thrift_fcntl
|
|
||||||
# define THRIFT_O_NONBLOCK 1
|
|
||||||
# define THRIFT_F_GETFL 0
|
|
||||||
# define THRIFT_F_SETFL 1
|
|
||||||
# define THRIFT_GETTIMEOFDAY thrift_gettimeofday
|
|
||||||
# define THRIFT_CLOSESOCKET closesocket
|
|
||||||
# define THRIFT_GAI_STRERROR gai_strerrorA
|
|
||||||
# define THRIFT_SSIZET ptrdiff_t
|
|
||||||
# define THRIFT_SNPRINTF _snprintf
|
|
||||||
# define THRIFT_SLEEP_SEC thrift_sleep
|
|
||||||
# define THRIFT_SLEEP_USEC thrift_usleep
|
|
||||||
# define THRIFT_TIMESPEC thrift_timespec
|
|
||||||
# define THRIFT_CTIME_R thrift_ctime_r
|
|
||||||
# define THRIFT_POLL thrift_poll
|
|
||||||
# if WINVER <= 0x0502 //XP, Server2003
|
|
||||||
# define THRIFT_POLLFD thrift_pollfd
|
|
||||||
# define THRIFT_POLLIN 0x0300
|
|
||||||
# define THRIFT_POLLOUT 0x0010
|
|
||||||
# else //Vista, Win7...
|
|
||||||
# define THRIFT_POLLFD pollfd
|
|
||||||
# define THRIFT_POLLIN POLLIN
|
|
||||||
# define THRIFT_POLLOUT POLLOUT
|
|
||||||
# endif //WINVER
|
|
||||||
# define THRIFT_SHUT_RDWR SD_BOTH
|
|
||||||
#else //not _WIN32
|
|
||||||
# include <errno.h>
|
|
||||||
# define THRIFT_GET_SOCKET_ERROR errno
|
|
||||||
# define THRIFT_EINTR EINTR
|
|
||||||
# define THRIFT_EINPROGRESS EINPROGRESS
|
|
||||||
# define THRIFT_ECONNRESET ECONNRESET
|
|
||||||
# define THRIFT_ENOTCONN ENOTCONN
|
|
||||||
# define THRIFT_ETIMEDOUT ETIMEDOUT
|
|
||||||
# define THRIFT_EWOULDBLOCK EWOULDBLOCK
|
|
||||||
# define THRIFT_EAGAIN EAGAIN
|
|
||||||
# define THRIFT_EPIPE EPIPE
|
|
||||||
# define THRIFT_NO_SOCKET_CACHING SO_REUSEADDR
|
|
||||||
# define THRIFT_SOCKET int
|
|
||||||
# define THRIFT_INVALID_SOCKET (-1)
|
|
||||||
# define THRIFT_SOCKETPAIR socketpair
|
|
||||||
# define THRIFT_FCNTL fcntl
|
|
||||||
# define THRIFT_O_NONBLOCK O_NONBLOCK
|
|
||||||
# define THRIFT_F_GETFL F_GETFL
|
|
||||||
# define THRIFT_F_SETFL F_SETFL
|
|
||||||
# define THRIFT_GETTIMEOFDAY gettimeofday
|
|
||||||
# define THRIFT_CLOSESOCKET close
|
|
||||||
# define THRIFT_GAI_STRERROR gai_strerror
|
|
||||||
# define THRIFT_SSIZET ssize_t
|
|
||||||
# define THRIFT_SNPRINTF snprintf
|
|
||||||
# define THRIFT_SLEEP_SEC sleep
|
|
||||||
# define THRIFT_SLEEP_USEC usleep
|
|
||||||
# define THRIFT_TIMESPEC timespec
|
|
||||||
# define THRIFT_CTIME_R ctime_r
|
|
||||||
# define THRIFT_POLL poll
|
|
||||||
# define THRIFT_POLLFD pollfd
|
|
||||||
# define THRIFT_POLLIN POLLIN
|
|
||||||
# define THRIFT_POLLOUT POLLOUT
|
|
||||||
# define THRIFT_SHUT_RDWR SHUT_RDWR
|
|
||||||
#endif
|
|
||||||
|
|
||||||
@@ -1,455 +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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <cassert>
|
|
||||||
#include <algorithm>
|
|
||||||
|
|
||||||
#include <thrift/transport/TBufferTransports.h>
|
|
||||||
|
|
||||||
using std::string;
|
|
||||||
|
|
||||||
namespace apache
|
|
||||||
{
|
|
||||||
namespace thrift
|
|
||||||
{
|
|
||||||
namespace transport
|
|
||||||
{
|
|
||||||
|
|
||||||
|
|
||||||
uint32_t TBufferedTransport::readSlow(uint8_t* buf, uint32_t len)
|
|
||||||
{
|
|
||||||
uint32_t have = static_cast<uint32_t>(rBound_ - rBase_);
|
|
||||||
|
|
||||||
// We should only take the slow path if we can't satisfy the read
|
|
||||||
// with the data already in the buffer.
|
|
||||||
assert(have < len);
|
|
||||||
|
|
||||||
// If we have some data in the buffer, copy it out and return it.
|
|
||||||
// We have to return it without attempting to read more, since we aren't
|
|
||||||
// guaranteed that the underlying transport actually has more data, so
|
|
||||||
// attempting to read from it could block.
|
|
||||||
if (have > 0)
|
|
||||||
{
|
|
||||||
memcpy(buf, rBase_, have);
|
|
||||||
setReadBuffer(rBuf_.get(), 0);
|
|
||||||
return have;
|
|
||||||
}
|
|
||||||
|
|
||||||
// No data is available in our buffer.
|
|
||||||
// Get more from underlying transport up to buffer size.
|
|
||||||
// Note that this makes a lot of sense if len < rBufSize_
|
|
||||||
// and almost no sense otherwise. TODO(dreiss): Fix that
|
|
||||||
// case (possibly including some readv hotness).
|
|
||||||
setReadBuffer(rBuf_.get(), transport_->read(rBuf_.get(), rBufSize_));
|
|
||||||
|
|
||||||
// Hand over whatever we have.
|
|
||||||
uint32_t give = (std::min)(len, static_cast<uint32_t>(rBound_ - rBase_));
|
|
||||||
memcpy(buf, rBase_, give);
|
|
||||||
rBase_ += give;
|
|
||||||
|
|
||||||
return give;
|
|
||||||
}
|
|
||||||
|
|
||||||
void TBufferedTransport::writeSlow(const uint8_t* buf, uint32_t len)
|
|
||||||
{
|
|
||||||
uint32_t have_bytes = static_cast<uint32_t>(wBase_ - wBuf_.get());
|
|
||||||
uint32_t space = static_cast<uint32_t>(wBound_ - wBase_);
|
|
||||||
// We should only take the slow path if we can't accomodate the write
|
|
||||||
// with the free space already in the buffer.
|
|
||||||
assert(wBound_ - wBase_ < static_cast<ptrdiff_t>(len));
|
|
||||||
|
|
||||||
// Now here's the tricky question: should we copy data from buf into our
|
|
||||||
// internal buffer and write it from there, or should we just write out
|
|
||||||
// the current internal buffer in one syscall and write out buf in another.
|
|
||||||
// If our currently buffered data plus buf is at least double our buffer
|
|
||||||
// size, we will have to do two syscalls no matter what (except in the
|
|
||||||
// degenerate case when our buffer is empty), so there is no use copying.
|
|
||||||
// Otherwise, there is sort of a sliding scale. If we have N-1 bytes
|
|
||||||
// buffered and need to write 2, it would be crazy to do two syscalls.
|
|
||||||
// On the other hand, if we have 2 bytes buffered and are writing 2N-3,
|
|
||||||
// we can save a syscall in the short term by loading up our buffer, writing
|
|
||||||
// it out, and copying the rest of the bytes into our buffer. Of course,
|
|
||||||
// if we get another 2-byte write, we haven't saved any syscalls at all,
|
|
||||||
// and have just copied nearly 2N bytes for nothing. Finding a perfect
|
|
||||||
// policy would require predicting the size of future writes, so we're just
|
|
||||||
// going to always eschew syscalls if we have less than 2N bytes to write.
|
|
||||||
|
|
||||||
// The case where we have to do two syscalls.
|
|
||||||
// This case also covers the case where the buffer is empty,
|
|
||||||
// but it is clearer (I think) to think of it as two separate cases.
|
|
||||||
if ((have_bytes + len >= 2 * wBufSize_) || (have_bytes == 0))
|
|
||||||
{
|
|
||||||
// TODO(dreiss): writev
|
|
||||||
if (have_bytes > 0)
|
|
||||||
{
|
|
||||||
transport_->write(wBuf_.get(), have_bytes);
|
|
||||||
}
|
|
||||||
|
|
||||||
transport_->write(buf, len);
|
|
||||||
wBase_ = wBuf_.get();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fill up our internal buffer for a write.
|
|
||||||
memcpy(wBase_, buf, space);
|
|
||||||
buf += space;
|
|
||||||
len -= space;
|
|
||||||
transport_->write(wBuf_.get(), wBufSize_);
|
|
||||||
|
|
||||||
// Copy the rest into our buffer.
|
|
||||||
assert(len < wBufSize_);
|
|
||||||
memcpy(wBuf_.get(), buf, len);
|
|
||||||
wBase_ = wBuf_.get() + len;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const uint8_t* TBufferedTransport::borrowSlow(uint8_t* buf, uint32_t* len)
|
|
||||||
{
|
|
||||||
(void) buf;
|
|
||||||
(void) len;
|
|
||||||
// Simply return NULL. We don't know if there is actually data available on
|
|
||||||
// the underlying transport, so calling read() might block.
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
void TBufferedTransport::flush()
|
|
||||||
{
|
|
||||||
// Write out any data waiting in the write buffer.
|
|
||||||
uint32_t have_bytes = static_cast<uint32_t>(wBase_ - wBuf_.get());
|
|
||||||
|
|
||||||
if (have_bytes > 0)
|
|
||||||
{
|
|
||||||
// Note that we reset wBase_ prior to the underlying write
|
|
||||||
// to ensure we're in a sane state (i.e. internal buffer cleaned)
|
|
||||||
// if the underlying write throws up an exception
|
|
||||||
wBase_ = wBuf_.get();
|
|
||||||
transport_->write(wBuf_.get(), have_bytes);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Flush the underlying transport.
|
|
||||||
transport_->flush();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
uint32_t TFramedTransport::readSlow(uint8_t* buf, uint32_t len)
|
|
||||||
{
|
|
||||||
uint32_t want = len;
|
|
||||||
uint32_t have = static_cast<uint32_t>(rBound_ - rBase_);
|
|
||||||
|
|
||||||
// We should only take the slow path if we can't satisfy the read
|
|
||||||
// with the data already in the buffer.
|
|
||||||
assert(have < want);
|
|
||||||
|
|
||||||
// If we have some data in the buffer, copy it out and return it.
|
|
||||||
// We have to return it without attempting to read more, since we aren't
|
|
||||||
// guaranteed that the underlying transport actually has more data, so
|
|
||||||
// attempting to read from it could block.
|
|
||||||
if (have > 0)
|
|
||||||
{
|
|
||||||
memcpy(buf, rBase_, have);
|
|
||||||
setReadBuffer(rBuf_.get(), 0);
|
|
||||||
return have;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Read another frame.
|
|
||||||
if (!readFrame())
|
|
||||||
{
|
|
||||||
// EOF. No frame available.
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO(dreiss): Should we warn when reads cross frames?
|
|
||||||
|
|
||||||
// Hand over whatever we have.
|
|
||||||
uint32_t give = (std::min)(want, static_cast<uint32_t>(rBound_ - rBase_));
|
|
||||||
memcpy(buf, rBase_, give);
|
|
||||||
rBase_ += give;
|
|
||||||
want -= give;
|
|
||||||
|
|
||||||
return (len - want);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool TFramedTransport::readFrame()
|
|
||||||
{
|
|
||||||
// TODO(dreiss): Think about using readv here, even though it would
|
|
||||||
// result in (gasp) read-ahead.
|
|
||||||
|
|
||||||
// Read the size of the next frame.
|
|
||||||
// We can't use readAll(&sz, sizeof(sz)), since that always throws an
|
|
||||||
// exception on EOF. We want to throw an exception only if EOF occurs after
|
|
||||||
// partial size data.
|
|
||||||
int32_t sz;
|
|
||||||
uint32_t size_bytes_read = 0;
|
|
||||||
|
|
||||||
while (size_bytes_read < sizeof(sz))
|
|
||||||
{
|
|
||||||
uint8_t* szp = reinterpret_cast<uint8_t*>(&sz) + size_bytes_read;
|
|
||||||
uint32_t bytes_read = transport_->read(
|
|
||||||
szp,
|
|
||||||
static_cast<uint32_t>(sizeof(sz)) - size_bytes_read);
|
|
||||||
|
|
||||||
if (bytes_read == 0)
|
|
||||||
{
|
|
||||||
if (size_bytes_read == 0)
|
|
||||||
{
|
|
||||||
// EOF before any data was read.
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// EOF after a partial frame header. Raise an exception.
|
|
||||||
throw TTransportException(TTransportException::END_OF_FILE,
|
|
||||||
"No more data to read after "
|
|
||||||
"partial frame header.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
size_bytes_read += bytes_read;
|
|
||||||
}
|
|
||||||
|
|
||||||
sz = ntohl(sz);
|
|
||||||
|
|
||||||
if (sz < 0)
|
|
||||||
{
|
|
||||||
throw TTransportException("Frame size has negative value");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Read the frame payload, and reset markers.
|
|
||||||
if (sz > static_cast<int32_t>(rBufSize_))
|
|
||||||
{
|
|
||||||
rBuf_.reset(new uint8_t[sz]);
|
|
||||||
rBufSize_ = sz;
|
|
||||||
}
|
|
||||||
|
|
||||||
transport_->readAll(rBuf_.get(), sz);
|
|
||||||
setReadBuffer(rBuf_.get(), sz);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void TFramedTransport::writeSlow(const uint8_t* buf, uint32_t len)
|
|
||||||
{
|
|
||||||
// Double buffer size until sufficient.
|
|
||||||
uint32_t have = static_cast<uint32_t>(wBase_ - wBuf_.get());
|
|
||||||
uint32_t new_size = wBufSize_;
|
|
||||||
|
|
||||||
if (len + have < have /* overflow */ || len + have > 0x7fffffff)
|
|
||||||
{
|
|
||||||
throw TTransportException(TTransportException::BAD_ARGS,
|
|
||||||
"Attempted to write over 2 GB to TFramedTransport.");
|
|
||||||
}
|
|
||||||
|
|
||||||
while (new_size < len + have)
|
|
||||||
{
|
|
||||||
new_size = new_size > 0 ? new_size * 2 : 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO(dreiss): Consider modifying this class to use malloc/free
|
|
||||||
// so we can use realloc here.
|
|
||||||
|
|
||||||
// Allocate new buffer.
|
|
||||||
uint8_t* new_buf = new uint8_t[new_size];
|
|
||||||
|
|
||||||
// Copy the old buffer to the new one.
|
|
||||||
memcpy(new_buf, wBuf_.get(), have);
|
|
||||||
|
|
||||||
// Now point buf to the new one.
|
|
||||||
wBuf_.reset(new_buf);
|
|
||||||
wBufSize_ = new_size;
|
|
||||||
wBase_ = wBuf_.get() + have;
|
|
||||||
wBound_ = wBuf_.get() + wBufSize_;
|
|
||||||
|
|
||||||
// Copy the data into the new buffer.
|
|
||||||
memcpy(wBase_, buf, len);
|
|
||||||
wBase_ += len;
|
|
||||||
}
|
|
||||||
|
|
||||||
void TFramedTransport::flush()
|
|
||||||
{
|
|
||||||
int32_t sz_hbo, sz_nbo;
|
|
||||||
assert(wBufSize_ > sizeof(sz_nbo));
|
|
||||||
|
|
||||||
// Slip the frame size into the start of the buffer.
|
|
||||||
sz_hbo = static_cast<uint32_t>(wBase_ - (wBuf_.get() + sizeof(sz_nbo)));
|
|
||||||
sz_nbo = (int32_t)htonl((uint32_t)(sz_hbo));
|
|
||||||
memcpy(wBuf_.get(), (uint8_t*)&sz_nbo, sizeof(sz_nbo));
|
|
||||||
|
|
||||||
if (sz_hbo > 0)
|
|
||||||
{
|
|
||||||
// Note that we reset wBase_ (with a pad for the frame size)
|
|
||||||
// prior to the underlying write to ensure we're in a sane state
|
|
||||||
// (i.e. internal buffer cleaned) if the underlying write throws
|
|
||||||
// up an exception
|
|
||||||
wBase_ = wBuf_.get() + sizeof(sz_nbo);
|
|
||||||
|
|
||||||
// Write size and frame body.
|
|
||||||
transport_->write(
|
|
||||||
wBuf_.get(),
|
|
||||||
static_cast<uint32_t>(sizeof(sz_nbo)) + sz_hbo);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Flush the underlying transport.
|
|
||||||
transport_->flush();
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t TFramedTransport::writeEnd()
|
|
||||||
{
|
|
||||||
return static_cast<uint32_t>(wBase_ - wBuf_.get());
|
|
||||||
}
|
|
||||||
|
|
||||||
const uint8_t* TFramedTransport::borrowSlow(uint8_t* buf, uint32_t* len)
|
|
||||||
{
|
|
||||||
(void) buf;
|
|
||||||
(void) len;
|
|
||||||
// Don't try to be clever with shifting buffers.
|
|
||||||
// If the fast path failed let the protocol use its slow path.
|
|
||||||
// Besides, who is going to try to borrow across messages?
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t TFramedTransport::readEnd()
|
|
||||||
{
|
|
||||||
// include framing bytes
|
|
||||||
return static_cast<uint32_t>(rBound_ - rBuf_.get() + sizeof(uint32_t));
|
|
||||||
}
|
|
||||||
|
|
||||||
void TMemoryBuffer::computeRead(uint32_t len, uint8_t** out_start, uint32_t* out_give)
|
|
||||||
{
|
|
||||||
// Correct rBound_ so we can use the fast path in the future.
|
|
||||||
rBound_ = wBase_;
|
|
||||||
|
|
||||||
// Decide how much to give.
|
|
||||||
uint32_t give = (std::min)(len, available_read());
|
|
||||||
|
|
||||||
*out_start = rBase_;
|
|
||||||
*out_give = give;
|
|
||||||
|
|
||||||
// Preincrement rBase_ so the caller doesn't have to.
|
|
||||||
rBase_ += give;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t TMemoryBuffer::readSlow(uint8_t* buf, uint32_t len)
|
|
||||||
{
|
|
||||||
uint8_t* start;
|
|
||||||
uint32_t give;
|
|
||||||
computeRead(len, &start, &give);
|
|
||||||
|
|
||||||
// Copy into the provided buffer.
|
|
||||||
memcpy(buf, start, give);
|
|
||||||
|
|
||||||
return give;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t TMemoryBuffer::readAppendToString(std::string& str, uint32_t len)
|
|
||||||
{
|
|
||||||
// Don't get some stupid assertion failure.
|
|
||||||
if (buffer_ == NULL)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t* start;
|
|
||||||
uint32_t give;
|
|
||||||
computeRead(len, &start, &give);
|
|
||||||
|
|
||||||
// Append to the provided string.
|
|
||||||
str.append((char*)start, give);
|
|
||||||
|
|
||||||
return give;
|
|
||||||
}
|
|
||||||
|
|
||||||
void TMemoryBuffer::ensureCanWrite(uint32_t len)
|
|
||||||
{
|
|
||||||
// Check available space
|
|
||||||
uint32_t avail = available_write();
|
|
||||||
|
|
||||||
if (len <= avail)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!owner_)
|
|
||||||
{
|
|
||||||
throw TTransportException("Insufficient space in external MemoryBuffer");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Grow the buffer as necessary.
|
|
||||||
uint32_t new_size = bufferSize_;
|
|
||||||
|
|
||||||
while (len > avail)
|
|
||||||
{
|
|
||||||
new_size = new_size > 0 ? new_size * 2 : 1;
|
|
||||||
avail = available_write() + (new_size - bufferSize_);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Allocate into a new pointer so we don't bork ours if it fails.
|
|
||||||
void* new_buffer = std::realloc(buffer_, new_size);
|
|
||||||
|
|
||||||
if (new_buffer == NULL)
|
|
||||||
{
|
|
||||||
throw std::bad_alloc();
|
|
||||||
}
|
|
||||||
|
|
||||||
bufferSize_ = new_size;
|
|
||||||
|
|
||||||
ptrdiff_t offset = (uint8_t*)new_buffer - buffer_;
|
|
||||||
buffer_ += offset;
|
|
||||||
rBase_ += offset;
|
|
||||||
rBound_ += offset;
|
|
||||||
wBase_ += offset;
|
|
||||||
wBound_ = buffer_ + bufferSize_;
|
|
||||||
}
|
|
||||||
|
|
||||||
void TMemoryBuffer::writeSlow(const uint8_t* buf, uint32_t len)
|
|
||||||
{
|
|
||||||
ensureCanWrite(len);
|
|
||||||
|
|
||||||
// Copy into the buffer and increment wBase_.
|
|
||||||
memcpy(wBase_, buf, len);
|
|
||||||
wBase_ += len;
|
|
||||||
}
|
|
||||||
|
|
||||||
void TMemoryBuffer::wroteBytes(uint32_t len)
|
|
||||||
{
|
|
||||||
uint32_t avail = available_write();
|
|
||||||
|
|
||||||
if (len > avail)
|
|
||||||
{
|
|
||||||
throw TTransportException("Client wrote more bytes than size of buffer.");
|
|
||||||
}
|
|
||||||
|
|
||||||
wBase_ += len;
|
|
||||||
}
|
|
||||||
|
|
||||||
const uint8_t* TMemoryBuffer::borrowSlow(uint8_t* buf, uint32_t* len)
|
|
||||||
{
|
|
||||||
(void) buf;
|
|
||||||
rBound_ = wBase_;
|
|
||||||
|
|
||||||
if (available_read() >= *len)
|
|
||||||
{
|
|
||||||
*len = available_read();
|
|
||||||
return rBase_;
|
|
||||||
}
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} // apache::thrift::transport
|
|
||||||
@@ -1,824 +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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <cstring>
|
|
||||||
#include <boost/scoped_array.hpp>
|
|
||||||
|
|
||||||
#include <thrift/transport/TTransport.h>
|
|
||||||
#include <thrift/transport/TVirtualTransport.h>
|
|
||||||
|
|
||||||
#ifdef __GNUC__
|
|
||||||
#define TDB_LIKELY(val) (__builtin_expect((val), 1))
|
|
||||||
#define TDB_UNLIKELY(val) (__builtin_expect((val), 0))
|
|
||||||
#else
|
|
||||||
#define TDB_LIKELY(val) (val)
|
|
||||||
#define TDB_UNLIKELY(val) (val)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace apache
|
|
||||||
{
|
|
||||||
namespace thrift
|
|
||||||
{
|
|
||||||
namespace transport
|
|
||||||
{
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Base class for all transports that use read/write buffers for performance.
|
|
||||||
*
|
|
||||||
* TBufferBase is designed to implement the fast-path "memcpy" style
|
|
||||||
* operations that work in the common case. It does so with small and
|
|
||||||
* (eventually) nonvirtual, inlinable methods. TBufferBase is an abstract
|
|
||||||
* class. Subclasses are expected to define the "slow path" operations
|
|
||||||
* that have to be done when the buffers are full or empty.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
class TBufferBase : public TVirtualTransport<TBufferBase>
|
|
||||||
{
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fast-path read.
|
|
||||||
*
|
|
||||||
* When we have enough data buffered to fulfill the read, we can satisfy it
|
|
||||||
* with a single memcpy, then adjust our internal pointers. If the buffer
|
|
||||||
* is empty, we call out to our slow path, implemented by a subclass.
|
|
||||||
* This method is meant to eventually be nonvirtual and inlinable.
|
|
||||||
*/
|
|
||||||
uint32_t read(uint8_t* buf, uint32_t len)
|
|
||||||
{
|
|
||||||
uint8_t* new_rBase = rBase_ + len;
|
|
||||||
|
|
||||||
if (TDB_LIKELY(new_rBase <= rBound_))
|
|
||||||
{
|
|
||||||
std::memcpy(buf, rBase_, len);
|
|
||||||
rBase_ = new_rBase;
|
|
||||||
return len;
|
|
||||||
}
|
|
||||||
|
|
||||||
return readSlow(buf, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Shortcutted version of readAll.
|
|
||||||
*/
|
|
||||||
uint32_t readAll(uint8_t* buf, uint32_t len)
|
|
||||||
{
|
|
||||||
uint8_t* new_rBase = rBase_ + len;
|
|
||||||
|
|
||||||
if (TDB_LIKELY(new_rBase <= rBound_))
|
|
||||||
{
|
|
||||||
std::memcpy(buf, rBase_, len);
|
|
||||||
rBase_ = new_rBase;
|
|
||||||
return len;
|
|
||||||
}
|
|
||||||
|
|
||||||
return apache::thrift::transport::readAll(*this, buf, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fast-path write.
|
|
||||||
*
|
|
||||||
* When we have enough empty space in our buffer to accomodate the write, we
|
|
||||||
* can satisfy it with a single memcpy, then adjust our internal pointers.
|
|
||||||
* If the buffer is full, we call out to our slow path, implemented by a
|
|
||||||
* subclass. This method is meant to eventually be nonvirtual and
|
|
||||||
* inlinable.
|
|
||||||
*/
|
|
||||||
void write(const uint8_t* buf, uint32_t len)
|
|
||||||
{
|
|
||||||
uint8_t* new_wBase = wBase_ + len;
|
|
||||||
|
|
||||||
if (TDB_LIKELY(new_wBase <= wBound_))
|
|
||||||
{
|
|
||||||
std::memcpy(wBase_, buf, len);
|
|
||||||
wBase_ = new_wBase;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
writeSlow(buf, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fast-path borrow. A lot like the fast-path read.
|
|
||||||
*/
|
|
||||||
const uint8_t* borrow(uint8_t* buf, uint32_t* len)
|
|
||||||
{
|
|
||||||
if (TDB_LIKELY(static_cast<ptrdiff_t>(*len) <= rBound_ - rBase_))
|
|
||||||
{
|
|
||||||
// With strict aliasing, writing to len shouldn't force us to
|
|
||||||
// refetch rBase_ from memory. TODO(dreiss): Verify this.
|
|
||||||
*len = static_cast<uint32_t>(rBound_ - rBase_);
|
|
||||||
return rBase_;
|
|
||||||
}
|
|
||||||
|
|
||||||
return borrowSlow(buf, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Consume doesn't require a slow path.
|
|
||||||
*/
|
|
||||||
void consume(uint32_t len)
|
|
||||||
{
|
|
||||||
if (TDB_LIKELY(static_cast<ptrdiff_t>(len) <= rBound_ - rBase_))
|
|
||||||
{
|
|
||||||
rBase_ += len;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
throw TTransportException(TTransportException::BAD_ARGS,
|
|
||||||
"consume did not follow a borrow.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
protected:
|
|
||||||
|
|
||||||
/// Slow path read.
|
|
||||||
virtual uint32_t readSlow(uint8_t* buf, uint32_t len) = 0;
|
|
||||||
|
|
||||||
/// Slow path write.
|
|
||||||
virtual void writeSlow(const uint8_t* buf, uint32_t len) = 0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Slow path borrow.
|
|
||||||
*
|
|
||||||
* POSTCONDITION: return == NULL || rBound_ - rBase_ >= *len
|
|
||||||
*/
|
|
||||||
virtual const uint8_t* borrowSlow(uint8_t* buf, uint32_t* len) = 0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Trivial constructor.
|
|
||||||
*
|
|
||||||
* Initialize pointers safely. Constructing is not a very
|
|
||||||
* performance-sensitive operation, so it is okay to just leave it to
|
|
||||||
* the concrete class to set up pointers correctly.
|
|
||||||
*/
|
|
||||||
TBufferBase()
|
|
||||||
: rBase_(NULL)
|
|
||||||
, rBound_(NULL)
|
|
||||||
, wBase_(NULL)
|
|
||||||
, wBound_(NULL)
|
|
||||||
{}
|
|
||||||
|
|
||||||
/// Convenience mutator for setting the read buffer.
|
|
||||||
void setReadBuffer(uint8_t* buf, uint32_t len)
|
|
||||||
{
|
|
||||||
rBase_ = buf;
|
|
||||||
rBound_ = buf + len;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Convenience mutator for setting the write buffer.
|
|
||||||
void setWriteBuffer(uint8_t* buf, uint32_t len)
|
|
||||||
{
|
|
||||||
wBase_ = buf;
|
|
||||||
wBound_ = buf + len;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual ~TBufferBase() {}
|
|
||||||
|
|
||||||
/// Reads begin here.
|
|
||||||
uint8_t* rBase_;
|
|
||||||
/// Reads may extend to just before here.
|
|
||||||
uint8_t* rBound_;
|
|
||||||
|
|
||||||
/// Writes begin here.
|
|
||||||
uint8_t* wBase_;
|
|
||||||
/// Writes may extend to just before here.
|
|
||||||
uint8_t* wBound_;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Buffered transport. For reads it will read more data than is requested
|
|
||||||
* and will serve future data out of a local buffer. For writes, data is
|
|
||||||
* stored to an in memory buffer before being written out.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
class TBufferedTransport
|
|
||||||
: public TVirtualTransport<TBufferedTransport, TBufferBase>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
static const int DEFAULT_BUFFER_SIZE = 512;
|
|
||||||
|
|
||||||
/// Use default buffer sizes.
|
|
||||||
TBufferedTransport(boost::shared_ptr<TTransport> transport)
|
|
||||||
: transport_(transport)
|
|
||||||
, rBufSize_(DEFAULT_BUFFER_SIZE)
|
|
||||||
, wBufSize_(DEFAULT_BUFFER_SIZE)
|
|
||||||
, rBuf_(new uint8_t[rBufSize_])
|
|
||||||
, wBuf_(new uint8_t[wBufSize_])
|
|
||||||
{
|
|
||||||
initPointers();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Use specified buffer sizes.
|
|
||||||
TBufferedTransport(boost::shared_ptr<TTransport> transport, uint32_t sz)
|
|
||||||
: transport_(transport)
|
|
||||||
, rBufSize_(sz)
|
|
||||||
, wBufSize_(sz)
|
|
||||||
, rBuf_(new uint8_t[rBufSize_])
|
|
||||||
, wBuf_(new uint8_t[wBufSize_])
|
|
||||||
{
|
|
||||||
initPointers();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Use specified read and write buffer sizes.
|
|
||||||
TBufferedTransport(boost::shared_ptr<TTransport> transport, uint32_t rsz, uint32_t wsz)
|
|
||||||
: transport_(transport)
|
|
||||||
, rBufSize_(rsz)
|
|
||||||
, wBufSize_(wsz)
|
|
||||||
, rBuf_(new uint8_t[rBufSize_])
|
|
||||||
, wBuf_(new uint8_t[wBufSize_])
|
|
||||||
{
|
|
||||||
initPointers();
|
|
||||||
}
|
|
||||||
|
|
||||||
void open()
|
|
||||||
{
|
|
||||||
transport_->open();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool isOpen()
|
|
||||||
{
|
|
||||||
return transport_->isOpen();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool peek()
|
|
||||||
{
|
|
||||||
if (rBase_ == rBound_)
|
|
||||||
{
|
|
||||||
setReadBuffer(rBuf_.get(), transport_->read(rBuf_.get(), rBufSize_));
|
|
||||||
}
|
|
||||||
|
|
||||||
return (rBound_ > rBase_);
|
|
||||||
}
|
|
||||||
|
|
||||||
void close()
|
|
||||||
{
|
|
||||||
flush();
|
|
||||||
transport_->close();
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual uint32_t readSlow(uint8_t* buf, uint32_t len);
|
|
||||||
|
|
||||||
virtual void writeSlow(const uint8_t* buf, uint32_t len);
|
|
||||||
|
|
||||||
void flush();
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The following behavior is currently implemented by TBufferedTransport,
|
|
||||||
* but that may change in a future version:
|
|
||||||
* 1/ If len is at most rBufSize_, borrow will never return NULL.
|
|
||||||
* Depending on the underlying transport, it could throw an exception
|
|
||||||
* or hang forever.
|
|
||||||
* 2/ Some borrow requests may copy bytes internally. However,
|
|
||||||
* if len is at most rBufSize_/2, none of the copied bytes
|
|
||||||
* will ever have to be copied again. For optimial performance,
|
|
||||||
* stay under this limit.
|
|
||||||
*/
|
|
||||||
virtual const uint8_t* borrowSlow(uint8_t* buf, uint32_t* len);
|
|
||||||
|
|
||||||
boost::shared_ptr<TTransport> getUnderlyingTransport()
|
|
||||||
{
|
|
||||||
return transport_;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* TVirtualTransport provides a default implementation of readAll().
|
|
||||||
* We want to use the TBufferBase version instead.
|
|
||||||
*/
|
|
||||||
uint32_t readAll(uint8_t* buf, uint32_t len)
|
|
||||||
{
|
|
||||||
return TBufferBase::readAll(buf, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
void initPointers()
|
|
||||||
{
|
|
||||||
setReadBuffer(rBuf_.get(), 0);
|
|
||||||
setWriteBuffer(wBuf_.get(), wBufSize_);
|
|
||||||
// Write size never changes.
|
|
||||||
}
|
|
||||||
|
|
||||||
boost::shared_ptr<TTransport> transport_;
|
|
||||||
|
|
||||||
uint32_t rBufSize_;
|
|
||||||
uint32_t wBufSize_;
|
|
||||||
boost::scoped_array<uint8_t> rBuf_;
|
|
||||||
boost::scoped_array<uint8_t> wBuf_;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Wraps a transport into a buffered one.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
class TBufferedTransportFactory : public TTransportFactory
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
TBufferedTransportFactory() {}
|
|
||||||
|
|
||||||
virtual ~TBufferedTransportFactory() {}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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));
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Framed transport. All writes go into an in-memory buffer until flush is
|
|
||||||
* called, at which point the transport writes the length of the entire
|
|
||||||
* binary chunk followed by the data payload. This allows the receiver on the
|
|
||||||
* other end to always do fixed-length reads.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
class TFramedTransport
|
|
||||||
: public TVirtualTransport<TFramedTransport, TBufferBase>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
static const int DEFAULT_BUFFER_SIZE = 512;
|
|
||||||
|
|
||||||
/// Use default buffer sizes.
|
|
||||||
TFramedTransport(boost::shared_ptr<TTransport> transport)
|
|
||||||
: transport_(transport)
|
|
||||||
, rBufSize_(0)
|
|
||||||
, wBufSize_(DEFAULT_BUFFER_SIZE)
|
|
||||||
, rBuf_()
|
|
||||||
, wBuf_(new uint8_t[wBufSize_])
|
|
||||||
{
|
|
||||||
initPointers();
|
|
||||||
}
|
|
||||||
|
|
||||||
TFramedTransport(boost::shared_ptr<TTransport> transport, uint32_t sz)
|
|
||||||
: transport_(transport)
|
|
||||||
, rBufSize_(0)
|
|
||||||
, wBufSize_(sz)
|
|
||||||
, rBuf_()
|
|
||||||
, wBuf_(new uint8_t[wBufSize_])
|
|
||||||
{
|
|
||||||
initPointers();
|
|
||||||
}
|
|
||||||
|
|
||||||
void open()
|
|
||||||
{
|
|
||||||
transport_->open();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool isOpen()
|
|
||||||
{
|
|
||||||
return transport_->isOpen();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool peek()
|
|
||||||
{
|
|
||||||
return (rBase_ < rBound_) || transport_->peek();
|
|
||||||
}
|
|
||||||
|
|
||||||
void close()
|
|
||||||
{
|
|
||||||
flush();
|
|
||||||
transport_->close();
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual uint32_t readSlow(uint8_t* buf, uint32_t len);
|
|
||||||
|
|
||||||
virtual void writeSlow(const uint8_t* buf, uint32_t len);
|
|
||||||
|
|
||||||
virtual void flush();
|
|
||||||
|
|
||||||
uint32_t readEnd();
|
|
||||||
|
|
||||||
uint32_t writeEnd();
|
|
||||||
|
|
||||||
const uint8_t* borrowSlow(uint8_t* buf, uint32_t* len);
|
|
||||||
|
|
||||||
boost::shared_ptr<TTransport> getUnderlyingTransport()
|
|
||||||
{
|
|
||||||
return transport_;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* TVirtualTransport provides a default implementation of readAll().
|
|
||||||
* We want to use the TBufferBase version instead.
|
|
||||||
*/
|
|
||||||
uint32_t readAll(uint8_t* buf, uint32_t len)
|
|
||||||
{
|
|
||||||
return TBufferBase::readAll(buf, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
/**
|
|
||||||
* Reads a frame of input from the underlying stream.
|
|
||||||
*
|
|
||||||
* Returns true if a frame was read successfully, or false on EOF.
|
|
||||||
* (Raises a TTransportException if EOF occurs after a partial frame.)
|
|
||||||
*/
|
|
||||||
bool readFrame();
|
|
||||||
|
|
||||||
void initPointers()
|
|
||||||
{
|
|
||||||
setReadBuffer(NULL, 0);
|
|
||||||
setWriteBuffer(wBuf_.get(), wBufSize_);
|
|
||||||
|
|
||||||
// Pad the buffer so we can insert the size later.
|
|
||||||
int32_t pad = 0;
|
|
||||||
this->write((uint8_t*)&pad, sizeof(pad));
|
|
||||||
}
|
|
||||||
|
|
||||||
boost::shared_ptr<TTransport> transport_;
|
|
||||||
|
|
||||||
uint32_t rBufSize_;
|
|
||||||
uint32_t wBufSize_;
|
|
||||||
boost::scoped_array<uint8_t> rBuf_;
|
|
||||||
boost::scoped_array<uint8_t> wBuf_;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Wraps a transport into a framed one.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
class TFramedTransportFactory : public TTransportFactory
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
TFramedTransportFactory() {}
|
|
||||||
|
|
||||||
virtual ~TFramedTransportFactory() {}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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));
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A memory buffer is a tranpsort that simply reads from and writes to an
|
|
||||||
* in memory buffer. Anytime you call write on it, the data is simply placed
|
|
||||||
* into a buffer, and anytime you call read, data is read from that buffer.
|
|
||||||
*
|
|
||||||
* The buffers are allocated using C constructs malloc,realloc, and the size
|
|
||||||
* doubles as necessary. We've considered using scoped
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
if (buf == NULL && size != 0)
|
|
||||||
{
|
|
||||||
assert(owner);
|
|
||||||
buf = (uint8_t*)std::malloc(size);
|
|
||||||
|
|
||||||
if (buf == NULL)
|
|
||||||
{
|
|
||||||
throw std::bad_alloc();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
buffer_ = buf;
|
|
||||||
bufferSize_ = size;
|
|
||||||
|
|
||||||
rBase_ = buffer_;
|
|
||||||
rBound_ = buffer_ + wPos;
|
|
||||||
// TODO(dreiss): Investigate NULL-ing this if !owner.
|
|
||||||
wBase_ = buffer_ + wPos;
|
|
||||||
wBound_ = buffer_ + bufferSize_;
|
|
||||||
|
|
||||||
owner_ = owner;
|
|
||||||
|
|
||||||
// rBound_ is really an artifact. In principle, it should always be
|
|
||||||
// equal to wBase_. We update it in a few places (computeRead, etc.).
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
static const uint32_t defaultSize = 1024;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This enum specifies how a TMemoryBuffer should treat
|
|
||||||
* memory passed to it via constructors or resetBuffer.
|
|
||||||
*
|
|
||||||
* OBSERVE:
|
|
||||||
* TMemoryBuffer will simply store a pointer to the memory.
|
|
||||||
* It is the callers responsibility to ensure that the pointer
|
|
||||||
* remains valid for the lifetime of the TMemoryBuffer,
|
|
||||||
* and that it is properly cleaned up.
|
|
||||||
* Note that no data can be written to observed buffers.
|
|
||||||
*
|
|
||||||
* COPY:
|
|
||||||
* TMemoryBuffer will make an internal copy of the buffer.
|
|
||||||
* The caller has no responsibilities.
|
|
||||||
*
|
|
||||||
* TAKE_OWNERSHIP:
|
|
||||||
* TMemoryBuffer will become the "owner" of the buffer,
|
|
||||||
* and will be responsible for freeing it.
|
|
||||||
* The membory must have been allocated with malloc.
|
|
||||||
*/
|
|
||||||
enum MemoryPolicy
|
|
||||||
{
|
|
||||||
OBSERVE = 1
|
|
||||||
, COPY = 2
|
|
||||||
, TAKE_OWNERSHIP = 3
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Construct a TMemoryBuffer with a default-sized buffer,
|
|
||||||
* owned by the TMemoryBuffer object.
|
|
||||||
*/
|
|
||||||
TMemoryBuffer()
|
|
||||||
{
|
|
||||||
initCommon(NULL, defaultSize, true, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Construct a TMemoryBuffer with a buffer of a specified size,
|
|
||||||
* owned by the TMemoryBuffer object.
|
|
||||||
*
|
|
||||||
* @param sz The initial size of the buffer.
|
|
||||||
*/
|
|
||||||
TMemoryBuffer(uint32_t sz)
|
|
||||||
{
|
|
||||||
initCommon(NULL, sz, true, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Construct a TMemoryBuffer with buf as its initial contents.
|
|
||||||
*
|
|
||||||
* @param buf The initial contents of the buffer.
|
|
||||||
* Note that, while buf is a non-const pointer,
|
|
||||||
* TMemoryBuffer will not write to it if policy == OBSERVE,
|
|
||||||
* so it is safe to const_cast<uint8_t*>(whatever).
|
|
||||||
* @param sz The size of @c buf.
|
|
||||||
* @param policy See @link MemoryPolicy @endlink .
|
|
||||||
*/
|
|
||||||
TMemoryBuffer(uint8_t* buf, uint32_t sz, MemoryPolicy policy = OBSERVE)
|
|
||||||
{
|
|
||||||
if (buf == NULL && sz != 0)
|
|
||||||
{
|
|
||||||
throw TTransportException(TTransportException::BAD_ARGS,
|
|
||||||
"TMemoryBuffer given null buffer with non-zero size.");
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (policy)
|
|
||||||
{
|
|
||||||
case OBSERVE:
|
|
||||||
case TAKE_OWNERSHIP:
|
|
||||||
initCommon(buf, sz, policy == TAKE_OWNERSHIP, sz);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case COPY:
|
|
||||||
initCommon(NULL, sz, true, 0);
|
|
||||||
this->write(buf, sz);
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
throw TTransportException(TTransportException::BAD_ARGS,
|
|
||||||
"Invalid MemoryPolicy for TMemoryBuffer");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
~TMemoryBuffer()
|
|
||||||
{
|
|
||||||
if (owner_)
|
|
||||||
{
|
|
||||||
std::free(buffer_);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool isOpen()
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool peek()
|
|
||||||
{
|
|
||||||
return (rBase_ < wBase_);
|
|
||||||
}
|
|
||||||
|
|
||||||
void open() {}
|
|
||||||
|
|
||||||
void close() {}
|
|
||||||
|
|
||||||
// TODO(dreiss): Make bufPtr const.
|
|
||||||
void getBuffer(uint8_t** bufPtr, uint32_t* sz)
|
|
||||||
{
|
|
||||||
*bufPtr = rBase_;
|
|
||||||
*sz = static_cast<uint32_t>(wBase_ - rBase_);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string getBufferAsString()
|
|
||||||
{
|
|
||||||
if (buffer_ == NULL)
|
|
||||||
{
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t* buf;
|
|
||||||
uint32_t sz;
|
|
||||||
getBuffer(&buf, &sz);
|
|
||||||
return std::string((char*)buf, (std::string::size_type)sz);
|
|
||||||
}
|
|
||||||
|
|
||||||
void appendBufferToString(std::string& str)
|
|
||||||
{
|
|
||||||
if (buffer_ == NULL)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t* buf;
|
|
||||||
uint32_t sz;
|
|
||||||
getBuffer(&buf, &sz);
|
|
||||||
str.append((char*)buf, sz);
|
|
||||||
}
|
|
||||||
|
|
||||||
void resetBuffer()
|
|
||||||
{
|
|
||||||
rBase_ = buffer_;
|
|
||||||
rBound_ = buffer_;
|
|
||||||
wBase_ = buffer_;
|
|
||||||
|
|
||||||
// It isn't safe to write into a buffer we don't own.
|
|
||||||
if (!owner_)
|
|
||||||
{
|
|
||||||
wBound_ = wBase_;
|
|
||||||
bufferSize_ = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// See constructor documentation.
|
|
||||||
void resetBuffer(uint8_t* buf, uint32_t sz, MemoryPolicy policy = OBSERVE)
|
|
||||||
{
|
|
||||||
// Use a variant of the copy-and-swap trick for assignment operators.
|
|
||||||
// This is sub-optimal in terms of performance for two reasons:
|
|
||||||
// 1/ The constructing and swapping of the (small) values
|
|
||||||
// in the temporary object takes some time, and is not necessary.
|
|
||||||
// 2/ If policy == COPY, we allocate the new buffer before
|
|
||||||
// freeing the old one, precluding the possibility of
|
|
||||||
// reusing that memory.
|
|
||||||
// I doubt that either of these problems could be optimized away,
|
|
||||||
// but the second is probably no a common case, and the first is minor.
|
|
||||||
// I don't expect resetBuffer to be a common operation, so I'm willing to
|
|
||||||
// bite the performance bullet to make the method this simple.
|
|
||||||
|
|
||||||
// Construct the new buffer.
|
|
||||||
TMemoryBuffer new_buffer(buf, sz, policy);
|
|
||||||
// Move it into ourself.
|
|
||||||
this->swap(new_buffer);
|
|
||||||
// Our old self gets destroyed.
|
|
||||||
}
|
|
||||||
|
|
||||||
/// See constructor documentation.
|
|
||||||
void resetBuffer(uint32_t sz)
|
|
||||||
{
|
|
||||||
// Construct the new buffer.
|
|
||||||
TMemoryBuffer new_buffer(sz);
|
|
||||||
// Move it into ourself.
|
|
||||||
this->swap(new_buffer);
|
|
||||||
// Our old self gets destroyed.
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string readAsString(uint32_t len)
|
|
||||||
{
|
|
||||||
std::string str;
|
|
||||||
(void)readAppendToString(str, len);
|
|
||||||
return str;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t readAppendToString(std::string& str, uint32_t len);
|
|
||||||
|
|
||||||
// return number of bytes read
|
|
||||||
uint32_t readEnd()
|
|
||||||
{
|
|
||||||
//This cast should be safe, because buffer_'s size is a uint32_t
|
|
||||||
uint32_t bytes = static_cast<uint32_t>(rBase_ - buffer_);
|
|
||||||
|
|
||||||
if (rBase_ == wBase_)
|
|
||||||
{
|
|
||||||
resetBuffer();
|
|
||||||
}
|
|
||||||
|
|
||||||
return bytes;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return number of bytes written
|
|
||||||
uint32_t writeEnd()
|
|
||||||
{
|
|
||||||
//This cast should be safe, because buffer_'s size is a uint32_t
|
|
||||||
return static_cast<uint32_t>(wBase_ - buffer_);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t available_read() const
|
|
||||||
{
|
|
||||||
// Remember, wBase_ is the real rBound_.
|
|
||||||
return static_cast<uint32_t>(wBase_ - rBase_);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t available_write() const
|
|
||||||
{
|
|
||||||
return static_cast<uint32_t>(wBound_ - wBase_);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns a pointer to where the client can write data to append to
|
|
||||||
// the TMemoryBuffer, and ensures the buffer is big enough to accomodate a
|
|
||||||
// write of the provided length. The returned pointer is very convenient for
|
|
||||||
// passing to read(), recv(), or similar. You must call wroteBytes() as soon
|
|
||||||
// as data is written or the buffer will not be aware that data has changed.
|
|
||||||
uint8_t* getWritePtr(uint32_t len)
|
|
||||||
{
|
|
||||||
ensureCanWrite(len);
|
|
||||||
return wBase_;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Informs the buffer that the client has written 'len' bytes into storage
|
|
||||||
// that had been provided by getWritePtr().
|
|
||||||
void wroteBytes(uint32_t len);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* TVirtualTransport provides a default implementation of readAll().
|
|
||||||
* We want to use the TBufferBase version instead.
|
|
||||||
*/
|
|
||||||
uint32_t readAll(uint8_t* buf, uint32_t len)
|
|
||||||
{
|
|
||||||
return TBufferBase::readAll(buf, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
void swap(TMemoryBuffer& that)
|
|
||||||
{
|
|
||||||
using std::swap;
|
|
||||||
swap(buffer_, that.buffer_);
|
|
||||||
swap(bufferSize_, that.bufferSize_);
|
|
||||||
|
|
||||||
swap(rBase_, that.rBase_);
|
|
||||||
swap(rBound_, that.rBound_);
|
|
||||||
swap(wBase_, that.wBase_);
|
|
||||||
swap(wBound_, that.wBound_);
|
|
||||||
|
|
||||||
swap(owner_, that.owner_);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Make sure there's at least 'len' bytes available for writing.
|
|
||||||
void ensureCanWrite(uint32_t len);
|
|
||||||
|
|
||||||
// Compute the position and available data for reading.
|
|
||||||
void computeRead(uint32_t len, uint8_t** out_start, uint32_t* out_give);
|
|
||||||
|
|
||||||
uint32_t readSlow(uint8_t* buf, uint32_t len);
|
|
||||||
|
|
||||||
void writeSlow(const uint8_t* buf, uint32_t len);
|
|
||||||
|
|
||||||
const uint8_t* borrowSlow(uint8_t* buf, uint32_t* len);
|
|
||||||
|
|
||||||
// Data buffer
|
|
||||||
uint8_t* buffer_;
|
|
||||||
|
|
||||||
// Allocated buffer size
|
|
||||||
uint32_t bufferSize_;
|
|
||||||
|
|
||||||
// Is this object the owner of the buffer?
|
|
||||||
bool owner_;
|
|
||||||
|
|
||||||
// Don't forget to update constrctors, initCommon, and swap if
|
|
||||||
// you add new members.
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} // apache::thrift::transport
|
|
||||||
|
|
||||||
@@ -1,93 +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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#ifdef HAVE_SYS_TIME_H
|
|
||||||
#include <sys/time.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <thrift/transport/TTransport.h>
|
|
||||||
#include <thrift/transport/TVirtualTransport.h>
|
|
||||||
|
|
||||||
namespace apache
|
|
||||||
{
|
|
||||||
namespace thrift
|
|
||||||
{
|
|
||||||
namespace transport
|
|
||||||
{
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Dead-simple wrapper around a file descriptor.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
class TFDTransport : public TVirtualTransport<TFDTransport>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
enum ClosePolicy
|
|
||||||
{
|
|
||||||
NO_CLOSE_ON_DESTROY = 0
|
|
||||||
, CLOSE_ON_DESTROY = 1
|
|
||||||
};
|
|
||||||
|
|
||||||
TFDTransport(int fd, ClosePolicy close_policy = NO_CLOSE_ON_DESTROY)
|
|
||||||
: fd_(fd)
|
|
||||||
, close_policy_(close_policy)
|
|
||||||
{}
|
|
||||||
|
|
||||||
~TFDTransport()
|
|
||||||
{
|
|
||||||
if (close_policy_ == CLOSE_ON_DESTROY)
|
|
||||||
{
|
|
||||||
close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool isOpen()
|
|
||||||
{
|
|
||||||
return fd_ >= 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void open() {}
|
|
||||||
|
|
||||||
void close();
|
|
||||||
|
|
||||||
uint32_t read(uint8_t* buf, uint32_t len);
|
|
||||||
|
|
||||||
void write(const uint8_t* buf, uint32_t len);
|
|
||||||
|
|
||||||
void setFD(int fd)
|
|
||||||
{
|
|
||||||
fd_ = fd;
|
|
||||||
}
|
|
||||||
int getFD()
|
|
||||||
{
|
|
||||||
return fd_;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
int fd_;
|
|
||||||
ClosePolicy close_policy_;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} // apache::thrift::transport
|
|
||||||
|
|
||||||
@@ -1,529 +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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <thrift/transport/TTransport.h>
|
|
||||||
#include <thrift/Thrift.h>
|
|
||||||
#include <thrift/TProcessor.h>
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
#include <boost/scoped_ptr.hpp>
|
|
||||||
#include <boost/shared_ptr.hpp>
|
|
||||||
|
|
||||||
#include <thrift/concurrency/Mutex.h>
|
|
||||||
#include <thrift/concurrency/Monitor.h>
|
|
||||||
#include <thrift/concurrency/PlatformThreadFactory.h>
|
|
||||||
#include <thrift/concurrency/Thread.h>
|
|
||||||
|
|
||||||
namespace apache
|
|
||||||
{
|
|
||||||
namespace thrift
|
|
||||||
{
|
|
||||||
namespace transport
|
|
||||||
{
|
|
||||||
|
|
||||||
using apache::thrift::TProcessor;
|
|
||||||
using apache::thrift::protocol::TProtocolFactory;
|
|
||||||
using apache::thrift::concurrency::Mutex;
|
|
||||||
using apache::thrift::concurrency::Monitor;
|
|
||||||
|
|
||||||
// Data pertaining to a single event
|
|
||||||
typedef struct eventInfo
|
|
||||||
{
|
|
||||||
uint8_t* eventBuff_;
|
|
||||||
uint32_t eventSize_;
|
|
||||||
uint32_t eventBuffPos_;
|
|
||||||
|
|
||||||
eventInfo(): eventBuff_(NULL), eventSize_(0), eventBuffPos_(0) {};
|
|
||||||
~eventInfo()
|
|
||||||
{
|
|
||||||
if (eventBuff_)
|
|
||||||
{
|
|
||||||
delete[] eventBuff_;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} eventInfo;
|
|
||||||
|
|
||||||
// information about current read state
|
|
||||||
typedef struct readState
|
|
||||||
{
|
|
||||||
eventInfo* event_;
|
|
||||||
|
|
||||||
// keep track of event size
|
|
||||||
uint8_t eventSizeBuff_[4];
|
|
||||||
uint8_t eventSizeBuffPos_;
|
|
||||||
bool readingSize_;
|
|
||||||
|
|
||||||
// read buffer variables
|
|
||||||
int32_t bufferPtr_;
|
|
||||||
int32_t bufferLen_;
|
|
||||||
|
|
||||||
// last successful dispatch point
|
|
||||||
int32_t lastDispatchPtr_;
|
|
||||||
|
|
||||||
void resetState(uint32_t lastDispatchPtr)
|
|
||||||
{
|
|
||||||
readingSize_ = true;
|
|
||||||
eventSizeBuffPos_ = 0;
|
|
||||||
lastDispatchPtr_ = lastDispatchPtr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void resetAllValues()
|
|
||||||
{
|
|
||||||
resetState(0);
|
|
||||||
bufferPtr_ = 0;
|
|
||||||
bufferLen_ = 0;
|
|
||||||
|
|
||||||
if (event_)
|
|
||||||
{
|
|
||||||
delete (event_);
|
|
||||||
}
|
|
||||||
|
|
||||||
event_ = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline uint32_t getEventSize()
|
|
||||||
{
|
|
||||||
const void* buffer = reinterpret_cast<const void*>(eventSizeBuff_);
|
|
||||||
return *reinterpret_cast<const uint32_t*>(buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
readState()
|
|
||||||
{
|
|
||||||
event_ = 0;
|
|
||||||
resetAllValues();
|
|
||||||
}
|
|
||||||
|
|
||||||
~readState()
|
|
||||||
{
|
|
||||||
if (event_)
|
|
||||||
{
|
|
||||||
delete (event_);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} readState;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* TFileTransportBuffer - buffer class used by TFileTransport for queueing up events
|
|
||||||
* to be written to disk. Should be used in the following way:
|
|
||||||
* 1) Buffer created
|
|
||||||
* 2) Buffer written to (addEvent)
|
|
||||||
* 3) Buffer read from (getNext)
|
|
||||||
* 4) Buffer reset (reset)
|
|
||||||
* 5) Go back to 2, or destroy buffer
|
|
||||||
*
|
|
||||||
* The buffer should never be written to after it is read from, unless it is reset first.
|
|
||||||
* Note: The above rules are enforced mainly for debugging its sole client TFileTransport
|
|
||||||
* which uses the buffer in this way.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
class TFileTransportBuffer
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
TFileTransportBuffer(uint32_t size);
|
|
||||||
~TFileTransportBuffer();
|
|
||||||
|
|
||||||
bool addEvent(eventInfo* event);
|
|
||||||
eventInfo* getNext();
|
|
||||||
void reset();
|
|
||||||
bool isFull();
|
|
||||||
bool isEmpty();
|
|
||||||
|
|
||||||
private:
|
|
||||||
TFileTransportBuffer(); // should not be used
|
|
||||||
|
|
||||||
enum mode
|
|
||||||
{
|
|
||||||
WRITE,
|
|
||||||
READ
|
|
||||||
};
|
|
||||||
mode bufferMode_;
|
|
||||||
|
|
||||||
uint32_t writePoint_;
|
|
||||||
uint32_t readPoint_;
|
|
||||||
uint32_t size_;
|
|
||||||
eventInfo** buffer_;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Abstract interface for transports used to read files
|
|
||||||
*/
|
|
||||||
class TFileReaderTransport : virtual public TTransport
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
virtual int32_t getReadTimeout() = 0;
|
|
||||||
virtual void setReadTimeout(int32_t readTimeout) = 0;
|
|
||||||
|
|
||||||
virtual uint32_t getNumChunks() = 0;
|
|
||||||
virtual uint32_t getCurChunk() = 0;
|
|
||||||
virtual void seekToChunk(int32_t chunk) = 0;
|
|
||||||
virtual void seekToEnd() = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Abstract interface for transports used to write files
|
|
||||||
*/
|
|
||||||
class TFileWriterTransport : virtual public TTransport
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
virtual uint32_t getChunkSize() = 0;
|
|
||||||
virtual void setChunkSize(uint32_t chunkSize) = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* File implementation of a transport. Reads and writes are done to a
|
|
||||||
* file on disk.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
class TFileTransport : public TFileReaderTransport,
|
|
||||||
public TFileWriterTransport
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
TFileTransport(std::string path, bool readOnly = false);
|
|
||||||
~TFileTransport();
|
|
||||||
|
|
||||||
// TODO: what is the correct behaviour for this?
|
|
||||||
// the log file is generally always open
|
|
||||||
bool isOpen()
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void write(const uint8_t* buf, uint32_t len);
|
|
||||||
void flush();
|
|
||||||
|
|
||||||
uint32_t readAll(uint8_t* buf, uint32_t len);
|
|
||||||
uint32_t read(uint8_t* buf, uint32_t len);
|
|
||||||
bool peek();
|
|
||||||
|
|
||||||
// log-file specific functions
|
|
||||||
void seekToChunk(int32_t chunk);
|
|
||||||
void seekToEnd();
|
|
||||||
uint32_t getNumChunks();
|
|
||||||
uint32_t getCurChunk();
|
|
||||||
|
|
||||||
// for changing the output file
|
|
||||||
void resetOutputFile(int fd, std::string filename, off_t offset);
|
|
||||||
|
|
||||||
// Setter/Getter functions for user-controllable options
|
|
||||||
void setReadBuffSize(uint32_t readBuffSize)
|
|
||||||
{
|
|
||||||
if (readBuffSize)
|
|
||||||
{
|
|
||||||
readBuffSize_ = readBuffSize;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
uint32_t getReadBuffSize()
|
|
||||||
{
|
|
||||||
return readBuffSize_;
|
|
||||||
}
|
|
||||||
|
|
||||||
static const int32_t TAIL_READ_TIMEOUT = -1;
|
|
||||||
static const int32_t NO_TAIL_READ_TIMEOUT = 0;
|
|
||||||
void setReadTimeout(int32_t readTimeout)
|
|
||||||
{
|
|
||||||
readTimeout_ = readTimeout;
|
|
||||||
}
|
|
||||||
int32_t getReadTimeout()
|
|
||||||
{
|
|
||||||
return readTimeout_;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setChunkSize(uint32_t chunkSize)
|
|
||||||
{
|
|
||||||
if (chunkSize)
|
|
||||||
{
|
|
||||||
chunkSize_ = chunkSize;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
uint32_t getChunkSize()
|
|
||||||
{
|
|
||||||
return chunkSize_;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setEventBufferSize(uint32_t bufferSize)
|
|
||||||
{
|
|
||||||
if (bufferAndThreadInitialized_)
|
|
||||||
{
|
|
||||||
GlobalOutput("Cannot change the buffer size after writer thread started");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
eventBufferSize_ = bufferSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t getEventBufferSize()
|
|
||||||
{
|
|
||||||
return eventBufferSize_;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setFlushMaxUs(uint32_t flushMaxUs)
|
|
||||||
{
|
|
||||||
if (flushMaxUs)
|
|
||||||
{
|
|
||||||
flushMaxUs_ = flushMaxUs;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
uint32_t getFlushMaxUs()
|
|
||||||
{
|
|
||||||
return flushMaxUs_;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setFlushMaxBytes(uint32_t flushMaxBytes)
|
|
||||||
{
|
|
||||||
if (flushMaxBytes)
|
|
||||||
{
|
|
||||||
flushMaxBytes_ = flushMaxBytes;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
uint32_t getFlushMaxBytes()
|
|
||||||
{
|
|
||||||
return flushMaxBytes_;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setMaxEventSize(uint32_t maxEventSize)
|
|
||||||
{
|
|
||||||
maxEventSize_ = maxEventSize;
|
|
||||||
}
|
|
||||||
uint32_t getMaxEventSize()
|
|
||||||
{
|
|
||||||
return maxEventSize_;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setMaxCorruptedEvents(uint32_t maxCorruptedEvents)
|
|
||||||
{
|
|
||||||
maxCorruptedEvents_ = maxCorruptedEvents;
|
|
||||||
}
|
|
||||||
uint32_t getMaxCorruptedEvents()
|
|
||||||
{
|
|
||||||
return maxCorruptedEvents_;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setEofSleepTimeUs(uint32_t eofSleepTime)
|
|
||||||
{
|
|
||||||
if (eofSleepTime)
|
|
||||||
{
|
|
||||||
eofSleepTime_ = eofSleepTime;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
uint32_t getEofSleepTimeUs()
|
|
||||||
{
|
|
||||||
return eofSleepTime_;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Override TTransport *_virt() functions to invoke our implementations.
|
|
||||||
* We cannot use TVirtualTransport to provide these, since we need to inherit
|
|
||||||
* virtually from TTransport.
|
|
||||||
*/
|
|
||||||
virtual uint32_t read_virt(uint8_t* buf, uint32_t len)
|
|
||||||
{
|
|
||||||
return this->read(buf, len);
|
|
||||||
}
|
|
||||||
virtual uint32_t readAll_virt(uint8_t* buf, uint32_t len)
|
|
||||||
{
|
|
||||||
return this->readAll(buf, len);
|
|
||||||
}
|
|
||||||
virtual void write_virt(const uint8_t* buf, uint32_t len)
|
|
||||||
{
|
|
||||||
this->write(buf, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
// helper functions for writing to a file
|
|
||||||
void enqueueEvent(const uint8_t* buf, uint32_t eventLen);
|
|
||||||
bool swapEventBuffers(struct timeval* deadline);
|
|
||||||
bool initBufferAndWriteThread();
|
|
||||||
|
|
||||||
// control for writer thread
|
|
||||||
static void* startWriterThread(void* ptr)
|
|
||||||
{
|
|
||||||
static_cast<TFileTransport*>(ptr)->writerThread();
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
void writerThread();
|
|
||||||
|
|
||||||
// helper functions for reading from a file
|
|
||||||
eventInfo* readEvent();
|
|
||||||
|
|
||||||
// event corruption-related functions
|
|
||||||
bool isEventCorrupted();
|
|
||||||
void performRecovery();
|
|
||||||
|
|
||||||
// Utility functions
|
|
||||||
void openLogFile();
|
|
||||||
void getNextFlushTime(struct timeval* ts_next_flush);
|
|
||||||
|
|
||||||
// Class variables
|
|
||||||
readState readState_;
|
|
||||||
uint8_t* readBuff_;
|
|
||||||
eventInfo* currentEvent_;
|
|
||||||
|
|
||||||
uint32_t readBuffSize_;
|
|
||||||
static const uint32_t DEFAULT_READ_BUFF_SIZE = 1 * 1024 * 1024;
|
|
||||||
|
|
||||||
int32_t readTimeout_;
|
|
||||||
static const int32_t DEFAULT_READ_TIMEOUT_MS = 200;
|
|
||||||
|
|
||||||
// size of chunks that file will be split up into
|
|
||||||
uint32_t chunkSize_;
|
|
||||||
static const uint32_t DEFAULT_CHUNK_SIZE = 16 * 1024 * 1024;
|
|
||||||
|
|
||||||
// size of event buffers
|
|
||||||
uint32_t eventBufferSize_;
|
|
||||||
static const uint32_t DEFAULT_EVENT_BUFFER_SIZE = 10000;
|
|
||||||
|
|
||||||
// max number of microseconds that can pass without flushing
|
|
||||||
uint32_t flushMaxUs_;
|
|
||||||
static const uint32_t DEFAULT_FLUSH_MAX_US = 3000000;
|
|
||||||
|
|
||||||
// max number of bytes that can be written without flushing
|
|
||||||
uint32_t flushMaxBytes_;
|
|
||||||
static const uint32_t DEFAULT_FLUSH_MAX_BYTES = 1000 * 1024;
|
|
||||||
|
|
||||||
// max event size
|
|
||||||
uint32_t maxEventSize_;
|
|
||||||
static const uint32_t DEFAULT_MAX_EVENT_SIZE = 0;
|
|
||||||
|
|
||||||
// max number of corrupted events per chunk
|
|
||||||
uint32_t maxCorruptedEvents_;
|
|
||||||
static const uint32_t DEFAULT_MAX_CORRUPTED_EVENTS = 0;
|
|
||||||
|
|
||||||
// sleep duration when EOF is hit
|
|
||||||
uint32_t eofSleepTime_;
|
|
||||||
static const uint32_t DEFAULT_EOF_SLEEP_TIME_US = 500 * 1000;
|
|
||||||
|
|
||||||
// sleep duration when a corrupted event is encountered
|
|
||||||
uint32_t corruptedEventSleepTime_;
|
|
||||||
static const uint32_t DEFAULT_CORRUPTED_SLEEP_TIME_US = 1 * 1000 * 1000;
|
|
||||||
|
|
||||||
// sleep duration in seconds when an IO error is encountered in the writer thread
|
|
||||||
uint32_t writerThreadIOErrorSleepTime_;
|
|
||||||
static const uint32_t DEFAULT_WRITER_THREAD_SLEEP_TIME_US = 60 * 1000 * 1000;
|
|
||||||
|
|
||||||
// writer thread
|
|
||||||
apache::thrift::concurrency::PlatformThreadFactory threadFactory_;
|
|
||||||
boost::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.
|
|
||||||
TFileTransportBuffer* dequeueBuffer_;
|
|
||||||
TFileTransportBuffer* enqueueBuffer_;
|
|
||||||
|
|
||||||
// conditions used to block when the buffer is full or empty
|
|
||||||
Monitor notFull_, notEmpty_;
|
|
||||||
volatile bool closing_;
|
|
||||||
|
|
||||||
// To keep track of whether the buffer has been flushed
|
|
||||||
Monitor flushed_;
|
|
||||||
volatile bool forceFlush_;
|
|
||||||
|
|
||||||
// Mutex that is grabbed when enqueueing and swapping the read/write buffers
|
|
||||||
Mutex mutex_;
|
|
||||||
|
|
||||||
// File information
|
|
||||||
std::string filename_;
|
|
||||||
int fd_;
|
|
||||||
|
|
||||||
// Whether the writer thread and buffers have been initialized
|
|
||||||
bool bufferAndThreadInitialized_;
|
|
||||||
|
|
||||||
// Offset within the file
|
|
||||||
off_t offset_;
|
|
||||||
|
|
||||||
// event corruption information
|
|
||||||
uint32_t lastBadChunk_;
|
|
||||||
uint32_t numCorruptedEventsInChunk_;
|
|
||||||
|
|
||||||
bool readOnly_;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Exception thrown when EOF is hit
|
|
||||||
class TEOFException : public TTransportException
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
TEOFException():
|
|
||||||
TTransportException(TTransportException::END_OF_FILE) {};
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
// wrapper class to process events from a file containing thrift events
|
|
||||||
class TFileProcessor
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
/**
|
|
||||||
* Constructor that defaults output transport to null transport
|
|
||||||
*
|
|
||||||
* @param processor processes log-file events
|
|
||||||
* @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(boost::shared_ptr<TProcessor> processor,
|
|
||||||
boost::shared_ptr<TProtocolFactory> inputProtocolFactory,
|
|
||||||
boost::shared_ptr<TProtocolFactory> outputProtocolFactory,
|
|
||||||
boost::shared_ptr<TFileReaderTransport> inputTransport);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor
|
|
||||||
*
|
|
||||||
* @param processor processes log-file events
|
|
||||||
* @param protocolFactory protocol factory
|
|
||||||
* @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);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* processes events from the file
|
|
||||||
*
|
|
||||||
* @param numEvents number of events to process (0 for unlimited)
|
|
||||||
* @param tail tails the file if true
|
|
||||||
*/
|
|
||||||
void process(uint32_t numEvents, bool tail);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* process events until the end of the chunk
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
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_;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} // apache::thrift::transport
|
|
||||||
|
|
||||||
@@ -1,55 +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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <thrift/transport/THttpTransport.h>
|
|
||||||
|
|
||||||
namespace apache
|
|
||||||
{
|
|
||||||
namespace thrift
|
|
||||||
{
|
|
||||||
namespace transport
|
|
||||||
{
|
|
||||||
|
|
||||||
class THttpClient : public THttpTransport
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
THttpClient(boost::shared_ptr<TTransport> transport, std::string host, std::string path = "");
|
|
||||||
|
|
||||||
THttpClient(std::string host, int port, std::string path = "");
|
|
||||||
|
|
||||||
virtual ~THttpClient();
|
|
||||||
|
|
||||||
virtual void flush();
|
|
||||||
|
|
||||||
protected:
|
|
||||||
|
|
||||||
std::string host_;
|
|
||||||
std::string path_;
|
|
||||||
|
|
||||||
virtual void parseHeader(char* header);
|
|
||||||
virtual bool parseStatusLine(char* status);
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} // apache::thrift::transport
|
|
||||||
|
|
||||||
@@ -1,72 +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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <thrift/transport/THttpTransport.h>
|
|
||||||
|
|
||||||
namespace apache
|
|
||||||
{
|
|
||||||
namespace thrift
|
|
||||||
{
|
|
||||||
namespace transport
|
|
||||||
{
|
|
||||||
|
|
||||||
class THttpServer : public THttpTransport
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
THttpServer(boost::shared_ptr<TTransport> transport);
|
|
||||||
|
|
||||||
virtual ~THttpServer();
|
|
||||||
|
|
||||||
virtual void flush();
|
|
||||||
|
|
||||||
protected:
|
|
||||||
|
|
||||||
void readHeaders();
|
|
||||||
virtual void parseHeader(char* header);
|
|
||||||
virtual bool parseStatusLine(char* status);
|
|
||||||
std::string getTimeRFC1123();
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Wraps a transport into HTTP protocol
|
|
||||||
*/
|
|
||||||
class THttpServerTransportFactory : public TTransportFactory
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
THttpServerTransportFactory() {}
|
|
||||||
|
|
||||||
virtual ~THttpServerTransportFactory() {}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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));
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} // apache::thrift::transport
|
|
||||||
|
|
||||||
@@ -1,117 +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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <thrift/transport/TBufferTransports.h>
|
|
||||||
#include <thrift/transport/TVirtualTransport.h>
|
|
||||||
|
|
||||||
namespace apache
|
|
||||||
{
|
|
||||||
namespace thrift
|
|
||||||
{
|
|
||||||
namespace transport
|
|
||||||
{
|
|
||||||
|
|
||||||
/**
|
|
||||||
* HTTP implementation of the thrift transport. This was irritating
|
|
||||||
* to write, but the alternatives in C++ land are daunting. Linking CURL
|
|
||||||
* requires 23 dynamic libraries last time I checked (WTF?!?). All we have
|
|
||||||
* here is a VERY basic HTTP/1.1 client which supports HTTP 100 Continue,
|
|
||||||
* chunked transfer encoding, keepalive, etc. Tested against Apache.
|
|
||||||
*/
|
|
||||||
class THttpTransport : public TVirtualTransport<THttpTransport>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
THttpTransport(boost::shared_ptr<TTransport> transport);
|
|
||||||
|
|
||||||
virtual ~THttpTransport();
|
|
||||||
|
|
||||||
void open()
|
|
||||||
{
|
|
||||||
transport_->open();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool isOpen()
|
|
||||||
{
|
|
||||||
return transport_->isOpen();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool peek()
|
|
||||||
{
|
|
||||||
return transport_->peek();
|
|
||||||
}
|
|
||||||
|
|
||||||
void close()
|
|
||||||
{
|
|
||||||
transport_->close();
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t read(uint8_t* buf, uint32_t len);
|
|
||||||
|
|
||||||
uint32_t readEnd();
|
|
||||||
|
|
||||||
void write(const uint8_t* buf, uint32_t len);
|
|
||||||
|
|
||||||
virtual void flush() = 0;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
|
|
||||||
boost::shared_ptr<TTransport> transport_;
|
|
||||||
|
|
||||||
TMemoryBuffer writeBuffer_;
|
|
||||||
TMemoryBuffer readBuffer_;
|
|
||||||
|
|
||||||
bool readHeaders_;
|
|
||||||
bool chunked_;
|
|
||||||
bool chunkedDone_;
|
|
||||||
uint32_t chunkSize_;
|
|
||||||
uint32_t contentLength_;
|
|
||||||
|
|
||||||
char* httpBuf_;
|
|
||||||
uint32_t httpPos_;
|
|
||||||
uint32_t httpBufLen_;
|
|
||||||
uint32_t httpBufSize_;
|
|
||||||
|
|
||||||
virtual void init();
|
|
||||||
|
|
||||||
uint32_t readMoreData();
|
|
||||||
char* readLine();
|
|
||||||
|
|
||||||
void readHeaders();
|
|
||||||
virtual void parseHeader(char* header) = 0;
|
|
||||||
virtual bool parseStatusLine(char* status) = 0;
|
|
||||||
|
|
||||||
uint32_t readChunked();
|
|
||||||
void readChunkedFooters();
|
|
||||||
uint32_t parseChunkSize(char* line);
|
|
||||||
|
|
||||||
uint32_t readContent(uint32_t size);
|
|
||||||
|
|
||||||
void refill();
|
|
||||||
void shift();
|
|
||||||
|
|
||||||
static const char* CRLF;
|
|
||||||
static const int CRLF_LEN;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} // apache::thrift::transport
|
|
||||||
|
|
||||||
@@ -1,102 +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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <thrift/transport/TTransport.h>
|
|
||||||
#include <thrift/transport/TVirtualTransport.h>
|
|
||||||
#ifndef _WIN32
|
|
||||||
# include <thrift/transport/TSocket.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace apache
|
|
||||||
{
|
|
||||||
namespace thrift
|
|
||||||
{
|
|
||||||
namespace transport
|
|
||||||
{
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Windows Pipes implementation of the TTransport interface.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
#ifdef _WIN32
|
|
||||||
class TPipe : public TVirtualTransport<TPipe>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
// Constructs a new pipe object.
|
|
||||||
TPipe();
|
|
||||||
// Named pipe constructors -
|
|
||||||
explicit TPipe(HANDLE Pipe); //HANDLE is a void*
|
|
||||||
//need a const char * overload so string literals don't go to the HANDLE overload
|
|
||||||
explicit TPipe(const char* pipename);
|
|
||||||
explicit TPipe(const std::string& pipename);
|
|
||||||
// Anonymous pipe -
|
|
||||||
TPipe(HANDLE PipeRd, HANDLE PipeWrt);
|
|
||||||
|
|
||||||
// Destroys the pipe object, closing it if necessary.
|
|
||||||
virtual ~TPipe();
|
|
||||||
|
|
||||||
// Returns whether the pipe is open & valid.
|
|
||||||
virtual bool isOpen();
|
|
||||||
|
|
||||||
// Checks whether more data is available in the pipe.
|
|
||||||
virtual bool peek();
|
|
||||||
|
|
||||||
// Creates and opens the named/anonymous pipe.
|
|
||||||
virtual void open();
|
|
||||||
|
|
||||||
// Shuts down communications on the pipe.
|
|
||||||
virtual void close();
|
|
||||||
|
|
||||||
// Reads from the pipe.
|
|
||||||
virtual uint32_t read(uint8_t* buf, uint32_t len);
|
|
||||||
|
|
||||||
// Writes to the pipe.
|
|
||||||
virtual void write(const uint8_t* buf, uint32_t len);
|
|
||||||
|
|
||||||
|
|
||||||
//Accessors
|
|
||||||
std::string getPipename();
|
|
||||||
void setPipename(const std::string& pipename);
|
|
||||||
HANDLE getPipeHandle(); //doubles as the read handle for anon pipe
|
|
||||||
void setPipeHandle(HANDLE pipehandle);
|
|
||||||
HANDLE getWrtPipeHandle();
|
|
||||||
void setWrtPipeHandle(HANDLE pipehandle);
|
|
||||||
long getConnectTimeout();
|
|
||||||
void setConnectTimeout(long seconds);
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::string pipename_;
|
|
||||||
|
|
||||||
//Named pipe handles are R/W, while anonymous pipes are one or the other (half duplex).
|
|
||||||
HANDLE Pipe_, PipeWrt_;
|
|
||||||
long TimeoutSeconds_;
|
|
||||||
bool isAnonymous;
|
|
||||||
};
|
|
||||||
#else
|
|
||||||
typedef TSocket TPipe;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} // apache::thrift::transport
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,99 +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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <thrift/transport/TServerTransport.h>
|
|
||||||
#include <boost/shared_ptr.hpp>
|
|
||||||
#ifndef _WIN32
|
|
||||||
# include "TServerSocket.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define TPIPE_SERVER_MAX_CONNS_DEFAULT 10
|
|
||||||
|
|
||||||
namespace apache
|
|
||||||
{
|
|
||||||
namespace thrift
|
|
||||||
{
|
|
||||||
namespace transport
|
|
||||||
{
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Windows Pipes implementation of TServerTransport.
|
|
||||||
*/
|
|
||||||
#ifdef _WIN32
|
|
||||||
class TPipeServer : public TServerTransport
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
//Constructors
|
|
||||||
// Named Pipe -
|
|
||||||
TPipeServer(const std::string& pipename, uint32_t bufsize);
|
|
||||||
TPipeServer(const std::string& pipename, uint32_t bufsize, uint32_t maxconnections);
|
|
||||||
TPipeServer(const std::string& pipename);
|
|
||||||
// Anonymous pipe -
|
|
||||||
TPipeServer(int bufsize);
|
|
||||||
TPipeServer();
|
|
||||||
|
|
||||||
//Destructor
|
|
||||||
~TPipeServer();
|
|
||||||
|
|
||||||
//Standard transport callbacks
|
|
||||||
void interrupt();
|
|
||||||
void close();
|
|
||||||
protected:
|
|
||||||
boost::shared_ptr<TTransport> acceptImpl();
|
|
||||||
|
|
||||||
bool TCreateNamedPipe();
|
|
||||||
bool TCreateAnonPipe();
|
|
||||||
void createWakeupEvent();
|
|
||||||
|
|
||||||
public:
|
|
||||||
//Accessors
|
|
||||||
std::string getPipename();
|
|
||||||
void setPipename(const std::string& pipename);
|
|
||||||
int getBufferSize();
|
|
||||||
void setBufferSize(int bufsize);
|
|
||||||
HANDLE getPipeHandle(); //Named Pipe R/W -or- Anonymous pipe Read handle
|
|
||||||
HANDLE getWrtPipeHandle();
|
|
||||||
HANDLE getClientRdPipeHandle();
|
|
||||||
HANDLE getClientWrtPipeHandle();
|
|
||||||
bool getAnonymous();
|
|
||||||
void setAnonymous(bool anon);
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::string pipename_;
|
|
||||||
uint32_t bufsize_;
|
|
||||||
HANDLE Pipe_; //Named Pipe (R/W) or Anonymous Pipe (R)
|
|
||||||
uint32_t maxconns_;
|
|
||||||
HANDLE PipeW_; //Anonymous Pipe (W)
|
|
||||||
HANDLE ClientAnonRead, ClientAnonWrite; //Client side anonymous pipe handles
|
|
||||||
HANDLE wakeup; // wake up event
|
|
||||||
//? Do we need duplicates to send to client?
|
|
||||||
bool isAnonymous;
|
|
||||||
bool stop_; // stop flag
|
|
||||||
};
|
|
||||||
#else //_WIN32
|
|
||||||
//*NIX named pipe implementation uses domain socket
|
|
||||||
typedef TServerSocket TPipeServer;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} // apache::thrift::transport
|
|
||||||
|
|
||||||
@@ -1,65 +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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <boost/shared_ptr.hpp>
|
|
||||||
#include <thrift/transport/TServerSocket.h>
|
|
||||||
|
|
||||||
namespace apache
|
|
||||||
{
|
|
||||||
namespace thrift
|
|
||||||
{
|
|
||||||
namespace transport
|
|
||||||
{
|
|
||||||
|
|
||||||
class TSSLSocketFactory;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Server socket that accepts SSL connections.
|
|
||||||
*/
|
|
||||||
class TSSLServerSocket: public TServerSocket
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
/**
|
|
||||||
* Constructor.
|
|
||||||
*
|
|
||||||
* @param port Listening port
|
|
||||||
* @param factory SSL socket factory implementation
|
|
||||||
*/
|
|
||||||
TSSLServerSocket(int port, boost::shared_ptr<TSSLSocketFactory> factory);
|
|
||||||
/**
|
|
||||||
* Constructor.
|
|
||||||
*
|
|
||||||
* @param port Listening port
|
|
||||||
* @param sendTimeout Socket send timeout
|
|
||||||
* @param recvTimeout Socket receive timeout
|
|
||||||
* @param factory SSL socket factory implementation
|
|
||||||
*/
|
|
||||||
TSSLServerSocket(int port, int sendTimeout, int recvTimeout,
|
|
||||||
boost::shared_ptr<TSSLSocketFactory> factory);
|
|
||||||
protected:
|
|
||||||
boost::shared_ptr<TSocket> createSocket(int socket);
|
|
||||||
boost::shared_ptr<TSSLSocketFactory> factory_;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,357 +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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include <boost/shared_ptr.hpp>
|
|
||||||
#include <openssl/ssl.h>
|
|
||||||
#include <thrift/concurrency/Mutex.h>
|
|
||||||
#include <thrift/transport/TSocket.h>
|
|
||||||
|
|
||||||
namespace apache
|
|
||||||
{
|
|
||||||
namespace thrift
|
|
||||||
{
|
|
||||||
namespace transport
|
|
||||||
{
|
|
||||||
|
|
||||||
class AccessManager;
|
|
||||||
class SSLContext;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* OpenSSL implementation for SSL socket interface.
|
|
||||||
*/
|
|
||||||
class TSSLSocket: public TSocket
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
~TSSLSocket();
|
|
||||||
/**
|
|
||||||
* TTransport interface.
|
|
||||||
*/
|
|
||||||
bool isOpen();
|
|
||||||
bool peek();
|
|
||||||
void open();
|
|
||||||
void close();
|
|
||||||
uint32_t read(uint8_t* buf, uint32_t len);
|
|
||||||
void write(const uint8_t* buf, uint32_t len);
|
|
||||||
void flush();
|
|
||||||
/**
|
|
||||||
* Set whether to use client or server side SSL handshake protocol.
|
|
||||||
*
|
|
||||||
* @param flag Use server side handshake protocol if true.
|
|
||||||
*/
|
|
||||||
void server(bool flag)
|
|
||||||
{
|
|
||||||
server_ = flag;
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Determine whether the SSL socket is server or client mode.
|
|
||||||
*/
|
|
||||||
bool server() const
|
|
||||||
{
|
|
||||||
return server_;
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Set AccessManager.
|
|
||||||
*
|
|
||||||
* @param manager Instance of AccessManager
|
|
||||||
*/
|
|
||||||
virtual void access(boost::shared_ptr<AccessManager> manager)
|
|
||||||
{
|
|
||||||
access_ = manager;
|
|
||||||
}
|
|
||||||
protected:
|
|
||||||
/**
|
|
||||||
* Constructor.
|
|
||||||
*/
|
|
||||||
TSSLSocket(boost::shared_ptr<SSLContext> ctx);
|
|
||||||
/**
|
|
||||||
* Constructor, create an instance of TSSLSocket given an existing socket.
|
|
||||||
*
|
|
||||||
* @param socket An existing socket
|
|
||||||
*/
|
|
||||||
TSSLSocket(boost::shared_ptr<SSLContext> ctx, int socket);
|
|
||||||
/**
|
|
||||||
* Constructor.
|
|
||||||
*
|
|
||||||
* @param host Remote host name
|
|
||||||
* @param port Remote port number
|
|
||||||
*/
|
|
||||||
TSSLSocket(boost::shared_ptr<SSLContext> ctx,
|
|
||||||
std::string host,
|
|
||||||
int port);
|
|
||||||
/**
|
|
||||||
* Authorize peer access after SSL handshake completes.
|
|
||||||
*/
|
|
||||||
virtual void authorize();
|
|
||||||
/**
|
|
||||||
* Initiate SSL handshake if not already initiated.
|
|
||||||
*/
|
|
||||||
void checkHandshake();
|
|
||||||
|
|
||||||
bool server_;
|
|
||||||
SSL* ssl_;
|
|
||||||
boost::shared_ptr<SSLContext> ctx_;
|
|
||||||
boost::shared_ptr<AccessManager> access_;
|
|
||||||
friend class TSSLSocketFactory;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* SSL socket factory. SSL sockets should be created via SSL factory.
|
|
||||||
*/
|
|
||||||
class TSSLSocketFactory
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
/**
|
|
||||||
* Constructor/Destructor
|
|
||||||
*/
|
|
||||||
TSSLSocketFactory();
|
|
||||||
virtual ~TSSLSocketFactory();
|
|
||||||
/**
|
|
||||||
* Create an instance of TSSLSocket with a fresh new socket.
|
|
||||||
*/
|
|
||||||
virtual boost::shared_ptr<TSSLSocket> createSocket();
|
|
||||||
/**
|
|
||||||
* Create an instance of TSSLSocket with the given socket.
|
|
||||||
*
|
|
||||||
* @param socket An existing socket.
|
|
||||||
*/
|
|
||||||
virtual boost::shared_ptr<TSSLSocket> createSocket(int socket);
|
|
||||||
/**
|
|
||||||
* 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);
|
|
||||||
/**
|
|
||||||
* Set ciphers to be used in SSL handshake process.
|
|
||||||
*
|
|
||||||
* @param ciphers A list of ciphers
|
|
||||||
*/
|
|
||||||
virtual void ciphers(const std::string& enable);
|
|
||||||
/**
|
|
||||||
* Enable/Disable authentication.
|
|
||||||
*
|
|
||||||
* @param required Require peer to present valid certificate if true
|
|
||||||
*/
|
|
||||||
virtual void authenticate(bool required);
|
|
||||||
/**
|
|
||||||
* Load server certificate.
|
|
||||||
*
|
|
||||||
* @param path Path to the certificate file
|
|
||||||
* @param format Certificate file format
|
|
||||||
*/
|
|
||||||
virtual void loadCertificate(const char* path, const char* format = "PEM");
|
|
||||||
/**
|
|
||||||
* Load private key.
|
|
||||||
*
|
|
||||||
* @param path Path to the private key file
|
|
||||||
* @param format Private key file format
|
|
||||||
*/
|
|
||||||
virtual void loadPrivateKey(const char* path, const char* format = "PEM");
|
|
||||||
/**
|
|
||||||
* Load trusted certificates from specified file.
|
|
||||||
*
|
|
||||||
* @param path Path to trusted certificate file
|
|
||||||
*/
|
|
||||||
virtual void loadTrustedCertificates(const char* path);
|
|
||||||
/**
|
|
||||||
* Default randomize method.
|
|
||||||
*/
|
|
||||||
virtual void randomize();
|
|
||||||
/**
|
|
||||||
* Override default OpenSSL password callback with getPassword().
|
|
||||||
*/
|
|
||||||
void overrideDefaultPasswordCallback();
|
|
||||||
/**
|
|
||||||
* Set/Unset server mode.
|
|
||||||
*
|
|
||||||
* @param flag Server mode if true
|
|
||||||
*/
|
|
||||||
virtual void server(bool flag)
|
|
||||||
{
|
|
||||||
server_ = flag;
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Determine whether the socket is in server or client mode.
|
|
||||||
*
|
|
||||||
* @return true, if server mode, or, false, if client mode
|
|
||||||
*/
|
|
||||||
virtual bool server() const
|
|
||||||
{
|
|
||||||
return server_;
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Set AccessManager.
|
|
||||||
*
|
|
||||||
* @param manager The AccessManager instance
|
|
||||||
*/
|
|
||||||
virtual void access(boost::shared_ptr<AccessManager> manager)
|
|
||||||
{
|
|
||||||
access_ = manager;
|
|
||||||
}
|
|
||||||
protected:
|
|
||||||
boost::shared_ptr<SSLContext> ctx_;
|
|
||||||
|
|
||||||
static void initializeOpenSSL();
|
|
||||||
static void cleanupOpenSSL();
|
|
||||||
/**
|
|
||||||
* Override this method for custom password callback. It may be called
|
|
||||||
* multiple times at any time during a session as necessary.
|
|
||||||
*
|
|
||||||
* @param password Pass collected password to OpenSSL
|
|
||||||
* @param size Maximum length of password including NULL character
|
|
||||||
*/
|
|
||||||
virtual void getPassword(std::string& /* password */, int /* size */) {}
|
|
||||||
private:
|
|
||||||
bool server_;
|
|
||||||
boost::shared_ptr<AccessManager> access_;
|
|
||||||
static bool initialized;
|
|
||||||
static concurrency::Mutex mutex_;
|
|
||||||
static uint64_t count_;
|
|
||||||
void setup(boost::shared_ptr<TSSLSocket> ssl);
|
|
||||||
static int passwordCallback(char* password, int size, int, void* data);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* SSL exception.
|
|
||||||
*/
|
|
||||||
class TSSLException: public TTransportException
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
TSSLException(const std::string& message):
|
|
||||||
TTransportException(TTransportException::INTERNAL_ERROR, message) {}
|
|
||||||
|
|
||||||
virtual const char* what() const throw()
|
|
||||||
{
|
|
||||||
if (message_.empty())
|
|
||||||
{
|
|
||||||
return "TSSLException";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return message_.c_str();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Wrap OpenSSL SSL_CTX into a class.
|
|
||||||
*/
|
|
||||||
class SSLContext
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
SSLContext();
|
|
||||||
virtual ~SSLContext();
|
|
||||||
SSL* createSSL();
|
|
||||||
SSL_CTX* get()
|
|
||||||
{
|
|
||||||
return ctx_;
|
|
||||||
}
|
|
||||||
private:
|
|
||||||
SSL_CTX* ctx_;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Callback interface for access control. It's meant to verify the remote host.
|
|
||||||
* It's constructed when application starts and set to TSSLSocketFactory
|
|
||||||
* instance. It's passed onto all TSSLSocket instances created by this factory
|
|
||||||
* object.
|
|
||||||
*/
|
|
||||||
class AccessManager
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
enum Decision
|
|
||||||
{
|
|
||||||
DENY = -1, // deny access
|
|
||||||
SKIP = 0, // cannot make decision, move on to next (if any)
|
|
||||||
ALLOW = 1 // allow access
|
|
||||||
};
|
|
||||||
/**
|
|
||||||
* Destructor
|
|
||||||
*/
|
|
||||||
virtual ~AccessManager() {}
|
|
||||||
/**
|
|
||||||
* Determine whether the peer should be granted access or not. It's called
|
|
||||||
* once after the SSL handshake completes successfully, before peer certificate
|
|
||||||
* is examined.
|
|
||||||
*
|
|
||||||
* If a valid decision (ALLOW or DENY) is returned, the peer certificate is
|
|
||||||
* not to be verified.
|
|
||||||
*
|
|
||||||
* @param sa Peer IP address
|
|
||||||
* @return True if the peer is trusted, false otherwise
|
|
||||||
*/
|
|
||||||
virtual Decision verify(const sockaddr_storage& /* sa */ ) throw()
|
|
||||||
{
|
|
||||||
return DENY;
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Determine whether the peer should be granted access or not. It's called
|
|
||||||
* every time a DNS subjectAltName/common name is extracted from peer's
|
|
||||||
* certificate.
|
|
||||||
*
|
|
||||||
* @param host Client mode: host name returned by TSocket::getHost()
|
|
||||||
* Server mode: host name returned by TSocket::getPeerHost()
|
|
||||||
* @param name SubjectAltName or common name extracted from peer certificate
|
|
||||||
* @param size Length of name
|
|
||||||
* @return True if the peer is trusted, false otherwise
|
|
||||||
*
|
|
||||||
* Note: The "name" parameter may be UTF8 encoded.
|
|
||||||
*/
|
|
||||||
virtual Decision verify(const std::string& /* host */, const char* /* name */, int /* size */)
|
|
||||||
throw()
|
|
||||||
{
|
|
||||||
return DENY;
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Determine whether the peer should be granted access or not. It's called
|
|
||||||
* every time an IP subjectAltName is extracted from peer's certificate.
|
|
||||||
*
|
|
||||||
* @param sa Peer IP address retrieved from the underlying socket
|
|
||||||
* @param data IP address extracted from certificate
|
|
||||||
* @param size Length of the IP address
|
|
||||||
* @return True if the peer is trusted, false otherwise
|
|
||||||
*/
|
|
||||||
virtual Decision verify(const sockaddr_storage& /* sa */, const char* /* data */, int /* size */)
|
|
||||||
throw()
|
|
||||||
{
|
|
||||||
return DENY;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef AccessManager::Decision Decision;
|
|
||||||
|
|
||||||
class DefaultClientAccessManager: public AccessManager
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
// AccessManager interface
|
|
||||||
Decision verify(const sockaddr_storage& sa) throw();
|
|
||||||
Decision verify(const std::string& host, const char* name, int size) throw();
|
|
||||||
Decision verify(const sockaddr_storage& sa, const char* data, int size) throw();
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,609 +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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <thrift/thrift-config.h>
|
|
||||||
|
|
||||||
#include <cstring>
|
|
||||||
#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/TServerSocket.h>
|
|
||||||
#include <thrift/transport/PlatformSocket.h>
|
|
||||||
#include <boost/shared_ptr.hpp>
|
|
||||||
|
|
||||||
#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 namespace std;
|
|
||||||
using boost::shared_ptr;
|
|
||||||
|
|
||||||
TServerSocket::TServerSocket(int port) :
|
|
||||||
port_(port),
|
|
||||||
serverSocket_(THRIFT_INVALID_SOCKET),
|
|
||||||
acceptBacklog_(DEFAULT_BACKLOG),
|
|
||||||
sendTimeout_(0),
|
|
||||||
recvTimeout_(0),
|
|
||||||
accTimeout_(-1),
|
|
||||||
retryLimit_(0),
|
|
||||||
retryDelay_(0),
|
|
||||||
tcpSendBuffer_(0),
|
|
||||||
tcpRecvBuffer_(0),
|
|
||||||
intSock1_(THRIFT_INVALID_SOCKET),
|
|
||||||
intSock2_(THRIFT_INVALID_SOCKET) {}
|
|
||||||
|
|
||||||
TServerSocket::TServerSocket(int port, int sendTimeout, int recvTimeout) :
|
|
||||||
port_(port),
|
|
||||||
serverSocket_(THRIFT_INVALID_SOCKET),
|
|
||||||
acceptBacklog_(DEFAULT_BACKLOG),
|
|
||||||
sendTimeout_(sendTimeout),
|
|
||||||
recvTimeout_(recvTimeout),
|
|
||||||
accTimeout_(-1),
|
|
||||||
retryLimit_(0),
|
|
||||||
retryDelay_(0),
|
|
||||||
tcpSendBuffer_(0),
|
|
||||||
tcpRecvBuffer_(0),
|
|
||||||
intSock1_(THRIFT_INVALID_SOCKET),
|
|
||||||
intSock2_(THRIFT_INVALID_SOCKET) {}
|
|
||||||
|
|
||||||
TServerSocket::TServerSocket(string path) :
|
|
||||||
port_(0),
|
|
||||||
path_(path),
|
|
||||||
serverSocket_(THRIFT_INVALID_SOCKET),
|
|
||||||
acceptBacklog_(DEFAULT_BACKLOG),
|
|
||||||
sendTimeout_(0),
|
|
||||||
recvTimeout_(0),
|
|
||||||
accTimeout_(-1),
|
|
||||||
retryLimit_(0),
|
|
||||||
retryDelay_(0),
|
|
||||||
tcpSendBuffer_(0),
|
|
||||||
tcpRecvBuffer_(0),
|
|
||||||
intSock1_(THRIFT_INVALID_SOCKET),
|
|
||||||
intSock2_(THRIFT_INVALID_SOCKET) {}
|
|
||||||
|
|
||||||
TServerSocket::~TServerSocket()
|
|
||||||
{
|
|
||||||
close();
|
|
||||||
}
|
|
||||||
|
|
||||||
void TServerSocket::setSendTimeout(int sendTimeout)
|
|
||||||
{
|
|
||||||
sendTimeout_ = sendTimeout;
|
|
||||||
}
|
|
||||||
|
|
||||||
void TServerSocket::setRecvTimeout(int recvTimeout)
|
|
||||||
{
|
|
||||||
recvTimeout_ = recvTimeout;
|
|
||||||
}
|
|
||||||
|
|
||||||
void TServerSocket::setAcceptTimeout(int accTimeout)
|
|
||||||
{
|
|
||||||
accTimeout_ = accTimeout;
|
|
||||||
}
|
|
||||||
|
|
||||||
void TServerSocket::setAcceptBacklog(int accBacklog)
|
|
||||||
{
|
|
||||||
acceptBacklog_ = accBacklog;
|
|
||||||
}
|
|
||||||
|
|
||||||
void TServerSocket::setRetryLimit(int retryLimit)
|
|
||||||
{
|
|
||||||
retryLimit_ = retryLimit;
|
|
||||||
}
|
|
||||||
|
|
||||||
void TServerSocket::setRetryDelay(int retryDelay)
|
|
||||||
{
|
|
||||||
retryDelay_ = retryDelay;
|
|
||||||
}
|
|
||||||
|
|
||||||
void TServerSocket::setTcpSendBuffer(int tcpSendBuffer)
|
|
||||||
{
|
|
||||||
tcpSendBuffer_ = tcpSendBuffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
void TServerSocket::setTcpRecvBuffer(int tcpRecvBuffer)
|
|
||||||
{
|
|
||||||
tcpRecvBuffer_ = tcpRecvBuffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
void TServerSocket::listen()
|
|
||||||
{
|
|
||||||
THRIFT_SOCKET sv[2];
|
|
||||||
|
|
||||||
if (-1 == THRIFT_SOCKETPAIR(AF_LOCAL, SOCK_STREAM, 0, sv))
|
|
||||||
{
|
|
||||||
GlobalOutput.perror("TServerSocket::listen() socketpair() ", THRIFT_GET_SOCKET_ERROR);
|
|
||||||
intSock1_ = THRIFT_INVALID_SOCKET;
|
|
||||||
intSock2_ = THRIFT_INVALID_SOCKET;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
intSock1_ = sv[1];
|
|
||||||
intSock2_ = sv[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
struct addrinfo hints, *res, *res0;
|
|
||||||
|
|
||||||
int error;
|
|
||||||
|
|
||||||
char port[sizeof("65536") + 1];
|
|
||||||
|
|
||||||
std::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)
|
|
||||||
{
|
|
||||||
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 = res0; 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
|
|
||||||
{
|
|
||||||
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("TServerSocket::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("TServerSocket::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("TServerSocket::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("TServerSocket::listen() setsockopt() SO_RCVBUF ", errno_copy);
|
|
||||||
close();
|
|
||||||
throw TTransportException(TTransportException::NOT_OPEN, "Could not set SO_RCVBUF", errno_copy);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Defer accept
|
|
||||||
#ifdef TCP_DEFER_ACCEPT
|
|
||||||
|
|
||||||
if (-1 == setsockopt(serverSocket_, SOL_SOCKET, TCP_DEFER_ACCEPT,
|
|
||||||
&one, sizeof(one)))
|
|
||||||
{
|
|
||||||
int errno_copy = THRIFT_GET_SOCKET_ERROR;
|
|
||||||
GlobalOutput.perror("TServerSocket::listen() setsockopt() TCP_DEFER_ACCEPT ", errno_copy);
|
|
||||||
close();
|
|
||||||
throw TTransportException(TTransportException::NOT_OPEN, "Could not set TCP_DEFER_ACCEPT", errno_copy);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // #ifdef TCP_DEFER_ACCEPT
|
|
||||||
|
|
||||||
#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("TServerSocket::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("TServerSocket::listen() setsockopt() SO_LINGER ", errno_copy);
|
|
||||||
close();
|
|
||||||
throw TTransportException(TTransportException::NOT_OPEN, "Could not set SO_LINGER", errno_copy);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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("TServerSocket::listen() setsockopt() TCP_NODELAY ", errno_copy);
|
|
||||||
close();
|
|
||||||
throw TTransportException(TTransportException::NOT_OPEN, "Could not set TCP_NODELAY", errno_copy);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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("TServerSocket::listen() THRIFT_FCNTL() THRIFT_F_GETFL ", errno_copy);
|
|
||||||
throw TTransportException(TTransportException::NOT_OPEN, "THRIFT_FCNTL() failed", errno_copy);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (-1 == THRIFT_FCNTL(serverSocket_, THRIFT_F_SETFL, flags | THRIFT_O_NONBLOCK))
|
|
||||||
{
|
|
||||||
int errno_copy = THRIFT_GET_SOCKET_ERROR;
|
|
||||||
GlobalOutput.perror("TServerSocket::listen() THRIFT_FCNTL() THRIFT_O_NONBLOCK ", errno_copy);
|
|
||||||
throw TTransportException(TTransportException::NOT_OPEN, "THRIFT_FCNTL() failed", errno_copy);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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;
|
|
||||||
|
|
||||||
if (! path_.empty())
|
|
||||||
{
|
|
||||||
|
|
||||||
#ifndef _WIN32
|
|
||||||
|
|
||||||
// Unix Domain Socket
|
|
||||||
struct sockaddr_un address;
|
|
||||||
socklen_t len;
|
|
||||||
|
|
||||||
if (path_.length() > sizeof(address.sun_path))
|
|
||||||
{
|
|
||||||
int 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");
|
|
||||||
}
|
|
||||||
|
|
||||||
address.sun_family = AF_UNIX;
|
|
||||||
THRIFT_SNPRINTF(address.sun_path, sizeof(address.sun_path), "%s", path_.c_str());
|
|
||||||
len = sizeof(address);
|
|
||||||
|
|
||||||
do
|
|
||||||
{
|
|
||||||
if (0 == ::bind(serverSocket_, (struct sockaddr*) &address, len))
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
// use short circuit evaluation here to only sleep if we need to
|
|
||||||
}
|
|
||||||
while ((retries++ < retryLimit_) && (THRIFT_SLEEP_SEC(retryDelay_) == 0));
|
|
||||||
|
|
||||||
// free addrinfo
|
|
||||||
freeaddrinfo(res0);
|
|
||||||
}
|
|
||||||
|
|
||||||
// throw an error if we failed to bind properly
|
|
||||||
if (retries > retryLimit_)
|
|
||||||
{
|
|
||||||
char errbuf[1024];
|
|
||||||
|
|
||||||
if (! path_.empty())
|
|
||||||
{
|
|
||||||
sprintf(errbuf, "TServerSocket::listen() PATH %s", path_.c_str());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
sprintf(errbuf, "TServerSocket::listen() BIND %d", port_);
|
|
||||||
}
|
|
||||||
|
|
||||||
GlobalOutput(errbuf);
|
|
||||||
close();
|
|
||||||
throw TTransportException(TTransportException::NOT_OPEN, "Could not bind",
|
|
||||||
THRIFT_GET_SOCKET_ERROR);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Call listen
|
|
||||||
if (-1 == ::listen(serverSocket_, acceptBacklog_))
|
|
||||||
{
|
|
||||||
int errno_copy = THRIFT_GET_SOCKET_ERROR;
|
|
||||||
GlobalOutput.perror("TServerSocket::listen() listen() ", errno_copy);
|
|
||||||
close();
|
|
||||||
throw TTransportException(TTransportException::NOT_OPEN, "Could not listen", errno_copy);
|
|
||||||
}
|
|
||||||
|
|
||||||
// The socket is now listening!
|
|
||||||
}
|
|
||||||
|
|
||||||
shared_ptr<TTransport> TServerSocket::acceptImpl()
|
|
||||||
{
|
|
||||||
if (serverSocket_ == THRIFT_INVALID_SOCKET)
|
|
||||||
{
|
|
||||||
throw TTransportException(TTransportException::NOT_OPEN, "TServerSocket not listening");
|
|
||||||
}
|
|
||||||
|
|
||||||
struct THRIFT_POLLFD fds[2];
|
|
||||||
|
|
||||||
int maxEintrs = 5;
|
|
||||||
|
|
||||||
int numEintrs = 0;
|
|
||||||
|
|
||||||
while (true)
|
|
||||||
{
|
|
||||||
std::memset(fds, 0, sizeof(fds));
|
|
||||||
fds[0].fd = serverSocket_;
|
|
||||||
fds[0].events = THRIFT_POLLIN;
|
|
||||||
|
|
||||||
if (intSock2_ != THRIFT_INVALID_SOCKET)
|
|
||||||
{
|
|
||||||
fds[1].fd = intSock2_;
|
|
||||||
fds[1].events = THRIFT_POLLIN;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
TODO: if THRIFT_EINTR is received, we'll restart the timeout.
|
|
||||||
To be accurate, we need to fix this in the future.
|
|
||||||
*/
|
|
||||||
int ret = THRIFT_POLL(fds, 2, accTimeout_);
|
|
||||||
|
|
||||||
if (ret < 0)
|
|
||||||
{
|
|
||||||
// error cases
|
|
||||||
if (THRIFT_GET_SOCKET_ERROR == THRIFT_EINTR && (numEintrs++ < maxEintrs))
|
|
||||||
{
|
|
||||||
// THRIFT_EINTR needs to be handled manually and we can tolerate
|
|
||||||
// a certain number
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
int errno_copy = THRIFT_GET_SOCKET_ERROR;
|
|
||||||
GlobalOutput.perror("TServerSocket::acceptImpl() THRIFT_POLL() ", errno_copy);
|
|
||||||
throw TTransportException(TTransportException::UNKNOWN, "Unknown", errno_copy);
|
|
||||||
}
|
|
||||||
else if (ret > 0)
|
|
||||||
{
|
|
||||||
// Check for an interrupt signal
|
|
||||||
if (intSock2_ != THRIFT_INVALID_SOCKET
|
|
||||||
&& (fds[1].revents & THRIFT_POLLIN))
|
|
||||||
{
|
|
||||||
int8_t buf;
|
|
||||||
|
|
||||||
if (-1 == recv(intSock2_, cast_sockopt(&buf), sizeof(int8_t), 0))
|
|
||||||
{
|
|
||||||
GlobalOutput.perror("TServerSocket::acceptImpl() recv() interrupt ", THRIFT_GET_SOCKET_ERROR);
|
|
||||||
}
|
|
||||||
|
|
||||||
throw TTransportException(TTransportException::INTERRUPTED);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check for the actual server socket being ready
|
|
||||||
if (fds[0].revents & THRIFT_POLLIN)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
GlobalOutput("TServerSocket::acceptImpl() THRIFT_POLL 0");
|
|
||||||
throw TTransportException(TTransportException::UNKNOWN);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct sockaddr_storage clientAddress;
|
|
||||||
|
|
||||||
int size = sizeof(clientAddress);
|
|
||||||
|
|
||||||
THRIFT_SOCKET clientSocket = ::accept(serverSocket_,
|
|
||||||
(struct sockaddr*) &clientAddress,
|
|
||||||
(socklen_t*) &size);
|
|
||||||
|
|
||||||
if (clientSocket == -1)
|
|
||||||
{
|
|
||||||
int errno_copy = THRIFT_GET_SOCKET_ERROR;
|
|
||||||
GlobalOutput.perror("TServerSocket::acceptImpl() ::accept() ", errno_copy);
|
|
||||||
throw TTransportException(TTransportException::UNKNOWN, "accept()", errno_copy);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Make sure client socket is blocking
|
|
||||||
int flags = THRIFT_FCNTL(clientSocket, THRIFT_F_GETFL, 0);
|
|
||||||
|
|
||||||
if (flags == -1)
|
|
||||||
{
|
|
||||||
int errno_copy = THRIFT_GET_SOCKET_ERROR;
|
|
||||||
GlobalOutput.perror("TServerSocket::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;
|
|
||||||
GlobalOutput.perror("TServerSocket::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_);
|
|
||||||
}
|
|
||||||
|
|
||||||
client->setCachedAddress((sockaddr*) &clientAddress, size);
|
|
||||||
|
|
||||||
return client;
|
|
||||||
}
|
|
||||||
|
|
||||||
shared_ptr<TSocket> TServerSocket::createSocket(THRIFT_SOCKET clientSocket)
|
|
||||||
{
|
|
||||||
return shared_ptr<TSocket>(new TSocket(clientSocket));
|
|
||||||
}
|
|
||||||
|
|
||||||
void TServerSocket::interrupt()
|
|
||||||
{
|
|
||||||
if (intSock1_ != THRIFT_INVALID_SOCKET)
|
|
||||||
{
|
|
||||||
int8_t byte = 0;
|
|
||||||
|
|
||||||
if (-1 == send(intSock1_, cast_sockopt(&byte), sizeof(int8_t), 0))
|
|
||||||
{
|
|
||||||
GlobalOutput.perror("TServerSocket::interrupt() send() ", THRIFT_GET_SOCKET_ERROR);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void TServerSocket::close()
|
|
||||||
{
|
|
||||||
if (serverSocket_ != THRIFT_INVALID_SOCKET)
|
|
||||||
{
|
|
||||||
shutdown(serverSocket_, THRIFT_SHUT_RDWR);
|
|
||||||
::THRIFT_CLOSESOCKET(serverSocket_);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (intSock1_ != THRIFT_INVALID_SOCKET)
|
|
||||||
{
|
|
||||||
::THRIFT_CLOSESOCKET(intSock1_);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (intSock2_ != THRIFT_INVALID_SOCKET)
|
|
||||||
{
|
|
||||||
::THRIFT_CLOSESOCKET(intSock2_);
|
|
||||||
}
|
|
||||||
|
|
||||||
serverSocket_ = THRIFT_INVALID_SOCKET;
|
|
||||||
intSock1_ = THRIFT_INVALID_SOCKET;
|
|
||||||
intSock2_ = THRIFT_INVALID_SOCKET;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} // apache::thrift::transport
|
|
||||||
@@ -1,92 +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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <thrift/transport/TServerTransport.h>
|
|
||||||
#include <thrift/transport/PlatformSocket.h>
|
|
||||||
#include <boost/shared_ptr.hpp>
|
|
||||||
|
|
||||||
namespace apache
|
|
||||||
{
|
|
||||||
namespace thrift
|
|
||||||
{
|
|
||||||
namespace transport
|
|
||||||
{
|
|
||||||
|
|
||||||
class TSocket;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Server socket implementation of TServerTransport. Wrapper around a unix
|
|
||||||
* socket listen and accept calls.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
class TServerSocket : public TServerTransport
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
const static int DEFAULT_BACKLOG = 1024;
|
|
||||||
|
|
||||||
TServerSocket(int port);
|
|
||||||
TServerSocket(int port, int sendTimeout, int recvTimeout);
|
|
||||||
TServerSocket(std::string path);
|
|
||||||
|
|
||||||
~TServerSocket();
|
|
||||||
|
|
||||||
void setSendTimeout(int sendTimeout);
|
|
||||||
void setRecvTimeout(int recvTimeout);
|
|
||||||
|
|
||||||
void setAcceptTimeout(int accTimeout);
|
|
||||||
void setAcceptBacklog(int accBacklog);
|
|
||||||
|
|
||||||
void setRetryLimit(int retryLimit);
|
|
||||||
void setRetryDelay(int retryDelay);
|
|
||||||
|
|
||||||
void setTcpSendBuffer(int tcpSendBuffer);
|
|
||||||
void setTcpRecvBuffer(int tcpRecvBuffer);
|
|
||||||
|
|
||||||
void listen();
|
|
||||||
void close();
|
|
||||||
|
|
||||||
void interrupt();
|
|
||||||
|
|
||||||
protected:
|
|
||||||
boost::shared_ptr<TTransport> acceptImpl();
|
|
||||||
virtual boost::shared_ptr<TSocket> createSocket(THRIFT_SOCKET client);
|
|
||||||
|
|
||||||
private:
|
|
||||||
int port_;
|
|
||||||
std::string path_;
|
|
||||||
THRIFT_SOCKET serverSocket_;
|
|
||||||
int acceptBacklog_;
|
|
||||||
int sendTimeout_;
|
|
||||||
int recvTimeout_;
|
|
||||||
int accTimeout_;
|
|
||||||
int retryLimit_;
|
|
||||||
int retryDelay_;
|
|
||||||
int tcpSendBuffer_;
|
|
||||||
int tcpRecvBuffer_;
|
|
||||||
|
|
||||||
THRIFT_SOCKET intSock1_;
|
|
||||||
THRIFT_SOCKET intSock2_;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} // apache::thrift::transport
|
|
||||||
|
|
||||||
@@ -1,102 +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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <thrift/transport/TTransport.h>
|
|
||||||
#include <thrift/transport/TTransportException.h>
|
|
||||||
#include <boost/shared_ptr.hpp>
|
|
||||||
|
|
||||||
namespace apache
|
|
||||||
{
|
|
||||||
namespace thrift
|
|
||||||
{
|
|
||||||
namespace transport
|
|
||||||
{
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Server transport framework. A server needs to have some facility for
|
|
||||||
* creating base transports to read/write from.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
class TServerTransport
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
virtual ~TServerTransport() {}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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
|
|
||||||
*/
|
|
||||||
boost::shared_ptr<TTransport> accept()
|
|
||||||
{
|
|
||||||
boost::shared_ptr<TTransport> result = acceptImpl();
|
|
||||||
|
|
||||||
if (!result)
|
|
||||||
{
|
|
||||||
throw TTransportException("accept() may not return NULL");
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* For "smart" TServerTransport implementations that work in a multi
|
|
||||||
* threaded context this can be used to break out of an accept() call.
|
|
||||||
* It is expected that the transport will throw a TTransportException
|
|
||||||
* with the interrupted error code.
|
|
||||||
*/
|
|
||||||
virtual void interrupt() {}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Closes this transport such that future calls to accept will do nothing.
|
|
||||||
*/
|
|
||||||
virtual void close() = 0;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
TServerTransport() {}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Subclasses should implement this function for accept.
|
|
||||||
*
|
|
||||||
* @return A newly allocated TTransport object
|
|
||||||
* @throw TTransportException If an error occurs
|
|
||||||
*/
|
|
||||||
virtual boost::shared_ptr<TTransport> acceptImpl() = 0;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} // apache::thrift::transport
|
|
||||||
|
|
||||||
@@ -1,119 +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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <cstdlib>
|
|
||||||
|
|
||||||
#include <thrift/transport/TTransport.h>
|
|
||||||
#include <thrift/transport/TVirtualTransport.h>
|
|
||||||
|
|
||||||
namespace apache
|
|
||||||
{
|
|
||||||
namespace thrift
|
|
||||||
{
|
|
||||||
namespace transport
|
|
||||||
{
|
|
||||||
namespace test
|
|
||||||
{
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This class is only meant for testing. It wraps another transport.
|
|
||||||
* Calls to read are passed through with some probability. Otherwise,
|
|
||||||
* the read amount is randomly reduced before being passed through.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
class TShortReadTransport : public TVirtualTransport<TShortReadTransport>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
TShortReadTransport(boost::shared_ptr<TTransport> transport, double full_prob)
|
|
||||||
: transport_(transport)
|
|
||||||
, fullProb_(full_prob)
|
|
||||||
{}
|
|
||||||
|
|
||||||
bool isOpen()
|
|
||||||
{
|
|
||||||
return transport_->isOpen();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool peek()
|
|
||||||
{
|
|
||||||
return transport_->peek();
|
|
||||||
}
|
|
||||||
|
|
||||||
void open()
|
|
||||||
{
|
|
||||||
transport_->open();
|
|
||||||
}
|
|
||||||
|
|
||||||
void close()
|
|
||||||
{
|
|
||||||
transport_->close();
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t read(uint8_t* buf, uint32_t len)
|
|
||||||
{
|
|
||||||
if (len == 0)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (rand() / (double)RAND_MAX >= fullProb_)
|
|
||||||
{
|
|
||||||
len = 1 + rand() % len;
|
|
||||||
}
|
|
||||||
|
|
||||||
return transport_->read(buf, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
void write(const uint8_t* buf, uint32_t len)
|
|
||||||
{
|
|
||||||
transport_->write(buf, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
void flush()
|
|
||||||
{
|
|
||||||
transport_->flush();
|
|
||||||
}
|
|
||||||
|
|
||||||
const uint8_t* borrow(uint8_t* buf, uint32_t* len)
|
|
||||||
{
|
|
||||||
return transport_->borrow(buf, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
void consume(uint32_t len)
|
|
||||||
{
|
|
||||||
return transport_->consume(len);
|
|
||||||
}
|
|
||||||
|
|
||||||
boost::shared_ptr<TTransport> getUnderlyingTransport()
|
|
||||||
{
|
|
||||||
return transport_;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
boost::shared_ptr<TTransport> transport_;
|
|
||||||
double fullProb_;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} // apache::thrift::transport::test
|
|
||||||
|
|
||||||
@@ -1,47 +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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <thrift/transport/TFDTransport.h>
|
|
||||||
|
|
||||||
namespace apache
|
|
||||||
{
|
|
||||||
namespace thrift
|
|
||||||
{
|
|
||||||
namespace transport
|
|
||||||
{
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Dead-simple wrapper around a file.
|
|
||||||
*
|
|
||||||
* Writeable files are opened with O_CREAT and O_APPEND
|
|
||||||
*/
|
|
||||||
class TSimpleFileTransport : public TFDTransport
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
TSimpleFileTransport(const std::string& path,
|
|
||||||
bool read = true,
|
|
||||||
bool write = false);
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} // apache::thrift::transport
|
|
||||||
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,317 +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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
#include <thrift/transport/TTransport.h>
|
|
||||||
#include <thrift/transport/TVirtualTransport.h>
|
|
||||||
#include <thrift/transport/TServerSocket.h>
|
|
||||||
#include <thrift/transport/PlatformSocket.h>
|
|
||||||
|
|
||||||
#ifdef HAVE_ARPA_INET_H
|
|
||||||
#include <arpa/inet.h>
|
|
||||||
#endif
|
|
||||||
#ifdef HAVE_SYS_TIME_H
|
|
||||||
#include <sys/time.h>
|
|
||||||
#endif
|
|
||||||
#ifdef HAVE_NETDB_H
|
|
||||||
#include <netdb.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace apache
|
|
||||||
{
|
|
||||||
namespace thrift
|
|
||||||
{
|
|
||||||
namespace transport
|
|
||||||
{
|
|
||||||
|
|
||||||
/**
|
|
||||||
* TCP Socket implementation of the TTransport interface.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
class TSocket : public TVirtualTransport<TSocket>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
/**
|
|
||||||
* Constructs a new socket. Note that this does NOT actually connect the
|
|
||||||
* socket.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
TSocket();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructs a new socket. Note that this does NOT actually connect the
|
|
||||||
* socket.
|
|
||||||
*
|
|
||||||
* @param host An IP address or hostname to connect to
|
|
||||||
* @param port The port to connect on
|
|
||||||
*/
|
|
||||||
TSocket(std::string host, int port);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructs a new Unix domain socket.
|
|
||||||
* Note that this does NOT actually connect the socket.
|
|
||||||
*
|
|
||||||
* @param path The Unix domain socket e.g. "/tmp/ThriftTest.binary.thrift"
|
|
||||||
*/
|
|
||||||
TSocket(std::string path);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Destroyes the socket object, closing it if necessary.
|
|
||||||
*/
|
|
||||||
virtual ~TSocket();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Whether the socket is alive.
|
|
||||||
*
|
|
||||||
* @return Is the socket alive?
|
|
||||||
*/
|
|
||||||
virtual bool isOpen();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Calls select on the socket to see if there is more data available.
|
|
||||||
*/
|
|
||||||
virtual bool peek();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates and opens the UNIX socket.
|
|
||||||
*
|
|
||||||
* @throws TTransportException If the socket could not connect
|
|
||||||
*/
|
|
||||||
virtual void open();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Shuts down communications on the socket.
|
|
||||||
*/
|
|
||||||
virtual void close();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reads from the underlying socket.
|
|
||||||
*/
|
|
||||||
virtual uint32_t read(uint8_t* buf, uint32_t len);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Writes to the underlying socket. Loops until done or fail.
|
|
||||||
*/
|
|
||||||
virtual void write(const uint8_t* buf, uint32_t len);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Writes to the underlying socket. Does single send() and returns result.
|
|
||||||
*/
|
|
||||||
uint32_t write_partial(const uint8_t* buf, uint32_t len);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the host that the socket is connected to
|
|
||||||
*
|
|
||||||
* @return string host identifier
|
|
||||||
*/
|
|
||||||
std::string getHost();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the port that the socket is connected to
|
|
||||||
*
|
|
||||||
* @return int port number
|
|
||||||
*/
|
|
||||||
int getPort();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the host that socket will connect to
|
|
||||||
*
|
|
||||||
* @param host host identifier
|
|
||||||
*/
|
|
||||||
void setHost(std::string host);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the port that socket will connect to
|
|
||||||
*
|
|
||||||
* @param port port number
|
|
||||||
*/
|
|
||||||
void setPort(int port);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Controls whether the linger option is set on the socket.
|
|
||||||
*
|
|
||||||
* @param on Whether SO_LINGER is on
|
|
||||||
* @param linger If linger is active, the number of seconds to linger for
|
|
||||||
*/
|
|
||||||
void setLinger(bool on, int linger);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Whether to enable/disable Nagle's algorithm.
|
|
||||||
*
|
|
||||||
* @param noDelay Whether or not to disable the algorithm.
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
void setNoDelay(bool noDelay);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the connect timeout
|
|
||||||
*/
|
|
||||||
void setConnTimeout(int ms);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the receive timeout
|
|
||||||
*/
|
|
||||||
void setRecvTimeout(int ms);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the send timeout
|
|
||||||
*/
|
|
||||||
void setSendTimeout(int ms);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the max number of recv retries in case of an THRIFT_EAGAIN
|
|
||||||
* error
|
|
||||||
*/
|
|
||||||
void setMaxRecvRetries(int maxRecvRetries);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get socket information formated as a string <Host: x Port: x>
|
|
||||||
*/
|
|
||||||
std::string getSocketInfo();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the DNS name of the host to which the socket is connected
|
|
||||||
*/
|
|
||||||
std::string getPeerHost();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the address of the host to which the socket is connected
|
|
||||||
*/
|
|
||||||
std::string getPeerAddress();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the port of the host to which the socket is connected
|
|
||||||
**/
|
|
||||||
int getPeerPort();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the underlying socket file descriptor.
|
|
||||||
*/
|
|
||||||
THRIFT_SOCKET getSocketFD()
|
|
||||||
{
|
|
||||||
return socket_;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* (Re-)initialize a TSocket for the supplied descriptor. This is only
|
|
||||||
* intended for use by TNonblockingServer -- other use may result in
|
|
||||||
* unfortunate surprises.
|
|
||||||
*
|
|
||||||
* @param fd the descriptor for an already-connected socket
|
|
||||||
*/
|
|
||||||
void setSocketFD(THRIFT_SOCKET fd);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Returns a cached copy of the peer address.
|
|
||||||
*/
|
|
||||||
sockaddr* getCachedAddress(socklen_t* len) const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets whether to use a low minimum TCP retransmission timeout.
|
|
||||||
*/
|
|
||||||
static void setUseLowMinRto(bool useLowMinRto);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets whether to use a low minimum TCP retransmission timeout.
|
|
||||||
*/
|
|
||||||
static bool getUseLowMinRto();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor to create socket from raw UNIX handle.
|
|
||||||
*/
|
|
||||||
TSocket(THRIFT_SOCKET socket);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set a cache of the peer address (used when trivially available: e.g.
|
|
||||||
* accept() or connect()). Only caches IPV4 and IPV6; unset for others.
|
|
||||||
*/
|
|
||||||
void setCachedAddress(const sockaddr* addr, socklen_t len);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
/** connect, called by open */
|
|
||||||
void openConnection(struct addrinfo* res);
|
|
||||||
|
|
||||||
/** Host to connect to */
|
|
||||||
std::string host_;
|
|
||||||
|
|
||||||
/** Peer hostname */
|
|
||||||
std::string peerHost_;
|
|
||||||
|
|
||||||
/** Peer address */
|
|
||||||
std::string peerAddress_;
|
|
||||||
|
|
||||||
/** Peer port */
|
|
||||||
int peerPort_;
|
|
||||||
|
|
||||||
/** Port number to connect on */
|
|
||||||
int port_;
|
|
||||||
|
|
||||||
/** UNIX domain socket path */
|
|
||||||
std::string path_;
|
|
||||||
|
|
||||||
/** Underlying UNIX socket handle */
|
|
||||||
THRIFT_SOCKET socket_;
|
|
||||||
|
|
||||||
/** Connect timeout in ms */
|
|
||||||
int connTimeout_;
|
|
||||||
|
|
||||||
/** Send timeout in ms */
|
|
||||||
int sendTimeout_;
|
|
||||||
|
|
||||||
/** Recv timeout in ms */
|
|
||||||
int recvTimeout_;
|
|
||||||
|
|
||||||
/** Linger on */
|
|
||||||
bool lingerOn_;
|
|
||||||
|
|
||||||
/** Linger val */
|
|
||||||
int lingerVal_;
|
|
||||||
|
|
||||||
/** Nodelay */
|
|
||||||
bool noDelay_;
|
|
||||||
|
|
||||||
/** Recv EGAIN retries */
|
|
||||||
int maxRecvRetries_;
|
|
||||||
|
|
||||||
/** Recv timeout timeval */
|
|
||||||
struct timeval recvTimeval_;
|
|
||||||
|
|
||||||
/** Cached peer address */
|
|
||||||
union
|
|
||||||
{
|
|
||||||
sockaddr_in ipv4;
|
|
||||||
sockaddr_in6 ipv6;
|
|
||||||
} cachedPeerAddr_;
|
|
||||||
|
|
||||||
/** Whether to use low minimum TCP retransmission timeout */
|
|
||||||
static bool useLowMinRto_;
|
|
||||||
|
|
||||||
private:
|
|
||||||
void unix_open();
|
|
||||||
void local_open();
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} // apache::thrift::transport
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,203 +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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
#include <thrift/transport/TSocket.h>
|
|
||||||
|
|
||||||
namespace apache
|
|
||||||
{
|
|
||||||
namespace thrift
|
|
||||||
{
|
|
||||||
namespace transport
|
|
||||||
{
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class to hold server information for TSocketPool
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
class TSocketPoolServer
|
|
||||||
{
|
|
||||||
|
|
||||||
public:
|
|
||||||
/**
|
|
||||||
* Default constructor for server info
|
|
||||||
*/
|
|
||||||
TSocketPoolServer();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor for TSocketPool server
|
|
||||||
*/
|
|
||||||
TSocketPoolServer(const std::string& host, int port);
|
|
||||||
|
|
||||||
// Host name
|
|
||||||
std::string host_;
|
|
||||||
|
|
||||||
// Port to connect on
|
|
||||||
int port_;
|
|
||||||
|
|
||||||
// Socket for the server
|
|
||||||
THRIFT_SOCKET socket_;
|
|
||||||
|
|
||||||
// Last time connecting to this server failed
|
|
||||||
time_t lastFailTime_;
|
|
||||||
|
|
||||||
// Number of consecutive times connecting to this server failed
|
|
||||||
int consecutiveFailures_;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* TCP Socket implementation of the TTransport interface.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
class TSocketPool : public TSocket
|
|
||||||
{
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Socket pool constructor
|
|
||||||
*/
|
|
||||||
TSocketPool();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Socket pool constructor
|
|
||||||
*
|
|
||||||
* @param hosts list of host names
|
|
||||||
* @param ports list of port names
|
|
||||||
*/
|
|
||||||
TSocketPool(const std::vector<std::string>& hosts,
|
|
||||||
const std::vector<int>& ports);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Socket pool constructor
|
|
||||||
*
|
|
||||||
* @param servers list of pairs of host name and port
|
|
||||||
*/
|
|
||||||
TSocketPool(const std::vector<std::pair<std::string, int> >& servers);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Socket pool constructor
|
|
||||||
*
|
|
||||||
* @param servers list of TSocketPoolServers
|
|
||||||
*/
|
|
||||||
TSocketPool(const std::vector< boost::shared_ptr<TSocketPoolServer> >& servers);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Socket pool constructor
|
|
||||||
*
|
|
||||||
* @param host single host
|
|
||||||
* @param port single port
|
|
||||||
*/
|
|
||||||
TSocketPool(const std::string& host, int port);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Destroyes the socket object, closing it if necessary.
|
|
||||||
*/
|
|
||||||
virtual ~TSocketPool();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add a server to the pool
|
|
||||||
*/
|
|
||||||
void addServer(const std::string& host, int port);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add a server to the pool
|
|
||||||
*/
|
|
||||||
void addServer(boost::shared_ptr<TSocketPoolServer>& server);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set list of servers in this pool
|
|
||||||
*/
|
|
||||||
void setServers(const std::vector< boost::shared_ptr<TSocketPoolServer> >& servers);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get list of servers in this pool
|
|
||||||
*/
|
|
||||||
void getServers(std::vector< boost::shared_ptr<TSocketPoolServer> >& servers);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets how many times to keep retrying a host in the connect function.
|
|
||||||
*/
|
|
||||||
void setNumRetries(int numRetries);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets how long to wait until retrying a host if it was marked down
|
|
||||||
*/
|
|
||||||
void setRetryInterval(int retryInterval);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets how many times to keep retrying a host before marking it as down.
|
|
||||||
*/
|
|
||||||
void setMaxConsecutiveFailures(int maxConsecutiveFailures);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Turns randomization in connect order on or off.
|
|
||||||
*/
|
|
||||||
void setRandomize(bool randomize);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Whether to always try the last server.
|
|
||||||
*/
|
|
||||||
void setAlwaysTryLast(bool alwaysTryLast);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates and opens the UNIX socket.
|
|
||||||
*/
|
|
||||||
void open();
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Closes the UNIX socket
|
|
||||||
*/
|
|
||||||
void close();
|
|
||||||
|
|
||||||
protected:
|
|
||||||
|
|
||||||
void setCurrentServer(const boost::shared_ptr<TSocketPoolServer>& server);
|
|
||||||
|
|
||||||
/** List of servers to connect to */
|
|
||||||
std::vector< boost::shared_ptr<TSocketPoolServer> > servers_;
|
|
||||||
|
|
||||||
/** Current server */
|
|
||||||
boost::shared_ptr<TSocketPoolServer> currentServer_;
|
|
||||||
|
|
||||||
/** How many times to retry each host in connect */
|
|
||||||
int numRetries_;
|
|
||||||
|
|
||||||
/** Retry interval in seconds, how long to not try a host if it has been
|
|
||||||
* marked as down.
|
|
||||||
*/
|
|
||||||
time_t retryInterval_;
|
|
||||||
|
|
||||||
/** Max consecutive failures before marking a host down. */
|
|
||||||
int maxConsecutiveFailures_;
|
|
||||||
|
|
||||||
/** Try hosts in order? or Randomized? */
|
|
||||||
bool randomize_;
|
|
||||||
|
|
||||||
/** Always try last host, even if marked down? */
|
|
||||||
bool alwaysTryLast_;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} // apache::thrift::transport
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,300 +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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <thrift/Thrift.h>
|
|
||||||
#include <boost/shared_ptr.hpp>
|
|
||||||
#include <thrift/transport/TTransportException.h>
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
namespace apache
|
|
||||||
{
|
|
||||||
namespace thrift
|
|
||||||
{
|
|
||||||
namespace transport
|
|
||||||
{
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Helper template to hoist readAll implementation out of TTransport
|
|
||||||
*/
|
|
||||||
template <class Transport_>
|
|
||||||
uint32_t readAll(Transport_ &trans, uint8_t* buf, uint32_t len)
|
|
||||||
{
|
|
||||||
uint32_t have = 0;
|
|
||||||
uint32_t get = 0;
|
|
||||||
|
|
||||||
while (have < len)
|
|
||||||
{
|
|
||||||
get = trans.read(buf + have, len - have);
|
|
||||||
|
|
||||||
if (get <= 0)
|
|
||||||
{
|
|
||||||
throw TTransportException(TTransportException::END_OF_FILE,
|
|
||||||
"No more data to read.");
|
|
||||||
}
|
|
||||||
|
|
||||||
have += get;
|
|
||||||
}
|
|
||||||
|
|
||||||
return have;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Generic interface for a method of transporting data. A TTransport may be
|
|
||||||
* capable of either reading or writing, but not necessarily both.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
class TTransport
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
/**
|
|
||||||
* Virtual deconstructor.
|
|
||||||
*/
|
|
||||||
virtual ~TTransport() {}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Whether this transport is open.
|
|
||||||
*/
|
|
||||||
virtual bool isOpen()
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests whether there is more data to read or if the remote side is
|
|
||||||
* still open. By default this is true whenever the transport is open,
|
|
||||||
* but implementations should add logic to test for this condition where
|
|
||||||
* possible (i.e. on a socket).
|
|
||||||
* This is used by a server to check if it should listen for another
|
|
||||||
* request.
|
|
||||||
*/
|
|
||||||
virtual bool peek()
|
|
||||||
{
|
|
||||||
return isOpen();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Opens the transport for communications.
|
|
||||||
*
|
|
||||||
* @return bool Whether the transport was successfully opened
|
|
||||||
* @throws TTransportException if opening failed
|
|
||||||
*/
|
|
||||||
virtual void open()
|
|
||||||
{
|
|
||||||
throw TTransportException(TTransportException::NOT_OPEN, "Cannot open base TTransport.");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Closes the transport.
|
|
||||||
*/
|
|
||||||
virtual void close()
|
|
||||||
{
|
|
||||||
throw TTransportException(TTransportException::NOT_OPEN, "Cannot close base TTransport.");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Attempt to read up to the specified number of bytes into the string.
|
|
||||||
*
|
|
||||||
* @param buf Reference to the location to write the data
|
|
||||||
* @param len How many bytes to read
|
|
||||||
* @return How many bytes were actually read
|
|
||||||
* @throws TTransportException If an error occurs
|
|
||||||
*/
|
|
||||||
uint32_t read(uint8_t* buf, uint32_t len)
|
|
||||||
{
|
|
||||||
T_VIRTUAL_CALL();
|
|
||||||
return read_virt(buf, len);
|
|
||||||
}
|
|
||||||
virtual uint32_t read_virt(uint8_t* /* buf */, uint32_t /* len */)
|
|
||||||
{
|
|
||||||
throw TTransportException(TTransportException::NOT_OPEN,
|
|
||||||
"Base TTransport cannot read.");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reads the given amount of data in its entirety no matter what.
|
|
||||||
*
|
|
||||||
* @param s Reference to location for read data
|
|
||||||
* @param len How many bytes to read
|
|
||||||
* @return How many bytes read, which must be equal to size
|
|
||||||
* @throws TTransportException If insufficient data was read
|
|
||||||
*/
|
|
||||||
uint32_t readAll(uint8_t* buf, uint32_t len)
|
|
||||||
{
|
|
||||||
T_VIRTUAL_CALL();
|
|
||||||
return readAll_virt(buf, len);
|
|
||||||
}
|
|
||||||
virtual uint32_t readAll_virt(uint8_t* buf, uint32_t len)
|
|
||||||
{
|
|
||||||
return apache::thrift::transport::readAll(*this, buf, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called when read is completed.
|
|
||||||
* This can be over-ridden to perform a transport-specific action
|
|
||||||
* e.g. logging the request to a file
|
|
||||||
*
|
|
||||||
* @return number of bytes read if available, 0 otherwise.
|
|
||||||
*/
|
|
||||||
virtual uint32_t readEnd()
|
|
||||||
{
|
|
||||||
// default behaviour is to do nothing
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Writes the string in its entirety to the buffer.
|
|
||||||
*
|
|
||||||
* Note: You must call flush() to ensure the data is actually written,
|
|
||||||
* and available to be read back in the future. Destroying a TTransport
|
|
||||||
* object does not automatically flush pending data--if you destroy a
|
|
||||||
* TTransport object with written but unflushed data, that data may be
|
|
||||||
* discarded.
|
|
||||||
*
|
|
||||||
* @param buf The data to write out
|
|
||||||
* @throws TTransportException if an error occurs
|
|
||||||
*/
|
|
||||||
void write(const uint8_t* buf, uint32_t len)
|
|
||||||
{
|
|
||||||
T_VIRTUAL_CALL();
|
|
||||||
write_virt(buf, len);
|
|
||||||
}
|
|
||||||
virtual void write_virt(const uint8_t* /* buf */, uint32_t /* len */)
|
|
||||||
{
|
|
||||||
throw TTransportException(TTransportException::NOT_OPEN,
|
|
||||||
"Base TTransport cannot write.");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called when write is completed.
|
|
||||||
* This can be over-ridden to perform a transport-specific action
|
|
||||||
* at the end of a request.
|
|
||||||
*
|
|
||||||
* @return number of bytes written if available, 0 otherwise
|
|
||||||
*/
|
|
||||||
virtual uint32_t writeEnd()
|
|
||||||
{
|
|
||||||
// default behaviour is to do nothing
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Flushes any pending data to be written. Typically used with buffered
|
|
||||||
* transport mechanisms.
|
|
||||||
*
|
|
||||||
* @throws TTransportException if an error occurs
|
|
||||||
*/
|
|
||||||
virtual void flush()
|
|
||||||
{
|
|
||||||
// default behaviour is to do nothing
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Attempts to return a pointer to \c len bytes, possibly copied into \c buf.
|
|
||||||
* Does not consume the bytes read (i.e.: a later read will return the same
|
|
||||||
* data). This method is meant to support protocols that need to read
|
|
||||||
* variable-length fields. They can attempt to borrow the maximum amount of
|
|
||||||
* data that they will need, then consume (see next method) what they
|
|
||||||
* actually use. Some transports will not support this method and others
|
|
||||||
* will fail occasionally, so protocols must be prepared to use read if
|
|
||||||
* borrow fails.
|
|
||||||
*
|
|
||||||
* @oaram buf A buffer where the data can be stored if needed.
|
|
||||||
* If borrow doesn't return buf, then the contents of
|
|
||||||
* buf after the call are undefined. This parameter may be
|
|
||||||
* NULL to indicate that the caller is not supplying storage,
|
|
||||||
* but would like a pointer into an internal buffer, if
|
|
||||||
* available.
|
|
||||||
* @param len *len should initially contain the number of bytes to borrow.
|
|
||||||
* If borrow succeeds, *len will contain the number of bytes
|
|
||||||
* available in the returned pointer. This will be at least
|
|
||||||
* what was requested, but may be more if borrow returns
|
|
||||||
* a pointer to an internal buffer, rather than buf.
|
|
||||||
* If borrow fails, the contents of *len are undefined.
|
|
||||||
* @return If the borrow succeeds, return a pointer to the borrowed data.
|
|
||||||
* This might be equal to \c buf, or it might be a pointer into
|
|
||||||
* the transport's internal buffers.
|
|
||||||
* @throws TTransportException if an error occurs
|
|
||||||
*/
|
|
||||||
const uint8_t* borrow(uint8_t* buf, uint32_t* len)
|
|
||||||
{
|
|
||||||
T_VIRTUAL_CALL();
|
|
||||||
return borrow_virt(buf, len);
|
|
||||||
}
|
|
||||||
virtual const uint8_t* borrow_virt(uint8_t* /* buf */, uint32_t* /* len */)
|
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove len bytes from the transport. This should always follow a borrow
|
|
||||||
* of at least len bytes, and should always succeed.
|
|
||||||
* TODO(dreiss): Is there any transport that could borrow but fail to
|
|
||||||
* consume, or that would require a buffer to dump the consumed data?
|
|
||||||
*
|
|
||||||
* @param len How many bytes to consume
|
|
||||||
* @throws TTransportException If an error occurs
|
|
||||||
*/
|
|
||||||
void consume(uint32_t len)
|
|
||||||
{
|
|
||||||
T_VIRTUAL_CALL();
|
|
||||||
consume_virt(len);
|
|
||||||
}
|
|
||||||
virtual void consume_virt(uint32_t /* len */)
|
|
||||||
{
|
|
||||||
throw TTransportException(TTransportException::NOT_OPEN,
|
|
||||||
"Base TTransport cannot consume.");
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
/**
|
|
||||||
* Simple constructor.
|
|
||||||
*/
|
|
||||||
TTransport() {}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Generic factory class to make an input and output transport out of a
|
|
||||||
* source transport. Commonly used inside servers to make input and output
|
|
||||||
* streams out of raw clients.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
class TTransportFactory
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
TTransportFactory() {}
|
|
||||||
|
|
||||||
virtual ~TTransportFactory() {}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Default implementation does nothing, just returns the transport given.
|
|
||||||
*/
|
|
||||||
virtual boost::shared_ptr<TTransport> getTransport(boost::shared_ptr<TTransport> trans)
|
|
||||||
{
|
|
||||||
return trans;
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} // apache::thrift::transport
|
|
||||||
|
|
||||||
@@ -1,145 +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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include <thrift/Thrift.h>
|
|
||||||
|
|
||||||
namespace apache
|
|
||||||
{
|
|
||||||
namespace thrift
|
|
||||||
{
|
|
||||||
namespace transport
|
|
||||||
{
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class to encapsulate all the possible types of transport errors that may
|
|
||||||
* occur in various transport systems. This provides a sort of generic
|
|
||||||
* wrapper around the vague UNIX E_ error codes that lets a common code
|
|
||||||
* base of error handling to be used for various types of transports, i.e.
|
|
||||||
* pipes etc.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
class TTransportException : public apache::thrift::TException
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
/**
|
|
||||||
* Error codes for the various types of exceptions.
|
|
||||||
*/
|
|
||||||
enum TTransportExceptionType
|
|
||||||
{
|
|
||||||
UNKNOWN = 0
|
|
||||||
, NOT_OPEN = 1
|
|
||||||
, TIMED_OUT = 2
|
|
||||||
, END_OF_FILE = 3
|
|
||||||
, INTERRUPTED = 4
|
|
||||||
, BAD_ARGS = 5
|
|
||||||
, CORRUPTED_DATA = 6
|
|
||||||
, INTERNAL_ERROR = 7
|
|
||||||
};
|
|
||||||
|
|
||||||
TTransportException() :
|
|
||||||
apache::thrift::TException(),
|
|
||||||
type_(UNKNOWN) {}
|
|
||||||
|
|
||||||
TTransportException(TTransportExceptionType type) :
|
|
||||||
apache::thrift::TException(),
|
|
||||||
type_(type) {}
|
|
||||||
|
|
||||||
TTransportException(const std::string& message) :
|
|
||||||
apache::thrift::TException(message),
|
|
||||||
type_(UNKNOWN) {}
|
|
||||||
|
|
||||||
TTransportException(TTransportExceptionType type, const std::string& message) :
|
|
||||||
apache::thrift::TException(message),
|
|
||||||
type_(type) {}
|
|
||||||
|
|
||||||
TTransportException(TTransportExceptionType type,
|
|
||||||
const std::string& message,
|
|
||||||
int errno_copy) :
|
|
||||||
apache::thrift::TException(message + ": " + TOutput::strerror_s(errno_copy)),
|
|
||||||
type_(type) {}
|
|
||||||
|
|
||||||
virtual ~TTransportException() throw() {}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns an error code that provides information about the type of error
|
|
||||||
* that has occurred.
|
|
||||||
*
|
|
||||||
* @return Error code
|
|
||||||
*/
|
|
||||||
TTransportExceptionType getType() const throw()
|
|
||||||
{
|
|
||||||
return type_;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual const char* what() const throw()
|
|
||||||
{
|
|
||||||
if (message_.empty())
|
|
||||||
{
|
|
||||||
switch (type_)
|
|
||||||
{
|
|
||||||
case UNKNOWN :
|
|
||||||
return "TTransportException: Unknown transport exception";
|
|
||||||
|
|
||||||
case NOT_OPEN :
|
|
||||||
return "TTransportException: Transport not open";
|
|
||||||
|
|
||||||
case TIMED_OUT :
|
|
||||||
return "TTransportException: Timed out";
|
|
||||||
|
|
||||||
case END_OF_FILE :
|
|
||||||
return "TTransportException: End of file";
|
|
||||||
|
|
||||||
case INTERRUPTED :
|
|
||||||
return "TTransportException: Interrupted";
|
|
||||||
|
|
||||||
case BAD_ARGS :
|
|
||||||
return "TTransportException: Invalid arguments";
|
|
||||||
|
|
||||||
case CORRUPTED_DATA :
|
|
||||||
return "TTransportException: Corrupted Data";
|
|
||||||
|
|
||||||
case INTERNAL_ERROR :
|
|
||||||
return "TTransportException: Internal error";
|
|
||||||
|
|
||||||
default :
|
|
||||||
return "TTransportException: (Invalid exception type)";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return message_.c_str();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
/** Just like strerror_r but returns a C++ string object. */
|
|
||||||
std::string strerror_s(int errno_copy);
|
|
||||||
|
|
||||||
/** Error code */
|
|
||||||
TTransportExceptionType type_;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} // apache::thrift::transport
|
|
||||||
|
|
||||||
@@ -1,387 +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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <cstdlib>
|
|
||||||
#include <cstring>
|
|
||||||
#include <string>
|
|
||||||
#include <algorithm>
|
|
||||||
#include <thrift/transport/TTransport.h>
|
|
||||||
// Include the buffered transports that used to be defined here.
|
|
||||||
#include <thrift/transport/TBufferTransports.h>
|
|
||||||
#include <thrift/transport/TFileTransport.h>
|
|
||||||
|
|
||||||
namespace apache
|
|
||||||
{
|
|
||||||
namespace thrift
|
|
||||||
{
|
|
||||||
namespace transport
|
|
||||||
{
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The null transport is a dummy transport that doesn't actually do anything.
|
|
||||||
* It's sort of an analogy to /dev/null, you can never read anything from it
|
|
||||||
* and it will let you write anything you want to it, though it won't actually
|
|
||||||
* go anywhere.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
class TNullTransport : public TVirtualTransport<TNullTransport>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
TNullTransport() {}
|
|
||||||
|
|
||||||
~TNullTransport() {}
|
|
||||||
|
|
||||||
bool isOpen()
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void open() {}
|
|
||||||
|
|
||||||
void write(const uint8_t* /* buf */, uint32_t /* len */)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* TPipedTransport. This transport allows piping of a request from one
|
|
||||||
* transport to another either when readEnd() or writeEnd(). The typical
|
|
||||||
* use case for this is to log a request or a reply to disk.
|
|
||||||
* The underlying buffer expands to a keep a copy of the entire
|
|
||||||
* request/response.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
class TPipedTransport : virtual public TTransport
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
TPipedTransport(boost::shared_ptr<TTransport> srcTrans,
|
|
||||||
boost::shared_ptr<TTransport> dstTrans) :
|
|
||||||
srcTrans_(srcTrans),
|
|
||||||
dstTrans_(dstTrans),
|
|
||||||
rBufSize_(512), rPos_(0), rLen_(0),
|
|
||||||
wBufSize_(512), wLen_(0)
|
|
||||||
{
|
|
||||||
|
|
||||||
// default is to to pipe the request when readEnd() is called
|
|
||||||
pipeOnRead_ = true;
|
|
||||||
pipeOnWrite_ = false;
|
|
||||||
|
|
||||||
rBuf_ = (uint8_t*) std::malloc(sizeof(uint8_t) * rBufSize_);
|
|
||||||
|
|
||||||
if (rBuf_ == NULL)
|
|
||||||
{
|
|
||||||
throw std::bad_alloc();
|
|
||||||
}
|
|
||||||
|
|
||||||
wBuf_ = (uint8_t*) std::malloc(sizeof(uint8_t) * wBufSize_);
|
|
||||||
|
|
||||||
if (wBuf_ == NULL)
|
|
||||||
{
|
|
||||||
throw std::bad_alloc();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TPipedTransport(boost::shared_ptr<TTransport> srcTrans,
|
|
||||||
boost::shared_ptr<TTransport> dstTrans,
|
|
||||||
uint32_t sz) :
|
|
||||||
srcTrans_(srcTrans),
|
|
||||||
dstTrans_(dstTrans),
|
|
||||||
rBufSize_(512), rPos_(0), rLen_(0),
|
|
||||||
wBufSize_(sz), wLen_(0)
|
|
||||||
{
|
|
||||||
|
|
||||||
rBuf_ = (uint8_t*) std::malloc(sizeof(uint8_t) * rBufSize_);
|
|
||||||
|
|
||||||
if (rBuf_ == NULL)
|
|
||||||
{
|
|
||||||
throw std::bad_alloc();
|
|
||||||
}
|
|
||||||
|
|
||||||
wBuf_ = (uint8_t*) std::malloc(sizeof(uint8_t) * wBufSize_);
|
|
||||||
|
|
||||||
if (wBuf_ == NULL)
|
|
||||||
{
|
|
||||||
throw std::bad_alloc();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
~TPipedTransport()
|
|
||||||
{
|
|
||||||
std::free(rBuf_);
|
|
||||||
std::free(wBuf_);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool isOpen()
|
|
||||||
{
|
|
||||||
return srcTrans_->isOpen();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool peek()
|
|
||||||
{
|
|
||||||
if (rPos_ >= rLen_)
|
|
||||||
{
|
|
||||||
// Double the size of the underlying buffer if it is full
|
|
||||||
if (rLen_ == rBufSize_)
|
|
||||||
{
|
|
||||||
rBufSize_ *= 2;
|
|
||||||
rBuf_ = (uint8_t*)std::realloc(rBuf_, sizeof(uint8_t) * rBufSize_);
|
|
||||||
}
|
|
||||||
|
|
||||||
// try to fill up the buffer
|
|
||||||
rLen_ += srcTrans_->read(rBuf_ + rPos_, rBufSize_ - rPos_);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (rLen_ > rPos_);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void open()
|
|
||||||
{
|
|
||||||
srcTrans_->open();
|
|
||||||
}
|
|
||||||
|
|
||||||
void close()
|
|
||||||
{
|
|
||||||
srcTrans_->close();
|
|
||||||
}
|
|
||||||
|
|
||||||
void setPipeOnRead(bool pipeVal)
|
|
||||||
{
|
|
||||||
pipeOnRead_ = pipeVal;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setPipeOnWrite(bool pipeVal)
|
|
||||||
{
|
|
||||||
pipeOnWrite_ = pipeVal;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t read(uint8_t* buf, uint32_t len);
|
|
||||||
|
|
||||||
uint32_t readEnd()
|
|
||||||
{
|
|
||||||
|
|
||||||
if (pipeOnRead_)
|
|
||||||
{
|
|
||||||
dstTrans_->write(rBuf_, rPos_);
|
|
||||||
dstTrans_->flush();
|
|
||||||
}
|
|
||||||
|
|
||||||
srcTrans_->readEnd();
|
|
||||||
|
|
||||||
// If requests are being pipelined, copy down our read-ahead data,
|
|
||||||
// then reset our state.
|
|
||||||
int read_ahead = rLen_ - rPos_;
|
|
||||||
uint32_t bytes = rPos_;
|
|
||||||
memcpy(rBuf_, rBuf_ + rPos_, read_ahead);
|
|
||||||
rPos_ = 0;
|
|
||||||
rLen_ = read_ahead;
|
|
||||||
|
|
||||||
return bytes;
|
|
||||||
}
|
|
||||||
|
|
||||||
void write(const uint8_t* buf, uint32_t len);
|
|
||||||
|
|
||||||
uint32_t writeEnd()
|
|
||||||
{
|
|
||||||
if (pipeOnWrite_)
|
|
||||||
{
|
|
||||||
dstTrans_->write(wBuf_, wLen_);
|
|
||||||
dstTrans_->flush();
|
|
||||||
}
|
|
||||||
|
|
||||||
return wLen_;
|
|
||||||
}
|
|
||||||
|
|
||||||
void flush();
|
|
||||||
|
|
||||||
boost::shared_ptr<TTransport> getTargetTransport()
|
|
||||||
{
|
|
||||||
return dstTrans_;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Override TTransport *_virt() functions to invoke our implementations.
|
|
||||||
* We cannot use TVirtualTransport to provide these, since we need to inherit
|
|
||||||
* virtually from TTransport.
|
|
||||||
*/
|
|
||||||
virtual uint32_t read_virt(uint8_t* buf, uint32_t len)
|
|
||||||
{
|
|
||||||
return this->read(buf, len);
|
|
||||||
}
|
|
||||||
virtual void write_virt(const uint8_t* buf, uint32_t len)
|
|
||||||
{
|
|
||||||
this->write(buf, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
boost::shared_ptr<TTransport> srcTrans_;
|
|
||||||
boost::shared_ptr<TTransport> dstTrans_;
|
|
||||||
|
|
||||||
uint8_t* rBuf_;
|
|
||||||
uint32_t rBufSize_;
|
|
||||||
uint32_t rPos_;
|
|
||||||
uint32_t rLen_;
|
|
||||||
|
|
||||||
uint8_t* wBuf_;
|
|
||||||
uint32_t wBufSize_;
|
|
||||||
uint32_t wLen_;
|
|
||||||
|
|
||||||
bool pipeOnRead_;
|
|
||||||
bool pipeOnWrite_;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Wraps a transport into a pipedTransport instance.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
class TPipedTransportFactory : public TTransportFactory
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
TPipedTransportFactory() {}
|
|
||||||
TPipedTransportFactory(boost::shared_ptr<TTransport> dstTrans)
|
|
||||||
{
|
|
||||||
initializeTargetTransport(dstTrans);
|
|
||||||
}
|
|
||||||
virtual ~TPipedTransportFactory() {}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Wraps the base transport into a piped transport.
|
|
||||||
*/
|
|
||||||
virtual boost::shared_ptr<TTransport> getTransport(boost::shared_ptr<TTransport> srcTrans)
|
|
||||||
{
|
|
||||||
return boost::shared_ptr<TTransport>(new TPipedTransport(srcTrans, dstTrans_));
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void initializeTargetTransport(boost::shared_ptr<TTransport> dstTrans)
|
|
||||||
{
|
|
||||||
if (dstTrans_.get() == NULL)
|
|
||||||
{
|
|
||||||
dstTrans_ = dstTrans;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
throw TException("Target transport already initialized");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
boost::shared_ptr<TTransport> dstTrans_;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* TPipedFileTransport. This is just like a TTransport, except that
|
|
||||||
* it is a templatized class, so that clients who rely on a specific
|
|
||||||
* TTransport can still access the original transport.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
class TPipedFileReaderTransport : public TPipedTransport,
|
|
||||||
public TFileReaderTransport
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
TPipedFileReaderTransport(boost::shared_ptr<TFileReaderTransport> srcTrans, boost::shared_ptr<TTransport> dstTrans);
|
|
||||||
|
|
||||||
~TPipedFileReaderTransport();
|
|
||||||
|
|
||||||
// TTransport functions
|
|
||||||
bool isOpen();
|
|
||||||
bool peek();
|
|
||||||
void open();
|
|
||||||
void close();
|
|
||||||
uint32_t read(uint8_t* buf, uint32_t len);
|
|
||||||
uint32_t readAll(uint8_t* buf, uint32_t len);
|
|
||||||
uint32_t readEnd();
|
|
||||||
void write(const uint8_t* buf, uint32_t len);
|
|
||||||
uint32_t writeEnd();
|
|
||||||
void flush();
|
|
||||||
|
|
||||||
// TFileReaderTransport functions
|
|
||||||
int32_t getReadTimeout();
|
|
||||||
void setReadTimeout(int32_t readTimeout);
|
|
||||||
uint32_t getNumChunks();
|
|
||||||
uint32_t getCurChunk();
|
|
||||||
void seekToChunk(int32_t chunk);
|
|
||||||
void seekToEnd();
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Override TTransport *_virt() functions to invoke our implementations.
|
|
||||||
* We cannot use TVirtualTransport to provide these, since we need to inherit
|
|
||||||
* virtually from TTransport.
|
|
||||||
*/
|
|
||||||
virtual uint32_t read_virt(uint8_t* buf, uint32_t len)
|
|
||||||
{
|
|
||||||
return this->read(buf, len);
|
|
||||||
}
|
|
||||||
virtual uint32_t readAll_virt(uint8_t* buf, uint32_t len)
|
|
||||||
{
|
|
||||||
return this->readAll(buf, len);
|
|
||||||
}
|
|
||||||
virtual void write_virt(const uint8_t* buf, uint32_t len)
|
|
||||||
{
|
|
||||||
this->write(buf, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
// shouldn't be used
|
|
||||||
TPipedFileReaderTransport();
|
|
||||||
boost::shared_ptr<TFileReaderTransport> srcTrans_;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a TPipedFileReaderTransport from a filepath and a destination transport
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
class TPipedFileReaderTransportFactory : public TPipedTransportFactory
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
TPipedFileReaderTransportFactory() {}
|
|
||||||
TPipedFileReaderTransportFactory(boost::shared_ptr<TTransport> dstTrans)
|
|
||||||
: TPipedTransportFactory(dstTrans)
|
|
||||||
{}
|
|
||||||
virtual ~TPipedFileReaderTransportFactory() {}
|
|
||||||
|
|
||||||
boost::shared_ptr<TTransport> getTransport(boost::shared_ptr<TTransport> srcTrans)
|
|
||||||
{
|
|
||||||
boost::shared_ptr<TFileReaderTransport> pFileReaderTransport = boost::dynamic_pointer_cast<TFileReaderTransport>(srcTrans);
|
|
||||||
|
|
||||||
if (pFileReaderTransport.get() != NULL)
|
|
||||||
{
|
|
||||||
return getFileReaderTransport(pFileReaderTransport);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return boost::shared_ptr<TTransport>();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
boost::shared_ptr<TFileReaderTransport> getFileReaderTransport(boost::shared_ptr<TFileReaderTransport> srcTrans)
|
|
||||||
{
|
|
||||||
return boost::shared_ptr<TFileReaderTransport>(new TPipedFileReaderTransport(srcTrans, dstTrans_));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} // apache::thrift::transport
|
|
||||||
|
|
||||||
@@ -1,164 +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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <thrift/transport/TTransport.h>
|
|
||||||
|
|
||||||
namespace apache
|
|
||||||
{
|
|
||||||
namespace thrift
|
|
||||||
{
|
|
||||||
namespace transport
|
|
||||||
{
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Helper class that provides default implementations of TTransport methods.
|
|
||||||
*
|
|
||||||
* This class provides default implementations of read(), readAll(), write(),
|
|
||||||
* borrow() and consume().
|
|
||||||
*
|
|
||||||
* In the TTransport base class, each of these methods simply invokes its
|
|
||||||
* virtual counterpart. This class overrides them to always perform the
|
|
||||||
* default behavior, without a virtual function call.
|
|
||||||
*
|
|
||||||
* The primary purpose of this class is to serve as a base class for
|
|
||||||
* TVirtualTransport, and prevent infinite recursion if one of its subclasses
|
|
||||||
* does not override the TTransport implementation of these methods. (Since
|
|
||||||
* TVirtualTransport::read_virt() calls read(), and TTransport::read() calls
|
|
||||||
* read_virt().)
|
|
||||||
*/
|
|
||||||
class TTransportDefaults : public TTransport
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
/*
|
|
||||||
* TTransport *_virt() methods provide reasonable default implementations.
|
|
||||||
* Invoke them non-virtually.
|
|
||||||
*/
|
|
||||||
uint32_t read(uint8_t* buf, uint32_t len)
|
|
||||||
{
|
|
||||||
return this->TTransport::read_virt(buf, len);
|
|
||||||
}
|
|
||||||
uint32_t readAll(uint8_t* buf, uint32_t len)
|
|
||||||
{
|
|
||||||
return this->TTransport::readAll_virt(buf, len);
|
|
||||||
}
|
|
||||||
void write(const uint8_t* buf, uint32_t len)
|
|
||||||
{
|
|
||||||
this->TTransport::write_virt(buf, len);
|
|
||||||
}
|
|
||||||
const uint8_t* borrow(uint8_t* buf, uint32_t* len)
|
|
||||||
{
|
|
||||||
return this->TTransport::borrow_virt(buf, len);
|
|
||||||
}
|
|
||||||
void consume(uint32_t len)
|
|
||||||
{
|
|
||||||
this->TTransport::consume_virt(len);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
TTransportDefaults() {}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Helper class to provide polymorphism for subclasses of TTransport.
|
|
||||||
*
|
|
||||||
* This class implements *_virt() methods of TTransport, to call the
|
|
||||||
* non-virtual versions of these functions in the proper subclass.
|
|
||||||
*
|
|
||||||
* To define your own transport class using TVirtualTransport:
|
|
||||||
* 1) Derive your subclass from TVirtualTransport<your class>
|
|
||||||
* e.g: class MyTransport : public TVirtualTransport<MyTransport> {
|
|
||||||
* 2) Provide your own implementations of read(), readAll(), etc.
|
|
||||||
* These methods should be non-virtual.
|
|
||||||
*
|
|
||||||
* Transport implementations that need to use virtual inheritance when
|
|
||||||
* inheriting from TTransport cannot use TVirtualTransport.
|
|
||||||
*
|
|
||||||
* @author Chad Walters <chad@powerset.com>
|
|
||||||
*/
|
|
||||||
template <class Transport_, class Super_ = TTransportDefaults>
|
|
||||||
class TVirtualTransport : public Super_
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
/*
|
|
||||||
* Implementations of the *_virt() functions, to call the subclass's
|
|
||||||
* non-virtual implementation function.
|
|
||||||
*/
|
|
||||||
virtual uint32_t read_virt(uint8_t* buf, uint32_t len)
|
|
||||||
{
|
|
||||||
return static_cast<Transport_*>(this)->read(buf, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual uint32_t readAll_virt(uint8_t* buf, uint32_t len)
|
|
||||||
{
|
|
||||||
return static_cast<Transport_*>(this)->readAll(buf, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void write_virt(const uint8_t* buf, uint32_t len)
|
|
||||||
{
|
|
||||||
static_cast<Transport_*>(this)->write(buf, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual const uint8_t* borrow_virt(uint8_t* buf, uint32_t* len)
|
|
||||||
{
|
|
||||||
return static_cast<Transport_*>(this)->borrow(buf, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void consume_virt(uint32_t len)
|
|
||||||
{
|
|
||||||
static_cast<Transport_*>(this)->consume(len);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Provide a default readAll() implementation that invokes
|
|
||||||
* read() non-virtually.
|
|
||||||
*
|
|
||||||
* Note: subclasses that use TVirtualTransport to derive from another
|
|
||||||
* transport implementation (i.e., not TTransportDefaults) should beware that
|
|
||||||
* this may override any non-default readAll() implementation provided by
|
|
||||||
* the parent transport class. They may need to redefine readAll() to call
|
|
||||||
* the correct parent implementation, if desired.
|
|
||||||
*/
|
|
||||||
uint32_t readAll(uint8_t* buf, uint32_t len)
|
|
||||||
{
|
|
||||||
Transport_* trans = static_cast<Transport_*>(this);
|
|
||||||
return ::apache::thrift::transport::readAll(*trans, buf, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
TVirtualTransport() {}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Templatized constructors, to allow arguments to be passed to the Super_
|
|
||||||
* constructor. Currently we only support 0, 1, or 2 arguments, but
|
|
||||||
* additional versions can be added as needed.
|
|
||||||
*/
|
|
||||||
template <typename Arg_>
|
|
||||||
TVirtualTransport(Arg_ const& arg) : Super_(arg) { }
|
|
||||||
|
|
||||||
template <typename Arg1_, typename Arg2_>
|
|
||||||
TVirtualTransport(Arg1_ const& a1, Arg2_ const& a2) : Super_(a1, a2) { }
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} // apache::thrift::transport
|
|
||||||
|
|
||||||
@@ -1,276 +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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <boost/lexical_cast.hpp>
|
|
||||||
#include <thrift/transport/TTransport.h>
|
|
||||||
#include <thrift/transport/TVirtualTransport.h>
|
|
||||||
#include <zlib.h>
|
|
||||||
|
|
||||||
struct z_stream_s;
|
|
||||||
|
|
||||||
namespace apache
|
|
||||||
{
|
|
||||||
namespace thrift
|
|
||||||
{
|
|
||||||
namespace transport
|
|
||||||
{
|
|
||||||
|
|
||||||
class TZlibTransportException : public TTransportException
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
TZlibTransportException(int status, const char* msg) :
|
|
||||||
TTransportException(TTransportException::INTERNAL_ERROR,
|
|
||||||
errorMessage(status, msg)),
|
|
||||||
zlib_status_(status),
|
|
||||||
zlib_msg_(msg == NULL ? "(null)" : msg) {}
|
|
||||||
|
|
||||||
virtual ~TZlibTransportException() throw() {}
|
|
||||||
|
|
||||||
int getZlibStatus()
|
|
||||||
{
|
|
||||||
return zlib_status_;
|
|
||||||
}
|
|
||||||
std::string getZlibMessage()
|
|
||||||
{
|
|
||||||
return zlib_msg_;
|
|
||||||
}
|
|
||||||
|
|
||||||
static std::string errorMessage(int status, const char* msg)
|
|
||||||
{
|
|
||||||
std::string rv = "zlib error: ";
|
|
||||||
|
|
||||||
if (msg)
|
|
||||||
{
|
|
||||||
rv += msg;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
rv += "(no message)";
|
|
||||||
}
|
|
||||||
|
|
||||||
rv += " (status = ";
|
|
||||||
rv += boost::lexical_cast<std::string>(status);
|
|
||||||
rv += ")";
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
int zlib_status_;
|
|
||||||
std::string zlib_msg_;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This transport uses zlib to compress on write and decompress on read
|
|
||||||
*
|
|
||||||
* TODO(dreiss): Don't do an extra copy of the compressed data if
|
|
||||||
* the underlying transport is TBuffered or TMemory.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
class TZlibTransport : public TVirtualTransport<TZlibTransport>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param transport The transport to read compressed data from
|
|
||||||
* and write compressed data to.
|
|
||||||
* @param urbuf_size Uncompressed buffer size for reading.
|
|
||||||
* @param crbuf_size Compressed buffer size for reading.
|
|
||||||
* @param uwbuf_size Uncompressed buffer size for writing.
|
|
||||||
* @param cwbuf_size Compressed buffer size for writing.
|
|
||||||
* @param comp_level Compression level (0=none[fast], 6=default, 9=max[slow]).
|
|
||||||
*/
|
|
||||||
TZlibTransport(boost::shared_ptr<TTransport> transport,
|
|
||||||
int urbuf_size = DEFAULT_URBUF_SIZE,
|
|
||||||
int crbuf_size = DEFAULT_CRBUF_SIZE,
|
|
||||||
int uwbuf_size = DEFAULT_UWBUF_SIZE,
|
|
||||||
int cwbuf_size = DEFAULT_CWBUF_SIZE,
|
|
||||||
int16_t comp_level = Z_DEFAULT_COMPRESSION) :
|
|
||||||
transport_(transport),
|
|
||||||
urpos_(0),
|
|
||||||
uwpos_(0),
|
|
||||||
input_ended_(false),
|
|
||||||
output_finished_(false),
|
|
||||||
urbuf_size_(urbuf_size),
|
|
||||||
crbuf_size_(crbuf_size),
|
|
||||||
uwbuf_size_(uwbuf_size),
|
|
||||||
cwbuf_size_(cwbuf_size),
|
|
||||||
urbuf_(NULL),
|
|
||||||
crbuf_(NULL),
|
|
||||||
uwbuf_(NULL),
|
|
||||||
cwbuf_(NULL),
|
|
||||||
rstream_(NULL),
|
|
||||||
wstream_(NULL),
|
|
||||||
comp_level_(comp_level)
|
|
||||||
{
|
|
||||||
if (uwbuf_size_ < MIN_DIRECT_DEFLATE_SIZE)
|
|
||||||
{
|
|
||||||
// Have to copy this into a local because of a linking issue.
|
|
||||||
int minimum = MIN_DIRECT_DEFLATE_SIZE;
|
|
||||||
throw TTransportException(
|
|
||||||
TTransportException::BAD_ARGS,
|
|
||||||
"TZLibTransport: uncompressed write buffer must be at least"
|
|
||||||
+ boost::lexical_cast<std::string>(minimum) + ".");
|
|
||||||
}
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
urbuf_ = new uint8_t[urbuf_size];
|
|
||||||
crbuf_ = new uint8_t[crbuf_size];
|
|
||||||
uwbuf_ = new uint8_t[uwbuf_size];
|
|
||||||
cwbuf_ = new uint8_t[cwbuf_size];
|
|
||||||
|
|
||||||
// Don't call this outside of the constructor.
|
|
||||||
initZlib();
|
|
||||||
|
|
||||||
}
|
|
||||||
catch (...)
|
|
||||||
{
|
|
||||||
delete[] urbuf_;
|
|
||||||
delete[] crbuf_;
|
|
||||||
delete[] uwbuf_;
|
|
||||||
delete[] cwbuf_;
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Don't call this outside of the constructor.
|
|
||||||
void initZlib();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* TZlibTransport destructor.
|
|
||||||
*
|
|
||||||
* Warning: Destroying a TZlibTransport object may discard any written but
|
|
||||||
* unflushed data. You must explicitly call flush() or finish() to ensure
|
|
||||||
* that data is actually written and flushed to the underlying transport.
|
|
||||||
*/
|
|
||||||
~TZlibTransport();
|
|
||||||
|
|
||||||
bool isOpen();
|
|
||||||
bool peek();
|
|
||||||
|
|
||||||
void open()
|
|
||||||
{
|
|
||||||
transport_->open();
|
|
||||||
}
|
|
||||||
|
|
||||||
void close()
|
|
||||||
{
|
|
||||||
transport_->close();
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t read(uint8_t* buf, uint32_t len);
|
|
||||||
|
|
||||||
void write(const uint8_t* buf, uint32_t len);
|
|
||||||
|
|
||||||
void flush();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Finalize the zlib stream.
|
|
||||||
*
|
|
||||||
* This causes zlib to flush any pending write data and write end-of-stream
|
|
||||||
* information, including the checksum. Once finish() has been called, no
|
|
||||||
* new data can be written to the stream.
|
|
||||||
*/
|
|
||||||
void finish();
|
|
||||||
|
|
||||||
const uint8_t* borrow(uint8_t* buf, uint32_t* len);
|
|
||||||
|
|
||||||
void consume(uint32_t len);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Verify the checksum at the end of the zlib stream.
|
|
||||||
*
|
|
||||||
* This may only be called after all data has been read.
|
|
||||||
* It verifies the checksum that was written by the finish() call.
|
|
||||||
*/
|
|
||||||
void verifyChecksum();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* TODO(someone_smart): Choose smart defaults.
|
|
||||||
*/
|
|
||||||
static const int DEFAULT_URBUF_SIZE = 128;
|
|
||||||
static const int DEFAULT_CRBUF_SIZE = 1024;
|
|
||||||
static const int DEFAULT_UWBUF_SIZE = 128;
|
|
||||||
static const int DEFAULT_CWBUF_SIZE = 1024;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
|
|
||||||
inline void checkZlibRv(int status, const char* msg);
|
|
||||||
inline void checkZlibRvNothrow(int status, const char* msg);
|
|
||||||
inline int readAvail();
|
|
||||||
void flushToTransport(int flush);
|
|
||||||
void flushToZlib(const uint8_t* buf, int len, int flush);
|
|
||||||
bool readFromZlib();
|
|
||||||
|
|
||||||
protected:
|
|
||||||
// Writes smaller than this are buffered up.
|
|
||||||
// Larger (or equal) writes are dumped straight to zlib.
|
|
||||||
static const uint32_t MIN_DIRECT_DEFLATE_SIZE = 32;
|
|
||||||
|
|
||||||
boost::shared_ptr<TTransport> transport_;
|
|
||||||
|
|
||||||
int urpos_;
|
|
||||||
int uwpos_;
|
|
||||||
|
|
||||||
/// True iff zlib has reached the end of the input stream.
|
|
||||||
bool input_ended_;
|
|
||||||
/// True iff we have finished the output stream.
|
|
||||||
bool output_finished_;
|
|
||||||
|
|
||||||
uint32_t urbuf_size_;
|
|
||||||
uint32_t crbuf_size_;
|
|
||||||
uint32_t uwbuf_size_;
|
|
||||||
uint32_t cwbuf_size_;
|
|
||||||
|
|
||||||
uint8_t* urbuf_;
|
|
||||||
uint8_t* crbuf_;
|
|
||||||
uint8_t* uwbuf_;
|
|
||||||
uint8_t* cwbuf_;
|
|
||||||
|
|
||||||
struct z_stream_s* rstream_;
|
|
||||||
struct z_stream_s* wstream_;
|
|
||||||
|
|
||||||
const int comp_level_;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Wraps a transport into a zlibbed one.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
class TZlibTransportFactory : public TTransportFactory
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
TZlibTransportFactory() {}
|
|
||||||
|
|
||||||
virtual ~TZlibTransportFactory() {}
|
|
||||||
|
|
||||||
virtual boost::shared_ptr<TTransport> getTransport(
|
|
||||||
boost::shared_ptr<TTransport> trans)
|
|
||||||
{
|
|
||||||
return boost::shared_ptr<TTransport>(new TZlibTransport(trans));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} // apache::thrift::transport
|
|
||||||
|
|
||||||
@@ -1,114 +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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <thrift/windows/GetTimeOfDay.h>
|
|
||||||
#include <thrift/thrift-config.h>
|
|
||||||
|
|
||||||
// win32
|
|
||||||
#include <time.h>
|
|
||||||
|
|
||||||
#if defined(_MSC_VER) || defined(_MSC_EXTENSIONS)
|
|
||||||
# define DELTA_EPOCH_IN_MICROSECS 11644473600000000Ui64
|
|
||||||
#else
|
|
||||||
# define DELTA_EPOCH_IN_MICROSECS 11644473600000000ULL
|
|
||||||
#endif
|
|
||||||
|
|
||||||
struct timezone
|
|
||||||
{
|
|
||||||
int tz_minuteswest; /* minutes W of Greenwich */
|
|
||||||
int tz_dsttime; /* type of dst correction */
|
|
||||||
};
|
|
||||||
|
|
||||||
int thrift_gettimeofday(struct timeval* tv, struct timezone* tz)
|
|
||||||
{
|
|
||||||
FILETIME ft;
|
|
||||||
unsigned __int64 tmpres(0);
|
|
||||||
static int tzflag;
|
|
||||||
|
|
||||||
if (NULL != tv)
|
|
||||||
{
|
|
||||||
GetSystemTimeAsFileTime(&ft);
|
|
||||||
|
|
||||||
tmpres |= ft.dwHighDateTime;
|
|
||||||
tmpres <<= 32;
|
|
||||||
tmpres |= ft.dwLowDateTime;
|
|
||||||
|
|
||||||
/*converting file time to unix epoch*/
|
|
||||||
tmpres -= DELTA_EPOCH_IN_MICROSECS;
|
|
||||||
tmpres /= 10; /*convert into microseconds*/
|
|
||||||
tv->tv_sec = (long)(tmpres / 1000000UL);
|
|
||||||
tv->tv_usec = (long)(tmpres % 1000000UL);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (NULL != tz)
|
|
||||||
{
|
|
||||||
if (!tzflag)
|
|
||||||
{
|
|
||||||
_tzset();
|
|
||||||
tzflag++;
|
|
||||||
}
|
|
||||||
|
|
||||||
long time_zone(0);
|
|
||||||
errno_t err(_get_timezone(&time_zone));
|
|
||||||
|
|
||||||
if (err == NO_ERROR)
|
|
||||||
{
|
|
||||||
tz->tz_minuteswest = time_zone / 60;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int day_light(0);
|
|
||||||
err = (_get_daylight(&day_light));
|
|
||||||
|
|
||||||
if (err == NO_ERROR)
|
|
||||||
{
|
|
||||||
tz->tz_dsttime = day_light;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int thrift_sleep(unsigned int seconds)
|
|
||||||
{
|
|
||||||
::Sleep(seconds * 1000);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
int thrift_usleep(unsigned int microseconds)
|
|
||||||
{
|
|
||||||
unsigned int milliseconds = (microseconds + 999) / 1000;
|
|
||||||
::Sleep(milliseconds);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
char* thrift_ctime_r(const time_t* _clock, char* _buf)
|
|
||||||
{
|
|
||||||
strcpy(_buf, ctime(_clock));
|
|
||||||
return _buf;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,42 +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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#if defined(_MSC_VER) && (_MSC_VER > 1200)
|
|
||||||
#pragma once
|
|
||||||
#endif // _MSC_VER
|
|
||||||
|
|
||||||
#ifndef _WIN32
|
|
||||||
#error This is a MSVC header only.
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <thrift/thrift-config.h>
|
|
||||||
|
|
||||||
struct thrift_timespec
|
|
||||||
{
|
|
||||||
int64_t tv_sec;
|
|
||||||
int64_t tv_nsec;
|
|
||||||
};
|
|
||||||
|
|
||||||
int thrift_gettimeofday(struct timeval* tv, struct timezone* tz);
|
|
||||||
int thrift_sleep(unsigned int seconds);
|
|
||||||
int thrift_usleep(unsigned int micro_seconds);
|
|
||||||
char* thrift_ctime_r(const time_t* _clock, char* _buf);
|
|
||||||
|
|
||||||
@@ -1,42 +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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#if defined(_MSC_VER) && (_MSC_VER > 1200)
|
|
||||||
#pragma once
|
|
||||||
#endif // _MSC_VER
|
|
||||||
|
|
||||||
namespace apache
|
|
||||||
{
|
|
||||||
namespace thrift
|
|
||||||
{
|
|
||||||
|
|
||||||
class TEnumIterator;
|
|
||||||
|
|
||||||
inline bool operator == (const TEnumIterator&, const TEnumIterator&)
|
|
||||||
{
|
|
||||||
// Not entirely sure what the test should be here. It is only to enable
|
|
||||||
// iterator debugging and is not used in release mode.
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
} // apache::thrift
|
|
||||||
|
|
||||||
@@ -1,35 +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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#if defined(_MSC_VER) && (_MSC_VER > 1200)
|
|
||||||
#pragma once
|
|
||||||
#endif // _MSC_VER
|
|
||||||
|
|
||||||
#ifndef _WIN32
|
|
||||||
#error This is a MSVC header only.
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Win32
|
|
||||||
#include <Winsock2.h>
|
|
||||||
#include <thrift/thrift-config.h>
|
|
||||||
|
|
||||||
int thrift_socketpair(int d, int type, int protocol, THRIFT_SOCKET sv[2]);
|
|
||||||
|
|
||||||
@@ -1,81 +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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <thrift/windows/TWinsockSingleton.h>
|
|
||||||
|
|
||||||
// boost
|
|
||||||
#include <boost/assert.hpp>
|
|
||||||
#include <stdexcept>
|
|
||||||
|
|
||||||
namespace apache
|
|
||||||
{
|
|
||||||
namespace thrift
|
|
||||||
{
|
|
||||||
namespace transport
|
|
||||||
{
|
|
||||||
|
|
||||||
TWinsockSingleton::instance_ptr TWinsockSingleton::instance_ptr_(NULL);
|
|
||||||
#if USE_BOOST_THREAD
|
|
||||||
boost::once_flag TWinsockSingleton::flags_ = BOOST_ONCE_INIT;
|
|
||||||
#elif USE_STD_THREAD
|
|
||||||
std::once_flag TWinsockSingleton::flags_;
|
|
||||||
#else
|
|
||||||
#error For windows you must choose USE_BOOST_THREAD or USE_STD_THREAD
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
TWinsockSingleton::TWinsockSingleton(void)
|
|
||||||
{
|
|
||||||
WORD version(MAKEWORD(2, 2));
|
|
||||||
WSAData data = {0};
|
|
||||||
|
|
||||||
int error(WSAStartup(version, &data));
|
|
||||||
|
|
||||||
if (error != 0)
|
|
||||||
{
|
|
||||||
BOOST_ASSERT(false);
|
|
||||||
throw std::runtime_error("Failed to initialise Winsock.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
TWinsockSingleton::~TWinsockSingleton(void)
|
|
||||||
{
|
|
||||||
WSACleanup();
|
|
||||||
}
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
void TWinsockSingleton::create(void)
|
|
||||||
{
|
|
||||||
#if USE_BOOST_THREAD
|
|
||||||
boost::call_once(init, flags_);
|
|
||||||
#elif USE_STD_THREAD
|
|
||||||
std::call_once(flags_, init);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
void TWinsockSingleton::init(void)
|
|
||||||
{
|
|
||||||
instance_ptr_.reset(new TWinsockSingleton);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} // apache::thrift::transport
|
|
||||||
@@ -1,93 +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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#if defined(_MSC_VER) && (_MSC_VER > 1200)
|
|
||||||
#pragma once
|
|
||||||
#endif // _MSC_VER
|
|
||||||
|
|
||||||
#ifndef _WIN32
|
|
||||||
#error This is a MSVC header only.
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <thrift/thrift-config.h>
|
|
||||||
|
|
||||||
// boost
|
|
||||||
#include <boost/noncopyable.hpp>
|
|
||||||
#include <boost/scoped_ptr.hpp>
|
|
||||||
|
|
||||||
#if USE_BOOST_THREAD
|
|
||||||
#include <boost/thread/once.hpp>
|
|
||||||
#elif USE_STD_THREAD
|
|
||||||
#include <mutex>
|
|
||||||
#else
|
|
||||||
#error For windows you must choose USE_BOOST_THREAD or USE_STD_THREAD
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace apache
|
|
||||||
{
|
|
||||||
namespace thrift
|
|
||||||
{
|
|
||||||
namespace transport
|
|
||||||
{
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Winsock2 must be intialised once only in order to create sockets. This class
|
|
||||||
* performs a one time initialisation when create is called.
|
|
||||||
*/
|
|
||||||
class TWinsockSingleton : private boost::noncopyable
|
|
||||||
{
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
typedef boost::scoped_ptr<TWinsockSingleton> instance_ptr;
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
TWinsockSingleton(void);
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
~TWinsockSingleton(void);
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
static void create(void);
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
static void init(void);
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
static instance_ptr instance_ptr_;
|
|
||||||
#if USE_BOOST_THREAD
|
|
||||||
static boost::once_flag flags_;
|
|
||||||
#elif USE_STD_THREAD
|
|
||||||
static std::once_flag flags_;
|
|
||||||
#else
|
|
||||||
#error Need a non-Boost non-C++11 way to track single initialization here.
|
|
||||||
#endif
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} // apache::thrift::transport
|
|
||||||
|
|
||||||
@@ -1,117 +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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <thrift/windows/WinFcntl.h>
|
|
||||||
|
|
||||||
int thrift_fcntl(THRIFT_SOCKET fd, int cmd, int flags)
|
|
||||||
{
|
|
||||||
if (cmd != THRIFT_F_GETFL && cmd != THRIFT_F_SETFL)
|
|
||||||
{
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (flags != THRIFT_O_NONBLOCK && flags != 0)
|
|
||||||
{
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cmd == THRIFT_F_GETFL)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int res;
|
|
||||||
|
|
||||||
if (flags)
|
|
||||||
{
|
|
||||||
res = ioctlsocket(fd, FIONBIO, reinterpret_cast<u_long*>(&(flags = 1)));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
res = ioctlsocket(fd, FIONBIO, reinterpret_cast<u_long*>(&(flags = 0)));
|
|
||||||
}
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if WINVER <= 0x0502 //XP, Server2003
|
|
||||||
int thrift_poll(THRIFT_POLLFD* fdArray, ULONG nfds, INT timeout)
|
|
||||||
{
|
|
||||||
fd_set read_fds, write_fds;
|
|
||||||
fd_set* read_fds_ptr = NULL;
|
|
||||||
fd_set* write_fds_ptr = NULL;
|
|
||||||
|
|
||||||
FD_ZERO(&read_fds);
|
|
||||||
FD_ZERO(&write_fds);
|
|
||||||
|
|
||||||
for (ULONG i = 0; i < nfds; i++)
|
|
||||||
{
|
|
||||||
//Read (in) socket
|
|
||||||
if ((fdArray[i].events & THRIFT_POLLIN) == THRIFT_POLLIN)
|
|
||||||
{
|
|
||||||
read_fds_ptr = &read_fds;
|
|
||||||
FD_SET(fdArray[i].fd, &read_fds);
|
|
||||||
}
|
|
||||||
//Write (out) socket
|
|
||||||
else if ((fdArray[i].events & THRIFT_POLLOUT) == THRIFT_POLLOUT)
|
|
||||||
{
|
|
||||||
write_fds_ptr = &write_fds;
|
|
||||||
FD_SET(fdArray[i].fd, &write_fds);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
timeval time_out;
|
|
||||||
timeval* time_out_ptr = NULL;
|
|
||||||
|
|
||||||
if (timeout >= 0)
|
|
||||||
{
|
|
||||||
timeval time_out = {timeout / 1000, timeout * 1000};
|
|
||||||
time_out_ptr = &time_out;
|
|
||||||
}
|
|
||||||
else //to avoid compiler warnings
|
|
||||||
{
|
|
||||||
(void)time_out;
|
|
||||||
(void)timeout;
|
|
||||||
}
|
|
||||||
|
|
||||||
int sktready = select(1, read_fds_ptr, write_fds_ptr, NULL, time_out_ptr);
|
|
||||||
|
|
||||||
if (sktready > 0)
|
|
||||||
{
|
|
||||||
for (ULONG i = 0; i < nfds; i++)
|
|
||||||
{
|
|
||||||
fdArray[i].revents = 0;
|
|
||||||
|
|
||||||
if (FD_ISSET(fdArray[i].fd, &read_fds))
|
|
||||||
fdArray[i].revents |= THRIFT_POLLIN;
|
|
||||||
|
|
||||||
if (FD_ISSET(fdArray[i].fd, &write_fds))
|
|
||||||
fdArray[i].revents |= THRIFT_POLLOUT;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return sktready;
|
|
||||||
}
|
|
||||||
#else //Vista, Win7...
|
|
||||||
int thrift_poll(THRIFT_POLLFD* fdArray, ULONG nfds, INT timeout)
|
|
||||||
{
|
|
||||||
return WSAPoll(fdArray, nfds, timeout);
|
|
||||||
}
|
|
||||||
#endif // WINVER
|
|
||||||
|
|
||||||
@@ -1,47 +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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#if defined(_MSC_VER) && (_MSC_VER > 1200)
|
|
||||||
#pragma once
|
|
||||||
#endif // _MSC_VER
|
|
||||||
|
|
||||||
#ifndef _WIN32
|
|
||||||
#error This is a MSVC header only.
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Win32
|
|
||||||
#include <Winsock2.h>
|
|
||||||
#include <thrift/transport/PlatformSocket.h>
|
|
||||||
|
|
||||||
#if WINVER <= 0x0502 //XP, Server2003
|
|
||||||
struct thrift_pollfd
|
|
||||||
{
|
|
||||||
THRIFT_SOCKET fd;
|
|
||||||
SHORT events;
|
|
||||||
SHORT revents;
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
|
|
||||||
extern "C" {
|
|
||||||
int thrift_fcntl(THRIFT_SOCKET fd, int cmd, int flags);
|
|
||||||
int thrift_poll(THRIFT_POLLFD* fdArray, ULONG nfds, INT timeout);
|
|
||||||
}
|
|
||||||
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user