Checking in vendor folder for ease of using go get.
This commit is contained in:
parent
7a1251853b
commit
cdb4b5a1d0
3554 changed files with 1270116 additions and 0 deletions
81
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/TApplicationException.cpp
generated
vendored
Normal file
81
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/TApplicationException.cpp
generated
vendored
Normal file
|
@ -0,0 +1,81 @@
|
|||
/*
|
||||
* 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
|
115
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/TApplicationException.h
generated
vendored
Normal file
115
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/TApplicationException.h
generated
vendored
Normal file
|
@ -0,0 +1,115 @@
|
|||
/*
|
||||
* 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_TAPPLICATIONEXCEPTION_H_
|
||||
#define _THRIFT_TAPPLICATIONEXCEPTION_H_ 1
|
||||
|
||||
#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() const { 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
|
||||
|
||||
#endif // #ifndef _THRIFT_TAPPLICATIONEXCEPTION_H_
|
38
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/TBase.h
generated
vendored
Normal file
38
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/TBase.h
generated
vendored
Normal file
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* 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_TBASE_H_
|
||||
#define _THRIFT_TBASE_H_ 1
|
||||
|
||||
#include <thrift/Thrift.h>
|
||||
#include <thrift/protocol/TProtocol.h>
|
||||
|
||||
namespace apache {
|
||||
namespace thrift {
|
||||
|
||||
class TBase {
|
||||
public:
|
||||
virtual ~TBase(){};
|
||||
virtual uint32_t read(protocol::TProtocol* iprot) = 0;
|
||||
virtual uint32_t write(protocol::TProtocol* oprot) const = 0;
|
||||
};
|
||||
}
|
||||
} // apache::thrift
|
||||
|
||||
#endif // #ifndef _THRIFT_TBASE_H_
|
141
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/TDispatchProcessor.h
generated
vendored
Normal file
141
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/TDispatchProcessor.h
generated
vendored
Normal file
|
@ -0,0 +1,141 @@
|
|||
/*
|
||||
* 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_TDISPATCHPROCESSOR_H_
|
||||
#define _THRIFT_TDISPATCHPROCESSOR_H_ 1
|
||||
|
||||
#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
|
||||
|
||||
#endif // _THRIFT_TDISPATCHPROCESSOR_H_
|
195
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/TLogging.h
generated
vendored
Normal file
195
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/TLogging.h
generated
vendored
Normal file
|
@ -0,0 +1,195 @@
|
|||
/*
|
||||
* 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_TLOGGING_H_
|
||||
#define _THRIFT_TLOGGING_H_ 1
|
||||
|
||||
#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
|
||||
|
||||
/**
|
||||
* analogous 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
|
||||
|
||||
/**
|
||||
* analogous 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__); \
|
||||
}
|
||||
|
||||
/**
|
||||
* Analogous 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
|
||||
|
||||
#endif // #ifndef _THRIFT_TLOGGING_H_
|
126
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/TOutput.cpp
generated
vendored
Normal file
126
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/TOutput.cpp
generated
vendored
Normal file
|
@ -0,0 +1,126 @@
|
|||
/*
|
||||
* 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
|
58
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/TOutput.h
generated
vendored
Normal file
58
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/TOutput.h
generated
vendored
Normal file
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
#ifndef _THRIFT_OUTPUT_H_
|
||||
#define _THRIFT_OUTPUT_H_ 1
|
||||
|
||||
namespace apache {
|
||||
namespace thrift {
|
||||
|
||||
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;
|
||||
}
|
||||
} // namespace apache::thrift
|
||||
|
||||
#endif //_THRIFT_OUTPUT_H_
|
230
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/TProcessor.h
generated
vendored
Normal file
230
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/TProcessor.h
generated
vendored
Normal file
|
@ -0,0 +1,230 @@
|
|||
/*
|
||||
* 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_TPROCESSOR_H_
|
||||
#define _THRIFT_TPROCESSOR_H_ 1
|
||||
|
||||
#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() const { 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
|
||||
|
||||
#endif // #ifndef _THRIFT_TPROCESSOR_H_
|
89
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/TToString.h
generated
vendored
Normal file
89
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/TToString.h
generated
vendored
Normal file
|
@ -0,0 +1,89 @@
|
|||
/*
|
||||
* 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_TOSTRING_H_
|
||||
#define _THRIFT_TOSTRING_H_ 1
|
||||
|
||||
#include <boost/lexical_cast.hpp>
|
||||
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
|
||||
namespace apache {
|
||||
namespace thrift {
|
||||
|
||||
template <typename T>
|
||||
std::string to_string(const T& t) {
|
||||
return boost::lexical_cast<std::string>(t);
|
||||
}
|
||||
|
||||
template <typename K, typename V>
|
||||
std::string to_string(const std::map<K, V>& m);
|
||||
|
||||
template <typename T>
|
||||
std::string to_string(const std::set<T>& s);
|
||||
|
||||
template <typename T>
|
||||
std::string to_string(const std::vector<T>& t);
|
||||
|
||||
template <typename K, typename V>
|
||||
std::string to_string(const typename std::pair<K, V>& v) {
|
||||
std::ostringstream o;
|
||||
o << to_string(v.first) << ": " << to_string(v.second);
|
||||
return o.str();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
std::string to_string(const T& beg, const T& end) {
|
||||
std::ostringstream o;
|
||||
for (T it = beg; it != end; ++it) {
|
||||
if (it != beg)
|
||||
o << ", ";
|
||||
o << to_string(*it);
|
||||
}
|
||||
return o.str();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
std::string to_string(const std::vector<T>& t) {
|
||||
std::ostringstream o;
|
||||
o << "[" << to_string(t.begin(), t.end()) << "]";
|
||||
return o.str();
|
||||
}
|
||||
|
||||
template <typename K, typename V>
|
||||
std::string to_string(const std::map<K, V>& m) {
|
||||
std::ostringstream o;
|
||||
o << "{" << to_string(m.begin(), m.end()) << "}";
|
||||
return o.str();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
std::string to_string(const std::set<T>& s) {
|
||||
std::ostringstream o;
|
||||
o << "{" << to_string(s.begin(), s.end()) << "}";
|
||||
return o.str();
|
||||
}
|
||||
}
|
||||
} // apache::thrift
|
||||
|
||||
#endif // _THRIFT_TOSTRING_H_
|
136
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/Thrift.h
generated
vendored
Normal file
136
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/Thrift.h
generated
vendored
Normal file
|
@ -0,0 +1,136 @@
|
|||
/*
|
||||
* 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_THRIFT_H_
|
||||
#define _THRIFT_THRIFT_H_ 1
|
||||
|
||||
#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>
|
||||
#include <thrift/TOutput.h>
|
||||
|
||||
#define THRIFT_UNUSED_VARIABLE(x) ((void)(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) {
|
||||
THRIFT_UNUSED_VARIABLE(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 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_;
|
||||
};
|
||||
|
||||
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
|
||||
|
||||
#endif // #ifndef _THRIFT_THRIFT_H_
|
425
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/VirtualProfiling.cpp
generated
vendored
Normal file
425
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/VirtualProfiling.cpp
generated
vendored
Normal file
|
@ -0,0 +1,425 @@
|
|||
/*
|
||||
* 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>
|
||||
|
||||
// Do nothing if virtual call profiling is not enabled
|
||||
#if T_GLOBAL_DEBUG_VIRTUAL > 1
|
||||
|
||||
// TODO: This code only works with g++ (since we rely on the fact
|
||||
// that all std::type_info instances referring to a particular type
|
||||
// always return the exact same pointer value from name().)
|
||||
#ifndef __GNUG__
|
||||
#error "Thrift virtual function profiling currently only works with gcc"
|
||||
#endif // !__GNUG__
|
||||
|
||||
// TODO: We also require glibc for the backtrace() and backtrace_symbols()
|
||||
// functions.
|
||||
#ifndef __GLIBC__
|
||||
#error "Thrift virtual function profiling currently requires glibc"
|
||||
#endif // !__GLIBC__
|
||||
|
||||
#include <thrift/concurrency/Mutex.h>
|
||||
|
||||
#include <ext/hash_map>
|
||||
#include <execinfo.h>
|
||||
#include <stdio.h>
|
||||
|
||||
namespace apache {
|
||||
namespace thrift {
|
||||
|
||||
using ::apache::thrift::concurrency::Mutex;
|
||||
using ::apache::thrift::concurrency::Guard;
|
||||
|
||||
static const unsigned int MAX_STACK_DEPTH = 15;
|
||||
|
||||
/**
|
||||
* A stack trace
|
||||
*/
|
||||
class Backtrace {
|
||||
public:
|
||||
Backtrace(int skip = 0);
|
||||
Backtrace(Backtrace const& bt);
|
||||
|
||||
void operator=(Backtrace const& bt) {
|
||||
numCallers_ = bt.numCallers_;
|
||||
if (numCallers_ >= 0) {
|
||||
memcpy(callers_, bt.callers_, numCallers_ * sizeof(void*));
|
||||
}
|
||||
}
|
||||
|
||||
bool operator==(Backtrace const& bt) const { return (cmp(bt) == 0); }
|
||||
|
||||
size_t hash() const {
|
||||
intptr_t ret = 0;
|
||||
for (int n = 0; n < numCallers_; ++n) {
|
||||
ret ^= reinterpret_cast<intptr_t>(callers_[n]);
|
||||
}
|
||||
return static_cast<size_t>(ret);
|
||||
}
|
||||
|
||||
int cmp(Backtrace const& bt) const {
|
||||
int depth_diff = (numCallers_ - bt.numCallers_);
|
||||
if (depth_diff != 0) {
|
||||
return depth_diff;
|
||||
}
|
||||
|
||||
for (int n = 0; n < numCallers_; ++n) {
|
||||
int diff = reinterpret_cast<intptr_t>(callers_[n])
|
||||
- reinterpret_cast<intptr_t>(bt.callers_[n]);
|
||||
if (diff != 0) {
|
||||
return diff;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void print(FILE* f, int indent = 0, int start = 0) const {
|
||||
char** strings = backtrace_symbols(callers_, numCallers_);
|
||||
if (strings) {
|
||||
start += skip_;
|
||||
if (start < 0) {
|
||||
start = 0;
|
||||
}
|
||||
for (int n = start; n < numCallers_; ++n) {
|
||||
fprintf(f, "%*s#%-2d %s\n", indent, "", n, strings[n]);
|
||||
}
|
||||
free(strings);
|
||||
} else {
|
||||
fprintf(f, "%*s<failed to determine symbols>\n", indent, "");
|
||||
}
|
||||
}
|
||||
|
||||
int getDepth() const { return numCallers_ - skip_; }
|
||||
|
||||
void* getFrame(int index) const {
|
||||
int adjusted_index = index + skip_;
|
||||
if (adjusted_index < 0 || adjusted_index >= numCallers_) {
|
||||
return NULL;
|
||||
}
|
||||
return callers_[adjusted_index];
|
||||
}
|
||||
|
||||
private:
|
||||
void* callers_[MAX_STACK_DEPTH];
|
||||
int numCallers_;
|
||||
int skip_;
|
||||
};
|
||||
|
||||
// Define the constructors non-inline, so they consistently add a single
|
||||
// frame to the stack trace, regardless of whether optimization is enabled
|
||||
Backtrace::Backtrace(int skip)
|
||||
: skip_(skip + 1) // ignore the constructor itself
|
||||
{
|
||||
numCallers_ = backtrace(callers_, MAX_STACK_DEPTH);
|
||||
if (skip_ > numCallers_) {
|
||||
skip_ = numCallers_;
|
||||
}
|
||||
}
|
||||
|
||||
Backtrace::Backtrace(Backtrace const& bt) : numCallers_(bt.numCallers_), skip_(bt.skip_) {
|
||||
if (numCallers_ >= 0) {
|
||||
memcpy(callers_, bt.callers_, numCallers_ * sizeof(void*));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A backtrace, plus one or two type names
|
||||
*/
|
||||
class Key {
|
||||
public:
|
||||
class Hash {
|
||||
public:
|
||||
size_t operator()(Key const& k) const { return k.hash(); }
|
||||
};
|
||||
|
||||
Key(const Backtrace* bt, const std::type_info& type_info)
|
||||
: backtrace_(bt), typeName1_(type_info.name()), typeName2_(NULL) {}
|
||||
|
||||
Key(const Backtrace* bt, const std::type_info& type_info1, const std::type_info& type_info2)
|
||||
: backtrace_(bt), typeName1_(type_info1.name()), typeName2_(type_info2.name()) {}
|
||||
|
||||
Key(const Key& k)
|
||||
: backtrace_(k.backtrace_), typeName1_(k.typeName1_), typeName2_(k.typeName2_) {}
|
||||
|
||||
void operator=(const Key& k) {
|
||||
backtrace_ = k.backtrace_;
|
||||
typeName1_ = k.typeName1_;
|
||||
typeName2_ = k.typeName2_;
|
||||
}
|
||||
|
||||
const Backtrace* getBacktrace() const { return backtrace_; }
|
||||
|
||||
const char* getTypeName() const { return typeName1_; }
|
||||
|
||||
const char* getTypeName2() const { return typeName2_; }
|
||||
|
||||
void makePersistent() {
|
||||
// Copy the Backtrace object
|
||||
backtrace_ = new Backtrace(*backtrace_);
|
||||
|
||||
// NOTE: We don't copy the type name.
|
||||
// The GNU libstdc++ implementation of type_info::name() returns a value
|
||||
// that will be valid for the lifetime of the program. (Although the C++
|
||||
// standard doesn't guarantee this will be true on all implementations.)
|
||||
}
|
||||
|
||||
/**
|
||||
* Clean up memory allocated by makePersistent()
|
||||
*
|
||||
* Should only be invoked if makePersistent() has previously been called.
|
||||
* The Key should no longer be used after cleanup() is called.
|
||||
*/
|
||||
void cleanup() {
|
||||
delete backtrace_;
|
||||
backtrace_ = NULL;
|
||||
}
|
||||
|
||||
int cmp(const Key& k) const {
|
||||
int ret = backtrace_->cmp(*k.backtrace_);
|
||||
if (ret != 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
// NOTE: We compare just the name pointers.
|
||||
// With GNU libstdc++, every type_info object for the same type points to
|
||||
// exactly the same name string. (Although this isn't guaranteed by the
|
||||
// C++ standard.)
|
||||
ret = k.typeName1_ - typeName1_;
|
||||
if (ret != 0) {
|
||||
return ret;
|
||||
}
|
||||
return k.typeName2_ - typeName2_;
|
||||
}
|
||||
|
||||
bool operator==(const Key& k) const { return cmp(k) == 0; }
|
||||
|
||||
size_t hash() const {
|
||||
// NOTE: As above, we just use the name pointer value.
|
||||
// Works with GNU libstdc++, but not guaranteed to be correct on all
|
||||
// implementations.
|
||||
return backtrace_->hash() ^ reinterpret_cast<size_t>(typeName1_)
|
||||
^ reinterpret_cast<size_t>(typeName2_);
|
||||
}
|
||||
|
||||
private:
|
||||
const Backtrace* backtrace_;
|
||||
const char* typeName1_;
|
||||
const char* typeName2_;
|
||||
};
|
||||
|
||||
/**
|
||||
* A functor that determines which of two BacktraceMap entries
|
||||
* has a higher count.
|
||||
*/
|
||||
class CountGreater {
|
||||
public:
|
||||
bool operator()(std::pair<Key, size_t> bt1, std::pair<Key, size_t> bt2) const {
|
||||
return bt1.second > bt2.second;
|
||||
}
|
||||
};
|
||||
|
||||
typedef __gnu_cxx::hash_map<Key, size_t, Key::Hash> BacktraceMap;
|
||||
|
||||
/**
|
||||
* A map describing how many times T_VIRTUAL_CALL() has been invoked.
|
||||
*/
|
||||
BacktraceMap virtual_calls;
|
||||
Mutex virtual_calls_mutex;
|
||||
|
||||
/**
|
||||
* A map describing how many times T_GENERIC_PROTOCOL() has been invoked.
|
||||
*/
|
||||
BacktraceMap generic_calls;
|
||||
Mutex generic_calls_mutex;
|
||||
|
||||
void _record_backtrace(BacktraceMap* map, const Mutex& mutex, Key* k) {
|
||||
Guard guard(mutex);
|
||||
|
||||
BacktraceMap::iterator it = map->find(*k);
|
||||
if (it == map->end()) {
|
||||
k->makePersistent();
|
||||
map->insert(std::make_pair(*k, 1));
|
||||
} else {
|
||||
// increment the count
|
||||
// NOTE: we could assert if it->second is 0 afterwards, since that would
|
||||
// mean we've wrapped.
|
||||
++(it->second);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Record an unnecessary virtual function call.
|
||||
*
|
||||
* This method is invoked by the T_VIRTUAL_CALL() macro.
|
||||
*/
|
||||
void profile_virtual_call(const std::type_info& type) {
|
||||
int const skip = 1; // ignore this frame
|
||||
Backtrace bt(skip);
|
||||
Key k(&bt, type);
|
||||
_record_backtrace(&virtual_calls, virtual_calls_mutex, &k);
|
||||
}
|
||||
|
||||
/**
|
||||
* Record a call to a template processor with a protocol that is not the one
|
||||
* specified in the template parameter.
|
||||
*
|
||||
* This method is invoked by the T_GENERIC_PROTOCOL() macro.
|
||||
*/
|
||||
void profile_generic_protocol(const std::type_info& template_type,
|
||||
const std::type_info& prot_type) {
|
||||
int const skip = 1; // ignore this frame
|
||||
Backtrace bt(skip);
|
||||
Key k(&bt, template_type, prot_type);
|
||||
_record_backtrace(&generic_calls, generic_calls_mutex, &k);
|
||||
}
|
||||
|
||||
/**
|
||||
* Print the recorded profiling information to the specified file.
|
||||
*/
|
||||
void profile_print_info(FILE* f) {
|
||||
typedef std::vector<std::pair<Key, size_t> > BacktraceVector;
|
||||
|
||||
CountGreater is_greater;
|
||||
|
||||
// Grab both locks for the duration of the print operation,
|
||||
// to ensure the output is a consistent snapshot of a single point in time
|
||||
Guard generic_calls_guard(generic_calls_mutex);
|
||||
Guard virtual_calls_guard(virtual_calls_mutex);
|
||||
|
||||
// print the info from generic_calls, sorted by frequency
|
||||
//
|
||||
// We print the generic_calls info ahead of virtual_calls, since it is more
|
||||
// useful in some cases. All T_GENERIC_PROTOCOL calls can be eliminated
|
||||
// from most programs. Not all T_VIRTUAL_CALLs will be eliminated by
|
||||
// converting to templates.
|
||||
BacktraceVector gp_sorted(generic_calls.begin(), generic_calls.end());
|
||||
std::sort(gp_sorted.begin(), gp_sorted.end(), is_greater);
|
||||
|
||||
for (BacktraceVector::const_iterator it = gp_sorted.begin(); it != gp_sorted.end(); ++it) {
|
||||
Key const& key = it->first;
|
||||
size_t const count = it->second;
|
||||
fprintf(f,
|
||||
"T_GENERIC_PROTOCOL: %zu calls to %s with a %s:\n",
|
||||
count,
|
||||
key.getTypeName(),
|
||||
key.getTypeName2());
|
||||
key.getBacktrace()->print(f, 2);
|
||||
fprintf(f, "\n");
|
||||
}
|
||||
|
||||
// print the info from virtual_calls, sorted by frequency
|
||||
BacktraceVector vc_sorted(virtual_calls.begin(), virtual_calls.end());
|
||||
std::sort(vc_sorted.begin(), vc_sorted.end(), is_greater);
|
||||
|
||||
for (BacktraceVector::const_iterator it = vc_sorted.begin(); it != vc_sorted.end(); ++it) {
|
||||
Key const& key = it->first;
|
||||
size_t const count = it->second;
|
||||
fprintf(f, "T_VIRTUAL_CALL: %zu calls on %s:\n", count, key.getTypeName());
|
||||
key.getBacktrace()->print(f, 2);
|
||||
fprintf(f, "\n");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Print the recorded profiling information to stdout.
|
||||
*/
|
||||
void profile_print_info() {
|
||||
profile_print_info(stdout);
|
||||
}
|
||||
|
||||
/**
|
||||
* Write a BacktraceMap as Google CPU profiler binary data.
|
||||
*/
|
||||
static void profile_write_pprof_file(FILE* f, BacktraceMap const& map) {
|
||||
// Write the header
|
||||
uintptr_t header[5] = {0, 3, 0, 0, 0};
|
||||
fwrite(&header, sizeof(header), 1, f);
|
||||
|
||||
// Write the profile records
|
||||
for (BacktraceMap::const_iterator it = map.begin(); it != map.end(); ++it) {
|
||||
uintptr_t count = it->second;
|
||||
fwrite(&count, sizeof(count), 1, f);
|
||||
|
||||
Backtrace const* bt = it->first.getBacktrace();
|
||||
uintptr_t num_pcs = bt->getDepth();
|
||||
fwrite(&num_pcs, sizeof(num_pcs), 1, f);
|
||||
|
||||
for (uintptr_t n = 0; n < num_pcs; ++n) {
|
||||
void* pc = bt->getFrame(n);
|
||||
fwrite(&pc, sizeof(pc), 1, f);
|
||||
}
|
||||
}
|
||||
|
||||
// Write the trailer
|
||||
uintptr_t trailer[3] = {0, 1, 0};
|
||||
fwrite(&trailer, sizeof(trailer), 1, f);
|
||||
|
||||
// Write /proc/self/maps
|
||||
// TODO(simpkins): This only works on linux
|
||||
FILE* proc_maps = fopen("/proc/self/maps", "r");
|
||||
if (proc_maps) {
|
||||
uint8_t buf[4096];
|
||||
while (true) {
|
||||
size_t bytes_read = fread(buf, 1, sizeof(buf), proc_maps);
|
||||
if (bytes_read == 0) {
|
||||
break;
|
||||
}
|
||||
fwrite(buf, 1, bytes_read, f);
|
||||
}
|
||||
fclose(proc_maps);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Write the recorded profiling information as pprof files.
|
||||
*
|
||||
* This writes the information using the Google CPU profiler binary data
|
||||
* format, so it can be analyzed with pprof. Note that information about the
|
||||
* protocol/transport data types cannot be stored in this file format.
|
||||
*
|
||||
* See http://code.google.com/p/google-perftools/ for more details.
|
||||
*
|
||||
* @param gen_calls_f The information about calls to
|
||||
* profile_generic_protocol() will be written to this
|
||||
* file.
|
||||
* @param virtual_calls_f The information about calls to
|
||||
* profile_virtual_call() will be written to this file.
|
||||
*/
|
||||
void profile_write_pprof(FILE* gen_calls_f, FILE* virtual_calls_f) {
|
||||
typedef std::vector<std::pair<Key, size_t> > BacktraceVector;
|
||||
|
||||
CountGreater is_greater;
|
||||
|
||||
// Grab both locks for the duration of the print operation,
|
||||
// to ensure the output is a consistent snapshot of a single point in time
|
||||
Guard generic_calls_guard(generic_calls_mutex);
|
||||
Guard virtual_calls_guard(virtual_calls_mutex);
|
||||
|
||||
// write the info from generic_calls
|
||||
profile_write_pprof_file(gen_calls_f, generic_calls);
|
||||
|
||||
// write the info from virtual_calls
|
||||
profile_write_pprof_file(virtual_calls_f, virtual_calls);
|
||||
}
|
||||
}
|
||||
} // apache::thrift
|
||||
|
||||
#endif // T_GLOBAL_PROFILE_VIRTUAL > 0
|
48
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/async/TAsyncBufferProcessor.h
generated
vendored
Normal file
48
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/async/TAsyncBufferProcessor.h
generated
vendored
Normal file
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
* 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_TASYNC_BUFFER_PROCESSOR_H_
|
||||
#define _THRIFT_TASYNC_BUFFER_PROCESSOR_H_ 1
|
||||
|
||||
#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
|
||||
|
||||
#endif // #ifndef _THRIFT_TASYNC_BUFFER_PROCESSOR_H_
|
37
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/async/TAsyncChannel.cpp
generated
vendored
Normal file
37
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/async/TAsyncChannel.cpp
generated
vendored
Normal file
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
* 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/async/TAsyncChannel.h>
|
||||
#include <thrift/cxxfunctional.h>
|
||||
|
||||
namespace apache {
|
||||
namespace thrift {
|
||||
namespace async {
|
||||
|
||||
void TAsyncChannel::sendAndRecvMessage(const VoidCallback& cob,
|
||||
TMemoryBuffer* sendBuf,
|
||||
TMemoryBuffer* recvBuf) {
|
||||
apache::thrift::stdcxx::function<void()> send_done
|
||||
= apache::thrift::stdcxx::bind(&TAsyncChannel::recvMessage, this, cob, recvBuf);
|
||||
|
||||
sendMessage(send_done, sendBuf);
|
||||
}
|
||||
}
|
||||
}
|
||||
} // apache::thrift::async
|
73
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/async/TAsyncChannel.h
generated
vendored
Normal file
73
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/async/TAsyncChannel.h
generated
vendored
Normal file
|
@ -0,0 +1,73 @@
|
|||
/*
|
||||
* 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_ASYNC_TASYNCCHANNEL_H_
|
||||
#define _THRIFT_ASYNC_TASYNCCHANNEL_H_ 1
|
||||
|
||||
#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
|
||||
|
||||
#endif // #ifndef _THRIFT_ASYNC_TASYNCCHANNEL_H_
|
151
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/async/TAsyncDispatchProcessor.h
generated
vendored
Normal file
151
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/async/TAsyncDispatchProcessor.h
generated
vendored
Normal file
|
@ -0,0 +1,151 @@
|
|||
/*
|
||||
* 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_ASYNC_TASYNCDISPATCHPROCESSOR_H_
|
||||
#define _THRIFT_ASYNC_TASYNCDISPATCHPROCESSOR_H_ 1
|
||||
|
||||
#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
|
||||
|
||||
#endif // _THRIFT_ASYNC_TASYNCDISPATCHPROCESSOR_H_
|
86
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/async/TAsyncProcessor.h
generated
vendored
Normal file
86
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/async/TAsyncProcessor.h
generated
vendored
Normal file
|
@ -0,0 +1,86 @@
|
|||
/*
|
||||
* 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_TASYNCPROCESSOR_H_
|
||||
#define _THRIFT_TASYNCPROCESSOR_H_ 1
|
||||
|
||||
#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 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() const { return eventHandler_; }
|
||||
|
||||
void setEventHandler(boost::shared_ptr<TProcessorEventHandler> eventHandler) {
|
||||
eventHandler_ = eventHandler;
|
||||
}
|
||||
|
||||
protected:
|
||||
TAsyncProcessor() {}
|
||||
|
||||
boost::shared_ptr<TProcessorEventHandler> eventHandler_;
|
||||
};
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // #ifndef _THRIFT_TASYNCPROCESSOR_H_
|
53
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/async/TAsyncProtocolProcessor.cpp
generated
vendored
Normal file
53
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/async/TAsyncProtocolProcessor.cpp
generated
vendored
Normal file
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
* 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/async/TAsyncProtocolProcessor.h>
|
||||
|
||||
using apache::thrift::transport::TBufferBase;
|
||||
using apache::thrift::protocol::TProtocol;
|
||||
|
||||
namespace apache {
|
||||
namespace thrift {
|
||||
namespace async {
|
||||
|
||||
void TAsyncProtocolProcessor::process(apache::thrift::stdcxx::function<void(bool healthy)> _return,
|
||||
boost::shared_ptr<TBufferBase> ibuf,
|
||||
boost::shared_ptr<TBufferBase> obuf) {
|
||||
boost::shared_ptr<TProtocol> iprot(pfact_->getProtocol(ibuf));
|
||||
boost::shared_ptr<TProtocol> oprot(pfact_->getProtocol(obuf));
|
||||
return underlying_
|
||||
->process(apache::thrift::stdcxx::bind(&TAsyncProtocolProcessor::finish,
|
||||
_return,
|
||||
oprot,
|
||||
apache::thrift::stdcxx::placeholders::_1),
|
||||
iprot,
|
||||
oprot);
|
||||
}
|
||||
|
||||
/* static */ void TAsyncProtocolProcessor::finish(
|
||||
apache::thrift::stdcxx::function<void(bool healthy)> _return,
|
||||
boost::shared_ptr<TProtocol> oprot,
|
||||
bool healthy) {
|
||||
(void)oprot;
|
||||
// This is a stub function to hold a reference to oprot.
|
||||
return _return(healthy);
|
||||
}
|
||||
}
|
||||
}
|
||||
} // apache::thrift::async
|
55
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/async/TAsyncProtocolProcessor.h
generated
vendored
Normal file
55
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/async/TAsyncProtocolProcessor.h
generated
vendored
Normal file
|
@ -0,0 +1,55 @@
|
|||
/*
|
||||
* 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_TNAME_ME_H_
|
||||
#define _THRIFT_TNAME_ME_H_ 1
|
||||
|
||||
#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
|
||||
|
||||
#endif // #ifndef _THRIFT_TNAME_ME_H_
|
242
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/async/TConcurrentClientSyncInfo.cpp
generated
vendored
Normal file
242
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/async/TConcurrentClientSyncInfo.cpp
generated
vendored
Normal file
|
@ -0,0 +1,242 @@
|
|||
/*
|
||||
* 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/async/TConcurrentClientSyncInfo.h>
|
||||
#include <thrift/TApplicationException.h>
|
||||
#include <thrift/transport/TTransportException.h>
|
||||
#include <limits>
|
||||
|
||||
namespace apache { namespace thrift { namespace async {
|
||||
|
||||
using namespace ::apache::thrift::concurrency;
|
||||
|
||||
TConcurrentClientSyncInfo::TConcurrentClientSyncInfo() :
|
||||
stop_(false),
|
||||
seqidMutex_(),
|
||||
// test rollover all the time
|
||||
nextseqid_((std::numeric_limits<int32_t>::max)()-10),
|
||||
seqidToMonitorMap_(),
|
||||
freeMonitors_(),
|
||||
writeMutex_(),
|
||||
readMutex_(),
|
||||
recvPending_(false),
|
||||
wakeupSomeone_(false),
|
||||
seqidPending_(0),
|
||||
fnamePending_(),
|
||||
mtypePending_(::apache::thrift::protocol::T_CALL)
|
||||
{
|
||||
freeMonitors_.reserve(MONITOR_CACHE_SIZE);
|
||||
}
|
||||
|
||||
bool TConcurrentClientSyncInfo::getPending(
|
||||
std::string &fname,
|
||||
::apache::thrift::protocol::TMessageType &mtype,
|
||||
int32_t &rseqid)
|
||||
{
|
||||
if(stop_)
|
||||
throwDeadConnection_();
|
||||
wakeupSomeone_ = false;
|
||||
if(recvPending_)
|
||||
{
|
||||
recvPending_ = false;
|
||||
rseqid = seqidPending_;
|
||||
fname = fnamePending_;
|
||||
mtype = mtypePending_;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void TConcurrentClientSyncInfo::updatePending(
|
||||
const std::string &fname,
|
||||
::apache::thrift::protocol::TMessageType mtype,
|
||||
int32_t rseqid)
|
||||
{
|
||||
recvPending_ = true;
|
||||
seqidPending_ = rseqid;
|
||||
fnamePending_ = fname;
|
||||
mtypePending_ = mtype;
|
||||
MonitorPtr monitor;
|
||||
{
|
||||
Guard seqidGuard(seqidMutex_);
|
||||
MonitorMap::iterator i = seqidToMonitorMap_.find(rseqid);
|
||||
if(i == seqidToMonitorMap_.end())
|
||||
throwBadSeqId_();
|
||||
monitor = i->second;
|
||||
}
|
||||
monitor->notify();
|
||||
}
|
||||
|
||||
void TConcurrentClientSyncInfo::waitForWork(int32_t seqid)
|
||||
{
|
||||
MonitorPtr m;
|
||||
{
|
||||
Guard seqidGuard(seqidMutex_);
|
||||
m = seqidToMonitorMap_[seqid];
|
||||
}
|
||||
while(true)
|
||||
{
|
||||
// be very careful about setting state in this loop that affects waking up. You may exit
|
||||
// this function, attempt to grab some work, and someone else could have beaten you (or not
|
||||
// left) the read mutex, and that will put you right back in this loop, with the mangled
|
||||
// state you left behind.
|
||||
if(stop_)
|
||||
throwDeadConnection_();
|
||||
if(wakeupSomeone_)
|
||||
return;
|
||||
if(recvPending_ && seqidPending_ == seqid)
|
||||
return;
|
||||
m->waitForever();
|
||||
}
|
||||
}
|
||||
|
||||
void TConcurrentClientSyncInfo::throwBadSeqId_()
|
||||
{
|
||||
throw apache::thrift::TApplicationException(
|
||||
TApplicationException::BAD_SEQUENCE_ID,
|
||||
"server sent a bad seqid");
|
||||
}
|
||||
|
||||
void TConcurrentClientSyncInfo::throwDeadConnection_()
|
||||
{
|
||||
throw apache::thrift::transport::TTransportException(
|
||||
apache::thrift::transport::TTransportException::NOT_OPEN,
|
||||
"this client died on another thread, and is now in an unusable state");
|
||||
}
|
||||
|
||||
void TConcurrentClientSyncInfo::wakeupAnyone_(const Guard &)
|
||||
{
|
||||
wakeupSomeone_ = true;
|
||||
if(!seqidToMonitorMap_.empty())
|
||||
{
|
||||
// The monitor map maps integers to monitors. Larger integers are more recent
|
||||
// messages. Since this is ordered, it means that the last element is the most recent.
|
||||
// We are trying to guess which thread will have its message complete next, so we are picking
|
||||
// the most recent. The oldest message is likely to be some polling, long lived message.
|
||||
// If we guess right, the thread we wake up will handle the message that comes in.
|
||||
// If we guess wrong, the thread we wake up will hand off the work to the correct thread,
|
||||
// costing us an extra context switch.
|
||||
seqidToMonitorMap_.rbegin()->second->notify();
|
||||
}
|
||||
}
|
||||
|
||||
void TConcurrentClientSyncInfo::markBad_(const Guard &)
|
||||
{
|
||||
wakeupSomeone_ = true;
|
||||
stop_ = true;
|
||||
for(MonitorMap::iterator i = seqidToMonitorMap_.begin(); i != seqidToMonitorMap_.end(); ++i)
|
||||
i->second->notify();
|
||||
}
|
||||
|
||||
TConcurrentClientSyncInfo::MonitorPtr
|
||||
TConcurrentClientSyncInfo::newMonitor_(const Guard &)
|
||||
{
|
||||
if(freeMonitors_.empty())
|
||||
return MonitorPtr(new Monitor(&readMutex_));
|
||||
MonitorPtr retval;
|
||||
//swapping to avoid an atomic operation
|
||||
retval.swap(freeMonitors_.back());
|
||||
freeMonitors_.pop_back();
|
||||
return retval;
|
||||
}
|
||||
|
||||
void TConcurrentClientSyncInfo::deleteMonitor_(
|
||||
const Guard &,
|
||||
TConcurrentClientSyncInfo::MonitorPtr &m) /*noexcept*/
|
||||
{
|
||||
if(freeMonitors_.size() > MONITOR_CACHE_SIZE)
|
||||
{
|
||||
m.reset();
|
||||
return;
|
||||
}
|
||||
//freeMonitors_ was reserved up to MONITOR_CACHE_SIZE in the ctor,
|
||||
//so this shouldn't throw
|
||||
freeMonitors_.push_back(TConcurrentClientSyncInfo::MonitorPtr());
|
||||
//swapping to avoid an atomic operation
|
||||
m.swap(freeMonitors_.back());
|
||||
}
|
||||
|
||||
int32_t TConcurrentClientSyncInfo::generateSeqId()
|
||||
{
|
||||
Guard seqidGuard(seqidMutex_);
|
||||
if(stop_)
|
||||
throwDeadConnection_();
|
||||
|
||||
if(!seqidToMonitorMap_.empty())
|
||||
if(nextseqid_ == seqidToMonitorMap_.begin()->first)
|
||||
throw apache::thrift::TApplicationException(
|
||||
TApplicationException::BAD_SEQUENCE_ID,
|
||||
"about to repeat a seqid");
|
||||
int32_t newSeqId = nextseqid_++;
|
||||
seqidToMonitorMap_[newSeqId] = newMonitor_(seqidGuard);
|
||||
return newSeqId;
|
||||
}
|
||||
|
||||
TConcurrentRecvSentry::TConcurrentRecvSentry(TConcurrentClientSyncInfo *sync, int32_t seqid) :
|
||||
sync_(*sync),
|
||||
seqid_(seqid),
|
||||
committed_(false)
|
||||
{
|
||||
sync_.getReadMutex().lock();
|
||||
}
|
||||
|
||||
TConcurrentRecvSentry::~TConcurrentRecvSentry()
|
||||
{
|
||||
{
|
||||
Guard seqidGuard(sync_.seqidMutex_);
|
||||
sync_.deleteMonitor_(seqidGuard, sync_.seqidToMonitorMap_[seqid_]);
|
||||
|
||||
sync_.seqidToMonitorMap_.erase(seqid_);
|
||||
if(committed_)
|
||||
sync_.wakeupAnyone_(seqidGuard);
|
||||
else
|
||||
sync_.markBad_(seqidGuard);
|
||||
}
|
||||
sync_.getReadMutex().unlock();
|
||||
}
|
||||
|
||||
void TConcurrentRecvSentry::commit()
|
||||
{
|
||||
committed_ = true;
|
||||
}
|
||||
|
||||
TConcurrentSendSentry::TConcurrentSendSentry(TConcurrentClientSyncInfo *sync) :
|
||||
sync_(*sync),
|
||||
committed_(false)
|
||||
{
|
||||
sync_.getWriteMutex().lock();
|
||||
}
|
||||
|
||||
TConcurrentSendSentry::~TConcurrentSendSentry()
|
||||
{
|
||||
if(!committed_)
|
||||
{
|
||||
Guard seqidGuard(sync_.seqidMutex_);
|
||||
sync_.markBad_(seqidGuard);
|
||||
}
|
||||
sync_.getWriteMutex().unlock();
|
||||
}
|
||||
|
||||
void TConcurrentSendSentry::commit()
|
||||
{
|
||||
committed_ = true;
|
||||
}
|
||||
|
||||
|
||||
}}} // apache::thrift::async
|
126
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/async/TConcurrentClientSyncInfo.h
generated
vendored
Normal file
126
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/async/TConcurrentClientSyncInfo.h
generated
vendored
Normal file
|
@ -0,0 +1,126 @@
|
|||
/*
|
||||
* 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_TCONCURRENTCLIENTSYNCINFO_H_
|
||||
#define _THRIFT_TCONCURRENTCLIENTSYNCINFO_H_ 1
|
||||
|
||||
#include <thrift/protocol/TProtocol.h>
|
||||
#include <thrift/concurrency/Mutex.h>
|
||||
#include <thrift/concurrency/Monitor.h>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <map>
|
||||
|
||||
namespace apache {
|
||||
namespace thrift {
|
||||
namespace async {
|
||||
|
||||
class TConcurrentClientSyncInfo;
|
||||
|
||||
class TConcurrentSendSentry {
|
||||
public:
|
||||
explicit TConcurrentSendSentry(TConcurrentClientSyncInfo* sync);
|
||||
~TConcurrentSendSentry();
|
||||
|
||||
void commit();
|
||||
|
||||
private:
|
||||
TConcurrentClientSyncInfo& sync_;
|
||||
bool committed_;
|
||||
};
|
||||
|
||||
class TConcurrentRecvSentry {
|
||||
public:
|
||||
TConcurrentRecvSentry(TConcurrentClientSyncInfo* sync, int32_t seqid);
|
||||
~TConcurrentRecvSentry();
|
||||
|
||||
void commit();
|
||||
|
||||
private:
|
||||
TConcurrentClientSyncInfo& sync_;
|
||||
int32_t seqid_;
|
||||
bool committed_;
|
||||
};
|
||||
|
||||
class TConcurrentClientSyncInfo {
|
||||
private: // typedefs
|
||||
typedef boost::shared_ptr< ::apache::thrift::concurrency::Monitor> MonitorPtr;
|
||||
typedef std::map<int32_t, MonitorPtr> MonitorMap;
|
||||
|
||||
public:
|
||||
TConcurrentClientSyncInfo();
|
||||
|
||||
int32_t generateSeqId();
|
||||
|
||||
bool getPending(std::string& fname,
|
||||
::apache::thrift::protocol::TMessageType& mtype,
|
||||
int32_t& rseqid); /* requires readMutex_ */
|
||||
|
||||
void updatePending(const std::string& fname,
|
||||
::apache::thrift::protocol::TMessageType mtype,
|
||||
int32_t rseqid); /* requires readMutex_ */
|
||||
|
||||
void waitForWork(int32_t seqid); /* requires readMutex_ */
|
||||
|
||||
::apache::thrift::concurrency::Mutex& getReadMutex() { return readMutex_; }
|
||||
::apache::thrift::concurrency::Mutex& getWriteMutex() { return writeMutex_; }
|
||||
|
||||
private: // constants
|
||||
enum { MONITOR_CACHE_SIZE = 10 };
|
||||
|
||||
private: // functions
|
||||
MonitorPtr newMonitor_(
|
||||
const ::apache::thrift::concurrency::Guard& seqidGuard); /* requires seqidMutex_ */
|
||||
void deleteMonitor_(const ::apache::thrift::concurrency::Guard& seqidGuard, MonitorPtr& m);
|
||||
/*noexcept*/ /* requires seqidMutex_ */
|
||||
void wakeupAnyone_(
|
||||
const ::apache::thrift::concurrency::Guard& seqidGuard); /* requires seqidMutex_ */
|
||||
void markBad_(const ::apache::thrift::concurrency::Guard& seqidGuard); /* requires seqidMutex_ */
|
||||
void throwBadSeqId_();
|
||||
void throwDeadConnection_();
|
||||
|
||||
private: // data members
|
||||
volatile bool stop_;
|
||||
|
||||
::apache::thrift::concurrency::Mutex seqidMutex_;
|
||||
// begin seqidMutex_ protected members
|
||||
int32_t nextseqid_;
|
||||
MonitorMap seqidToMonitorMap_;
|
||||
std::vector<MonitorPtr> freeMonitors_;
|
||||
// end seqidMutex_ protected members
|
||||
|
||||
::apache::thrift::concurrency::Mutex writeMutex_;
|
||||
|
||||
::apache::thrift::concurrency::Mutex readMutex_;
|
||||
// begin readMutex_ protected members
|
||||
bool recvPending_;
|
||||
bool wakeupSomeone_;
|
||||
int32_t seqidPending_;
|
||||
std::string fnamePending_;
|
||||
::apache::thrift::protocol::TMessageType mtypePending_;
|
||||
// end readMutex_ protected members
|
||||
|
||||
friend class TConcurrentSendSentry;
|
||||
friend class TConcurrentRecvSentry;
|
||||
};
|
||||
}
|
||||
}
|
||||
} // apache::thrift::async
|
||||
|
||||
#endif // _THRIFT_TCONCURRENTCLIENTSYNCINFO_H_
|
155
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/async/TEvhttpClientChannel.cpp
generated
vendored
Normal file
155
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/async/TEvhttpClientChannel.cpp
generated
vendored
Normal file
|
@ -0,0 +1,155 @@
|
|||
/*
|
||||
* 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/async/TEvhttpClientChannel.h>
|
||||
#include <evhttp.h>
|
||||
#include <event2/buffer.h>
|
||||
#include <event2/buffer_compat.h>
|
||||
#include <thrift/transport/TBufferTransports.h>
|
||||
#include <thrift/protocol/TProtocolException.h>
|
||||
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
|
||||
using namespace apache::thrift::protocol;
|
||||
using apache::thrift::transport::TTransportException;
|
||||
|
||||
namespace apache {
|
||||
namespace thrift {
|
||||
namespace async {
|
||||
|
||||
TEvhttpClientChannel::TEvhttpClientChannel(const std::string& host,
|
||||
const std::string& path,
|
||||
const char* address,
|
||||
int port,
|
||||
struct event_base* eb)
|
||||
: host_(host), path_(path), conn_(NULL) {
|
||||
conn_ = evhttp_connection_new(address, port);
|
||||
if (conn_ == NULL) {
|
||||
throw TException("evhttp_connection_new failed");
|
||||
}
|
||||
evhttp_connection_set_base(conn_, eb);
|
||||
}
|
||||
|
||||
TEvhttpClientChannel::~TEvhttpClientChannel() {
|
||||
if (conn_ != NULL) {
|
||||
evhttp_connection_free(conn_);
|
||||
}
|
||||
}
|
||||
|
||||
void TEvhttpClientChannel::sendAndRecvMessage(const VoidCallback& cob,
|
||||
apache::thrift::transport::TMemoryBuffer* sendBuf,
|
||||
apache::thrift::transport::TMemoryBuffer* recvBuf) {
|
||||
struct evhttp_request* req = evhttp_request_new(response, this);
|
||||
if (req == NULL) {
|
||||
throw TException("evhttp_request_new failed");
|
||||
}
|
||||
|
||||
int rv;
|
||||
|
||||
rv = evhttp_add_header(req->output_headers, "Host", host_.c_str());
|
||||
if (rv != 0) {
|
||||
throw TException("evhttp_add_header failed");
|
||||
}
|
||||
|
||||
rv = evhttp_add_header(req->output_headers, "Content-Type", "application/x-thrift");
|
||||
if (rv != 0) {
|
||||
throw TException("evhttp_add_header failed");
|
||||
}
|
||||
|
||||
uint8_t* obuf;
|
||||
uint32_t sz;
|
||||
sendBuf->getBuffer(&obuf, &sz);
|
||||
rv = evbuffer_add(req->output_buffer, obuf, sz);
|
||||
if (rv != 0) {
|
||||
throw TException("evbuffer_add failed");
|
||||
}
|
||||
|
||||
rv = evhttp_make_request(conn_, req, EVHTTP_REQ_POST, path_.c_str());
|
||||
if (rv != 0) {
|
||||
throw TException("evhttp_make_request failed");
|
||||
}
|
||||
|
||||
completionQueue_.push(Completion(cob, recvBuf));
|
||||
}
|
||||
|
||||
void TEvhttpClientChannel::sendMessage(const VoidCallback& cob,
|
||||
apache::thrift::transport::TMemoryBuffer* message) {
|
||||
(void)cob;
|
||||
(void)message;
|
||||
throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
|
||||
"Unexpected call to TEvhttpClientChannel::sendMessage");
|
||||
}
|
||||
|
||||
void TEvhttpClientChannel::recvMessage(const VoidCallback& cob,
|
||||
apache::thrift::transport::TMemoryBuffer* message) {
|
||||
(void)cob;
|
||||
(void)message;
|
||||
throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
|
||||
"Unexpected call to TEvhttpClientChannel::recvMessage");
|
||||
}
|
||||
|
||||
void TEvhttpClientChannel::finish(struct evhttp_request* req) {
|
||||
assert(!completionQueue_.empty());
|
||||
Completion completion = completionQueue_.front();
|
||||
completionQueue_.pop();
|
||||
if (req == NULL) {
|
||||
try {
|
||||
completion.first();
|
||||
} catch (const TTransportException& e) {
|
||||
if (e.getType() == TTransportException::END_OF_FILE)
|
||||
throw TException("connect failed");
|
||||
else
|
||||
throw;
|
||||
}
|
||||
return;
|
||||
} else if (req->response_code != 200) {
|
||||
try {
|
||||
completion.first();
|
||||
} catch (const TTransportException& e) {
|
||||
std::stringstream ss;
|
||||
ss << "server returned code " << req->response_code;
|
||||
if (req->response_code_line)
|
||||
ss << ": " << req->response_code_line;
|
||||
if (e.getType() == TTransportException::END_OF_FILE)
|
||||
throw TException(ss.str());
|
||||
else
|
||||
throw;
|
||||
}
|
||||
return;
|
||||
}
|
||||
completion.second->resetBuffer(EVBUFFER_DATA(req->input_buffer),
|
||||
static_cast<uint32_t>(EVBUFFER_LENGTH(req->input_buffer)));
|
||||
completion.first();
|
||||
return;
|
||||
}
|
||||
|
||||
/* static */ void TEvhttpClientChannel::response(struct evhttp_request* req, void* arg) {
|
||||
TEvhttpClientChannel* self = (TEvhttpClientChannel*)arg;
|
||||
try {
|
||||
self->finish(req);
|
||||
} catch (std::exception& e) {
|
||||
// don't propagate a C++ exception in C code (e.g. libevent)
|
||||
std::cerr << "TEvhttpClientChannel::response exception thrown (ignored): " << e.what()
|
||||
<< std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} // apache::thrift::async
|
86
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/async/TEvhttpClientChannel.h
generated
vendored
Normal file
86
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/async/TEvhttpClientChannel.h
generated
vendored
Normal file
|
@ -0,0 +1,86 @@
|
|||
/*
|
||||
* 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_TEVHTTP_CLIENT_CHANNEL_H_
|
||||
#define _THRIFT_TEVHTTP_CLIENT_CHANNEL_H_ 1
|
||||
|
||||
#include <queue>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#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_;
|
||||
typedef std::pair<VoidCallback, apache::thrift::transport::TMemoryBuffer*> Completion;
|
||||
typedef std::queue<Completion> CompletionQueue;
|
||||
CompletionQueue completionQueue_;
|
||||
struct evhttp_connection* conn_;
|
||||
};
|
||||
}
|
||||
}
|
||||
} // apache::thrift::async
|
||||
|
||||
#endif // #ifndef _THRIFT_TEVHTTP_CLIENT_CHANNEL_H_
|
159
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/async/TEvhttpServer.cpp
generated
vendored
Normal file
159
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/async/TEvhttpServer.cpp
generated
vendored
Normal file
|
@ -0,0 +1,159 @@
|
|||
/*
|
||||
* 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/async/TEvhttpServer.h>
|
||||
#include <thrift/async/TAsyncBufferProcessor.h>
|
||||
#include <thrift/transport/TBufferTransports.h>
|
||||
#include <evhttp.h>
|
||||
#include <event2/buffer.h>
|
||||
#include <event2/buffer_compat.h>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#ifndef HTTP_INTERNAL // libevent < 2
|
||||
#define HTTP_INTERNAL 500
|
||||
#endif
|
||||
|
||||
using apache::thrift::transport::TMemoryBuffer;
|
||||
|
||||
namespace apache {
|
||||
namespace thrift {
|
||||
namespace async {
|
||||
|
||||
struct TEvhttpServer::RequestContext {
|
||||
struct evhttp_request* req;
|
||||
boost::shared_ptr<apache::thrift::transport::TMemoryBuffer> ibuf;
|
||||
boost::shared_ptr<apache::thrift::transport::TMemoryBuffer> obuf;
|
||||
|
||||
RequestContext(struct evhttp_request* req);
|
||||
};
|
||||
|
||||
TEvhttpServer::TEvhttpServer(boost::shared_ptr<TAsyncBufferProcessor> processor)
|
||||
: processor_(processor), eb_(NULL), eh_(NULL) {
|
||||
}
|
||||
|
||||
TEvhttpServer::TEvhttpServer(boost::shared_ptr<TAsyncBufferProcessor> processor, int port)
|
||||
: processor_(processor), eb_(NULL), eh_(NULL) {
|
||||
// Create event_base and evhttp.
|
||||
eb_ = event_base_new();
|
||||
if (eb_ == NULL) {
|
||||
throw TException("event_base_new failed");
|
||||
}
|
||||
eh_ = evhttp_new(eb_);
|
||||
if (eh_ == NULL) {
|
||||
event_base_free(eb_);
|
||||
throw TException("evhttp_new failed");
|
||||
}
|
||||
|
||||
// Bind to port.
|
||||
int ret = evhttp_bind_socket(eh_, NULL, port);
|
||||
if (ret < 0) {
|
||||
evhttp_free(eh_);
|
||||
event_base_free(eb_);
|
||||
throw TException("evhttp_bind_socket failed");
|
||||
}
|
||||
|
||||
// Register a handler. If you use the other constructor,
|
||||
// you will want to do this yourself.
|
||||
// Don't forget to unregister before destorying this TEvhttpServer.
|
||||
evhttp_set_cb(eh_, "/", request, (void*)this);
|
||||
}
|
||||
|
||||
TEvhttpServer::~TEvhttpServer() {
|
||||
if (eh_ != NULL) {
|
||||
evhttp_free(eh_);
|
||||
}
|
||||
if (eb_ != NULL) {
|
||||
event_base_free(eb_);
|
||||
}
|
||||
}
|
||||
|
||||
int TEvhttpServer::serve() {
|
||||
if (eb_ == NULL) {
|
||||
throw TException("Unexpected call to TEvhttpServer::serve");
|
||||
}
|
||||
return event_base_dispatch(eb_);
|
||||
}
|
||||
|
||||
TEvhttpServer::RequestContext::RequestContext(struct evhttp_request* req)
|
||||
: req(req),
|
||||
ibuf(new TMemoryBuffer(EVBUFFER_DATA(req->input_buffer),
|
||||
static_cast<uint32_t>(EVBUFFER_LENGTH(req->input_buffer)))),
|
||||
obuf(new TMemoryBuffer()) {
|
||||
}
|
||||
|
||||
void TEvhttpServer::request(struct evhttp_request* req, void* self) {
|
||||
try {
|
||||
static_cast<TEvhttpServer*>(self)->process(req);
|
||||
} catch (std::exception& e) {
|
||||
evhttp_send_reply(req, HTTP_INTERNAL, e.what(), 0);
|
||||
}
|
||||
}
|
||||
|
||||
void TEvhttpServer::process(struct evhttp_request* req) {
|
||||
RequestContext* ctx = new RequestContext(req);
|
||||
return processor_->process(apache::thrift::stdcxx::bind(&TEvhttpServer::complete,
|
||||
this,
|
||||
ctx,
|
||||
apache::thrift::stdcxx::placeholders::_1),
|
||||
ctx->ibuf,
|
||||
ctx->obuf);
|
||||
}
|
||||
|
||||
void TEvhttpServer::complete(RequestContext* ctx, bool success) {
|
||||
(void)success;
|
||||
std::auto_ptr<RequestContext> ptr(ctx);
|
||||
|
||||
int code = success ? 200 : 400;
|
||||
const char* reason = success ? "OK" : "Bad Request";
|
||||
|
||||
int rv = evhttp_add_header(ctx->req->output_headers, "Content-Type", "application/x-thrift");
|
||||
if (rv != 0) {
|
||||
// TODO: Log an error.
|
||||
std::cerr << "evhttp_add_header failed " << __FILE__ << ":" << __LINE__ << std::endl;
|
||||
}
|
||||
|
||||
struct evbuffer* buf = evbuffer_new();
|
||||
if (buf == NULL) {
|
||||
// TODO: Log an error.
|
||||
std::cerr << "evbuffer_new failed " << __FILE__ << ":" << __LINE__ << std::endl;
|
||||
} else {
|
||||
uint8_t* obuf;
|
||||
uint32_t sz;
|
||||
ctx->obuf->getBuffer(&obuf, &sz);
|
||||
int ret = evbuffer_add(buf, obuf, sz);
|
||||
if (ret != 0) {
|
||||
// TODO: Log an error.
|
||||
std::cerr << "evhttp_add failed with " << ret << " " << __FILE__ << ":" << __LINE__
|
||||
<< std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
evhttp_send_reply(ctx->req, code, reason, buf);
|
||||
if (buf != NULL) {
|
||||
evbuffer_free(buf);
|
||||
}
|
||||
}
|
||||
|
||||
struct event_base* TEvhttpServer::getEventBase() {
|
||||
return eb_;
|
||||
}
|
||||
}
|
||||
}
|
||||
} // apache::thrift::async
|
74
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/async/TEvhttpServer.h
generated
vendored
Normal file
74
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/async/TEvhttpServer.h
generated
vendored
Normal file
|
@ -0,0 +1,74 @@
|
|||
/*
|
||||
* 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_TEVHTTP_SERVER_H_
|
||||
#define _THRIFT_TEVHTTP_SERVER_H_ 1
|
||||
|
||||
#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
|
||||
|
||||
#endif // #ifndef _THRIFT_TEVHTTP_SERVER_H_
|
214
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/concurrency/BoostMonitor.cpp
generated
vendored
Normal file
214
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/concurrency/BoostMonitor.cpp
generated
vendored
Normal file
|
@ -0,0 +1,214 @@
|
|||
/*
|
||||
* 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 <thrift/concurrency/Monitor.h>
|
||||
#include <thrift/concurrency/Exception.h>
|
||||
#include <thrift/concurrency/Util.h>
|
||||
#include <thrift/transport/PlatformSocket.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include <boost/scoped_ptr.hpp>
|
||||
#include <boost/thread.hpp>
|
||||
#include <boost/date_time/posix_time/posix_time.hpp>
|
||||
|
||||
namespace apache {
|
||||
namespace thrift {
|
||||
namespace concurrency {
|
||||
|
||||
/**
|
||||
* Monitor implementation using the boost thread library
|
||||
*
|
||||
* @version $Id:$
|
||||
*/
|
||||
class Monitor::Impl : public boost::condition_variable_any {
|
||||
|
||||
public:
|
||||
Impl() : ownedMutex_(new Mutex()), mutex_(NULL) { init(ownedMutex_.get()); }
|
||||
|
||||
Impl(Mutex* mutex) : mutex_(NULL) { init(mutex); }
|
||||
|
||||
Impl(Monitor* monitor) : mutex_(NULL) { init(&(monitor->mutex())); }
|
||||
|
||||
Mutex& mutex() { return *mutex_; }
|
||||
void lock() { mutex().lock(); }
|
||||
void unlock() { mutex().unlock(); }
|
||||
|
||||
/**
|
||||
* 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) {
|
||||
int result = waitForTimeRelative(timeout_ms);
|
||||
if (result == THRIFT_ETIMEDOUT) {
|
||||
throw TimedOutException();
|
||||
} else if (result != 0) {
|
||||
throw TException("Monitor::wait() failed");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Waits until 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) {
|
||||
if (timeout_ms == 0LL) {
|
||||
return waitForever();
|
||||
}
|
||||
|
||||
assert(mutex_);
|
||||
boost::timed_mutex* mutexImpl
|
||||
= reinterpret_cast<boost::timed_mutex*>(mutex_->getUnderlyingImpl());
|
||||
assert(mutexImpl);
|
||||
|
||||
boost::timed_mutex::scoped_lock lock(*mutexImpl, boost::adopt_lock);
|
||||
int res
|
||||
= timed_wait(lock, boost::get_system_time() + boost::posix_time::milliseconds(timeout_ms))
|
||||
? 0
|
||||
: THRIFT_ETIMEDOUT;
|
||||
lock.release();
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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) {
|
||||
struct timeval temp;
|
||||
temp.tv_sec = static_cast<long>(abstime->tv_sec);
|
||||
temp.tv_usec = static_cast<long>(abstime->tv_nsec) / 1000;
|
||||
return waitForTime(&temp);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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) {
|
||||
assert(mutex_);
|
||||
boost::timed_mutex* mutexImpl = static_cast<boost::timed_mutex*>(mutex_->getUnderlyingImpl());
|
||||
assert(mutexImpl);
|
||||
|
||||
struct timeval currenttime;
|
||||
Util::toTimeval(currenttime, Util::currentTime());
|
||||
|
||||
long tv_sec = static_cast<long>(abstime->tv_sec - currenttime.tv_sec);
|
||||
long tv_usec = static_cast<long>(abstime->tv_usec - currenttime.tv_usec);
|
||||
if (tv_sec < 0)
|
||||
tv_sec = 0;
|
||||
if (tv_usec < 0)
|
||||
tv_usec = 0;
|
||||
|
||||
boost::timed_mutex::scoped_lock lock(*mutexImpl, boost::adopt_lock);
|
||||
int res = timed_wait(lock,
|
||||
boost::get_system_time() + boost::posix_time::seconds(tv_sec)
|
||||
+ boost::posix_time::microseconds(tv_usec))
|
||||
? 0
|
||||
: THRIFT_ETIMEDOUT;
|
||||
lock.release();
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* Waits forever until the condition occurs.
|
||||
* Returns 0 if condition occurs, or an error code otherwise.
|
||||
*/
|
||||
int waitForever() {
|
||||
assert(mutex_);
|
||||
boost::timed_mutex* mutexImpl
|
||||
= reinterpret_cast<boost::timed_mutex*>(mutex_->getUnderlyingImpl());
|
||||
assert(mutexImpl);
|
||||
|
||||
boost::timed_mutex::scoped_lock lock(*mutexImpl, boost::adopt_lock);
|
||||
((boost::condition_variable_any*)this)->wait(lock);
|
||||
lock.release();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void notify() { notify_one(); }
|
||||
|
||||
void notifyAll() { notify_all(); }
|
||||
|
||||
private:
|
||||
void init(Mutex* mutex) { mutex_ = mutex; }
|
||||
|
||||
boost::scoped_ptr<Mutex> ownedMutex_;
|
||||
Mutex* mutex_;
|
||||
};
|
||||
|
||||
Monitor::Monitor() : impl_(new Monitor::Impl()) {
|
||||
}
|
||||
Monitor::Monitor(Mutex* mutex) : impl_(new Monitor::Impl(mutex)) {
|
||||
}
|
||||
Monitor::Monitor(Monitor* monitor) : impl_(new Monitor::Impl(monitor)) {
|
||||
}
|
||||
|
||||
Monitor::~Monitor() {
|
||||
delete impl_;
|
||||
}
|
||||
|
||||
Mutex& Monitor::mutex() const {
|
||||
return const_cast<Monitor::Impl*>(impl_)->mutex();
|
||||
}
|
||||
|
||||
void Monitor::lock() const {
|
||||
const_cast<Monitor::Impl*>(impl_)->lock();
|
||||
}
|
||||
|
||||
void Monitor::unlock() const {
|
||||
const_cast<Monitor::Impl*>(impl_)->unlock();
|
||||
}
|
||||
|
||||
void Monitor::wait(int64_t timeout) const {
|
||||
const_cast<Monitor::Impl*>(impl_)->wait(timeout);
|
||||
}
|
||||
|
||||
int Monitor::waitForTime(const THRIFT_TIMESPEC* abstime) const {
|
||||
return const_cast<Monitor::Impl*>(impl_)->waitForTime(abstime);
|
||||
}
|
||||
|
||||
int Monitor::waitForTime(const timeval* abstime) const {
|
||||
return const_cast<Monitor::Impl*>(impl_)->waitForTime(abstime);
|
||||
}
|
||||
|
||||
int Monitor::waitForTimeRelative(int64_t timeout_ms) const {
|
||||
return const_cast<Monitor::Impl*>(impl_)->waitForTimeRelative(timeout_ms);
|
||||
}
|
||||
|
||||
int Monitor::waitForever() const {
|
||||
return const_cast<Monitor::Impl*>(impl_)->waitForever();
|
||||
}
|
||||
|
||||
void Monitor::notify() const {
|
||||
const_cast<Monitor::Impl*>(impl_)->notify();
|
||||
}
|
||||
|
||||
void Monitor::notifyAll() const {
|
||||
const_cast<Monitor::Impl*>(impl_)->notifyAll();
|
||||
}
|
||||
}
|
||||
}
|
||||
} // apache::thrift::concurrency
|
71
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/concurrency/BoostMutex.cpp
generated
vendored
Normal file
71
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/concurrency/BoostMutex.cpp
generated
vendored
Normal file
|
@ -0,0 +1,71 @@
|
|||
/*
|
||||
* 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 <thrift/concurrency/Mutex.h>
|
||||
#include <thrift/concurrency/Util.h>
|
||||
#include <thrift/Thrift.h>
|
||||
|
||||
#include <cassert>
|
||||
#include <boost/thread.hpp>
|
||||
#include <boost/thread/mutex.hpp>
|
||||
#include <boost/date_time/posix_time/posix_time.hpp>
|
||||
|
||||
namespace apache {
|
||||
namespace thrift {
|
||||
namespace concurrency {
|
||||
|
||||
/**
|
||||
* Implementation of Mutex class using boost interprocess mutex
|
||||
*
|
||||
* @version $Id:$
|
||||
*/
|
||||
class Mutex::impl : public boost::timed_mutex {};
|
||||
|
||||
Mutex::Mutex(Initializer init) : impl_(new Mutex::impl()) {
|
||||
THRIFT_UNUSED_VARIABLE(init);
|
||||
}
|
||||
|
||||
void* Mutex::getUnderlyingImpl() const {
|
||||
return impl_.get();
|
||||
}
|
||||
|
||||
void Mutex::lock() const {
|
||||
impl_->lock();
|
||||
}
|
||||
|
||||
bool Mutex::trylock() const {
|
||||
return impl_->try_lock();
|
||||
}
|
||||
|
||||
bool Mutex::timedlock(int64_t ms) const {
|
||||
return impl_->timed_lock(boost::get_system_time() + boost::posix_time::milliseconds(ms));
|
||||
}
|
||||
|
||||
void Mutex::unlock() const {
|
||||
impl_->unlock();
|
||||
}
|
||||
|
||||
void Mutex::DEFAULT_INITIALIZER(void* arg) {
|
||||
THRIFT_UNUSED_VARIABLE(arg);
|
||||
}
|
||||
}
|
||||
}
|
||||
} // apache::thrift::concurrency
|
147
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/concurrency/BoostThreadFactory.cpp
generated
vendored
Normal file
147
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/concurrency/BoostThreadFactory.cpp
generated
vendored
Normal file
|
@ -0,0 +1,147 @@
|
|||
/*
|
||||
* 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>
|
||||
|
||||
#if USE_BOOST_THREAD
|
||||
|
||||
#include <thrift/concurrency/BoostThreadFactory.h>
|
||||
#include <thrift/concurrency/Exception.h>
|
||||
|
||||
#include <cassert>
|
||||
|
||||
#include <boost/weak_ptr.hpp>
|
||||
#include <boost/thread.hpp>
|
||||
|
||||
namespace apache {
|
||||
namespace thrift {
|
||||
namespace concurrency {
|
||||
|
||||
using boost::shared_ptr;
|
||||
using boost::weak_ptr;
|
||||
|
||||
/**
|
||||
* The boost thread class.
|
||||
*
|
||||
* @version $Id:$
|
||||
*/
|
||||
class BoostThread : public Thread {
|
||||
public:
|
||||
enum STATE { uninitialized, starting, started, stopping, stopped };
|
||||
|
||||
static void* threadMain(void* arg);
|
||||
|
||||
private:
|
||||
std::auto_ptr<boost::thread> thread_;
|
||||
STATE state_;
|
||||
weak_ptr<BoostThread> self_;
|
||||
bool detached_;
|
||||
|
||||
public:
|
||||
BoostThread(bool detached, shared_ptr<Runnable> runnable)
|
||||
: state_(uninitialized), detached_(detached) {
|
||||
this->Thread::runnable(runnable);
|
||||
}
|
||||
|
||||
~BoostThread() {
|
||||
if (!detached_) {
|
||||
try {
|
||||
join();
|
||||
} catch (...) {
|
||||
// We're really hosed.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void start() {
|
||||
if (state_ != uninitialized) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Create reference
|
||||
shared_ptr<BoostThread>* selfRef = new shared_ptr<BoostThread>();
|
||||
*selfRef = self_.lock();
|
||||
|
||||
state_ = starting;
|
||||
|
||||
thread_
|
||||
= std::auto_ptr<boost::thread>(new boost::thread(boost::bind(threadMain, (void*)selfRef)));
|
||||
|
||||
if (detached_)
|
||||
thread_->detach();
|
||||
}
|
||||
|
||||
void join() {
|
||||
if (!detached_ && state_ != uninitialized) {
|
||||
thread_->join();
|
||||
}
|
||||
}
|
||||
|
||||
Thread::id_t getId() { return thread_.get() ? thread_->get_id() : boost::thread::id(); }
|
||||
|
||||
shared_ptr<Runnable> runnable() const { return Thread::runnable(); }
|
||||
|
||||
void runnable(shared_ptr<Runnable> value) { Thread::runnable(value); }
|
||||
|
||||
void weakRef(shared_ptr<BoostThread> self) {
|
||||
assert(self.get() == this);
|
||||
self_ = weak_ptr<BoostThread>(self);
|
||||
}
|
||||
};
|
||||
|
||||
void* BoostThread::threadMain(void* arg) {
|
||||
shared_ptr<BoostThread> thread = *(shared_ptr<BoostThread>*)arg;
|
||||
delete reinterpret_cast<shared_ptr<BoostThread>*>(arg);
|
||||
|
||||
if (!thread) {
|
||||
return (void*)0;
|
||||
}
|
||||
|
||||
if (thread->state_ != starting) {
|
||||
return (void*)0;
|
||||
}
|
||||
|
||||
thread->state_ = started;
|
||||
thread->runnable()->run();
|
||||
|
||||
if (thread->state_ != stopping && thread->state_ != stopped) {
|
||||
thread->state_ = stopping;
|
||||
}
|
||||
return (void*)0;
|
||||
}
|
||||
|
||||
BoostThreadFactory::BoostThreadFactory(bool detached)
|
||||
: ThreadFactory(detached) {
|
||||
}
|
||||
|
||||
shared_ptr<Thread> BoostThreadFactory::newThread(shared_ptr<Runnable> runnable) const {
|
||||
shared_ptr<BoostThread> result = shared_ptr<BoostThread>(new BoostThread(isDetached(), runnable));
|
||||
result->weakRef(result);
|
||||
runnable->thread(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
Thread::id_t BoostThreadFactory::getCurrentThreadId() const {
|
||||
return boost::this_thread::get_id();
|
||||
}
|
||||
}
|
||||
}
|
||||
} // apache::thrift::concurrency
|
||||
|
||||
#endif // USE_BOOST_THREAD
|
64
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/concurrency/BoostThreadFactory.h
generated
vendored
Normal file
64
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/concurrency/BoostThreadFactory.h
generated
vendored
Normal file
|
@ -0,0 +1,64 @@
|
|||
/*
|
||||
* 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_CONCURRENCY_BOOSTTHREADFACTORY_H_
|
||||
#define _THRIFT_CONCURRENCY_BOOSTTHREADFACTORY_H_ 1
|
||||
|
||||
#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;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
} // apache::thrift::concurrency
|
||||
|
||||
#endif // #ifndef _THRIFT_CONCURRENCY_BOOSTTHREADFACTORY_H_
|
64
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/concurrency/Exception.h
generated
vendored
Normal file
64
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/concurrency/Exception.h
generated
vendored
Normal file
|
@ -0,0 +1,64 @@
|
|||
/*
|
||||
* 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_CONCURRENCY_EXCEPTION_H_
|
||||
#define _THRIFT_CONCURRENCY_EXCEPTION_H_ 1
|
||||
|
||||
#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
|
||||
|
||||
#endif // #ifndef _THRIFT_CONCURRENCY_EXCEPTION_H_
|
118
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/concurrency/FunctionRunner.h
generated
vendored
Normal file
118
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/concurrency/FunctionRunner.h
generated
vendored
Normal file
|
@ -0,0 +1,118 @@
|
|||
/*
|
||||
* 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_CONCURRENCY_FUNCTION_RUNNER_H
|
||||
#define _THRIFT_CONCURRENCY_FUNCTION_RUNNER_H 1
|
||||
|
||||
#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)), intervalMs_(-1) {}
|
||||
|
||||
/**
|
||||
* Given a generic callback, this FunctionRunner will execute it.
|
||||
*/
|
||||
FunctionRunner(const VoidFunc& cob) : func_(cob), intervalMs_(-1) {}
|
||||
|
||||
/**
|
||||
* 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
|
||||
|
||||
#endif // #ifndef _THRIFT_CONCURRENCY_FUNCTION_RUNNER_H
|
224
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/concurrency/Monitor.cpp
generated
vendored
Normal file
224
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/concurrency/Monitor.cpp
generated
vendored
Normal file
|
@ -0,0 +1,224 @@
|
|||
/*
|
||||
* 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 <thrift/concurrency/Monitor.h>
|
||||
#include <thrift/concurrency/Exception.h>
|
||||
#include <thrift/concurrency/Util.h>
|
||||
#include <thrift/transport/PlatformSocket.h>
|
||||
|
||||
#include <boost/scoped_ptr.hpp>
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
namespace apache {
|
||||
namespace thrift {
|
||||
namespace concurrency {
|
||||
|
||||
using boost::scoped_ptr;
|
||||
|
||||
/**
|
||||
* Monitor implementation using the POSIX pthread library
|
||||
*
|
||||
* @version $Id:$
|
||||
*/
|
||||
class Monitor::Impl {
|
||||
|
||||
public:
|
||||
Impl() : ownedMutex_(new Mutex()), mutex_(NULL), condInitialized_(false) {
|
||||
init(ownedMutex_.get());
|
||||
}
|
||||
|
||||
Impl(Mutex* mutex) : mutex_(NULL), condInitialized_(false) { init(mutex); }
|
||||
|
||||
Impl(Monitor* monitor) : mutex_(NULL), condInitialized_(false) { init(&(monitor->mutex())); }
|
||||
|
||||
~Impl() { cleanup(); }
|
||||
|
||||
Mutex& mutex() { return *mutex_; }
|
||||
void lock() { mutex().lock(); }
|
||||
void unlock() { mutex().unlock(); }
|
||||
|
||||
/**
|
||||
* 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) const {
|
||||
int result = waitForTimeRelative(timeout_ms);
|
||||
if (result == THRIFT_ETIMEDOUT) {
|
||||
// pthread_cond_timedwait has been observed to return early on
|
||||
// various platforms, so comment out this assert.
|
||||
// assert(Util::currentTime() >= (now + timeout));
|
||||
throw TimedOutException();
|
||||
} else if (result != 0) {
|
||||
throw TException("pthread_cond_wait() or pthread_cond_timedwait() failed");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Waits until 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 {
|
||||
if (timeout_ms == 0LL) {
|
||||
return waitForever();
|
||||
}
|
||||
|
||||
struct THRIFT_TIMESPEC abstime;
|
||||
Util::toTimespec(abstime, Util::currentTime() + timeout_ms);
|
||||
return waitForTime(&abstime);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 {
|
||||
assert(mutex_);
|
||||
pthread_mutex_t* mutexImpl = reinterpret_cast<pthread_mutex_t*>(mutex_->getUnderlyingImpl());
|
||||
assert(mutexImpl);
|
||||
|
||||
// XXX Need to assert that caller owns mutex
|
||||
return pthread_cond_timedwait(&pthread_cond_, mutexImpl, abstime);
|
||||
}
|
||||
|
||||
int waitForTime(const struct timeval* abstime) const {
|
||||
struct THRIFT_TIMESPEC temp;
|
||||
temp.tv_sec = abstime->tv_sec;
|
||||
temp.tv_nsec = abstime->tv_usec * 1000;
|
||||
return waitForTime(&temp);
|
||||
}
|
||||
/**
|
||||
* Waits forever until the condition occurs.
|
||||
* Returns 0 if condition occurs, or an error code otherwise.
|
||||
*/
|
||||
int waitForever() const {
|
||||
assert(mutex_);
|
||||
pthread_mutex_t* mutexImpl = reinterpret_cast<pthread_mutex_t*>(mutex_->getUnderlyingImpl());
|
||||
assert(mutexImpl);
|
||||
return pthread_cond_wait(&pthread_cond_, mutexImpl);
|
||||
}
|
||||
|
||||
void notify() {
|
||||
// XXX Need to assert that caller owns mutex
|
||||
int iret = pthread_cond_signal(&pthread_cond_);
|
||||
THRIFT_UNUSED_VARIABLE(iret);
|
||||
assert(iret == 0);
|
||||
}
|
||||
|
||||
void notifyAll() {
|
||||
// XXX Need to assert that caller owns mutex
|
||||
int iret = pthread_cond_broadcast(&pthread_cond_);
|
||||
THRIFT_UNUSED_VARIABLE(iret);
|
||||
assert(iret == 0);
|
||||
}
|
||||
|
||||
private:
|
||||
void init(Mutex* mutex) {
|
||||
mutex_ = mutex;
|
||||
|
||||
if (pthread_cond_init(&pthread_cond_, NULL) == 0) {
|
||||
condInitialized_ = true;
|
||||
}
|
||||
|
||||
if (!condInitialized_) {
|
||||
cleanup();
|
||||
throw SystemResourceException();
|
||||
}
|
||||
}
|
||||
|
||||
void cleanup() {
|
||||
if (condInitialized_) {
|
||||
condInitialized_ = false;
|
||||
int iret = pthread_cond_destroy(&pthread_cond_);
|
||||
THRIFT_UNUSED_VARIABLE(iret);
|
||||
assert(iret == 0);
|
||||
}
|
||||
}
|
||||
|
||||
scoped_ptr<Mutex> ownedMutex_;
|
||||
Mutex* mutex_;
|
||||
|
||||
mutable pthread_cond_t pthread_cond_;
|
||||
mutable bool condInitialized_;
|
||||
};
|
||||
|
||||
Monitor::Monitor() : impl_(new Monitor::Impl()) {
|
||||
}
|
||||
Monitor::Monitor(Mutex* mutex) : impl_(new Monitor::Impl(mutex)) {
|
||||
}
|
||||
Monitor::Monitor(Monitor* monitor) : impl_(new Monitor::Impl(monitor)) {
|
||||
}
|
||||
|
||||
Monitor::~Monitor() {
|
||||
delete impl_;
|
||||
}
|
||||
|
||||
Mutex& Monitor::mutex() const {
|
||||
return impl_->mutex();
|
||||
}
|
||||
|
||||
void Monitor::lock() const {
|
||||
impl_->lock();
|
||||
}
|
||||
|
||||
void Monitor::unlock() const {
|
||||
impl_->unlock();
|
||||
}
|
||||
|
||||
void Monitor::wait(int64_t timeout) const {
|
||||
impl_->wait(timeout);
|
||||
}
|
||||
|
||||
int Monitor::waitForTime(const THRIFT_TIMESPEC* abstime) const {
|
||||
return impl_->waitForTime(abstime);
|
||||
}
|
||||
|
||||
int Monitor::waitForTime(const timeval* abstime) const {
|
||||
return impl_->waitForTime(abstime);
|
||||
}
|
||||
|
||||
int Monitor::waitForTimeRelative(int64_t timeout_ms) const {
|
||||
return impl_->waitForTimeRelative(timeout_ms);
|
||||
}
|
||||
|
||||
int Monitor::waitForever() const {
|
||||
return impl_->waitForever();
|
||||
}
|
||||
|
||||
void Monitor::notify() const {
|
||||
impl_->notify();
|
||||
}
|
||||
|
||||
void Monitor::notifyAll() const {
|
||||
impl_->notifyAll();
|
||||
}
|
||||
}
|
||||
}
|
||||
} // apache::thrift::concurrency
|
133
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/concurrency/Monitor.h
generated
vendored
Normal file
133
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/concurrency/Monitor.h
generated
vendored
Normal file
|
@ -0,0 +1,133 @@
|
|||
/*
|
||||
* 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_CONCURRENCY_MONITOR_H_
|
||||
#define _THRIFT_CONCURRENCY_MONITOR_H_ 1
|
||||
|
||||
#ifdef HAVE_SYS_TIME_H
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
|
||||
#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
|
||||
|
||||
#endif // #ifndef _THRIFT_CONCURRENCY_MONITOR_H_
|
373
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/concurrency/Mutex.cpp
generated
vendored
Normal file
373
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/concurrency/Mutex.cpp
generated
vendored
Normal file
|
@ -0,0 +1,373 @@
|
|||
/*
|
||||
* 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 <thrift/Thrift.h>
|
||||
#include <thrift/concurrency/Mutex.h>
|
||||
#include <thrift/concurrency/Util.h>
|
||||
|
||||
#include <assert.h>
|
||||
#ifdef HAVE_PTHREAD_H
|
||||
#include <pthread.h>
|
||||
#endif
|
||||
#include <signal.h>
|
||||
|
||||
using boost::shared_ptr;
|
||||
|
||||
namespace apache {
|
||||
namespace thrift {
|
||||
namespace concurrency {
|
||||
|
||||
#ifndef THRIFT_NO_CONTENTION_PROFILING
|
||||
|
||||
static int32_t mutexProfilingCounter = 0;
|
||||
static int32_t mutexProfilingSampleRate = 0;
|
||||
static MutexWaitCallback mutexProfilingCallback = 0;
|
||||
|
||||
void enableMutexProfiling(int32_t profilingSampleRate, MutexWaitCallback callback) {
|
||||
mutexProfilingSampleRate = profilingSampleRate;
|
||||
mutexProfilingCallback = callback;
|
||||
}
|
||||
|
||||
#define PROFILE_MUTEX_START_LOCK() int64_t _lock_startTime = maybeGetProfilingStartTime();
|
||||
|
||||
#define PROFILE_MUTEX_NOT_LOCKED() \
|
||||
do { \
|
||||
if (_lock_startTime > 0) { \
|
||||
int64_t endTime = Util::currentTimeUsec(); \
|
||||
(*mutexProfilingCallback)(this, endTime - _lock_startTime); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define PROFILE_MUTEX_LOCKED() \
|
||||
do { \
|
||||
profileTime_ = _lock_startTime; \
|
||||
if (profileTime_ > 0) { \
|
||||
profileTime_ = Util::currentTimeUsec() - profileTime_; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define PROFILE_MUTEX_START_UNLOCK() \
|
||||
int64_t _temp_profileTime = profileTime_; \
|
||||
profileTime_ = 0;
|
||||
|
||||
#define PROFILE_MUTEX_UNLOCKED() \
|
||||
do { \
|
||||
if (_temp_profileTime > 0) { \
|
||||
(*mutexProfilingCallback)(this, _temp_profileTime); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
static inline int64_t maybeGetProfilingStartTime() {
|
||||
if (mutexProfilingSampleRate && mutexProfilingCallback) {
|
||||
// This block is unsynchronized, but should produce a reasonable sampling
|
||||
// rate on most architectures. The main race conditions are the gap
|
||||
// between the decrement and the test, the non-atomicity of decrement, and
|
||||
// potential caching of different values at different CPUs.
|
||||
//
|
||||
// - if two decrements race, the likeliest result is that the counter
|
||||
// decrements slowly (perhaps much more slowly) than intended.
|
||||
//
|
||||
// - many threads could potentially decrement before resetting the counter
|
||||
// to its large value, causing each additional incoming thread to
|
||||
// profile every call. This situation is unlikely to persist for long
|
||||
// as the critical gap is quite short, but profiling could be bursty.
|
||||
sig_atomic_t localValue = --mutexProfilingCounter;
|
||||
if (localValue <= 0) {
|
||||
mutexProfilingCounter = mutexProfilingSampleRate;
|
||||
return Util::currentTimeUsec();
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#else
|
||||
#define PROFILE_MUTEX_START_LOCK()
|
||||
#define PROFILE_MUTEX_NOT_LOCKED()
|
||||
#define PROFILE_MUTEX_LOCKED()
|
||||
#define PROFILE_MUTEX_START_UNLOCK()
|
||||
#define PROFILE_MUTEX_UNLOCKED()
|
||||
#endif // THRIFT_NO_CONTENTION_PROFILING
|
||||
|
||||
/**
|
||||
* Implementation of Mutex class using POSIX mutex
|
||||
*
|
||||
* @version $Id:$
|
||||
*/
|
||||
class Mutex::impl {
|
||||
public:
|
||||
impl(Initializer init) : initialized_(false) {
|
||||
#ifndef THRIFT_NO_CONTENTION_PROFILING
|
||||
profileTime_ = 0;
|
||||
#endif
|
||||
init(&pthread_mutex_);
|
||||
initialized_ = true;
|
||||
}
|
||||
|
||||
~impl() {
|
||||
if (initialized_) {
|
||||
initialized_ = false;
|
||||
int ret = pthread_mutex_destroy(&pthread_mutex_);
|
||||
THRIFT_UNUSED_VARIABLE(ret);
|
||||
assert(ret == 0);
|
||||
}
|
||||
}
|
||||
|
||||
void lock() const {
|
||||
PROFILE_MUTEX_START_LOCK();
|
||||
pthread_mutex_lock(&pthread_mutex_);
|
||||
PROFILE_MUTEX_LOCKED();
|
||||
}
|
||||
|
||||
bool trylock() const { return (0 == pthread_mutex_trylock(&pthread_mutex_)); }
|
||||
|
||||
bool timedlock(int64_t milliseconds) const {
|
||||
#if defined(_POSIX_TIMEOUTS) && _POSIX_TIMEOUTS >= 200112L
|
||||
PROFILE_MUTEX_START_LOCK();
|
||||
|
||||
struct THRIFT_TIMESPEC ts;
|
||||
Util::toTimespec(ts, milliseconds + Util::currentTime());
|
||||
int ret = pthread_mutex_timedlock(&pthread_mutex_, &ts);
|
||||
if (ret == 0) {
|
||||
PROFILE_MUTEX_LOCKED();
|
||||
return true;
|
||||
}
|
||||
|
||||
PROFILE_MUTEX_NOT_LOCKED();
|
||||
return false;
|
||||
#else
|
||||
/* Otherwise follow solution used by Mono for Android */
|
||||
struct THRIFT_TIMESPEC sleepytime, now, to;
|
||||
|
||||
/* This is just to avoid a completely busy wait */
|
||||
sleepytime.tv_sec = 0;
|
||||
sleepytime.tv_nsec = 10000000L; /* 10ms */
|
||||
|
||||
Util::toTimespec(to, milliseconds + Util::currentTime());
|
||||
|
||||
while ((trylock()) == false) {
|
||||
Util::toTimespec(now, Util::currentTime());
|
||||
if (now.tv_sec >= to.tv_sec && now.tv_nsec >= to.tv_nsec) {
|
||||
return false;
|
||||
}
|
||||
nanosleep(&sleepytime, NULL);
|
||||
}
|
||||
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
void unlock() const {
|
||||
PROFILE_MUTEX_START_UNLOCK();
|
||||
pthread_mutex_unlock(&pthread_mutex_);
|
||||
PROFILE_MUTEX_UNLOCKED();
|
||||
}
|
||||
|
||||
void* getUnderlyingImpl() const { return (void*)&pthread_mutex_; }
|
||||
|
||||
private:
|
||||
mutable pthread_mutex_t pthread_mutex_;
|
||||
mutable bool initialized_;
|
||||
#ifndef THRIFT_NO_CONTENTION_PROFILING
|
||||
mutable int64_t profileTime_;
|
||||
#endif
|
||||
};
|
||||
|
||||
Mutex::Mutex(Initializer init) : impl_(new Mutex::impl(init)) {
|
||||
}
|
||||
|
||||
void* Mutex::getUnderlyingImpl() const {
|
||||
return impl_->getUnderlyingImpl();
|
||||
}
|
||||
|
||||
void Mutex::lock() const {
|
||||
impl_->lock();
|
||||
}
|
||||
|
||||
bool Mutex::trylock() const {
|
||||
return impl_->trylock();
|
||||
}
|
||||
|
||||
bool Mutex::timedlock(int64_t ms) const {
|
||||
return impl_->timedlock(ms);
|
||||
}
|
||||
|
||||
void Mutex::unlock() const {
|
||||
impl_->unlock();
|
||||
}
|
||||
|
||||
void Mutex::DEFAULT_INITIALIZER(void* arg) {
|
||||
pthread_mutex_t* pthread_mutex = (pthread_mutex_t*)arg;
|
||||
int ret = pthread_mutex_init(pthread_mutex, NULL);
|
||||
THRIFT_UNUSED_VARIABLE(ret);
|
||||
assert(ret == 0);
|
||||
}
|
||||
|
||||
#if defined(PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP) \
|
||||
|| defined(PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP)
|
||||
static void init_with_kind(pthread_mutex_t* mutex, int kind) {
|
||||
pthread_mutexattr_t mutexattr;
|
||||
int ret = pthread_mutexattr_init(&mutexattr);
|
||||
assert(ret == 0);
|
||||
|
||||
// Apparently, this can fail. Should we really be aborting?
|
||||
ret = pthread_mutexattr_settype(&mutexattr, kind);
|
||||
assert(ret == 0);
|
||||
|
||||
ret = pthread_mutex_init(mutex, &mutexattr);
|
||||
assert(ret == 0);
|
||||
|
||||
ret = pthread_mutexattr_destroy(&mutexattr);
|
||||
assert(ret == 0);
|
||||
THRIFT_UNUSED_VARIABLE(ret);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP
|
||||
void Mutex::ADAPTIVE_INITIALIZER(void* arg) {
|
||||
// From mysql source: mysys/my_thr_init.c
|
||||
// Set mutex type to "fast" a.k.a "adaptive"
|
||||
//
|
||||
// In this case the thread may steal the mutex from some other thread
|
||||
// that is waiting for the same mutex. This will save us some
|
||||
// context switches but may cause a thread to 'starve forever' while
|
||||
// waiting for the mutex (not likely if the code within the mutex is
|
||||
// short).
|
||||
init_with_kind((pthread_mutex_t*)arg, PTHREAD_MUTEX_ADAPTIVE_NP);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
|
||||
void Mutex::RECURSIVE_INITIALIZER(void* arg) {
|
||||
init_with_kind((pthread_mutex_t*)arg, PTHREAD_MUTEX_RECURSIVE_NP);
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Implementation of ReadWriteMutex class using POSIX rw lock
|
||||
*
|
||||
* @version $Id:$
|
||||
*/
|
||||
class ReadWriteMutex::impl {
|
||||
public:
|
||||
impl() : initialized_(false) {
|
||||
#ifndef THRIFT_NO_CONTENTION_PROFILING
|
||||
profileTime_ = 0;
|
||||
#endif
|
||||
int ret = pthread_rwlock_init(&rw_lock_, NULL);
|
||||
THRIFT_UNUSED_VARIABLE(ret);
|
||||
assert(ret == 0);
|
||||
initialized_ = true;
|
||||
}
|
||||
|
||||
~impl() {
|
||||
if (initialized_) {
|
||||
initialized_ = false;
|
||||
int ret = pthread_rwlock_destroy(&rw_lock_);
|
||||
THRIFT_UNUSED_VARIABLE(ret);
|
||||
assert(ret == 0);
|
||||
}
|
||||
}
|
||||
|
||||
void acquireRead() const {
|
||||
PROFILE_MUTEX_START_LOCK();
|
||||
pthread_rwlock_rdlock(&rw_lock_);
|
||||
PROFILE_MUTEX_NOT_LOCKED(); // not exclusive, so use not-locked path
|
||||
}
|
||||
|
||||
void acquireWrite() const {
|
||||
PROFILE_MUTEX_START_LOCK();
|
||||
pthread_rwlock_wrlock(&rw_lock_);
|
||||
PROFILE_MUTEX_LOCKED();
|
||||
}
|
||||
|
||||
bool attemptRead() const { return !pthread_rwlock_tryrdlock(&rw_lock_); }
|
||||
|
||||
bool attemptWrite() const { return !pthread_rwlock_trywrlock(&rw_lock_); }
|
||||
|
||||
void release() const {
|
||||
PROFILE_MUTEX_START_UNLOCK();
|
||||
pthread_rwlock_unlock(&rw_lock_);
|
||||
PROFILE_MUTEX_UNLOCKED();
|
||||
}
|
||||
|
||||
private:
|
||||
mutable pthread_rwlock_t rw_lock_;
|
||||
mutable bool initialized_;
|
||||
#ifndef THRIFT_NO_CONTENTION_PROFILING
|
||||
mutable int64_t profileTime_;
|
||||
#endif
|
||||
};
|
||||
|
||||
ReadWriteMutex::ReadWriteMutex() : impl_(new ReadWriteMutex::impl()) {
|
||||
}
|
||||
|
||||
void ReadWriteMutex::acquireRead() const {
|
||||
impl_->acquireRead();
|
||||
}
|
||||
|
||||
void ReadWriteMutex::acquireWrite() const {
|
||||
impl_->acquireWrite();
|
||||
}
|
||||
|
||||
bool ReadWriteMutex::attemptRead() const {
|
||||
return impl_->attemptRead();
|
||||
}
|
||||
|
||||
bool ReadWriteMutex::attemptWrite() const {
|
||||
return impl_->attemptWrite();
|
||||
}
|
||||
|
||||
void ReadWriteMutex::release() const {
|
||||
impl_->release();
|
||||
}
|
||||
|
||||
NoStarveReadWriteMutex::NoStarveReadWriteMutex() : writerWaiting_(false) {
|
||||
}
|
||||
|
||||
void NoStarveReadWriteMutex::acquireRead() const {
|
||||
if (writerWaiting_) {
|
||||
// writer is waiting, block on the writer's mutex until he's done with it
|
||||
mutex_.lock();
|
||||
mutex_.unlock();
|
||||
}
|
||||
|
||||
ReadWriteMutex::acquireRead();
|
||||
}
|
||||
|
||||
void NoStarveReadWriteMutex::acquireWrite() const {
|
||||
// if we can acquire the rwlock the easy way, we're done
|
||||
if (attemptWrite()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// failed to get the rwlock, do it the hard way:
|
||||
// locking the mutex and setting writerWaiting will cause all new readers to
|
||||
// block on the mutex rather than on the rwlock.
|
||||
mutex_.lock();
|
||||
writerWaiting_ = true;
|
||||
ReadWriteMutex::acquireWrite();
|
||||
writerWaiting_ = false;
|
||||
mutex_.unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
} // apache::thrift::concurrency
|
180
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/concurrency/Mutex.h
generated
vendored
Normal file
180
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/concurrency/Mutex.h
generated
vendored
Normal file
|
@ -0,0 +1,180 @@
|
|||
/*
|
||||
* 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_CONCURRENCY_MUTEX_H_
|
||||
#define _THRIFT_CONCURRENCY_MUTEX_H_ 1
|
||||
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <boost/noncopyable.hpp>
|
||||
#include <stdint.h>
|
||||
|
||||
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
|
||||
|
||||
#endif // #ifndef _THRIFT_CONCURRENCY_MUTEX_H_
|
52
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/concurrency/PlatformThreadFactory.h
generated
vendored
Normal file
52
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/concurrency/PlatformThreadFactory.h
generated
vendored
Normal file
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
* 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_CONCURRENCY_PLATFORMTHREADFACTORY_H_
|
||||
#define _THRIFT_CONCURRENCY_PLATFORMTHREADFACTORY_H_ 1
|
||||
|
||||
// clang-format off
|
||||
#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
|
||||
// clang-format on
|
||||
|
||||
namespace apache {
|
||||
namespace thrift {
|
||||
namespace concurrency {
|
||||
|
||||
// clang-format off
|
||||
#if USE_BOOST_THREAD
|
||||
typedef BoostThreadFactory PlatformThreadFactory;
|
||||
#elif USE_STD_THREAD
|
||||
typedef StdThreadFactory PlatformThreadFactory;
|
||||
#else
|
||||
typedef PosixThreadFactory PlatformThreadFactory;
|
||||
#endif
|
||||
// clang-format on
|
||||
|
||||
}
|
||||
}
|
||||
} // apache::thrift::concurrency
|
||||
|
||||
#endif // #ifndef _THRIFT_CONCURRENCY_PLATFORMTHREADFACTORY_H_
|
317
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/concurrency/PosixThreadFactory.cpp
generated
vendored
Normal file
317
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/concurrency/PosixThreadFactory.cpp
generated
vendored
Normal file
|
@ -0,0 +1,317 @@
|
|||
/*
|
||||
* 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 <thrift/concurrency/PosixThreadFactory.h>
|
||||
#include <thrift/concurrency/Exception.h>
|
||||
|
||||
#if GOOGLE_PERFTOOLS_REGISTER_THREAD
|
||||
#include <google/profiler.h>
|
||||
#endif
|
||||
|
||||
#include <assert.h>
|
||||
#include <pthread.h>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include <boost/weak_ptr.hpp>
|
||||
|
||||
namespace apache {
|
||||
namespace thrift {
|
||||
namespace concurrency {
|
||||
|
||||
using boost::shared_ptr;
|
||||
using boost::weak_ptr;
|
||||
|
||||
/**
|
||||
* The POSIX thread class.
|
||||
*
|
||||
* @version $Id:$
|
||||
*/
|
||||
class PthreadThread : public Thread {
|
||||
public:
|
||||
enum STATE { uninitialized, starting, started, stopping, stopped };
|
||||
|
||||
static const int MB = 1024 * 1024;
|
||||
|
||||
static void* threadMain(void* arg);
|
||||
|
||||
private:
|
||||
pthread_t pthread_;
|
||||
STATE state_;
|
||||
int policy_;
|
||||
int priority_;
|
||||
int stackSize_;
|
||||
weak_ptr<PthreadThread> self_;
|
||||
bool detached_;
|
||||
|
||||
public:
|
||||
PthreadThread(int policy,
|
||||
int priority,
|
||||
int stackSize,
|
||||
bool detached,
|
||||
shared_ptr<Runnable> runnable)
|
||||
:
|
||||
|
||||
#ifndef _WIN32
|
||||
pthread_(0),
|
||||
#endif // _WIN32
|
||||
|
||||
state_(uninitialized),
|
||||
policy_(policy),
|
||||
priority_(priority),
|
||||
stackSize_(stackSize),
|
||||
detached_(detached) {
|
||||
|
||||
this->Thread::runnable(runnable);
|
||||
}
|
||||
|
||||
~PthreadThread() {
|
||||
/* Nothing references this thread, if is is not detached, do a join
|
||||
now, otherwise the thread-id and, possibly, other resources will
|
||||
be leaked. */
|
||||
if (!detached_) {
|
||||
try {
|
||||
join();
|
||||
} catch (...) {
|
||||
// We're really hosed.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void start() {
|
||||
if (state_ != uninitialized) {
|
||||
return;
|
||||
}
|
||||
|
||||
pthread_attr_t thread_attr;
|
||||
if (pthread_attr_init(&thread_attr) != 0) {
|
||||
throw SystemResourceException("pthread_attr_init failed");
|
||||
}
|
||||
|
||||
if (pthread_attr_setdetachstate(&thread_attr,
|
||||
detached_ ? PTHREAD_CREATE_DETACHED : PTHREAD_CREATE_JOINABLE)
|
||||
!= 0) {
|
||||
throw SystemResourceException("pthread_attr_setdetachstate failed");
|
||||
}
|
||||
|
||||
// Set thread stack size
|
||||
if (pthread_attr_setstacksize(&thread_attr, MB * stackSize_) != 0) {
|
||||
throw SystemResourceException("pthread_attr_setstacksize failed");
|
||||
}
|
||||
|
||||
// Set thread policy
|
||||
#ifdef _WIN32
|
||||
// WIN32 Pthread implementation doesn't seem to support sheduling policies other then
|
||||
// PosixThreadFactory::OTHER - runtime error
|
||||
policy_ = PosixThreadFactory::OTHER;
|
||||
#endif
|
||||
|
||||
#if _POSIX_THREAD_PRIORITY_SCHEDULING > 0
|
||||
if (pthread_attr_setschedpolicy(&thread_attr, policy_) != 0) {
|
||||
throw SystemResourceException("pthread_attr_setschedpolicy failed");
|
||||
}
|
||||
#endif
|
||||
|
||||
struct sched_param sched_param;
|
||||
sched_param.sched_priority = priority_;
|
||||
|
||||
// Set thread priority
|
||||
if (pthread_attr_setschedparam(&thread_attr, &sched_param) != 0) {
|
||||
throw SystemResourceException("pthread_attr_setschedparam failed");
|
||||
}
|
||||
|
||||
// Create reference
|
||||
shared_ptr<PthreadThread>* selfRef = new shared_ptr<PthreadThread>();
|
||||
*selfRef = self_.lock();
|
||||
|
||||
state_ = starting;
|
||||
|
||||
if (pthread_create(&pthread_, &thread_attr, threadMain, (void*)selfRef) != 0) {
|
||||
throw SystemResourceException("pthread_create failed");
|
||||
}
|
||||
}
|
||||
|
||||
void join() {
|
||||
if (!detached_ && state_ != uninitialized) {
|
||||
void* ignore;
|
||||
/* XXX
|
||||
If join fails it is most likely due to the fact
|
||||
that the last reference was the thread itself and cannot
|
||||
join. This results in leaked threads and will eventually
|
||||
cause the process to run out of thread resources.
|
||||
We're beyond the point of throwing an exception. Not clear how
|
||||
best to handle this. */
|
||||
int res = pthread_join(pthread_, &ignore);
|
||||
detached_ = (res == 0);
|
||||
if (res != 0) {
|
||||
GlobalOutput.printf("PthreadThread::join(): fail with code %d", res);
|
||||
}
|
||||
} else {
|
||||
GlobalOutput.printf("PthreadThread::join(): detached thread");
|
||||
}
|
||||
}
|
||||
|
||||
Thread::id_t getId() {
|
||||
|
||||
#ifndef _WIN32
|
||||
return (Thread::id_t)pthread_;
|
||||
#else
|
||||
return (Thread::id_t)pthread_.p;
|
||||
#endif // _WIN32
|
||||
}
|
||||
|
||||
shared_ptr<Runnable> runnable() const { return Thread::runnable(); }
|
||||
|
||||
void runnable(shared_ptr<Runnable> value) { Thread::runnable(value); }
|
||||
|
||||
void weakRef(shared_ptr<PthreadThread> self) {
|
||||
assert(self.get() == this);
|
||||
self_ = weak_ptr<PthreadThread>(self);
|
||||
}
|
||||
};
|
||||
|
||||
void* PthreadThread::threadMain(void* arg) {
|
||||
shared_ptr<PthreadThread> thread = *(shared_ptr<PthreadThread>*)arg;
|
||||
delete reinterpret_cast<shared_ptr<PthreadThread>*>(arg);
|
||||
|
||||
if (thread == NULL) {
|
||||
return (void*)0;
|
||||
}
|
||||
|
||||
if (thread->state_ != starting) {
|
||||
return (void*)0;
|
||||
}
|
||||
|
||||
#if GOOGLE_PERFTOOLS_REGISTER_THREAD
|
||||
ProfilerRegisterThread();
|
||||
#endif
|
||||
|
||||
thread->state_ = started;
|
||||
thread->runnable()->run();
|
||||
if (thread->state_ != stopping && thread->state_ != stopped) {
|
||||
thread->state_ = stopping;
|
||||
}
|
||||
|
||||
return (void*)0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts generic posix thread schedule policy enums into pthread
|
||||
* API values.
|
||||
*/
|
||||
static int toPthreadPolicy(PosixThreadFactory::POLICY policy) {
|
||||
switch (policy) {
|
||||
case PosixThreadFactory::OTHER:
|
||||
return SCHED_OTHER;
|
||||
case PosixThreadFactory::FIFO:
|
||||
return SCHED_FIFO;
|
||||
case PosixThreadFactory::ROUND_ROBIN:
|
||||
return SCHED_RR;
|
||||
}
|
||||
return SCHED_OTHER;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts relative thread priorities to absolute value based on posix
|
||||
* thread scheduler policy
|
||||
*
|
||||
* The idea is simply to divide up the priority range for the given policy
|
||||
* into the correpsonding relative priority level (lowest..highest) and
|
||||
* then pro-rate accordingly.
|
||||
*/
|
||||
static int toPthreadPriority(PosixThreadFactory::POLICY policy, PosixThreadFactory::PRIORITY priority) {
|
||||
int pthread_policy = toPthreadPolicy(policy);
|
||||
int min_priority = 0;
|
||||
int max_priority = 0;
|
||||
#ifdef HAVE_SCHED_GET_PRIORITY_MIN
|
||||
min_priority = sched_get_priority_min(pthread_policy);
|
||||
#endif
|
||||
#ifdef HAVE_SCHED_GET_PRIORITY_MAX
|
||||
max_priority = sched_get_priority_max(pthread_policy);
|
||||
#endif
|
||||
int quanta = (PosixThreadFactory::HIGHEST - PosixThreadFactory::LOWEST) + 1;
|
||||
float stepsperquanta = (float)(max_priority - min_priority) / quanta;
|
||||
|
||||
if (priority <= PosixThreadFactory::HIGHEST) {
|
||||
return (int)(min_priority + stepsperquanta * priority);
|
||||
} else {
|
||||
// should never get here for priority increments.
|
||||
assert(false);
|
||||
return (int)(min_priority + stepsperquanta * PosixThreadFactory::NORMAL);
|
||||
}
|
||||
}
|
||||
|
||||
PosixThreadFactory::PosixThreadFactory(POLICY policy,
|
||||
PRIORITY priority,
|
||||
int stackSize,
|
||||
bool detached)
|
||||
: ThreadFactory(detached),
|
||||
policy_(policy),
|
||||
priority_(priority),
|
||||
stackSize_(stackSize) {
|
||||
}
|
||||
|
||||
PosixThreadFactory::PosixThreadFactory(bool detached)
|
||||
: ThreadFactory(detached),
|
||||
policy_(ROUND_ROBIN),
|
||||
priority_(NORMAL),
|
||||
stackSize_(1) {
|
||||
}
|
||||
|
||||
shared_ptr<Thread> PosixThreadFactory::newThread(shared_ptr<Runnable> runnable) const {
|
||||
shared_ptr<PthreadThread> result
|
||||
= shared_ptr<PthreadThread>(new PthreadThread(toPthreadPolicy(policy_),
|
||||
toPthreadPriority(policy_, priority_),
|
||||
stackSize_,
|
||||
isDetached(),
|
||||
runnable));
|
||||
result->weakRef(result);
|
||||
runnable->thread(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
int PosixThreadFactory::getStackSize() const {
|
||||
return stackSize_;
|
||||
}
|
||||
|
||||
void PosixThreadFactory::setStackSize(int value) {
|
||||
stackSize_ = value;
|
||||
}
|
||||
|
||||
PosixThreadFactory::PRIORITY PosixThreadFactory::getPriority() const {
|
||||
return priority_;
|
||||
}
|
||||
|
||||
void PosixThreadFactory::setPriority(PRIORITY value) {
|
||||
priority_ = value;
|
||||
}
|
||||
|
||||
Thread::id_t PosixThreadFactory::getCurrentThreadId() const {
|
||||
#ifndef _WIN32
|
||||
return (Thread::id_t)pthread_self();
|
||||
#else
|
||||
return (Thread::id_t)pthread_self().p;
|
||||
#endif // _WIN32
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
} // apache::thrift::concurrency
|
129
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/concurrency/PosixThreadFactory.h
generated
vendored
Normal file
129
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/concurrency/PosixThreadFactory.h
generated
vendored
Normal file
|
@ -0,0 +1,129 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
#ifndef _THRIFT_CONCURRENCY_POSIXTHREADFACTORY_H_
|
||||
#define _THRIFT_CONCURRENCY_POSIXTHREADFACTORY_H_ 1
|
||||
|
||||
#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 within 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);
|
||||
|
||||
/**
|
||||
* Provide a constructor compatible with the other factories
|
||||
* The default policy is POLICY::ROUND_ROBIN.
|
||||
* The default priority is PRIORITY::NORMAL.
|
||||
* The default stackSize is 1.
|
||||
*/
|
||||
PosixThreadFactory(bool detached);
|
||||
|
||||
// From ThreadFactory;
|
||||
boost::shared_ptr<Thread> newThread(boost::shared_ptr<Runnable> runnable) const;
|
||||
|
||||
// From ThreadFactory;
|
||||
Thread::id_t getCurrentThreadId() const;
|
||||
|
||||
/**
|
||||
* Gets stack size for newly created threads
|
||||
*
|
||||
* @return int size in megabytes
|
||||
*/
|
||||
virtual int getStackSize() const;
|
||||
|
||||
/**
|
||||
* Sets stack size for newly 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);
|
||||
|
||||
private:
|
||||
POLICY policy_;
|
||||
PRIORITY priority_;
|
||||
int stackSize_;
|
||||
};
|
||||
}
|
||||
}
|
||||
} // apache::thrift::concurrency
|
||||
|
||||
#endif // #ifndef _THRIFT_CONCURRENCY_POSIXTHREADFACTORY_H_
|
213
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/concurrency/StdMonitor.cpp
generated
vendored
Normal file
213
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/concurrency/StdMonitor.cpp
generated
vendored
Normal file
|
@ -0,0 +1,213 @@
|
|||
/*
|
||||
* 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 <thrift/concurrency/Monitor.h>
|
||||
#include <thrift/concurrency/Exception.h>
|
||||
#include <thrift/concurrency/Util.h>
|
||||
#include <thrift/transport/PlatformSocket.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include <condition_variable>
|
||||
#include <chrono>
|
||||
#include <thread>
|
||||
#include <mutex>
|
||||
|
||||
namespace apache {
|
||||
namespace thrift {
|
||||
namespace concurrency {
|
||||
|
||||
/**
|
||||
* Monitor implementation using the std thread library
|
||||
*
|
||||
* @version $Id:$
|
||||
*/
|
||||
class Monitor::Impl {
|
||||
|
||||
public:
|
||||
Impl() : ownedMutex_(new Mutex()), conditionVariable_(), mutex_(NULL) { init(ownedMutex_.get()); }
|
||||
|
||||
Impl(Mutex* mutex) : ownedMutex_(), conditionVariable_(), mutex_(NULL) { init(mutex); }
|
||||
|
||||
Impl(Monitor* monitor) : ownedMutex_(), conditionVariable_(), mutex_(NULL) {
|
||||
init(&(monitor->mutex()));
|
||||
}
|
||||
|
||||
Mutex& mutex() { return *mutex_; }
|
||||
void lock() { mutex_->lock(); }
|
||||
void unlock() { mutex_->unlock(); }
|
||||
|
||||
/**
|
||||
* 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) {
|
||||
int result = waitForTimeRelative(timeout_ms);
|
||||
if (result == THRIFT_ETIMEDOUT) {
|
||||
throw TimedOutException();
|
||||
} else if (result != 0) {
|
||||
throw TException("Monitor::wait() failed");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Waits until 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) {
|
||||
if (timeout_ms == 0LL) {
|
||||
return waitForever();
|
||||
}
|
||||
|
||||
assert(mutex_);
|
||||
std::timed_mutex* mutexImpl = static_cast<std::timed_mutex*>(mutex_->getUnderlyingImpl());
|
||||
assert(mutexImpl);
|
||||
|
||||
std::unique_lock<std::timed_mutex> lock(*mutexImpl, std::adopt_lock);
|
||||
bool timedout = (conditionVariable_.wait_for(lock, std::chrono::milliseconds(timeout_ms))
|
||||
== std::cv_status::timeout);
|
||||
lock.release();
|
||||
return (timedout ? THRIFT_ETIMEDOUT : 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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) {
|
||||
struct timeval temp;
|
||||
temp.tv_sec = static_cast<long>(abstime->tv_sec);
|
||||
temp.tv_usec = static_cast<long>(abstime->tv_nsec) / 1000;
|
||||
return waitForTime(&temp);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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) {
|
||||
assert(mutex_);
|
||||
std::timed_mutex* mutexImpl = static_cast<std::timed_mutex*>(mutex_->getUnderlyingImpl());
|
||||
assert(mutexImpl);
|
||||
|
||||
struct timeval currenttime;
|
||||
Util::toTimeval(currenttime, Util::currentTime());
|
||||
|
||||
long tv_sec = static_cast<long>(abstime->tv_sec - currenttime.tv_sec);
|
||||
long tv_usec = static_cast<long>(abstime->tv_usec - currenttime.tv_usec);
|
||||
if (tv_sec < 0)
|
||||
tv_sec = 0;
|
||||
if (tv_usec < 0)
|
||||
tv_usec = 0;
|
||||
|
||||
std::unique_lock<std::timed_mutex> lock(*mutexImpl, std::adopt_lock);
|
||||
bool timedout = (conditionVariable_.wait_for(lock,
|
||||
std::chrono::seconds(tv_sec)
|
||||
+ std::chrono::microseconds(tv_usec))
|
||||
== std::cv_status::timeout);
|
||||
lock.release();
|
||||
return (timedout ? THRIFT_ETIMEDOUT : 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Waits forever until the condition occurs.
|
||||
* Returns 0 if condition occurs, or an error code otherwise.
|
||||
*/
|
||||
int waitForever() {
|
||||
assert(mutex_);
|
||||
std::timed_mutex* mutexImpl = static_cast<std::timed_mutex*>(mutex_->getUnderlyingImpl());
|
||||
assert(mutexImpl);
|
||||
|
||||
std::unique_lock<std::timed_mutex> lock(*mutexImpl, std::adopt_lock);
|
||||
conditionVariable_.wait(lock);
|
||||
lock.release();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void notify() { conditionVariable_.notify_one(); }
|
||||
|
||||
void notifyAll() { conditionVariable_.notify_all(); }
|
||||
|
||||
private:
|
||||
void init(Mutex* mutex) { mutex_ = mutex; }
|
||||
|
||||
const std::unique_ptr<Mutex> ownedMutex_;
|
||||
std::condition_variable_any conditionVariable_;
|
||||
Mutex* mutex_;
|
||||
};
|
||||
|
||||
Monitor::Monitor() : impl_(new Monitor::Impl()) {
|
||||
}
|
||||
Monitor::Monitor(Mutex* mutex) : impl_(new Monitor::Impl(mutex)) {
|
||||
}
|
||||
Monitor::Monitor(Monitor* monitor) : impl_(new Monitor::Impl(monitor)) {
|
||||
}
|
||||
|
||||
Monitor::~Monitor() {
|
||||
delete impl_;
|
||||
}
|
||||
|
||||
Mutex& Monitor::mutex() const {
|
||||
return const_cast<Monitor::Impl*>(impl_)->mutex();
|
||||
}
|
||||
|
||||
void Monitor::lock() const {
|
||||
const_cast<Monitor::Impl*>(impl_)->lock();
|
||||
}
|
||||
|
||||
void Monitor::unlock() const {
|
||||
const_cast<Monitor::Impl*>(impl_)->unlock();
|
||||
}
|
||||
|
||||
void Monitor::wait(int64_t timeout) const {
|
||||
const_cast<Monitor::Impl*>(impl_)->wait(timeout);
|
||||
}
|
||||
|
||||
int Monitor::waitForTime(const THRIFT_TIMESPEC* abstime) const {
|
||||
return const_cast<Monitor::Impl*>(impl_)->waitForTime(abstime);
|
||||
}
|
||||
|
||||
int Monitor::waitForTime(const timeval* abstime) const {
|
||||
return const_cast<Monitor::Impl*>(impl_)->waitForTime(abstime);
|
||||
}
|
||||
|
||||
int Monitor::waitForTimeRelative(int64_t timeout_ms) const {
|
||||
return const_cast<Monitor::Impl*>(impl_)->waitForTimeRelative(timeout_ms);
|
||||
}
|
||||
|
||||
int Monitor::waitForever() const {
|
||||
return const_cast<Monitor::Impl*>(impl_)->waitForever();
|
||||
}
|
||||
|
||||
void Monitor::notify() const {
|
||||
const_cast<Monitor::Impl*>(impl_)->notify();
|
||||
}
|
||||
|
||||
void Monitor::notifyAll() const {
|
||||
const_cast<Monitor::Impl*>(impl_)->notifyAll();
|
||||
}
|
||||
}
|
||||
}
|
||||
} // apache::thrift::concurrency
|
67
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/concurrency/StdMutex.cpp
generated
vendored
Normal file
67
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/concurrency/StdMutex.cpp
generated
vendored
Normal file
|
@ -0,0 +1,67 @@
|
|||
/*
|
||||
* 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 <thrift/concurrency/Mutex.h>
|
||||
#include <thrift/concurrency/Util.h>
|
||||
|
||||
#include <cassert>
|
||||
#include <chrono>
|
||||
#include <mutex>
|
||||
|
||||
namespace apache {
|
||||
namespace thrift {
|
||||
namespace concurrency {
|
||||
|
||||
/**
|
||||
* Implementation of Mutex class using C++11 std::timed_mutex
|
||||
*
|
||||
* @version $Id:$
|
||||
*/
|
||||
class Mutex::impl : public std::timed_mutex {};
|
||||
|
||||
Mutex::Mutex(Initializer init) : impl_(new Mutex::impl()) {
|
||||
}
|
||||
|
||||
void* Mutex::getUnderlyingImpl() const {
|
||||
return impl_.get();
|
||||
}
|
||||
|
||||
void Mutex::lock() const {
|
||||
impl_->lock();
|
||||
}
|
||||
|
||||
bool Mutex::trylock() const {
|
||||
return impl_->try_lock();
|
||||
}
|
||||
|
||||
bool Mutex::timedlock(int64_t ms) const {
|
||||
return impl_->try_lock_for(std::chrono::milliseconds(ms));
|
||||
}
|
||||
|
||||
void Mutex::unlock() const {
|
||||
impl_->unlock();
|
||||
}
|
||||
|
||||
void Mutex::DEFAULT_INITIALIZER(void* arg) {
|
||||
}
|
||||
}
|
||||
}
|
||||
} // apache::thrift::concurrency
|
135
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/concurrency/StdThreadFactory.cpp
generated
vendored
Normal file
135
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/concurrency/StdThreadFactory.cpp
generated
vendored
Normal file
|
@ -0,0 +1,135 @@
|
|||
/*
|
||||
* 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>
|
||||
|
||||
#if USE_STD_THREAD
|
||||
|
||||
#include <thrift/concurrency/StdThreadFactory.h>
|
||||
#include <thrift/concurrency/Exception.h>
|
||||
|
||||
#include <cassert>
|
||||
|
||||
#include <boost/enable_shared_from_this.hpp>
|
||||
#include <boost/weak_ptr.hpp>
|
||||
#include <thread>
|
||||
|
||||
namespace apache {
|
||||
namespace thrift {
|
||||
namespace concurrency {
|
||||
|
||||
/**
|
||||
* The C++11 thread class.
|
||||
*
|
||||
* Note that we use boost shared_ptr rather than std shared_ptrs here
|
||||
* because the Thread/Runnable classes use those and we don't want to
|
||||
* mix them.
|
||||
*
|
||||
* @version $Id:$
|
||||
*/
|
||||
class StdThread : public Thread, public boost::enable_shared_from_this<StdThread> {
|
||||
public:
|
||||
enum STATE { uninitialized, starting, started, stopping, stopped };
|
||||
|
||||
static void threadMain(boost::shared_ptr<StdThread> thread);
|
||||
|
||||
private:
|
||||
std::unique_ptr<std::thread> thread_;
|
||||
STATE state_;
|
||||
bool detached_;
|
||||
|
||||
public:
|
||||
StdThread(bool detached, boost::shared_ptr<Runnable> runnable)
|
||||
: state_(uninitialized), detached_(detached) {
|
||||
this->Thread::runnable(runnable);
|
||||
}
|
||||
|
||||
~StdThread() {
|
||||
if (!detached_) {
|
||||
try {
|
||||
join();
|
||||
} catch (...) {
|
||||
// We're really hosed.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void start() {
|
||||
if (state_ != uninitialized) {
|
||||
return;
|
||||
}
|
||||
|
||||
boost::shared_ptr<StdThread> selfRef = shared_from_this();
|
||||
state_ = starting;
|
||||
|
||||
thread_ = std::unique_ptr<std::thread>(new std::thread(threadMain, selfRef));
|
||||
|
||||
if (detached_)
|
||||
thread_->detach();
|
||||
}
|
||||
|
||||
void join() {
|
||||
if (!detached_ && state_ != uninitialized) {
|
||||
thread_->join();
|
||||
}
|
||||
}
|
||||
|
||||
Thread::id_t getId() { return thread_.get() ? thread_->get_id() : std::thread::id(); }
|
||||
|
||||
boost::shared_ptr<Runnable> runnable() const { return Thread::runnable(); }
|
||||
|
||||
void runnable(boost::shared_ptr<Runnable> value) { Thread::runnable(value); }
|
||||
};
|
||||
|
||||
void StdThread::threadMain(boost::shared_ptr<StdThread> thread) {
|
||||
if (thread == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (thread->state_ != starting) {
|
||||
return;
|
||||
}
|
||||
|
||||
thread->state_ = started;
|
||||
thread->runnable()->run();
|
||||
|
||||
if (thread->state_ != stopping && thread->state_ != stopped) {
|
||||
thread->state_ = stopping;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
StdThreadFactory::StdThreadFactory(bool detached) : ThreadFactory(detached) {
|
||||
}
|
||||
|
||||
boost::shared_ptr<Thread> StdThreadFactory::newThread(boost::shared_ptr<Runnable> runnable) const {
|
||||
boost::shared_ptr<StdThread> result = boost::shared_ptr<StdThread>(new StdThread(isDetached(), runnable));
|
||||
runnable->thread(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
Thread::id_t StdThreadFactory::getCurrentThreadId() const {
|
||||
return std::this_thread::get_id();
|
||||
}
|
||||
}
|
||||
}
|
||||
} // apache::thrift::concurrency
|
||||
|
||||
#endif // USE_STD_THREAD
|
61
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/concurrency/StdThreadFactory.h
generated
vendored
Normal file
61
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/concurrency/StdThreadFactory.h
generated
vendored
Normal file
|
@ -0,0 +1,61 @@
|
|||
/*
|
||||
* 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_CONCURRENCY_STDTHREADFACTORY_H_
|
||||
#define _THRIFT_CONCURRENCY_STDTHREADFACTORY_H_ 1
|
||||
|
||||
#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;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
} // apache::thrift::concurrency
|
||||
|
||||
#endif // #ifndef _THRIFT_CONCURRENCY_STDTHREADFACTORY_H_
|
178
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/concurrency/Thread.h
generated
vendored
Normal file
178
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/concurrency/Thread.h
generated
vendored
Normal file
|
@ -0,0 +1,178 @@
|
|||
/*
|
||||
* 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_CONCURRENCY_THREAD_H_
|
||||
#define _THRIFT_CONCURRENCY_THREAD_H_ 1
|
||||
|
||||
#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 that 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. If this thread is joinable, the calling thread blocks
|
||||
* until this thread completes. If the target thread is not joinable, then
|
||||
* nothing happens.
|
||||
*/
|
||||
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 {
|
||||
protected:
|
||||
ThreadFactory(bool detached) : detached_(detached) { }
|
||||
|
||||
public:
|
||||
virtual ~ThreadFactory() { }
|
||||
|
||||
/**
|
||||
* Gets current detached mode
|
||||
*/
|
||||
bool isDetached() const { return detached_; }
|
||||
|
||||
/**
|
||||
* Sets the detached disposition of newly created threads.
|
||||
*/
|
||||
void setDetached(bool detached) { detached_ = detached; }
|
||||
|
||||
/**
|
||||
* Create a new thread.
|
||||
*/
|
||||
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
|
||||
*/
|
||||
virtual Thread::id_t getCurrentThreadId() const = 0;
|
||||
|
||||
/**
|
||||
* For code readability define the unknown/undefined thread id
|
||||
*/
|
||||
static const Thread::id_t unknown_thread_id;
|
||||
|
||||
private:
|
||||
bool detached_;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
} // apache::thrift::concurrency
|
||||
|
||||
#endif // #ifndef _THRIFT_CONCURRENCY_THREAD_H_
|
588
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/concurrency/ThreadManager.cpp
generated
vendored
Normal file
588
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/concurrency/ThreadManager.cpp
generated
vendored
Normal file
|
@ -0,0 +1,588 @@
|
|||
/*
|
||||
* 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 <thrift/concurrency/ThreadManager.h>
|
||||
#include <thrift/concurrency/Exception.h>
|
||||
#include <thrift/concurrency/Monitor.h>
|
||||
#include <thrift/concurrency/Util.h>
|
||||
|
||||
#include <boost/shared_ptr.hpp>
|
||||
|
||||
#include <stdexcept>
|
||||
#include <deque>
|
||||
#include <set>
|
||||
|
||||
#if defined(DEBUG)
|
||||
#include <iostream>
|
||||
#endif // defined(DEBUG)
|
||||
|
||||
namespace apache {
|
||||
namespace thrift {
|
||||
namespace concurrency {
|
||||
|
||||
using boost::shared_ptr;
|
||||
using boost::dynamic_pointer_cast;
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
* There are three different monitors used for signaling different conditions
|
||||
* however they all share the same mutex_.
|
||||
*
|
||||
* @version $Id:$
|
||||
*/
|
||||
class ThreadManager::Impl : public ThreadManager {
|
||||
|
||||
public:
|
||||
Impl()
|
||||
: workerCount_(0),
|
||||
workerMaxCount_(0),
|
||||
idleCount_(0),
|
||||
pendingTaskCountMax_(0),
|
||||
expiredCount_(0),
|
||||
state_(ThreadManager::UNINITIALIZED),
|
||||
monitor_(&mutex_),
|
||||
maxMonitor_(&mutex_),
|
||||
workerMonitor_(&mutex_) {}
|
||||
|
||||
~Impl() { stop(); }
|
||||
|
||||
void start();
|
||||
void stop();
|
||||
|
||||
ThreadManager::STATE state() const { return state_; }
|
||||
|
||||
shared_ptr<ThreadFactory> threadFactory() const {
|
||||
Guard g(mutex_);
|
||||
return threadFactory_;
|
||||
}
|
||||
|
||||
void threadFactory(shared_ptr<ThreadFactory> value) {
|
||||
Guard g(mutex_);
|
||||
if (threadFactory_ && threadFactory_->isDetached() != value->isDetached()) {
|
||||
throw InvalidArgumentException();
|
||||
}
|
||||
threadFactory_ = value;
|
||||
}
|
||||
|
||||
void addWorker(size_t value);
|
||||
|
||||
void removeWorker(size_t value);
|
||||
|
||||
size_t idleWorkerCount() const { return idleCount_; }
|
||||
|
||||
size_t workerCount() const {
|
||||
Guard g(mutex_);
|
||||
return workerCount_;
|
||||
}
|
||||
|
||||
size_t pendingTaskCount() const {
|
||||
Guard g(mutex_);
|
||||
return tasks_.size();
|
||||
}
|
||||
|
||||
size_t totalTaskCount() const {
|
||||
Guard g(mutex_);
|
||||
return tasks_.size() + workerCount_ - idleCount_;
|
||||
}
|
||||
|
||||
size_t pendingTaskCountMax() const {
|
||||
Guard g(mutex_);
|
||||
return pendingTaskCountMax_;
|
||||
}
|
||||
|
||||
size_t expiredTaskCount() {
|
||||
Guard g(mutex_);
|
||||
return expiredCount_;
|
||||
}
|
||||
|
||||
void pendingTaskCountMax(const size_t value) {
|
||||
Guard g(mutex_);
|
||||
pendingTaskCountMax_ = value;
|
||||
}
|
||||
|
||||
void add(shared_ptr<Runnable> value, int64_t timeout, int64_t expiration);
|
||||
|
||||
void remove(shared_ptr<Runnable> task);
|
||||
|
||||
shared_ptr<Runnable> removeNextPending();
|
||||
|
||||
void removeExpiredTasks() {
|
||||
removeExpired(false);
|
||||
}
|
||||
|
||||
void setExpireCallback(ExpireCallback expireCallback);
|
||||
|
||||
private:
|
||||
/**
|
||||
* Remove one or more expired tasks.
|
||||
* \param[in] justOne if true, try to remove just one task and return
|
||||
*/
|
||||
void removeExpired(bool justOne);
|
||||
|
||||
/**
|
||||
* \returns whether it is acceptable to block, depending on the current thread id
|
||||
*/
|
||||
bool canSleep() const;
|
||||
|
||||
/**
|
||||
* Lowers the maximum worker count and blocks until enough worker threads complete
|
||||
* to get to the new maximum worker limit. The caller is responsible for acquiring
|
||||
* a lock on the class mutex_.
|
||||
*/
|
||||
void removeWorkersUnderLock(size_t value);
|
||||
|
||||
size_t workerCount_;
|
||||
size_t workerMaxCount_;
|
||||
size_t idleCount_;
|
||||
size_t pendingTaskCountMax_;
|
||||
size_t expiredCount_;
|
||||
ExpireCallback expireCallback_;
|
||||
|
||||
ThreadManager::STATE state_;
|
||||
shared_ptr<ThreadFactory> threadFactory_;
|
||||
|
||||
friend class ThreadManager::Task;
|
||||
typedef std::deque<shared_ptr<Task> > TaskQueue;
|
||||
TaskQueue tasks_;
|
||||
Mutex mutex_;
|
||||
Monitor monitor_;
|
||||
Monitor maxMonitor_;
|
||||
Monitor workerMonitor_; // used to synchronize changes in worker count
|
||||
|
||||
friend class ThreadManager::Worker;
|
||||
std::set<shared_ptr<Thread> > workers_;
|
||||
std::set<shared_ptr<Thread> > deadWorkers_;
|
||||
std::map<const Thread::id_t, shared_ptr<Thread> > idMap_;
|
||||
};
|
||||
|
||||
class ThreadManager::Task : public Runnable {
|
||||
|
||||
public:
|
||||
enum STATE { WAITING, EXECUTING, TIMEDOUT, COMPLETE };
|
||||
|
||||
Task(shared_ptr<Runnable> runnable, int64_t expiration = 0LL)
|
||||
: runnable_(runnable),
|
||||
state_(WAITING),
|
||||
expireTime_(expiration != 0LL ? Util::currentTime() + expiration : 0LL) {}
|
||||
|
||||
~Task() {}
|
||||
|
||||
void run() {
|
||||
if (state_ == EXECUTING) {
|
||||
runnable_->run();
|
||||
state_ = COMPLETE;
|
||||
}
|
||||
}
|
||||
|
||||
shared_ptr<Runnable> getRunnable() { return runnable_; }
|
||||
|
||||
int64_t getExpireTime() const { return expireTime_; }
|
||||
|
||||
private:
|
||||
shared_ptr<Runnable> runnable_;
|
||||
friend class ThreadManager::Worker;
|
||||
STATE state_;
|
||||
int64_t expireTime_;
|
||||
};
|
||||
|
||||
class ThreadManager::Worker : public Runnable {
|
||||
enum STATE { UNINITIALIZED, STARTING, STARTED, STOPPING, STOPPED };
|
||||
|
||||
public:
|
||||
Worker(ThreadManager::Impl* manager) : manager_(manager), state_(UNINITIALIZED) {}
|
||||
|
||||
~Worker() {}
|
||||
|
||||
private:
|
||||
bool isActive() const {
|
||||
return (manager_->workerCount_ <= manager_->workerMaxCount_)
|
||||
|| (manager_->state_ == JOINING && !manager_->tasks_.empty());
|
||||
}
|
||||
|
||||
public:
|
||||
/**
|
||||
* Worker entry point
|
||||
*
|
||||
* As long as worker thread is running, pull tasks off the task queue and
|
||||
* execute.
|
||||
*/
|
||||
void run() {
|
||||
Guard g(manager_->mutex_);
|
||||
|
||||
/**
|
||||
* This method has three parts; one is to check for and account for
|
||||
* admitting a task which happens under a lock. Then the lock is released
|
||||
* and the task itself is executed. Finally we do some accounting
|
||||
* under lock again when the task completes.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Admitting
|
||||
*/
|
||||
|
||||
/**
|
||||
* Increment worker semaphore and notify manager if worker count reached
|
||||
* desired max
|
||||
*/
|
||||
bool active = manager_->workerCount_ < manager_->workerMaxCount_;
|
||||
if (active) {
|
||||
if (++manager_->workerCount_ == manager_->workerMaxCount_) {
|
||||
manager_->workerMonitor_.notify();
|
||||
}
|
||||
}
|
||||
|
||||
while (active) {
|
||||
/**
|
||||
* While holding manager monitor block for non-empty task queue (Also
|
||||
* check that the thread hasn't been requested to stop). Once the queue
|
||||
* is non-empty, dequeue a task, release monitor, and execute. If the
|
||||
* worker max count has been decremented such that we exceed it, mark
|
||||
* ourself inactive, decrement the worker count and notify the manager
|
||||
* (technically we're notifying the next blocked thread but eventually
|
||||
* the manager will see it.
|
||||
*/
|
||||
active = isActive();
|
||||
|
||||
while (active && manager_->tasks_.empty()) {
|
||||
manager_->idleCount_++;
|
||||
manager_->monitor_.wait();
|
||||
active = isActive();
|
||||
manager_->idleCount_--;
|
||||
}
|
||||
|
||||
shared_ptr<ThreadManager::Task> task;
|
||||
|
||||
if (active) {
|
||||
if (!manager_->tasks_.empty()) {
|
||||
task = manager_->tasks_.front();
|
||||
manager_->tasks_.pop_front();
|
||||
if (task->state_ == ThreadManager::Task::WAITING) {
|
||||
// If the state is changed to anything other than EXECUTING or TIMEDOUT here
|
||||
// then the execution loop needs to be changed below.
|
||||
task->state_ =
|
||||
(task->getExpireTime() && task->getExpireTime() < Util::currentTime()) ?
|
||||
ThreadManager::Task::TIMEDOUT :
|
||||
ThreadManager::Task::EXECUTING;
|
||||
}
|
||||
}
|
||||
|
||||
/* If we have a pending task max and we just dropped below it, wakeup any
|
||||
thread that might be blocked on add. */
|
||||
if (manager_->pendingTaskCountMax_ != 0
|
||||
&& manager_->tasks_.size() <= manager_->pendingTaskCountMax_ - 1) {
|
||||
manager_->maxMonitor_.notify();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Execution - not holding a lock
|
||||
*/
|
||||
if (task) {
|
||||
if (task->state_ == ThreadManager::Task::EXECUTING) {
|
||||
|
||||
// Release the lock so we can run the task without blocking the thread manager
|
||||
manager_->mutex_.unlock();
|
||||
|
||||
try {
|
||||
task->run();
|
||||
} catch (const std::exception& e) {
|
||||
GlobalOutput.printf("[ERROR] task->run() raised an exception: %s", e.what());
|
||||
} catch (...) {
|
||||
GlobalOutput.printf("[ERROR] task->run() raised an unknown exception");
|
||||
}
|
||||
|
||||
// Re-acquire the lock to proceed in the thread manager
|
||||
manager_->mutex_.lock();
|
||||
|
||||
} else if (manager_->expireCallback_) {
|
||||
// The only other state the task could have been in is TIMEDOUT (see above)
|
||||
manager_->expireCallback_(task->getRunnable());
|
||||
manager_->expiredCount_++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Final accounting for the worker thread that is done working
|
||||
*/
|
||||
manager_->deadWorkers_.insert(this->thread());
|
||||
if (--manager_->workerCount_ == manager_->workerMaxCount_) {
|
||||
manager_->workerMonitor_.notify();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
ThreadManager::Impl* manager_;
|
||||
friend class ThreadManager::Impl;
|
||||
STATE state_;
|
||||
};
|
||||
|
||||
void ThreadManager::Impl::addWorker(size_t value) {
|
||||
std::set<shared_ptr<Thread> > newThreads;
|
||||
for (size_t ix = 0; ix < value; ix++) {
|
||||
shared_ptr<ThreadManager::Worker> worker
|
||||
= shared_ptr<ThreadManager::Worker>(new ThreadManager::Worker(this));
|
||||
newThreads.insert(threadFactory_->newThread(worker));
|
||||
}
|
||||
|
||||
Guard g(mutex_);
|
||||
workerMaxCount_ += value;
|
||||
workers_.insert(newThreads.begin(), newThreads.end());
|
||||
|
||||
for (std::set<shared_ptr<Thread> >::iterator ix = newThreads.begin(); ix != newThreads.end();
|
||||
++ix) {
|
||||
shared_ptr<ThreadManager::Worker> worker
|
||||
= dynamic_pointer_cast<ThreadManager::Worker, Runnable>((*ix)->runnable());
|
||||
worker->state_ = ThreadManager::Worker::STARTING;
|
||||
(*ix)->start();
|
||||
idMap_.insert(std::pair<const Thread::id_t, shared_ptr<Thread> >((*ix)->getId(), *ix));
|
||||
}
|
||||
|
||||
while (workerCount_ != workerMaxCount_) {
|
||||
workerMonitor_.wait();
|
||||
}
|
||||
}
|
||||
|
||||
void ThreadManager::Impl::start() {
|
||||
Guard g(mutex_);
|
||||
if (state_ == ThreadManager::STOPPED) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (state_ == ThreadManager::UNINITIALIZED) {
|
||||
if (!threadFactory_) {
|
||||
throw InvalidArgumentException();
|
||||
}
|
||||
state_ = ThreadManager::STARTED;
|
||||
monitor_.notifyAll();
|
||||
}
|
||||
|
||||
while (state_ == STARTING) {
|
||||
monitor_.wait();
|
||||
}
|
||||
}
|
||||
|
||||
void ThreadManager::Impl::stop() {
|
||||
Guard g(mutex_);
|
||||
bool doStop = false;
|
||||
|
||||
if (state_ != ThreadManager::STOPPING && state_ != ThreadManager::JOINING
|
||||
&& state_ != ThreadManager::STOPPED) {
|
||||
doStop = true;
|
||||
state_ = ThreadManager::JOINING;
|
||||
}
|
||||
|
||||
if (doStop) {
|
||||
removeWorkersUnderLock(workerCount_);
|
||||
}
|
||||
|
||||
state_ = ThreadManager::STOPPED;
|
||||
}
|
||||
|
||||
void ThreadManager::Impl::removeWorker(size_t value) {
|
||||
Guard g(mutex_);
|
||||
removeWorkersUnderLock(value);
|
||||
}
|
||||
|
||||
void ThreadManager::Impl::removeWorkersUnderLock(size_t value) {
|
||||
if (value > workerMaxCount_) {
|
||||
throw InvalidArgumentException();
|
||||
}
|
||||
|
||||
workerMaxCount_ -= value;
|
||||
|
||||
if (idleCount_ > value) {
|
||||
// There are more idle workers than we need to remove,
|
||||
// so notify enough of them so they can terminate.
|
||||
for (size_t ix = 0; ix < value; ix++) {
|
||||
monitor_.notify();
|
||||
}
|
||||
} else {
|
||||
// There are as many or less idle workers than we need to remove,
|
||||
// so just notify them all so they can terminate.
|
||||
monitor_.notifyAll();
|
||||
}
|
||||
|
||||
while (workerCount_ != workerMaxCount_) {
|
||||
workerMonitor_.wait();
|
||||
}
|
||||
|
||||
for (std::set<shared_ptr<Thread> >::iterator ix = deadWorkers_.begin();
|
||||
ix != deadWorkers_.end();
|
||||
++ix) {
|
||||
|
||||
// when used with a joinable thread factory, we join the threads as we remove them
|
||||
if (!threadFactory_->isDetached()) {
|
||||
(*ix)->join();
|
||||
}
|
||||
|
||||
idMap_.erase((*ix)->getId());
|
||||
workers_.erase(*ix);
|
||||
}
|
||||
|
||||
deadWorkers_.clear();
|
||||
}
|
||||
|
||||
bool ThreadManager::Impl::canSleep() const {
|
||||
const Thread::id_t id = threadFactory_->getCurrentThreadId();
|
||||
return idMap_.find(id) == idMap_.end();
|
||||
}
|
||||
|
||||
void ThreadManager::Impl::add(shared_ptr<Runnable> value, int64_t timeout, int64_t expiration) {
|
||||
Guard g(mutex_, timeout);
|
||||
|
||||
if (!g) {
|
||||
throw TimedOutException();
|
||||
}
|
||||
|
||||
if (state_ != ThreadManager::STARTED) {
|
||||
throw IllegalStateException(
|
||||
"ThreadManager::Impl::add ThreadManager "
|
||||
"not started");
|
||||
}
|
||||
|
||||
// if we're at a limit, remove an expired task to see if the limit clears
|
||||
if (pendingTaskCountMax_ > 0 && (tasks_.size() >= pendingTaskCountMax_)) {
|
||||
removeExpired(true);
|
||||
}
|
||||
|
||||
if (pendingTaskCountMax_ > 0 && (tasks_.size() >= pendingTaskCountMax_)) {
|
||||
if (canSleep() && timeout >= 0) {
|
||||
while (pendingTaskCountMax_ > 0 && tasks_.size() >= pendingTaskCountMax_) {
|
||||
// This is thread safe because the mutex is shared between monitors.
|
||||
maxMonitor_.wait(timeout);
|
||||
}
|
||||
} else {
|
||||
throw TooManyPendingTasksException();
|
||||
}
|
||||
}
|
||||
|
||||
tasks_.push_back(shared_ptr<ThreadManager::Task>(new ThreadManager::Task(value, expiration)));
|
||||
|
||||
// If idle thread is available notify it, otherwise all worker threads are
|
||||
// running and will get around to this task in time.
|
||||
if (idleCount_ > 0) {
|
||||
monitor_.notify();
|
||||
}
|
||||
}
|
||||
|
||||
void ThreadManager::Impl::remove(shared_ptr<Runnable> task) {
|
||||
Guard g(mutex_);
|
||||
if (state_ != ThreadManager::STARTED) {
|
||||
throw IllegalStateException(
|
||||
"ThreadManager::Impl::remove ThreadManager not "
|
||||
"started");
|
||||
}
|
||||
|
||||
for (TaskQueue::iterator it = tasks_.begin(); it != tasks_.end(); ++it)
|
||||
{
|
||||
if ((*it)->getRunnable() == task)
|
||||
{
|
||||
tasks_.erase(it);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
boost::shared_ptr<Runnable> ThreadManager::Impl::removeNextPending() {
|
||||
Guard g(mutex_);
|
||||
if (state_ != ThreadManager::STARTED) {
|
||||
throw IllegalStateException(
|
||||
"ThreadManager::Impl::removeNextPending "
|
||||
"ThreadManager not started");
|
||||
}
|
||||
|
||||
if (tasks_.empty()) {
|
||||
return boost::shared_ptr<Runnable>();
|
||||
}
|
||||
|
||||
shared_ptr<ThreadManager::Task> task = tasks_.front();
|
||||
tasks_.pop_front();
|
||||
|
||||
return task->getRunnable();
|
||||
}
|
||||
|
||||
void ThreadManager::Impl::removeExpired(bool justOne) {
|
||||
// this is always called under a lock
|
||||
int64_t now = 0LL;
|
||||
|
||||
for (TaskQueue::iterator it = tasks_.begin(); it != tasks_.end(); )
|
||||
{
|
||||
if (now == 0LL) {
|
||||
now = Util::currentTime();
|
||||
}
|
||||
|
||||
if ((*it)->getExpireTime() > 0LL && (*it)->getExpireTime() < now) {
|
||||
if (expireCallback_) {
|
||||
expireCallback_((*it)->getRunnable());
|
||||
}
|
||||
it = tasks_.erase(it);
|
||||
++expiredCount_;
|
||||
if (justOne) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
++it;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ThreadManager::Impl::setExpireCallback(ExpireCallback expireCallback) {
|
||||
Guard g(mutex_);
|
||||
expireCallback_ = expireCallback;
|
||||
}
|
||||
|
||||
class SimpleThreadManager : public ThreadManager::Impl {
|
||||
|
||||
public:
|
||||
SimpleThreadManager(size_t workerCount = 4, size_t pendingTaskCountMax = 0)
|
||||
: workerCount_(workerCount), pendingTaskCountMax_(pendingTaskCountMax) {}
|
||||
|
||||
void start() {
|
||||
ThreadManager::Impl::pendingTaskCountMax(pendingTaskCountMax_);
|
||||
ThreadManager::Impl::start();
|
||||
addWorker(workerCount_);
|
||||
}
|
||||
|
||||
private:
|
||||
const size_t workerCount_;
|
||||
const size_t pendingTaskCountMax_;
|
||||
};
|
||||
|
||||
shared_ptr<ThreadManager> ThreadManager::newThreadManager() {
|
||||
return shared_ptr<ThreadManager>(new ThreadManager::Impl());
|
||||
}
|
||||
|
||||
shared_ptr<ThreadManager> ThreadManager::newSimpleThreadManager(size_t count,
|
||||
size_t pendingTaskCountMax) {
|
||||
return shared_ptr<ThreadManager>(new SimpleThreadManager(count, pendingTaskCountMax));
|
||||
}
|
||||
}
|
||||
}
|
||||
} // apache::thrift::concurrency
|
214
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/concurrency/ThreadManager.h
generated
vendored
Normal file
214
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/concurrency/ThreadManager.h
generated
vendored
Normal file
|
@ -0,0 +1,214 @@
|
|||
/*
|
||||
* 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_CONCURRENCY_THREADMANAGER_H_
|
||||
#define _THRIFT_CONCURRENCY_THREADMANAGER_H_ 1
|
||||
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <thrift/cxxfunctional.h>
|
||||
#include <sys/types.h>
|
||||
#include <thrift/concurrency/Thread.h>
|
||||
|
||||
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 use 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:
|
||||
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 releases 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.
|
||||
*
|
||||
* Worker threads will be joined depending on the threadFactory's detached
|
||||
* disposition.
|
||||
*/
|
||||
virtual void stop() = 0;
|
||||
|
||||
enum STATE { UNINITIALIZED, STARTING, STARTED, JOINING, STOPPING, STOPPED };
|
||||
|
||||
virtual STATE state() const = 0;
|
||||
|
||||
/**
|
||||
* \returns the current thread factory
|
||||
*/
|
||||
virtual boost::shared_ptr<ThreadFactory> threadFactory() const = 0;
|
||||
|
||||
/**
|
||||
* Set the thread factory.
|
||||
* \throws InvalidArgumentException if the new thread factory has a different
|
||||
* detached disposition than the one replacing it
|
||||
*/
|
||||
virtual void threadFactory(boost::shared_ptr<ThreadFactory> value) = 0;
|
||||
|
||||
/**
|
||||
* Adds worker thread(s).
|
||||
*/
|
||||
virtual void addWorker(size_t value = 1) = 0;
|
||||
|
||||
/**
|
||||
* Removes worker thread(s).
|
||||
* Threads are joined if the thread factory detached disposition allows it.
|
||||
* Blocks until the number of worker threads reaches the new limit.
|
||||
* \param[in] value the number to remove
|
||||
* \throws InvalidArgumentException if the value is greater than the number
|
||||
* of workers
|
||||
*/
|
||||
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
|
||||
* since start() was called.
|
||||
*/
|
||||
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
|
||||
|
||||
#endif // #ifndef _THRIFT_CONCURRENCY_THREADMANAGER_H_
|
305
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/concurrency/TimerManager.cpp
generated
vendored
Normal file
305
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/concurrency/TimerManager.cpp
generated
vendored
Normal file
|
@ -0,0 +1,305 @@
|
|||
/*
|
||||
* 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/concurrency/TimerManager.h>
|
||||
#include <thrift/concurrency/Exception.h>
|
||||
#include <thrift/concurrency/Util.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <iostream>
|
||||
#include <set>
|
||||
|
||||
namespace apache {
|
||||
namespace thrift {
|
||||
namespace concurrency {
|
||||
|
||||
using boost::shared_ptr;
|
||||
|
||||
/**
|
||||
* TimerManager class
|
||||
*
|
||||
* @version $Id:$
|
||||
*/
|
||||
class TimerManager::Task : public Runnable {
|
||||
|
||||
public:
|
||||
enum STATE { WAITING, EXECUTING, CANCELLED, COMPLETE };
|
||||
|
||||
Task(shared_ptr<Runnable> runnable) : runnable_(runnable), state_(WAITING) {}
|
||||
|
||||
~Task() {}
|
||||
|
||||
void run() {
|
||||
if (state_ == EXECUTING) {
|
||||
runnable_->run();
|
||||
state_ = COMPLETE;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
shared_ptr<Runnable> runnable_;
|
||||
friend class TimerManager::Dispatcher;
|
||||
STATE state_;
|
||||
};
|
||||
|
||||
class TimerManager::Dispatcher : public Runnable {
|
||||
|
||||
public:
|
||||
Dispatcher(TimerManager* manager) : manager_(manager) {}
|
||||
|
||||
~Dispatcher() {}
|
||||
|
||||
/**
|
||||
* Dispatcher entry point
|
||||
*
|
||||
* As long as dispatcher thread is running, pull tasks off the task taskMap_
|
||||
* and execute.
|
||||
*/
|
||||
void run() {
|
||||
{
|
||||
Synchronized s(manager_->monitor_);
|
||||
if (manager_->state_ == TimerManager::STARTING) {
|
||||
manager_->state_ = TimerManager::STARTED;
|
||||
manager_->monitor_.notifyAll();
|
||||
}
|
||||
}
|
||||
|
||||
do {
|
||||
std::set<shared_ptr<TimerManager::Task> > expiredTasks;
|
||||
{
|
||||
Synchronized s(manager_->monitor_);
|
||||
task_iterator expiredTaskEnd;
|
||||
int64_t now = Util::currentTime();
|
||||
while (manager_->state_ == TimerManager::STARTED
|
||||
&& (expiredTaskEnd = manager_->taskMap_.upper_bound(now))
|
||||
== manager_->taskMap_.begin()) {
|
||||
int64_t timeout = 0LL;
|
||||
if (!manager_->taskMap_.empty()) {
|
||||
timeout = manager_->taskMap_.begin()->first - now;
|
||||
}
|
||||
assert((timeout != 0 && manager_->taskCount_ > 0)
|
||||
|| (timeout == 0 && manager_->taskCount_ == 0));
|
||||
try {
|
||||
manager_->monitor_.wait(timeout);
|
||||
} catch (TimedOutException&) {
|
||||
}
|
||||
now = Util::currentTime();
|
||||
}
|
||||
|
||||
if (manager_->state_ == TimerManager::STARTED) {
|
||||
for (task_iterator ix = manager_->taskMap_.begin(); ix != expiredTaskEnd; ix++) {
|
||||
shared_ptr<TimerManager::Task> task = ix->second;
|
||||
expiredTasks.insert(task);
|
||||
if (task->state_ == TimerManager::Task::WAITING) {
|
||||
task->state_ = TimerManager::Task::EXECUTING;
|
||||
}
|
||||
manager_->taskCount_--;
|
||||
}
|
||||
manager_->taskMap_.erase(manager_->taskMap_.begin(), expiredTaskEnd);
|
||||
}
|
||||
}
|
||||
|
||||
for (std::set<shared_ptr<Task> >::iterator ix = expiredTasks.begin();
|
||||
ix != expiredTasks.end();
|
||||
++ix) {
|
||||
(*ix)->run();
|
||||
}
|
||||
|
||||
} while (manager_->state_ == TimerManager::STARTED);
|
||||
|
||||
{
|
||||
Synchronized s(manager_->monitor_);
|
||||
if (manager_->state_ == TimerManager::STOPPING) {
|
||||
manager_->state_ = TimerManager::STOPPED;
|
||||
manager_->monitor_.notify();
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
private:
|
||||
TimerManager* manager_;
|
||||
friend class TimerManager;
|
||||
};
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4355) // 'this' used in base member initializer list
|
||||
#endif
|
||||
|
||||
TimerManager::TimerManager()
|
||||
: taskCount_(0),
|
||||
state_(TimerManager::UNINITIALIZED),
|
||||
dispatcher_(shared_ptr<Dispatcher>(new Dispatcher(this))) {
|
||||
}
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
TimerManager::~TimerManager() {
|
||||
|
||||
// If we haven't been explicitly stopped, do so now. We don't need to grab
|
||||
// the monitor here, since stop already takes care of reentrancy.
|
||||
|
||||
if (state_ != STOPPED) {
|
||||
try {
|
||||
stop();
|
||||
} catch (...) {
|
||||
// We're really hosed.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TimerManager::start() {
|
||||
bool doStart = false;
|
||||
{
|
||||
Synchronized s(monitor_);
|
||||
if (!threadFactory_) {
|
||||
throw InvalidArgumentException();
|
||||
}
|
||||
if (state_ == TimerManager::UNINITIALIZED) {
|
||||
state_ = TimerManager::STARTING;
|
||||
doStart = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (doStart) {
|
||||
dispatcherThread_ = threadFactory_->newThread(dispatcher_);
|
||||
dispatcherThread_->start();
|
||||
}
|
||||
|
||||
{
|
||||
Synchronized s(monitor_);
|
||||
while (state_ == TimerManager::STARTING) {
|
||||
monitor_.wait();
|
||||
}
|
||||
assert(state_ != TimerManager::STARTING);
|
||||
}
|
||||
}
|
||||
|
||||
void TimerManager::stop() {
|
||||
bool doStop = false;
|
||||
{
|
||||
Synchronized s(monitor_);
|
||||
if (state_ == TimerManager::UNINITIALIZED) {
|
||||
state_ = TimerManager::STOPPED;
|
||||
} else if (state_ != STOPPING && state_ != STOPPED) {
|
||||
doStop = true;
|
||||
state_ = STOPPING;
|
||||
monitor_.notifyAll();
|
||||
}
|
||||
while (state_ != STOPPED) {
|
||||
monitor_.wait();
|
||||
}
|
||||
}
|
||||
|
||||
if (doStop) {
|
||||
// Clean up any outstanding tasks
|
||||
taskMap_.clear();
|
||||
|
||||
// Remove dispatcher's reference to us.
|
||||
dispatcher_->manager_ = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
shared_ptr<const ThreadFactory> TimerManager::threadFactory() const {
|
||||
Synchronized s(monitor_);
|
||||
return threadFactory_;
|
||||
}
|
||||
|
||||
void TimerManager::threadFactory(shared_ptr<const ThreadFactory> value) {
|
||||
Synchronized s(monitor_);
|
||||
threadFactory_ = value;
|
||||
}
|
||||
|
||||
size_t TimerManager::taskCount() const {
|
||||
return taskCount_;
|
||||
}
|
||||
|
||||
void TimerManager::add(shared_ptr<Runnable> task, int64_t timeout) {
|
||||
int64_t now = Util::currentTime();
|
||||
timeout += now;
|
||||
|
||||
{
|
||||
Synchronized s(monitor_);
|
||||
if (state_ != TimerManager::STARTED) {
|
||||
throw IllegalStateException();
|
||||
}
|
||||
|
||||
// If the task map is empty, we will kick the dispatcher for sure. Otherwise, we kick him
|
||||
// if the expiration time is shorter than the current value. Need to test before we insert,
|
||||
// because the new task might insert at the front.
|
||||
bool notifyRequired = (taskCount_ == 0) ? true : timeout < taskMap_.begin()->first;
|
||||
|
||||
taskCount_++;
|
||||
taskMap_.insert(
|
||||
std::pair<int64_t, shared_ptr<Task> >(timeout, shared_ptr<Task>(new Task(task))));
|
||||
|
||||
// If the task map was empty, or if we have an expiration that is earlier
|
||||
// than any previously seen, kick the dispatcher so it can update its
|
||||
// timeout
|
||||
if (notifyRequired) {
|
||||
monitor_.notify();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TimerManager::add(shared_ptr<Runnable> task, const struct THRIFT_TIMESPEC& value) {
|
||||
|
||||
int64_t expiration;
|
||||
Util::toMilliseconds(expiration, value);
|
||||
|
||||
int64_t now = Util::currentTime();
|
||||
|
||||
if (expiration < now) {
|
||||
throw InvalidArgumentException();
|
||||
}
|
||||
|
||||
add(task, expiration - now);
|
||||
}
|
||||
|
||||
void TimerManager::add(shared_ptr<Runnable> task, const struct timeval& value) {
|
||||
|
||||
int64_t expiration;
|
||||
Util::toMilliseconds(expiration, value);
|
||||
|
||||
int64_t now = Util::currentTime();
|
||||
|
||||
if (expiration < now) {
|
||||
throw InvalidArgumentException();
|
||||
}
|
||||
|
||||
add(task, expiration - now);
|
||||
}
|
||||
|
||||
void TimerManager::remove(shared_ptr<Runnable> task) {
|
||||
(void)task;
|
||||
Synchronized s(monitor_);
|
||||
if (state_ != TimerManager::STARTED) {
|
||||
throw IllegalStateException();
|
||||
}
|
||||
}
|
||||
|
||||
TimerManager::STATE TimerManager::state() const {
|
||||
return state_;
|
||||
}
|
||||
}
|
||||
}
|
||||
} // apache::thrift::concurrency
|
126
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/concurrency/TimerManager.h
generated
vendored
Normal file
126
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/concurrency/TimerManager.h
generated
vendored
Normal file
|
@ -0,0 +1,126 @@
|
|||
/*
|
||||
* 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_CONCURRENCY_TIMERMANAGER_H_
|
||||
#define _THRIFT_CONCURRENCY_TIMERMANAGER_H_ 1
|
||||
|
||||
#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
|
||||
|
||||
#endif // #ifndef _THRIFT_CONCURRENCY_TIMERMANAGER_H_
|
44
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/concurrency/Util.cpp
generated
vendored
Normal file
44
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/concurrency/Util.cpp
generated
vendored
Normal file
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* 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 <thrift/Thrift.h>
|
||||
#include <thrift/concurrency/Util.h>
|
||||
|
||||
#if defined(HAVE_SYS_TIME_H)
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
|
||||
namespace apache {
|
||||
namespace thrift {
|
||||
namespace concurrency {
|
||||
|
||||
int64_t Util::currentTimeTicks(int64_t ticksPerSec) {
|
||||
int64_t result;
|
||||
struct timeval now;
|
||||
int ret = THRIFT_GETTIMEOFDAY(&now, NULL);
|
||||
assert(ret == 0);
|
||||
THRIFT_UNUSED_VARIABLE(ret); // squelching "unused variable" warning
|
||||
toTicks(result, now, ticksPerSec);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
} // apache::thrift::concurrency
|
151
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/concurrency/Util.h
generated
vendored
Normal file
151
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/concurrency/Util.h
generated
vendored
Normal file
|
@ -0,0 +1,151 @@
|
|||
/*
|
||||
* 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_CONCURRENCY_UTIL_H_
|
||||
#define _THRIFT_CONCURRENCY_UTIL_H_ 1
|
||||
|
||||
#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, (unsigned long)value.tv_sec, (unsigned long)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
|
||||
|
||||
#endif // #ifndef _THRIFT_CONCURRENCY_UTIL_H_
|
132
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/cxxfunctional.h
generated
vendored
Normal file
132
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/cxxfunctional.h
generated
vendored
Normal file
|
@ -0,0 +1,132 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
#ifndef _THRIFT_CXXFUNCTIONAL_H_
|
||||
#define _THRIFT_CXXFUNCTIONAL_H_ 1
|
||||
|
||||
// clang-format off
|
||||
|
||||
/**
|
||||
* Loads <functional> from the 'right' location, depending
|
||||
* on compiler and whether or not it's using C++03 with TR1
|
||||
* or C++11.
|
||||
*/
|
||||
|
||||
/*
|
||||
* MSVC 10 and 11 have the <functional> stuff at <functional>.
|
||||
* In MSVC 10 all of the implementations live in std::tr1.
|
||||
* In MSVC 11 all of the implementations live in std, with aliases
|
||||
* in std::tr1 to point to the ones in std.
|
||||
*/
|
||||
#if defined(_WIN32) && !defined(__MINGW32__)
|
||||
#define _THRIFT_USING_MICROSOFT_STDLIB 1
|
||||
#endif
|
||||
|
||||
#ifdef __clang__
|
||||
/* Clang has two options, depending on standard library:
|
||||
* - no -stdlib or -stdlib=libstdc++ set; uses GNU libstdc++.
|
||||
* <tr1/functional>
|
||||
* - -stdlib=libc++; uses LLVM libc++.
|
||||
* <functional>, no 'std::tr1'.
|
||||
*
|
||||
* The compiler itself doesn't define anything differently
|
||||
* depending on the value of -stdlib, but the library headers
|
||||
* will set different preprocessor options. In order to check,
|
||||
* though, we have to pull in some library header.
|
||||
*/
|
||||
#include <utility>
|
||||
|
||||
/* With LLVM libc++, utility pulls in __config, which sets
|
||||
_LIBCPP_VERSION. */
|
||||
#if defined(_LIBCPP_VERSION)
|
||||
#define _THRIFT_USING_CLANG_LIBCXX 1
|
||||
|
||||
/* With GNU libstdc++, utility pulls in bits/c++config.h,
|
||||
which sets __GLIBCXX__. */
|
||||
#elif defined(__GLIBCXX__)
|
||||
#define _THRIFT_USING_GNU_LIBSTDCXX 1
|
||||
|
||||
/* No idea. */
|
||||
#else
|
||||
#error Unable to detect which C++ standard library is in use.
|
||||
#endif
|
||||
#elif __GNUC__
|
||||
#define _THRIFT_USING_GNU_LIBSTDCXX 1
|
||||
#endif
|
||||
|
||||
#if _THRIFT_USING_MICROSOFT_STDLIB
|
||||
#include <functional>
|
||||
|
||||
namespace apache { namespace thrift { namespace stdcxx {
|
||||
using ::std::tr1::function;
|
||||
using ::std::tr1::bind;
|
||||
|
||||
namespace placeholders {
|
||||
using ::std::tr1::placeholders::_1;
|
||||
using ::std::tr1::placeholders::_2;
|
||||
using ::std::tr1::placeholders::_3;
|
||||
using ::std::tr1::placeholders::_4;
|
||||
using ::std::tr1::placeholders::_5;
|
||||
using ::std::tr1::placeholders::_6;
|
||||
} // apache::thrift::stdcxx::placeholders
|
||||
}}} // apache::thrift::stdcxx
|
||||
|
||||
#elif _THRIFT_USING_CLANG_LIBCXX
|
||||
#include <functional>
|
||||
|
||||
namespace apache { namespace thrift { namespace stdcxx {
|
||||
using ::std::function;
|
||||
using ::std::bind;
|
||||
|
||||
namespace placeholders {
|
||||
using ::std::placeholders::_1;
|
||||
using ::std::placeholders::_2;
|
||||
using ::std::placeholders::_3;
|
||||
using ::std::placeholders::_4;
|
||||
using ::std::placeholders::_5;
|
||||
using ::std::placeholders::_6;
|
||||
} // apache::thrift::stdcxx::placeholders
|
||||
}}} // apache::thrift::stdcxx
|
||||
|
||||
#elif _THRIFT_USING_GNU_LIBSTDCXX
|
||||
#ifdef USE_BOOST_THREAD
|
||||
#include <boost/tr1/functional.hpp>
|
||||
#else
|
||||
#include <tr1/functional>
|
||||
#endif
|
||||
|
||||
namespace apache { namespace thrift { namespace stdcxx {
|
||||
using ::std::tr1::function;
|
||||
using ::std::tr1::bind;
|
||||
|
||||
namespace placeholders {
|
||||
using ::std::tr1::placeholders::_1;
|
||||
using ::std::tr1::placeholders::_2;
|
||||
using ::std::tr1::placeholders::_3;
|
||||
using ::std::tr1::placeholders::_4;
|
||||
using ::std::tr1::placeholders::_5;
|
||||
using ::std::tr1::placeholders::_6;
|
||||
} // apache::thrift::stdcxx::placeholders
|
||||
}}} // apache::thrift::stdcxx
|
||||
#endif
|
||||
|
||||
// Alias for thrift c++ compatibility namespace
|
||||
namespace tcxx = apache::thrift::stdcxx;
|
||||
|
||||
#endif // #ifndef _THRIFT_CXXFUNCTIONAL_H_
|
132
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/processor/PeekProcessor.cpp
generated
vendored
Normal file
132
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/processor/PeekProcessor.cpp
generated
vendored
Normal file
|
@ -0,0 +1,132 @@
|
|||
/*
|
||||
* 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/processor/PeekProcessor.h>
|
||||
|
||||
using namespace apache::thrift::transport;
|
||||
using namespace apache::thrift::protocol;
|
||||
using namespace apache::thrift;
|
||||
|
||||
namespace apache {
|
||||
namespace thrift {
|
||||
namespace processor {
|
||||
|
||||
PeekProcessor::PeekProcessor() {
|
||||
memoryBuffer_.reset(new TMemoryBuffer());
|
||||
targetTransport_ = memoryBuffer_;
|
||||
}
|
||||
PeekProcessor::~PeekProcessor() {
|
||||
}
|
||||
|
||||
void PeekProcessor::initialize(boost::shared_ptr<TProcessor> actualProcessor,
|
||||
boost::shared_ptr<TProtocolFactory> protocolFactory,
|
||||
boost::shared_ptr<TPipedTransportFactory> transportFactory) {
|
||||
actualProcessor_ = actualProcessor;
|
||||
pipedProtocol_ = protocolFactory->getProtocol(targetTransport_);
|
||||
transportFactory_ = transportFactory;
|
||||
transportFactory_->initializeTargetTransport(targetTransport_);
|
||||
}
|
||||
|
||||
boost::shared_ptr<TTransport> PeekProcessor::getPipedTransport(boost::shared_ptr<TTransport> in) {
|
||||
return transportFactory_->getTransport(in);
|
||||
}
|
||||
|
||||
void PeekProcessor::setTargetTransport(boost::shared_ptr<TTransport> targetTransport) {
|
||||
targetTransport_ = targetTransport;
|
||||
if (boost::dynamic_pointer_cast<TMemoryBuffer>(targetTransport_)) {
|
||||
memoryBuffer_ = boost::dynamic_pointer_cast<TMemoryBuffer>(targetTransport);
|
||||
} else if (boost::dynamic_pointer_cast<TPipedTransport>(targetTransport_)) {
|
||||
memoryBuffer_ = boost::dynamic_pointer_cast<TMemoryBuffer>(
|
||||
boost::dynamic_pointer_cast<TPipedTransport>(targetTransport_)->getTargetTransport());
|
||||
}
|
||||
|
||||
if (!memoryBuffer_) {
|
||||
throw TException(
|
||||
"Target transport must be a TMemoryBuffer or a TPipedTransport with TMemoryBuffer");
|
||||
}
|
||||
}
|
||||
|
||||
bool PeekProcessor::process(boost::shared_ptr<TProtocol> in,
|
||||
boost::shared_ptr<TProtocol> out,
|
||||
void* connectionContext) {
|
||||
|
||||
std::string fname;
|
||||
TMessageType mtype;
|
||||
int32_t seqid;
|
||||
in->readMessageBegin(fname, mtype, seqid);
|
||||
|
||||
if (mtype != T_CALL && mtype != T_ONEWAY) {
|
||||
throw TException("Unexpected message type");
|
||||
}
|
||||
|
||||
// Peek at the name
|
||||
peekName(fname);
|
||||
|
||||
TType ftype;
|
||||
int16_t fid;
|
||||
while (true) {
|
||||
in->readFieldBegin(fname, ftype, fid);
|
||||
if (ftype == T_STOP) {
|
||||
break;
|
||||
}
|
||||
|
||||
// Peek at the variable
|
||||
peek(in, ftype, fid);
|
||||
in->readFieldEnd();
|
||||
}
|
||||
in->readMessageEnd();
|
||||
in->getTransport()->readEnd();
|
||||
|
||||
//
|
||||
// All the data is now in memoryBuffer_ and ready to be processed
|
||||
//
|
||||
|
||||
// Let's first take a peek at the full data in memory
|
||||
uint8_t* buffer;
|
||||
uint32_t size;
|
||||
memoryBuffer_->getBuffer(&buffer, &size);
|
||||
peekBuffer(buffer, size);
|
||||
|
||||
// Done peeking at variables
|
||||
peekEnd();
|
||||
|
||||
bool ret = actualProcessor_->process(pipedProtocol_, out, connectionContext);
|
||||
memoryBuffer_->resetBuffer();
|
||||
return ret;
|
||||
}
|
||||
|
||||
void PeekProcessor::peekName(const std::string& fname) {
|
||||
(void)fname;
|
||||
}
|
||||
|
||||
void PeekProcessor::peekBuffer(uint8_t* buffer, uint32_t size) {
|
||||
(void)buffer;
|
||||
(void)size;
|
||||
}
|
||||
|
||||
void PeekProcessor::peek(boost::shared_ptr<TProtocol> in, TType ftype, int16_t fid) {
|
||||
(void)fid;
|
||||
in->skip(ftype);
|
||||
}
|
||||
|
||||
void PeekProcessor::peekEnd() {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
83
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/processor/PeekProcessor.h
generated
vendored
Normal file
83
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/processor/PeekProcessor.h
generated
vendored
Normal file
|
@ -0,0 +1,83 @@
|
|||
/*
|
||||
* 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 PEEKPROCESSOR_H
|
||||
#define PEEKPROCESSOR_H
|
||||
|
||||
#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
|
||||
|
||||
#endif
|
242
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/processor/StatsProcessor.h
generated
vendored
Normal file
242
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/processor/StatsProcessor.h
generated
vendored
Normal file
|
@ -0,0 +1,242 @@
|
|||
/*
|
||||
* 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 STATSPROCESSOR_H
|
||||
#define STATSPROCESSOR_H
|
||||
|
||||
#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 && mtype != apache::thrift::protocol::T_ONEWAY) {
|
||||
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
|
||||
|
||||
#endif
|
201
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/processor/TMultiplexedProcessor.h
generated
vendored
Normal file
201
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/processor/TMultiplexedProcessor.h
generated
vendored
Normal file
|
@ -0,0 +1,201 @@
|
|||
/*
|
||||
* 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_TMULTIPLEXEDPROCESSOR_H_
|
||||
#define THRIFT_TMULTIPLEXEDPROCESSOR_H_ 1
|
||||
|
||||
#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, usually 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;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif // THRIFT_TMULTIPLEXEDPROCESSOR_H_
|
317
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/protocol/TBase64Utils.cpp
generated
vendored
Normal file
317
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/protocol/TBase64Utils.cpp
generated
vendored
Normal file
|
@ -0,0 +1,317 @@
|
|||
/*
|
||||
* 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/protocol/TBase64Utils.h>
|
||||
|
||||
#include <boost/static_assert.hpp>
|
||||
|
||||
using std::string;
|
||||
|
||||
namespace apache {
|
||||
namespace thrift {
|
||||
namespace protocol {
|
||||
|
||||
static const uint8_t* kBase64EncodeTable
|
||||
= (const uint8_t*)"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||
|
||||
void base64_encode(const uint8_t* in, uint32_t len, uint8_t* buf) {
|
||||
buf[0] = kBase64EncodeTable[(in[0] >> 2) & 0x3f];
|
||||
if (len == 3) {
|
||||
buf[1] = kBase64EncodeTable[((in[0] << 4) & 0x30) | ((in[1] >> 4) & 0x0f)];
|
||||
buf[2] = kBase64EncodeTable[((in[1] << 2) & 0x3c) | ((in[2] >> 6) & 0x03)];
|
||||
buf[3] = kBase64EncodeTable[in[2] & 0x3f];
|
||||
} else if (len == 2) {
|
||||
buf[1] = kBase64EncodeTable[((in[0] << 4) & 0x30) | ((in[1] >> 4) & 0x0f)];
|
||||
buf[2] = kBase64EncodeTable[(in[1] << 2) & 0x3c];
|
||||
} else { // len == 1
|
||||
buf[1] = kBase64EncodeTable[(in[0] << 4) & 0x30];
|
||||
}
|
||||
}
|
||||
|
||||
static const uint8_t kBase64DecodeTable[256] = {
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0x3e,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0x3f,
|
||||
0x34,
|
||||
0x35,
|
||||
0x36,
|
||||
0x37,
|
||||
0x38,
|
||||
0x39,
|
||||
0x3a,
|
||||
0x3b,
|
||||
0x3c,
|
||||
0x3d,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0x00,
|
||||
0x01,
|
||||
0x02,
|
||||
0x03,
|
||||
0x04,
|
||||
0x05,
|
||||
0x06,
|
||||
0x07,
|
||||
0x08,
|
||||
0x09,
|
||||
0x0a,
|
||||
0x0b,
|
||||
0x0c,
|
||||
0x0d,
|
||||
0x0e,
|
||||
0x0f,
|
||||
0x10,
|
||||
0x11,
|
||||
0x12,
|
||||
0x13,
|
||||
0x14,
|
||||
0x15,
|
||||
0x16,
|
||||
0x17,
|
||||
0x18,
|
||||
0x19,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0x1a,
|
||||
0x1b,
|
||||
0x1c,
|
||||
0x1d,
|
||||
0x1e,
|
||||
0x1f,
|
||||
0x20,
|
||||
0x21,
|
||||
0x22,
|
||||
0x23,
|
||||
0x24,
|
||||
0x25,
|
||||
0x26,
|
||||
0x27,
|
||||
0x28,
|
||||
0x29,
|
||||
0x2a,
|
||||
0x2b,
|
||||
0x2c,
|
||||
0x2d,
|
||||
0x2e,
|
||||
0x2f,
|
||||
0x30,
|
||||
0x31,
|
||||
0x32,
|
||||
0x33,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
};
|
||||
|
||||
void base64_decode(uint8_t* buf, uint32_t len) {
|
||||
buf[0] = (kBase64DecodeTable[buf[0]] << 2) | (kBase64DecodeTable[buf[1]] >> 4);
|
||||
if (len > 2) {
|
||||
buf[1] = ((kBase64DecodeTable[buf[1]] << 4) & 0xf0) | (kBase64DecodeTable[buf[2]] >> 2);
|
||||
if (len > 3) {
|
||||
buf[2] = ((kBase64DecodeTable[buf[2]] << 6) & 0xc0) | (kBase64DecodeTable[buf[3]]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} // apache::thrift::protocol
|
45
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/protocol/TBase64Utils.h
generated
vendored
Normal file
45
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/protocol/TBase64Utils.h
generated
vendored
Normal file
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* 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_TBASE64UTILS_H_
|
||||
#define _THRIFT_PROTOCOL_TBASE64UTILS_H_
|
||||
|
||||
#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
|
||||
|
||||
#endif // #define _THRIFT_PROTOCOL_TBASE64UTILS_H_
|
250
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/protocol/TBinaryProtocol.h
generated
vendored
Normal file
250
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/protocol/TBinaryProtocol.h
generated
vendored
Normal file
|
@ -0,0 +1,250 @@
|
|||
/*
|
||||
* 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_H_
|
||||
#define _THRIFT_PROTOCOL_TBINARYPROTOCOL_H_ 1
|
||||
|
||||
#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 ByteOrder_ = TNetworkBigEndian>
|
||||
class TBinaryProtocolT : public TVirtualProtocol<TBinaryProtocolT<Transport_, ByteOrder_> > {
|
||||
public:
|
||||
static const int32_t VERSION_MASK = ((int32_t)0xffff0000);
|
||||
static const int32_t VERSION_1 = ((int32_t)0x80010000);
|
||||
// VERSION_2 (0x80020000) was taken by TDenseProtocol (which has since been removed)
|
||||
|
||||
TBinaryProtocolT(boost::shared_ptr<Transport_> trans)
|
||||
: TVirtualProtocol<TBinaryProtocolT<Transport_, ByteOrder_> >(trans),
|
||||
trans_(trans.get()),
|
||||
string_limit_(0),
|
||||
container_limit_(0),
|
||||
strict_read_(false),
|
||||
strict_write_(true) {}
|
||||
|
||||
TBinaryProtocolT(boost::shared_ptr<Transport_> trans,
|
||||
int32_t string_limit,
|
||||
int32_t container_limit,
|
||||
bool strict_read,
|
||||
bool strict_write)
|
||||
: TVirtualProtocol<TBinaryProtocolT<Transport_, ByteOrder_> >(trans),
|
||||
trans_(trans.get()),
|
||||
string_limit_(string_limit),
|
||||
container_limit_(container_limit),
|
||||
strict_read_(strict_read),
|
||||
strict_write_(strict_write) {}
|
||||
|
||||
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_, ByteOrder_> >::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_;
|
||||
};
|
||||
|
||||
typedef TBinaryProtocolT<TTransport> TBinaryProtocol;
|
||||
typedef TBinaryProtocolT<TTransport, TNetworkLittleEndian> TLEBinaryProtocol;
|
||||
|
||||
/**
|
||||
* Constructs binary protocol handlers
|
||||
*/
|
||||
template <class Transport_, class ByteOrder_ = TNetworkBigEndian>
|
||||
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_, ByteOrder_>(specific_trans,
|
||||
string_limit_,
|
||||
container_limit_,
|
||||
strict_read_,
|
||||
strict_write_);
|
||||
} else {
|
||||
prot = new TBinaryProtocolT<TTransport, ByteOrder_>(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;
|
||||
typedef TBinaryProtocolFactoryT<TTransport, TNetworkLittleEndian> TLEBinaryProtocolFactory;
|
||||
}
|
||||
}
|
||||
} // apache::thrift::protocol
|
||||
|
||||
#include <thrift/protocol/TBinaryProtocol.tcc>
|
||||
|
||||
#endif // #ifndef _THRIFT_PROTOCOL_TBINARYPROTOCOL_H_
|
454
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/protocol/TBinaryProtocol.tcc
generated
vendored
Normal file
454
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/protocol/TBinaryProtocol.tcc
generated
vendored
Normal file
|
@ -0,0 +1,454 @@
|
|||
/*
|
||||
* 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_, class ByteOrder_>
|
||||
uint32_t TBinaryProtocolT<Transport_, ByteOrder_>::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_, class ByteOrder_>
|
||||
uint32_t TBinaryProtocolT<Transport_, ByteOrder_>::writeMessageEnd() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
template <class Transport_, class ByteOrder_>
|
||||
uint32_t TBinaryProtocolT<Transport_, ByteOrder_>::writeStructBegin(const char* name) {
|
||||
(void)name;
|
||||
return 0;
|
||||
}
|
||||
|
||||
template <class Transport_, class ByteOrder_>
|
||||
uint32_t TBinaryProtocolT<Transport_, ByteOrder_>::writeStructEnd() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
template <class Transport_, class ByteOrder_>
|
||||
uint32_t TBinaryProtocolT<Transport_, ByteOrder_>::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_, class ByteOrder_>
|
||||
uint32_t TBinaryProtocolT<Transport_, ByteOrder_>::writeFieldEnd() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
template <class Transport_, class ByteOrder_>
|
||||
uint32_t TBinaryProtocolT<Transport_, ByteOrder_>::writeFieldStop() {
|
||||
return writeByte((int8_t)T_STOP);
|
||||
}
|
||||
|
||||
template <class Transport_, class ByteOrder_>
|
||||
uint32_t TBinaryProtocolT<Transport_, ByteOrder_>::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_, class ByteOrder_>
|
||||
uint32_t TBinaryProtocolT<Transport_, ByteOrder_>::writeMapEnd() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
template <class Transport_, class ByteOrder_>
|
||||
uint32_t TBinaryProtocolT<Transport_, ByteOrder_>::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_, class ByteOrder_>
|
||||
uint32_t TBinaryProtocolT<Transport_, ByteOrder_>::writeListEnd() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
template <class Transport_, class ByteOrder_>
|
||||
uint32_t TBinaryProtocolT<Transport_, ByteOrder_>::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_, class ByteOrder_>
|
||||
uint32_t TBinaryProtocolT<Transport_, ByteOrder_>::writeSetEnd() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
template <class Transport_, class ByteOrder_>
|
||||
uint32_t TBinaryProtocolT<Transport_, ByteOrder_>::writeBool(const bool value) {
|
||||
uint8_t tmp = value ? 1 : 0;
|
||||
this->trans_->write(&tmp, 1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
template <class Transport_, class ByteOrder_>
|
||||
uint32_t TBinaryProtocolT<Transport_, ByteOrder_>::writeByte(const int8_t byte) {
|
||||
this->trans_->write((uint8_t*)&byte, 1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
template <class Transport_, class ByteOrder_>
|
||||
uint32_t TBinaryProtocolT<Transport_, ByteOrder_>::writeI16(const int16_t i16) {
|
||||
int16_t net = (int16_t)ByteOrder_::toWire16(i16);
|
||||
this->trans_->write((uint8_t*)&net, 2);
|
||||
return 2;
|
||||
}
|
||||
|
||||
template <class Transport_, class ByteOrder_>
|
||||
uint32_t TBinaryProtocolT<Transport_, ByteOrder_>::writeI32(const int32_t i32) {
|
||||
int32_t net = (int32_t)ByteOrder_::toWire32(i32);
|
||||
this->trans_->write((uint8_t*)&net, 4);
|
||||
return 4;
|
||||
}
|
||||
|
||||
template <class Transport_, class ByteOrder_>
|
||||
uint32_t TBinaryProtocolT<Transport_, ByteOrder_>::writeI64(const int64_t i64) {
|
||||
int64_t net = (int64_t)ByteOrder_::toWire64(i64);
|
||||
this->trans_->write((uint8_t*)&net, 8);
|
||||
return 8;
|
||||
}
|
||||
|
||||
template <class Transport_, class ByteOrder_>
|
||||
uint32_t TBinaryProtocolT<Transport_, ByteOrder_>::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 = ByteOrder_::toWire64(bits);
|
||||
this->trans_->write((uint8_t*)&bits, 8);
|
||||
return 8;
|
||||
}
|
||||
|
||||
template <class Transport_, class ByteOrder_>
|
||||
template <typename StrType>
|
||||
uint32_t TBinaryProtocolT<Transport_, ByteOrder_>::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_, class ByteOrder_>
|
||||
uint32_t TBinaryProtocolT<Transport_, ByteOrder_>::writeBinary(const std::string& str) {
|
||||
return TBinaryProtocolT<Transport_, ByteOrder_>::writeString(str);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reading functions
|
||||
*/
|
||||
|
||||
template <class Transport_, class ByteOrder_>
|
||||
uint32_t TBinaryProtocolT<Transport_, ByteOrder_>::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_, class ByteOrder_>
|
||||
uint32_t TBinaryProtocolT<Transport_, ByteOrder_>::readMessageEnd() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
template <class Transport_, class ByteOrder_>
|
||||
uint32_t TBinaryProtocolT<Transport_, ByteOrder_>::readStructBegin(std::string& name) {
|
||||
name = "";
|
||||
return 0;
|
||||
}
|
||||
|
||||
template <class Transport_, class ByteOrder_>
|
||||
uint32_t TBinaryProtocolT<Transport_, ByteOrder_>::readStructEnd() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
template <class Transport_, class ByteOrder_>
|
||||
uint32_t TBinaryProtocolT<Transport_, ByteOrder_>::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_, class ByteOrder_>
|
||||
uint32_t TBinaryProtocolT<Transport_, ByteOrder_>::readFieldEnd() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
template <class Transport_, class ByteOrder_>
|
||||
uint32_t TBinaryProtocolT<Transport_, ByteOrder_>::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_, class ByteOrder_>
|
||||
uint32_t TBinaryProtocolT<Transport_, ByteOrder_>::readMapEnd() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
template <class Transport_, class ByteOrder_>
|
||||
uint32_t TBinaryProtocolT<Transport_, ByteOrder_>::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_, class ByteOrder_>
|
||||
uint32_t TBinaryProtocolT<Transport_, ByteOrder_>::readListEnd() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
template <class Transport_, class ByteOrder_>
|
||||
uint32_t TBinaryProtocolT<Transport_, ByteOrder_>::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_, class ByteOrder_>
|
||||
uint32_t TBinaryProtocolT<Transport_, ByteOrder_>::readSetEnd() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
template <class Transport_, class ByteOrder_>
|
||||
uint32_t TBinaryProtocolT<Transport_, ByteOrder_>::readBool(bool& value) {
|
||||
uint8_t b[1];
|
||||
this->trans_->readAll(b, 1);
|
||||
value = *(int8_t*)b != 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
template <class Transport_, class ByteOrder_>
|
||||
uint32_t TBinaryProtocolT<Transport_, ByteOrder_>::readByte(int8_t& byte) {
|
||||
uint8_t b[1];
|
||||
this->trans_->readAll(b, 1);
|
||||
byte = *(int8_t*)b;
|
||||
return 1;
|
||||
}
|
||||
|
||||
template <class Transport_, class ByteOrder_>
|
||||
uint32_t TBinaryProtocolT<Transport_, ByteOrder_>::readI16(int16_t& i16) {
|
||||
union bytes {
|
||||
uint8_t b[2];
|
||||
int16_t all;
|
||||
} theBytes;
|
||||
this->trans_->readAll(theBytes.b, 2);
|
||||
i16 = (int16_t)ByteOrder_::fromWire16(theBytes.all);
|
||||
return 2;
|
||||
}
|
||||
|
||||
template <class Transport_, class ByteOrder_>
|
||||
uint32_t TBinaryProtocolT<Transport_, ByteOrder_>::readI32(int32_t& i32) {
|
||||
union bytes {
|
||||
uint8_t b[4];
|
||||
int32_t all;
|
||||
} theBytes;
|
||||
this->trans_->readAll(theBytes.b, 4);
|
||||
i32 = (int32_t)ByteOrder_::fromWire32(theBytes.all);
|
||||
return 4;
|
||||
}
|
||||
|
||||
template <class Transport_, class ByteOrder_>
|
||||
uint32_t TBinaryProtocolT<Transport_, ByteOrder_>::readI64(int64_t& i64) {
|
||||
union bytes {
|
||||
uint8_t b[8];
|
||||
int64_t all;
|
||||
} theBytes;
|
||||
this->trans_->readAll(theBytes.b, 8);
|
||||
i64 = (int64_t)ByteOrder_::fromWire64(theBytes.all);
|
||||
return 8;
|
||||
}
|
||||
|
||||
template <class Transport_, class ByteOrder_>
|
||||
uint32_t TBinaryProtocolT<Transport_, ByteOrder_>::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 = ByteOrder_::fromWire64(theBytes.all);
|
||||
dub = bitwise_cast<double>(theBytes.all);
|
||||
return 8;
|
||||
}
|
||||
|
||||
template <class Transport_, class ByteOrder_>
|
||||
template <typename StrType>
|
||||
uint32_t TBinaryProtocolT<Transport_, ByteOrder_>::readString(StrType& str) {
|
||||
uint32_t result;
|
||||
int32_t size;
|
||||
result = readI32(size);
|
||||
return result + readStringBody(str, size);
|
||||
}
|
||||
|
||||
template <class Transport_, class ByteOrder_>
|
||||
uint32_t TBinaryProtocolT<Transport_, ByteOrder_>::readBinary(std::string& str) {
|
||||
return TBinaryProtocolT<Transport_, ByteOrder_>::readString(str);
|
||||
}
|
||||
|
||||
template <class Transport_, class ByteOrder_>
|
||||
template <typename StrType>
|
||||
uint32_t TBinaryProtocolT<Transport_, ByteOrder_>::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;
|
||||
}
|
||||
|
||||
str.resize(size);
|
||||
this->trans_->readAll(reinterpret_cast<uint8_t*>(&str[0]), size);
|
||||
return (uint32_t)size;
|
||||
}
|
||||
}
|
||||
}
|
||||
} // apache::thrift::protocol
|
||||
|
||||
#endif // #ifndef _THRIFT_PROTOCOL_TBINARYPROTOCOL_TCC_
|
266
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/protocol/TCompactProtocol.h
generated
vendored
Normal file
266
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/protocol/TCompactProtocol.h
generated
vendored
Normal file
|
@ -0,0 +1,266 @@
|
|||
/*
|
||||
* 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_H_
|
||||
#define _THRIFT_PROTOCOL_TCOMPACTPROTOCOL_H_ 1
|
||||
|
||||
#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_> > {
|
||||
public:
|
||||
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
|
||||
|
||||
protected:
|
||||
static const int8_t TYPE_MASK = (int8_t)0xE0u; // 1110 0000
|
||||
static const int8_t TYPE_BITS = 0x07; // 0000 0111
|
||||
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>
|
||||
|
||||
#endif
|
826
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/protocol/TCompactProtocol.tcc
generated
vendored
Normal file
826
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/protocol/TCompactProtocol.tcc
generated
vendored
Normal file
|
@ -0,0 +1,826 @@
|
|||
/*
|
||||
* 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>
|
||||
|
||||
#include "thrift/config.h"
|
||||
|
||||
/*
|
||||
* 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 = THRIFT_htolell(bits);
|
||||
trans_->write((uint8_t*)&bits, 8);
|
||||
return 8;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write a string to the wire with a varint size preceding.
|
||||
*/
|
||||
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) {
|
||||
if(str.size() > (std::numeric_limits<uint32_t>::max)())
|
||||
throw TProtocolException(TProtocolException::SIZE_LIMIT);
|
||||
uint32_t ssize = static_cast<uint32_t>(str.size());
|
||||
uint32_t wsize = writeVarint32(ssize) ;
|
||||
// checking ssize + wsize > uint_max, but we don't want to overflow while checking for overflows.
|
||||
// transforming the check to ssize > uint_max - wsize
|
||||
if(ssize > (std::numeric_limits<uint32_t>::max)() - wsize)
|
||||
throw TProtocolException(TProtocolException::SIZE_LIMIT);
|
||||
wsize += 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) & TYPE_BITS);
|
||||
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 = THRIFT_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<uint32_t>(-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<uint64_t>(-static_cast<int64_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);
|
||||
}
|
||||
}
|
||||
|
||||
}}} // apache::thrift::protocol
|
||||
|
||||
#endif // _THRIFT_PROTOCOL_TCOMPACTPROTOCOL_TCC_
|
394
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/protocol/TDebugProtocol.cpp
generated
vendored
Normal file
394
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/protocol/TDebugProtocol.cpp
generated
vendored
Normal file
|
@ -0,0 +1,394 @@
|
|||
/*
|
||||
* 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/protocol/TDebugProtocol.h>
|
||||
|
||||
#include <cassert>
|
||||
#include <cctype>
|
||||
#include <cstdio>
|
||||
#include <stdexcept>
|
||||
#include <boost/static_assert.hpp>
|
||||
#include <boost/lexical_cast.hpp>
|
||||
|
||||
using std::string;
|
||||
|
||||
static string byte_to_hex(const uint8_t byte) {
|
||||
char buf[3];
|
||||
int ret = std::sprintf(buf, "%02x", (int)byte);
|
||||
THRIFT_UNUSED_VARIABLE(ret);
|
||||
assert(ret == 2);
|
||||
assert(buf[2] == '\0');
|
||||
return buf;
|
||||
}
|
||||
|
||||
namespace apache {
|
||||
namespace thrift {
|
||||
namespace protocol {
|
||||
|
||||
string TDebugProtocol::fieldTypeName(TType type) {
|
||||
switch (type) {
|
||||
case T_STOP:
|
||||
return "stop";
|
||||
case T_VOID:
|
||||
return "void";
|
||||
case T_BOOL:
|
||||
return "bool";
|
||||
case T_BYTE:
|
||||
return "byte";
|
||||
case T_I16:
|
||||
return "i16";
|
||||
case T_I32:
|
||||
return "i32";
|
||||
case T_U64:
|
||||
return "u64";
|
||||
case T_I64:
|
||||
return "i64";
|
||||
case T_DOUBLE:
|
||||
return "double";
|
||||
case T_STRING:
|
||||
return "string";
|
||||
case T_STRUCT:
|
||||
return "struct";
|
||||
case T_MAP:
|
||||
return "map";
|
||||
case T_SET:
|
||||
return "set";
|
||||
case T_LIST:
|
||||
return "list";
|
||||
case T_UTF8:
|
||||
return "utf8";
|
||||
case T_UTF16:
|
||||
return "utf16";
|
||||
default:
|
||||
return "unknown";
|
||||
}
|
||||
}
|
||||
|
||||
void TDebugProtocol::indentUp() {
|
||||
indent_str_ += string(indent_inc, ' ');
|
||||
}
|
||||
|
||||
void TDebugProtocol::indentDown() {
|
||||
if (indent_str_.length() < (string::size_type)indent_inc) {
|
||||
throw TProtocolException(TProtocolException::INVALID_DATA);
|
||||
}
|
||||
indent_str_.erase(indent_str_.length() - indent_inc);
|
||||
}
|
||||
|
||||
uint32_t TDebugProtocol::writePlain(const string& str) {
|
||||
if (str.length() > (std::numeric_limits<uint32_t>::max)())
|
||||
throw TProtocolException(TProtocolException::SIZE_LIMIT);
|
||||
trans_->write((uint8_t*)str.data(), static_cast<uint32_t>(str.length()));
|
||||
return static_cast<uint32_t>(str.length());
|
||||
}
|
||||
|
||||
uint32_t TDebugProtocol::writeIndented(const string& str) {
|
||||
if (str.length() > (std::numeric_limits<uint32_t>::max)())
|
||||
throw TProtocolException(TProtocolException::SIZE_LIMIT);
|
||||
if (indent_str_.length() > (std::numeric_limits<uint32_t>::max)())
|
||||
throw TProtocolException(TProtocolException::SIZE_LIMIT);
|
||||
uint64_t total_len = indent_str_.length() + str.length();
|
||||
if (total_len > (std::numeric_limits<uint32_t>::max)())
|
||||
throw TProtocolException(TProtocolException::SIZE_LIMIT);
|
||||
trans_->write((uint8_t*)indent_str_.data(), static_cast<uint32_t>(indent_str_.length()));
|
||||
trans_->write((uint8_t*)str.data(), static_cast<uint32_t>(str.length()));
|
||||
return static_cast<uint32_t>(indent_str_.length() + str.length());
|
||||
}
|
||||
|
||||
uint32_t TDebugProtocol::startItem() {
|
||||
uint32_t size;
|
||||
|
||||
switch (write_state_.back()) {
|
||||
case UNINIT:
|
||||
// XXX figure out what to do here.
|
||||
// throw TProtocolException(TProtocolException::INVALID_DATA);
|
||||
// return writeIndented(str);
|
||||
return 0;
|
||||
case STRUCT:
|
||||
return 0;
|
||||
case SET:
|
||||
return writeIndented("");
|
||||
case MAP_KEY:
|
||||
return writeIndented("");
|
||||
case MAP_VALUE:
|
||||
return writePlain(" -> ");
|
||||
case LIST:
|
||||
size = writeIndented("[" + boost::lexical_cast<string>(list_idx_.back()) + "] = ");
|
||||
list_idx_.back()++;
|
||||
return size;
|
||||
default:
|
||||
throw std::logic_error("Invalid enum value.");
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t TDebugProtocol::endItem() {
|
||||
// uint32_t size;
|
||||
|
||||
switch (write_state_.back()) {
|
||||
case UNINIT:
|
||||
// XXX figure out what to do here.
|
||||
// throw TProtocolException(TProtocolException::INVALID_DATA);
|
||||
// return writeIndented(str);
|
||||
return 0;
|
||||
case STRUCT:
|
||||
return writePlain(",\n");
|
||||
case SET:
|
||||
return writePlain(",\n");
|
||||
case MAP_KEY:
|
||||
write_state_.back() = MAP_VALUE;
|
||||
return 0;
|
||||
case MAP_VALUE:
|
||||
write_state_.back() = MAP_KEY;
|
||||
return writePlain(",\n");
|
||||
case LIST:
|
||||
return writePlain(",\n");
|
||||
default:
|
||||
throw std::logic_error("Invalid enum value.");
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t TDebugProtocol::writeItem(const std::string& str) {
|
||||
uint32_t size = 0;
|
||||
size += startItem();
|
||||
size += writePlain(str);
|
||||
size += endItem();
|
||||
return size;
|
||||
}
|
||||
|
||||
uint32_t TDebugProtocol::writeMessageBegin(const std::string& name,
|
||||
const TMessageType messageType,
|
||||
const int32_t seqid) {
|
||||
(void)seqid;
|
||||
string mtype;
|
||||
switch (messageType) {
|
||||
case T_CALL:
|
||||
mtype = "call";
|
||||
break;
|
||||
case T_REPLY:
|
||||
mtype = "reply";
|
||||
break;
|
||||
case T_EXCEPTION:
|
||||
mtype = "exn";
|
||||
break;
|
||||
case T_ONEWAY:
|
||||
mtype = "oneway";
|
||||
break;
|
||||
}
|
||||
|
||||
uint32_t size = writeIndented("(" + mtype + ") " + name + "(");
|
||||
indentUp();
|
||||
return size;
|
||||
}
|
||||
|
||||
uint32_t TDebugProtocol::writeMessageEnd() {
|
||||
indentDown();
|
||||
return writeIndented(")\n");
|
||||
}
|
||||
|
||||
uint32_t TDebugProtocol::writeStructBegin(const char* name) {
|
||||
uint32_t size = 0;
|
||||
size += startItem();
|
||||
size += writePlain(string(name) + " {\n");
|
||||
indentUp();
|
||||
write_state_.push_back(STRUCT);
|
||||
return size;
|
||||
}
|
||||
|
||||
uint32_t TDebugProtocol::writeStructEnd() {
|
||||
indentDown();
|
||||
write_state_.pop_back();
|
||||
uint32_t size = 0;
|
||||
size += writeIndented("}");
|
||||
size += endItem();
|
||||
return size;
|
||||
}
|
||||
|
||||
uint32_t TDebugProtocol::writeFieldBegin(const char* name,
|
||||
const TType fieldType,
|
||||
const int16_t fieldId) {
|
||||
// sprintf(id_str, "%02d", fieldId);
|
||||
string id_str = boost::lexical_cast<string>(fieldId);
|
||||
if (id_str.length() == 1)
|
||||
id_str = '0' + id_str;
|
||||
|
||||
return writeIndented(id_str + ": " + name + " (" + fieldTypeName(fieldType) + ") = ");
|
||||
}
|
||||
|
||||
uint32_t TDebugProtocol::writeFieldEnd() {
|
||||
assert(write_state_.back() == STRUCT);
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t TDebugProtocol::writeFieldStop() {
|
||||
return 0;
|
||||
// writeIndented("***STOP***\n");
|
||||
}
|
||||
|
||||
uint32_t TDebugProtocol::writeMapBegin(const TType keyType,
|
||||
const TType valType,
|
||||
const uint32_t size) {
|
||||
// TODO(dreiss): Optimize short maps?
|
||||
uint32_t bsize = 0;
|
||||
bsize += startItem();
|
||||
bsize += writePlain(
|
||||
"map<" + fieldTypeName(keyType) + "," + fieldTypeName(valType) + ">"
|
||||
"[" + boost::lexical_cast<string>(size) + "] {\n");
|
||||
indentUp();
|
||||
write_state_.push_back(MAP_KEY);
|
||||
return bsize;
|
||||
}
|
||||
|
||||
uint32_t TDebugProtocol::writeMapEnd() {
|
||||
indentDown();
|
||||
write_state_.pop_back();
|
||||
uint32_t size = 0;
|
||||
size += writeIndented("}");
|
||||
size += endItem();
|
||||
return size;
|
||||
}
|
||||
|
||||
uint32_t TDebugProtocol::writeListBegin(const TType elemType, const uint32_t size) {
|
||||
// TODO(dreiss): Optimize short arrays.
|
||||
uint32_t bsize = 0;
|
||||
bsize += startItem();
|
||||
bsize += writePlain(
|
||||
"list<" + fieldTypeName(elemType) + ">"
|
||||
"[" + boost::lexical_cast<string>(size) + "] {\n");
|
||||
indentUp();
|
||||
write_state_.push_back(LIST);
|
||||
list_idx_.push_back(0);
|
||||
return bsize;
|
||||
}
|
||||
|
||||
uint32_t TDebugProtocol::writeListEnd() {
|
||||
indentDown();
|
||||
write_state_.pop_back();
|
||||
list_idx_.pop_back();
|
||||
uint32_t size = 0;
|
||||
size += writeIndented("}");
|
||||
size += endItem();
|
||||
return size;
|
||||
}
|
||||
|
||||
uint32_t TDebugProtocol::writeSetBegin(const TType elemType, const uint32_t size) {
|
||||
// TODO(dreiss): Optimize short sets.
|
||||
uint32_t bsize = 0;
|
||||
bsize += startItem();
|
||||
bsize += writePlain(
|
||||
"set<" + fieldTypeName(elemType) + ">"
|
||||
"[" + boost::lexical_cast<string>(size) + "] {\n");
|
||||
indentUp();
|
||||
write_state_.push_back(SET);
|
||||
return bsize;
|
||||
}
|
||||
|
||||
uint32_t TDebugProtocol::writeSetEnd() {
|
||||
indentDown();
|
||||
write_state_.pop_back();
|
||||
uint32_t size = 0;
|
||||
size += writeIndented("}");
|
||||
size += endItem();
|
||||
return size;
|
||||
}
|
||||
|
||||
uint32_t TDebugProtocol::writeBool(const bool value) {
|
||||
return writeItem(value ? "true" : "false");
|
||||
}
|
||||
|
||||
uint32_t TDebugProtocol::writeByte(const int8_t byte) {
|
||||
return writeItem("0x" + byte_to_hex(byte));
|
||||
}
|
||||
|
||||
uint32_t TDebugProtocol::writeI16(const int16_t i16) {
|
||||
return writeItem(boost::lexical_cast<string>(i16));
|
||||
}
|
||||
|
||||
uint32_t TDebugProtocol::writeI32(const int32_t i32) {
|
||||
return writeItem(boost::lexical_cast<string>(i32));
|
||||
}
|
||||
|
||||
uint32_t TDebugProtocol::writeI64(const int64_t i64) {
|
||||
return writeItem(boost::lexical_cast<string>(i64));
|
||||
}
|
||||
|
||||
uint32_t TDebugProtocol::writeDouble(const double dub) {
|
||||
return writeItem(boost::lexical_cast<string>(dub));
|
||||
}
|
||||
|
||||
uint32_t TDebugProtocol::writeString(const string& str) {
|
||||
// XXX Raw/UTF-8?
|
||||
|
||||
string to_show = str;
|
||||
if (to_show.length() > (string::size_type)string_limit_) {
|
||||
to_show = str.substr(0, string_prefix_size_);
|
||||
to_show += "[...](" + boost::lexical_cast<string>(str.length()) + ")";
|
||||
}
|
||||
|
||||
string output = "\"";
|
||||
|
||||
for (string::const_iterator it = to_show.begin(); it != to_show.end(); ++it) {
|
||||
if (*it == '\\') {
|
||||
output += "\\\\";
|
||||
} else if (*it == '"') {
|
||||
output += "\\\"";
|
||||
// passing characters <0 to std::isprint causes asserts. isprint takes an
|
||||
// int, so we need to be careful of sign extension
|
||||
} else if (std::isprint((unsigned char)*it)) {
|
||||
output += *it;
|
||||
} else {
|
||||
switch (*it) {
|
||||
case '\a':
|
||||
output += "\\a";
|
||||
break;
|
||||
case '\b':
|
||||
output += "\\b";
|
||||
break;
|
||||
case '\f':
|
||||
output += "\\f";
|
||||
break;
|
||||
case '\n':
|
||||
output += "\\n";
|
||||
break;
|
||||
case '\r':
|
||||
output += "\\r";
|
||||
break;
|
||||
case '\t':
|
||||
output += "\\t";
|
||||
break;
|
||||
case '\v':
|
||||
output += "\\v";
|
||||
break;
|
||||
default:
|
||||
output += "\\x";
|
||||
output += byte_to_hex(*it);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
output += '\"';
|
||||
return writeItem(output);
|
||||
}
|
||||
|
||||
uint32_t TDebugProtocol::writeBinary(const string& str) {
|
||||
// XXX Hex?
|
||||
return TDebugProtocol::writeString(str);
|
||||
}
|
||||
}
|
||||
}
|
||||
} // apache::thrift::protocol
|
204
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/protocol/TDebugProtocol.h
generated
vendored
Normal file
204
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/protocol/TDebugProtocol.h
generated
vendored
Normal file
|
@ -0,0 +1,204 @@
|
|||
/*
|
||||
* 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_TDEBUGPROTOCOL_H_
|
||||
#define _THRIFT_PROTOCOL_TDEBUGPROTOCOL_H_ 1
|
||||
|
||||
#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
|
||||
|
||||
#endif // #ifndef _THRIFT_PROTOCOL_TDEBUGPROTOCOL_H_
|
254
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/protocol/THeaderProtocol.cpp
generated
vendored
Normal file
254
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/protocol/THeaderProtocol.cpp
generated
vendored
Normal file
|
@ -0,0 +1,254 @@
|
|||
/*
|
||||
* 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_THEADERPROTOCOL_CPP_
|
||||
#define THRIFT_PROTOCOL_THEADERPROTOCOL_CPP_ 1
|
||||
|
||||
#include <thrift/protocol/THeaderProtocol.h>
|
||||
#include <thrift/protocol/TCompactProtocol.h>
|
||||
#include <thrift/protocol/TBinaryProtocol.h>
|
||||
#include <thrift/TApplicationException.h>
|
||||
|
||||
#include <limits>
|
||||
|
||||
#include <boost/static_assert.hpp>
|
||||
#include <boost/make_shared.hpp>
|
||||
|
||||
namespace apache {
|
||||
namespace thrift {
|
||||
namespace protocol {
|
||||
|
||||
void THeaderProtocol::resetProtocol() {
|
||||
if (proto_ && protoId_ == trans_->getProtocolId()) {
|
||||
return;
|
||||
}
|
||||
|
||||
protoId_ = trans_->getProtocolId();
|
||||
|
||||
switch (protoId_) {
|
||||
case T_BINARY_PROTOCOL:
|
||||
proto_ = boost::make_shared<TBinaryProtocolT<THeaderTransport> >(trans_);
|
||||
break;
|
||||
|
||||
case T_COMPACT_PROTOCOL:
|
||||
proto_ = boost::make_shared<TCompactProtocolT<THeaderTransport> >(trans_);
|
||||
break;
|
||||
|
||||
default:
|
||||
throw TApplicationException(TApplicationException::INVALID_PROTOCOL,
|
||||
"Unknown protocol requested");
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t THeaderProtocol::writeMessageBegin(const std::string& name,
|
||||
const TMessageType messageType,
|
||||
const int32_t seqId) {
|
||||
resetProtocol(); // Reset in case we changed protocols
|
||||
trans_->setSequenceNumber(seqId);
|
||||
return proto_->writeMessageBegin(name, messageType, seqId);
|
||||
}
|
||||
|
||||
uint32_t THeaderProtocol::writeMessageEnd() {
|
||||
return proto_->writeMessageEnd();
|
||||
}
|
||||
|
||||
uint32_t THeaderProtocol::writeStructBegin(const char* name) {
|
||||
return proto_->writeStructBegin(name);
|
||||
}
|
||||
|
||||
uint32_t THeaderProtocol::writeStructEnd() {
|
||||
return proto_->writeStructEnd();
|
||||
}
|
||||
|
||||
uint32_t THeaderProtocol::writeFieldBegin(const char* name,
|
||||
const TType fieldType,
|
||||
const int16_t fieldId) {
|
||||
return proto_->writeFieldBegin(name, fieldType, fieldId);
|
||||
}
|
||||
|
||||
uint32_t THeaderProtocol::writeFieldEnd() {
|
||||
return proto_->writeFieldEnd();
|
||||
}
|
||||
|
||||
uint32_t THeaderProtocol::writeFieldStop() {
|
||||
return proto_->writeFieldStop();
|
||||
}
|
||||
|
||||
uint32_t THeaderProtocol::writeMapBegin(const TType keyType,
|
||||
const TType valType,
|
||||
const uint32_t size) {
|
||||
return proto_->writeMapBegin(keyType, valType, size);
|
||||
}
|
||||
|
||||
uint32_t THeaderProtocol::writeMapEnd() {
|
||||
return proto_->writeMapEnd();
|
||||
}
|
||||
|
||||
uint32_t THeaderProtocol::writeListBegin(const TType elemType, const uint32_t size) {
|
||||
return proto_->writeListBegin(elemType, size);
|
||||
}
|
||||
|
||||
uint32_t THeaderProtocol::writeListEnd() {
|
||||
return proto_->writeListEnd();
|
||||
}
|
||||
|
||||
uint32_t THeaderProtocol::writeSetBegin(const TType elemType, const uint32_t size) {
|
||||
return proto_->writeSetBegin(elemType, size);
|
||||
}
|
||||
|
||||
uint32_t THeaderProtocol::writeSetEnd() {
|
||||
return proto_->writeSetEnd();
|
||||
}
|
||||
|
||||
uint32_t THeaderProtocol::writeBool(const bool value) {
|
||||
return proto_->writeBool(value);
|
||||
}
|
||||
|
||||
uint32_t THeaderProtocol::writeByte(const int8_t byte) {
|
||||
return proto_->writeByte(byte);
|
||||
}
|
||||
|
||||
uint32_t THeaderProtocol::writeI16(const int16_t i16) {
|
||||
return proto_->writeI16(i16);
|
||||
}
|
||||
|
||||
uint32_t THeaderProtocol::writeI32(const int32_t i32) {
|
||||
return proto_->writeI32(i32);
|
||||
}
|
||||
|
||||
uint32_t THeaderProtocol::writeI64(const int64_t i64) {
|
||||
return proto_->writeI64(i64);
|
||||
}
|
||||
|
||||
uint32_t THeaderProtocol::writeDouble(const double dub) {
|
||||
return proto_->writeDouble(dub);
|
||||
}
|
||||
|
||||
uint32_t THeaderProtocol::writeString(const std::string& str) {
|
||||
return proto_->writeString(str);
|
||||
}
|
||||
|
||||
uint32_t THeaderProtocol::writeBinary(const std::string& str) {
|
||||
return proto_->writeBinary(str);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reading functions
|
||||
*/
|
||||
|
||||
uint32_t THeaderProtocol::readMessageBegin(std::string& name,
|
||||
TMessageType& messageType,
|
||||
int32_t& seqId) {
|
||||
// Read the next frame, and change protocols if needed
|
||||
try {
|
||||
trans_->resetProtocol();
|
||||
resetProtocol();
|
||||
} catch (const TApplicationException& ex) {
|
||||
writeMessageBegin("", T_EXCEPTION, 0);
|
||||
ex.write((TProtocol*)this);
|
||||
writeMessageEnd();
|
||||
trans_->flush();
|
||||
|
||||
// The framing is still good, but we don't know about this protocol.
|
||||
// In the future, this could be made a client-side only error if
|
||||
// connection pooling is used.
|
||||
throw ex;
|
||||
}
|
||||
return proto_->readMessageBegin(name, messageType, seqId);
|
||||
}
|
||||
|
||||
uint32_t THeaderProtocol::readMessageEnd() {
|
||||
return proto_->readMessageEnd();
|
||||
}
|
||||
|
||||
uint32_t THeaderProtocol::readStructBegin(std::string& name) {
|
||||
return proto_->readStructBegin(name);
|
||||
}
|
||||
|
||||
uint32_t THeaderProtocol::readStructEnd() {
|
||||
return proto_->readStructEnd();
|
||||
}
|
||||
|
||||
uint32_t THeaderProtocol::readFieldBegin(std::string& name, TType& fieldType, int16_t& fieldId) {
|
||||
return proto_->readFieldBegin(name, fieldType, fieldId);
|
||||
}
|
||||
|
||||
uint32_t THeaderProtocol::readFieldEnd() {
|
||||
return proto_->readFieldEnd();
|
||||
}
|
||||
|
||||
uint32_t THeaderProtocol::readMapBegin(TType& keyType, TType& valType, uint32_t& size) {
|
||||
return proto_->readMapBegin(keyType, valType, size);
|
||||
}
|
||||
|
||||
uint32_t THeaderProtocol::readMapEnd() {
|
||||
return proto_->readMapEnd();
|
||||
}
|
||||
|
||||
uint32_t THeaderProtocol::readListBegin(TType& elemType, uint32_t& size) {
|
||||
return proto_->readListBegin(elemType, size);
|
||||
}
|
||||
|
||||
uint32_t THeaderProtocol::readListEnd() {
|
||||
return proto_->readListEnd();
|
||||
}
|
||||
|
||||
uint32_t THeaderProtocol::readSetBegin(TType& elemType, uint32_t& size) {
|
||||
return proto_->readSetBegin(elemType, size);
|
||||
}
|
||||
|
||||
uint32_t THeaderProtocol::readSetEnd() {
|
||||
return proto_->readSetEnd();
|
||||
}
|
||||
|
||||
uint32_t THeaderProtocol::readBool(bool& value) {
|
||||
return proto_->readBool(value);
|
||||
}
|
||||
|
||||
uint32_t THeaderProtocol::readByte(int8_t& byte) {
|
||||
return proto_->readByte(byte);
|
||||
}
|
||||
|
||||
uint32_t THeaderProtocol::readI16(int16_t& i16) {
|
||||
return proto_->readI16(i16);
|
||||
}
|
||||
|
||||
uint32_t THeaderProtocol::readI32(int32_t& i32) {
|
||||
return proto_->readI32(i32);
|
||||
}
|
||||
|
||||
uint32_t THeaderProtocol::readI64(int64_t& i64) {
|
||||
return proto_->readI64(i64);
|
||||
}
|
||||
|
||||
uint32_t THeaderProtocol::readDouble(double& dub) {
|
||||
return proto_->readDouble(dub);
|
||||
}
|
||||
|
||||
uint32_t THeaderProtocol::readString(std::string& str) {
|
||||
return proto_->readString(str);
|
||||
}
|
||||
|
||||
uint32_t THeaderProtocol::readBinary(std::string& binary) {
|
||||
return proto_->readBinary(binary);
|
||||
}
|
||||
}
|
||||
}
|
||||
} // apache::thrift::protocol
|
||||
|
||||
#endif // #ifndef THRIFT_PROTOCOL_THEADERPROTOCOL_CPP_
|
210
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/protocol/THeaderProtocol.h
generated
vendored
Normal file
210
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/protocol/THeaderProtocol.h
generated
vendored
Normal file
|
@ -0,0 +1,210 @@
|
|||
/*
|
||||
* 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_THEADERPROTOCOL_H_
|
||||
#define THRIFT_PROTOCOL_THEADERPROTOCOL_H_ 1
|
||||
|
||||
#include <thrift/protocol/TProtocol.h>
|
||||
#include <thrift/protocol/TProtocolTypes.h>
|
||||
#include <thrift/protocol/TVirtualProtocol.h>
|
||||
#include <thrift/transport/THeaderTransport.h>
|
||||
|
||||
#include <boost/shared_ptr.hpp>
|
||||
|
||||
using apache::thrift::transport::THeaderTransport;
|
||||
|
||||
namespace apache {
|
||||
namespace thrift {
|
||||
namespace protocol {
|
||||
|
||||
/**
|
||||
* The header protocol for thrift. Reads unframed, framed, header format,
|
||||
* and http
|
||||
*
|
||||
*/
|
||||
class THeaderProtocol : public TVirtualProtocol<THeaderProtocol> {
|
||||
protected:
|
||||
public:
|
||||
void resetProtocol();
|
||||
|
||||
explicit THeaderProtocol(const boost::shared_ptr<TTransport>& trans,
|
||||
uint16_t protoId = T_COMPACT_PROTOCOL)
|
||||
: TVirtualProtocol<THeaderProtocol>(boost::shared_ptr<TTransport>(new THeaderTransport(trans))),
|
||||
trans_(boost::dynamic_pointer_cast<THeaderTransport>(this->getTransport())),
|
||||
protoId_(protoId) {
|
||||
trans_->setProtocolId(protoId);
|
||||
resetProtocol();
|
||||
}
|
||||
|
||||
THeaderProtocol(const boost::shared_ptr<TTransport>& inTrans,
|
||||
const boost::shared_ptr<TTransport>& outTrans,
|
||||
uint16_t protoId = T_COMPACT_PROTOCOL)
|
||||
: TVirtualProtocol<THeaderProtocol>(
|
||||
boost::shared_ptr<TTransport>(new THeaderTransport(inTrans, outTrans))),
|
||||
trans_(boost::dynamic_pointer_cast<THeaderTransport>(this->getTransport())),
|
||||
protoId_(protoId) {
|
||||
trans_->setProtocolId(protoId);
|
||||
resetProtocol();
|
||||
}
|
||||
|
||||
~THeaderProtocol() {}
|
||||
|
||||
/**
|
||||
* Functions to work with headers by calling into THeaderTransport
|
||||
*/
|
||||
void setProtocolId(uint16_t protoId) {
|
||||
trans_->setProtocolId(protoId);
|
||||
resetProtocol();
|
||||
}
|
||||
|
||||
typedef THeaderTransport::StringToStringMap StringToStringMap;
|
||||
|
||||
// these work with write headers
|
||||
void setHeader(const std::string& key, const std::string& value) {
|
||||
trans_->setHeader(key, value);
|
||||
}
|
||||
|
||||
void clearHeaders() { trans_->clearHeaders(); }
|
||||
|
||||
StringToStringMap& getWriteHeaders() { return trans_->getWriteHeaders(); }
|
||||
|
||||
// these work with read headers
|
||||
const StringToStringMap& getHeaders() const { return trans_->getHeaders(); }
|
||||
|
||||
/**
|
||||
* Writing functions.
|
||||
*/
|
||||
|
||||
/*ol*/ uint32_t writeMessageBegin(const std::string& name,
|
||||
const TMessageType messageType,
|
||||
const int32_t seqId);
|
||||
|
||||
/*ol*/ 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
|
||||
*/
|
||||
|
||||
/*ol*/ uint32_t readMessageBegin(std::string& name, TMessageType& messageType, int32_t& seqId);
|
||||
|
||||
/*ol*/ 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<THeaderProtocol>::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& binary);
|
||||
|
||||
protected:
|
||||
boost::shared_ptr<THeaderTransport> trans_;
|
||||
|
||||
boost::shared_ptr<TProtocol> proto_;
|
||||
uint32_t protoId_;
|
||||
};
|
||||
|
||||
class THeaderProtocolFactory : public TProtocolFactory {
|
||||
public:
|
||||
virtual boost::shared_ptr<TProtocol> getProtocol(boost::shared_ptr<transport::TTransport> trans) {
|
||||
THeaderProtocol* headerProtocol
|
||||
= new THeaderProtocol(trans, boost::shared_ptr<transport::TTransport>(), T_BINARY_PROTOCOL);
|
||||
return boost::shared_ptr<TProtocol>(headerProtocol);
|
||||
}
|
||||
|
||||
virtual boost::shared_ptr<TProtocol> getProtocol(
|
||||
boost::shared_ptr<transport::TTransport> inTrans,
|
||||
boost::shared_ptr<transport::TTransport> outTrans) {
|
||||
THeaderProtocol* headerProtocol = new THeaderProtocol(inTrans, outTrans, T_BINARY_PROTOCOL);
|
||||
return boost::shared_ptr<TProtocol>(headerProtocol);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
} // apache::thrift::protocol
|
||||
|
||||
#endif // #ifndef THRIFT_PROTOCOL_THEADERPROTOCOL_H_
|
1099
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/protocol/TJSONProtocol.cpp
generated
vendored
Normal file
1099
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/protocol/TJSONProtocol.cpp
generated
vendored
Normal file
File diff suppressed because it is too large
Load diff
324
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/protocol/TJSONProtocol.h
generated
vendored
Normal file
324
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/protocol/TJSONProtocol.h
generated
vendored
Normal file
|
@ -0,0 +1,324 @@
|
|||
/*
|
||||
* 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_TJSONPROTOCOL_H_
|
||||
#define _THRIFT_PROTOCOL_TJSONPROTOCOL_H_ 1
|
||||
|
||||
#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 positive 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).
|
||||
*
|
||||
* NOTE: Base64 padding is optional for Thrift binary value encoding. So
|
||||
* the readBinary() method needs to decode both input strings with padding
|
||||
* and those without one.
|
||||
*
|
||||
* 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(uint16_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
|
||||
|
||||
#endif // #define _THRIFT_PROTOCOL_TJSONPROTOCOL_H_ 1
|
40
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/protocol/TMultiplexedProtocol.cpp
generated
vendored
Normal file
40
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/protocol/TMultiplexedProtocol.cpp
generated
vendored
Normal file
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* 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/protocol/TMultiplexedProtocol.h>
|
||||
#include <thrift/processor/TMultiplexedProcessor.h>
|
||||
#include <thrift/protocol/TProtocolDecorator.h>
|
||||
|
||||
namespace apache {
|
||||
namespace thrift {
|
||||
namespace protocol {
|
||||
uint32_t TMultiplexedProtocol::writeMessageBegin_virt(const std::string& _name,
|
||||
const TMessageType _type,
|
||||
const int32_t _seqid) {
|
||||
if (_type == T_CALL || _type == T_ONEWAY) {
|
||||
return TProtocolDecorator::writeMessageBegin_virt(serviceName + separator + _name,
|
||||
_type,
|
||||
_seqid);
|
||||
} else {
|
||||
return TProtocolDecorator::writeMessageBegin_virt(_name, _type, _seqid);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
95
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/protocol/TMultiplexedProtocol.h
generated
vendored
Normal file
95
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/protocol/TMultiplexedProtocol.h
generated
vendored
Normal file
|
@ -0,0 +1,95 @@
|
|||
/*
|
||||
* 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_TMULTIPLEXEDPROTOCOL_H_
|
||||
#define THRIFT_TMULTIPLEXEDPROTOCOL_H_ 1
|
||||
|
||||
#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;
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // THRIFT_TMULTIPLEXEDPROTOCOL_H_
|
33
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/protocol/TProtocol.cpp
generated
vendored
Normal file
33
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/protocol/TProtocol.cpp
generated
vendored
Normal file
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
* 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/protocol/TProtocol.h>
|
||||
|
||||
namespace apache {
|
||||
namespace thrift {
|
||||
namespace protocol {
|
||||
|
||||
TProtocol::~TProtocol() {}
|
||||
uint32_t TProtocol::skip_virt(TType type) {
|
||||
return ::apache::thrift::protocol::skip(*this, type);
|
||||
}
|
||||
|
||||
TProtocolFactory::~TProtocolFactory() {}
|
||||
|
||||
}}} // apache::thrift::protocol
|
762
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/protocol/TProtocol.h
generated
vendored
Normal file
762
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/protocol/TProtocol.h
generated
vendored
Normal file
|
@ -0,0 +1,762 @@
|
|||
/*
|
||||
* 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_TPROTOCOL_H_
|
||||
#define _THRIFT_PROTOCOL_TPROTOCOL_H_ 1
|
||||
|
||||
#ifdef _WIN32
|
||||
// Need to come before any Windows.h includes
|
||||
#include <Winsock2.h>
|
||||
#endif
|
||||
|
||||
#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>
|
||||
#include <climits>
|
||||
|
||||
// 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://cellperformance.beyond3d.com/articles/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
|
||||
# if !defined(THRIFT_ntohll)
|
||||
# define THRIFT_ntohll(n) (n)
|
||||
# define THRIFT_htonll(n) (n)
|
||||
# endif
|
||||
# if defined(__GNUC__) && defined(__GLIBC__)
|
||||
# include <byteswap.h>
|
||||
# define THRIFT_htolell(n) bswap_64(n)
|
||||
# define THRIFT_letohll(n) bswap_64(n)
|
||||
# define THRIFT_htolel(n) bswap_32(n)
|
||||
# define THRIFT_letohl(n) bswap_32(n)
|
||||
# define THRIFT_htoles(n) bswap_16(n)
|
||||
# define THRIFT_letohs(n) bswap_16(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 bswap_32(n) \
|
||||
( (((n) & 0xff000000ul) >> 24) \
|
||||
| (((n) & 0x00ff0000ul) >> 8) \
|
||||
| (((n) & 0x0000ff00ul) << 8) \
|
||||
| (((n) & 0x000000fful) << 24) )
|
||||
# define bswap_16(n) \
|
||||
( (((n) & ((unsigned short)0xff00ul)) >> 8) \
|
||||
| (((n) & ((unsigned short)0x00fful)) << 8) )
|
||||
# define THRIFT_htolell(n) bswap_64(n)
|
||||
# define THRIFT_letohll(n) bswap_64(n)
|
||||
# define THRIFT_htolel(n) bswap_32(n)
|
||||
# define THRIFT_letohl(n) bswap_32(n)
|
||||
# define THRIFT_htoles(n) bswap_16(n)
|
||||
# define THRIFT_letohs(n) bswap_16(n)
|
||||
# endif /* GNUC & GLIBC */
|
||||
#elif __THRIFT_BYTE_ORDER == __THRIFT_LITTLE_ENDIAN
|
||||
# define THRIFT_htolell(n) (n)
|
||||
# define THRIFT_letohll(n) (n)
|
||||
# define THRIFT_htolel(n) (n)
|
||||
# define THRIFT_letohl(n) (n)
|
||||
# define THRIFT_htoles(n) (n)
|
||||
# define THRIFT_letohs(n) (n)
|
||||
# if defined(__GNUC__) && defined(__GLIBC__)
|
||||
# include <byteswap.h>
|
||||
# define THRIFT_ntohll(n) bswap_64(n)
|
||||
# define THRIFT_htonll(n) bswap_64(n)
|
||||
# elif defined(_MSC_VER) /* Microsoft Visual C++ */
|
||||
# define THRIFT_ntohll(n) ( _byteswap_uint64((uint64_t)n) )
|
||||
# define THRIFT_htonll(n) ( _byteswap_uint64((uint64_t)n) )
|
||||
# elif !defined(THRIFT_ntohll) /* Not GNUC/GLIBC or MSVC */
|
||||
# define THRIFT_ntohll(n) ( (((uint64_t)ntohl((uint32_t)n)) << 32) + ntohl((uint32_t)(n >> 32)) )
|
||||
# define THRIFT_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 THRIFT_htonll or THRIFT_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
|
||||
};
|
||||
|
||||
static const uint32_t DEFAULT_RECURSION_LIMIT = 64;
|
||||
|
||||
/**
|
||||
* 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);
|
||||
|
||||
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_; }
|
||||
|
||||
// input and output recursion depth are kept separate so that one protocol
|
||||
// can be used concurrently for both input and output.
|
||||
void incrementInputRecursionDepth() {
|
||||
if (recursion_limit_ < ++input_recursion_depth_) {
|
||||
throw TProtocolException(TProtocolException::DEPTH_LIMIT);
|
||||
}
|
||||
}
|
||||
void decrementInputRecursionDepth() { --input_recursion_depth_; }
|
||||
|
||||
void incrementOutputRecursionDepth() {
|
||||
if (recursion_limit_ < ++output_recursion_depth_) {
|
||||
throw TProtocolException(TProtocolException::DEPTH_LIMIT);
|
||||
}
|
||||
}
|
||||
void decrementOutputRecursionDepth() { --output_recursion_depth_; }
|
||||
|
||||
uint32_t getRecursionLimit() const {return recursion_limit_;}
|
||||
void setRecurisionLimit(uint32_t depth) {recursion_limit_ = depth;}
|
||||
|
||||
protected:
|
||||
TProtocol(boost::shared_ptr<TTransport> ptrans)
|
||||
: ptrans_(ptrans), input_recursion_depth_(0), output_recursion_depth_(0), recursion_limit_(DEFAULT_RECURSION_LIMIT)
|
||||
{}
|
||||
|
||||
boost::shared_ptr<TTransport> ptrans_;
|
||||
|
||||
private:
|
||||
TProtocol() {}
|
||||
uint32_t input_recursion_depth_;
|
||||
uint32_t output_recursion_depth_;
|
||||
uint32_t recursion_limit_;
|
||||
};
|
||||
|
||||
/**
|
||||
* 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;
|
||||
virtual boost::shared_ptr<TProtocol> getProtocol(boost::shared_ptr<TTransport> inTrans,
|
||||
boost::shared_ptr<TTransport> outTrans) {
|
||||
(void)outTrans;
|
||||
return getProtocol(inTrans);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Dummy protocol class.
|
||||
*
|
||||
* This class does nothing, and should never be instantiated.
|
||||
* It is used only by the generator code.
|
||||
*/
|
||||
class TDummyProtocol : public TProtocol {};
|
||||
|
||||
// This is the default / legacy choice
|
||||
struct TNetworkBigEndian
|
||||
{
|
||||
static uint16_t toWire16(uint16_t x) {return htons(x);}
|
||||
static uint32_t toWire32(uint32_t x) {return htonl(x);}
|
||||
static uint64_t toWire64(uint64_t x) {return THRIFT_htonll(x);}
|
||||
static uint16_t fromWire16(uint16_t x) {return ntohs(x);}
|
||||
static uint32_t fromWire32(uint32_t x) {return ntohl(x);}
|
||||
static uint64_t fromWire64(uint64_t x) {return THRIFT_ntohll(x);}
|
||||
};
|
||||
|
||||
// On most systems, this will be a bit faster than TNetworkBigEndian
|
||||
struct TNetworkLittleEndian
|
||||
{
|
||||
static uint16_t toWire16(uint16_t x) {return THRIFT_htoles(x);}
|
||||
static uint32_t toWire32(uint32_t x) {return THRIFT_htolel(x);}
|
||||
static uint64_t toWire64(uint64_t x) {return THRIFT_htolell(x);}
|
||||
static uint16_t fromWire16(uint16_t x) {return THRIFT_letohs(x);}
|
||||
static uint32_t fromWire32(uint32_t x) {return THRIFT_letohl(x);}
|
||||
static uint64_t fromWire64(uint64_t x) {return THRIFT_letohll(x);}
|
||||
};
|
||||
|
||||
struct TOutputRecursionTracker {
|
||||
TProtocol &prot_;
|
||||
TOutputRecursionTracker(TProtocol &prot) : prot_(prot) {
|
||||
prot_.incrementOutputRecursionDepth();
|
||||
}
|
||||
~TOutputRecursionTracker() {
|
||||
prot_.decrementOutputRecursionDepth();
|
||||
}
|
||||
};
|
||||
|
||||
struct TInputRecursionTracker {
|
||||
TProtocol &prot_;
|
||||
TInputRecursionTracker(TProtocol &prot) : prot_(prot) {
|
||||
prot_.incrementInputRecursionDepth();
|
||||
}
|
||||
~TInputRecursionTracker() {
|
||||
prot_.decrementInputRecursionDepth();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 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) {
|
||||
TInputRecursionTracker tracker(prot);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
}}} // apache::thrift::protocol
|
||||
|
||||
#endif // #define _THRIFT_PROTOCOL_TPROTOCOL_H_ 1
|
151
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/protocol/TProtocolDecorator.h
generated
vendored
Normal file
151
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/protocol/TProtocolDecorator.h
generated
vendored
Normal file
|
@ -0,0 +1,151 @@
|
|||
/*
|
||||
* 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_TPROTOCOLDECORATOR_H_
|
||||
#define THRIFT_TPROTOCOLDECORATOR_H_ 1
|
||||
|
||||
#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;
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // THRIFT_TPROTOCOLDECORATOR_H_
|
105
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/protocol/TProtocolException.h
generated
vendored
Normal file
105
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/protocol/TProtocolException.h
generated
vendored
Normal file
|
@ -0,0 +1,105 @@
|
|||
/*
|
||||
* 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_TPROTOCOLEXCEPTION_H_
|
||||
#define _THRIFT_PROTOCOL_TPROTOCOLEXCEPTION_H_ 1
|
||||
|
||||
#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,
|
||||
DEPTH_LIMIT = 6
|
||||
};
|
||||
|
||||
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() const { 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
|
||||
|
||||
#endif // #ifndef _THRIFT_PROTOCOL_TPROTOCOLEXCEPTION_H_
|
177
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/protocol/TProtocolTap.h
generated
vendored
Normal file
177
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/protocol/TProtocolTap.h
generated
vendored
Normal file
|
@ -0,0 +1,177 @@
|
|||
/*
|
||||
* 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_TPROTOCOLTAP_H_
|
||||
#define _THRIFT_PROTOCOL_TPROTOCOLTAP_H_ 1
|
||||
|
||||
#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
|
||||
|
||||
#endif // #define _THRIFT_PROTOCOL_TPROTOCOLTAP_H_ 1
|
36
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/protocol/TProtocolTypes.h
generated
vendored
Normal file
36
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/protocol/TProtocolTypes.h
generated
vendored
Normal file
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
* 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_TPROTOCOLTYPES_H_
|
||||
#define THRIFT_PROTOCOL_TPROTOCOLTYPES_H_ 1
|
||||
|
||||
namespace apache {
|
||||
namespace thrift {
|
||||
namespace protocol {
|
||||
|
||||
enum PROTOCOL_TYPES {
|
||||
T_BINARY_PROTOCOL = 0,
|
||||
T_JSON_PROTOCOL = 1,
|
||||
T_COMPACT_PROTOCOL = 2,
|
||||
};
|
||||
}
|
||||
}
|
||||
} // apache::thrift::protocol
|
||||
|
||||
#endif // #define _THRIFT_PROTOCOL_TPROTOCOLTYPES_H_ 1
|
513
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/protocol/TVirtualProtocol.h
generated
vendored
Normal file
513
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/protocol/TVirtualProtocol.h
generated
vendored
Normal file
|
@ -0,0 +1,513 @@
|
|||
/*
|
||||
* 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_TVIRTUALPROTOCOL_H_
|
||||
#define _THRIFT_PROTOCOL_TVIRTUALPROTOCOL_H_ 1
|
||||
|
||||
#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
|
||||
|
||||
#endif // #define _THRIFT_PROTOCOL_TVIRTUALPROTOCOL_H_ 1
|
28
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/qt/CMakeLists.txt
generated
vendored
Normal file
28
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/qt/CMakeLists.txt
generated
vendored
Normal file
|
@ -0,0 +1,28 @@
|
|||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
set( thriftcppqt5_SOURCES
|
||||
TQIODeviceTransport.cpp
|
||||
TQTcpServer.cpp
|
||||
)
|
||||
set(CMAKE_AUTOMOC ON)
|
||||
find_package(Qt5 REQUIRED COMPONENTS Core Network)
|
||||
ADD_LIBRARY_THRIFT(thriftqt5 ${thriftcppqt5_SOURCES})
|
||||
TARGET_LINK_LIBRARIES_THRIFT(thriftqt5 Qt5::Core Qt5::Network)
|
||||
TARGET_LINK_LIBRARIES_THRIFT_AGAINST_THRIFT_LIBRARY(thriftqt5 thrift)
|
167
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/qt/TQIODeviceTransport.cpp
generated
vendored
Normal file
167
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/qt/TQIODeviceTransport.cpp
generated
vendored
Normal file
|
@ -0,0 +1,167 @@
|
|||
/*
|
||||
* 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/qt/TQIODeviceTransport.h>
|
||||
|
||||
#include <QAbstractSocket>
|
||||
#include <QIODevice>
|
||||
|
||||
#include <thrift/transport/TBufferTransports.h>
|
||||
|
||||
using boost::shared_ptr;
|
||||
|
||||
namespace apache {
|
||||
namespace thrift {
|
||||
namespace transport {
|
||||
|
||||
TQIODeviceTransport::TQIODeviceTransport(shared_ptr<QIODevice> dev) : dev_(dev) {
|
||||
}
|
||||
|
||||
TQIODeviceTransport::~TQIODeviceTransport() {
|
||||
dev_->close();
|
||||
}
|
||||
|
||||
void TQIODeviceTransport::open() {
|
||||
if (!isOpen()) {
|
||||
throw TTransportException(TTransportException::NOT_OPEN,
|
||||
"open(): underlying QIODevice isn't open");
|
||||
}
|
||||
}
|
||||
|
||||
bool TQIODeviceTransport::isOpen() {
|
||||
return dev_->isOpen();
|
||||
}
|
||||
|
||||
bool TQIODeviceTransport::peek() {
|
||||
return dev_->bytesAvailable() > 0;
|
||||
}
|
||||
|
||||
void TQIODeviceTransport::close() {
|
||||
dev_->close();
|
||||
}
|
||||
|
||||
uint32_t TQIODeviceTransport::readAll(uint8_t* buf, uint32_t len) {
|
||||
uint32_t requestLen = len;
|
||||
while (len) {
|
||||
uint32_t readSize;
|
||||
try {
|
||||
readSize = read(buf, len);
|
||||
} catch (...) {
|
||||
if (len != requestLen) {
|
||||
// something read already
|
||||
return requestLen - len;
|
||||
}
|
||||
// error but nothing read yet
|
||||
throw;
|
||||
}
|
||||
if (readSize == 0) {
|
||||
dev_->waitForReadyRead(50);
|
||||
} else {
|
||||
buf += readSize;
|
||||
len -= readSize;
|
||||
}
|
||||
}
|
||||
return requestLen;
|
||||
}
|
||||
|
||||
uint32_t TQIODeviceTransport::read(uint8_t* buf, uint32_t len) {
|
||||
uint32_t actualSize;
|
||||
qint64 readSize;
|
||||
|
||||
if (!dev_->isOpen()) {
|
||||
throw TTransportException(TTransportException::NOT_OPEN,
|
||||
"read(): underlying QIODevice is not open");
|
||||
}
|
||||
|
||||
actualSize = (uint32_t)std::min((qint64)len, dev_->bytesAvailable());
|
||||
readSize = dev_->read(reinterpret_cast<char*>(buf), actualSize);
|
||||
|
||||
if (readSize < 0) {
|
||||
QAbstractSocket* socket;
|
||||
if ((socket = qobject_cast<QAbstractSocket*>(dev_.get()))) {
|
||||
throw TTransportException(TTransportException::UNKNOWN,
|
||||
"Failed to read() from QAbstractSocket",
|
||||
socket->error());
|
||||
}
|
||||
throw TTransportException(TTransportException::UNKNOWN, "Failed to read from from QIODevice");
|
||||
}
|
||||
|
||||
return (uint32_t)readSize;
|
||||
}
|
||||
|
||||
void TQIODeviceTransport::write(const uint8_t* buf, uint32_t len) {
|
||||
while (len) {
|
||||
uint32_t written = write_partial(buf, len);
|
||||
len -= written;
|
||||
dev_->waitForBytesWritten(50);
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t TQIODeviceTransport::write_partial(const uint8_t* buf, uint32_t len) {
|
||||
qint64 written;
|
||||
|
||||
if (!dev_->isOpen()) {
|
||||
throw TTransportException(TTransportException::NOT_OPEN,
|
||||
"write_partial(): underlying QIODevice is not open");
|
||||
}
|
||||
|
||||
written = dev_->write(reinterpret_cast<const char*>(buf), len);
|
||||
if (written < 0) {
|
||||
QAbstractSocket* socket;
|
||||
if ((socket = qobject_cast<QAbstractSocket*>(dev_.get()))) {
|
||||
throw TTransportException(TTransportException::UNKNOWN,
|
||||
"write_partial(): failed to write to QAbstractSocket",
|
||||
socket->error());
|
||||
}
|
||||
|
||||
throw TTransportException(TTransportException::UNKNOWN,
|
||||
"write_partial(): failed to write to underlying QIODevice");
|
||||
}
|
||||
|
||||
return (uint32_t)written;
|
||||
}
|
||||
|
||||
void TQIODeviceTransport::flush() {
|
||||
if (!dev_->isOpen()) {
|
||||
throw TTransportException(TTransportException::NOT_OPEN,
|
||||
"flush(): underlying QIODevice is not open");
|
||||
}
|
||||
|
||||
QAbstractSocket* socket;
|
||||
|
||||
if ((socket = qobject_cast<QAbstractSocket*>(dev_.get()))) {
|
||||
socket->flush();
|
||||
} else {
|
||||
dev_->waitForBytesWritten(1);
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t* TQIODeviceTransport::borrow(uint8_t* buf, uint32_t* len) {
|
||||
(void)buf;
|
||||
(void)len;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void TQIODeviceTransport::consume(uint32_t len) {
|
||||
(void)len;
|
||||
throw TTransportException(TTransportException::UNKNOWN);
|
||||
}
|
||||
}
|
||||
}
|
||||
} // apache::thrift::transport
|
68
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/qt/TQIODeviceTransport.h
generated
vendored
Normal file
68
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/qt/TQIODeviceTransport.h
generated
vendored
Normal file
|
@ -0,0 +1,68 @@
|
|||
/*
|
||||
* 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_ASYNC_TQIODEVICE_TRANSPORT_H_
|
||||
#define _THRIFT_ASYNC_TQIODEVICE_TRANSPORT_H_ 1
|
||||
|
||||
#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
|
||||
|
||||
#endif // #ifndef _THRIFT_ASYNC_TQIODEVICE_TRANSPORT_H_
|
150
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/qt/TQTcpServer.cpp
generated
vendored
Normal file
150
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/qt/TQTcpServer.cpp
generated
vendored
Normal file
|
@ -0,0 +1,150 @@
|
|||
/*
|
||||
* 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/qt/TQTcpServer.h>
|
||||
#include <thrift/qt/TQIODeviceTransport.h>
|
||||
|
||||
#include <QMetaType>
|
||||
#include <QTcpSocket>
|
||||
|
||||
#include <thrift/cxxfunctional.h>
|
||||
|
||||
#include <thrift/protocol/TProtocol.h>
|
||||
#include <thrift/async/TAsyncProcessor.h>
|
||||
|
||||
using boost::shared_ptr;
|
||||
using apache::thrift::protocol::TProtocol;
|
||||
using apache::thrift::protocol::TProtocolFactory;
|
||||
using apache::thrift::transport::TTransport;
|
||||
using apache::thrift::transport::TTransportException;
|
||||
using apache::thrift::transport::TQIODeviceTransport;
|
||||
using apache::thrift::stdcxx::function;
|
||||
using apache::thrift::stdcxx::bind;
|
||||
|
||||
QT_USE_NAMESPACE
|
||||
|
||||
namespace apache {
|
||||
namespace thrift {
|
||||
namespace async {
|
||||
|
||||
struct TQTcpServer::ConnectionContext {
|
||||
shared_ptr<QTcpSocket> connection_;
|
||||
shared_ptr<TTransport> transport_;
|
||||
shared_ptr<TProtocol> iprot_;
|
||||
shared_ptr<TProtocol> oprot_;
|
||||
|
||||
explicit ConnectionContext(shared_ptr<QTcpSocket> connection,
|
||||
shared_ptr<TTransport> transport,
|
||||
shared_ptr<TProtocol> iprot,
|
||||
shared_ptr<TProtocol> oprot)
|
||||
: connection_(connection), transport_(transport), iprot_(iprot), oprot_(oprot) {}
|
||||
};
|
||||
|
||||
TQTcpServer::TQTcpServer(shared_ptr<QTcpServer> server,
|
||||
shared_ptr<TAsyncProcessor> processor,
|
||||
shared_ptr<TProtocolFactory> pfact,
|
||||
QObject* parent)
|
||||
: QObject(parent), server_(server), processor_(processor), pfact_(pfact) {
|
||||
qRegisterMetaType<QTcpSocket*>("QTcpSocket*");
|
||||
connect(server.get(), SIGNAL(newConnection()), SLOT(processIncoming()));
|
||||
}
|
||||
|
||||
TQTcpServer::~TQTcpServer() {
|
||||
}
|
||||
|
||||
void TQTcpServer::processIncoming() {
|
||||
while (server_->hasPendingConnections()) {
|
||||
// take ownership of the QTcpSocket; technically it could be deleted
|
||||
// when the QTcpServer is destroyed, but any real app should delete this
|
||||
// class before deleting the QTcpServer that we are using
|
||||
shared_ptr<QTcpSocket> connection(server_->nextPendingConnection());
|
||||
|
||||
shared_ptr<TTransport> transport;
|
||||
shared_ptr<TProtocol> iprot;
|
||||
shared_ptr<TProtocol> oprot;
|
||||
|
||||
try {
|
||||
transport = shared_ptr<TTransport>(new TQIODeviceTransport(connection));
|
||||
iprot = shared_ptr<TProtocol>(pfact_->getProtocol(transport));
|
||||
oprot = shared_ptr<TProtocol>(pfact_->getProtocol(transport));
|
||||
} catch (...) {
|
||||
qWarning("[TQTcpServer] Failed to initialize transports/protocols");
|
||||
continue;
|
||||
}
|
||||
|
||||
ctxMap_[connection.get()]
|
||||
= shared_ptr<ConnectionContext>(new ConnectionContext(connection, transport, iprot, oprot));
|
||||
|
||||
connect(connection.get(), SIGNAL(readyRead()), SLOT(beginDecode()));
|
||||
|
||||
connect(connection.get(), SIGNAL(disconnected()), SLOT(socketClosed()));
|
||||
}
|
||||
}
|
||||
|
||||
void TQTcpServer::beginDecode() {
|
||||
QTcpSocket* connection(qobject_cast<QTcpSocket*>(sender()));
|
||||
Q_ASSERT(connection);
|
||||
|
||||
if (ctxMap_.find(connection) == ctxMap_.end()) {
|
||||
qWarning("[TQTcpServer] Got data on an unknown QTcpSocket");
|
||||
return;
|
||||
}
|
||||
|
||||
shared_ptr<ConnectionContext> ctx = ctxMap_[connection];
|
||||
|
||||
try {
|
||||
processor_
|
||||
->process(bind(&TQTcpServer::finish, this, ctx, apache::thrift::stdcxx::placeholders::_1),
|
||||
ctx->iprot_,
|
||||
ctx->oprot_);
|
||||
} catch (const TTransportException& ex) {
|
||||
qWarning("[TQTcpServer] TTransportException during processing: '%s'", ex.what());
|
||||
scheduleDeleteConnectionContext(connection);
|
||||
} catch (...) {
|
||||
qWarning("[TQTcpServer] Unknown processor exception");
|
||||
scheduleDeleteConnectionContext(connection);
|
||||
}
|
||||
}
|
||||
|
||||
void TQTcpServer::socketClosed() {
|
||||
QTcpSocket* connection(qobject_cast<QTcpSocket*>(sender()));
|
||||
Q_ASSERT(connection);
|
||||
scheduleDeleteConnectionContext(connection);
|
||||
}
|
||||
|
||||
void TQTcpServer::deleteConnectionContext(QTcpSocket* connection) {
|
||||
const ConnectionContextMap::size_type deleted = ctxMap_.erase(connection);
|
||||
if (0 == deleted) {
|
||||
qWarning("[TQTcpServer] Unknown QTcpSocket");
|
||||
}
|
||||
}
|
||||
|
||||
void TQTcpServer::scheduleDeleteConnectionContext(QTcpSocket* connection) {
|
||||
QMetaObject::invokeMethod(this, "deleteConnectionContext", Qt::QueuedConnection, Q_ARG(QTcpSocket*, connection));
|
||||
}
|
||||
|
||||
void TQTcpServer::finish(shared_ptr<ConnectionContext> ctx, bool healthy) {
|
||||
if (!healthy) {
|
||||
qWarning("[TQTcpServer] Processor failed to process data successfully");
|
||||
deleteConnectionContext(ctx->connection_.get());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} // apache::thrift::async
|
81
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/qt/TQTcpServer.h
generated
vendored
Normal file
81
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/qt/TQTcpServer.h
generated
vendored
Normal file
|
@ -0,0 +1,81 @@
|
|||
/*
|
||||
* 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_TASYNC_QTCP_SERVER_H_
|
||||
#define _THRIFT_TASYNC_QTCP_SERVER_H_
|
||||
|
||||
#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,
|
||||
QObject* parent = NULL);
|
||||
virtual ~TQTcpServer();
|
||||
|
||||
private Q_SLOTS:
|
||||
void processIncoming();
|
||||
void beginDecode();
|
||||
void socketClosed();
|
||||
void deleteConnectionContext(QTcpSocket* connection);
|
||||
|
||||
private:
|
||||
Q_DISABLE_COPY(TQTcpServer)
|
||||
|
||||
struct ConnectionContext;
|
||||
|
||||
void scheduleDeleteConnectionContext(QTcpSocket* connection);
|
||||
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_;
|
||||
|
||||
typedef std::map<QTcpSocket*, boost::shared_ptr<ConnectionContext> > ConnectionContextMap;
|
||||
ConnectionContextMap ctxMap_;
|
||||
};
|
||||
}
|
||||
}
|
||||
} // apache::thrift::async
|
||||
|
||||
#endif // #ifndef _THRIFT_TASYNC_QTCP_SERVER_H_
|
123
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/server/TConnectedClient.cpp
generated
vendored
Normal file
123
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/server/TConnectedClient.cpp
generated
vendored
Normal file
|
@ -0,0 +1,123 @@
|
|||
/*
|
||||
* 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/TConnectedClient.h>
|
||||
|
||||
namespace apache {
|
||||
namespace thrift {
|
||||
namespace server {
|
||||
|
||||
using apache::thrift::TProcessor;
|
||||
using apache::thrift::protocol::TProtocol;
|
||||
using apache::thrift::server::TServerEventHandler;
|
||||
using apache::thrift::transport::TTransport;
|
||||
using apache::thrift::transport::TTransportException;
|
||||
using boost::shared_ptr;
|
||||
using std::string;
|
||||
|
||||
TConnectedClient::TConnectedClient(const shared_ptr<TProcessor>& processor,
|
||||
const shared_ptr<TProtocol>& inputProtocol,
|
||||
const shared_ptr<TProtocol>& outputProtocol,
|
||||
const shared_ptr<TServerEventHandler>& eventHandler,
|
||||
const shared_ptr<TTransport>& client)
|
||||
|
||||
: processor_(processor),
|
||||
inputProtocol_(inputProtocol),
|
||||
outputProtocol_(outputProtocol),
|
||||
eventHandler_(eventHandler),
|
||||
client_(client),
|
||||
opaqueContext_(0) {
|
||||
}
|
||||
|
||||
TConnectedClient::~TConnectedClient() {
|
||||
}
|
||||
|
||||
void TConnectedClient::run() {
|
||||
if (eventHandler_) {
|
||||
opaqueContext_ = eventHandler_->createContext(inputProtocol_, outputProtocol_);
|
||||
}
|
||||
|
||||
for (bool done = false; !done;) {
|
||||
if (eventHandler_) {
|
||||
eventHandler_->processContext(opaqueContext_, client_);
|
||||
}
|
||||
|
||||
try {
|
||||
if (!processor_->process(inputProtocol_, outputProtocol_, opaqueContext_)) {
|
||||
break;
|
||||
}
|
||||
} catch (const TTransportException& ttx) {
|
||||
switch (ttx.getType()) {
|
||||
case TTransportException::END_OF_FILE:
|
||||
case TTransportException::INTERRUPTED:
|
||||
case TTransportException::TIMED_OUT:
|
||||
// Client disconnected or was interrupted or did not respond within the receive timeout.
|
||||
// No logging needed. Done.
|
||||
done = true;
|
||||
break;
|
||||
|
||||
default: {
|
||||
// All other transport exceptions are logged.
|
||||
// State of connection is unknown. Done.
|
||||
string errStr = string("TConnectedClient died: ") + ttx.what();
|
||||
GlobalOutput(errStr.c_str());
|
||||
done = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} catch (const TException& tex) {
|
||||
string errStr = string("TConnectedClient processing exception: ") + tex.what();
|
||||
GlobalOutput(errStr.c_str());
|
||||
// Disconnect from client, because we could not process the message.
|
||||
done = true;
|
||||
}
|
||||
}
|
||||
|
||||
cleanup();
|
||||
}
|
||||
|
||||
void TConnectedClient::cleanup() {
|
||||
if (eventHandler_) {
|
||||
eventHandler_->deleteContext(opaqueContext_, inputProtocol_, outputProtocol_);
|
||||
}
|
||||
|
||||
try {
|
||||
inputProtocol_->getTransport()->close();
|
||||
} catch (const TTransportException& ttx) {
|
||||
string errStr = string("TConnectedClient input close failed: ") + ttx.what();
|
||||
GlobalOutput(errStr.c_str());
|
||||
}
|
||||
|
||||
try {
|
||||
outputProtocol_->getTransport()->close();
|
||||
} catch (const TTransportException& ttx) {
|
||||
string errStr = string("TConnectedClient output close failed: ") + ttx.what();
|
||||
GlobalOutput(errStr.c_str());
|
||||
}
|
||||
|
||||
try {
|
||||
client_->close();
|
||||
} catch (const TTransportException& ttx) {
|
||||
string errStr = string("TConnectedClient client close failed: ") + ttx.what();
|
||||
GlobalOutput(errStr.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} // apache::thrift::server
|
110
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/server/TConnectedClient.h
generated
vendored
Normal file
110
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/server/TConnectedClient.h
generated
vendored
Normal file
|
@ -0,0 +1,110 @@
|
|||
/*
|
||||
* 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_SERVER_TCONNECTEDCLIENT_H_
|
||||
#define _THRIFT_SERVER_TCONNECTEDCLIENT_H_ 1
|
||||
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <thrift/TProcessor.h>
|
||||
#include <thrift/protocol/TProtocol.h>
|
||||
#include <thrift/server/TServer.h>
|
||||
#include <thrift/transport/TTransport.h>
|
||||
|
||||
namespace apache {
|
||||
namespace thrift {
|
||||
namespace server {
|
||||
|
||||
/**
|
||||
* This represents a client connected to a TServer. The
|
||||
* processing loop for a client must provide some required
|
||||
* functionality common to all implementations so it is
|
||||
* encapsulated here.
|
||||
*/
|
||||
|
||||
class TConnectedClient : public apache::thrift::concurrency::Runnable {
|
||||
public:
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param[in] processor the TProcessor
|
||||
* @param[in] inputProtocol the input TProtocol
|
||||
* @param[in] outputProtocol the output TProtocol
|
||||
* @param[in] eventHandler the server event handler
|
||||
* @param[in] client the TTransport representing the client
|
||||
*/
|
||||
TConnectedClient(
|
||||
const boost::shared_ptr<apache::thrift::TProcessor>& processor,
|
||||
const boost::shared_ptr<apache::thrift::protocol::TProtocol>& inputProtocol,
|
||||
const boost::shared_ptr<apache::thrift::protocol::TProtocol>& outputProtocol,
|
||||
const boost::shared_ptr<apache::thrift::server::TServerEventHandler>& eventHandler,
|
||||
const boost::shared_ptr<apache::thrift::transport::TTransport>& client);
|
||||
|
||||
/**
|
||||
* Destructor.
|
||||
*/
|
||||
virtual ~TConnectedClient();
|
||||
|
||||
/**
|
||||
* Drive the client until it is done.
|
||||
* The client processing loop is:
|
||||
*
|
||||
* [optional] call eventHandler->createContext once
|
||||
* [optional] call eventHandler->processContext per request
|
||||
* call processor->process per request
|
||||
* handle expected transport exceptions:
|
||||
* END_OF_FILE means the client is gone
|
||||
* INTERRUPTED means the client was interrupted
|
||||
* by TServerTransport::interruptChildren()
|
||||
* handle unexpected transport exceptions by logging
|
||||
* handle standard exceptions by logging
|
||||
* handle unexpected exceptions by logging
|
||||
* cleanup()
|
||||
*/
|
||||
virtual void run() /* override */;
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Cleanup after a client. This happens if the client disconnects,
|
||||
* or if the server is stopped, or if an exception occurs.
|
||||
*
|
||||
* The cleanup processing is:
|
||||
* [optional] call eventHandler->deleteContext once
|
||||
* close the inputProtocol's TTransport
|
||||
* close the outputProtocol's TTransport
|
||||
* close the client
|
||||
*/
|
||||
virtual void cleanup();
|
||||
|
||||
private:
|
||||
boost::shared_ptr<apache::thrift::TProcessor> processor_;
|
||||
boost::shared_ptr<apache::thrift::protocol::TProtocol> inputProtocol_;
|
||||
boost::shared_ptr<apache::thrift::protocol::TProtocol> outputProtocol_;
|
||||
boost::shared_ptr<apache::thrift::server::TServerEventHandler> eventHandler_;
|
||||
boost::shared_ptr<apache::thrift::transport::TTransport> client_;
|
||||
|
||||
/**
|
||||
* Context acquired from the eventHandler_ if one exists.
|
||||
*/
|
||||
void* opaqueContext_;
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // #ifndef _THRIFT_SERVER_TCONNECTEDCLIENT_H_
|
1625
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/server/TNonblockingServer.cpp
generated
vendored
Normal file
1625
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/server/TNonblockingServer.cpp
generated
vendored
Normal file
File diff suppressed because it is too large
Load diff
877
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/server/TNonblockingServer.h
generated
vendored
Normal file
877
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/server/TNonblockingServer.h
generated
vendored
Normal file
|
@ -0,0 +1,877 @@
|
|||
/*
|
||||
* 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_SERVER_TNONBLOCKINGSERVER_H_
|
||||
#define _THRIFT_SERVER_TNONBLOCKINGSERVER_H_ 1
|
||||
|
||||
#include <thrift/Thrift.h>
|
||||
#include <thrift/server/TServer.h>
|
||||
#include <thrift/transport/PlatformSocket.h>
|
||||
#include <thrift/transport/TBufferTransports.h>
|
||||
#include <thrift/transport/TSocket.h>
|
||||
#include <thrift/concurrency/ThreadManager.h>
|
||||
#include <climits>
|
||||
#include <thrift/concurrency/Thread.h>
|
||||
#include <thrift/concurrency/PlatformThreadFactory.h>
|
||||
#include <thrift/concurrency/Mutex.h>
|
||||
#include <stack>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <cstdlib>
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#include <event.h>
|
||||
#include <event2/event_compat.h>
|
||||
#include <event2/event_struct.h>
|
||||
|
||||
namespace apache {
|
||||
namespace thrift {
|
||||
namespace server {
|
||||
|
||||
using apache::thrift::transport::TMemoryBuffer;
|
||||
using apache::thrift::transport::TSocket;
|
||||
using apache::thrift::protocol::TProtocol;
|
||||
using apache::thrift::concurrency::Runnable;
|
||||
using apache::thrift::concurrency::ThreadManager;
|
||||
using apache::thrift::concurrency::PlatformThreadFactory;
|
||||
using apache::thrift::concurrency::ThreadFactory;
|
||||
using apache::thrift::concurrency::Thread;
|
||||
using apache::thrift::concurrency::Mutex;
|
||||
using apache::thrift::concurrency::Guard;
|
||||
|
||||
#ifdef LIBEVENT_VERSION_NUMBER
|
||||
#define LIBEVENT_VERSION_MAJOR (LIBEVENT_VERSION_NUMBER >> 24)
|
||||
#define LIBEVENT_VERSION_MINOR ((LIBEVENT_VERSION_NUMBER >> 16) & 0xFF)
|
||||
#define LIBEVENT_VERSION_REL ((LIBEVENT_VERSION_NUMBER >> 8) & 0xFF)
|
||||
#else
|
||||
// assume latest version 1 series
|
||||
#define LIBEVENT_VERSION_MAJOR 1
|
||||
#define LIBEVENT_VERSION_MINOR 14
|
||||
#define LIBEVENT_VERSION_REL 13
|
||||
#define LIBEVENT_VERSION_NUMBER \
|
||||
((LIBEVENT_VERSION_MAJOR << 24) | (LIBEVENT_VERSION_MINOR << 16) | (LIBEVENT_VERSION_REL << 8))
|
||||
#endif
|
||||
|
||||
#if LIBEVENT_VERSION_NUMBER < 0x02000000
|
||||
typedef THRIFT_SOCKET evutil_socket_t;
|
||||
#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);
|
||||
}
|
||||
|
||||
/**
|
||||
* This is a non-blocking server in C++ for high performance that
|
||||
* operates a set of IO threads (by default only one). It assumes that
|
||||
* all incoming requests are framed with a 4 byte length indicator and
|
||||
* writes out responses using the same framing.
|
||||
*
|
||||
* It does not use the TServerTransport framework, but rather has socket
|
||||
* operations hardcoded for use with select.
|
||||
*
|
||||
*/
|
||||
|
||||
/// Overload condition actions.
|
||||
enum TOverloadAction {
|
||||
T_OVERLOAD_NO_ACTION, ///< Don't handle overload */
|
||||
T_OVERLOAD_CLOSE_ON_ACCEPT, ///< Drop new connections immediately */
|
||||
T_OVERLOAD_DRAIN_TASK_QUEUE ///< Drop some tasks from head of task queue */
|
||||
};
|
||||
|
||||
class TNonblockingIOThread;
|
||||
|
||||
class TNonblockingServer : public TServer {
|
||||
private:
|
||||
class TConnection;
|
||||
|
||||
friend class TNonblockingIOThread;
|
||||
|
||||
private:
|
||||
/// Listen backlog
|
||||
static const int LISTEN_BACKLOG = 1024;
|
||||
|
||||
/// Default limit on size of idle connection pool
|
||||
static const size_t CONNECTION_STACK_LIMIT = 1024;
|
||||
|
||||
/// Default limit on frame size
|
||||
static const int MAX_FRAME_SIZE = 256 * 1024 * 1024;
|
||||
|
||||
/// Default limit on total number of connected sockets
|
||||
static const int MAX_CONNECTIONS = INT_MAX;
|
||||
|
||||
/// Default limit on connections in handler/task processing
|
||||
static const int MAX_ACTIVE_PROCESSORS = INT_MAX;
|
||||
|
||||
/// Default size of write buffer
|
||||
static const int WRITE_BUFFER_DEFAULT_SIZE = 1024;
|
||||
|
||||
/// Maximum size of read buffer allocated to idle connection (0 = unlimited)
|
||||
static const int IDLE_READ_BUFFER_LIMIT = 1024;
|
||||
|
||||
/// Maximum size of write buffer allocated to idle connection (0 = unlimited)
|
||||
static const int IDLE_WRITE_BUFFER_LIMIT = 1024;
|
||||
|
||||
/// # of calls before resizing oversized buffers (0 = check only on close)
|
||||
static const int RESIZE_BUFFER_EVERY_N = 512;
|
||||
|
||||
/// # of IO threads to use by default
|
||||
static const int DEFAULT_IO_THREADS = 1;
|
||||
|
||||
/// # of IO threads this server will use
|
||||
size_t numIOThreads_;
|
||||
|
||||
/// Whether to set high scheduling priority for IO threads
|
||||
bool useHighPriorityIOThreads_;
|
||||
|
||||
/// Server socket file descriptor
|
||||
THRIFT_SOCKET serverSocket_;
|
||||
|
||||
/// Port server runs on. Zero when letting OS decide actual port
|
||||
int port_;
|
||||
|
||||
/// Port server actually runs on
|
||||
int listenPort_;
|
||||
|
||||
/// The optional user-provided event-base (for single-thread servers)
|
||||
event_base* userEventBase_;
|
||||
|
||||
/// For processing via thread pool, may be NULL
|
||||
boost::shared_ptr<ThreadManager> threadManager_;
|
||||
|
||||
/// Is thread pool processing?
|
||||
bool threadPoolProcessing_;
|
||||
|
||||
// Factory to create the IO threads
|
||||
boost::shared_ptr<PlatformThreadFactory> ioThreadFactory_;
|
||||
|
||||
// Vector of IOThread objects that will handle our IO
|
||||
std::vector<boost::shared_ptr<TNonblockingIOThread> > ioThreads_;
|
||||
|
||||
// Index of next IO Thread to be used (for round-robin)
|
||||
uint32_t nextIOThread_;
|
||||
|
||||
// Synchronizes access to connection stack and similar data
|
||||
Mutex connMutex_;
|
||||
|
||||
/// Number of TConnection object we've created
|
||||
size_t numTConnections_;
|
||||
|
||||
/// Number of Connections processing or waiting to process
|
||||
size_t numActiveProcessors_;
|
||||
|
||||
/// Limit for how many TConnection objects to cache
|
||||
size_t connectionStackLimit_;
|
||||
|
||||
/// Limit for number of connections processing or waiting to process
|
||||
size_t maxActiveProcessors_;
|
||||
|
||||
/// Limit for number of open connections
|
||||
size_t maxConnections_;
|
||||
|
||||
/// Limit for frame size
|
||||
size_t maxFrameSize_;
|
||||
|
||||
/// Time in milliseconds before an unperformed task expires (0 == infinite).
|
||||
int64_t taskExpireTime_;
|
||||
|
||||
/**
|
||||
* Hysteresis for overload state. This is the fraction of the overload
|
||||
* value that needs to be reached before the overload state is cleared;
|
||||
* must be <= 1.0.
|
||||
*/
|
||||
double overloadHysteresis_;
|
||||
|
||||
/// Action to take when we're overloaded.
|
||||
TOverloadAction overloadAction_;
|
||||
|
||||
/**
|
||||
* The write buffer is initialized (and when idleWriteBufferLimit_ is checked
|
||||
* and found to be exceeded, reinitialized) to this size.
|
||||
*/
|
||||
size_t writeBufferDefaultSize_;
|
||||
|
||||
/**
|
||||
* Max read buffer size for an idle TConnection. When we place an idle
|
||||
* TConnection into connectionStack_ or on every resizeBufferEveryN_ calls,
|
||||
* we will free the buffer (such that it will be reinitialized by the next
|
||||
* received frame) if it has exceeded this limit. 0 disables this check.
|
||||
*/
|
||||
size_t idleReadBufferLimit_;
|
||||
|
||||
/**
|
||||
* Max write buffer size for an idle connection. When we place an idle
|
||||
* TConnection into connectionStack_ or on every resizeBufferEveryN_ calls,
|
||||
* we insure that its write buffer is <= to this size; otherwise we
|
||||
* replace it with a new one of writeBufferDefaultSize_ bytes to insure that
|
||||
* idle connections don't hog memory. 0 disables this check.
|
||||
*/
|
||||
size_t idleWriteBufferLimit_;
|
||||
|
||||
/**
|
||||
* Every N calls we check the buffer size limits on a connected TConnection.
|
||||
* 0 disables (i.e. the checks are only done when a connection closes).
|
||||
*/
|
||||
int32_t resizeBufferEveryN_;
|
||||
|
||||
/// Set if we are currently in an overloaded state.
|
||||
bool overloaded_;
|
||||
|
||||
/// Count of connections dropped since overload started
|
||||
uint32_t nConnectionsDropped_;
|
||||
|
||||
/// Count of connections dropped on overload since server started
|
||||
uint64_t nTotalConnectionsDropped_;
|
||||
|
||||
/**
|
||||
* This is a stack of all the objects that have been created but that
|
||||
* are NOT currently in use. When we close a connection, we place it on this
|
||||
* stack so that the object can be reused later, rather than freeing the
|
||||
* memory and reallocating a new object later.
|
||||
*/
|
||||
std::stack<TConnection*> connectionStack_;
|
||||
|
||||
/**
|
||||
* This container holds pointers to all active connections. This container
|
||||
* allows the server to clean up unlcosed connection objects at destruction,
|
||||
* which in turn allows their transports, protocols, processors and handlers
|
||||
* to deallocate and clean up correctly.
|
||||
*/
|
||||
std::vector<TConnection*> activeConnections_;
|
||||
|
||||
/**
|
||||
* Called when server socket had something happen. We accept all waiting
|
||||
* client connections on listen socket fd and assign TConnection objects
|
||||
* to handle those requests.
|
||||
*
|
||||
* @param fd the listen socket.
|
||||
* @param which the event flag that triggered the handler.
|
||||
*/
|
||||
void handleEvent(THRIFT_SOCKET fd, short which);
|
||||
|
||||
void init(int port) {
|
||||
serverSocket_ = THRIFT_INVALID_SOCKET;
|
||||
numIOThreads_ = DEFAULT_IO_THREADS;
|
||||
nextIOThread_ = 0;
|
||||
useHighPriorityIOThreads_ = false;
|
||||
port_ = port;
|
||||
listenPort_ = port;
|
||||
userEventBase_ = NULL;
|
||||
threadPoolProcessing_ = false;
|
||||
numTConnections_ = 0;
|
||||
numActiveProcessors_ = 0;
|
||||
connectionStackLimit_ = CONNECTION_STACK_LIMIT;
|
||||
maxActiveProcessors_ = MAX_ACTIVE_PROCESSORS;
|
||||
maxConnections_ = MAX_CONNECTIONS;
|
||||
maxFrameSize_ = MAX_FRAME_SIZE;
|
||||
taskExpireTime_ = 0;
|
||||
overloadHysteresis_ = 0.8;
|
||||
overloadAction_ = T_OVERLOAD_NO_ACTION;
|
||||
writeBufferDefaultSize_ = WRITE_BUFFER_DEFAULT_SIZE;
|
||||
idleReadBufferLimit_ = IDLE_READ_BUFFER_LIMIT;
|
||||
idleWriteBufferLimit_ = IDLE_WRITE_BUFFER_LIMIT;
|
||||
resizeBufferEveryN_ = RESIZE_BUFFER_EVERY_N;
|
||||
overloaded_ = false;
|
||||
nConnectionsDropped_ = 0;
|
||||
nTotalConnectionsDropped_ = 0;
|
||||
}
|
||||
|
||||
public:
|
||||
TNonblockingServer(const boost::shared_ptr<TProcessorFactory>& processorFactory, int port)
|
||||
: TServer(processorFactory) {
|
||||
init(port);
|
||||
}
|
||||
|
||||
TNonblockingServer(const boost::shared_ptr<TProcessor>& processor, int port)
|
||||
: TServer(processor) {
|
||||
init(port);
|
||||
}
|
||||
|
||||
TNonblockingServer(const boost::shared_ptr<TProcessorFactory>& processorFactory,
|
||||
const boost::shared_ptr<TProtocolFactory>& protocolFactory,
|
||||
int port,
|
||||
const boost::shared_ptr<ThreadManager>& threadManager
|
||||
= boost::shared_ptr<ThreadManager>())
|
||||
: TServer(processorFactory) {
|
||||
|
||||
init(port);
|
||||
|
||||
setInputProtocolFactory(protocolFactory);
|
||||
setOutputProtocolFactory(protocolFactory);
|
||||
setThreadManager(threadManager);
|
||||
}
|
||||
|
||||
TNonblockingServer(const boost::shared_ptr<TProcessor>& processor,
|
||||
const boost::shared_ptr<TProtocolFactory>& protocolFactory,
|
||||
int port,
|
||||
const boost::shared_ptr<ThreadManager>& threadManager
|
||||
= boost::shared_ptr<ThreadManager>())
|
||||
: TServer(processor) {
|
||||
|
||||
init(port);
|
||||
|
||||
setInputProtocolFactory(protocolFactory);
|
||||
setOutputProtocolFactory(protocolFactory);
|
||||
setThreadManager(threadManager);
|
||||
}
|
||||
|
||||
TNonblockingServer(const boost::shared_ptr<TProcessorFactory>& processorFactory,
|
||||
const boost::shared_ptr<TTransportFactory>& inputTransportFactory,
|
||||
const boost::shared_ptr<TTransportFactory>& outputTransportFactory,
|
||||
const boost::shared_ptr<TProtocolFactory>& inputProtocolFactory,
|
||||
const boost::shared_ptr<TProtocolFactory>& outputProtocolFactory,
|
||||
int port,
|
||||
const boost::shared_ptr<ThreadManager>& threadManager
|
||||
= boost::shared_ptr<ThreadManager>())
|
||||
: TServer(processorFactory) {
|
||||
|
||||
init(port);
|
||||
|
||||
setInputTransportFactory(inputTransportFactory);
|
||||
setOutputTransportFactory(outputTransportFactory);
|
||||
setInputProtocolFactory(inputProtocolFactory);
|
||||
setOutputProtocolFactory(outputProtocolFactory);
|
||||
setThreadManager(threadManager);
|
||||
}
|
||||
|
||||
TNonblockingServer(const boost::shared_ptr<TProcessor>& processor,
|
||||
const boost::shared_ptr<TTransportFactory>& inputTransportFactory,
|
||||
const boost::shared_ptr<TTransportFactory>& outputTransportFactory,
|
||||
const boost::shared_ptr<TProtocolFactory>& inputProtocolFactory,
|
||||
const boost::shared_ptr<TProtocolFactory>& outputProtocolFactory,
|
||||
int port,
|
||||
const boost::shared_ptr<ThreadManager>& threadManager
|
||||
= boost::shared_ptr<ThreadManager>())
|
||||
: TServer(processor) {
|
||||
|
||||
init(port);
|
||||
|
||||
setInputTransportFactory(inputTransportFactory);
|
||||
setOutputTransportFactory(outputTransportFactory);
|
||||
setInputProtocolFactory(inputProtocolFactory);
|
||||
setOutputProtocolFactory(outputProtocolFactory);
|
||||
setThreadManager(threadManager);
|
||||
}
|
||||
|
||||
~TNonblockingServer();
|
||||
|
||||
void setThreadManager(boost::shared_ptr<ThreadManager> threadManager);
|
||||
|
||||
int getListenPort() { return listenPort_; }
|
||||
|
||||
boost::shared_ptr<ThreadManager> getThreadManager() { return threadManager_; }
|
||||
|
||||
/**
|
||||
* Sets the number of IO threads used by this server. Can only be used before
|
||||
* the call to serve() and has no effect afterwards. We always use a
|
||||
* PosixThreadFactory for the IO worker threads, because they must joinable
|
||||
* for clean shutdown.
|
||||
*/
|
||||
void setNumIOThreads(size_t numThreads) {
|
||||
numIOThreads_ = numThreads;
|
||||
// User-provided event-base doesn't works for multi-threaded servers
|
||||
assert(numIOThreads_ <= 1 || !userEventBase_);
|
||||
}
|
||||
|
||||
/** Return whether the IO threads will get high scheduling priority */
|
||||
bool useHighPriorityIOThreads() const { return useHighPriorityIOThreads_; }
|
||||
|
||||
/** Set whether the IO threads will get high scheduling priority. */
|
||||
void setUseHighPriorityIOThreads(bool val) { useHighPriorityIOThreads_ = val; }
|
||||
|
||||
/** Return the number of IO threads used by this server. */
|
||||
size_t getNumIOThreads() const { return numIOThreads_; }
|
||||
|
||||
/**
|
||||
* Get the maximum number of unused TConnection we will hold in reserve.
|
||||
*
|
||||
* @return the current limit on TConnection pool size.
|
||||
*/
|
||||
size_t getConnectionStackLimit() const { return connectionStackLimit_; }
|
||||
|
||||
/**
|
||||
* Set the maximum number of unused TConnection we will hold in reserve.
|
||||
*
|
||||
* @param sz the new limit for TConnection pool size.
|
||||
*/
|
||||
void setConnectionStackLimit(size_t sz) { connectionStackLimit_ = sz; }
|
||||
|
||||
bool isThreadPoolProcessing() const { return threadPoolProcessing_; }
|
||||
|
||||
void addTask(boost::shared_ptr<Runnable> task) {
|
||||
threadManager_->add(task, 0LL, taskExpireTime_);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the count of sockets currently connected to.
|
||||
*
|
||||
* @return count of connected sockets.
|
||||
*/
|
||||
size_t getNumConnections() const { return numTConnections_; }
|
||||
|
||||
/**
|
||||
* Return the count of sockets currently connected to.
|
||||
*
|
||||
* @return count of connected sockets.
|
||||
*/
|
||||
size_t getNumActiveConnections() const { return getNumConnections() - getNumIdleConnections(); }
|
||||
|
||||
/**
|
||||
* Return the count of connection objects allocated but not in use.
|
||||
*
|
||||
* @return count of idle connection objects.
|
||||
*/
|
||||
size_t getNumIdleConnections() const { return connectionStack_.size(); }
|
||||
|
||||
/**
|
||||
* Return count of number of connections which are currently processing.
|
||||
* This is defined as a connection where all data has been received and
|
||||
* either assigned a task (when threading) or passed to a handler (when
|
||||
* not threading), and where the handler has not yet returned.
|
||||
*
|
||||
* @return # of connections currently processing.
|
||||
*/
|
||||
size_t getNumActiveProcessors() const { return numActiveProcessors_; }
|
||||
|
||||
/// Increment the count of connections currently processing.
|
||||
void incrementActiveProcessors() {
|
||||
Guard g(connMutex_);
|
||||
++numActiveProcessors_;
|
||||
}
|
||||
|
||||
/// Decrement the count of connections currently processing.
|
||||
void decrementActiveProcessors() {
|
||||
Guard g(connMutex_);
|
||||
if (numActiveProcessors_ > 0) {
|
||||
--numActiveProcessors_;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the maximum # of connections allowed before overload.
|
||||
*
|
||||
* @return current setting.
|
||||
*/
|
||||
size_t getMaxConnections() const { return maxConnections_; }
|
||||
|
||||
/**
|
||||
* Set the maximum # of connections allowed before overload.
|
||||
*
|
||||
* @param maxConnections new setting for maximum # of connections.
|
||||
*/
|
||||
void setMaxConnections(size_t maxConnections) { maxConnections_ = maxConnections; }
|
||||
|
||||
/**
|
||||
* Get the maximum # of connections waiting in handler/task before overload.
|
||||
*
|
||||
* @return current setting.
|
||||
*/
|
||||
size_t getMaxActiveProcessors() const { return maxActiveProcessors_; }
|
||||
|
||||
/**
|
||||
* Set the maximum # of connections waiting in handler/task before overload.
|
||||
*
|
||||
* @param maxActiveProcessors new setting for maximum # of active processes.
|
||||
*/
|
||||
void setMaxActiveProcessors(size_t maxActiveProcessors) {
|
||||
maxActiveProcessors_ = maxActiveProcessors;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the maximum allowed frame size.
|
||||
*
|
||||
* If a client tries to send a message larger than this limit,
|
||||
* its connection will be closed.
|
||||
*
|
||||
* @return Maxium frame size, in bytes.
|
||||
*/
|
||||
size_t getMaxFrameSize() const { return maxFrameSize_; }
|
||||
|
||||
/**
|
||||
* Set the maximum allowed frame size.
|
||||
*
|
||||
* @param maxFrameSize The new maximum frame size.
|
||||
*/
|
||||
void setMaxFrameSize(size_t maxFrameSize) { maxFrameSize_ = maxFrameSize; }
|
||||
|
||||
/**
|
||||
* Get fraction of maximum limits before an overload condition is cleared.
|
||||
*
|
||||
* @return hysteresis fraction
|
||||
*/
|
||||
double getOverloadHysteresis() const { return overloadHysteresis_; }
|
||||
|
||||
/**
|
||||
* Set fraction of maximum limits before an overload condition is cleared.
|
||||
* A good value would probably be between 0.5 and 0.9.
|
||||
*
|
||||
* @param hysteresisFraction fraction <= 1.0.
|
||||
*/
|
||||
void setOverloadHysteresis(double hysteresisFraction) {
|
||||
if (hysteresisFraction <= 1.0 && hysteresisFraction > 0.0) {
|
||||
overloadHysteresis_ = hysteresisFraction;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the action the server will take on overload.
|
||||
*
|
||||
* @return a TOverloadAction enum value for the currently set action.
|
||||
*/
|
||||
TOverloadAction getOverloadAction() const { return overloadAction_; }
|
||||
|
||||
/**
|
||||
* Set the action the server is to take on overload.
|
||||
*
|
||||
* @param overloadAction a TOverloadAction enum value for the action.
|
||||
*/
|
||||
void setOverloadAction(TOverloadAction overloadAction) { overloadAction_ = overloadAction; }
|
||||
|
||||
/**
|
||||
* Get the time in milliseconds after which a task expires (0 == infinite).
|
||||
*
|
||||
* @return a 64-bit time in milliseconds.
|
||||
*/
|
||||
int64_t getTaskExpireTime() const { return taskExpireTime_; }
|
||||
|
||||
/**
|
||||
* Set the time in milliseconds after which a task expires (0 == infinite).
|
||||
*
|
||||
* @param taskExpireTime a 64-bit time in milliseconds.
|
||||
*/
|
||||
void setTaskExpireTime(int64_t taskExpireTime) { taskExpireTime_ = taskExpireTime; }
|
||||
|
||||
/**
|
||||
* Determine if the server is currently overloaded.
|
||||
* This function checks the maximums for open connections and connections
|
||||
* currently in processing, and sets an overload condition if they are
|
||||
* exceeded. The overload will persist until both values are below the
|
||||
* current hysteresis fraction of their maximums.
|
||||
*
|
||||
* @return true if an overload condition exists, false if not.
|
||||
*/
|
||||
bool serverOverloaded();
|
||||
|
||||
/** Pop and discard next task on threadpool wait queue.
|
||||
*
|
||||
* @return true if a task was discarded, false if the wait queue was empty.
|
||||
*/
|
||||
bool drainPendingTask();
|
||||
|
||||
/**
|
||||
* Get the starting size of a TConnection object's write buffer.
|
||||
*
|
||||
* @return # bytes we initialize a TConnection object's write buffer to.
|
||||
*/
|
||||
size_t getWriteBufferDefaultSize() const { return writeBufferDefaultSize_; }
|
||||
|
||||
/**
|
||||
* Set the starting size of a TConnection object's write buffer.
|
||||
*
|
||||
* @param size # bytes we initialize a TConnection object's write buffer to.
|
||||
*/
|
||||
void setWriteBufferDefaultSize(size_t size) { writeBufferDefaultSize_ = size; }
|
||||
|
||||
/**
|
||||
* Get the maximum size of read buffer allocated to idle TConnection objects.
|
||||
*
|
||||
* @return # bytes beyond which we will dealloc idle buffer.
|
||||
*/
|
||||
size_t getIdleReadBufferLimit() const { return idleReadBufferLimit_; }
|
||||
|
||||
/**
|
||||
* [NOTE: This is for backwards compatibility, use getIdleReadBufferLimit().]
|
||||
* Get the maximum size of read buffer allocated to idle TConnection objects.
|
||||
*
|
||||
* @return # bytes beyond which we will dealloc idle buffer.
|
||||
*/
|
||||
size_t getIdleBufferMemLimit() const { return idleReadBufferLimit_; }
|
||||
|
||||
/**
|
||||
* Set the maximum size read buffer allocated to idle TConnection objects.
|
||||
* If a TConnection object is found (either on connection close or between
|
||||
* calls when resizeBufferEveryN_ is set) with more than this much memory
|
||||
* allocated to its read buffer, we free it and allow it to be reinitialized
|
||||
* on the next received frame.
|
||||
*
|
||||
* @param limit of bytes beyond which we will shrink buffers when checked.
|
||||
*/
|
||||
void setIdleReadBufferLimit(size_t limit) { idleReadBufferLimit_ = limit; }
|
||||
|
||||
/**
|
||||
* [NOTE: This is for backwards compatibility, use setIdleReadBufferLimit().]
|
||||
* Set the maximum size read buffer allocated to idle TConnection objects.
|
||||
* If a TConnection object is found (either on connection close or between
|
||||
* calls when resizeBufferEveryN_ is set) with more than this much memory
|
||||
* allocated to its read buffer, we free it and allow it to be reinitialized
|
||||
* on the next received frame.
|
||||
*
|
||||
* @param limit of bytes beyond which we will shrink buffers when checked.
|
||||
*/
|
||||
void setIdleBufferMemLimit(size_t limit) { idleReadBufferLimit_ = limit; }
|
||||
|
||||
/**
|
||||
* Get the maximum size of write buffer allocated to idle TConnection objects.
|
||||
*
|
||||
* @return # bytes beyond which we will reallocate buffers when checked.
|
||||
*/
|
||||
size_t getIdleWriteBufferLimit() const { return idleWriteBufferLimit_; }
|
||||
|
||||
/**
|
||||
* Set the maximum size write buffer allocated to idle TConnection objects.
|
||||
* If a TConnection object is found (either on connection close or between
|
||||
* calls when resizeBufferEveryN_ is set) with more than this much memory
|
||||
* allocated to its write buffer, we destroy and construct that buffer with
|
||||
* writeBufferDefaultSize_ bytes.
|
||||
*
|
||||
* @param limit of bytes beyond which we will shrink buffers when idle.
|
||||
*/
|
||||
void setIdleWriteBufferLimit(size_t limit) { idleWriteBufferLimit_ = limit; }
|
||||
|
||||
/**
|
||||
* Get # of calls made between buffer size checks. 0 means disabled.
|
||||
*
|
||||
* @return # of calls between buffer size checks.
|
||||
*/
|
||||
int32_t getResizeBufferEveryN() const { return resizeBufferEveryN_; }
|
||||
|
||||
/**
|
||||
* Check buffer sizes every "count" calls. This allows buffer limits
|
||||
* to be enforced for persistent connections with a controllable degree
|
||||
* of overhead. 0 disables checks except at connection close.
|
||||
*
|
||||
* @param count the number of calls between checks, or 0 to disable
|
||||
*/
|
||||
void setResizeBufferEveryN(int32_t count) { resizeBufferEveryN_ = count; }
|
||||
|
||||
/**
|
||||
* Main workhorse function, starts up the server listening on a port and
|
||||
* loops over the libevent handler.
|
||||
*/
|
||||
void serve();
|
||||
|
||||
/**
|
||||
* Causes the server to terminate gracefully (can be called from any thread).
|
||||
*/
|
||||
void stop();
|
||||
|
||||
/// Creates a socket to listen on and binds it to the local port.
|
||||
void createAndListenOnSocket();
|
||||
|
||||
/**
|
||||
* Takes a socket created by createAndListenOnSocket() and sets various
|
||||
* options on it to prepare for use in the server.
|
||||
*
|
||||
* @param fd descriptor of socket to be initialized/
|
||||
*/
|
||||
void listenSocket(THRIFT_SOCKET fd);
|
||||
|
||||
/**
|
||||
* Register the optional user-provided event-base (for single-thread servers)
|
||||
*
|
||||
* This method should be used when the server is running in a single-thread
|
||||
* mode, and the event base is provided by the user (i.e., the caller).
|
||||
*
|
||||
* @param user_event_base the user-provided event-base. The user is
|
||||
* responsible for freeing the event base memory.
|
||||
*/
|
||||
void registerEvents(event_base* user_event_base);
|
||||
|
||||
/**
|
||||
* Returns the optional user-provided event-base (for single-thread servers).
|
||||
*/
|
||||
event_base* getUserEventBase() const { return userEventBase_; }
|
||||
|
||||
/** Some transports, like THeaderTransport, require passing through
|
||||
* the framing size instead of stripping it.
|
||||
*/
|
||||
bool getHeaderTransport();
|
||||
|
||||
private:
|
||||
/**
|
||||
* Callback function that the threadmanager calls when a task reaches
|
||||
* its expiration time. It is needed to clean up the expired connection.
|
||||
*
|
||||
* @param task the runnable associated with the expired task.
|
||||
*/
|
||||
void expireClose(boost::shared_ptr<Runnable> task);
|
||||
|
||||
/**
|
||||
* Return an initialized connection object. Creates or recovers from
|
||||
* pool a TConnection and initializes it with the provided socket FD
|
||||
* and flags.
|
||||
*
|
||||
* @param socket FD of socket associated with this connection.
|
||||
* @param addr the sockaddr of the client
|
||||
* @param addrLen the length of addr
|
||||
* @return pointer to initialized TConnection object.
|
||||
*/
|
||||
TConnection* createConnection(THRIFT_SOCKET socket, const sockaddr* addr, socklen_t addrLen);
|
||||
|
||||
/**
|
||||
* Returns a connection to pool or deletion. If the connection pool
|
||||
* (a stack) isn't full, place the connection object on it, otherwise
|
||||
* just delete it.
|
||||
*
|
||||
* @param connection the TConection being returned.
|
||||
*/
|
||||
void returnConnection(TConnection* connection);
|
||||
};
|
||||
|
||||
class TNonblockingIOThread : public Runnable {
|
||||
public:
|
||||
// Creates an IO thread and sets up the event base. The listenSocket should
|
||||
// be a valid FD on which listen() has already been called. If the
|
||||
// listenSocket is < 0, accepting will not be done.
|
||||
TNonblockingIOThread(TNonblockingServer* server,
|
||||
int number,
|
||||
THRIFT_SOCKET listenSocket,
|
||||
bool useHighPriority);
|
||||
|
||||
~TNonblockingIOThread();
|
||||
|
||||
// Returns the event-base for this thread.
|
||||
event_base* getEventBase() const { return eventBase_; }
|
||||
|
||||
// Returns the server for this thread.
|
||||
TNonblockingServer* getServer() const { return server_; }
|
||||
|
||||
// Returns the number of this IO thread.
|
||||
int getThreadNumber() const { return number_; }
|
||||
|
||||
// Returns the thread id associated with this object. This should
|
||||
// only be called after the thread has been started.
|
||||
Thread::id_t getThreadId() const { return threadId_; }
|
||||
|
||||
// Returns the send-fd for task complete notifications.
|
||||
evutil_socket_t getNotificationSendFD() const { return notificationPipeFDs_[1]; }
|
||||
|
||||
// Returns the read-fd for task complete notifications.
|
||||
evutil_socket_t getNotificationRecvFD() const { return notificationPipeFDs_[0]; }
|
||||
|
||||
// Returns the actual thread object associated with this IO thread.
|
||||
boost::shared_ptr<Thread> getThread() const { return thread_; }
|
||||
|
||||
// Sets the actual thread object associated with this IO thread.
|
||||
void setThread(const boost::shared_ptr<Thread>& t) { thread_ = t; }
|
||||
|
||||
// Used by TConnection objects to indicate processing has finished.
|
||||
bool notify(TNonblockingServer::TConnection* conn);
|
||||
|
||||
// Enters the event loop and does not return until a call to stop().
|
||||
virtual void run();
|
||||
|
||||
// Exits the event loop as soon as possible.
|
||||
void stop();
|
||||
|
||||
// Ensures that the event-loop thread is fully finished and shut down.
|
||||
void join();
|
||||
|
||||
/// Registers the events for the notification & listen sockets
|
||||
void registerEvents();
|
||||
|
||||
private:
|
||||
/**
|
||||
* C-callable event handler for signaling task completion. Provides a
|
||||
* callback that libevent can understand that will read a connection
|
||||
* object's address from a pipe and call connection->transition() for
|
||||
* that object.
|
||||
*
|
||||
* @param fd the descriptor the event occurred on.
|
||||
*/
|
||||
static void notifyHandler(evutil_socket_t fd, short which, void* v);
|
||||
|
||||
/**
|
||||
* C-callable event handler for listener events. Provides a callback
|
||||
* that libevent can understand which invokes server->handleEvent().
|
||||
*
|
||||
* @param fd the descriptor the event occurred on.
|
||||
* @param which the flags associated with the event.
|
||||
* @param v void* callback arg where we placed TNonblockingServer's "this".
|
||||
*/
|
||||
static void listenHandler(evutil_socket_t fd, short which, void* v) {
|
||||
((TNonblockingServer*)v)->handleEvent(fd, which);
|
||||
}
|
||||
|
||||
/// Exits the loop ASAP in case of shutdown or error.
|
||||
void breakLoop(bool error);
|
||||
|
||||
/// Create the pipe used to notify I/O process of task completion.
|
||||
void createNotificationPipe();
|
||||
|
||||
/// Unregisters our events for notification and listen sockets.
|
||||
void cleanupEvents();
|
||||
|
||||
/// Sets (or clears) high priority scheduling status for the current thread.
|
||||
void setCurrentThreadHighPriority(bool value);
|
||||
|
||||
private:
|
||||
/// associated server
|
||||
TNonblockingServer* server_;
|
||||
|
||||
/// thread number (for debugging).
|
||||
const int number_;
|
||||
|
||||
/// The actual physical thread id.
|
||||
Thread::id_t threadId_;
|
||||
|
||||
/// If listenSocket_ >= 0, adds an event on the event_base to accept conns
|
||||
THRIFT_SOCKET listenSocket_;
|
||||
|
||||
/// Sets a high scheduling priority when running
|
||||
bool useHighPriority_;
|
||||
|
||||
/// pointer to eventbase to be used for looping
|
||||
event_base* eventBase_;
|
||||
|
||||
/// Set to true if this class is responsible for freeing the event base
|
||||
/// memory.
|
||||
bool ownEventBase_;
|
||||
|
||||
/// Used with eventBase_ for connection events (only in listener thread)
|
||||
struct event serverEvent_;
|
||||
|
||||
/// Used with eventBase_ for task completion notification
|
||||
struct event notificationEvent_;
|
||||
|
||||
/// File descriptors for pipe used for task completion notification.
|
||||
evutil_socket_t notificationPipeFDs_[2];
|
||||
|
||||
/// Actual IO Thread
|
||||
boost::shared_ptr<Thread> thread_;
|
||||
};
|
||||
}
|
||||
}
|
||||
} // apache::thrift::server
|
||||
|
||||
#endif // #ifndef _THRIFT_SERVER_TNONBLOCKINGSERVER_H_
|
52
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/server/TServer.cpp
generated
vendored
Normal file
52
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/server/TServer.cpp
generated
vendored
Normal file
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
* 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>
|
||||
|
||||
#ifdef HAVE_SYS_TIME_H
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
#ifdef HAVE_SYS_RESOURCE_H
|
||||
#include <sys/resource.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
namespace apache {
|
||||
namespace thrift {
|
||||
namespace server {
|
||||
|
||||
#ifdef HAVE_SYS_RESOURCE_H
|
||||
int increase_max_fds(int max_fds = (1 << 24)) {
|
||||
struct rlimit fdmaxrl;
|
||||
|
||||
for (fdmaxrl.rlim_cur = max_fds, fdmaxrl.rlim_max = max_fds;
|
||||
max_fds && (setrlimit(RLIMIT_NOFILE, &fdmaxrl) < 0);
|
||||
fdmaxrl.rlim_cur = max_fds, fdmaxrl.rlim_max = max_fds) {
|
||||
max_fds /= 2;
|
||||
}
|
||||
|
||||
return static_cast<int>(fdmaxrl.rlim_cur);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
} // apache::thrift::server
|
273
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/server/TServer.h
generated
vendored
Normal file
273
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/server/TServer.h
generated
vendored
Normal file
|
@ -0,0 +1,273 @@
|
|||
/*
|
||||
* 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_SERVER_TSERVER_H_
|
||||
#define _THRIFT_SERVER_TSERVER_H_ 1
|
||||
|
||||
#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:
|
||||
TServer(const boost::shared_ptr<TProcessorFactory>& processorFactory)
|
||||
: processorFactory_(processorFactory) {
|
||||
setInputTransportFactory(boost::shared_ptr<TTransportFactory>(new TTransportFactory()));
|
||||
setOutputTransportFactory(boost::shared_ptr<TTransportFactory>(new TTransportFactory()));
|
||||
setInputProtocolFactory(boost::shared_ptr<TProtocolFactory>(new TBinaryProtocolFactory()));
|
||||
setOutputProtocolFactory(boost::shared_ptr<TProtocolFactory>(new TBinaryProtocolFactory()));
|
||||
}
|
||||
|
||||
TServer(const boost::shared_ptr<TProcessor>& processor)
|
||||
: processorFactory_(new TSingletonProcessorFactory(processor)) {
|
||||
setInputTransportFactory(boost::shared_ptr<TTransportFactory>(new TTransportFactory()));
|
||||
setOutputTransportFactory(boost::shared_ptr<TTransportFactory>(new TTransportFactory()));
|
||||
setInputProtocolFactory(boost::shared_ptr<TProtocolFactory>(new TBinaryProtocolFactory()));
|
||||
setOutputProtocolFactory(boost::shared_ptr<TProtocolFactory>(new TBinaryProtocolFactory()));
|
||||
}
|
||||
|
||||
TServer(const boost::shared_ptr<TProcessorFactory>& processorFactory,
|
||||
const boost::shared_ptr<TServerTransport>& serverTransport)
|
||||
: processorFactory_(processorFactory), serverTransport_(serverTransport) {
|
||||
setInputTransportFactory(boost::shared_ptr<TTransportFactory>(new TTransportFactory()));
|
||||
setOutputTransportFactory(boost::shared_ptr<TTransportFactory>(new TTransportFactory()));
|
||||
setInputProtocolFactory(boost::shared_ptr<TProtocolFactory>(new TBinaryProtocolFactory()));
|
||||
setOutputProtocolFactory(boost::shared_ptr<TProtocolFactory>(new TBinaryProtocolFactory()));
|
||||
}
|
||||
|
||||
TServer(const boost::shared_ptr<TProcessor>& processor,
|
||||
const boost::shared_ptr<TServerTransport>& serverTransport)
|
||||
: processorFactory_(new TSingletonProcessorFactory(processor)),
|
||||
serverTransport_(serverTransport) {
|
||||
setInputTransportFactory(boost::shared_ptr<TTransportFactory>(new TTransportFactory()));
|
||||
setOutputTransportFactory(boost::shared_ptr<TTransportFactory>(new TTransportFactory()));
|
||||
setInputProtocolFactory(boost::shared_ptr<TProtocolFactory>(new TBinaryProtocolFactory()));
|
||||
setOutputProtocolFactory(boost::shared_ptr<TProtocolFactory>(new TBinaryProtocolFactory()));
|
||||
}
|
||||
|
||||
TServer(const boost::shared_ptr<TProcessorFactory>& processorFactory,
|
||||
const boost::shared_ptr<TServerTransport>& serverTransport,
|
||||
const boost::shared_ptr<TTransportFactory>& transportFactory,
|
||||
const boost::shared_ptr<TProtocolFactory>& protocolFactory)
|
||||
: processorFactory_(processorFactory),
|
||||
serverTransport_(serverTransport),
|
||||
inputTransportFactory_(transportFactory),
|
||||
outputTransportFactory_(transportFactory),
|
||||
inputProtocolFactory_(protocolFactory),
|
||||
outputProtocolFactory_(protocolFactory) {}
|
||||
|
||||
TServer(const boost::shared_ptr<TProcessor>& processor,
|
||||
const boost::shared_ptr<TServerTransport>& serverTransport,
|
||||
const boost::shared_ptr<TTransportFactory>& transportFactory,
|
||||
const boost::shared_ptr<TProtocolFactory>& protocolFactory)
|
||||
: processorFactory_(new TSingletonProcessorFactory(processor)),
|
||||
serverTransport_(serverTransport),
|
||||
inputTransportFactory_(transportFactory),
|
||||
outputTransportFactory_(transportFactory),
|
||||
inputProtocolFactory_(protocolFactory),
|
||||
outputProtocolFactory_(protocolFactory) {}
|
||||
|
||||
TServer(const boost::shared_ptr<TProcessorFactory>& processorFactory,
|
||||
const boost::shared_ptr<TServerTransport>& serverTransport,
|
||||
const boost::shared_ptr<TTransportFactory>& inputTransportFactory,
|
||||
const boost::shared_ptr<TTransportFactory>& outputTransportFactory,
|
||||
const boost::shared_ptr<TProtocolFactory>& inputProtocolFactory,
|
||||
const boost::shared_ptr<TProtocolFactory>& outputProtocolFactory)
|
||||
: processorFactory_(processorFactory),
|
||||
serverTransport_(serverTransport),
|
||||
inputTransportFactory_(inputTransportFactory),
|
||||
outputTransportFactory_(outputTransportFactory),
|
||||
inputProtocolFactory_(inputProtocolFactory),
|
||||
outputProtocolFactory_(outputProtocolFactory) {}
|
||||
|
||||
TServer(const boost::shared_ptr<TProcessor>& processor,
|
||||
const boost::shared_ptr<TServerTransport>& serverTransport,
|
||||
const boost::shared_ptr<TTransportFactory>& inputTransportFactory,
|
||||
const boost::shared_ptr<TTransportFactory>& outputTransportFactory,
|
||||
const boost::shared_ptr<TProtocolFactory>& inputProtocolFactory,
|
||||
const boost::shared_ptr<TProtocolFactory>& outputProtocolFactory)
|
||||
: 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.
|
||||
*/
|
||||
#ifdef HAVE_SYS_RESOURCE_H
|
||||
int increase_max_fds(int max_fds = (1 << 24));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
} // apache::thrift::server
|
||||
|
||||
#endif // #ifndef _THRIFT_SERVER_TSERVER_H_
|
246
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/server/TServerFramework.cpp
generated
vendored
Normal file
246
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/server/TServerFramework.cpp
generated
vendored
Normal file
|
@ -0,0 +1,246 @@
|
|||
/*
|
||||
* 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 <algorithm>
|
||||
#include <boost/bind.hpp>
|
||||
#include <stdexcept>
|
||||
#include <stdint.h>
|
||||
#include <thrift/server/TServerFramework.h>
|
||||
|
||||
namespace apache {
|
||||
namespace thrift {
|
||||
namespace server {
|
||||
|
||||
using apache::thrift::concurrency::Synchronized;
|
||||
using apache::thrift::transport::TServerTransport;
|
||||
using apache::thrift::transport::TTransport;
|
||||
using apache::thrift::transport::TTransportException;
|
||||
using apache::thrift::transport::TTransportFactory;
|
||||
using apache::thrift::protocol::TProtocol;
|
||||
using apache::thrift::protocol::TProtocolFactory;
|
||||
using boost::bind;
|
||||
using boost::shared_ptr;
|
||||
using std::string;
|
||||
|
||||
TServerFramework::TServerFramework(const shared_ptr<TProcessorFactory>& processorFactory,
|
||||
const shared_ptr<TServerTransport>& serverTransport,
|
||||
const shared_ptr<TTransportFactory>& transportFactory,
|
||||
const shared_ptr<TProtocolFactory>& protocolFactory)
|
||||
: TServer(processorFactory, serverTransport, transportFactory, protocolFactory),
|
||||
clients_(0),
|
||||
hwm_(0),
|
||||
limit_(INT64_MAX) {
|
||||
}
|
||||
|
||||
TServerFramework::TServerFramework(const shared_ptr<TProcessor>& processor,
|
||||
const shared_ptr<TServerTransport>& serverTransport,
|
||||
const shared_ptr<TTransportFactory>& transportFactory,
|
||||
const shared_ptr<TProtocolFactory>& protocolFactory)
|
||||
: TServer(processor, serverTransport, transportFactory, protocolFactory),
|
||||
clients_(0),
|
||||
hwm_(0),
|
||||
limit_(INT64_MAX) {
|
||||
}
|
||||
|
||||
TServerFramework::TServerFramework(const shared_ptr<TProcessorFactory>& processorFactory,
|
||||
const shared_ptr<TServerTransport>& serverTransport,
|
||||
const shared_ptr<TTransportFactory>& inputTransportFactory,
|
||||
const shared_ptr<TTransportFactory>& outputTransportFactory,
|
||||
const shared_ptr<TProtocolFactory>& inputProtocolFactory,
|
||||
const shared_ptr<TProtocolFactory>& outputProtocolFactory)
|
||||
: TServer(processorFactory,
|
||||
serverTransport,
|
||||
inputTransportFactory,
|
||||
outputTransportFactory,
|
||||
inputProtocolFactory,
|
||||
outputProtocolFactory),
|
||||
clients_(0),
|
||||
hwm_(0),
|
||||
limit_(INT64_MAX) {
|
||||
}
|
||||
|
||||
TServerFramework::TServerFramework(const shared_ptr<TProcessor>& processor,
|
||||
const shared_ptr<TServerTransport>& serverTransport,
|
||||
const shared_ptr<TTransportFactory>& inputTransportFactory,
|
||||
const shared_ptr<TTransportFactory>& outputTransportFactory,
|
||||
const shared_ptr<TProtocolFactory>& inputProtocolFactory,
|
||||
const shared_ptr<TProtocolFactory>& outputProtocolFactory)
|
||||
: TServer(processor,
|
||||
serverTransport,
|
||||
inputTransportFactory,
|
||||
outputTransportFactory,
|
||||
inputProtocolFactory,
|
||||
outputProtocolFactory),
|
||||
clients_(0),
|
||||
hwm_(0),
|
||||
limit_(INT64_MAX) {
|
||||
}
|
||||
|
||||
TServerFramework::~TServerFramework() {
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static void releaseOneDescriptor(const string& name, T& pTransport) {
|
||||
if (pTransport) {
|
||||
try {
|
||||
pTransport->close();
|
||||
} catch (const TTransportException& ttx) {
|
||||
string errStr = string("TServerFramework " + name + " close failed: ") + ttx.what();
|
||||
GlobalOutput(errStr.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TServerFramework::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 to indicate server is now listening
|
||||
// and that it is safe to connect.
|
||||
if (eventHandler_) {
|
||||
eventHandler_->preServe();
|
||||
}
|
||||
|
||||
// Fetch client from server
|
||||
for (;;) {
|
||||
try {
|
||||
// Dereference any resources from any previous client creation
|
||||
// such that a blocking accept does not hold them indefinitely.
|
||||
outputProtocol.reset();
|
||||
inputProtocol.reset();
|
||||
outputTransport.reset();
|
||||
inputTransport.reset();
|
||||
client.reset();
|
||||
|
||||
// If we have reached the limit on the number of concurrent
|
||||
// clients allowed, wait for one or more clients to drain before
|
||||
// accepting another.
|
||||
{
|
||||
Synchronized sync(mon_);
|
||||
while (clients_ >= limit_) {
|
||||
mon_.wait();
|
||||
}
|
||||
}
|
||||
|
||||
client = serverTransport_->accept();
|
||||
|
||||
inputTransport = inputTransportFactory_->getTransport(client);
|
||||
outputTransport = outputTransportFactory_->getTransport(client);
|
||||
if (!outputProtocolFactory_) {
|
||||
inputProtocol = inputProtocolFactory_->getProtocol(inputTransport, outputTransport);
|
||||
outputProtocol = inputProtocol;
|
||||
} else {
|
||||
inputProtocol = inputProtocolFactory_->getProtocol(inputTransport);
|
||||
outputProtocol = outputProtocolFactory_->getProtocol(outputTransport);
|
||||
}
|
||||
|
||||
newlyConnectedClient(shared_ptr<TConnectedClient>(
|
||||
new TConnectedClient(getProcessor(inputProtocol, outputProtocol, client),
|
||||
inputProtocol,
|
||||
outputProtocol,
|
||||
eventHandler_,
|
||||
client),
|
||||
bind(&TServerFramework::disposeConnectedClient, this, _1)));
|
||||
|
||||
} catch (TTransportException& ttx) {
|
||||
releaseOneDescriptor("inputTransport", inputTransport);
|
||||
releaseOneDescriptor("outputTransport", outputTransport);
|
||||
releaseOneDescriptor("client", client);
|
||||
if (ttx.getType() == TTransportException::TIMED_OUT) {
|
||||
// Accept timeout - continue processing.
|
||||
continue;
|
||||
} else if (ttx.getType() == TTransportException::END_OF_FILE
|
||||
|| ttx.getType() == TTransportException::INTERRUPTED) {
|
||||
// Server was interrupted. This only happens when stopping.
|
||||
break;
|
||||
} else {
|
||||
// All other transport exceptions are logged.
|
||||
// State of connection is unknown. Done.
|
||||
string errStr = string("TServerTransport died: ") + ttx.what();
|
||||
GlobalOutput(errStr.c_str());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
releaseOneDescriptor("serverTransport", serverTransport_);
|
||||
}
|
||||
|
||||
int64_t TServerFramework::getConcurrentClientLimit() const {
|
||||
Synchronized sync(mon_);
|
||||
return limit_;
|
||||
}
|
||||
|
||||
int64_t TServerFramework::getConcurrentClientCount() const {
|
||||
Synchronized sync(mon_);
|
||||
return clients_;
|
||||
}
|
||||
|
||||
int64_t TServerFramework::getConcurrentClientCountHWM() const {
|
||||
Synchronized sync(mon_);
|
||||
return hwm_;
|
||||
}
|
||||
|
||||
void TServerFramework::setConcurrentClientLimit(int64_t newLimit) {
|
||||
if (newLimit < 1) {
|
||||
throw std::invalid_argument("newLimit must be greater than zero");
|
||||
}
|
||||
Synchronized sync(mon_);
|
||||
limit_ = newLimit;
|
||||
if (limit_ - clients_ > 0) {
|
||||
mon_.notify();
|
||||
}
|
||||
}
|
||||
|
||||
void TServerFramework::stop() {
|
||||
// Order is important because serve() releases serverTransport_ when it is
|
||||
// interrupted, which closes the socket that interruptChildren uses.
|
||||
serverTransport_->interruptChildren();
|
||||
serverTransport_->interrupt();
|
||||
}
|
||||
|
||||
void TServerFramework::newlyConnectedClient(const boost::shared_ptr<TConnectedClient>& pClient) {
|
||||
{
|
||||
Synchronized sync(mon_);
|
||||
++clients_;
|
||||
hwm_ = (std::max)(hwm_, clients_);
|
||||
}
|
||||
|
||||
onClientConnected(pClient);
|
||||
}
|
||||
|
||||
void TServerFramework::disposeConnectedClient(TConnectedClient* pClient) {
|
||||
onClientDisconnected(pClient);
|
||||
delete pClient;
|
||||
|
||||
Synchronized sync(mon_);
|
||||
if (limit_ - --clients_ > 0) {
|
||||
mon_.notify();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
} // apache::thrift::server
|
184
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/server/TServerFramework.h
generated
vendored
Normal file
184
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/server/TServerFramework.h
generated
vendored
Normal file
|
@ -0,0 +1,184 @@
|
|||
/*
|
||||
* 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_SERVER_TSERVERFRAMEWORK_H_
|
||||
#define _THRIFT_SERVER_TSERVERFRAMEWORK_H_ 1
|
||||
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <stdint.h>
|
||||
#include <thrift/TProcessor.h>
|
||||
#include <thrift/concurrency/Monitor.h>
|
||||
#include <thrift/server/TConnectedClient.h>
|
||||
#include <thrift/server/TServer.h>
|
||||
#include <thrift/transport/TServerTransport.h>
|
||||
#include <thrift/transport/TTransport.h>
|
||||
|
||||
namespace apache {
|
||||
namespace thrift {
|
||||
namespace server {
|
||||
|
||||
/**
|
||||
* TServerFramework provides a single consolidated processing loop for
|
||||
* servers. By having a single processing loop, behavior between servers
|
||||
* is more predictable and maintenance cost is lowered. Implementations
|
||||
* of TServerFramework must provide a method to deal with a client that
|
||||
* connects and one that disconnects.
|
||||
*
|
||||
* While this functionality could be rolled directly into TServer, and
|
||||
* probably should be, it would break the TServer interface contract so
|
||||
* to maintain backwards compatibility for third party servers, no TServers
|
||||
* were harmed in the making of this class.
|
||||
*/
|
||||
class TServerFramework : public TServer {
|
||||
public:
|
||||
TServerFramework(
|
||||
const boost::shared_ptr<apache::thrift::TProcessorFactory>& processorFactory,
|
||||
const boost::shared_ptr<apache::thrift::transport::TServerTransport>& serverTransport,
|
||||
const boost::shared_ptr<apache::thrift::transport::TTransportFactory>& transportFactory,
|
||||
const boost::shared_ptr<apache::thrift::protocol::TProtocolFactory>& protocolFactory);
|
||||
|
||||
TServerFramework(
|
||||
const boost::shared_ptr<apache::thrift::TProcessor>& processor,
|
||||
const boost::shared_ptr<apache::thrift::transport::TServerTransport>& serverTransport,
|
||||
const boost::shared_ptr<apache::thrift::transport::TTransportFactory>& transportFactory,
|
||||
const boost::shared_ptr<apache::thrift::protocol::TProtocolFactory>& protocolFactory);
|
||||
|
||||
TServerFramework(
|
||||
const boost::shared_ptr<apache::thrift::TProcessorFactory>& processorFactory,
|
||||
const boost::shared_ptr<apache::thrift::transport::TServerTransport>& serverTransport,
|
||||
const boost::shared_ptr<apache::thrift::transport::TTransportFactory>& inputTransportFactory,
|
||||
const boost::shared_ptr<apache::thrift::transport::TTransportFactory>& outputTransportFactory,
|
||||
const boost::shared_ptr<apache::thrift::protocol::TProtocolFactory>& inputProtocolFactory,
|
||||
const boost::shared_ptr<apache::thrift::protocol::TProtocolFactory>& outputProtocolFactory);
|
||||
|
||||
TServerFramework(
|
||||
const boost::shared_ptr<apache::thrift::TProcessor>& processor,
|
||||
const boost::shared_ptr<apache::thrift::transport::TServerTransport>& serverTransport,
|
||||
const boost::shared_ptr<apache::thrift::transport::TTransportFactory>& inputTransportFactory,
|
||||
const boost::shared_ptr<apache::thrift::transport::TTransportFactory>& outputTransportFactory,
|
||||
const boost::shared_ptr<apache::thrift::protocol::TProtocolFactory>& inputProtocolFactory,
|
||||
const boost::shared_ptr<apache::thrift::protocol::TProtocolFactory>& outputProtocolFactory);
|
||||
|
||||
virtual ~TServerFramework();
|
||||
|
||||
/**
|
||||
* Accept clients from the TServerTransport and add them for processing.
|
||||
* Call stop() on another thread to interrupt processing
|
||||
* and return control to the caller.
|
||||
* Post-conditions (return guarantees):
|
||||
* The serverTransport will be closed.
|
||||
*/
|
||||
virtual void serve();
|
||||
|
||||
/**
|
||||
* Interrupt serve() so that it meets post-conditions and returns.
|
||||
*/
|
||||
virtual void stop();
|
||||
|
||||
/**
|
||||
* Get the concurrent client limit.
|
||||
* \returns the concurrent client limit
|
||||
*/
|
||||
virtual int64_t getConcurrentClientLimit() const;
|
||||
|
||||
/**
|
||||
* Get the number of currently connected clients.
|
||||
* \returns the number of currently connected clients
|
||||
*/
|
||||
virtual int64_t getConcurrentClientCount() const;
|
||||
|
||||
/**
|
||||
* Get the highest number of concurrent clients.
|
||||
* \returns the highest number of concurrent clients
|
||||
*/
|
||||
virtual int64_t getConcurrentClientCountHWM() const;
|
||||
|
||||
/**
|
||||
* Set the concurrent client limit. This can be changed while
|
||||
* the server is serving however it will not necessarily be
|
||||
* enforced until the next client is accepted and added. If the
|
||||
* limit is lowered below the number of connected clients, no
|
||||
* action is taken to disconnect the clients.
|
||||
* The default value used if this is not called is INT64_MAX.
|
||||
* \param[in] newLimit the new limit of concurrent clients
|
||||
* \throws std::invalid_argument if newLimit is less than 1
|
||||
*/
|
||||
virtual void setConcurrentClientLimit(int64_t newLimit);
|
||||
|
||||
protected:
|
||||
/**
|
||||
* A client has connected. The implementation is responsible for managing the
|
||||
* lifetime of the client object. This is called during the serve() thread,
|
||||
* therefore a failure to return quickly will result in new client connection
|
||||
* delays.
|
||||
*
|
||||
* \param[in] pClient the newly connected client
|
||||
*/
|
||||
virtual void onClientConnected(const boost::shared_ptr<TConnectedClient>& pClient) = 0;
|
||||
|
||||
/**
|
||||
* A client has disconnected.
|
||||
* When called:
|
||||
* The server no longer tracks the client.
|
||||
* The client TTransport has already been closed.
|
||||
* The implementation must not delete the pointer.
|
||||
*
|
||||
* \param[in] pClient the disconnected client
|
||||
*/
|
||||
virtual void onClientDisconnected(TConnectedClient* pClient) = 0;
|
||||
|
||||
private:
|
||||
/**
|
||||
* Common handling for new connected clients. Implements concurrent
|
||||
* client rate limiting after onClientConnected returns by blocking the
|
||||
* serve() thread if the limit has been reached.
|
||||
*/
|
||||
void newlyConnectedClient(const boost::shared_ptr<TConnectedClient>& pClient);
|
||||
|
||||
/**
|
||||
* Smart pointer client deletion.
|
||||
* Calls onClientDisconnected and then deletes pClient.
|
||||
*/
|
||||
void disposeConnectedClient(TConnectedClient* pClient);
|
||||
|
||||
/**
|
||||
* Monitor for limiting the number of concurrent clients.
|
||||
*/
|
||||
apache::thrift::concurrency::Monitor mon_;
|
||||
|
||||
/**
|
||||
* The number of concurrent clients.
|
||||
*/
|
||||
int64_t clients_;
|
||||
|
||||
/**
|
||||
* The high water mark of concurrent clients.
|
||||
*/
|
||||
int64_t hwm_;
|
||||
|
||||
/**
|
||||
* The limit on the number of concurrent clients.
|
||||
*/
|
||||
int64_t limit_;
|
||||
};
|
||||
}
|
||||
}
|
||||
} // apache::thrift::server
|
||||
|
||||
#endif // #ifndef _THRIFT_SERVER_TSERVERFRAMEWORK_H_
|
107
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/server/TSimpleServer.cpp
generated
vendored
Normal file
107
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/server/TSimpleServer.cpp
generated
vendored
Normal file
|
@ -0,0 +1,107 @@
|
|||
/*
|
||||
* 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>
|
||||
|
||||
namespace apache {
|
||||
namespace thrift {
|
||||
namespace server {
|
||||
|
||||
using apache::thrift::protocol::TProtocol;
|
||||
using apache::thrift::protocol::TProtocolFactory;
|
||||
using apache::thrift::transport::TServerTransport;
|
||||
using apache::thrift::transport::TTransport;
|
||||
using apache::thrift::transport::TTransportException;
|
||||
using apache::thrift::transport::TTransportFactory;
|
||||
using boost::shared_ptr;
|
||||
using std::string;
|
||||
|
||||
TSimpleServer::TSimpleServer(const shared_ptr<TProcessorFactory>& processorFactory,
|
||||
const shared_ptr<TServerTransport>& serverTransport,
|
||||
const shared_ptr<TTransportFactory>& transportFactory,
|
||||
const shared_ptr<TProtocolFactory>& protocolFactory)
|
||||
: TServerFramework(processorFactory, serverTransport, transportFactory, protocolFactory) {
|
||||
TServerFramework::setConcurrentClientLimit(1);
|
||||
}
|
||||
|
||||
TSimpleServer::TSimpleServer(const shared_ptr<TProcessor>& processor,
|
||||
const shared_ptr<TServerTransport>& serverTransport,
|
||||
const shared_ptr<TTransportFactory>& transportFactory,
|
||||
const shared_ptr<TProtocolFactory>& protocolFactory)
|
||||
: TServerFramework(processor, serverTransport, transportFactory, protocolFactory) {
|
||||
TServerFramework::setConcurrentClientLimit(1);
|
||||
}
|
||||
|
||||
TSimpleServer::TSimpleServer(const shared_ptr<TProcessorFactory>& processorFactory,
|
||||
const shared_ptr<TServerTransport>& serverTransport,
|
||||
const shared_ptr<TTransportFactory>& inputTransportFactory,
|
||||
const shared_ptr<TTransportFactory>& outputTransportFactory,
|
||||
const shared_ptr<TProtocolFactory>& inputProtocolFactory,
|
||||
const shared_ptr<TProtocolFactory>& outputProtocolFactory)
|
||||
: TServerFramework(processorFactory,
|
||||
serverTransport,
|
||||
inputTransportFactory,
|
||||
outputTransportFactory,
|
||||
inputProtocolFactory,
|
||||
outputProtocolFactory) {
|
||||
TServerFramework::setConcurrentClientLimit(1);
|
||||
}
|
||||
|
||||
TSimpleServer::TSimpleServer(const shared_ptr<TProcessor>& processor,
|
||||
const shared_ptr<TServerTransport>& serverTransport,
|
||||
const shared_ptr<TTransportFactory>& inputTransportFactory,
|
||||
const shared_ptr<TTransportFactory>& outputTransportFactory,
|
||||
const shared_ptr<TProtocolFactory>& inputProtocolFactory,
|
||||
const shared_ptr<TProtocolFactory>& outputProtocolFactory)
|
||||
: TServerFramework(processor,
|
||||
serverTransport,
|
||||
inputTransportFactory,
|
||||
outputTransportFactory,
|
||||
inputProtocolFactory,
|
||||
outputProtocolFactory) {
|
||||
TServerFramework::setConcurrentClientLimit(1);
|
||||
}
|
||||
|
||||
TSimpleServer::~TSimpleServer() {
|
||||
}
|
||||
|
||||
/**
|
||||
* The main body of customized implementation for TSimpleServer is quite simple:
|
||||
* When a client connects, use the serve() thread to drive it to completion thus
|
||||
* blocking new connections.
|
||||
*/
|
||||
void TSimpleServer::onClientConnected(const shared_ptr<TConnectedClient>& pClient) {
|
||||
pClient->run();
|
||||
}
|
||||
|
||||
/**
|
||||
* TSimpleServer does not track clients so there is nothing to do here.
|
||||
*/
|
||||
void TSimpleServer::onClientDisconnected(TConnectedClient*) {
|
||||
}
|
||||
|
||||
/**
|
||||
* This makes little sense to the simple server because it is not capable
|
||||
* of having more than one client at a time, so we hide it.
|
||||
*/
|
||||
void TSimpleServer::setConcurrentClientLimit(int64_t) {
|
||||
}
|
||||
}
|
||||
}
|
||||
} // apache::thrift::server
|
77
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/server/TSimpleServer.h
generated
vendored
Normal file
77
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/server/TSimpleServer.h
generated
vendored
Normal file
|
@ -0,0 +1,77 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
#ifndef _THRIFT_SERVER_TSIMPLESERVER_H_
|
||||
#define _THRIFT_SERVER_TSIMPLESERVER_H_ 1
|
||||
|
||||
#include <thrift/server/TServerFramework.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.
|
||||
*/
|
||||
class TSimpleServer : public TServerFramework {
|
||||
public:
|
||||
TSimpleServer(
|
||||
const boost::shared_ptr<apache::thrift::TProcessorFactory>& processorFactory,
|
||||
const boost::shared_ptr<apache::thrift::transport::TServerTransport>& serverTransport,
|
||||
const boost::shared_ptr<apache::thrift::transport::TTransportFactory>& transportFactory,
|
||||
const boost::shared_ptr<apache::thrift::protocol::TProtocolFactory>& protocolFactory);
|
||||
|
||||
TSimpleServer(
|
||||
const boost::shared_ptr<apache::thrift::TProcessor>& processor,
|
||||
const boost::shared_ptr<apache::thrift::transport::TServerTransport>& serverTransport,
|
||||
const boost::shared_ptr<apache::thrift::transport::TTransportFactory>& transportFactory,
|
||||
const boost::shared_ptr<apache::thrift::protocol::TProtocolFactory>& protocolFactory);
|
||||
|
||||
TSimpleServer(
|
||||
const boost::shared_ptr<apache::thrift::TProcessorFactory>& processorFactory,
|
||||
const boost::shared_ptr<apache::thrift::transport::TServerTransport>& serverTransport,
|
||||
const boost::shared_ptr<apache::thrift::transport::TTransportFactory>& inputTransportFactory,
|
||||
const boost::shared_ptr<apache::thrift::transport::TTransportFactory>& outputTransportFactory,
|
||||
const boost::shared_ptr<apache::thrift::protocol::TProtocolFactory>& inputProtocolFactory,
|
||||
const boost::shared_ptr<apache::thrift::protocol::TProtocolFactory>& outputProtocolFactory);
|
||||
|
||||
TSimpleServer(
|
||||
const boost::shared_ptr<apache::thrift::TProcessor>& processor,
|
||||
const boost::shared_ptr<apache::thrift::transport::TServerTransport>& serverTransport,
|
||||
const boost::shared_ptr<apache::thrift::transport::TTransportFactory>& inputTransportFactory,
|
||||
const boost::shared_ptr<apache::thrift::transport::TTransportFactory>& outputTransportFactory,
|
||||
const boost::shared_ptr<apache::thrift::protocol::TProtocolFactory>& inputProtocolFactory,
|
||||
const boost::shared_ptr<apache::thrift::protocol::TProtocolFactory>& outputProtocolFactory);
|
||||
|
||||
virtual ~TSimpleServer();
|
||||
|
||||
protected:
|
||||
virtual void onClientConnected(const boost::shared_ptr<TConnectedClient>& pClient) /* override */;
|
||||
virtual void onClientDisconnected(TConnectedClient* pClient) /* override */;
|
||||
|
||||
private:
|
||||
void setConcurrentClientLimit(int64_t newLimit); // hide
|
||||
};
|
||||
}
|
||||
}
|
||||
} // apache::thrift::server
|
||||
|
||||
#endif // #ifndef _THRIFT_SERVER_TSIMPLESERVER_H_
|
132
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/server/TThreadPoolServer.cpp
generated
vendored
Normal file
132
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/server/TThreadPoolServer.cpp
generated
vendored
Normal file
|
@ -0,0 +1,132 @@
|
|||
/*
|
||||
* 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/TThreadPoolServer.h>
|
||||
|
||||
namespace apache {
|
||||
namespace thrift {
|
||||
namespace server {
|
||||
|
||||
using apache::thrift::concurrency::ThreadManager;
|
||||
using apache::thrift::protocol::TProtocol;
|
||||
using apache::thrift::protocol::TProtocolFactory;
|
||||
using apache::thrift::transport::TServerTransport;
|
||||
using apache::thrift::transport::TTransport;
|
||||
using apache::thrift::transport::TTransportException;
|
||||
using apache::thrift::transport::TTransportFactory;
|
||||
using boost::shared_ptr;
|
||||
using std::string;
|
||||
|
||||
TThreadPoolServer::TThreadPoolServer(const shared_ptr<TProcessorFactory>& processorFactory,
|
||||
const shared_ptr<TServerTransport>& serverTransport,
|
||||
const shared_ptr<TTransportFactory>& transportFactory,
|
||||
const shared_ptr<TProtocolFactory>& protocolFactory,
|
||||
const shared_ptr<ThreadManager>& threadManager)
|
||||
: TServerFramework(processorFactory, serverTransport, transportFactory, protocolFactory),
|
||||
threadManager_(threadManager),
|
||||
timeout_(0),
|
||||
taskExpiration_(0) {
|
||||
}
|
||||
|
||||
TThreadPoolServer::TThreadPoolServer(const shared_ptr<TProcessor>& processor,
|
||||
const shared_ptr<TServerTransport>& serverTransport,
|
||||
const shared_ptr<TTransportFactory>& transportFactory,
|
||||
const shared_ptr<TProtocolFactory>& protocolFactory,
|
||||
const shared_ptr<ThreadManager>& threadManager)
|
||||
: TServerFramework(processor, serverTransport, transportFactory, protocolFactory),
|
||||
threadManager_(threadManager),
|
||||
timeout_(0),
|
||||
taskExpiration_(0) {
|
||||
}
|
||||
|
||||
TThreadPoolServer::TThreadPoolServer(const shared_ptr<TProcessorFactory>& processorFactory,
|
||||
const shared_ptr<TServerTransport>& serverTransport,
|
||||
const shared_ptr<TTransportFactory>& inputTransportFactory,
|
||||
const shared_ptr<TTransportFactory>& outputTransportFactory,
|
||||
const shared_ptr<TProtocolFactory>& inputProtocolFactory,
|
||||
const shared_ptr<TProtocolFactory>& outputProtocolFactory,
|
||||
const shared_ptr<ThreadManager>& threadManager)
|
||||
: TServerFramework(processorFactory,
|
||||
serverTransport,
|
||||
inputTransportFactory,
|
||||
outputTransportFactory,
|
||||
inputProtocolFactory,
|
||||
outputProtocolFactory),
|
||||
threadManager_(threadManager),
|
||||
timeout_(0),
|
||||
taskExpiration_(0) {
|
||||
}
|
||||
|
||||
TThreadPoolServer::TThreadPoolServer(const shared_ptr<TProcessor>& processor,
|
||||
const shared_ptr<TServerTransport>& serverTransport,
|
||||
const shared_ptr<TTransportFactory>& inputTransportFactory,
|
||||
const shared_ptr<TTransportFactory>& outputTransportFactory,
|
||||
const shared_ptr<TProtocolFactory>& inputProtocolFactory,
|
||||
const shared_ptr<TProtocolFactory>& outputProtocolFactory,
|
||||
const shared_ptr<ThreadManager>& threadManager)
|
||||
: TServerFramework(processor,
|
||||
serverTransport,
|
||||
inputTransportFactory,
|
||||
outputTransportFactory,
|
||||
inputProtocolFactory,
|
||||
outputProtocolFactory),
|
||||
threadManager_(threadManager),
|
||||
timeout_(0),
|
||||
taskExpiration_(0) {
|
||||
}
|
||||
|
||||
TThreadPoolServer::~TThreadPoolServer() {
|
||||
}
|
||||
|
||||
void TThreadPoolServer::serve() {
|
||||
TServerFramework::serve();
|
||||
threadManager_->stop();
|
||||
}
|
||||
|
||||
int64_t TThreadPoolServer::getTimeout() const {
|
||||
return timeout_;
|
||||
}
|
||||
|
||||
void TThreadPoolServer::setTimeout(int64_t value) {
|
||||
timeout_ = value;
|
||||
}
|
||||
|
||||
int64_t TThreadPoolServer::getTaskExpiration() const {
|
||||
return taskExpiration_;
|
||||
}
|
||||
|
||||
void TThreadPoolServer::setTaskExpiration(int64_t value) {
|
||||
taskExpiration_ = value;
|
||||
}
|
||||
|
||||
boost::shared_ptr<apache::thrift::concurrency::ThreadManager>
|
||||
TThreadPoolServer::getThreadManager() const {
|
||||
return threadManager_;
|
||||
}
|
||||
|
||||
void TThreadPoolServer::onClientConnected(const shared_ptr<TConnectedClient>& pClient) {
|
||||
threadManager_->add(pClient, getTimeout(), getTaskExpiration());
|
||||
}
|
||||
|
||||
void TThreadPoolServer::onClientDisconnected(TConnectedClient*) {
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
} // apache::thrift::server
|
101
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/server/TThreadPoolServer.h
generated
vendored
Normal file
101
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/server/TThreadPoolServer.h
generated
vendored
Normal file
|
@ -0,0 +1,101 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
#ifndef _THRIFT_SERVER_TTHREADPOOLSERVER_H_
|
||||
#define _THRIFT_SERVER_TTHREADPOOLSERVER_H_ 1
|
||||
|
||||
#include <boost/atomic.hpp>
|
||||
#include <thrift/concurrency/ThreadManager.h>
|
||||
#include <thrift/server/TServerFramework.h>
|
||||
|
||||
namespace apache {
|
||||
namespace thrift {
|
||||
namespace server {
|
||||
|
||||
/**
|
||||
* Manage clients using a thread pool.
|
||||
*/
|
||||
class TThreadPoolServer : public TServerFramework {
|
||||
public:
|
||||
TThreadPoolServer(
|
||||
const boost::shared_ptr<apache::thrift::TProcessorFactory>& processorFactory,
|
||||
const boost::shared_ptr<apache::thrift::transport::TServerTransport>& serverTransport,
|
||||
const boost::shared_ptr<apache::thrift::transport::TTransportFactory>& transportFactory,
|
||||
const boost::shared_ptr<apache::thrift::protocol::TProtocolFactory>& protocolFactory,
|
||||
const boost::shared_ptr<apache::thrift::concurrency::ThreadManager>& threadManager
|
||||
= apache::thrift::concurrency::ThreadManager::newSimpleThreadManager());
|
||||
|
||||
TThreadPoolServer(
|
||||
const boost::shared_ptr<apache::thrift::TProcessor>& processor,
|
||||
const boost::shared_ptr<apache::thrift::transport::TServerTransport>& serverTransport,
|
||||
const boost::shared_ptr<apache::thrift::transport::TTransportFactory>& transportFactory,
|
||||
const boost::shared_ptr<apache::thrift::protocol::TProtocolFactory>& protocolFactory,
|
||||
const boost::shared_ptr<apache::thrift::concurrency::ThreadManager>& threadManager
|
||||
= apache::thrift::concurrency::ThreadManager::newSimpleThreadManager());
|
||||
|
||||
TThreadPoolServer(
|
||||
const boost::shared_ptr<apache::thrift::TProcessorFactory>& processorFactory,
|
||||
const boost::shared_ptr<apache::thrift::transport::TServerTransport>& serverTransport,
|
||||
const boost::shared_ptr<apache::thrift::transport::TTransportFactory>& inputTransportFactory,
|
||||
const boost::shared_ptr<apache::thrift::transport::TTransportFactory>& outputTransportFactory,
|
||||
const boost::shared_ptr<apache::thrift::protocol::TProtocolFactory>& inputProtocolFactory,
|
||||
const boost::shared_ptr<apache::thrift::protocol::TProtocolFactory>& outputProtocolFactory,
|
||||
const boost::shared_ptr<apache::thrift::concurrency::ThreadManager>& threadManager
|
||||
= apache::thrift::concurrency::ThreadManager::newSimpleThreadManager());
|
||||
|
||||
TThreadPoolServer(
|
||||
const boost::shared_ptr<apache::thrift::TProcessor>& processor,
|
||||
const boost::shared_ptr<apache::thrift::transport::TServerTransport>& serverTransport,
|
||||
const boost::shared_ptr<apache::thrift::transport::TTransportFactory>& inputTransportFactory,
|
||||
const boost::shared_ptr<apache::thrift::transport::TTransportFactory>& outputTransportFactory,
|
||||
const boost::shared_ptr<apache::thrift::protocol::TProtocolFactory>& inputProtocolFactory,
|
||||
const boost::shared_ptr<apache::thrift::protocol::TProtocolFactory>& outputProtocolFactory,
|
||||
const boost::shared_ptr<apache::thrift::concurrency::ThreadManager>& threadManager
|
||||
= apache::thrift::concurrency::ThreadManager::newSimpleThreadManager());
|
||||
|
||||
virtual ~TThreadPoolServer();
|
||||
|
||||
/**
|
||||
* Post-conditions (return guarantees):
|
||||
* There will be no clients connected.
|
||||
*/
|
||||
virtual void serve();
|
||||
|
||||
virtual int64_t getTimeout() const;
|
||||
virtual void setTimeout(int64_t value);
|
||||
|
||||
virtual int64_t getTaskExpiration() const;
|
||||
virtual void setTaskExpiration(int64_t value);
|
||||
|
||||
virtual boost::shared_ptr<apache::thrift::concurrency::ThreadManager> getThreadManager() const;
|
||||
|
||||
protected:
|
||||
virtual void onClientConnected(const boost::shared_ptr<TConnectedClient>& pClient) /* override */;
|
||||
virtual void onClientDisconnected(TConnectedClient* pClient) /* override */;
|
||||
|
||||
boost::shared_ptr<apache::thrift::concurrency::ThreadManager> threadManager_;
|
||||
boost::atomic<int64_t> timeout_;
|
||||
boost::atomic<int64_t> taskExpiration_;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
} // apache::thrift::server
|
||||
|
||||
#endif // #ifndef _THRIFT_SERVER_TTHREADPOOLSERVER_H_
|
153
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/server/TThreadedServer.cpp
generated
vendored
Normal file
153
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/server/TThreadedServer.cpp
generated
vendored
Normal file
|
@ -0,0 +1,153 @@
|
|||
/*
|
||||
* 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 <boost/bind.hpp>
|
||||
#include <boost/function.hpp>
|
||||
#include <boost/make_shared.hpp>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <string>
|
||||
#include <thrift/concurrency/PlatformThreadFactory.h>
|
||||
#include <thrift/server/TThreadedServer.h>
|
||||
|
||||
namespace apache {
|
||||
namespace thrift {
|
||||
namespace server {
|
||||
|
||||
using apache::thrift::concurrency::Runnable;
|
||||
using apache::thrift::concurrency::Synchronized;
|
||||
using apache::thrift::concurrency::Thread;
|
||||
using apache::thrift::concurrency::ThreadFactory;
|
||||
using apache::thrift::protocol::TProtocol;
|
||||
using apache::thrift::protocol::TProtocolFactory;
|
||||
using apache::thrift::transport::TServerTransport;
|
||||
using apache::thrift::transport::TTransport;
|
||||
using apache::thrift::transport::TTransportException;
|
||||
using apache::thrift::transport::TTransportFactory;
|
||||
using boost::shared_ptr;
|
||||
|
||||
TThreadedServer::TThreadedServer(const shared_ptr<TProcessorFactory>& processorFactory,
|
||||
const shared_ptr<TServerTransport>& serverTransport,
|
||||
const shared_ptr<TTransportFactory>& transportFactory,
|
||||
const shared_ptr<TProtocolFactory>& protocolFactory,
|
||||
const shared_ptr<ThreadFactory>& threadFactory)
|
||||
: TServerFramework(processorFactory, serverTransport, transportFactory, protocolFactory),
|
||||
threadFactory_(threadFactory) {
|
||||
}
|
||||
|
||||
TThreadedServer::TThreadedServer(const shared_ptr<TProcessor>& processor,
|
||||
const shared_ptr<TServerTransport>& serverTransport,
|
||||
const shared_ptr<TTransportFactory>& transportFactory,
|
||||
const shared_ptr<TProtocolFactory>& protocolFactory,
|
||||
const shared_ptr<ThreadFactory>& threadFactory)
|
||||
: TServerFramework(processor, serverTransport, transportFactory, protocolFactory),
|
||||
threadFactory_(threadFactory) {
|
||||
}
|
||||
|
||||
TThreadedServer::TThreadedServer(const shared_ptr<TProcessorFactory>& processorFactory,
|
||||
const shared_ptr<TServerTransport>& serverTransport,
|
||||
const shared_ptr<TTransportFactory>& inputTransportFactory,
|
||||
const shared_ptr<TTransportFactory>& outputTransportFactory,
|
||||
const shared_ptr<TProtocolFactory>& inputProtocolFactory,
|
||||
const shared_ptr<TProtocolFactory>& outputProtocolFactory,
|
||||
const shared_ptr<ThreadFactory>& threadFactory)
|
||||
: TServerFramework(processorFactory,
|
||||
serverTransport,
|
||||
inputTransportFactory,
|
||||
outputTransportFactory,
|
||||
inputProtocolFactory,
|
||||
outputProtocolFactory),
|
||||
threadFactory_(threadFactory) {
|
||||
}
|
||||
|
||||
TThreadedServer::TThreadedServer(const shared_ptr<TProcessor>& processor,
|
||||
const shared_ptr<TServerTransport>& serverTransport,
|
||||
const shared_ptr<TTransportFactory>& inputTransportFactory,
|
||||
const shared_ptr<TTransportFactory>& outputTransportFactory,
|
||||
const shared_ptr<TProtocolFactory>& inputProtocolFactory,
|
||||
const shared_ptr<TProtocolFactory>& outputProtocolFactory,
|
||||
const shared_ptr<ThreadFactory>& threadFactory)
|
||||
: TServerFramework(processor,
|
||||
serverTransport,
|
||||
inputTransportFactory,
|
||||
outputTransportFactory,
|
||||
inputProtocolFactory,
|
||||
outputProtocolFactory),
|
||||
threadFactory_(threadFactory) {
|
||||
}
|
||||
|
||||
TThreadedServer::~TThreadedServer() {
|
||||
}
|
||||
|
||||
void TThreadedServer::serve() {
|
||||
TServerFramework::serve();
|
||||
|
||||
// Ensure post-condition of no active clients
|
||||
Synchronized s(clientMonitor_);
|
||||
while (!activeClientMap_.empty()) {
|
||||
clientMonitor_.wait();
|
||||
}
|
||||
|
||||
drainDeadClients();
|
||||
}
|
||||
|
||||
void TThreadedServer::drainDeadClients() {
|
||||
// we're in a monitor here
|
||||
while (!deadClientMap_.empty()) {
|
||||
ClientMap::iterator it = deadClientMap_.begin();
|
||||
it->second->join();
|
||||
deadClientMap_.erase(it);
|
||||
}
|
||||
}
|
||||
|
||||
void TThreadedServer::onClientConnected(const shared_ptr<TConnectedClient>& pClient) {
|
||||
Synchronized sync(clientMonitor_);
|
||||
boost::shared_ptr<TConnectedClientRunner> pRunnable = boost::make_shared<TConnectedClientRunner>(pClient);
|
||||
boost::shared_ptr<Thread> pThread = threadFactory_->newThread(pRunnable);
|
||||
pRunnable->thread(pThread);
|
||||
activeClientMap_.insert(ClientMap::value_type(pClient.get(), pThread));
|
||||
pThread->start();
|
||||
}
|
||||
|
||||
void TThreadedServer::onClientDisconnected(TConnectedClient* pClient) {
|
||||
Synchronized sync(clientMonitor_);
|
||||
drainDeadClients(); // use the outgoing thread to do some maintenance on our dead client backlog
|
||||
ClientMap::iterator it = activeClientMap_.find(pClient);
|
||||
ClientMap::iterator end = it;
|
||||
deadClientMap_.insert(it, ++end);
|
||||
activeClientMap_.erase(it);
|
||||
if (activeClientMap_.empty()) {
|
||||
clientMonitor_.notify();
|
||||
}
|
||||
}
|
||||
|
||||
TThreadedServer::TConnectedClientRunner::TConnectedClientRunner(const boost::shared_ptr<TConnectedClient>& pClient)
|
||||
: pClient_(pClient) {
|
||||
}
|
||||
|
||||
TThreadedServer::TConnectedClientRunner::~TConnectedClientRunner() {
|
||||
}
|
||||
|
||||
void TThreadedServer::TConnectedClientRunner::run() /* override */ {
|
||||
pClient_->run(); // Run the client
|
||||
pClient_.reset(); // The client is done - release it here rather than in the destructor for safety
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
} // apache::thrift::server
|
143
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/server/TThreadedServer.h
generated
vendored
Normal file
143
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/server/TThreadedServer.h
generated
vendored
Normal file
|
@ -0,0 +1,143 @@
|
|||
/*
|
||||
* 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_SERVER_TTHREADEDSERVER_H_
|
||||
#define _THRIFT_SERVER_TTHREADEDSERVER_H_ 1
|
||||
|
||||
#include <map>
|
||||
#include <thrift/concurrency/Monitor.h>
|
||||
#include <thrift/concurrency/PlatformThreadFactory.h>
|
||||
#include <thrift/concurrency/Thread.h>
|
||||
#include <thrift/server/TServerFramework.h>
|
||||
|
||||
namespace apache {
|
||||
namespace thrift {
|
||||
namespace server {
|
||||
|
||||
/**
|
||||
* Manage clients using threads - threads are created one for each client and are
|
||||
* released when the client disconnects. This server is used to make a dynamically
|
||||
* scalable server up to the concurrent connection limit.
|
||||
*/
|
||||
class TThreadedServer : public TServerFramework {
|
||||
public:
|
||||
TThreadedServer(
|
||||
const boost::shared_ptr<apache::thrift::TProcessorFactory>& processorFactory,
|
||||
const boost::shared_ptr<apache::thrift::transport::TServerTransport>& serverTransport,
|
||||
const boost::shared_ptr<apache::thrift::transport::TTransportFactory>& transportFactory,
|
||||
const boost::shared_ptr<apache::thrift::protocol::TProtocolFactory>& protocolFactory,
|
||||
const boost::shared_ptr<apache::thrift::concurrency::ThreadFactory>& threadFactory
|
||||
= boost::shared_ptr<apache::thrift::concurrency::ThreadFactory>(
|
||||
new apache::thrift::concurrency::PlatformThreadFactory(false)));
|
||||
|
||||
TThreadedServer(
|
||||
const boost::shared_ptr<apache::thrift::TProcessor>& processor,
|
||||
const boost::shared_ptr<apache::thrift::transport::TServerTransport>& serverTransport,
|
||||
const boost::shared_ptr<apache::thrift::transport::TTransportFactory>& transportFactory,
|
||||
const boost::shared_ptr<apache::thrift::protocol::TProtocolFactory>& protocolFactory,
|
||||
const boost::shared_ptr<apache::thrift::concurrency::ThreadFactory>& threadFactory
|
||||
= boost::shared_ptr<apache::thrift::concurrency::ThreadFactory>(
|
||||
new apache::thrift::concurrency::PlatformThreadFactory(false)));
|
||||
|
||||
TThreadedServer(
|
||||
const boost::shared_ptr<apache::thrift::TProcessorFactory>& processorFactory,
|
||||
const boost::shared_ptr<apache::thrift::transport::TServerTransport>& serverTransport,
|
||||
const boost::shared_ptr<apache::thrift::transport::TTransportFactory>& inputTransportFactory,
|
||||
const boost::shared_ptr<apache::thrift::transport::TTransportFactory>& outputTransportFactory,
|
||||
const boost::shared_ptr<apache::thrift::protocol::TProtocolFactory>& inputProtocolFactory,
|
||||
const boost::shared_ptr<apache::thrift::protocol::TProtocolFactory>& outputProtocolFactory,
|
||||
const boost::shared_ptr<apache::thrift::concurrency::ThreadFactory>& threadFactory
|
||||
= boost::shared_ptr<apache::thrift::concurrency::ThreadFactory>(
|
||||
new apache::thrift::concurrency::PlatformThreadFactory(false)));
|
||||
|
||||
TThreadedServer(
|
||||
const boost::shared_ptr<apache::thrift::TProcessor>& processor,
|
||||
const boost::shared_ptr<apache::thrift::transport::TServerTransport>& serverTransport,
|
||||
const boost::shared_ptr<apache::thrift::transport::TTransportFactory>& inputTransportFactory,
|
||||
const boost::shared_ptr<apache::thrift::transport::TTransportFactory>& outputTransportFactory,
|
||||
const boost::shared_ptr<apache::thrift::protocol::TProtocolFactory>& inputProtocolFactory,
|
||||
const boost::shared_ptr<apache::thrift::protocol::TProtocolFactory>& outputProtocolFactory,
|
||||
const boost::shared_ptr<apache::thrift::concurrency::ThreadFactory>& threadFactory
|
||||
= boost::shared_ptr<apache::thrift::concurrency::ThreadFactory>(
|
||||
new apache::thrift::concurrency::PlatformThreadFactory(false)));
|
||||
|
||||
virtual ~TThreadedServer();
|
||||
|
||||
/**
|
||||
* Post-conditions (return guarantees):
|
||||
* There will be no clients connected.
|
||||
*/
|
||||
virtual void serve();
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Drain recently connected clients by joining their threads - this is done lazily because
|
||||
* we cannot do it inside the thread context that is disconnecting.
|
||||
*/
|
||||
virtual void drainDeadClients();
|
||||
|
||||
/**
|
||||
* Implementation of TServerFramework::onClientConnected
|
||||
*/
|
||||
virtual void onClientConnected(const boost::shared_ptr<TConnectedClient>& pClient) /* override */;
|
||||
|
||||
/**
|
||||
* Implementation of TServerFramework::onClientDisconnected
|
||||
*/
|
||||
virtual void onClientDisconnected(TConnectedClient *pClient) /* override */;
|
||||
|
||||
boost::shared_ptr<apache::thrift::concurrency::ThreadFactory> threadFactory_;
|
||||
|
||||
/**
|
||||
* A helper wrapper used to wrap the client in something we can use to maintain
|
||||
* the lifetime of the connected client within a detached thread. We cannot simply
|
||||
* track the threads because a shared_ptr<Thread> hangs on to the Runnable it is
|
||||
* passed, and TServerFramework requires the runnable (TConnectedClient) to be
|
||||
* destroyed in order to work properly.
|
||||
*/
|
||||
class TConnectedClientRunner : public apache::thrift::concurrency::Runnable
|
||||
{
|
||||
public:
|
||||
TConnectedClientRunner(const boost::shared_ptr<TConnectedClient>& pClient);
|
||||
virtual ~TConnectedClientRunner();
|
||||
void run() /* override */;
|
||||
private:
|
||||
boost::shared_ptr<TConnectedClient> pClient_;
|
||||
};
|
||||
|
||||
apache::thrift::concurrency::Monitor clientMonitor_;
|
||||
|
||||
typedef std::map<TConnectedClient *, boost::shared_ptr<apache::thrift::concurrency::Thread> > ClientMap;
|
||||
|
||||
/**
|
||||
* A map of active clients
|
||||
*/
|
||||
ClientMap activeClientMap_;
|
||||
|
||||
/**
|
||||
* A map of clients that have disconnected but their threads have not been joined
|
||||
*/
|
||||
ClientMap deadClientMap_;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
} // apache::thrift::server
|
||||
|
||||
#endif // #ifndef _THRIFT_SERVER_TTHREADEDSERVER_H_
|
24
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/thrift-config.h
generated
vendored
Normal file
24
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/thrift-config.h
generated
vendored
Normal file
|
@ -0,0 +1,24 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <thrift/windows/config.h>
|
||||
#else
|
||||
#include <thrift/config.h>
|
||||
#endif
|
126
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/transport/PlatformSocket.h
generated
vendored
Normal file
126
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/transport/PlatformSocket.h
generated
vendored
Normal file
|
@ -0,0 +1,126 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
// clang-format off
|
||||
|
||||
#ifndef _THRIFT_TRANSPORT_PLATFORM_SOCKET_H_
|
||||
# define _THRIFT_TRANSPORT_PLATFORM_SOCKET_H_
|
||||
|
||||
#ifdef _WIN32
|
||||
# define THRIFT_GET_SOCKET_ERROR ::WSAGetLastError()
|
||||
# define THRIFT_ERRNO (*_errno())
|
||||
# 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_CLOSE _close
|
||||
# define THRIFT_OPEN _open
|
||||
# define THRIFT_FTRUNCATE _chsize_s
|
||||
# define THRIFT_FSYNC _commit
|
||||
# define THRIFT_LSEEK _lseek
|
||||
# define THRIFT_WRITE _write
|
||||
# define THRIFT_READ _read
|
||||
# define THRIFT_FSTAT _fstat
|
||||
# define THRIFT_STAT _stat
|
||||
# ifdef _WIN32_WCE
|
||||
# define THRIFT_GAI_STRERROR(...) thrift_wstr2str(gai_strerrorW(__VA_ARGS__))
|
||||
# else
|
||||
# define THRIFT_GAI_STRERROR gai_strerrorA
|
||||
# endif
|
||||
# define THRIFT_SSIZET ptrdiff_t
|
||||
# if (_MSC_VER < 1900)
|
||||
# define THRIFT_SNPRINTF _snprintf
|
||||
# else
|
||||
# define THRIFT_SNPRINTF snprintf
|
||||
# endif
|
||||
# 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_ERRNO 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_CLOSE close
|
||||
# define THRIFT_OPEN open
|
||||
# define THRIFT_FTRUNCATE ftruncate
|
||||
# define THRIFT_FSYNC fsync
|
||||
# define THRIFT_LSEEK lseek
|
||||
# define THRIFT_WRITE write
|
||||
# define THRIFT_READ read
|
||||
# define THRIFT_STAT stat
|
||||
# define THRIFT_FSTAT fstat
|
||||
# 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
|
||||
|
||||
#endif // _THRIFT_TRANSPORT_PLATFORM_SOCKET_H_
|
411
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/transport/TBufferTransports.cpp
generated
vendored
Normal file
411
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/transport/TBufferTransports.cpp
generated
vendored
Normal file
|
@ -0,0 +1,411 @@
|
|||
/*
|
||||
* 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 accommodate 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 = -1;
|
||||
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");
|
||||
}
|
||||
|
||||
// Check for oversized frame
|
||||
if (sz > static_cast<int32_t>(maxFrameSize_))
|
||||
throw TTransportException(TTransportException::CORRUPTED_DATA, "Received an oversized frame");
|
||||
|
||||
// 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();
|
||||
|
||||
// reclaim write buffer
|
||||
if (wBufSize_ > bufReclaimThresh_) {
|
||||
wBufSize_ = DEFAULT_BUFFER_SIZE;
|
||||
wBuf_.reset(new uint8_t[wBufSize_]);
|
||||
setWriteBuffer(wBuf_.get(), wBufSize_);
|
||||
|
||||
// reset wBase_ with a pad for the frame size
|
||||
int32_t pad = 0;
|
||||
wBase_ = wBuf_.get() + sizeof(pad);
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
uint32_t bytes_read = static_cast<uint32_t>(rBound_ - rBuf_.get() + sizeof(uint32_t));
|
||||
|
||||
if (rBufSize_ > bufReclaimThresh_) {
|
||||
rBufSize_ = 0;
|
||||
rBuf_.reset();
|
||||
setReadBuffer(rBuf_.get(), rBufSize_);
|
||||
}
|
||||
|
||||
return bytes_read;
|
||||
}
|
||||
|
||||
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.
|
||||
uint8_t* new_buffer = static_cast<uint8_t*>(std::realloc(buffer_, new_size));
|
||||
if (new_buffer == NULL) {
|
||||
throw std::bad_alloc();
|
||||
}
|
||||
|
||||
rBase_ = new_buffer + (rBase_ - buffer_);
|
||||
rBound_ = new_buffer + (rBound_ - buffer_);
|
||||
wBase_ = new_buffer + (wBase_ - buffer_);
|
||||
wBound_ = new_buffer + new_size;
|
||||
buffer_ = new_buffer;
|
||||
bufferSize_ = new_size;
|
||||
}
|
||||
|
||||
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
|
718
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/transport/TBufferTransports.h
generated
vendored
Normal file
718
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/transport/TBufferTransports.h
generated
vendored
Normal file
|
@ -0,0 +1,718 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
#ifndef _THRIFT_TRANSPORT_TBUFFERTRANSPORTS_H_
|
||||
#define _THRIFT_TRANSPORT_TBUFFERTRANSPORTS_H_ 1
|
||||
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <limits>
|
||||
#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 accommodate 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();
|
||||
|
||||
/**
|
||||
* Returns the origin of the underlying transport
|
||||
*/
|
||||
virtual const std::string getOrigin() { return transport_->getOrigin(); }
|
||||
|
||||
/**
|
||||
* 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;
|
||||
static const int DEFAULT_MAX_FRAME_SIZE = 256 * 1024 * 1024;
|
||||
|
||||
/// Use default buffer sizes.
|
||||
TFramedTransport()
|
||||
: transport_(),
|
||||
rBufSize_(0),
|
||||
wBufSize_(DEFAULT_BUFFER_SIZE),
|
||||
rBuf_(),
|
||||
wBuf_(new uint8_t[wBufSize_]),
|
||||
bufReclaimThresh_((std::numeric_limits<uint32_t>::max)()) {
|
||||
initPointers();
|
||||
}
|
||||
|
||||
TFramedTransport(boost::shared_ptr<TTransport> transport)
|
||||
: transport_(transport),
|
||||
rBufSize_(0),
|
||||
wBufSize_(DEFAULT_BUFFER_SIZE),
|
||||
rBuf_(),
|
||||
wBuf_(new uint8_t[wBufSize_]),
|
||||
bufReclaimThresh_((std::numeric_limits<uint32_t>::max)()),
|
||||
maxFrameSize_(DEFAULT_MAX_FRAME_SIZE) {
|
||||
initPointers();
|
||||
}
|
||||
|
||||
TFramedTransport(boost::shared_ptr<TTransport> transport,
|
||||
uint32_t sz,
|
||||
uint32_t bufReclaimThresh = (std::numeric_limits<uint32_t>::max)())
|
||||
: transport_(transport),
|
||||
rBufSize_(0),
|
||||
wBufSize_(sz),
|
||||
rBuf_(),
|
||||
wBuf_(new uint8_t[wBufSize_]),
|
||||
bufReclaimThresh_(bufReclaimThresh),
|
||||
maxFrameSize_(DEFAULT_MAX_FRAME_SIZE) {
|
||||
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.
|
||||
*/
|
||||
using TBufferBase::readAll;
|
||||
|
||||
/**
|
||||
* Returns the origin of the underlying transport
|
||||
*/
|
||||
virtual const std::string getOrigin() { return transport_->getOrigin(); }
|
||||
|
||||
/**
|
||||
* Set the maximum size of the frame at read
|
||||
*/
|
||||
void setMaxFrameSize(uint32_t maxFrameSize) { maxFrameSize_ = maxFrameSize; }
|
||||
|
||||
/**
|
||||
* Get the maximum size of the frame at read
|
||||
*/
|
||||
uint32_t getMaxFrameSize() { return maxFrameSize_; }
|
||||
|
||||
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.)
|
||||
*/
|
||||
virtual 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_;
|
||||
uint32_t bufReclaimThresh_;
|
||||
uint32_t maxFrameSize_;
|
||||
};
|
||||
|
||||
/**
|
||||
* 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 accommodate 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
|
||||
|
||||
#endif // #ifndef _THRIFT_TRANSPORT_TBUFFERTRANSPORTS_H_
|
93
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/transport/TFDTransport.cpp
generated
vendored
Normal file
93
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/transport/TFDTransport.cpp
generated
vendored
Normal file
|
@ -0,0 +1,93 @@
|
|||
/*
|
||||
* 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 <cerrno>
|
||||
#include <exception>
|
||||
|
||||
#include <thrift/transport/TFDTransport.h>
|
||||
#include <thrift/transport/PlatformSocket.h>
|
||||
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <io.h>
|
||||
#endif
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace apache {
|
||||
namespace thrift {
|
||||
namespace transport {
|
||||
|
||||
void TFDTransport::close() {
|
||||
if (!isOpen()) {
|
||||
return;
|
||||
}
|
||||
|
||||
int rv = ::THRIFT_CLOSE(fd_);
|
||||
int errno_copy = THRIFT_ERRNO;
|
||||
fd_ = -1;
|
||||
// Have to check uncaught_exception because this is called in the destructor.
|
||||
if (rv < 0 && !std::uncaught_exception()) {
|
||||
throw TTransportException(TTransportException::UNKNOWN, "TFDTransport::close()", errno_copy);
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t TFDTransport::read(uint8_t* buf, uint32_t len) {
|
||||
unsigned int maxRetries = 5; // same as the TSocket default
|
||||
unsigned int retries = 0;
|
||||
while (true) {
|
||||
THRIFT_SSIZET rv = ::THRIFT_READ(fd_, buf, len);
|
||||
if (rv < 0) {
|
||||
if (THRIFT_ERRNO == THRIFT_EINTR && retries < maxRetries) {
|
||||
// If interrupted, try again
|
||||
++retries;
|
||||
continue;
|
||||
}
|
||||
int errno_copy = THRIFT_ERRNO;
|
||||
throw TTransportException(TTransportException::UNKNOWN, "TFDTransport::read()", errno_copy);
|
||||
}
|
||||
// this should be fine, since we already checked for negative values,
|
||||
// and ::read should only return a 32-bit value since len is 32-bit.
|
||||
return static_cast<uint32_t>(rv);
|
||||
}
|
||||
}
|
||||
|
||||
void TFDTransport::write(const uint8_t* buf, uint32_t len) {
|
||||
while (len > 0) {
|
||||
THRIFT_SSIZET rv = ::THRIFT_WRITE(fd_, buf, len);
|
||||
|
||||
if (rv < 0) {
|
||||
int errno_copy = THRIFT_ERRNO;
|
||||
throw TTransportException(TTransportException::UNKNOWN, "TFDTransport::write()", errno_copy);
|
||||
} else if (rv == 0) {
|
||||
throw TTransportException(TTransportException::END_OF_FILE, "TFDTransport::write()");
|
||||
}
|
||||
|
||||
buf += rv;
|
||||
// this should be fine, as we've already checked for negative values, and
|
||||
//::write shouldn't return more than a uint32_t since len is a uint32_t
|
||||
len -= static_cast<uint32_t>(rv);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} // apache::thrift::transport
|
77
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/transport/TFDTransport.h
generated
vendored
Normal file
77
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/transport/TFDTransport.h
generated
vendored
Normal file
|
@ -0,0 +1,77 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
#ifndef _THRIFT_TRANSPORT_TFDTRANSPORT_H_
|
||||
#define _THRIFT_TRANSPORT_TFDTRANSPORT_H_ 1
|
||||
|
||||
#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) {
|
||||
try {
|
||||
close();
|
||||
} catch (TTransportException& ex) {
|
||||
GlobalOutput.printf("~TFDTransport TTransportException: '%s'", ex.what());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
#endif // #ifndef _THRIFT_TRANSPORT_TFDTRANSPORT_H_
|
1069
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/transport/TFileTransport.cpp
generated
vendored
Normal file
1069
vendor/git.apache.org/thrift.git/lib/cpp/src/thrift/transport/TFileTransport.cpp
generated
vendored
Normal file
File diff suppressed because it is too large
Load diff
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue