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(misc)
|
||||
INCLUDE(boost)
|
||||
INCLUDE(thrift)
|
||||
|
||||
FIND_PACKAGE(BISON)
|
||||
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_OAM_LIBS oamcpp)
|
||||
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 (PLUGIN_WRITE_LIBS ddlpackageproc ddlpackage dmlpackageproc dmlpackage writeengine writeengineclient idbdatafile cacheutils)
|
||||
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_MYSQLCL_INCLUDE "${CMAKE_CURRENT_SOURCE_DIR}/utils/mysqlcl_idb")
|
||||
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_THREADPOOL_INCLUDE "${CMAKE_CURRENT_SOURCE_DIR}/utils/threadpool")
|
||||
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/*/libstoragemanager.so
|
||||
usr/lib/*/libthreadpool.so
|
||||
usr/lib/*/libthrift.so
|
||||
usr/lib/*/libudfsdk.so
|
||||
usr/lib/*/libwindowfunction.so
|
||||
usr/lib/*/libwriteengine.so
|
||||
|
||||
@@ -20,7 +20,6 @@ add_subdirectory(querystats)
|
||||
add_subdirectory(windowfunction)
|
||||
add_subdirectory(idbdatafile)
|
||||
add_subdirectory(winport)
|
||||
add_subdirectory(thrift)
|
||||
add_subdirectory(querytele)
|
||||
add_subdirectory(libmysql_client)
|
||||
add_subdirectory(regr)
|
||||
|
||||
@@ -13,7 +13,9 @@ set(querytele_LIB_SRCS
|
||||
queryteleprotoimpl.cpp)
|
||||
|
||||
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)
|
||||
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
::apache::thrift::ReleaseHandler<QueryTeleServiceIfFactory> cleanup(handlerFactory_);
|
||||
::boost::shared_ptr<QueryTeleServiceIf> handler(handlerFactory_->getHandler(connInfo), cleanup);
|
||||
::boost::shared_ptr< ::apache::thrift::TProcessor> processor(new QueryTeleServiceProcessor(handler));
|
||||
::std::shared_ptr<QueryTeleServiceIf> handler(handlerFactory_->getHandler(connInfo), cleanup);
|
||||
::std::shared_ptr< ::apache::thrift::TProcessor> processor(new QueryTeleServiceProcessor(handler));
|
||||
return processor;
|
||||
}
|
||||
} // namespace querytele
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include <thrift/TDispatchProcessor.h>
|
||||
#include "querytele_types.h"
|
||||
|
||||
|
||||
namespace querytele
|
||||
{
|
||||
class QueryTeleServiceIf
|
||||
@@ -38,7 +39,7 @@ class QueryTeleServiceIfFactory
|
||||
class QueryTeleServiceIfSingletonFactory : virtual public QueryTeleServiceIfFactory
|
||||
{
|
||||
public:
|
||||
QueryTeleServiceIfSingletonFactory(const boost::shared_ptr<QueryTeleServiceIf>& iface) : iface_(iface)
|
||||
QueryTeleServiceIfSingletonFactory(const std::shared_ptr<QueryTeleServiceIf>& iface) : iface_(iface)
|
||||
{
|
||||
}
|
||||
virtual ~QueryTeleServiceIfSingletonFactory()
|
||||
@@ -54,7 +55,7 @@ class QueryTeleServiceIfSingletonFactory : virtual public QueryTeleServiceIfFact
|
||||
}
|
||||
|
||||
protected:
|
||||
boost::shared_ptr<QueryTeleServiceIf> iface_;
|
||||
std::shared_ptr<QueryTeleServiceIf> iface_;
|
||||
};
|
||||
|
||||
class QueryTeleServiceNull : virtual public QueryTeleServiceIf
|
||||
@@ -362,24 +363,24 @@ class QueryTeleService_postImport_presult
|
||||
class QueryTeleServiceClient : virtual public QueryTeleServiceIf
|
||||
{
|
||||
public:
|
||||
QueryTeleServiceClient(boost::shared_ptr< ::apache::thrift::protocol::TProtocol> prot)
|
||||
QueryTeleServiceClient(std::shared_ptr< ::apache::thrift::protocol::TProtocol> prot)
|
||||
: piprot_(prot), poprot_(prot)
|
||||
{
|
||||
iprot_ = prot.get();
|
||||
oprot_ = prot.get();
|
||||
}
|
||||
QueryTeleServiceClient(boost::shared_ptr< ::apache::thrift::protocol::TProtocol> iprot,
|
||||
boost::shared_ptr< ::apache::thrift::protocol::TProtocol> oprot)
|
||||
QueryTeleServiceClient(std::shared_ptr< ::apache::thrift::protocol::TProtocol> iprot,
|
||||
std::shared_ptr< ::apache::thrift::protocol::TProtocol> oprot)
|
||||
: piprot_(iprot), poprot_(oprot)
|
||||
{
|
||||
iprot_ = iprot.get();
|
||||
oprot_ = oprot.get();
|
||||
}
|
||||
boost::shared_ptr< ::apache::thrift::protocol::TProtocol> getInputProtocol()
|
||||
std::shared_ptr< ::apache::thrift::protocol::TProtocol> getInputProtocol()
|
||||
{
|
||||
return piprot_;
|
||||
}
|
||||
boost::shared_ptr< ::apache::thrift::protocol::TProtocol> getOutputProtocol()
|
||||
std::shared_ptr< ::apache::thrift::protocol::TProtocol> getOutputProtocol()
|
||||
{
|
||||
return poprot_;
|
||||
}
|
||||
@@ -394,8 +395,8 @@ class QueryTeleServiceClient : virtual public QueryTeleServiceIf
|
||||
void recv_postImport();
|
||||
|
||||
protected:
|
||||
boost::shared_ptr< ::apache::thrift::protocol::TProtocol> piprot_;
|
||||
boost::shared_ptr< ::apache::thrift::protocol::TProtocol> poprot_;
|
||||
std::shared_ptr< ::apache::thrift::protocol::TProtocol> piprot_;
|
||||
std::shared_ptr< ::apache::thrift::protocol::TProtocol> poprot_;
|
||||
::apache::thrift::protocol::TProtocol* iprot_;
|
||||
::apache::thrift::protocol::TProtocol* oprot_;
|
||||
};
|
||||
@@ -403,7 +404,7 @@ class QueryTeleServiceClient : virtual public QueryTeleServiceIf
|
||||
class QueryTeleServiceProcessor : public ::apache::thrift::TDispatchProcessor
|
||||
{
|
||||
protected:
|
||||
boost::shared_ptr<QueryTeleServiceIf> iface_;
|
||||
std::shared_ptr<QueryTeleServiceIf> iface_;
|
||||
virtual bool dispatchCall(::apache::thrift::protocol::TProtocol* iprot,
|
||||
::apache::thrift::protocol::TProtocol* oprot, const std::string& fname,
|
||||
int32_t seqid, void* callContext);
|
||||
@@ -421,7 +422,7 @@ class QueryTeleServiceProcessor : public ::apache::thrift::TDispatchProcessor
|
||||
::apache::thrift::protocol::TProtocol* oprot, void* callContext);
|
||||
|
||||
public:
|
||||
QueryTeleServiceProcessor(boost::shared_ptr<QueryTeleServiceIf> iface) : iface_(iface)
|
||||
QueryTeleServiceProcessor(std::shared_ptr<QueryTeleServiceIf> iface) : iface_(iface)
|
||||
{
|
||||
processMap_["postQuery"] = &QueryTeleServiceProcessor::process_postQuery;
|
||||
processMap_["postStep"] = &QueryTeleServiceProcessor::process_postStep;
|
||||
@@ -436,22 +437,22 @@ class QueryTeleServiceProcessor : public ::apache::thrift::TDispatchProcessor
|
||||
class QueryTeleServiceProcessorFactory : public ::apache::thrift::TProcessorFactory
|
||||
{
|
||||
public:
|
||||
QueryTeleServiceProcessorFactory(const ::boost::shared_ptr<QueryTeleServiceIfFactory>& handlerFactory)
|
||||
QueryTeleServiceProcessorFactory(const ::std::shared_ptr<QueryTeleServiceIfFactory>& handlerFactory)
|
||||
: handlerFactory_(handlerFactory)
|
||||
{
|
||||
}
|
||||
|
||||
::boost::shared_ptr< ::apache::thrift::TProcessor> getProcessor(
|
||||
::std::shared_ptr< ::apache::thrift::TProcessor> getProcessor(
|
||||
const ::apache::thrift::TConnectionInfo& connInfo);
|
||||
|
||||
protected:
|
||||
::boost::shared_ptr<QueryTeleServiceIfFactory> handlerFactory_;
|
||||
::std::shared_ptr<QueryTeleServiceIfFactory> handlerFactory_;
|
||||
};
|
||||
|
||||
class QueryTeleServiceMultiface : virtual public QueryTeleServiceIf
|
||||
{
|
||||
public:
|
||||
QueryTeleServiceMultiface(std::vector<boost::shared_ptr<QueryTeleServiceIf> >& ifaces) : ifaces_(ifaces)
|
||||
QueryTeleServiceMultiface(std::vector<std::shared_ptr<QueryTeleServiceIf> >& ifaces) : ifaces_(ifaces)
|
||||
{
|
||||
}
|
||||
virtual ~QueryTeleServiceMultiface()
|
||||
@@ -459,11 +460,11 @@ class QueryTeleServiceMultiface : virtual public QueryTeleServiceIf
|
||||
}
|
||||
|
||||
protected:
|
||||
std::vector<boost::shared_ptr<QueryTeleServiceIf> > ifaces_;
|
||||
std::vector<std::shared_ptr<QueryTeleServiceIf> > ifaces_;
|
||||
QueryTeleServiceMultiface()
|
||||
{
|
||||
}
|
||||
void add(boost::shared_ptr<QueryTeleServiceIf> iface)
|
||||
void add(std::shared_ptr<QueryTeleServiceIf> iface)
|
||||
{
|
||||
ifaces_.push_back(iface);
|
||||
}
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
#include <thrift/protocol/TProtocol.h>
|
||||
#include <thrift/transport/TTransport.h>
|
||||
|
||||
#include <thrift/cxxfunctional.h>
|
||||
|
||||
namespace querytele
|
||||
{
|
||||
|
||||
@@ -22,7 +22,6 @@ using namespace std;
|
||||
|
||||
#define BOOST_DISABLE_ASSERTS
|
||||
#include <boost/thread.hpp>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
|
||||
#include "thrift/transport/TSocket.h"
|
||||
#include "thrift/transport/TBufferTransports.h"
|
||||
@@ -59,9 +58,9 @@ TsTeleQueue<querytele::ImportTele> itQueue;
|
||||
volatile bool isInited = false;
|
||||
boost::mutex initMux;
|
||||
|
||||
boost::shared_ptr<att::TSocket> fSocket;
|
||||
boost::shared_ptr<att::TBufferedTransport> fTransport;
|
||||
boost::shared_ptr<atp::TBinaryProtocol> fProtocol;
|
||||
std::shared_ptr<att::TSocket> fSocket;
|
||||
std::shared_ptr<att::TBufferedTransport> fTransport;
|
||||
std::shared_ptr<atp::TBinaryProtocol> fProtocol;
|
||||
|
||||
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