Index: build-common.xml =================================================================== --- build-common.xml (revision 720079) +++ build-common.xml (working copy) @@ -86,6 +86,9 @@ + + + @@ -215,7 +218,7 @@ - + Index: build.xml =================================================================== --- build.xml (revision 720079) +++ build.xml (working copy) @@ -67,6 +67,9 @@ + + + @@ -89,6 +92,9 @@ + + + Index: service/include/thrift/processor/StatsProcessor.h =================================================================== --- service/include/thrift/processor/StatsProcessor.h (revision 0) +++ service/include/thrift/processor/StatsProcessor.h (revision 0) @@ -0,0 +1,504 @@ +// Copyright (c) 2006- Facebook +// Distributed under the Thrift Software License +// +// See accompanying file LICENSE or visit the Thrift site at: +// http://developers.facebook.com/thrift/ + +#ifndef STATSPROCESSOR_H +#define STATSPROCESSOR_H + +#include +#include +#include +#include + +namespace facebook { namespace thrift { namespace processor { + +/* + * Class for keeping track of function call statistics and printing them if desired + * + * @author James Wang + */ +class StatsProcessor : public facebook::thrift::TProcessor { +public: + StatsProcessor(bool print, bool frequency) + : print_(print), + frequency_(frequency) + {} + virtual ~StatsProcessor() {}; + + virtual bool process(boost::shared_ptr piprot, boost::shared_ptr poprot) { + + piprot_ = piprot; + + std::string fname; + facebook::thrift::protocol::TMessageType mtype; + int32_t seqid; + + piprot_->readMessageBegin(fname, mtype, seqid); + if (mtype != facebook::thrift::protocol::T_CALL) { + if (print_) { + printf("Unknown message type\n"); + } + throw facebook::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; + } + } + + facebook::thrift::protocol::TType ftype; + int16_t fid; + + while (true) { + piprot_->readFieldBegin(fname, ftype, fid); + if (ftype == facebook::thrift::protocol::T_STOP) { + break; + } + + printAndPassToBuffer(ftype); + if (print_) { + printf(", "); + } + } + + if (print_) { + printf("\b\b)\n"); + } + return true; + } + + const std::map& get_frequency_map() { + return frequency_map_; + } + +protected: + void printAndPassToBuffer(facebook::thrift::protocol::TType ftype) { + switch (ftype) { + case facebook::thrift::protocol::T_BOOL: + { + bool boolv; + piprot_->readBool(boolv); + if (print_) { + printf("%d", boolv); + } + } + break; + case facebook::thrift::protocol::T_BYTE: + { + int8_t bytev; + piprot_->readByte(bytev); + if (print_) { + printf("%d", bytev); + } + } + break; + case facebook::thrift::protocol::T_I16: + { + int16_t i16; + piprot_->readI16(i16); + if (print_) { + printf("%d", i16); + } + } + break; + case facebook::thrift::protocol::T_I32: + { + int32_t i32; + piprot_->readI32(i32); + if (print_) { + printf("%d", i32); + } + } + break; + case facebook::thrift::protocol::T_I64: + { + int64_t i64; + piprot_->readI64(i64); + if (print_) { + printf("%ld", i64); + } + } + break; + case facebook::thrift::protocol::T_DOUBLE: + { + double dub; + piprot_->readDouble(dub); + if (print_) { + printf("%f", dub); + } + } + break; + case facebook::thrift::protocol::T_STRING: + { + std::string str; + piprot_->readString(str); + if (print_) { + printf("%s", str.c_str()); + } + } + break; + case facebook::thrift::protocol::T_STRUCT: + { + std::string name; + int16_t fid; + facebook::thrift::protocol::TType ftype; + piprot_->readStructBegin(name); + if (print_) { + printf("<"); + } + while (true) { + piprot_->readFieldBegin(name, ftype, fid); + if (ftype == facebook::thrift::protocol::T_STOP) { + break; + } + printAndPassToBuffer(ftype); + if (print_) { + printf(","); + } + piprot_->readFieldEnd(); + } + piprot_->readStructEnd(); + if (print_) { + printf("\b>"); + } + } + break; + case facebook::thrift::protocol::T_MAP: + { + facebook::thrift::protocol::TType keyType; + facebook::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 facebook::thrift::protocol::T_SET: + { + facebook::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 facebook::thrift::protocol::T_LIST: + { + facebook::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 piprot_; + std::map frequency_map_; + + bool print_; + bool frequency_; +}; + +}}} // facebook::thrift::processor + +#endif +// Copyright (c) 2006- Facebook +// Distributed under the Thrift Software License +// +// See accompanying file LICENSE or visit the Thrift site at: +// http://developers.facebook.com/thrift/ + +#ifndef STATSPROCESSOR_H +#define STATSPROCESSOR_H + +#include +#include +#include +#include + +namespace facebook { namespace thrift { namespace processor { + +/* + * Class for keeping track of function call statistics and printing them if desired + * + * @author James Wang + */ +class StatsProcessor : public facebook::thrift::TProcessor { +public: + StatsProcessor(bool print, bool frequency) + : print_(print), + frequency_(frequency) + {} + virtual ~StatsProcessor() {}; + + virtual bool process(boost::shared_ptr piprot, boost::shared_ptr poprot) { + + piprot_ = piprot; + + std::string fname; + facebook::thrift::protocol::TMessageType mtype; + int32_t seqid; + + piprot_->readMessageBegin(fname, mtype, seqid); + if (mtype != facebook::thrift::protocol::T_CALL) { + if (print_) { + printf("Unknown message type\n"); + } + throw facebook::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; + } + } + + facebook::thrift::protocol::TType ftype; + int16_t fid; + + while (true) { + piprot_->readFieldBegin(fname, ftype, fid); + if (ftype == facebook::thrift::protocol::T_STOP) { + break; + } + + printAndPassToBuffer(ftype); + if (print_) { + printf(", "); + } + } + + if (print_) { + printf("\b\b)\n"); + } + return true; + } + + const std::map& get_frequency_map() { + return frequency_map_; + } + +protected: + void printAndPassToBuffer(facebook::thrift::protocol::TType ftype) { + switch (ftype) { + case facebook::thrift::protocol::T_BOOL: + { + bool boolv; + piprot_->readBool(boolv); + if (print_) { + printf("%d", boolv); + } + } + break; + case facebook::thrift::protocol::T_BYTE: + { + int8_t bytev; + piprot_->readByte(bytev); + if (print_) { + printf("%d", bytev); + } + } + break; + case facebook::thrift::protocol::T_I16: + { + int16_t i16; + piprot_->readI16(i16); + if (print_) { + printf("%d", i16); + } + } + break; + case facebook::thrift::protocol::T_I32: + { + int32_t i32; + piprot_->readI32(i32); + if (print_) { + printf("%d", i32); + } + } + break; + case facebook::thrift::protocol::T_I64: + { + int64_t i64; + piprot_->readI64(i64); + if (print_) { + printf("%ld", i64); + } + } + break; + case facebook::thrift::protocol::T_DOUBLE: + { + double dub; + piprot_->readDouble(dub); + if (print_) { + printf("%f", dub); + } + } + break; + case facebook::thrift::protocol::T_STRING: + { + std::string str; + piprot_->readString(str); + if (print_) { + printf("%s", str.c_str()); + } + } + break; + case facebook::thrift::protocol::T_STRUCT: + { + std::string name; + int16_t fid; + facebook::thrift::protocol::TType ftype; + piprot_->readStructBegin(name); + if (print_) { + printf("<"); + } + while (true) { + piprot_->readFieldBegin(name, ftype, fid); + if (ftype == facebook::thrift::protocol::T_STOP) { + break; + } + printAndPassToBuffer(ftype); + if (print_) { + printf(","); + } + piprot_->readFieldEnd(); + } + piprot_->readStructEnd(); + if (print_) { + printf("\b>"); + } + } + break; + case facebook::thrift::protocol::T_MAP: + { + facebook::thrift::protocol::TType keyType; + facebook::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 facebook::thrift::protocol::T_SET: + { + facebook::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 facebook::thrift::protocol::T_LIST: + { + facebook::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 piprot_; + std::map frequency_map_; + + bool print_; + bool frequency_; +}; + +}}} // facebook::thrift::processor + +#endif Index: service/include/thrift/processor/PeekProcessor.h =================================================================== --- service/include/thrift/processor/PeekProcessor.h (revision 0) +++ service/include/thrift/processor/PeekProcessor.h (revision 0) @@ -0,0 +1,128 @@ +// Copyright (c) 2006- Facebook +// Distributed under the Thrift Software License +// +// See accompanying file LICENSE or visit the Thrift site at: +// http://developers.facebook.com/thrift/ + +#ifndef PEEKPROCESSOR_H +#define PEEKPROCESSOR_H + +#include +#include +#include +#include +#include + +namespace facebook { 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 + * + * @author James Wang + */ +class PeekProcessor : public facebook::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 actualProcessor, + boost::shared_ptr protocolFactory, + boost::shared_ptr transportFactory); + + boost::shared_ptr getPipedTransport(boost::shared_ptr in); + + void setTargetTransport(boost::shared_ptr targetTransport); + + virtual bool process(boost::shared_ptr in, + boost::shared_ptr out); + + // 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 in, + facebook::thrift::protocol::TType ftype, + int16_t fid); + virtual void peekEnd(); + + private: + boost::shared_ptr actualProcessor_; + boost::shared_ptr pipedProtocol_; + boost::shared_ptr transportFactory_; + boost::shared_ptr memoryBuffer_; + boost::shared_ptr targetTransport_; +}; + +}}} // facebook::thrift::processor + +#endif +// Copyright (c) 2006- Facebook +// Distributed under the Thrift Software License +// +// See accompanying file LICENSE or visit the Thrift site at: +// http://developers.facebook.com/thrift/ + +#ifndef PEEKPROCESSOR_H +#define PEEKPROCESSOR_H + +#include +#include +#include +#include +#include + +namespace facebook { 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 + * + * @author James Wang + */ +class PeekProcessor : public facebook::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 actualProcessor, + boost::shared_ptr protocolFactory, + boost::shared_ptr transportFactory); + + boost::shared_ptr getPipedTransport(boost::shared_ptr in); + + void setTargetTransport(boost::shared_ptr targetTransport); + + virtual bool process(boost::shared_ptr in, + boost::shared_ptr out); + + // 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 in, + facebook::thrift::protocol::TType ftype, + int16_t fid); + virtual void peekEnd(); + + private: + boost::shared_ptr actualProcessor_; + boost::shared_ptr pipedProtocol_; + boost::shared_ptr transportFactory_; + boost::shared_ptr memoryBuffer_; + boost::shared_ptr targetTransport_; +}; + +}}} // facebook::thrift::processor + +#endif Index: service/include/thrift/TReflectionLocal.h =================================================================== --- service/include/thrift/TReflectionLocal.h (revision 0) +++ service/include/thrift/TReflectionLocal.h (revision 0) @@ -0,0 +1,168 @@ +// Copyright (c) 2006- Facebook +// Distributed under the Thrift Software License +// +// See accompanying file LICENSE or visit the Thrift site at: +// http://developers.facebook.com/thrift/ + +#ifndef _THRIFT_TREFLECTIONLOCAL_H_ +#define _THRIFT_TREFLECTIONLOCAL_H_ 1 + +#include +#include +#include + +/** + * Local Reflection is a blanket term referring to the the structure + * and generation of this particular representation of Thrift types. + * (It is called local because it cannot be serialized by Thrift). + * + * @author David Reiss + */ + +namespace facebook { namespace thrift { namespace reflection { namespace local { + +using facebook::thrift::protocol::TType; + +// We include this many bytes of the structure's fingerprint when serializing +// a top-level structure. Long enough to make collisions unlikely, short +// enough to not significantly affect the amount of memory used. +const int FP_PREFIX_LEN = 4; + +struct FieldMeta { + int16_t tag; + bool is_optional; +}; + +struct TypeSpec { + TType ttype; + uint8_t fp_prefix[FP_PREFIX_LEN]; + + // Use an anonymous union here so we can fit two TypeSpecs in one cache line. + union { + struct { + // Use parallel arrays here for denser packing (of the arrays). + FieldMeta* metas; + TypeSpec** specs; + } tstruct; + struct { + TypeSpec *subtype1; + TypeSpec *subtype2; + } tcontainer; + }; + + // Static initialization of unions isn't really possible, + // so take the plunge and use constructors. + // Hopefully they'll be evaluated at compile time. + + TypeSpec(TType ttype) : ttype(ttype) { + std::memset(fp_prefix, 0, FP_PREFIX_LEN); + } + + TypeSpec(TType ttype, + const uint8_t* fingerprint, + FieldMeta* metas, + TypeSpec** specs) : + ttype(ttype) + { + std::memcpy(fp_prefix, fingerprint, FP_PREFIX_LEN); + tstruct.metas = metas; + tstruct.specs = specs; + } + + TypeSpec(TType ttype, TypeSpec* subtype1, TypeSpec* subtype2) : + ttype(ttype) + { + std::memset(fp_prefix, 0, FP_PREFIX_LEN); + tcontainer.subtype1 = subtype1; + tcontainer.subtype2 = subtype2; + } + +}; + +}}}} // facebook::thrift::reflection::local + +#endif // #ifndef _THRIFT_TREFLECTIONLOCAL_H_ +// Copyright (c) 2006- Facebook +// Distributed under the Thrift Software License +// +// See accompanying file LICENSE or visit the Thrift site at: +// http://developers.facebook.com/thrift/ + +#ifndef _THRIFT_TREFLECTIONLOCAL_H_ +#define _THRIFT_TREFLECTIONLOCAL_H_ 1 + +#include +#include +#include + +/** + * Local Reflection is a blanket term referring to the the structure + * and generation of this particular representation of Thrift types. + * (It is called local because it cannot be serialized by Thrift). + * + * @author David Reiss + */ + +namespace facebook { namespace thrift { namespace reflection { namespace local { + +using facebook::thrift::protocol::TType; + +// We include this many bytes of the structure's fingerprint when serializing +// a top-level structure. Long enough to make collisions unlikely, short +// enough to not significantly affect the amount of memory used. +const int FP_PREFIX_LEN = 4; + +struct FieldMeta { + int16_t tag; + bool is_optional; +}; + +struct TypeSpec { + TType ttype; + uint8_t fp_prefix[FP_PREFIX_LEN]; + + // Use an anonymous union here so we can fit two TypeSpecs in one cache line. + union { + struct { + // Use parallel arrays here for denser packing (of the arrays). + FieldMeta* metas; + TypeSpec** specs; + } tstruct; + struct { + TypeSpec *subtype1; + TypeSpec *subtype2; + } tcontainer; + }; + + // Static initialization of unions isn't really possible, + // so take the plunge and use constructors. + // Hopefully they'll be evaluated at compile time. + + TypeSpec(TType ttype) : ttype(ttype) { + std::memset(fp_prefix, 0, FP_PREFIX_LEN); + } + + TypeSpec(TType ttype, + const uint8_t* fingerprint, + FieldMeta* metas, + TypeSpec** specs) : + ttype(ttype) + { + std::memcpy(fp_prefix, fingerprint, FP_PREFIX_LEN); + tstruct.metas = metas; + tstruct.specs = specs; + } + + TypeSpec(TType ttype, TypeSpec* subtype1, TypeSpec* subtype2) : + ttype(ttype) + { + std::memset(fp_prefix, 0, FP_PREFIX_LEN); + tcontainer.subtype1 = subtype1; + tcontainer.subtype2 = subtype2; + } + +}; + +}}}} // facebook::thrift::reflection::local + +#endif // #ifndef _THRIFT_TREFLECTIONLOCAL_H_ Index: service/include/thrift/TLogging.h =================================================================== --- service/include/thrift/TLogging.h (revision 0) +++ service/include/thrift/TLogging.h (revision 0) @@ -0,0 +1,302 @@ +// Copyright (c) 2006- Facebook +// Distributed under the Thrift Software License +// +// See accompanying file LICENSE or visit the Thrift site at: +// http://developers.facebook.com/thrift/ + +#ifndef _THRIFT_TLOGGING_H_ +#define _THRIFT_TLOGGING_H_ 1 + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +/** + * Contains utility macros for debugging and logging. + * + * @author Aditya Agarwal + */ + +#ifndef HAVE_CLOCK_GETTIME +#include +#else +#include +#endif + +#ifdef HAVE_STDINT_H +#include +#endif + +/** + * T_GLOBAL_DEBUGGING_LEVEL = 0: all debugging turned off, debug macros undefined + * T_GLOBAL_DEBUGGING_LEVEL = 1: all debugging turned on + */ +#define T_GLOBAL_DEBUGGING_LEVEL 0 + + +/** + * T_GLOBAL_LOGGING_LEVEL = 0: all logging turned off, logging macros undefined + * T_GLOBAL_LOGGING_LEVEL = 1: all logging turned on + */ +#define T_GLOBAL_LOGGING_LEVEL 1 + + +/** + * Standard wrapper around fprintf what will prefix the file name and line + * number to the line. Uses T_GLOBAL_DEBUGGING_LEVEL to control whether it is + * turned on or off. + * + * @param format_string + */ +#if T_GLOBAL_DEBUGGING_LEVEL > 0 + #define T_DEBUG(format_string,...) \ + if (T_GLOBAL_DEBUGGING_LEVEL > 0) { \ + fprintf(stderr,"[%s,%d] " #format_string " \n", __FILE__, __LINE__,##__VA_ARGS__); \ + } +#else + #define T_DEBUG(format_string,...) +#endif + + +/** + * analagous to T_DEBUG but also prints the time + * + * @param string format_string input: printf style format string + */ +#if T_GLOBAL_DEBUGGING_LEVEL > 0 + #define T_DEBUG_T(format_string,...) \ + { \ + if (T_GLOBAL_DEBUGGING_LEVEL > 0) { \ + time_t now; \ + char dbgtime[26] ; \ + time(&now); \ + ctime_r(&now, dbgtime); \ + dbgtime[24] = '\0'; \ + fprintf(stderr,"[%s,%d] [%s] " #format_string " \n", __FILE__, __LINE__,dbgtime,##__VA_ARGS__); \ + } \ + } +#else + #define T_DEBUG_T(format_string,...) +#endif + + +/** + * analagous to T_DEBUG but uses input level to determine whether or not the string + * should be logged. + * + * @param int level: specified debug level + * @param string format_string input: format string + */ +#define T_DEBUG_L(level, format_string,...) \ + if ((level) > 0) { \ + fprintf(stderr,"[%s,%d] " #format_string " \n", __FILE__, __LINE__,##__VA_ARGS__); \ + } + + +/** + * Explicit error logging. Prints time, file name and line number + * + * @param string format_string input: printf style format string + */ +#define T_ERROR(format_string,...) \ + { \ + time_t now; \ + char dbgtime[26] ; \ + time(&now); \ + ctime_r(&now, dbgtime); \ + dbgtime[24] = '\0'; \ + fprintf(stderr,"[%s,%d] [%s] ERROR: " #format_string " \n", __FILE__, __LINE__,dbgtime,##__VA_ARGS__); \ + } + + +/** + * Analagous to T_ERROR, additionally aborting the process. + * WARNING: macro calls abort(), ending program execution + * + * @param string format_string input: printf style format string + */ +#define T_ERROR_ABORT(format_string,...) \ + { \ + time_t now; \ + char dbgtime[26] ; \ + time(&now); \ + 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); \ + ctime_r(&now, dbgtime); \ + dbgtime[24] = '\0'; \ + fprintf(stderr,"[%s] " #format_string " \n", dbgtime,##__VA_ARGS__); \ + } \ + } +#else + #define T_LOG_OPER(format_string,...) +#endif + +#endif // #ifndef _THRIFT_TLOGGING_H_ +// Copyright (c) 2006- Facebook +// Distributed under the Thrift Software License +// +// See accompanying file LICENSE or visit the Thrift site at: +// http://developers.facebook.com/thrift/ + +#ifndef _THRIFT_TLOGGING_H_ +#define _THRIFT_TLOGGING_H_ 1 + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +/** + * Contains utility macros for debugging and logging. + * + * @author Aditya Agarwal + */ + +#ifndef HAVE_CLOCK_GETTIME +#include +#else +#include +#endif + +#ifdef HAVE_STDINT_H +#include +#endif + +/** + * T_GLOBAL_DEBUGGING_LEVEL = 0: all debugging turned off, debug macros undefined + * T_GLOBAL_DEBUGGING_LEVEL = 1: all debugging turned on + */ +#define T_GLOBAL_DEBUGGING_LEVEL 0 + + +/** + * T_GLOBAL_LOGGING_LEVEL = 0: all logging turned off, logging macros undefined + * T_GLOBAL_LOGGING_LEVEL = 1: all logging turned on + */ +#define T_GLOBAL_LOGGING_LEVEL 1 + + +/** + * Standard wrapper around fprintf what will prefix the file name and line + * number to the line. Uses T_GLOBAL_DEBUGGING_LEVEL to control whether it is + * turned on or off. + * + * @param format_string + */ +#if T_GLOBAL_DEBUGGING_LEVEL > 0 + #define T_DEBUG(format_string,...) \ + if (T_GLOBAL_DEBUGGING_LEVEL > 0) { \ + fprintf(stderr,"[%s,%d] " #format_string " \n", __FILE__, __LINE__,##__VA_ARGS__); \ + } +#else + #define T_DEBUG(format_string,...) +#endif + + +/** + * analagous to T_DEBUG but also prints the time + * + * @param string format_string input: printf style format string + */ +#if T_GLOBAL_DEBUGGING_LEVEL > 0 + #define T_DEBUG_T(format_string,...) \ + { \ + if (T_GLOBAL_DEBUGGING_LEVEL > 0) { \ + time_t now; \ + char dbgtime[26] ; \ + time(&now); \ + ctime_r(&now, dbgtime); \ + dbgtime[24] = '\0'; \ + fprintf(stderr,"[%s,%d] [%s] " #format_string " \n", __FILE__, __LINE__,dbgtime,##__VA_ARGS__); \ + } \ + } +#else + #define T_DEBUG_T(format_string,...) +#endif + + +/** + * analagous to T_DEBUG but uses input level to determine whether or not the string + * should be logged. + * + * @param int level: specified debug level + * @param string format_string input: format string + */ +#define T_DEBUG_L(level, format_string,...) \ + if ((level) > 0) { \ + fprintf(stderr,"[%s,%d] " #format_string " \n", __FILE__, __LINE__,##__VA_ARGS__); \ + } + + +/** + * Explicit error logging. Prints time, file name and line number + * + * @param string format_string input: printf style format string + */ +#define T_ERROR(format_string,...) \ + { \ + time_t now; \ + char dbgtime[26] ; \ + time(&now); \ + ctime_r(&now, dbgtime); \ + dbgtime[24] = '\0'; \ + fprintf(stderr,"[%s,%d] [%s] ERROR: " #format_string " \n", __FILE__, __LINE__,dbgtime,##__VA_ARGS__); \ + } + + +/** + * Analagous to T_ERROR, additionally aborting the process. + * WARNING: macro calls abort(), ending program execution + * + * @param string format_string input: printf style format string + */ +#define T_ERROR_ABORT(format_string,...) \ + { \ + time_t now; \ + char dbgtime[26] ; \ + time(&now); \ + 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); \ + ctime_r(&now, dbgtime); \ + dbgtime[24] = '\0'; \ + fprintf(stderr,"[%s] " #format_string " \n", dbgtime,##__VA_ARGS__); \ + } \ + } +#else + #define T_LOG_OPER(format_string,...) +#endif + +#endif // #ifndef _THRIFT_TLOGGING_H_ Index: service/include/thrift/protocol/TBinaryProtocol.h =================================================================== --- service/include/thrift/protocol/TBinaryProtocol.h (revision 0) +++ service/include/thrift/protocol/TBinaryProtocol.h (revision 0) @@ -0,0 +1,478 @@ +// Copyright (c) 2006- Facebook +// Distributed under the Thrift Software License +// +// See accompanying file LICENSE or visit the Thrift site at: +// http://developers.facebook.com/thrift/ + +#ifndef _THRIFT_PROTOCOL_TBINARYPROTOCOL_H_ +#define _THRIFT_PROTOCOL_TBINARYPROTOCOL_H_ 1 + +#include "TProtocol.h" + +#include + +namespace facebook { 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. + * + * @author Mark Slee + */ +class TBinaryProtocol : public TProtocol { + protected: + static const int32_t VERSION_MASK = 0xffff0000; + static const int32_t VERSION_1 = 0x80010000; + // VERSION_2 (0x80020000) is taken by TDenseProtocol. + + public: + TBinaryProtocol(boost::shared_ptr trans) : + TProtocol(trans), + string_limit_(0), + container_limit_(0), + strict_read_(false), + strict_write_(true), + string_buf_(NULL), + string_buf_size_(0) {} + + TBinaryProtocol(boost::shared_ptr trans, + int32_t string_limit, + int32_t container_limit, + bool strict_read, + bool strict_write) : + TProtocol(trans), + string_limit_(string_limit), + container_limit_(container_limit), + strict_read_(strict_read), + strict_write_(strict_write), + string_buf_(NULL), + string_buf_size_(0) {} + + ~TBinaryProtocol() { + if (string_buf_ != NULL) { + free(string_buf_); + string_buf_size_ = 0; + } + } + + void setStringSizeLimit(int32_t string_limit) { + string_limit_ = string_limit; + } + + void setContainerSizeLimit(int32_t container_limit) { + container_limit_ = container_limit; + } + + void setStrict(bool strict_read, bool strict_write) { + strict_read_ = strict_read; + strict_write_ = strict_write; + } + + /** + * Writing functions. + */ + + virtual uint32_t writeMessageBegin(const std::string& name, + const TMessageType messageType, + const int32_t seqid); + + virtual uint32_t writeMessageEnd(); + + + uint32_t writeStructBegin(const std::string& name); + + uint32_t writeStructEnd(); + + uint32_t writeFieldBegin(const std::string& 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); + + /** + * 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); + + 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); + + protected: + uint32_t readStringBody(std::string& str, int32_t sz); + + int32_t string_limit_; + int32_t container_limit_; + + // Enforce presence of version identifier + bool strict_read_; + bool strict_write_; + + // Buffer for reading strings, save for the lifetime of the protocol to + // avoid memory churn allocating memory on every string read + uint8_t* string_buf_; + int32_t string_buf_size_; + +}; + +/** + * Constructs binary protocol handlers + */ +class TBinaryProtocolFactory : public TProtocolFactory { + public: + TBinaryProtocolFactory() : + string_limit_(0), + container_limit_(0), + strict_read_(false), + strict_write_(true) {} + + TBinaryProtocolFactory(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 ~TBinaryProtocolFactory() {} + + 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 getProtocol(boost::shared_ptr trans) { + return boost::shared_ptr(new TBinaryProtocol(trans, string_limit_, container_limit_, strict_read_, strict_write_)); + } + + private: + int32_t string_limit_; + int32_t container_limit_; + bool strict_read_; + bool strict_write_; + +}; + +}}} // facebook::thrift::protocol + +#endif // #ifndef _THRIFT_PROTOCOL_TBINARYPROTOCOL_H_ +// Copyright (c) 2006- Facebook +// Distributed under the Thrift Software License +// +// See accompanying file LICENSE or visit the Thrift site at: +// http://developers.facebook.com/thrift/ + +#ifndef _THRIFT_PROTOCOL_TBINARYPROTOCOL_H_ +#define _THRIFT_PROTOCOL_TBINARYPROTOCOL_H_ 1 + +#include "TProtocol.h" + +#include + +namespace facebook { 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. + * + * @author Mark Slee + */ +class TBinaryProtocol : public TProtocol { + protected: + static const int32_t VERSION_MASK = 0xffff0000; + static const int32_t VERSION_1 = 0x80010000; + // VERSION_2 (0x80020000) is taken by TDenseProtocol. + + public: + TBinaryProtocol(boost::shared_ptr trans) : + TProtocol(trans), + string_limit_(0), + container_limit_(0), + strict_read_(false), + strict_write_(true), + string_buf_(NULL), + string_buf_size_(0) {} + + TBinaryProtocol(boost::shared_ptr trans, + int32_t string_limit, + int32_t container_limit, + bool strict_read, + bool strict_write) : + TProtocol(trans), + string_limit_(string_limit), + container_limit_(container_limit), + strict_read_(strict_read), + strict_write_(strict_write), + string_buf_(NULL), + string_buf_size_(0) {} + + ~TBinaryProtocol() { + if (string_buf_ != NULL) { + free(string_buf_); + string_buf_size_ = 0; + } + } + + void setStringSizeLimit(int32_t string_limit) { + string_limit_ = string_limit; + } + + void setContainerSizeLimit(int32_t container_limit) { + container_limit_ = container_limit; + } + + void setStrict(bool strict_read, bool strict_write) { + strict_read_ = strict_read; + strict_write_ = strict_write; + } + + /** + * Writing functions. + */ + + virtual uint32_t writeMessageBegin(const std::string& name, + const TMessageType messageType, + const int32_t seqid); + + virtual uint32_t writeMessageEnd(); + + + uint32_t writeStructBegin(const std::string& name); + + uint32_t writeStructEnd(); + + uint32_t writeFieldBegin(const std::string& 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); + + /** + * 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); + + 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); + + protected: + uint32_t readStringBody(std::string& str, int32_t sz); + + int32_t string_limit_; + int32_t container_limit_; + + // Enforce presence of version identifier + bool strict_read_; + bool strict_write_; + + // Buffer for reading strings, save for the lifetime of the protocol to + // avoid memory churn allocating memory on every string read + uint8_t* string_buf_; + int32_t string_buf_size_; + +}; + +/** + * Constructs binary protocol handlers + */ +class TBinaryProtocolFactory : public TProtocolFactory { + public: + TBinaryProtocolFactory() : + string_limit_(0), + container_limit_(0), + strict_read_(false), + strict_write_(true) {} + + TBinaryProtocolFactory(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 ~TBinaryProtocolFactory() {} + + 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 getProtocol(boost::shared_ptr trans) { + return boost::shared_ptr(new TBinaryProtocol(trans, string_limit_, container_limit_, strict_read_, strict_write_)); + } + + private: + int32_t string_limit_; + int32_t container_limit_; + bool strict_read_; + bool strict_write_; + +}; + +}}} // facebook::thrift::protocol + +#endif // #ifndef _THRIFT_PROTOCOL_TBINARYPROTOCOL_H_ Index: service/include/thrift/protocol/TDebugProtocol.h =================================================================== --- service/include/thrift/protocol/TDebugProtocol.h (revision 0) +++ service/include/thrift/protocol/TDebugProtocol.h (revision 0) @@ -0,0 +1,388 @@ +// Copyright (c) 2006- Facebook +// Distributed under the Thrift Software License +// +// See accompanying file LICENSE or visit the Thrift site at: +// http://developers.facebook.com/thrift/ + +#ifndef _THRIFT_PROTOCOL_TDEBUGPROTOCOL_H_ +#define _THRIFT_PROTOCOL_TDEBUGPROTOCOL_H_ 1 + +#include "TProtocol.h" +#include "TOneWayProtocol.h" + +#include + +#include + +namespace facebook { 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. + * + * @author David Reiss + */ +class TDebugProtocol : public TWriteOnlyProtocol { + private: + enum write_state_t { + UNINIT, + STRUCT, + LIST, + SET, + MAP_KEY, + MAP_VALUE, + }; + + public: + TDebugProtocol(boost::shared_ptr trans) + : TWriteOnlyProtocol(trans, "TDebugProtocol") + { + write_state_.push_back(UNINIT); + } + + + virtual uint32_t writeMessageBegin(const std::string& name, + const TMessageType messageType, + const int32_t seqid); + + virtual uint32_t writeMessageEnd(); + + + uint32_t writeStructBegin(const std::string& name); + + uint32_t writeStructEnd(); + + uint32_t writeFieldBegin(const std::string& 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); + + + 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); + + std::string indent_str_; + static const int indent_inc = 2; + + std::vector write_state_; + std::vector list_idx_; +}; + +/** + * Constructs debug protocol handlers + */ +class TDebugProtocolFactory : public TProtocolFactory { + public: + TDebugProtocolFactory() {} + virtual ~TDebugProtocolFactory() {} + + boost::shared_ptr getProtocol(boost::shared_ptr trans) { + return boost::shared_ptr(new TDebugProtocol(trans)); + } + +}; + +}}} // facebook::thrift::protocol + + +namespace facebook { namespace thrift { + +template +std::string ThriftDebugString(const ThriftStruct& ts) { + using namespace facebook::thrift::transport; + using namespace facebook::thrift::protocol; + TMemoryBuffer* buffer = new TMemoryBuffer; + boost::shared_ptr 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 +std::string DebugString(const std::vector& vec) { + using namespace facebook::thrift::transport; + using namespace facebook::thrift::protocol; + TMemoryBuffer* buffer = new TMemoryBuffer; + boost::shared_ptr 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::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 + +}} // facebook::thrift + + +#endif // #ifndef _THRIFT_PROTOCOL_TDEBUGPROTOCOL_H_ + + +// Copyright (c) 2006- Facebook +// Distributed under the Thrift Software License +// +// See accompanying file LICENSE or visit the Thrift site at: +// http://developers.facebook.com/thrift/ + +#ifndef _THRIFT_PROTOCOL_TDEBUGPROTOCOL_H_ +#define _THRIFT_PROTOCOL_TDEBUGPROTOCOL_H_ 1 + +#include "TProtocol.h" +#include "TOneWayProtocol.h" + +#include + +#include + +namespace facebook { 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. + * + * @author David Reiss + */ +class TDebugProtocol : public TWriteOnlyProtocol { + private: + enum write_state_t { + UNINIT, + STRUCT, + LIST, + SET, + MAP_KEY, + MAP_VALUE, + }; + + public: + TDebugProtocol(boost::shared_ptr trans) + : TWriteOnlyProtocol(trans, "TDebugProtocol") + { + write_state_.push_back(UNINIT); + } + + + virtual uint32_t writeMessageBegin(const std::string& name, + const TMessageType messageType, + const int32_t seqid); + + virtual uint32_t writeMessageEnd(); + + + uint32_t writeStructBegin(const std::string& name); + + uint32_t writeStructEnd(); + + uint32_t writeFieldBegin(const std::string& 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); + + + 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); + + std::string indent_str_; + static const int indent_inc = 2; + + std::vector write_state_; + std::vector list_idx_; +}; + +/** + * Constructs debug protocol handlers + */ +class TDebugProtocolFactory : public TProtocolFactory { + public: + TDebugProtocolFactory() {} + virtual ~TDebugProtocolFactory() {} + + boost::shared_ptr getProtocol(boost::shared_ptr trans) { + return boost::shared_ptr(new TDebugProtocol(trans)); + } + +}; + +}}} // facebook::thrift::protocol + + +namespace facebook { namespace thrift { + +template +std::string ThriftDebugString(const ThriftStruct& ts) { + using namespace facebook::thrift::transport; + using namespace facebook::thrift::protocol; + TMemoryBuffer* buffer = new TMemoryBuffer; + boost::shared_ptr 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 +std::string DebugString(const std::vector& vec) { + using namespace facebook::thrift::transport; + using namespace facebook::thrift::protocol; + TMemoryBuffer* buffer = new TMemoryBuffer; + boost::shared_ptr 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::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 + +}} // facebook::thrift + + +#endif // #ifndef _THRIFT_PROTOCOL_TDEBUGPROTOCOL_H_ + + Index: service/include/thrift/protocol/TDenseProtocol.h =================================================================== --- service/include/thrift/protocol/TDenseProtocol.h (revision 0) +++ service/include/thrift/protocol/TDenseProtocol.h (revision 0) @@ -0,0 +1,476 @@ +// Copyright (c) 2006- Facebook +// Distributed under the Thrift Software License +// +// See accompanying file LICENSE or visit the Thrift site at: +// http://developers.facebook.com/thrift/ + +#ifndef _THRIFT_PROTOCOL_TDENSEPROTOCOL_H_ +#define _THRIFT_PROTOCOL_TDENSEPROTOCOL_H_ 1 + +#include "TBinaryProtocol.h" + +namespace facebook { namespace thrift { namespace protocol { + +/** + * !!!WARNING!!! + * This class is still highly experimental. Incompatible changes + * WILL be made to it without notice. DO NOT USE IT YET unless + * you are coordinating your testing with the author. + * + * The dense protocol is designed to use as little space as possible. + * + * There are two types of dense protocol instances. Standalone instances + * are not used for RPC and just encoded and decode structures of + * a predetermined type. Non-standalone instances are used for RPC. + * Currently, only standalone instances exist. + * + * To use a standalone dense protocol object, you must set the type_spec + * property (either in the constructor, or with setTypeSpec) to the local + * reflection TypeSpec of the structures you will write to (or read from) the + * protocol instance. + * + * BEST PRACTICES: + * - Never use optional for primitives or containers. + * - Only use optional for structures if they are very big and very rarely set. + * - All integers are variable-length, so you can use i64 without bloating. + * - NEVER EVER change the struct definitions IN ANY WAY without either + * changing your cache keys or talking to dreiss. + * + * TODO(dreiss): New class write with old meta. + * + * We override all of TBinaryProtocol's methods. + * We inherit so that we can can explicitly call TBPs's primitive-writing + * methods within our versions. + * + * @author David Reiss + */ +class TDenseProtocol : public TBinaryProtocol { + protected: + static const int32_t VERSION_MASK = 0xffff0000; + // VERSION_1 (0x80010000) is taken by TBinaryProtocol. + static const int32_t VERSION_2 = 0x80020000; + + public: + typedef facebook::thrift::reflection::local::TypeSpec TypeSpec; + static const int FP_PREFIX_LEN; + + /** + * @param tran The transport to use. + * @param type_spec The TypeSpec of the structures using this protocol. + */ + TDenseProtocol(boost::shared_ptr trans, + TypeSpec* type_spec = NULL) : + TBinaryProtocol(trans), + type_spec_(type_spec), + standalone_(true) + {} + + void setTypeSpec(TypeSpec* type_spec) { + type_spec_ = type_spec; + } + TypeSpec* getTypeSpec() { + return type_spec_; + } + + + /* + * Writing functions. + */ + + virtual uint32_t writeMessageBegin(const std::string& name, + const TMessageType messageType, + const int32_t seqid); + + virtual uint32_t writeMessageEnd(); + + + virtual uint32_t writeStructBegin(const std::string& name); + + virtual uint32_t writeStructEnd(); + + virtual uint32_t writeFieldBegin(const std::string& name, + const TType fieldType, + const int16_t fieldId); + + virtual uint32_t writeFieldEnd(); + + virtual uint32_t writeFieldStop(); + + virtual uint32_t writeMapBegin(const TType keyType, + const TType valType, + const uint32_t size); + + virtual uint32_t writeMapEnd(); + + virtual uint32_t writeListBegin(const TType elemType, + const uint32_t size); + + virtual uint32_t writeListEnd(); + + virtual uint32_t writeSetBegin(const TType elemType, + const uint32_t size); + + virtual uint32_t writeSetEnd(); + + virtual uint32_t writeBool(const bool value); + + virtual uint32_t writeByte(const int8_t byte); + + virtual uint32_t writeI16(const int16_t i16); + + virtual uint32_t writeI32(const int32_t i32); + + virtual uint32_t writeI64(const int64_t i64); + + virtual uint32_t writeDouble(const double dub); + + virtual uint32_t writeString(const std::string& str); + + + /* + * Helper writing functions (don't do state transitions). + */ + inline uint32_t subWriteI32(const int32_t i32); + + inline uint32_t subWriteString(const std::string& str); + + uint32_t subWriteBool(const bool value) { + return TBinaryProtocol::writeBool(value); + } + + + /* + * Reading functions + */ + + uint32_t readMessageBegin(std::string& name, + TMessageType& messageType, + int32_t& seqid); + + uint32_t readMessageEnd(); + + uint32_t readStructBegin(std::string& name); + + uint32_t readStructEnd(); + + uint32_t readFieldBegin(std::string& name, + TType& fieldType, + int16_t& fieldId); + + uint32_t readFieldEnd(); + + uint32_t readMapBegin(TType& keyType, + TType& valType, + uint32_t& size); + + uint32_t readMapEnd(); + + uint32_t readListBegin(TType& elemType, + uint32_t& size); + + uint32_t readListEnd(); + + uint32_t readSetBegin(TType& elemType, + uint32_t& size); + + uint32_t readSetEnd(); + + uint32_t readBool(bool& value); + + 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); + + + /* + * Helper reading functions (don't do state transitions). + */ + inline uint32_t subReadI32(int32_t& i32); + + inline uint32_t subReadString(std::string& str); + + uint32_t subReadBool(bool& value) { + return TBinaryProtocol::readBool(value); + } + + + private: + + // Implementation functions, documented in the .cpp. + inline void checkTType(const TType ttype); + inline void stateTransition(); + + // Read and write variable-length integers. + // Uses the same technique as the MIDI file format. + inline uint32_t vlqRead(uint64_t& vlq); + inline uint32_t vlqWrite(uint64_t vlq); + + // Called before throwing an exception to make the object reusable. + void resetState() { + ts_stack_.clear(); + idx_stack_.clear(); + mkv_stack_.clear(); + } + + // TypeSpec of the top-level structure to write, + // for standalone protocol objects. + TypeSpec* type_spec_; + + std::vector ts_stack_; // TypeSpec stack. + std::vector idx_stack_; // InDeX stack. + std::vector mkv_stack_; // Map Key/Vlue stack. + // True = key, False = value. + + // True iff this is a standalone instance (no RPC). + bool standalone_; +}; + +}}} // facebook::thrift::protocol + +#endif // #ifndef _THRIFT_PROTOCOL_TDENSEPROTOCOL_H_ +// Copyright (c) 2006- Facebook +// Distributed under the Thrift Software License +// +// See accompanying file LICENSE or visit the Thrift site at: +// http://developers.facebook.com/thrift/ + +#ifndef _THRIFT_PROTOCOL_TDENSEPROTOCOL_H_ +#define _THRIFT_PROTOCOL_TDENSEPROTOCOL_H_ 1 + +#include "TBinaryProtocol.h" + +namespace facebook { namespace thrift { namespace protocol { + +/** + * !!!WARNING!!! + * This class is still highly experimental. Incompatible changes + * WILL be made to it without notice. DO NOT USE IT YET unless + * you are coordinating your testing with the author. + * + * The dense protocol is designed to use as little space as possible. + * + * There are two types of dense protocol instances. Standalone instances + * are not used for RPC and just encoded and decode structures of + * a predetermined type. Non-standalone instances are used for RPC. + * Currently, only standalone instances exist. + * + * To use a standalone dense protocol object, you must set the type_spec + * property (either in the constructor, or with setTypeSpec) to the local + * reflection TypeSpec of the structures you will write to (or read from) the + * protocol instance. + * + * BEST PRACTICES: + * - Never use optional for primitives or containers. + * - Only use optional for structures if they are very big and very rarely set. + * - All integers are variable-length, so you can use i64 without bloating. + * - NEVER EVER change the struct definitions IN ANY WAY without either + * changing your cache keys or talking to dreiss. + * + * TODO(dreiss): New class write with old meta. + * + * We override all of TBinaryProtocol's methods. + * We inherit so that we can can explicitly call TBPs's primitive-writing + * methods within our versions. + * + * @author David Reiss + */ +class TDenseProtocol : public TBinaryProtocol { + protected: + static const int32_t VERSION_MASK = 0xffff0000; + // VERSION_1 (0x80010000) is taken by TBinaryProtocol. + static const int32_t VERSION_2 = 0x80020000; + + public: + typedef facebook::thrift::reflection::local::TypeSpec TypeSpec; + static const int FP_PREFIX_LEN; + + /** + * @param tran The transport to use. + * @param type_spec The TypeSpec of the structures using this protocol. + */ + TDenseProtocol(boost::shared_ptr trans, + TypeSpec* type_spec = NULL) : + TBinaryProtocol(trans), + type_spec_(type_spec), + standalone_(true) + {} + + void setTypeSpec(TypeSpec* type_spec) { + type_spec_ = type_spec; + } + TypeSpec* getTypeSpec() { + return type_spec_; + } + + + /* + * Writing functions. + */ + + virtual uint32_t writeMessageBegin(const std::string& name, + const TMessageType messageType, + const int32_t seqid); + + virtual uint32_t writeMessageEnd(); + + + virtual uint32_t writeStructBegin(const std::string& name); + + virtual uint32_t writeStructEnd(); + + virtual uint32_t writeFieldBegin(const std::string& name, + const TType fieldType, + const int16_t fieldId); + + virtual uint32_t writeFieldEnd(); + + virtual uint32_t writeFieldStop(); + + virtual uint32_t writeMapBegin(const TType keyType, + const TType valType, + const uint32_t size); + + virtual uint32_t writeMapEnd(); + + virtual uint32_t writeListBegin(const TType elemType, + const uint32_t size); + + virtual uint32_t writeListEnd(); + + virtual uint32_t writeSetBegin(const TType elemType, + const uint32_t size); + + virtual uint32_t writeSetEnd(); + + virtual uint32_t writeBool(const bool value); + + virtual uint32_t writeByte(const int8_t byte); + + virtual uint32_t writeI16(const int16_t i16); + + virtual uint32_t writeI32(const int32_t i32); + + virtual uint32_t writeI64(const int64_t i64); + + virtual uint32_t writeDouble(const double dub); + + virtual uint32_t writeString(const std::string& str); + + + /* + * Helper writing functions (don't do state transitions). + */ + inline uint32_t subWriteI32(const int32_t i32); + + inline uint32_t subWriteString(const std::string& str); + + uint32_t subWriteBool(const bool value) { + return TBinaryProtocol::writeBool(value); + } + + + /* + * Reading functions + */ + + uint32_t readMessageBegin(std::string& name, + TMessageType& messageType, + int32_t& seqid); + + uint32_t readMessageEnd(); + + uint32_t readStructBegin(std::string& name); + + uint32_t readStructEnd(); + + uint32_t readFieldBegin(std::string& name, + TType& fieldType, + int16_t& fieldId); + + uint32_t readFieldEnd(); + + uint32_t readMapBegin(TType& keyType, + TType& valType, + uint32_t& size); + + uint32_t readMapEnd(); + + uint32_t readListBegin(TType& elemType, + uint32_t& size); + + uint32_t readListEnd(); + + uint32_t readSetBegin(TType& elemType, + uint32_t& size); + + uint32_t readSetEnd(); + + uint32_t readBool(bool& value); + + 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); + + + /* + * Helper reading functions (don't do state transitions). + */ + inline uint32_t subReadI32(int32_t& i32); + + inline uint32_t subReadString(std::string& str); + + uint32_t subReadBool(bool& value) { + return TBinaryProtocol::readBool(value); + } + + + private: + + // Implementation functions, documented in the .cpp. + inline void checkTType(const TType ttype); + inline void stateTransition(); + + // Read and write variable-length integers. + // Uses the same technique as the MIDI file format. + inline uint32_t vlqRead(uint64_t& vlq); + inline uint32_t vlqWrite(uint64_t vlq); + + // Called before throwing an exception to make the object reusable. + void resetState() { + ts_stack_.clear(); + idx_stack_.clear(); + mkv_stack_.clear(); + } + + // TypeSpec of the top-level structure to write, + // for standalone protocol objects. + TypeSpec* type_spec_; + + std::vector ts_stack_; // TypeSpec stack. + std::vector idx_stack_; // InDeX stack. + std::vector mkv_stack_; // Map Key/Vlue stack. + // True = key, False = value. + + // True iff this is a standalone instance (no RPC). + bool standalone_; +}; + +}}} // facebook::thrift::protocol + +#endif // #ifndef _THRIFT_PROTOCOL_TDENSEPROTOCOL_H_ Index: service/include/thrift/protocol/TProtocolException.h =================================================================== --- service/include/thrift/protocol/TProtocolException.h (revision 0) +++ service/include/thrift/protocol/TProtocolException.h (revision 0) @@ -0,0 +1,186 @@ +// Copyright (c) 2006- Facebook +// Distributed under the Thrift Software License +// +// See accompanying file LICENSE or visit the Thrift site at: +// http://developers.facebook.com/thrift/ + +#ifndef _THRIFT_PROTOCOL_TPROTOCOLEXCEPTION_H_ +#define _THRIFT_PROTOCOL_TPROTOCOLEXCEPTION_H_ 1 + +#include +#include + +namespace facebook { 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 shitty 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. + * + * @author Mark Slee + */ +class TProtocolException : public facebook::thrift::TException { + public: + + /** + * Error codes for the various types of exceptions. + */ + enum TProtocolExceptionType { + UNKNOWN = 0, + INVALID_DATA = 1, + NEGATIVE_SIZE = 2, + SIZE_LIMIT = 3, + BAD_VERSION = 4, + NOT_IMPLEMENTED = 5, + }; + + TProtocolException() : + facebook::thrift::TException(), + type_(UNKNOWN) {} + + TProtocolException(TProtocolExceptionType type) : + facebook::thrift::TException(), + type_(type) {} + + TProtocolException(const std::string& message) : + facebook::thrift::TException(message), + type_(UNKNOWN) {} + + TProtocolException(TProtocolExceptionType type, const std::string& message) : + facebook::thrift::TException(message), + type_(type) {} + + virtual ~TProtocolException() throw() {} + + /** + * Returns an error code that provides information about the type of error + * that has occurred. + * + * @return Error code + */ + TProtocolExceptionType getType() { + return type_; + } + + virtual const char* what() const throw() { + if (message_.empty()) { + switch (type_) { + case UNKNOWN : return "TProtocolException: Unknown protocol exception"; + case INVALID_DATA : return "TProtocolException: Invalid data"; + case NEGATIVE_SIZE : return "TProtocolException: Negative size"; + case SIZE_LIMIT : return "TProtocolException: Exceeded size limit"; + case BAD_VERSION : return "TProtocolException: Invalid version"; + case NOT_IMPLEMENTED : return "TProtocolException: Not implemented"; + default : return "TProtocolException: (Invalid exception type)"; + } + } else { + return message_.c_str(); + } + } + + protected: + /** + * Error code + */ + TProtocolExceptionType type_; + +}; + +}}} // facebook::thrift::protocol + +#endif // #ifndef _THRIFT_PROTOCOL_TPROTOCOLEXCEPTION_H_ +// Copyright (c) 2006- Facebook +// Distributed under the Thrift Software License +// +// See accompanying file LICENSE or visit the Thrift site at: +// http://developers.facebook.com/thrift/ + +#ifndef _THRIFT_PROTOCOL_TPROTOCOLEXCEPTION_H_ +#define _THRIFT_PROTOCOL_TPROTOCOLEXCEPTION_H_ 1 + +#include +#include + +namespace facebook { 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 shitty 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. + * + * @author Mark Slee + */ +class TProtocolException : public facebook::thrift::TException { + public: + + /** + * Error codes for the various types of exceptions. + */ + enum TProtocolExceptionType { + UNKNOWN = 0, + INVALID_DATA = 1, + NEGATIVE_SIZE = 2, + SIZE_LIMIT = 3, + BAD_VERSION = 4, + NOT_IMPLEMENTED = 5, + }; + + TProtocolException() : + facebook::thrift::TException(), + type_(UNKNOWN) {} + + TProtocolException(TProtocolExceptionType type) : + facebook::thrift::TException(), + type_(type) {} + + TProtocolException(const std::string& message) : + facebook::thrift::TException(message), + type_(UNKNOWN) {} + + TProtocolException(TProtocolExceptionType type, const std::string& message) : + facebook::thrift::TException(message), + type_(type) {} + + virtual ~TProtocolException() throw() {} + + /** + * Returns an error code that provides information about the type of error + * that has occurred. + * + * @return Error code + */ + TProtocolExceptionType getType() { + return type_; + } + + virtual const char* what() const throw() { + if (message_.empty()) { + switch (type_) { + case UNKNOWN : return "TProtocolException: Unknown protocol exception"; + case INVALID_DATA : return "TProtocolException: Invalid data"; + case NEGATIVE_SIZE : return "TProtocolException: Negative size"; + case SIZE_LIMIT : return "TProtocolException: Exceeded size limit"; + case BAD_VERSION : return "TProtocolException: Invalid version"; + case NOT_IMPLEMENTED : return "TProtocolException: Not implemented"; + default : return "TProtocolException: (Invalid exception type)"; + } + } else { + return message_.c_str(); + } + } + + protected: + /** + * Error code + */ + TProtocolExceptionType type_; + +}; + +}}} // facebook::thrift::protocol + +#endif // #ifndef _THRIFT_PROTOCOL_TPROTOCOLEXCEPTION_H_ Index: service/include/thrift/protocol/TProtocol.h =================================================================== --- service/include/thrift/protocol/TProtocol.h (revision 0) +++ service/include/thrift/protocol/TProtocol.h (revision 0) @@ -0,0 +1,706 @@ +// Copyright (c) 2006- Facebook +// Distributed under the Thrift Software License +// +// See accompanying file LICENSE or visit the Thrift site at: +// http://developers.facebook.com/thrift/ + +#ifndef _THRIFT_PROTOCOL_TPROTOCOL_H_ +#define _THRIFT_PROTOCOL_TPROTOCOL_H_ 1 + +#include +#include + +#include + +#include +#include +#include +#include + +namespace facebook { namespace thrift { namespace protocol { + +using facebook::thrift::transport::TTransport; + +#ifdef HAVE_ENDIAN_H +#include +#endif + +#ifndef __BYTE_ORDER +# if defined(BYTE_ORDER) && defined(LITTLE_ENDIAN) && defined(BIG_ENDIAN) +# define __BYTE_ORDER BYTE_ORDER +# define __LITTLE_ENDIAN LITTLE_ENDIAN +# define __BIG_ENDIAN BIG_ENDIAN +# else +# error "Cannot determine endianness" +# endif +#endif + +#if __BYTE_ORDER == __BIG_ENDIAN +# define ntohll(n) (n) +# define htonll(n) (n) +#elif __BYTE_ORDER == __LITTLE_ENDIAN +# if defined(__GNUC__) && defined(__GLIBC__) +# include +# define ntohll(n) bswap_64(n) +# define htonll(n) bswap_64(n) +# else /* GNUC & GLIBC */ +# define ntohll(n) ( (((unsigned long long)ntohl(n)) << 32) + ntohl(n >> 32) ) +# define htonll(n) ( (((unsigned long long)htonl(n)) << 32) + htonl(n >> 32) ) +# endif /* GNUC & GLIBC */ +#else /* __BYTE_ORDER */ +# error "Can't define htonll or ntohll!" +#endif + +/** + * 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 +}; + +/** + * 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). + * + * @author Mark Slee + */ +class TProtocol { + public: + virtual ~TProtocol() {} + + /** + * Writing functions. + */ + + virtual uint32_t writeMessageBegin(const std::string& name, + const TMessageType messageType, + const int32_t seqid) = 0; + + virtual uint32_t writeMessageEnd() = 0; + + + virtual uint32_t writeStructBegin(const std::string& name) = 0; + + virtual uint32_t writeStructEnd() = 0; + + virtual uint32_t writeFieldBegin(const std::string& name, + const TType fieldType, + const int16_t fieldId) = 0; + + virtual uint32_t writeFieldEnd() = 0; + + virtual uint32_t writeFieldStop() = 0; + + virtual uint32_t writeMapBegin(const TType keyType, + const TType valType, + const uint32_t size) = 0; + + virtual uint32_t writeMapEnd() = 0; + + virtual uint32_t writeListBegin(const TType elemType, + const uint32_t size) = 0; + + virtual uint32_t writeListEnd() = 0; + + virtual uint32_t writeSetBegin(const TType elemType, + const uint32_t size) = 0; + + virtual uint32_t writeSetEnd() = 0; + + virtual uint32_t writeBool(const bool value) = 0; + + virtual uint32_t writeByte(const int8_t byte) = 0; + + virtual uint32_t writeI16(const int16_t i16) = 0; + + virtual uint32_t writeI32(const int32_t i32) = 0; + + virtual uint32_t writeI64(const int64_t i64) = 0; + + virtual uint32_t writeDouble(const double dub) = 0; + + virtual uint32_t writeString(const std::string& str) = 0; + + /** + * Reading functions + */ + + virtual uint32_t readMessageBegin(std::string& name, + TMessageType& messageType, + int32_t& seqid) = 0; + + virtual uint32_t readMessageEnd() = 0; + + virtual uint32_t readStructBegin(std::string& name) = 0; + + virtual uint32_t readStructEnd() = 0; + + virtual uint32_t readFieldBegin(std::string& name, + TType& fieldType, + int16_t& fieldId) = 0; + + virtual uint32_t readFieldEnd() = 0; + + virtual uint32_t readMapBegin(TType& keyType, + TType& valType, + uint32_t& size) = 0; + + virtual uint32_t readMapEnd() = 0; + + virtual uint32_t readListBegin(TType& elemType, + uint32_t& size) = 0; + + virtual uint32_t readListEnd() = 0; + + virtual uint32_t readSetBegin(TType& elemType, + uint32_t& size) = 0; + + virtual uint32_t readSetEnd() = 0; + + virtual uint32_t readBool(bool& value) = 0; + + virtual uint32_t readByte(int8_t& byte) = 0; + + virtual uint32_t readI16(int16_t& i16) = 0; + + virtual uint32_t readI32(int32_t& i32) = 0; + + virtual uint32_t readI64(int64_t& i64) = 0; + + virtual uint32_t readDouble(double& dub) = 0; + + virtual uint32_t readString(std::string& str) = 0; + + /** + * Method to arbitrarily skip over data. + */ + uint32_t skip(TType type) { + switch (type) { + case T_BOOL: + { + bool boolv; + return readBool(boolv); + } + case T_BYTE: + { + int8_t bytev; + return readByte(bytev); + } + case T_I16: + { + int16_t i16; + return readI16(i16); + } + case T_I32: + { + int32_t i32; + return readI32(i32); + } + case T_I64: + { + int64_t i64; + return readI64(i64); + } + case T_DOUBLE: + { + double dub; + return readDouble(dub); + } + case T_STRING: + { + std::string str; + return readString(str); + } + case T_STRUCT: + { + uint32_t result = 0; + std::string name; + int16_t fid; + TType ftype; + result += readStructBegin(name); + while (true) { + result += readFieldBegin(name, ftype, fid); + if (ftype == T_STOP) { + break; + } + result += skip(ftype); + result += readFieldEnd(); + } + result += readStructEnd(); + return result; + } + case T_MAP: + { + uint32_t result = 0; + TType keyType; + TType valType; + uint32_t i, size; + result += readMapBegin(keyType, valType, size); + for (i = 0; i < size; i++) { + result += skip(keyType); + result += skip(valType); + } + result += readMapEnd(); + return result; + } + case T_SET: + { + uint32_t result = 0; + TType elemType; + uint32_t i, size; + result += readSetBegin(elemType, size); + for (i = 0; i < size; i++) { + result += skip(elemType); + } + result += readSetEnd(); + return result; + } + case T_LIST: + { + uint32_t result = 0; + TType elemType; + uint32_t i, size; + result += readListBegin(elemType, size); + for (i = 0; i < size; i++) { + result += skip(elemType); + } + result += readListEnd(); + return result; + } + default: + return 0; + } + } + + inline boost::shared_ptr getTransport() { + return ptrans_; + } + + // TODO: remove these two calls, they are for backwards + // compatibility + inline boost::shared_ptr getInputTransport() { + return ptrans_; + } + inline boost::shared_ptr getOutputTransport() { + return ptrans_; + } + + protected: + TProtocol(boost::shared_ptr ptrans): + ptrans_(ptrans) { + trans_ = ptrans.get(); + } + + boost::shared_ptr ptrans_; + TTransport* trans_; + + private: + TProtocol() {} +}; + +/** + * Constructs input and output protocol objects given transports. + */ +class TProtocolFactory { + public: + TProtocolFactory() {} + + virtual ~TProtocolFactory() {} + + virtual boost::shared_ptr getProtocol(boost::shared_ptr trans) = 0; +}; + +}}} // facebook::thrift::protocol + +#endif // #define _THRIFT_PROTOCOL_TPROTOCOL_H_ 1 +// Copyright (c) 2006- Facebook +// Distributed under the Thrift Software License +// +// See accompanying file LICENSE or visit the Thrift site at: +// http://developers.facebook.com/thrift/ + +#ifndef _THRIFT_PROTOCOL_TPROTOCOL_H_ +#define _THRIFT_PROTOCOL_TPROTOCOL_H_ 1 + +#include +#include + +#include + +#include +#include +#include +#include + +namespace facebook { namespace thrift { namespace protocol { + +using facebook::thrift::transport::TTransport; + +#ifdef HAVE_ENDIAN_H +#include +#endif + +#ifndef __BYTE_ORDER +# if defined(BYTE_ORDER) && defined(LITTLE_ENDIAN) && defined(BIG_ENDIAN) +# define __BYTE_ORDER BYTE_ORDER +# define __LITTLE_ENDIAN LITTLE_ENDIAN +# define __BIG_ENDIAN BIG_ENDIAN +# else +# error "Cannot determine endianness" +# endif +#endif + +#if __BYTE_ORDER == __BIG_ENDIAN +# define ntohll(n) (n) +# define htonll(n) (n) +#elif __BYTE_ORDER == __LITTLE_ENDIAN +# if defined(__GNUC__) && defined(__GLIBC__) +# include +# define ntohll(n) bswap_64(n) +# define htonll(n) bswap_64(n) +# else /* GNUC & GLIBC */ +# define ntohll(n) ( (((unsigned long long)ntohl(n)) << 32) + ntohl(n >> 32) ) +# define htonll(n) ( (((unsigned long long)htonl(n)) << 32) + htonl(n >> 32) ) +# endif /* GNUC & GLIBC */ +#else /* __BYTE_ORDER */ +# error "Can't define htonll or ntohll!" +#endif + +/** + * 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 +}; + +/** + * 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). + * + * @author Mark Slee + */ +class TProtocol { + public: + virtual ~TProtocol() {} + + /** + * Writing functions. + */ + + virtual uint32_t writeMessageBegin(const std::string& name, + const TMessageType messageType, + const int32_t seqid) = 0; + + virtual uint32_t writeMessageEnd() = 0; + + + virtual uint32_t writeStructBegin(const std::string& name) = 0; + + virtual uint32_t writeStructEnd() = 0; + + virtual uint32_t writeFieldBegin(const std::string& name, + const TType fieldType, + const int16_t fieldId) = 0; + + virtual uint32_t writeFieldEnd() = 0; + + virtual uint32_t writeFieldStop() = 0; + + virtual uint32_t writeMapBegin(const TType keyType, + const TType valType, + const uint32_t size) = 0; + + virtual uint32_t writeMapEnd() = 0; + + virtual uint32_t writeListBegin(const TType elemType, + const uint32_t size) = 0; + + virtual uint32_t writeListEnd() = 0; + + virtual uint32_t writeSetBegin(const TType elemType, + const uint32_t size) = 0; + + virtual uint32_t writeSetEnd() = 0; + + virtual uint32_t writeBool(const bool value) = 0; + + virtual uint32_t writeByte(const int8_t byte) = 0; + + virtual uint32_t writeI16(const int16_t i16) = 0; + + virtual uint32_t writeI32(const int32_t i32) = 0; + + virtual uint32_t writeI64(const int64_t i64) = 0; + + virtual uint32_t writeDouble(const double dub) = 0; + + virtual uint32_t writeString(const std::string& str) = 0; + + /** + * Reading functions + */ + + virtual uint32_t readMessageBegin(std::string& name, + TMessageType& messageType, + int32_t& seqid) = 0; + + virtual uint32_t readMessageEnd() = 0; + + virtual uint32_t readStructBegin(std::string& name) = 0; + + virtual uint32_t readStructEnd() = 0; + + virtual uint32_t readFieldBegin(std::string& name, + TType& fieldType, + int16_t& fieldId) = 0; + + virtual uint32_t readFieldEnd() = 0; + + virtual uint32_t readMapBegin(TType& keyType, + TType& valType, + uint32_t& size) = 0; + + virtual uint32_t readMapEnd() = 0; + + virtual uint32_t readListBegin(TType& elemType, + uint32_t& size) = 0; + + virtual uint32_t readListEnd() = 0; + + virtual uint32_t readSetBegin(TType& elemType, + uint32_t& size) = 0; + + virtual uint32_t readSetEnd() = 0; + + virtual uint32_t readBool(bool& value) = 0; + + virtual uint32_t readByte(int8_t& byte) = 0; + + virtual uint32_t readI16(int16_t& i16) = 0; + + virtual uint32_t readI32(int32_t& i32) = 0; + + virtual uint32_t readI64(int64_t& i64) = 0; + + virtual uint32_t readDouble(double& dub) = 0; + + virtual uint32_t readString(std::string& str) = 0; + + /** + * Method to arbitrarily skip over data. + */ + uint32_t skip(TType type) { + switch (type) { + case T_BOOL: + { + bool boolv; + return readBool(boolv); + } + case T_BYTE: + { + int8_t bytev; + return readByte(bytev); + } + case T_I16: + { + int16_t i16; + return readI16(i16); + } + case T_I32: + { + int32_t i32; + return readI32(i32); + } + case T_I64: + { + int64_t i64; + return readI64(i64); + } + case T_DOUBLE: + { + double dub; + return readDouble(dub); + } + case T_STRING: + { + std::string str; + return readString(str); + } + case T_STRUCT: + { + uint32_t result = 0; + std::string name; + int16_t fid; + TType ftype; + result += readStructBegin(name); + while (true) { + result += readFieldBegin(name, ftype, fid); + if (ftype == T_STOP) { + break; + } + result += skip(ftype); + result += readFieldEnd(); + } + result += readStructEnd(); + return result; + } + case T_MAP: + { + uint32_t result = 0; + TType keyType; + TType valType; + uint32_t i, size; + result += readMapBegin(keyType, valType, size); + for (i = 0; i < size; i++) { + result += skip(keyType); + result += skip(valType); + } + result += readMapEnd(); + return result; + } + case T_SET: + { + uint32_t result = 0; + TType elemType; + uint32_t i, size; + result += readSetBegin(elemType, size); + for (i = 0; i < size; i++) { + result += skip(elemType); + } + result += readSetEnd(); + return result; + } + case T_LIST: + { + uint32_t result = 0; + TType elemType; + uint32_t i, size; + result += readListBegin(elemType, size); + for (i = 0; i < size; i++) { + result += skip(elemType); + } + result += readListEnd(); + return result; + } + default: + return 0; + } + } + + inline boost::shared_ptr getTransport() { + return ptrans_; + } + + // TODO: remove these two calls, they are for backwards + // compatibility + inline boost::shared_ptr getInputTransport() { + return ptrans_; + } + inline boost::shared_ptr getOutputTransport() { + return ptrans_; + } + + protected: + TProtocol(boost::shared_ptr ptrans): + ptrans_(ptrans) { + trans_ = ptrans.get(); + } + + boost::shared_ptr ptrans_; + TTransport* trans_; + + private: + TProtocol() {} +}; + +/** + * Constructs input and output protocol objects given transports. + */ +class TProtocolFactory { + public: + TProtocolFactory() {} + + virtual ~TProtocolFactory() {} + + virtual boost::shared_ptr getProtocol(boost::shared_ptr trans) = 0; +}; + +}}} // facebook::thrift::protocol + +#endif // #define _THRIFT_PROTOCOL_TPROTOCOL_H_ 1 Index: service/include/thrift/protocol/TOneWayProtocol.h =================================================================== --- service/include/thrift/protocol/TOneWayProtocol.h (revision 0) +++ service/include/thrift/protocol/TOneWayProtocol.h (revision 0) @@ -0,0 +1,294 @@ +// Copyright (c) 2006- Facebook +// Distributed under the Thrift Software License +// +// See accompanying file LICENSE or visit the Thrift site at: +// http://developers.facebook.com/thrift/ + +#ifndef _THRIFT_PROTOCOL_TONEWAYPROTOCOL_H_ +#define _THRIFT_PROTOCOL_TONEWAYPROTOCOL_H_ 1 + +#include "TProtocol.h" + +namespace facebook { namespace thrift { namespace protocol { + +/** + * Abstract class for implementing a protocol that can only be written, + * not read. + * + * @author David Reiss + */ +class TWriteOnlyProtocol : public TProtocol { + public: + /** + * @param subclass_name The name of the concrete subclass. + */ + TWriteOnlyProtocol(boost::shared_ptr trans, + const std::string& subclass_name) + : TProtocol(trans) + , subclass_(subclass_name) + {} + + // All writing functions remain abstract. + + /** + * Reading functions all throw an exception. + */ + + uint32_t readMessageBegin(std::string& name, + TMessageType& messageType, + int32_t& seqid) { + throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, + subclass_ + " does not support reading (yet)."); + } + + uint32_t readMessageEnd() { + throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, + subclass_ + " does not support reading (yet)."); + } + + uint32_t readStructBegin(std::string& name) { + throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, + subclass_ + " does not support reading (yet)."); + } + + uint32_t readStructEnd() { + throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, + subclass_ + " does not support reading (yet)."); + } + + uint32_t readFieldBegin(std::string& name, + TType& fieldType, + int16_t& fieldId) { + throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, + subclass_ + " does not support reading (yet)."); + } + + uint32_t readFieldEnd() { + throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, + subclass_ + " does not support reading (yet)."); + } + + uint32_t readMapBegin(TType& keyType, + TType& valType, + uint32_t& size) { + throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, + subclass_ + " does not support reading (yet)."); + } + + uint32_t readMapEnd() { + throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, + subclass_ + " does not support reading (yet)."); + } + + uint32_t readListBegin(TType& elemType, + uint32_t& size) { + throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, + subclass_ + " does not support reading (yet)."); + } + + uint32_t readListEnd() { + throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, + subclass_ + " does not support reading (yet)."); + } + + uint32_t readSetBegin(TType& elemType, + uint32_t& size) { + throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, + subclass_ + " does not support reading (yet)."); + } + + uint32_t readSetEnd() { + throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, + subclass_ + " does not support reading (yet)."); + } + + uint32_t readBool(bool& value) { + throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, + subclass_ + " does not support reading (yet)."); + } + + uint32_t readByte(int8_t& byte) { + throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, + subclass_ + " does not support reading (yet)."); + } + + uint32_t readI16(int16_t& i16) { + throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, + subclass_ + " does not support reading (yet)."); + } + + uint32_t readI32(int32_t& i32) { + throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, + subclass_ + " does not support reading (yet)."); + } + + uint32_t readI64(int64_t& i64) { + throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, + subclass_ + " does not support reading (yet)."); + } + + uint32_t readDouble(double& dub) { + throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, + subclass_ + " does not support reading (yet)."); + } + + uint32_t readString(std::string& str) { + throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, + subclass_ + " does not support reading (yet)."); + } + + + private: + std::string subclass_; +}; + +}}} // facebook::thrift::protocol + +#endif // #ifndef _THRIFT_PROTOCOL_TBINARYPROTOCOL_H_ +// Copyright (c) 2006- Facebook +// Distributed under the Thrift Software License +// +// See accompanying file LICENSE or visit the Thrift site at: +// http://developers.facebook.com/thrift/ + +#ifndef _THRIFT_PROTOCOL_TONEWAYPROTOCOL_H_ +#define _THRIFT_PROTOCOL_TONEWAYPROTOCOL_H_ 1 + +#include "TProtocol.h" + +namespace facebook { namespace thrift { namespace protocol { + +/** + * Abstract class for implementing a protocol that can only be written, + * not read. + * + * @author David Reiss + */ +class TWriteOnlyProtocol : public TProtocol { + public: + /** + * @param subclass_name The name of the concrete subclass. + */ + TWriteOnlyProtocol(boost::shared_ptr trans, + const std::string& subclass_name) + : TProtocol(trans) + , subclass_(subclass_name) + {} + + // All writing functions remain abstract. + + /** + * Reading functions all throw an exception. + */ + + uint32_t readMessageBegin(std::string& name, + TMessageType& messageType, + int32_t& seqid) { + throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, + subclass_ + " does not support reading (yet)."); + } + + uint32_t readMessageEnd() { + throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, + subclass_ + " does not support reading (yet)."); + } + + uint32_t readStructBegin(std::string& name) { + throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, + subclass_ + " does not support reading (yet)."); + } + + uint32_t readStructEnd() { + throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, + subclass_ + " does not support reading (yet)."); + } + + uint32_t readFieldBegin(std::string& name, + TType& fieldType, + int16_t& fieldId) { + throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, + subclass_ + " does not support reading (yet)."); + } + + uint32_t readFieldEnd() { + throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, + subclass_ + " does not support reading (yet)."); + } + + uint32_t readMapBegin(TType& keyType, + TType& valType, + uint32_t& size) { + throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, + subclass_ + " does not support reading (yet)."); + } + + uint32_t readMapEnd() { + throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, + subclass_ + " does not support reading (yet)."); + } + + uint32_t readListBegin(TType& elemType, + uint32_t& size) { + throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, + subclass_ + " does not support reading (yet)."); + } + + uint32_t readListEnd() { + throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, + subclass_ + " does not support reading (yet)."); + } + + uint32_t readSetBegin(TType& elemType, + uint32_t& size) { + throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, + subclass_ + " does not support reading (yet)."); + } + + uint32_t readSetEnd() { + throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, + subclass_ + " does not support reading (yet)."); + } + + uint32_t readBool(bool& value) { + throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, + subclass_ + " does not support reading (yet)."); + } + + uint32_t readByte(int8_t& byte) { + throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, + subclass_ + " does not support reading (yet)."); + } + + uint32_t readI16(int16_t& i16) { + throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, + subclass_ + " does not support reading (yet)."); + } + + uint32_t readI32(int32_t& i32) { + throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, + subclass_ + " does not support reading (yet)."); + } + + uint32_t readI64(int64_t& i64) { + throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, + subclass_ + " does not support reading (yet)."); + } + + uint32_t readDouble(double& dub) { + throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, + subclass_ + " does not support reading (yet)."); + } + + uint32_t readString(std::string& str) { + throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, + subclass_ + " does not support reading (yet)."); + } + + + private: + std::string subclass_; +}; + +}}} // facebook::thrift::protocol + +#endif // #ifndef _THRIFT_PROTOCOL_TBINARYPROTOCOL_H_ Index: service/include/thrift/server/TServer.h =================================================================== --- service/include/thrift/server/TServer.h (revision 0) +++ service/include/thrift/server/TServer.h (revision 0) @@ -0,0 +1,386 @@ +// Copyright (c) 2006- Facebook +// Distributed under the Thrift Software License +// +// See accompanying file LICENSE or visit the Thrift site at: +// http://developers.facebook.com/thrift/ + +#ifndef _THRIFT_SERVER_TSERVER_H_ +#define _THRIFT_SERVER_TSERVER_H_ 1 + +#include +#include +#include +#include + +#include + +namespace facebook { namespace thrift { namespace server { + +using facebook::thrift::TProcessor; +using facebook::thrift::protocol::TBinaryProtocolFactory; +using facebook::thrift::protocol::TProtocol; +using facebook::thrift::protocol::TProtocolFactory; +using facebook::thrift::transport::TServerTransport; +using facebook::thrift::transport::TTransport; +using facebook::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 clientBegin(boost::shared_ptr input, + boost::shared_ptr output) {} + + /** + * Called when a client has finished making requests. + */ + virtual void clientEnd(boost::shared_ptr input, + boost::shared_ptr output) {} + + protected: + + /** + * Prevent direct instantiation. + */ + TServerEventHandler() {} + +}; + +/** + * Thrift server. + * + * @author Mark Slee + */ +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 getProcessor() { + return processor_; + } + + boost::shared_ptr getServerTransport() { + return serverTransport_; + } + + boost::shared_ptr getInputTransportFactory() { + return inputTransportFactory_; + } + + boost::shared_ptr getOutputTransportFactory() { + return outputTransportFactory_; + } + + boost::shared_ptr getInputProtocolFactory() { + return inputProtocolFactory_; + } + + boost::shared_ptr getOutputProtocolFactory() { + return outputProtocolFactory_; + } + + boost::shared_ptr getEventHandler() { + return eventHandler_; + } + +protected: + TServer(boost::shared_ptr processor): + processor_(processor) { + setInputTransportFactory(boost::shared_ptr(new TTransportFactory())); + setOutputTransportFactory(boost::shared_ptr(new TTransportFactory())); + setInputProtocolFactory(boost::shared_ptr(new TBinaryProtocolFactory())); + setOutputProtocolFactory(boost::shared_ptr(new TBinaryProtocolFactory())); + } + + TServer(boost::shared_ptr processor, + boost::shared_ptr serverTransport): + processor_(processor), + serverTransport_(serverTransport) { + setInputTransportFactory(boost::shared_ptr(new TTransportFactory())); + setOutputTransportFactory(boost::shared_ptr(new TTransportFactory())); + setInputProtocolFactory(boost::shared_ptr(new TBinaryProtocolFactory())); + setOutputProtocolFactory(boost::shared_ptr(new TBinaryProtocolFactory())); + } + + TServer(boost::shared_ptr processor, + boost::shared_ptr serverTransport, + boost::shared_ptr transportFactory, + boost::shared_ptr protocolFactory): + processor_(processor), + serverTransport_(serverTransport), + inputTransportFactory_(transportFactory), + outputTransportFactory_(transportFactory), + inputProtocolFactory_(protocolFactory), + outputProtocolFactory_(protocolFactory) {} + + TServer(boost::shared_ptr processor, + boost::shared_ptr serverTransport, + boost::shared_ptr inputTransportFactory, + boost::shared_ptr outputTransportFactory, + boost::shared_ptr inputProtocolFactory, + boost::shared_ptr outputProtocolFactory): + processor_(processor), + serverTransport_(serverTransport), + inputTransportFactory_(inputTransportFactory), + outputTransportFactory_(outputTransportFactory), + inputProtocolFactory_(inputProtocolFactory), + outputProtocolFactory_(outputProtocolFactory) {} + + + // Class variables + boost::shared_ptr processor_; + boost::shared_ptr serverTransport_; + + boost::shared_ptr inputTransportFactory_; + boost::shared_ptr outputTransportFactory_; + + boost::shared_ptr inputProtocolFactory_; + boost::shared_ptr outputProtocolFactory_; + + boost::shared_ptr eventHandler_; + +public: + void setInputTransportFactory(boost::shared_ptr inputTransportFactory) { + inputTransportFactory_ = inputTransportFactory; + } + + void setOutputTransportFactory(boost::shared_ptr outputTransportFactory) { + outputTransportFactory_ = outputTransportFactory; + } + + void setInputProtocolFactory(boost::shared_ptr inputProtocolFactory) { + inputProtocolFactory_ = inputProtocolFactory; + } + + void setOutputProtocolFactory(boost::shared_ptr outputProtocolFactory) { + outputProtocolFactory_ = outputProtocolFactory; + } + + void setServerEventHandler(boost::shared_ptr eventHandler) { + eventHandler_ = eventHandler; + } + +}; + +}}} // facebook::thrift::server + +#endif // #ifndef _THRIFT_SERVER_TSERVER_H_ +// Copyright (c) 2006- Facebook +// Distributed under the Thrift Software License +// +// See accompanying file LICENSE or visit the Thrift site at: +// http://developers.facebook.com/thrift/ + +#ifndef _THRIFT_SERVER_TSERVER_H_ +#define _THRIFT_SERVER_TSERVER_H_ 1 + +#include +#include +#include +#include + +#include + +namespace facebook { namespace thrift { namespace server { + +using facebook::thrift::TProcessor; +using facebook::thrift::protocol::TBinaryProtocolFactory; +using facebook::thrift::protocol::TProtocol; +using facebook::thrift::protocol::TProtocolFactory; +using facebook::thrift::transport::TServerTransport; +using facebook::thrift::transport::TTransport; +using facebook::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 clientBegin(boost::shared_ptr input, + boost::shared_ptr output) {} + + /** + * Called when a client has finished making requests. + */ + virtual void clientEnd(boost::shared_ptr input, + boost::shared_ptr output) {} + + protected: + + /** + * Prevent direct instantiation. + */ + TServerEventHandler() {} + +}; + +/** + * Thrift server. + * + * @author Mark Slee + */ +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 getProcessor() { + return processor_; + } + + boost::shared_ptr getServerTransport() { + return serverTransport_; + } + + boost::shared_ptr getInputTransportFactory() { + return inputTransportFactory_; + } + + boost::shared_ptr getOutputTransportFactory() { + return outputTransportFactory_; + } + + boost::shared_ptr getInputProtocolFactory() { + return inputProtocolFactory_; + } + + boost::shared_ptr getOutputProtocolFactory() { + return outputProtocolFactory_; + } + + boost::shared_ptr getEventHandler() { + return eventHandler_; + } + +protected: + TServer(boost::shared_ptr processor): + processor_(processor) { + setInputTransportFactory(boost::shared_ptr(new TTransportFactory())); + setOutputTransportFactory(boost::shared_ptr(new TTransportFactory())); + setInputProtocolFactory(boost::shared_ptr(new TBinaryProtocolFactory())); + setOutputProtocolFactory(boost::shared_ptr(new TBinaryProtocolFactory())); + } + + TServer(boost::shared_ptr processor, + boost::shared_ptr serverTransport): + processor_(processor), + serverTransport_(serverTransport) { + setInputTransportFactory(boost::shared_ptr(new TTransportFactory())); + setOutputTransportFactory(boost::shared_ptr(new TTransportFactory())); + setInputProtocolFactory(boost::shared_ptr(new TBinaryProtocolFactory())); + setOutputProtocolFactory(boost::shared_ptr(new TBinaryProtocolFactory())); + } + + TServer(boost::shared_ptr processor, + boost::shared_ptr serverTransport, + boost::shared_ptr transportFactory, + boost::shared_ptr protocolFactory): + processor_(processor), + serverTransport_(serverTransport), + inputTransportFactory_(transportFactory), + outputTransportFactory_(transportFactory), + inputProtocolFactory_(protocolFactory), + outputProtocolFactory_(protocolFactory) {} + + TServer(boost::shared_ptr processor, + boost::shared_ptr serverTransport, + boost::shared_ptr inputTransportFactory, + boost::shared_ptr outputTransportFactory, + boost::shared_ptr inputProtocolFactory, + boost::shared_ptr outputProtocolFactory): + processor_(processor), + serverTransport_(serverTransport), + inputTransportFactory_(inputTransportFactory), + outputTransportFactory_(outputTransportFactory), + inputProtocolFactory_(inputProtocolFactory), + outputProtocolFactory_(outputProtocolFactory) {} + + + // Class variables + boost::shared_ptr processor_; + boost::shared_ptr serverTransport_; + + boost::shared_ptr inputTransportFactory_; + boost::shared_ptr outputTransportFactory_; + + boost::shared_ptr inputProtocolFactory_; + boost::shared_ptr outputProtocolFactory_; + + boost::shared_ptr eventHandler_; + +public: + void setInputTransportFactory(boost::shared_ptr inputTransportFactory) { + inputTransportFactory_ = inputTransportFactory; + } + + void setOutputTransportFactory(boost::shared_ptr outputTransportFactory) { + outputTransportFactory_ = outputTransportFactory; + } + + void setInputProtocolFactory(boost::shared_ptr inputProtocolFactory) { + inputProtocolFactory_ = inputProtocolFactory; + } + + void setOutputProtocolFactory(boost::shared_ptr outputProtocolFactory) { + outputProtocolFactory_ = outputProtocolFactory; + } + + void setServerEventHandler(boost::shared_ptr eventHandler) { + eventHandler_ = eventHandler; + } + +}; + +}}} // facebook::thrift::server + +#endif // #ifndef _THRIFT_SERVER_TSERVER_H_ Index: service/include/thrift/server/TThreadedServer.h =================================================================== --- service/include/thrift/server/TThreadedServer.h (revision 0) +++ service/include/thrift/server/TThreadedServer.h (revision 0) @@ -0,0 +1,110 @@ +// Copyright (c) 2006- Facebook +// Distributed under the Thrift Software License +// +// See accompanying file LICENSE or visit the Thrift site at: +// http://developers.facebook.com/thrift/ + +#ifndef _THRIFT_SERVER_TTHREADEDSERVER_H_ +#define _THRIFT_SERVER_TTHREADEDSERVER_H_ 1 + +#include +#include +#include +#include + +#include + +namespace facebook { namespace thrift { namespace server { + +using facebook::thrift::TProcessor; +using facebook::thrift::transport::TServerTransport; +using facebook::thrift::transport::TTransportFactory; +using facebook::thrift::concurrency::Monitor; +using facebook::thrift::concurrency::ThreadFactory; + +class TThreadedServer : public TServer { + + public: + class Task; + + TThreadedServer(boost::shared_ptr processor, + boost::shared_ptr serverTransport, + boost::shared_ptr transportFactory, + boost::shared_ptr protocolFactory); + + virtual ~TThreadedServer(); + + virtual void serve(); + + void stop() { + stop_ = true; + serverTransport_->interrupt(); + } + + protected: + boost::shared_ptr threadFactory_; + volatile bool stop_; + + Monitor tasksMonitor_; + std::set tasks_; + +}; + +}}} // facebook::thrift::server + +#endif // #ifndef _THRIFT_SERVER_TTHREADEDSERVER_H_ +// Copyright (c) 2006- Facebook +// Distributed under the Thrift Software License +// +// See accompanying file LICENSE or visit the Thrift site at: +// http://developers.facebook.com/thrift/ + +#ifndef _THRIFT_SERVER_TTHREADEDSERVER_H_ +#define _THRIFT_SERVER_TTHREADEDSERVER_H_ 1 + +#include +#include +#include +#include + +#include + +namespace facebook { namespace thrift { namespace server { + +using facebook::thrift::TProcessor; +using facebook::thrift::transport::TServerTransport; +using facebook::thrift::transport::TTransportFactory; +using facebook::thrift::concurrency::Monitor; +using facebook::thrift::concurrency::ThreadFactory; + +class TThreadedServer : public TServer { + + public: + class Task; + + TThreadedServer(boost::shared_ptr processor, + boost::shared_ptr serverTransport, + boost::shared_ptr transportFactory, + boost::shared_ptr protocolFactory); + + virtual ~TThreadedServer(); + + virtual void serve(); + + void stop() { + stop_ = true; + serverTransport_->interrupt(); + } + + protected: + boost::shared_ptr threadFactory_; + volatile bool stop_; + + Monitor tasksMonitor_; + std::set tasks_; + +}; + +}}} // facebook::thrift::server + +#endif // #ifndef _THRIFT_SERVER_TTHREADEDSERVER_H_ Index: service/include/thrift/server/TThreadPoolServer.h =================================================================== --- service/include/thrift/server/TThreadPoolServer.h (revision 0) +++ service/include/thrift/server/TThreadPoolServer.h (revision 0) @@ -0,0 +1,132 @@ +// Copyright (c) 2006- Facebook +// Distributed under the Thrift Software License +// +// See accompanying file LICENSE or visit the Thrift site at: +// http://developers.facebook.com/thrift/ + +#ifndef _THRIFT_SERVER_TTHREADPOOLSERVER_H_ +#define _THRIFT_SERVER_TTHREADPOOLSERVER_H_ 1 + +#include +#include +#include + +#include + +namespace facebook { namespace thrift { namespace server { + +using facebook::thrift::concurrency::ThreadManager; +using facebook::thrift::protocol::TProtocolFactory; +using facebook::thrift::transport::TServerTransport; +using facebook::thrift::transport::TTransportFactory; + +class TThreadPoolServer : public TServer { + public: + class Task; + + TThreadPoolServer(boost::shared_ptr processor, + boost::shared_ptr serverTransport, + boost::shared_ptr transportFactory, + boost::shared_ptr protocolFactory, + boost::shared_ptr threadManager); + + TThreadPoolServer(boost::shared_ptr processor, + boost::shared_ptr serverTransport, + boost::shared_ptr inputTransportFactory, + boost::shared_ptr outputTransportFactory, + boost::shared_ptr inputProtocolFactory, + boost::shared_ptr outputProtocolFactory, + boost::shared_ptr threadManager); + + virtual ~TThreadPoolServer(); + + virtual void serve(); + + virtual int64_t getTimeout() const; + + virtual void setTimeout(int64_t value); + + virtual void stop() { + stop_ = true; + serverTransport_->interrupt(); + } + + protected: + + boost::shared_ptr threadManager_; + + volatile bool stop_; + + volatile int64_t timeout_; + +}; + +}}} // facebook::thrift::server + +#endif // #ifndef _THRIFT_SERVER_TTHREADPOOLSERVER_H_ +// Copyright (c) 2006- Facebook +// Distributed under the Thrift Software License +// +// See accompanying file LICENSE or visit the Thrift site at: +// http://developers.facebook.com/thrift/ + +#ifndef _THRIFT_SERVER_TTHREADPOOLSERVER_H_ +#define _THRIFT_SERVER_TTHREADPOOLSERVER_H_ 1 + +#include +#include +#include + +#include + +namespace facebook { namespace thrift { namespace server { + +using facebook::thrift::concurrency::ThreadManager; +using facebook::thrift::protocol::TProtocolFactory; +using facebook::thrift::transport::TServerTransport; +using facebook::thrift::transport::TTransportFactory; + +class TThreadPoolServer : public TServer { + public: + class Task; + + TThreadPoolServer(boost::shared_ptr processor, + boost::shared_ptr serverTransport, + boost::shared_ptr transportFactory, + boost::shared_ptr protocolFactory, + boost::shared_ptr threadManager); + + TThreadPoolServer(boost::shared_ptr processor, + boost::shared_ptr serverTransport, + boost::shared_ptr inputTransportFactory, + boost::shared_ptr outputTransportFactory, + boost::shared_ptr inputProtocolFactory, + boost::shared_ptr outputProtocolFactory, + boost::shared_ptr threadManager); + + virtual ~TThreadPoolServer(); + + virtual void serve(); + + virtual int64_t getTimeout() const; + + virtual void setTimeout(int64_t value); + + virtual void stop() { + stop_ = true; + serverTransport_->interrupt(); + } + + protected: + + boost::shared_ptr threadManager_; + + volatile bool stop_; + + volatile int64_t timeout_; + +}; + +}}} // facebook::thrift::server + +#endif // #ifndef _THRIFT_SERVER_TTHREADPOOLSERVER_H_ Index: service/include/thrift/server/TNonblockingServer.h =================================================================== --- service/include/thrift/server/TNonblockingServer.h (revision 0) +++ service/include/thrift/server/TNonblockingServer.h (revision 0) @@ -0,0 +1,662 @@ +// Copyright (c) 2006- Facebook +// Distributed under the Thrift Software License +// +// See accompanying file LICENSE or visit the Thrift site at: +// http://developers.facebook.com/thrift/ + +#ifndef _THRIFT_SERVER_TNONBLOCKINGSERVER_H_ +#define _THRIFT_SERVER_TNONBLOCKINGSERVER_H_ 1 + +#include +#include +#include +#include +#include +#include + +namespace facebook { namespace thrift { namespace server { + +using facebook::thrift::transport::TMemoryBuffer; +using facebook::thrift::protocol::TProtocol; +using facebook::thrift::concurrency::Runnable; +using facebook::thrift::concurrency::ThreadManager; + +// Forward declaration of class +class TConnection; + +/** + * This is a non-blocking server in C++ for high performance that operates a + * single IO thread. 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. + * + * @author Mark Slee + */ +class TNonblockingServer : public TServer { + private: + + // Listen backlog + static const int LISTEN_BACKLOG = 1024; + + // Server socket file descriptor + int serverSocket_; + + // Port server runs on + int port_; + + // Whether to frame responses + bool frameResponses_; + + // For processing via thread pool, may be NULL + boost::shared_ptr threadManager_; + + // Is thread pool processing? + bool threadPoolProcessing_; + + // The event base for libevent + event_base* eventBase_; + + // Event struct, for use with eventBase_ + struct event serverEvent_; + + /** + * 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 connectionStack_; + + void handleEvent(int fd, short which); + + public: + TNonblockingServer(boost::shared_ptr processor, + int port) : + TServer(processor), + serverSocket_(-1), + port_(port), + frameResponses_(true), + threadPoolProcessing_(false), + eventBase_(NULL) {} + + TNonblockingServer(boost::shared_ptr processor, + boost::shared_ptr protocolFactory, + int port, + boost::shared_ptr threadManager = boost::shared_ptr()) : + TServer(processor), + serverSocket_(-1), + port_(port), + frameResponses_(true), + threadManager_(threadManager), + eventBase_(NULL) { + setInputTransportFactory(boost::shared_ptr(new TTransportFactory())); + setOutputTransportFactory(boost::shared_ptr(new TTransportFactory())); + setInputProtocolFactory(protocolFactory); + setOutputProtocolFactory(protocolFactory); + setThreadManager(threadManager); + } + + TNonblockingServer(boost::shared_ptr processor, + boost::shared_ptr inputTransportFactory, + boost::shared_ptr outputTransportFactory, + boost::shared_ptr inputProtocolFactory, + boost::shared_ptr outputProtocolFactory, + int port, + boost::shared_ptr threadManager = boost::shared_ptr()) : + TServer(processor), + serverSocket_(0), + port_(port), + frameResponses_(true), + threadManager_(threadManager), + eventBase_(NULL) { + setInputTransportFactory(inputTransportFactory); + setOutputTransportFactory(outputTransportFactory); + setInputProtocolFactory(inputProtocolFactory); + setOutputProtocolFactory(outputProtocolFactory); + setThreadManager(threadManager); + } + + ~TNonblockingServer() {} + + void setThreadManager(boost::shared_ptr threadManager) { + threadManager_ = threadManager; + threadPoolProcessing_ = (threadManager != NULL); + } + + bool isThreadPoolProcessing() const { + return threadPoolProcessing_; + } + + void addTask(boost::shared_ptr task) { + threadManager_->add(task); + } + + void setFrameResponses(bool frameResponses) { + frameResponses_ = frameResponses; + } + + bool getFrameResponses() const { + return frameResponses_; + } + + event_base* getEventBase() const { + return eventBase_; + } + + TConnection* createConnection(int socket, short flags); + + void returnConnection(TConnection* connection); + + static void eventHandler(int fd, short which, void* v) { + ((TNonblockingServer*)v)->handleEvent(fd, which); + } + + void listenSocket(); + + void listenSocket(int fd); + + void registerEvents(event_base* base); + + void serve(); + +}; + +/** + * Two states for sockets, recv and send mode + */ +enum TSocketState { + SOCKET_RECV, + SOCKET_SEND +}; + +/** + * Four states for the nonblocking servr: + * 1) initialize + * 2) read 4 byte frame size + * 3) read frame of data + * 4) send back data (if any) + */ +enum TAppState { + APP_INIT, + APP_READ_FRAME_SIZE, + APP_READ_REQUEST, + APP_WAIT_TASK, + APP_SEND_FRAME_SIZE, + APP_SEND_RESULT +}; + +/** + * Represents a connection that is handled via libevent. This connection + * essentially encapsulates a socket that has some associated libevent state. + */ +class TConnection { + private: + + class Task; + + // Server handle + TNonblockingServer* server_; + + // Socket handle + int socket_; + + // Libevent object + struct event event_; + + // Libevent flags + short eventFlags_; + + // Socket mode + TSocketState socketState_; + + // Application state + TAppState appState_; + + // How much data needed to read + uint32_t readWant_; + + // Where in the read buffer are we + uint32_t readBufferPos_; + + // Read buffer + uint8_t* readBuffer_; + + // Read buffer size + uint32_t readBufferSize_; + + // Write buffer + uint8_t* writeBuffer_; + + // Write buffer size + uint32_t writeBufferSize_; + + // How far through writing are we? + uint32_t writeBufferPos_; + + // Frame size + int32_t frameSize_; + + // Task handle + int taskHandle_; + + // Task event + struct event taskEvent_; + + // Transport to read from + boost::shared_ptr inputTransport_; + + // Transport that processor writes to + boost::shared_ptr outputTransport_; + + // extra transport generated by transport factory (e.g. BufferedRouterTransport) + boost::shared_ptr factoryInputTransport_; + boost::shared_ptr factoryOutputTransport_; + + // Protocol decoder + boost::shared_ptr inputProtocol_; + + // Protocol encoder + boost::shared_ptr outputProtocol_; + + // Go into read mode + void setRead() { + setFlags(EV_READ | EV_PERSIST); + } + + // Go into write mode + void setWrite() { + setFlags(EV_WRITE | EV_PERSIST); + } + + // Set socket idle + void setIdle() { + setFlags(0); + } + + // Set event flags + void setFlags(short eventFlags); + + // Libevent handlers + void workSocket(); + + // Close this client and reset + void close(); + + public: + + // Constructor + TConnection(int socket, short eventFlags, TNonblockingServer *s) { + readBuffer_ = (uint8_t*)malloc(1024); + if (readBuffer_ == NULL) { + throw new facebook::thrift::TException("Out of memory."); + } + readBufferSize_ = 1024; + + // Allocate input and output tranpsorts + // these only need to be allocated once per TConnection (they don't need to be + // reallocated on init() call) + inputTransport_ = boost::shared_ptr(new TMemoryBuffer(readBuffer_, readBufferSize_)); + outputTransport_ = boost::shared_ptr(new TMemoryBuffer()); + + init(socket, eventFlags, s); + } + + // Initialize + void init(int socket, short eventFlags, TNonblockingServer *s); + + // Transition into a new state + void transition(); + + // Handler wrapper + static void eventHandler(int fd, short which, void* v) { + assert(fd == ((TConnection*)v)->socket_); + ((TConnection*)v)->workSocket(); + } + + // Handler wrapper for task block + static void taskHandler(int fd, short which, void* v) { + assert(fd == ((TConnection*)v)->taskHandle_); + if (-1 == ::close(((TConnection*)v)->taskHandle_)) { + GlobalOutput("TConnection::taskHandler close handle failed, resource leak"); + } + ((TConnection*)v)->transition(); + } + +}; + +}}} // facebook::thrift::server + +#endif // #ifndef _THRIFT_SERVER_TSIMPLESERVER_H_ +// Copyright (c) 2006- Facebook +// Distributed under the Thrift Software License +// +// See accompanying file LICENSE or visit the Thrift site at: +// http://developers.facebook.com/thrift/ + +#ifndef _THRIFT_SERVER_TNONBLOCKINGSERVER_H_ +#define _THRIFT_SERVER_TNONBLOCKINGSERVER_H_ 1 + +#include +#include +#include +#include +#include +#include + +namespace facebook { namespace thrift { namespace server { + +using facebook::thrift::transport::TMemoryBuffer; +using facebook::thrift::protocol::TProtocol; +using facebook::thrift::concurrency::Runnable; +using facebook::thrift::concurrency::ThreadManager; + +// Forward declaration of class +class TConnection; + +/** + * This is a non-blocking server in C++ for high performance that operates a + * single IO thread. 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. + * + * @author Mark Slee + */ +class TNonblockingServer : public TServer { + private: + + // Listen backlog + static const int LISTEN_BACKLOG = 1024; + + // Server socket file descriptor + int serverSocket_; + + // Port server runs on + int port_; + + // Whether to frame responses + bool frameResponses_; + + // For processing via thread pool, may be NULL + boost::shared_ptr threadManager_; + + // Is thread pool processing? + bool threadPoolProcessing_; + + // The event base for libevent + event_base* eventBase_; + + // Event struct, for use with eventBase_ + struct event serverEvent_; + + /** + * 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 connectionStack_; + + void handleEvent(int fd, short which); + + public: + TNonblockingServer(boost::shared_ptr processor, + int port) : + TServer(processor), + serverSocket_(-1), + port_(port), + frameResponses_(true), + threadPoolProcessing_(false), + eventBase_(NULL) {} + + TNonblockingServer(boost::shared_ptr processor, + boost::shared_ptr protocolFactory, + int port, + boost::shared_ptr threadManager = boost::shared_ptr()) : + TServer(processor), + serverSocket_(-1), + port_(port), + frameResponses_(true), + threadManager_(threadManager), + eventBase_(NULL) { + setInputTransportFactory(boost::shared_ptr(new TTransportFactory())); + setOutputTransportFactory(boost::shared_ptr(new TTransportFactory())); + setInputProtocolFactory(protocolFactory); + setOutputProtocolFactory(protocolFactory); + setThreadManager(threadManager); + } + + TNonblockingServer(boost::shared_ptr processor, + boost::shared_ptr inputTransportFactory, + boost::shared_ptr outputTransportFactory, + boost::shared_ptr inputProtocolFactory, + boost::shared_ptr outputProtocolFactory, + int port, + boost::shared_ptr threadManager = boost::shared_ptr()) : + TServer(processor), + serverSocket_(0), + port_(port), + frameResponses_(true), + threadManager_(threadManager), + eventBase_(NULL) { + setInputTransportFactory(inputTransportFactory); + setOutputTransportFactory(outputTransportFactory); + setInputProtocolFactory(inputProtocolFactory); + setOutputProtocolFactory(outputProtocolFactory); + setThreadManager(threadManager); + } + + ~TNonblockingServer() {} + + void setThreadManager(boost::shared_ptr threadManager) { + threadManager_ = threadManager; + threadPoolProcessing_ = (threadManager != NULL); + } + + bool isThreadPoolProcessing() const { + return threadPoolProcessing_; + } + + void addTask(boost::shared_ptr task) { + threadManager_->add(task); + } + + void setFrameResponses(bool frameResponses) { + frameResponses_ = frameResponses; + } + + bool getFrameResponses() const { + return frameResponses_; + } + + event_base* getEventBase() const { + return eventBase_; + } + + TConnection* createConnection(int socket, short flags); + + void returnConnection(TConnection* connection); + + static void eventHandler(int fd, short which, void* v) { + ((TNonblockingServer*)v)->handleEvent(fd, which); + } + + void listenSocket(); + + void listenSocket(int fd); + + void registerEvents(event_base* base); + + void serve(); + +}; + +/** + * Two states for sockets, recv and send mode + */ +enum TSocketState { + SOCKET_RECV, + SOCKET_SEND +}; + +/** + * Four states for the nonblocking servr: + * 1) initialize + * 2) read 4 byte frame size + * 3) read frame of data + * 4) send back data (if any) + */ +enum TAppState { + APP_INIT, + APP_READ_FRAME_SIZE, + APP_READ_REQUEST, + APP_WAIT_TASK, + APP_SEND_FRAME_SIZE, + APP_SEND_RESULT +}; + +/** + * Represents a connection that is handled via libevent. This connection + * essentially encapsulates a socket that has some associated libevent state. + */ +class TConnection { + private: + + class Task; + + // Server handle + TNonblockingServer* server_; + + // Socket handle + int socket_; + + // Libevent object + struct event event_; + + // Libevent flags + short eventFlags_; + + // Socket mode + TSocketState socketState_; + + // Application state + TAppState appState_; + + // How much data needed to read + uint32_t readWant_; + + // Where in the read buffer are we + uint32_t readBufferPos_; + + // Read buffer + uint8_t* readBuffer_; + + // Read buffer size + uint32_t readBufferSize_; + + // Write buffer + uint8_t* writeBuffer_; + + // Write buffer size + uint32_t writeBufferSize_; + + // How far through writing are we? + uint32_t writeBufferPos_; + + // Frame size + int32_t frameSize_; + + // Task handle + int taskHandle_; + + // Task event + struct event taskEvent_; + + // Transport to read from + boost::shared_ptr inputTransport_; + + // Transport that processor writes to + boost::shared_ptr outputTransport_; + + // extra transport generated by transport factory (e.g. BufferedRouterTransport) + boost::shared_ptr factoryInputTransport_; + boost::shared_ptr factoryOutputTransport_; + + // Protocol decoder + boost::shared_ptr inputProtocol_; + + // Protocol encoder + boost::shared_ptr outputProtocol_; + + // Go into read mode + void setRead() { + setFlags(EV_READ | EV_PERSIST); + } + + // Go into write mode + void setWrite() { + setFlags(EV_WRITE | EV_PERSIST); + } + + // Set socket idle + void setIdle() { + setFlags(0); + } + + // Set event flags + void setFlags(short eventFlags); + + // Libevent handlers + void workSocket(); + + // Close this client and reset + void close(); + + public: + + // Constructor + TConnection(int socket, short eventFlags, TNonblockingServer *s) { + readBuffer_ = (uint8_t*)malloc(1024); + if (readBuffer_ == NULL) { + throw new facebook::thrift::TException("Out of memory."); + } + readBufferSize_ = 1024; + + // Allocate input and output tranpsorts + // these only need to be allocated once per TConnection (they don't need to be + // reallocated on init() call) + inputTransport_ = boost::shared_ptr(new TMemoryBuffer(readBuffer_, readBufferSize_)); + outputTransport_ = boost::shared_ptr(new TMemoryBuffer()); + + init(socket, eventFlags, s); + } + + // Initialize + void init(int socket, short eventFlags, TNonblockingServer *s); + + // Transition into a new state + void transition(); + + // Handler wrapper + static void eventHandler(int fd, short which, void* v) { + assert(fd == ((TConnection*)v)->socket_); + ((TConnection*)v)->workSocket(); + } + + // Handler wrapper for task block + static void taskHandler(int fd, short which, void* v) { + assert(fd == ((TConnection*)v)->taskHandle_); + if (-1 == ::close(((TConnection*)v)->taskHandle_)) { + GlobalOutput("TConnection::taskHandler close handle failed, resource leak"); + } + ((TConnection*)v)->transition(); + } + +}; + +}}} // facebook::thrift::server + +#endif // #ifndef _THRIFT_SERVER_TSIMPLESERVER_H_ Index: service/include/thrift/server/TSimpleServer.h =================================================================== --- service/include/thrift/server/TSimpleServer.h (revision 0) +++ service/include/thrift/server/TSimpleServer.h (revision 0) @@ -0,0 +1,116 @@ +// Copyright (c) 2006- Facebook +// Distributed under the Thrift Software License +// +// See accompanying file LICENSE or visit the Thrift site at: +// http://developers.facebook.com/thrift/ + +#ifndef _THRIFT_SERVER_TSIMPLESERVER_H_ +#define _THRIFT_SERVER_TSIMPLESERVER_H_ 1 + +#include "server/TServer.h" +#include "transport/TServerTransport.h" + +namespace facebook { namespace thrift { namespace server { + +/** + * This is the most basic simple server. It is single-threaded and runs a + * continuous loop of accepting a single connection, processing requests on + * that connection until it closes, and then repeating. It is a good example + * of how to extend the TServer interface. + * + * @author Mark Slee + */ +class TSimpleServer : public TServer { + public: + TSimpleServer(boost::shared_ptr processor, + boost::shared_ptr serverTransport, + boost::shared_ptr transportFactory, + boost::shared_ptr protocolFactory) : + TServer(processor, serverTransport, transportFactory, protocolFactory), + stop_(false) {} + + TSimpleServer(boost::shared_ptr processor, + boost::shared_ptr serverTransport, + boost::shared_ptr inputTransportFactory, + boost::shared_ptr outputTransportFactory, + boost::shared_ptr inputProtocolFactory, + boost::shared_ptr outputProtocolFactory): + TServer(processor, serverTransport, + inputTransportFactory, outputTransportFactory, + inputProtocolFactory, outputProtocolFactory), + stop_(false) {} + + ~TSimpleServer() {} + + void serve(); + + void stop() { + stop_ = true; + } + + protected: + bool stop_; + +}; + +}}} // facebook::thrift::server + +#endif // #ifndef _THRIFT_SERVER_TSIMPLESERVER_H_ +// Copyright (c) 2006- Facebook +// Distributed under the Thrift Software License +// +// See accompanying file LICENSE or visit the Thrift site at: +// http://developers.facebook.com/thrift/ + +#ifndef _THRIFT_SERVER_TSIMPLESERVER_H_ +#define _THRIFT_SERVER_TSIMPLESERVER_H_ 1 + +#include "server/TServer.h" +#include "transport/TServerTransport.h" + +namespace facebook { namespace thrift { namespace server { + +/** + * This is the most basic simple server. It is single-threaded and runs a + * continuous loop of accepting a single connection, processing requests on + * that connection until it closes, and then repeating. It is a good example + * of how to extend the TServer interface. + * + * @author Mark Slee + */ +class TSimpleServer : public TServer { + public: + TSimpleServer(boost::shared_ptr processor, + boost::shared_ptr serverTransport, + boost::shared_ptr transportFactory, + boost::shared_ptr protocolFactory) : + TServer(processor, serverTransport, transportFactory, protocolFactory), + stop_(false) {} + + TSimpleServer(boost::shared_ptr processor, + boost::shared_ptr serverTransport, + boost::shared_ptr inputTransportFactory, + boost::shared_ptr outputTransportFactory, + boost::shared_ptr inputProtocolFactory, + boost::shared_ptr outputProtocolFactory): + TServer(processor, serverTransport, + inputTransportFactory, outputTransportFactory, + inputProtocolFactory, outputProtocolFactory), + stop_(false) {} + + ~TSimpleServer() {} + + void serve(); + + void stop() { + stop_ = true; + } + + protected: + bool stop_; + +}; + +}}} // facebook::thrift::server + +#endif // #ifndef _THRIFT_SERVER_TSIMPLESERVER_H_ Index: service/include/thrift/Thrift.h =================================================================== --- service/include/thrift/Thrift.h (revision 0) +++ service/include/thrift/Thrift.h (revision 0) @@ -0,0 +1,324 @@ +// Copyright (c) 2006- Facebook +// Distributed under the Thrift Software License +// +// See accompanying file LICENSE or visit the Thrift site at: +// http://developers.facebook.com/thrift/ + +#ifndef _THRIFT_THRIFT_H_ +#define _THRIFT_THRIFT_H_ 1 + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#ifdef HAVE_INTTYPES_H +#include +#endif +#include +#include +#include +#include +#include +#include + +#include "TLogging.h" + +namespace facebook { namespace thrift { + +class TOutput { + public: + TOutput() : f_(&perrorTimeWrapper) {} + + inline void setOutputFunction(void (*function)(const char *)){ + f_ = function; + } + + inline void operator()(const char *message){ + f_(message); + } + + inline static void perrorTimeWrapper(const char* msg) { + time_t now; + char dbgtime[25]; + time(&now); + ctime_r(&now, dbgtime); + dbgtime[24] = 0; + fprintf(stderr, "%s ", dbgtime); + perror(msg); + } + private: + void (*f_)(const char *); +}; + +extern TOutput GlobalOutput; + +namespace protocol { + class TProtocol; +} + +class TException : public std::exception { + public: + TException() {} + + 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 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, + }; + + TApplicationException() : + TException(), + type_(UNKNOWN) {} + + TApplicationException(TApplicationExceptionType type) : + TException(), + type_(type) {} + + TApplicationException(const std::string& message) : + TException(message), + type_(UNKNOWN) {} + + TApplicationException(TApplicationExceptionType type, + const std::string& message) : + TException(message), + type_(type) {} + + virtual ~TApplicationException() throw() {} + + /** + * Returns an error code that provides information about the type of error + * that has occurred. + * + * @return Error code + */ + TApplicationExceptionType getType() { + return type_; + } + + virtual const char* what() const throw() { + if (message_.empty()) { + switch (type_) { + case UNKNOWN : return "TApplicationException: Unknown application exception"; + case UNKNOWN_METHOD : return "TApplicationException: Unknown method"; + case INVALID_MESSAGE_TYPE : return "TApplicationException: Invalid message type"; + case WRONG_METHOD_NAME : return "TApplicationException: Wrong method name"; + case BAD_SEQUENCE_ID : return "TApplicationException: Bad sequence identifier"; + case MISSING_RESULT : return "TApplicationException: Missing result"; + 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_; + +}; + + +// Forward declare this structure used by TDenseProtocol +namespace reflection { namespace local { +struct TypeSpec; +}} + + +}} // facebook::thrift + +#endif // #ifndef _THRIFT_THRIFT_H_ +// Copyright (c) 2006- Facebook +// Distributed under the Thrift Software License +// +// See accompanying file LICENSE or visit the Thrift site at: +// http://developers.facebook.com/thrift/ + +#ifndef _THRIFT_THRIFT_H_ +#define _THRIFT_THRIFT_H_ 1 + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#ifdef HAVE_INTTYPES_H +#include +#endif +#include +#include +#include +#include +#include +#include + +#include "TLogging.h" + +namespace facebook { namespace thrift { + +class TOutput { + public: + TOutput() : f_(&perrorTimeWrapper) {} + + inline void setOutputFunction(void (*function)(const char *)){ + f_ = function; + } + + inline void operator()(const char *message){ + f_(message); + } + + inline static void perrorTimeWrapper(const char* msg) { + time_t now; + char dbgtime[25]; + time(&now); + ctime_r(&now, dbgtime); + dbgtime[24] = 0; + fprintf(stderr, "%s ", dbgtime); + perror(msg); + } + private: + void (*f_)(const char *); +}; + +extern TOutput GlobalOutput; + +namespace protocol { + class TProtocol; +} + +class TException : public std::exception { + public: + TException() {} + + 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 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, + }; + + TApplicationException() : + TException(), + type_(UNKNOWN) {} + + TApplicationException(TApplicationExceptionType type) : + TException(), + type_(type) {} + + TApplicationException(const std::string& message) : + TException(message), + type_(UNKNOWN) {} + + TApplicationException(TApplicationExceptionType type, + const std::string& message) : + TException(message), + type_(type) {} + + virtual ~TApplicationException() throw() {} + + /** + * Returns an error code that provides information about the type of error + * that has occurred. + * + * @return Error code + */ + TApplicationExceptionType getType() { + return type_; + } + + virtual const char* what() const throw() { + if (message_.empty()) { + switch (type_) { + case UNKNOWN : return "TApplicationException: Unknown application exception"; + case UNKNOWN_METHOD : return "TApplicationException: Unknown method"; + case INVALID_MESSAGE_TYPE : return "TApplicationException: Invalid message type"; + case WRONG_METHOD_NAME : return "TApplicationException: Wrong method name"; + case BAD_SEQUENCE_ID : return "TApplicationException: Bad sequence identifier"; + case MISSING_RESULT : return "TApplicationException: Missing result"; + 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_; + +}; + + +// Forward declare this structure used by TDenseProtocol +namespace reflection { namespace local { +struct TypeSpec; +}} + + +}} // facebook::thrift + +#endif // #ifndef _THRIFT_THRIFT_H_ Index: service/include/thrift/TProcessor.h =================================================================== --- service/include/thrift/TProcessor.h (revision 0) +++ service/include/thrift/TProcessor.h (revision 0) @@ -0,0 +1,82 @@ +// Copyright (c) 2006- Facebook +// Distributed under the Thrift Software License +// +// See accompanying file LICENSE or visit the Thrift site at: +// http://developers.facebook.com/thrift/ + +#ifndef _THRIFT_TPROCESSOR_H_ +#define _THRIFT_TPROCESSOR_H_ 1 + +#include +#include +#include + +namespace facebook { namespace thrift { + +/** + * 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. + * + * @author Mark Slee + */ +class TProcessor { + public: + virtual ~TProcessor() {} + + virtual bool process(boost::shared_ptr in, + boost::shared_ptr out) = 0; + + bool process(boost::shared_ptr io) { + return process(io, io); + } + + protected: + TProcessor() {} +}; + +}} // facebook::thrift + +#endif // #ifndef _THRIFT_PROCESSOR_H_ +// Copyright (c) 2006- Facebook +// Distributed under the Thrift Software License +// +// See accompanying file LICENSE or visit the Thrift site at: +// http://developers.facebook.com/thrift/ + +#ifndef _THRIFT_TPROCESSOR_H_ +#define _THRIFT_TPROCESSOR_H_ 1 + +#include +#include +#include + +namespace facebook { namespace thrift { + +/** + * 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. + * + * @author Mark Slee + */ +class TProcessor { + public: + virtual ~TProcessor() {} + + virtual bool process(boost::shared_ptr in, + boost::shared_ptr out) = 0; + + bool process(boost::shared_ptr io) { + return process(io, io); + } + + protected: + TProcessor() {} +}; + +}} // facebook::thrift + +#endif // #ifndef _THRIFT_PROCESSOR_H_ Index: service/include/thrift/concurrency/TimerManager.h =================================================================== --- service/include/thrift/concurrency/TimerManager.h (revision 0) +++ service/include/thrift/concurrency/TimerManager.h (revision 0) @@ -0,0 +1,216 @@ +// Copyright (c) 2006- Facebook +// Distributed under the Thrift Software License +// +// See accompanying file LICENSE or visit the Thrift site at: +// http://developers.facebook.com/thrift/ + +#ifndef _THRIFT_CONCURRENCY_TIMERMANAGER_H_ +#define _THRIFT_CONCURRENCY_TIMERMANAGER_H_ 1 + +#include "Exception.h" +#include "Monitor.h" +#include "Thread.h" + +#include +#include +#include + +namespace facebook { namespace thrift { namespace concurrency { + +/** + * Timer Manager + * + * This class dispatches timer tasks when they fall due. + * + * @author marc + * @version $Id:$ + */ +class TimerManager { + + public: + + TimerManager(); + + virtual ~TimerManager(); + + virtual boost::shared_ptr threadFactory() const; + + virtual void threadFactory(boost::shared_ptr 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 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 task, const struct timespec& 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 task); + + enum STATE { + UNINITIALIZED, + STARTING, + STARTED, + STOPPING, + STOPPED + }; + + virtual const STATE state() const; + + private: + boost::shared_ptr threadFactory_; + class Task; + friend class Task; + std::multimap > taskMap_; + size_t taskCount_; + Monitor monitor_; + STATE state_; + class Dispatcher; + friend class Dispatcher; + boost::shared_ptr dispatcher_; + boost::shared_ptr dispatcherThread_; +}; + +}}} // facebook::thrift::concurrency + +#endif // #ifndef _THRIFT_CONCURRENCY_TIMERMANAGER_H_ +// Copyright (c) 2006- Facebook +// Distributed under the Thrift Software License +// +// See accompanying file LICENSE or visit the Thrift site at: +// http://developers.facebook.com/thrift/ + +#ifndef _THRIFT_CONCURRENCY_TIMERMANAGER_H_ +#define _THRIFT_CONCURRENCY_TIMERMANAGER_H_ 1 + +#include "Exception.h" +#include "Monitor.h" +#include "Thread.h" + +#include +#include +#include + +namespace facebook { namespace thrift { namespace concurrency { + +/** + * Timer Manager + * + * This class dispatches timer tasks when they fall due. + * + * @author marc + * @version $Id:$ + */ +class TimerManager { + + public: + + TimerManager(); + + virtual ~TimerManager(); + + virtual boost::shared_ptr threadFactory() const; + + virtual void threadFactory(boost::shared_ptr 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 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 task, const struct timespec& 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 task); + + enum STATE { + UNINITIALIZED, + STARTING, + STARTED, + STOPPING, + STOPPED + }; + + virtual const STATE state() const; + + private: + boost::shared_ptr threadFactory_; + class Task; + friend class Task; + std::multimap > taskMap_; + size_t taskCount_; + Monitor monitor_; + STATE state_; + class Dispatcher; + friend class Dispatcher; + boost::shared_ptr dispatcher_; + boost::shared_ptr dispatcherThread_; +}; + +}}} // facebook::thrift::concurrency + +#endif // #ifndef _THRIFT_CONCURRENCY_TIMERMANAGER_H_ Index: service/include/thrift/concurrency/Util.h =================================================================== --- service/include/thrift/concurrency/Util.h (revision 0) +++ service/include/thrift/concurrency/Util.h (revision 0) @@ -0,0 +1,182 @@ +// Copyright (c) 2006- Facebook +// Distributed under the Thrift Software License +// +// See accompanying file LICENSE or visit the Thrift site at: +// http://developers.facebook.com/thrift/ + +#ifndef _THRIFT_CONCURRENCY_UTIL_H_ +#define _THRIFT_CONCURRENCY_UTIL_H_ 1 + +#include + +#include +#include +#if defined(HAVE_CLOCK_GETTIME) +#include +#else // defined(HAVE_CLOCK_GETTIME) +#include +#endif // defined(HAVE_CLOCK_GETTIME) + +namespace facebook { 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 crap. Rather it should be inluded directly in + * concurrency library implementation source. + * + * @author marc + * @version $Id:$ + */ +class Util { + + static const int64_t NS_PER_S = 1000000000LL; + static const int64_t MS_PER_S = 1000LL; + static const int64_t NS_PER_MS = 1000000LL; + + public: + + /** + * Converts timespec to milliseconds + * + * @param struct timespec& result + * @param time or duration in milliseconds + */ + static void toTimespec(struct 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 + } + + /** + * Converts timespec to milliseconds + */ + static const void toMilliseconds(int64_t& result, const struct timespec& value) { + result = + (value.tv_sec * MS_PER_S) + + (value.tv_nsec / NS_PER_MS) + + (value.tv_nsec % NS_PER_MS >= 500000 ? 1 : 0); + } + + /** + * Get current time as milliseconds from epoch + */ + static const int64_t currentTime() { +#if defined(HAVE_CLOCK_GETTIME) + struct timespec now; + int ret = clock_gettime(CLOCK_REALTIME, &now); + assert(ret == 0); + return + (now.tv_sec * MS_PER_S) + + (now.tv_nsec / NS_PER_MS) + + (now.tv_nsec % NS_PER_MS >= 500000 ? 1 : 0) ; +#elif defined(HAVE_GETTIMEOFDAY) + struct timeval now; + int ret = gettimeofday(&now, NULL); + assert(ret == 0); + return + (((int64_t)now.tv_sec) * MS_PER_S) + + (now.tv_usec / MS_PER_S) + + (now.tv_usec % MS_PER_S >= 500 ? 1 : 0); +#endif // defined(HAVE_GETTIMEDAY) + } + +}; + +}}} // facebook::thrift::concurrency + +#endif // #ifndef _THRIFT_CONCURRENCY_UTIL_H_ +// Copyright (c) 2006- Facebook +// Distributed under the Thrift Software License +// +// See accompanying file LICENSE or visit the Thrift site at: +// http://developers.facebook.com/thrift/ + +#ifndef _THRIFT_CONCURRENCY_UTIL_H_ +#define _THRIFT_CONCURRENCY_UTIL_H_ 1 + +#include + +#include +#include +#if defined(HAVE_CLOCK_GETTIME) +#include +#else // defined(HAVE_CLOCK_GETTIME) +#include +#endif // defined(HAVE_CLOCK_GETTIME) + +namespace facebook { 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 crap. Rather it should be inluded directly in + * concurrency library implementation source. + * + * @author marc + * @version $Id:$ + */ +class Util { + + static const int64_t NS_PER_S = 1000000000LL; + static const int64_t MS_PER_S = 1000LL; + static const int64_t NS_PER_MS = 1000000LL; + + public: + + /** + * Converts timespec to milliseconds + * + * @param struct timespec& result + * @param time or duration in milliseconds + */ + static void toTimespec(struct 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 + } + + /** + * Converts timespec to milliseconds + */ + static const void toMilliseconds(int64_t& result, const struct timespec& value) { + result = + (value.tv_sec * MS_PER_S) + + (value.tv_nsec / NS_PER_MS) + + (value.tv_nsec % NS_PER_MS >= 500000 ? 1 : 0); + } + + /** + * Get current time as milliseconds from epoch + */ + static const int64_t currentTime() { +#if defined(HAVE_CLOCK_GETTIME) + struct timespec now; + int ret = clock_gettime(CLOCK_REALTIME, &now); + assert(ret == 0); + return + (now.tv_sec * MS_PER_S) + + (now.tv_nsec / NS_PER_MS) + + (now.tv_nsec % NS_PER_MS >= 500000 ? 1 : 0) ; +#elif defined(HAVE_GETTIMEOFDAY) + struct timeval now; + int ret = gettimeofday(&now, NULL); + assert(ret == 0); + return + (((int64_t)now.tv_sec) * MS_PER_S) + + (now.tv_usec / MS_PER_S) + + (now.tv_usec % MS_PER_S >= 500 ? 1 : 0); +#endif // defined(HAVE_GETTIMEDAY) + } + +}; + +}}} // facebook::thrift::concurrency + +#endif // #ifndef _THRIFT_CONCURRENCY_UTIL_H_ Index: service/include/thrift/concurrency/Exception.h =================================================================== --- service/include/thrift/concurrency/Exception.h (revision 0) +++ service/include/thrift/concurrency/Exception.h (revision 0) @@ -0,0 +1,94 @@ +// Copyright (c) 2006- Facebook +// Distributed under the Thrift Software License +// +// See accompanying file LICENSE or visit the Thrift site at: +// http://developers.facebook.com/thrift/ + +#ifndef _THRIFT_CONCURRENCY_EXCEPTION_H_ +#define _THRIFT_CONCURRENCY_EXCEPTION_H_ 1 + +#include +#include + +namespace facebook { namespace thrift { namespace concurrency { + +class NoSuchTaskException : public facebook::thrift::TException {}; + +class UncancellableTaskException : public facebook::thrift::TException {}; + +class InvalidArgumentException : public facebook::thrift::TException {}; + +class IllegalStateException : public facebook::thrift::TException {}; + +class TimedOutException : public facebook::thrift::TException { +public: + TimedOutException():TException("TimedOutException"){}; + TimedOutException(const std::string& message ) : + TException(message) {} +}; + +class TooManyPendingTasksException : public facebook::thrift::TException { +public: + TooManyPendingTasksException():TException("TooManyPendingTasksException"){}; + TooManyPendingTasksException(const std::string& message ) : + TException(message) {} +}; + +class SystemResourceException : public facebook::thrift::TException { +public: + SystemResourceException() {} + + SystemResourceException(const std::string& message) : + TException(message) {} +}; + +}}} // facebook::thrift::concurrency + +#endif // #ifndef _THRIFT_CONCURRENCY_EXCEPTION_H_ +// Copyright (c) 2006- Facebook +// Distributed under the Thrift Software License +// +// See accompanying file LICENSE or visit the Thrift site at: +// http://developers.facebook.com/thrift/ + +#ifndef _THRIFT_CONCURRENCY_EXCEPTION_H_ +#define _THRIFT_CONCURRENCY_EXCEPTION_H_ 1 + +#include +#include + +namespace facebook { namespace thrift { namespace concurrency { + +class NoSuchTaskException : public facebook::thrift::TException {}; + +class UncancellableTaskException : public facebook::thrift::TException {}; + +class InvalidArgumentException : public facebook::thrift::TException {}; + +class IllegalStateException : public facebook::thrift::TException {}; + +class TimedOutException : public facebook::thrift::TException { +public: + TimedOutException():TException("TimedOutException"){}; + TimedOutException(const std::string& message ) : + TException(message) {} +}; + +class TooManyPendingTasksException : public facebook::thrift::TException { +public: + TooManyPendingTasksException():TException("TooManyPendingTasksException"){}; + TooManyPendingTasksException(const std::string& message ) : + TException(message) {} +}; + +class SystemResourceException : public facebook::thrift::TException { +public: + SystemResourceException() {} + + SystemResourceException(const std::string& message) : + TException(message) {} +}; + +}}} // facebook::thrift::concurrency + +#endif // #ifndef _THRIFT_CONCURRENCY_EXCEPTION_H_ Index: service/include/thrift/concurrency/Mutex.h =================================================================== --- service/include/thrift/concurrency/Mutex.h (revision 0) +++ service/include/thrift/concurrency/Mutex.h (revision 0) @@ -0,0 +1,188 @@ +// Copyright (c) 2006- Facebook +// Distributed under the Thrift Software License +// +// See accompanying file LICENSE or visit the Thrift site at: +// http://developers.facebook.com/thrift/ + +#ifndef _THRIFT_CONCURRENCY_MUTEX_H_ +#define _THRIFT_CONCURRENCY_MUTEX_H_ 1 + +#include + +namespace facebook { namespace thrift { namespace concurrency { + +/** + * A simple mutex class + * + * @author marc + * @version $Id:$ + */ +class Mutex { + public: + Mutex(); + virtual ~Mutex() {} + virtual void lock() const; + virtual bool trylock() const; + virtual void unlock() const; + + private: + + class impl; + boost::shared_ptr 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_; +}; + +class Guard { + public: + Guard(const Mutex& value) : mutex_(value) { + mutex_.lock(); + } + ~Guard() { + mutex_.unlock(); + } + + private: + const Mutex& mutex_; +}; + +class RWGuard { + public: + RWGuard(const ReadWriteMutex& value, bool write = 0) : rw_mutex_(value) { + if (write) { + rw_mutex_.acquireWrite(); + } else { + rw_mutex_.acquireRead(); + } + } + ~RWGuard() { + rw_mutex_.release(); + } + private: + const ReadWriteMutex& rw_mutex_; +}; + + +// A little hack to prevent someone from trying to do "Guard(m);" +// Sorry for polluting the global namespace, but I think it's worth it. +#define Guard(m) incorrect_use_of_Guard(m) +#define RWGuard(m) incorrect_use_of_RWGuard(m) + + +}}} // facebook::thrift::concurrency + +#endif // #ifndef _THRIFT_CONCURRENCY_MUTEX_H_ +// Copyright (c) 2006- Facebook +// Distributed under the Thrift Software License +// +// See accompanying file LICENSE or visit the Thrift site at: +// http://developers.facebook.com/thrift/ + +#ifndef _THRIFT_CONCURRENCY_MUTEX_H_ +#define _THRIFT_CONCURRENCY_MUTEX_H_ 1 + +#include + +namespace facebook { namespace thrift { namespace concurrency { + +/** + * A simple mutex class + * + * @author marc + * @version $Id:$ + */ +class Mutex { + public: + Mutex(); + virtual ~Mutex() {} + virtual void lock() const; + virtual bool trylock() const; + virtual void unlock() const; + + private: + + class impl; + boost::shared_ptr 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_; +}; + +class Guard { + public: + Guard(const Mutex& value) : mutex_(value) { + mutex_.lock(); + } + ~Guard() { + mutex_.unlock(); + } + + private: + const Mutex& mutex_; +}; + +class RWGuard { + public: + RWGuard(const ReadWriteMutex& value, bool write = 0) : rw_mutex_(value) { + if (write) { + rw_mutex_.acquireWrite(); + } else { + rw_mutex_.acquireRead(); + } + } + ~RWGuard() { + rw_mutex_.release(); + } + private: + const ReadWriteMutex& rw_mutex_; +}; + + +// A little hack to prevent someone from trying to do "Guard(m);" +// Sorry for polluting the global namespace, but I think it's worth it. +#define Guard(m) incorrect_use_of_Guard(m) +#define RWGuard(m) incorrect_use_of_RWGuard(m) + + +}}} // facebook::thrift::concurrency + +#endif // #ifndef _THRIFT_CONCURRENCY_MUTEX_H_ Index: service/include/thrift/concurrency/PosixThreadFactory.h =================================================================== --- service/include/thrift/concurrency/PosixThreadFactory.h (revision 0) +++ service/include/thrift/concurrency/PosixThreadFactory.h (revision 0) @@ -0,0 +1,236 @@ +// Copyright (c) 2006- Facebook +// Distributed under the Thrift Software License +// +// See accompanying file LICENSE or visit the Thrift site at: +// http://developers.facebook.com/thrift/ + +#ifndef _THRIFT_CONCURRENCY_POSIXTHREADFACTORY_H_ +#define _THRIFT_CONCURRENCY_POSIXTHREADFACTORY_H_ 1 + +#include "Thread.h" + +#include + +namespace facebook { namespace thrift { namespace concurrency { + +/** + * A thread factory to create posix threads + * + * @author marc + * @version $Id:$ + */ +class PosixThreadFactory : public ThreadFactory { + + public: + + /** + * POSIX Thread scheduler policies + */ + enum POLICY { + OTHER, + FIFO, + ROUND_ROBIN + }; + + /** + * POSIX Thread scheduler relative priorities, + * + * Absolute priority is determined by scheduler policy and OS. This + * enumeration specifies relative priorities such that one can specify a + * priority withing a giving scheduler policy without knowing the absolute + * value of the priority. + */ + enum PRIORITY { + LOWEST = 0, + LOWER = 1, + LOW = 2, + NORMAL = 3, + HIGH = 4, + HIGHER = 5, + HIGHEST = 6, + INCREMENT = 7, + DECREMENT = 8 + }; + + /** + * Posix thread (pthread) factory. All threads created by a factory are reference-counted + * via boost::shared_ptr and boost::weak_ptr. The factory guarantees that threads and + * the Runnable tasks they host will be properly cleaned up once the last strong reference + * to both is given up. + * + * Threads are created with the specified policy, priority, stack-size and detachable-mode + * detached means the thread is free-running and will release all system resources the + * when it completes. A detachable thread is not joinable. The join method + * of a detachable thread will return immediately with no error. + * + * By default threads are not joinable. + */ + + PosixThreadFactory(POLICY policy=ROUND_ROBIN, PRIORITY priority=NORMAL, int stackSize=1, bool detached=true); + + // From ThreadFactory; + boost::shared_ptr newThread(boost::shared_ptr runnable) const; + + // From ThreadFactory; + Thread::id_t getCurrentThreadId() const; + + /** + * Gets stack size for created threads + * + * @return int size in megabytes + */ + virtual int getStackSize() const; + + /** + * Sets stack size for created threads + * + * @param value size in megabytes + */ + virtual void setStackSize(int value); + + /** + * Gets priority relative to current policy + */ + virtual PRIORITY getPriority() const; + + /** + * Sets priority relative to current policy + */ + virtual void setPriority(PRIORITY priority); + + /** + * Sets detached mode of threads + */ + virtual void setDetached(bool detached); + + /** + * Gets current detached mode + */ + virtual bool isDetached() const; + + private: + class Impl; + boost::shared_ptr impl_; +}; + +}}} // facebook::thrift::concurrency + +#endif // #ifndef _THRIFT_CONCURRENCY_POSIXTHREADFACTORY_H_ +// Copyright (c) 2006- Facebook +// Distributed under the Thrift Software License +// +// See accompanying file LICENSE or visit the Thrift site at: +// http://developers.facebook.com/thrift/ + +#ifndef _THRIFT_CONCURRENCY_POSIXTHREADFACTORY_H_ +#define _THRIFT_CONCURRENCY_POSIXTHREADFACTORY_H_ 1 + +#include "Thread.h" + +#include + +namespace facebook { namespace thrift { namespace concurrency { + +/** + * A thread factory to create posix threads + * + * @author marc + * @version $Id:$ + */ +class PosixThreadFactory : public ThreadFactory { + + public: + + /** + * POSIX Thread scheduler policies + */ + enum POLICY { + OTHER, + FIFO, + ROUND_ROBIN + }; + + /** + * POSIX Thread scheduler relative priorities, + * + * Absolute priority is determined by scheduler policy and OS. This + * enumeration specifies relative priorities such that one can specify a + * priority withing a giving scheduler policy without knowing the absolute + * value of the priority. + */ + enum PRIORITY { + LOWEST = 0, + LOWER = 1, + LOW = 2, + NORMAL = 3, + HIGH = 4, + HIGHER = 5, + HIGHEST = 6, + INCREMENT = 7, + DECREMENT = 8 + }; + + /** + * Posix thread (pthread) factory. All threads created by a factory are reference-counted + * via boost::shared_ptr and boost::weak_ptr. The factory guarantees that threads and + * the Runnable tasks they host will be properly cleaned up once the last strong reference + * to both is given up. + * + * Threads are created with the specified policy, priority, stack-size and detachable-mode + * detached means the thread is free-running and will release all system resources the + * when it completes. A detachable thread is not joinable. The join method + * of a detachable thread will return immediately with no error. + * + * By default threads are not joinable. + */ + + PosixThreadFactory(POLICY policy=ROUND_ROBIN, PRIORITY priority=NORMAL, int stackSize=1, bool detached=true); + + // From ThreadFactory; + boost::shared_ptr newThread(boost::shared_ptr runnable) const; + + // From ThreadFactory; + Thread::id_t getCurrentThreadId() const; + + /** + * Gets stack size for created threads + * + * @return int size in megabytes + */ + virtual int getStackSize() const; + + /** + * Sets stack size for created threads + * + * @param value size in megabytes + */ + virtual void setStackSize(int value); + + /** + * Gets priority relative to current policy + */ + virtual PRIORITY getPriority() const; + + /** + * Sets priority relative to current policy + */ + virtual void setPriority(PRIORITY priority); + + /** + * Sets detached mode of threads + */ + virtual void setDetached(bool detached); + + /** + * Gets current detached mode + */ + virtual bool isDetached() const; + + private: + class Impl; + boost::shared_ptr impl_; +}; + +}}} // facebook::thrift::concurrency + +#endif // #ifndef _THRIFT_CONCURRENCY_POSIXTHREADFACTORY_H_ Index: service/include/thrift/concurrency/ThreadManager.h =================================================================== --- service/include/thrift/concurrency/ThreadManager.h (revision 0) +++ service/include/thrift/concurrency/ThreadManager.h (revision 0) @@ -0,0 +1,314 @@ +// Copyright (c) 2006- Facebook +// Distributed under the Thrift Software License +// +// See accompanying file LICENSE or visit the Thrift site at: +// http://developers.facebook.com/thrift/ + +#ifndef _THRIFT_CONCURRENCY_THREADMANAGER_H_ +#define _THRIFT_CONCURRENCY_THREADMANAGER_H_ 1 + +#include +#include +#include "Thread.h" + +namespace facebook { namespace thrift { namespace concurrency { + +/** + * Thread Pool Manager and related classes + * + * @author marc + * @version $Id:$ + */ +class ThreadManager; + +/** + * ThreadManager class + * + * This class manages a pool of threads. It uses a ThreadFactory to create + * threads. It never actually creates or destroys worker threads, rather + * It maintains statistics on number of idle threads, number of active threads, + * task backlog, and average wait and service times and informs the PoolPolicy + * object bound to instances of this manager of interesting transitions. It is + * then up the PoolPolicy object to decide if the thread pool size needs to be + * adjusted and call this object addWorker and removeWorker methods to make + * changes. + * + * This design allows different policy implementations to used this code to + * handle basic worker thread management and worker task execution and focus on + * policy issues. The simplest policy, StaticPolicy, does nothing other than + * create a fixed number of threads. + */ +class ThreadManager { + + protected: + ThreadManager() {} + + public: + virtual ~ThreadManager() {} + + /** + * Starts the thread manager. Verifies all attributes have been properly + * initialized, then allocates necessary resources to begin operation + */ + virtual void start() = 0; + + /** + * Stops the thread manager. Aborts all remaining unprocessed task, shuts + * down all created worker threads, and realeases all allocated resources. + * This method blocks for all worker threads to complete, thus it can + * potentially block forever if a worker thread is running a task that + * won't terminate. + */ + virtual void stop() = 0; + + /** + * Joins the thread manager. This is the same as stop, except that it will + * block until all the workers have finished their work. At that point + * the ThreadManager will transition into the STOPPED state. + */ + virtual void join() = 0; + + enum STATE { + UNINITIALIZED, + STARTING, + STARTED, + JOINING, + STOPPING, + STOPPED + }; + + virtual const STATE state() const = 0; + + virtual boost::shared_ptr threadFactory() const = 0; + + virtual void threadFactory(boost::shared_ptr value) = 0; + + virtual void addWorker(size_t value=1) = 0; + + virtual void removeWorker(size_t value=1) = 0; + + /** + * Gets the current number of idle worker threads + */ + virtual size_t idleWorkerCount() const = 0; + + /** + * Gets the current number of total worker threads + */ + virtual size_t workerCount() const = 0; + + /** + * Gets the current number of pending tasks + */ + virtual size_t pendingTaskCount() const = 0; + + /** + * Gets the current number of pending and executing tasks + */ + virtual size_t totalTaskCount() const = 0; + + /** + * Gets the maximum pending task count. 0 indicates no maximum + */ + virtual size_t pendingTaskCountMax() const = 0; + + /** + * 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 + * + * @throws TooManyPendingTasksException Pending task count exceeds max pending task count + */ + virtual void add(boost::shared_ptrtask, int64_t timeout=0LL) = 0; + + /** + * Removes a pending task + */ + virtual void remove(boost::shared_ptr task) = 0; + + static boost::shared_ptr 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 newSimpleThreadManager(size_t count=4, size_t pendingTaskCountMax=0); + + class Task; + + class Worker; + + class Impl; +}; + +}}} // facebook::thrift::concurrency + +#endif // #ifndef _THRIFT_CONCURRENCY_THREADMANAGER_H_ +// Copyright (c) 2006- Facebook +// Distributed under the Thrift Software License +// +// See accompanying file LICENSE or visit the Thrift site at: +// http://developers.facebook.com/thrift/ + +#ifndef _THRIFT_CONCURRENCY_THREADMANAGER_H_ +#define _THRIFT_CONCURRENCY_THREADMANAGER_H_ 1 + +#include +#include +#include "Thread.h" + +namespace facebook { namespace thrift { namespace concurrency { + +/** + * Thread Pool Manager and related classes + * + * @author marc + * @version $Id:$ + */ +class ThreadManager; + +/** + * ThreadManager class + * + * This class manages a pool of threads. It uses a ThreadFactory to create + * threads. It never actually creates or destroys worker threads, rather + * It maintains statistics on number of idle threads, number of active threads, + * task backlog, and average wait and service times and informs the PoolPolicy + * object bound to instances of this manager of interesting transitions. It is + * then up the PoolPolicy object to decide if the thread pool size needs to be + * adjusted and call this object addWorker and removeWorker methods to make + * changes. + * + * This design allows different policy implementations to used this code to + * handle basic worker thread management and worker task execution and focus on + * policy issues. The simplest policy, StaticPolicy, does nothing other than + * create a fixed number of threads. + */ +class ThreadManager { + + protected: + ThreadManager() {} + + public: + virtual ~ThreadManager() {} + + /** + * Starts the thread manager. Verifies all attributes have been properly + * initialized, then allocates necessary resources to begin operation + */ + virtual void start() = 0; + + /** + * Stops the thread manager. Aborts all remaining unprocessed task, shuts + * down all created worker threads, and realeases all allocated resources. + * This method blocks for all worker threads to complete, thus it can + * potentially block forever if a worker thread is running a task that + * won't terminate. + */ + virtual void stop() = 0; + + /** + * Joins the thread manager. This is the same as stop, except that it will + * block until all the workers have finished their work. At that point + * the ThreadManager will transition into the STOPPED state. + */ + virtual void join() = 0; + + enum STATE { + UNINITIALIZED, + STARTING, + STARTED, + JOINING, + STOPPING, + STOPPED + }; + + virtual const STATE state() const = 0; + + virtual boost::shared_ptr threadFactory() const = 0; + + virtual void threadFactory(boost::shared_ptr value) = 0; + + virtual void addWorker(size_t value=1) = 0; + + virtual void removeWorker(size_t value=1) = 0; + + /** + * Gets the current number of idle worker threads + */ + virtual size_t idleWorkerCount() const = 0; + + /** + * Gets the current number of total worker threads + */ + virtual size_t workerCount() const = 0; + + /** + * Gets the current number of pending tasks + */ + virtual size_t pendingTaskCount() const = 0; + + /** + * Gets the current number of pending and executing tasks + */ + virtual size_t totalTaskCount() const = 0; + + /** + * Gets the maximum pending task count. 0 indicates no maximum + */ + virtual size_t pendingTaskCountMax() const = 0; + + /** + * 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 + * + * @throws TooManyPendingTasksException Pending task count exceeds max pending task count + */ + virtual void add(boost::shared_ptrtask, int64_t timeout=0LL) = 0; + + /** + * Removes a pending task + */ + virtual void remove(boost::shared_ptr task) = 0; + + static boost::shared_ptr 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 newSimpleThreadManager(size_t count=4, size_t pendingTaskCountMax=0); + + class Task; + + class Worker; + + class Impl; +}; + +}}} // facebook::thrift::concurrency + +#endif // #ifndef _THRIFT_CONCURRENCY_THREADMANAGER_H_ Index: service/include/thrift/concurrency/Monitor.h =================================================================== --- service/include/thrift/concurrency/Monitor.h (revision 0) +++ service/include/thrift/concurrency/Monitor.h (revision 0) @@ -0,0 +1,144 @@ +// Copyright (c) 2006- Facebook +// Distributed under the Thrift Software License +// +// See accompanying file LICENSE or visit the Thrift site at: +// http://developers.facebook.com/thrift/ + +#ifndef _THRIFT_CONCURRENCY_MONITOR_H_ +#define _THRIFT_CONCURRENCY_MONITOR_H_ 1 + +#include "Exception.h" + +namespace facebook { 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 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. + * + * @author marc + * @version $Id:$ + */ +class Monitor { + + public: + + Monitor(); + + virtual ~Monitor(); + + virtual void lock() const; + + virtual void unlock() const; + + virtual void wait(int64_t timeout=0LL) const; + + virtual void notify() const; + + virtual void notifyAll() const; + + private: + + class Impl; + + Impl* impl_; +}; + +class Synchronized { + public: + + Synchronized(const Monitor& value) : + monitor_(value) { + monitor_.lock(); + } + + ~Synchronized() { + monitor_.unlock(); + } + + private: + const Monitor& monitor_; +}; + + +}}} // facebook::thrift::concurrency + +#endif // #ifndef _THRIFT_CONCURRENCY_MONITOR_H_ +// Copyright (c) 2006- Facebook +// Distributed under the Thrift Software License +// +// See accompanying file LICENSE or visit the Thrift site at: +// http://developers.facebook.com/thrift/ + +#ifndef _THRIFT_CONCURRENCY_MONITOR_H_ +#define _THRIFT_CONCURRENCY_MONITOR_H_ 1 + +#include "Exception.h" + +namespace facebook { 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 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. + * + * @author marc + * @version $Id:$ + */ +class Monitor { + + public: + + Monitor(); + + virtual ~Monitor(); + + virtual void lock() const; + + virtual void unlock() const; + + virtual void wait(int64_t timeout=0LL) const; + + virtual void notify() const; + + virtual void notifyAll() const; + + private: + + class Impl; + + Impl* impl_; +}; + +class Synchronized { + public: + + Synchronized(const Monitor& value) : + monitor_(value) { + monitor_.lock(); + } + + ~Synchronized() { + monitor_.unlock(); + } + + private: + const Monitor& monitor_; +}; + + +}}} // facebook::thrift::concurrency + +#endif // #ifndef _THRIFT_CONCURRENCY_MONITOR_H_ Index: service/include/thrift/concurrency/Thread.h =================================================================== --- service/include/thrift/concurrency/Thread.h (revision 0) +++ service/include/thrift/concurrency/Thread.h (revision 0) @@ -0,0 +1,224 @@ +// Copyright (c) 2006- Facebook +// Distributed under the Thrift Software License +// +// See accompanying file LICENSE or visit the Thrift site at: +// http://developers.facebook.com/thrift/ + +#ifndef _THRIFT_CONCURRENCY_THREAD_H_ +#define _THRIFT_CONCURRENCY_THREAD_H_ 1 + +#include +#include + +namespace facebook { namespace thrift { namespace concurrency { + +class Thread; + +/** + * Minimal runnable class. More or less analogous to java.lang.Runnable. + * + * @author marc + * @version $Id:$ + */ +class Runnable { + + public: + virtual ~Runnable() {}; + virtual void run() = 0; + + /** + * Gets the thread object that is hosting this runnable object - can return + * an empty boost::shared pointer if no references remain on thet thread object + */ + virtual boost::shared_ptr thread() { 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 value) { thread_ = value; } + + private: + boost::weak_ptr 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 facebook::thrift::concurrency::ThreadFactory) + */ +class Thread { + + public: + + typedef uint64_t id_t; + + virtual ~Thread() {}; + + /** + * Starts the thread. Does platform specific thread creation and + * configuration then invokes the run method of the Runnable object bound + * to this thread. + */ + virtual void start() = 0; + + /** + * Join this thread. Current thread blocks until this target thread + * completes. + */ + virtual void join() = 0; + + /** + * Gets the thread's platform-specific ID + */ + virtual id_t getId() = 0; + + /** + * Gets the runnable object this thread is hosting + */ + virtual boost::shared_ptr runnable() const { return _runnable; } + + protected: + virtual void runnable(boost::shared_ptr value) { _runnable = value; } + + private: + boost::shared_ptr _runnable; + +}; + +/** + * Factory to create platform-specific thread object and bind them to Runnable + * object for execution + */ +class ThreadFactory { + + public: + virtual ~ThreadFactory() {} + virtual boost::shared_ptr newThread(boost::shared_ptr runnable) const = 0; + + /** Gets the current thread id or unknown_thread_id if the current thread is not a thrift thread */ + + static const Thread::id_t unknown_thread_id; + + virtual Thread::id_t getCurrentThreadId() const = 0; +}; + +}}} // facebook::thrift::concurrency + +#endif // #ifndef _THRIFT_CONCURRENCY_THREAD_H_ +// Copyright (c) 2006- Facebook +// Distributed under the Thrift Software License +// +// See accompanying file LICENSE or visit the Thrift site at: +// http://developers.facebook.com/thrift/ + +#ifndef _THRIFT_CONCURRENCY_THREAD_H_ +#define _THRIFT_CONCURRENCY_THREAD_H_ 1 + +#include +#include + +namespace facebook { namespace thrift { namespace concurrency { + +class Thread; + +/** + * Minimal runnable class. More or less analogous to java.lang.Runnable. + * + * @author marc + * @version $Id:$ + */ +class Runnable { + + public: + virtual ~Runnable() {}; + virtual void run() = 0; + + /** + * Gets the thread object that is hosting this runnable object - can return + * an empty boost::shared pointer if no references remain on thet thread object + */ + virtual boost::shared_ptr thread() { 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 value) { thread_ = value; } + + private: + boost::weak_ptr 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 facebook::thrift::concurrency::ThreadFactory) + */ +class Thread { + + public: + + typedef uint64_t id_t; + + virtual ~Thread() {}; + + /** + * Starts the thread. Does platform specific thread creation and + * configuration then invokes the run method of the Runnable object bound + * to this thread. + */ + virtual void start() = 0; + + /** + * Join this thread. Current thread blocks until this target thread + * completes. + */ + virtual void join() = 0; + + /** + * Gets the thread's platform-specific ID + */ + virtual id_t getId() = 0; + + /** + * Gets the runnable object this thread is hosting + */ + virtual boost::shared_ptr runnable() const { return _runnable; } + + protected: + virtual void runnable(boost::shared_ptr value) { _runnable = value; } + + private: + boost::shared_ptr _runnable; + +}; + +/** + * Factory to create platform-specific thread object and bind them to Runnable + * object for execution + */ +class ThreadFactory { + + public: + virtual ~ThreadFactory() {} + virtual boost::shared_ptr newThread(boost::shared_ptr runnable) const = 0; + + /** Gets the current thread id or unknown_thread_id if the current thread is not a thrift thread */ + + static const Thread::id_t unknown_thread_id; + + virtual Thread::id_t getCurrentThreadId() const = 0; +}; + +}}} // facebook::thrift::concurrency + +#endif // #ifndef _THRIFT_CONCURRENCY_THREAD_H_ Index: service/include/thrift/config.h =================================================================== --- service/include/thrift/config.h (revision 0) +++ service/include/thrift/config.h (revision 0) @@ -0,0 +1,520 @@ +/* config.h. Generated by configure. */ +/* config.hin. Generated from configure.ac by autoheader. */ + +/* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP + systems. This function is required for `alloca.c' support on those systems. + */ +/* #undef CRAY_STACKSEG_END */ + +/* Define to 1 if using `alloca.c'. */ +/* #undef C_ALLOCA */ + +/* Define to 1 if you have `alloca', as a function or macro. */ +#define HAVE_ALLOCA 1 + +/* Define to 1 if you have and it should be used (not on Ultrix). + */ +#define HAVE_ALLOCA_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_ARPA_INET_H 1 + +/* define if the Boost library is available */ +#define HAVE_BOOST + +/* Define to 1 if you have the `bzero' function. */ +#define HAVE_BZERO 1 + +/* Define to 1 if you have the `clock_gettime' function. */ +#define HAVE_CLOCK_GETTIME 1 + +/* Define to 1 if you have the declaration of `strerror_r', and to 0 if you + don't. */ +#define HAVE_DECL_STRERROR_R 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_DLFCN_H 1 + +/* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */ +/* #undef HAVE_DOPRNT */ + +/* Define to 1 if you have the header file. */ +#define HAVE_ENDIAN_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_FCNTL_H 1 + +/* Define to 1 if you have the `gethostbyname' function. */ +#define HAVE_GETHOSTBYNAME 1 + +/* Define to 1 if you have the `gettimeofday' function. */ +#define HAVE_GETTIMEOFDAY 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_INTTYPES_H 1 + +/* define if libevent is available */ +#define HAVE_LIBEVENT + +/* Define to 1 if you have the header file. */ +#define HAVE_LIBINTL_H 1 + +/* Define to 1 if you have the `pthread' library (-lpthread). */ +#define HAVE_LIBPTHREAD 1 + +/* Define to 1 if you have the `rt' library (-lrt). */ +#define HAVE_LIBRT 1 + +/* Define to 1 if your system has a GNU libc compatible `malloc' function, and + to 0 otherwise. */ +#define HAVE_MALLOC 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_MALLOC_H 1 + +/* Define to 1 if you have the `memmove' function. */ +#define HAVE_MEMMOVE 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_MEMORY_H 1 + +/* Define to 1 if you have the `memset' function. */ +#define HAVE_MEMSET 1 + +/* Define to 1 if you have the `mkdir' function. */ +#define HAVE_MKDIR 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_NETDB_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_NETINET_IN_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_PTHREAD_H 1 + +/* Define to 1 if your system has a GNU libc compatible `realloc' function, + and to 0 otherwise. */ +#define HAVE_REALLOC 1 + +/* Define to 1 if you have the `realpath' function. */ +#define HAVE_REALPATH 1 + +/* Define to 1 if you have the `select' function. */ +#define HAVE_SELECT 1 + +/* Define to 1 if you have the `socket' function. */ +#define HAVE_SOCKET 1 + +/* Define to 1 if you have the `sqrt' function. */ +#define HAVE_SQRT 1 + +/* Define to 1 if `stat' has the bug that it succeeds when given the + zero-length file name argument. */ +/* #undef HAVE_STAT_EMPTY_STRING_BUG */ + +/* Define to 1 if stdbool.h conforms to C99. */ +#define HAVE_STDBOOL_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDDEF_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDINT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDLIB_H 1 + +/* Define to 1 if you have the `strchr' function. */ +#define HAVE_STRCHR 1 + +/* Define to 1 if you have the `strdup' function. */ +#define HAVE_STRDUP 1 + +/* Define to 1 if you have the `strerror_r' function. */ +#define HAVE_STRERROR_R 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRINGS_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRING_H 1 + +/* Define to 1 if you have the `strstr' function. */ +#define HAVE_STRSTR 1 + +/* Define to 1 if you have the `strtol' function. */ +#define HAVE_STRTOL 1 + +/* Define to 1 if you have the `strtoul' function. */ +#define HAVE_STRTOUL 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_SELECT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_SOCKET_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_STAT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TIME_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TYPES_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_UNISTD_H 1 + +/* Define to 1 if you have the `vprintf' function. */ +#define HAVE_VPRINTF 1 + +/* define if zlib is available */ +/* #undef HAVE_ZLIB */ + +/* Define to 1 if the system has the type `_Bool'. */ +/* #undef HAVE__BOOL */ + +/* Define to 1 if `lstat' dereferences a symlink specified with a trailing + slash. */ +#define LSTAT_FOLLOWS_SLASHED_SYMLINK 1 + +/* Name of package */ +#define PACKAGE "thrift" + +/* Define to the address where bug reports for this package should be sent. */ +#define PACKAGE_BUGREPORT "" + +/* Define to the full name of this package. */ +#define PACKAGE_NAME "thrift" + +/* Define to the full name and version of this package. */ +#define PACKAGE_STRING "thrift 20070917" + +/* Define to the one symbol short name of this package. */ +#define PACKAGE_TARNAME "thrift" + +/* Define to the version of this package. */ +#define PACKAGE_VERSION "20070917" + +/* Define to the type of arg 1 for `select'. */ +#define SELECT_TYPE_ARG1 int + +/* Define to the type of args 2, 3 and 4 for `select'. */ +#define SELECT_TYPE_ARG234 (fd_set *) + +/* Define to the type of arg 5 for `select'. */ +#define SELECT_TYPE_ARG5 (struct timeval *) + +/* If using the C implementation of alloca, define if you know the + direction of stack growth for your system; otherwise it will be + automatically deduced at run-time. + STACK_DIRECTION > 0 => grows toward higher addresses + STACK_DIRECTION < 0 => grows toward lower addresses + STACK_DIRECTION = 0 => direction of growth unknown */ +/* #undef STACK_DIRECTION */ + +/* Define to 1 if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* Define to 1 if strerror_r returns char *. */ +#define STRERROR_R_CHAR_P 1 + +/* Define to 1 if you can safely include both and . */ +#define TIME_WITH_SYS_TIME 1 + +/* Version number of package */ +#define VERSION "20070917" + +/* Define to 1 if `lex' declares `yytext' as a `char *' by default, not a + `char[]'. */ +#define YYTEXT_POINTER 1 + +/* Define to empty if `const' does not conform to ANSI C. */ +/* #undef const */ + +/* Define to `__inline__' or `__inline' if that's what the C compiler + calls it, or to nothing if 'inline' is not supported under any name. */ +#ifndef __cplusplus +/* #undef inline */ +#endif + +/* Define to rpl_malloc if the replacement function should be used. */ +/* #undef malloc */ + +/* Define to `int' if does not define. */ +/* #undef mode_t */ + +/* Define to `long' if does not define. */ +/* #undef off_t */ + +/* Define to rpl_realloc if the replacement function should be used. */ +/* #undef realloc */ + +/* Define to `unsigned' if does not define. */ +/* #undef size_t */ + +/* Define to empty if the keyword `volatile' does not work. Warning: valid + code using `volatile' can become incorrect without. Disable with care. */ +/* #undef volatile */ +/* config.h. Generated by configure. */ +/* config.hin. Generated from configure.ac by autoheader. */ + +/* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP + systems. This function is required for `alloca.c' support on those systems. + */ +/* #undef CRAY_STACKSEG_END */ + +/* Define to 1 if using `alloca.c'. */ +/* #undef C_ALLOCA */ + +/* Define to 1 if you have `alloca', as a function or macro. */ +#define HAVE_ALLOCA 1 + +/* Define to 1 if you have and it should be used (not on Ultrix). + */ +#define HAVE_ALLOCA_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_ARPA_INET_H 1 + +/* define if the Boost library is available */ +#define HAVE_BOOST + +/* Define to 1 if you have the `bzero' function. */ +#define HAVE_BZERO 1 + +/* Define to 1 if you have the `clock_gettime' function. */ +#define HAVE_CLOCK_GETTIME 1 + +/* Define to 1 if you have the declaration of `strerror_r', and to 0 if you + don't. */ +#define HAVE_DECL_STRERROR_R 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_DLFCN_H 1 + +/* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */ +/* #undef HAVE_DOPRNT */ + +/* Define to 1 if you have the header file. */ +#define HAVE_ENDIAN_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_FCNTL_H 1 + +/* Define to 1 if you have the `gethostbyname' function. */ +#define HAVE_GETHOSTBYNAME 1 + +/* Define to 1 if you have the `gettimeofday' function. */ +#define HAVE_GETTIMEOFDAY 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_INTTYPES_H 1 + +/* define if libevent is available */ +#define HAVE_LIBEVENT + +/* Define to 1 if you have the header file. */ +#define HAVE_LIBINTL_H 1 + +/* Define to 1 if you have the `pthread' library (-lpthread). */ +#define HAVE_LIBPTHREAD 1 + +/* Define to 1 if you have the `rt' library (-lrt). */ +#define HAVE_LIBRT 1 + +/* Define to 1 if your system has a GNU libc compatible `malloc' function, and + to 0 otherwise. */ +#define HAVE_MALLOC 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_MALLOC_H 1 + +/* Define to 1 if you have the `memmove' function. */ +#define HAVE_MEMMOVE 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_MEMORY_H 1 + +/* Define to 1 if you have the `memset' function. */ +#define HAVE_MEMSET 1 + +/* Define to 1 if you have the `mkdir' function. */ +#define HAVE_MKDIR 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_NETDB_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_NETINET_IN_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_PTHREAD_H 1 + +/* Define to 1 if your system has a GNU libc compatible `realloc' function, + and to 0 otherwise. */ +#define HAVE_REALLOC 1 + +/* Define to 1 if you have the `realpath' function. */ +#define HAVE_REALPATH 1 + +/* Define to 1 if you have the `select' function. */ +#define HAVE_SELECT 1 + +/* Define to 1 if you have the `socket' function. */ +#define HAVE_SOCKET 1 + +/* Define to 1 if you have the `sqrt' function. */ +#define HAVE_SQRT 1 + +/* Define to 1 if `stat' has the bug that it succeeds when given the + zero-length file name argument. */ +/* #undef HAVE_STAT_EMPTY_STRING_BUG */ + +/* Define to 1 if stdbool.h conforms to C99. */ +#define HAVE_STDBOOL_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDDEF_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDINT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDLIB_H 1 + +/* Define to 1 if you have the `strchr' function. */ +#define HAVE_STRCHR 1 + +/* Define to 1 if you have the `strdup' function. */ +#define HAVE_STRDUP 1 + +/* Define to 1 if you have the `strerror_r' function. */ +#define HAVE_STRERROR_R 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRINGS_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRING_H 1 + +/* Define to 1 if you have the `strstr' function. */ +#define HAVE_STRSTR 1 + +/* Define to 1 if you have the `strtol' function. */ +#define HAVE_STRTOL 1 + +/* Define to 1 if you have the `strtoul' function. */ +#define HAVE_STRTOUL 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_SELECT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_SOCKET_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_STAT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TIME_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TYPES_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_UNISTD_H 1 + +/* Define to 1 if you have the `vprintf' function. */ +#define HAVE_VPRINTF 1 + +/* define if zlib is available */ +/* #undef HAVE_ZLIB */ + +/* Define to 1 if the system has the type `_Bool'. */ +/* #undef HAVE__BOOL */ + +/* Define to 1 if `lstat' dereferences a symlink specified with a trailing + slash. */ +#define LSTAT_FOLLOWS_SLASHED_SYMLINK 1 + +/* Name of package */ +#define PACKAGE "thrift" + +/* Define to the address where bug reports for this package should be sent. */ +#define PACKAGE_BUGREPORT "" + +/* Define to the full name of this package. */ +#define PACKAGE_NAME "thrift" + +/* Define to the full name and version of this package. */ +#define PACKAGE_STRING "thrift 20070917" + +/* Define to the one symbol short name of this package. */ +#define PACKAGE_TARNAME "thrift" + +/* Define to the version of this package. */ +#define PACKAGE_VERSION "20070917" + +/* Define to the type of arg 1 for `select'. */ +#define SELECT_TYPE_ARG1 int + +/* Define to the type of args 2, 3 and 4 for `select'. */ +#define SELECT_TYPE_ARG234 (fd_set *) + +/* Define to the type of arg 5 for `select'. */ +#define SELECT_TYPE_ARG5 (struct timeval *) + +/* If using the C implementation of alloca, define if you know the + direction of stack growth for your system; otherwise it will be + automatically deduced at run-time. + STACK_DIRECTION > 0 => grows toward higher addresses + STACK_DIRECTION < 0 => grows toward lower addresses + STACK_DIRECTION = 0 => direction of growth unknown */ +/* #undef STACK_DIRECTION */ + +/* Define to 1 if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* Define to 1 if strerror_r returns char *. */ +#define STRERROR_R_CHAR_P 1 + +/* Define to 1 if you can safely include both and . */ +#define TIME_WITH_SYS_TIME 1 + +/* Version number of package */ +#define VERSION "20070917" + +/* Define to 1 if `lex' declares `yytext' as a `char *' by default, not a + `char[]'. */ +#define YYTEXT_POINTER 1 + +/* Define to empty if `const' does not conform to ANSI C. */ +/* #undef const */ + +/* Define to `__inline__' or `__inline' if that's what the C compiler + calls it, or to nothing if 'inline' is not supported under any name. */ +#ifndef __cplusplus +/* #undef inline */ +#endif + +/* Define to rpl_malloc if the replacement function should be used. */ +/* #undef malloc */ + +/* Define to `int' if does not define. */ +/* #undef mode_t */ + +/* Define to `long' if does not define. */ +/* #undef off_t */ + +/* Define to rpl_realloc if the replacement function should be used. */ +/* #undef realloc */ + +/* Define to `unsigned' if does not define. */ +/* #undef size_t */ + +/* Define to empty if the keyword `volatile' does not work. Warning: valid + code using `volatile' can become incorrect without. Disable with care. */ +/* #undef volatile */ Index: service/include/thrift/reflection_limited_types.h =================================================================== --- service/include/thrift/reflection_limited_types.h (revision 0) +++ service/include/thrift/reflection_limited_types.h (revision 0) @@ -0,0 +1,570 @@ +/** + * Autogenerated by Thrift + * + * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING + */ +#ifndef reflection_limited_TYPES_H +#define reflection_limited_TYPES_H + +#include +#include +#include +#include + + + +namespace facebook { namespace thrift { namespace reflection { namespace limited { + +enum TTypeTag { + T_VOID = 1, + T_BOOL = 2, + T_BYTE = 3, + T_I16 = 6, + T_I32 = 8, + T_I64 = 10, + T_DOUBLE = 4, + T_STRING = 11, + T_STRUCT = 12, + T_MAP = 13, + T_SET = 14, + T_LIST = 15, + T_ENUM = 101, + T_NOT_REFLECTED = 102 +}; + +class SimpleType { + public: + + static char* ascii_fingerprint; // = "19B5240589E680301A7E32DF3971EFBE"; + static char binary_fingerprint[16]; // = {0x19,0xB5,0x24,0x05,0x89,0xE6,0x80,0x30,0x1A,0x7E,0x32,0xDF,0x39,0x71,0xEF,0xBE}; + + SimpleType() : name("") { + } + + virtual ~SimpleType() throw() {} + + TTypeTag ttype; + std::string name; + + struct __isset { + __isset() : ttype(false), name(false) {} + bool ttype; + bool name; + } __isset; + + bool operator == (const SimpleType & rhs) const + { + if (!(ttype == rhs.ttype)) + return false; + if (!(name == rhs.name)) + return false; + return true; + } + bool operator != (const SimpleType &rhs) const { + return !(*this == rhs); + } + + uint32_t read(facebook::thrift::protocol::TProtocol* iprot); + uint32_t write(facebook::thrift::protocol::TProtocol* oprot) const; + +}; + +class ContainerType { + public: + + static char* ascii_fingerprint; // = "654FA6EFFF8242F4C2A604B970686634"; + static char binary_fingerprint[16]; // = {0x65,0x4F,0xA6,0xEF,0xFF,0x82,0x42,0xF4,0xC2,0xA6,0x04,0xB9,0x70,0x68,0x66,0x34}; + + ContainerType() { + } + + virtual ~ContainerType() throw() {} + + TTypeTag ttype; + SimpleType subtype1; + SimpleType subtype2; + + struct __isset { + __isset() : ttype(false), subtype1(false), subtype2(false) {} + bool ttype; + bool subtype1; + bool subtype2; + } __isset; + + bool operator == (const ContainerType & rhs) const + { + if (!(ttype == rhs.ttype)) + return false; + if (!(subtype1 == rhs.subtype1)) + return false; + if (__isset.subtype2 != rhs.__isset.subtype2) + return false; + else if (__isset.subtype2 && !(subtype2 == rhs.subtype2)) + return false; + return true; + } + bool operator != (const ContainerType &rhs) const { + return !(*this == rhs); + } + + uint32_t read(facebook::thrift::protocol::TProtocol* iprot); + uint32_t write(facebook::thrift::protocol::TProtocol* oprot) const; + +}; + +class ThriftType { + public: + + static char* ascii_fingerprint; // = "76BC1CC759001D7D85FEE75C4F183062"; + static char binary_fingerprint[16]; // = {0x76,0xBC,0x1C,0xC7,0x59,0x00,0x1D,0x7D,0x85,0xFE,0xE7,0x5C,0x4F,0x18,0x30,0x62}; + + ThriftType() : is_container(0) { + } + + virtual ~ThriftType() throw() {} + + bool is_container; + SimpleType simple_type; + ContainerType container_type; + + struct __isset { + __isset() : is_container(false), simple_type(false), container_type(false) {} + bool is_container; + bool simple_type; + bool container_type; + } __isset; + + bool operator == (const ThriftType & rhs) const + { + if (!(is_container == rhs.is_container)) + return false; + if (__isset.simple_type != rhs.__isset.simple_type) + return false; + else if (__isset.simple_type && !(simple_type == rhs.simple_type)) + return false; + if (__isset.container_type != rhs.__isset.container_type) + return false; + else if (__isset.container_type && !(container_type == rhs.container_type)) + return false; + return true; + } + bool operator != (const ThriftType &rhs) const { + return !(*this == rhs); + } + + uint32_t read(facebook::thrift::protocol::TProtocol* iprot); + uint32_t write(facebook::thrift::protocol::TProtocol* oprot) const; + +}; + +class Argument { + public: + + static char* ascii_fingerprint; // = "8C45506BE0EFBB22FB19FA40DDCECB3F"; + static char binary_fingerprint[16]; // = {0x8C,0x45,0x50,0x6B,0xE0,0xEF,0xBB,0x22,0xFB,0x19,0xFA,0x40,0xDD,0xCE,0xCB,0x3F}; + + Argument() : key(0), name("") { + } + + virtual ~Argument() throw() {} + + int16_t key; + std::string name; + ThriftType type; + + struct __isset { + __isset() : key(false), name(false), type(false) {} + bool key; + bool name; + bool type; + } __isset; + + bool operator == (const Argument & rhs) const + { + if (!(key == rhs.key)) + return false; + if (!(name == rhs.name)) + return false; + if (!(type == rhs.type)) + return false; + return true; + } + bool operator != (const Argument &rhs) const { + return !(*this == rhs); + } + + uint32_t read(facebook::thrift::protocol::TProtocol* iprot); + uint32_t write(facebook::thrift::protocol::TProtocol* oprot) const; + +}; + +class Method { + public: + + static char* ascii_fingerprint; // = "E6573428C492D24C84A19432D39A17B0"; + static char binary_fingerprint[16]; // = {0xE6,0x57,0x34,0x28,0xC4,0x92,0xD2,0x4C,0x84,0xA1,0x94,0x32,0xD3,0x9A,0x17,0xB0}; + + Method() : name("") { + } + + virtual ~Method() throw() {} + + std::string name; + ThriftType return_type; + std::vector arguments; + + struct __isset { + __isset() : name(false), return_type(false), arguments(false) {} + bool name; + bool return_type; + bool arguments; + } __isset; + + bool operator == (const Method & rhs) const + { + if (!(name == rhs.name)) + return false; + if (!(return_type == rhs.return_type)) + return false; + if (!(arguments == rhs.arguments)) + return false; + return true; + } + bool operator != (const Method &rhs) const { + return !(*this == rhs); + } + + uint32_t read(facebook::thrift::protocol::TProtocol* iprot); + uint32_t write(facebook::thrift::protocol::TProtocol* oprot) const; + +}; + +class Service { + public: + + static char* ascii_fingerprint; // = "4673B0777B701D9B02A7A74CEC7908A7"; + static char binary_fingerprint[16]; // = {0x46,0x73,0xB0,0x77,0x7B,0x70,0x1D,0x9B,0x02,0xA7,0xA7,0x4C,0xEC,0x79,0x08,0xA7}; + + Service() : name(""), fully_reflected(0) { + } + + virtual ~Service() throw() {} + + std::string name; + std::vector methods; + bool fully_reflected; + + struct __isset { + __isset() : name(false), methods(false), fully_reflected(false) {} + bool name; + bool methods; + bool fully_reflected; + } __isset; + + bool operator == (const Service & rhs) const + { + if (!(name == rhs.name)) + return false; + if (!(methods == rhs.methods)) + return false; + if (!(fully_reflected == rhs.fully_reflected)) + return false; + return true; + } + bool operator != (const Service &rhs) const { + return !(*this == rhs); + } + + uint32_t read(facebook::thrift::protocol::TProtocol* iprot); + uint32_t write(facebook::thrift::protocol::TProtocol* oprot) const; + +}; + +}}}} // namespace + +#endif +/** + * Autogenerated by Thrift + * + * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING + */ +#ifndef reflection_limited_TYPES_H +#define reflection_limited_TYPES_H + +#include +#include +#include +#include + + + +namespace facebook { namespace thrift { namespace reflection { namespace limited { + +enum TTypeTag { + T_VOID = 1, + T_BOOL = 2, + T_BYTE = 3, + T_I16 = 6, + T_I32 = 8, + T_I64 = 10, + T_DOUBLE = 4, + T_STRING = 11, + T_STRUCT = 12, + T_MAP = 13, + T_SET = 14, + T_LIST = 15, + T_ENUM = 101, + T_NOT_REFLECTED = 102 +}; + +class SimpleType { + public: + + static char* ascii_fingerprint; // = "19B5240589E680301A7E32DF3971EFBE"; + static char binary_fingerprint[16]; // = {0x19,0xB5,0x24,0x05,0x89,0xE6,0x80,0x30,0x1A,0x7E,0x32,0xDF,0x39,0x71,0xEF,0xBE}; + + SimpleType() : name("") { + } + + virtual ~SimpleType() throw() {} + + TTypeTag ttype; + std::string name; + + struct __isset { + __isset() : ttype(false), name(false) {} + bool ttype; + bool name; + } __isset; + + bool operator == (const SimpleType & rhs) const + { + if (!(ttype == rhs.ttype)) + return false; + if (!(name == rhs.name)) + return false; + return true; + } + bool operator != (const SimpleType &rhs) const { + return !(*this == rhs); + } + + uint32_t read(facebook::thrift::protocol::TProtocol* iprot); + uint32_t write(facebook::thrift::protocol::TProtocol* oprot) const; + +}; + +class ContainerType { + public: + + static char* ascii_fingerprint; // = "654FA6EFFF8242F4C2A604B970686634"; + static char binary_fingerprint[16]; // = {0x65,0x4F,0xA6,0xEF,0xFF,0x82,0x42,0xF4,0xC2,0xA6,0x04,0xB9,0x70,0x68,0x66,0x34}; + + ContainerType() { + } + + virtual ~ContainerType() throw() {} + + TTypeTag ttype; + SimpleType subtype1; + SimpleType subtype2; + + struct __isset { + __isset() : ttype(false), subtype1(false), subtype2(false) {} + bool ttype; + bool subtype1; + bool subtype2; + } __isset; + + bool operator == (const ContainerType & rhs) const + { + if (!(ttype == rhs.ttype)) + return false; + if (!(subtype1 == rhs.subtype1)) + return false; + if (__isset.subtype2 != rhs.__isset.subtype2) + return false; + else if (__isset.subtype2 && !(subtype2 == rhs.subtype2)) + return false; + return true; + } + bool operator != (const ContainerType &rhs) const { + return !(*this == rhs); + } + + uint32_t read(facebook::thrift::protocol::TProtocol* iprot); + uint32_t write(facebook::thrift::protocol::TProtocol* oprot) const; + +}; + +class ThriftType { + public: + + static char* ascii_fingerprint; // = "76BC1CC759001D7D85FEE75C4F183062"; + static char binary_fingerprint[16]; // = {0x76,0xBC,0x1C,0xC7,0x59,0x00,0x1D,0x7D,0x85,0xFE,0xE7,0x5C,0x4F,0x18,0x30,0x62}; + + ThriftType() : is_container(0) { + } + + virtual ~ThriftType() throw() {} + + bool is_container; + SimpleType simple_type; + ContainerType container_type; + + struct __isset { + __isset() : is_container(false), simple_type(false), container_type(false) {} + bool is_container; + bool simple_type; + bool container_type; + } __isset; + + bool operator == (const ThriftType & rhs) const + { + if (!(is_container == rhs.is_container)) + return false; + if (__isset.simple_type != rhs.__isset.simple_type) + return false; + else if (__isset.simple_type && !(simple_type == rhs.simple_type)) + return false; + if (__isset.container_type != rhs.__isset.container_type) + return false; + else if (__isset.container_type && !(container_type == rhs.container_type)) + return false; + return true; + } + bool operator != (const ThriftType &rhs) const { + return !(*this == rhs); + } + + uint32_t read(facebook::thrift::protocol::TProtocol* iprot); + uint32_t write(facebook::thrift::protocol::TProtocol* oprot) const; + +}; + +class Argument { + public: + + static char* ascii_fingerprint; // = "8C45506BE0EFBB22FB19FA40DDCECB3F"; + static char binary_fingerprint[16]; // = {0x8C,0x45,0x50,0x6B,0xE0,0xEF,0xBB,0x22,0xFB,0x19,0xFA,0x40,0xDD,0xCE,0xCB,0x3F}; + + Argument() : key(0), name("") { + } + + virtual ~Argument() throw() {} + + int16_t key; + std::string name; + ThriftType type; + + struct __isset { + __isset() : key(false), name(false), type(false) {} + bool key; + bool name; + bool type; + } __isset; + + bool operator == (const Argument & rhs) const + { + if (!(key == rhs.key)) + return false; + if (!(name == rhs.name)) + return false; + if (!(type == rhs.type)) + return false; + return true; + } + bool operator != (const Argument &rhs) const { + return !(*this == rhs); + } + + uint32_t read(facebook::thrift::protocol::TProtocol* iprot); + uint32_t write(facebook::thrift::protocol::TProtocol* oprot) const; + +}; + +class Method { + public: + + static char* ascii_fingerprint; // = "E6573428C492D24C84A19432D39A17B0"; + static char binary_fingerprint[16]; // = {0xE6,0x57,0x34,0x28,0xC4,0x92,0xD2,0x4C,0x84,0xA1,0x94,0x32,0xD3,0x9A,0x17,0xB0}; + + Method() : name("") { + } + + virtual ~Method() throw() {} + + std::string name; + ThriftType return_type; + std::vector arguments; + + struct __isset { + __isset() : name(false), return_type(false), arguments(false) {} + bool name; + bool return_type; + bool arguments; + } __isset; + + bool operator == (const Method & rhs) const + { + if (!(name == rhs.name)) + return false; + if (!(return_type == rhs.return_type)) + return false; + if (!(arguments == rhs.arguments)) + return false; + return true; + } + bool operator != (const Method &rhs) const { + return !(*this == rhs); + } + + uint32_t read(facebook::thrift::protocol::TProtocol* iprot); + uint32_t write(facebook::thrift::protocol::TProtocol* oprot) const; + +}; + +class Service { + public: + + static char* ascii_fingerprint; // = "4673B0777B701D9B02A7A74CEC7908A7"; + static char binary_fingerprint[16]; // = {0x46,0x73,0xB0,0x77,0x7B,0x70,0x1D,0x9B,0x02,0xA7,0xA7,0x4C,0xEC,0x79,0x08,0xA7}; + + Service() : name(""), fully_reflected(0) { + } + + virtual ~Service() throw() {} + + std::string name; + std::vector methods; + bool fully_reflected; + + struct __isset { + __isset() : name(false), methods(false), fully_reflected(false) {} + bool name; + bool methods; + bool fully_reflected; + } __isset; + + bool operator == (const Service & rhs) const + { + if (!(name == rhs.name)) + return false; + if (!(methods == rhs.methods)) + return false; + if (!(fully_reflected == rhs.fully_reflected)) + return false; + return true; + } + bool operator != (const Service &rhs) const { + return !(*this == rhs); + } + + uint32_t read(facebook::thrift::protocol::TProtocol* iprot); + uint32_t write(facebook::thrift::protocol::TProtocol* oprot) const; + +}; + +}}}} // namespace + +#endif Index: service/include/thrift/transport/TSocket.h =================================================================== --- service/include/thrift/transport/TSocket.h (revision 0) +++ service/include/thrift/transport/TSocket.h (revision 0) @@ -0,0 +1,464 @@ +// Copyright (c) 2006- Facebook +// Distributed under the Thrift Software License +// +// See accompanying file LICENSE or visit the Thrift site at: +// http://developers.facebook.com/thrift/ + +#ifndef _THRIFT_TRANSPORT_TSOCKET_H_ +#define _THRIFT_TRANSPORT_TSOCKET_H_ 1 + +#include +#include + +#include "TTransport.h" +#include "TServerSocket.h" + +namespace facebook { namespace thrift { namespace transport { + +/** + * TCP Socket implementation of the TTransport interface. + * + * @author Mark Slee + * @author Aditya Agarwal + */ +class TSocket : public TTransport { + /** + * We allow the TServerSocket acceptImpl() method to access the private + * members of a socket so that it can access the TSocket(int socket) + * constructor which creates a socket object from the raw UNIX socket + * handle. + */ + friend class TServerSocket; + + public: + /** + * Constructs a new socket. Note that this does NOT actually connect the + * socket. + * + */ + TSocket(); + + /** + * Constructs a new socket. Note that this does NOT actually connect the + * socket. + * + * @param host An IP address or hostname to connect to + * @param port The port to connect on + */ + TSocket(std::string host, int port); + + /** + * Destroyes the socket object, closing it if necessary. + */ + virtual ~TSocket(); + + /** + * Whether the socket is alive. + * + * @return Is the socket alive? + */ + bool isOpen(); + + /** + * Calls select on the socket to see if there is more data available. + */ + bool peek(); + + /** + * Creates and opens the UNIX socket. + * + * @throws TTransportException If the socket could not connect + */ + virtual void open(); + + /** + * Shuts down communications on the socket. + */ + void close(); + + /** + * Reads from the underlying socket. + */ + uint32_t read(uint8_t* buf, uint32_t len); + + /** + * Writes to the underlying socket. + */ + void write(const uint8_t* buf, uint32_t len); + + /** + * Get the host that the socket is connected to + * + * @return string host identifier + */ + std::string getHost(); + + /** + * Get the port that the socket is connected to + * + * @return int port number + */ + int getPort(); + + /** + * Set the host that socket will connect to + * + * @param host host identifier + */ + void setHost(std::string host); + + /** + * Set the port that socket will connect to + * + * @param port port number + */ + void setPort(int port); + + /** + * Controls whether the linger option is set on the socket. + * + * @param on Whether SO_LINGER is on + * @param linger If linger is active, the number of seconds to linger for + */ + void setLinger(bool on, int linger); + + /** + * Whether to enable/disable Nagle's algorithm. + * + * @param noDelay Whether or not to disable the algorithm. + * @return + */ + void setNoDelay(bool noDelay); + + /** + * Set the connect timeout + */ + void setConnTimeout(int ms); + + /** + * Set the receive timeout + */ + void setRecvTimeout(int ms); + + /** + * Set the send timeout + */ + void setSendTimeout(int ms); + + /** + * Set the max number of recv retries in case of an EAGAIN + * error + */ + void setMaxRecvRetries(int maxRecvRetries); + + /** + * Get socket information formated as a string + */ + std::string getSocketInfo(); + + /** + * Returns the DNS name of the host to which the socket is connected + */ + std::string getPeerHost(); + + /** + * Returns the address of the host to which the socket is connected + */ + std::string getPeerAddress(); + + /** + * Returns the port of the host to which the socket is connected + **/ + int getPeerPort(); + + + protected: + /** + * Constructor to create socket from raw UNIX handle. Never called directly + * but used by the TServerSocket class. + */ + TSocket(int socket); + + /** connect, called by open */ + void openConnection(struct addrinfo *res); + + /** Host to connect to */ + std::string host_; + + /** Peer hostname */ + std::string peerHost_; + + /** Peer address */ + std::string peerAddress_; + + /** Peer port */ + int peerPort_; + + /** Port number to connect on */ + int port_; + + /** Underlying UNIX socket handle */ + int socket_; + + /** Connect timeout in ms */ + int connTimeout_; + + /** Send timeout in ms */ + int sendTimeout_; + + /** Recv timeout in ms */ + int recvTimeout_; + + /** Linger on */ + bool lingerOn_; + + /** Linger val */ + int lingerVal_; + + /** Nodelay */ + bool noDelay_; + + /** Recv EGAIN retries */ + int maxRecvRetries_; + + /** Recv timeout timeval */ + struct timeval recvTimeval_; + +}; + +}}} // facebook::thrift::transport + +#endif // #ifndef _THRIFT_TRANSPORT_TSOCKET_H_ + +// Copyright (c) 2006- Facebook +// Distributed under the Thrift Software License +// +// See accompanying file LICENSE or visit the Thrift site at: +// http://developers.facebook.com/thrift/ + +#ifndef _THRIFT_TRANSPORT_TSOCKET_H_ +#define _THRIFT_TRANSPORT_TSOCKET_H_ 1 + +#include +#include + +#include "TTransport.h" +#include "TServerSocket.h" + +namespace facebook { namespace thrift { namespace transport { + +/** + * TCP Socket implementation of the TTransport interface. + * + * @author Mark Slee + * @author Aditya Agarwal + */ +class TSocket : public TTransport { + /** + * We allow the TServerSocket acceptImpl() method to access the private + * members of a socket so that it can access the TSocket(int socket) + * constructor which creates a socket object from the raw UNIX socket + * handle. + */ + friend class TServerSocket; + + public: + /** + * Constructs a new socket. Note that this does NOT actually connect the + * socket. + * + */ + TSocket(); + + /** + * Constructs a new socket. Note that this does NOT actually connect the + * socket. + * + * @param host An IP address or hostname to connect to + * @param port The port to connect on + */ + TSocket(std::string host, int port); + + /** + * Destroyes the socket object, closing it if necessary. + */ + virtual ~TSocket(); + + /** + * Whether the socket is alive. + * + * @return Is the socket alive? + */ + bool isOpen(); + + /** + * Calls select on the socket to see if there is more data available. + */ + bool peek(); + + /** + * Creates and opens the UNIX socket. + * + * @throws TTransportException If the socket could not connect + */ + virtual void open(); + + /** + * Shuts down communications on the socket. + */ + void close(); + + /** + * Reads from the underlying socket. + */ + uint32_t read(uint8_t* buf, uint32_t len); + + /** + * Writes to the underlying socket. + */ + void write(const uint8_t* buf, uint32_t len); + + /** + * Get the host that the socket is connected to + * + * @return string host identifier + */ + std::string getHost(); + + /** + * Get the port that the socket is connected to + * + * @return int port number + */ + int getPort(); + + /** + * Set the host that socket will connect to + * + * @param host host identifier + */ + void setHost(std::string host); + + /** + * Set the port that socket will connect to + * + * @param port port number + */ + void setPort(int port); + + /** + * Controls whether the linger option is set on the socket. + * + * @param on Whether SO_LINGER is on + * @param linger If linger is active, the number of seconds to linger for + */ + void setLinger(bool on, int linger); + + /** + * Whether to enable/disable Nagle's algorithm. + * + * @param noDelay Whether or not to disable the algorithm. + * @return + */ + void setNoDelay(bool noDelay); + + /** + * Set the connect timeout + */ + void setConnTimeout(int ms); + + /** + * Set the receive timeout + */ + void setRecvTimeout(int ms); + + /** + * Set the send timeout + */ + void setSendTimeout(int ms); + + /** + * Set the max number of recv retries in case of an EAGAIN + * error + */ + void setMaxRecvRetries(int maxRecvRetries); + + /** + * Get socket information formated as a string + */ + std::string getSocketInfo(); + + /** + * Returns the DNS name of the host to which the socket is connected + */ + std::string getPeerHost(); + + /** + * Returns the address of the host to which the socket is connected + */ + std::string getPeerAddress(); + + /** + * Returns the port of the host to which the socket is connected + **/ + int getPeerPort(); + + + protected: + /** + * Constructor to create socket from raw UNIX handle. Never called directly + * but used by the TServerSocket class. + */ + TSocket(int socket); + + /** connect, called by open */ + void openConnection(struct addrinfo *res); + + /** Host to connect to */ + std::string host_; + + /** Peer hostname */ + std::string peerHost_; + + /** Peer address */ + std::string peerAddress_; + + /** Peer port */ + int peerPort_; + + /** Port number to connect on */ + int port_; + + /** Underlying UNIX socket handle */ + int socket_; + + /** Connect timeout in ms */ + int connTimeout_; + + /** Send timeout in ms */ + int sendTimeout_; + + /** Recv timeout in ms */ + int recvTimeout_; + + /** Linger on */ + bool lingerOn_; + + /** Linger val */ + int lingerVal_; + + /** Nodelay */ + bool noDelay_; + + /** Recv EGAIN retries */ + int maxRecvRetries_; + + /** Recv timeout timeval */ + struct timeval recvTimeval_; + +}; + +}}} // facebook::thrift::transport + +#endif // #ifndef _THRIFT_TRANSPORT_TSOCKET_H_ + Index: service/include/thrift/transport/TTransportException.h =================================================================== --- service/include/thrift/transport/TTransportException.h (revision 0) +++ service/include/thrift/transport/TTransportException.h (revision 0) @@ -0,0 +1,212 @@ +// Copyright (c) 2006- Facebook +// Distributed under the Thrift Software License +// +// See accompanying file LICENSE or visit the Thrift site at: +// http://developers.facebook.com/thrift/ + +#ifndef _THRIFT_TRANSPORT_TTRANSPORTEXCEPTION_H_ +#define _THRIFT_TRANSPORT_TTRANSPORTEXCEPTION_H_ 1 + +#include +#include +#include + +namespace facebook { namespace thrift { namespace transport { + +/** + * Class to encapsulate all the possible types of transport errors that may + * occur in various transport systems. This provides a sort of generic + * wrapper around the shitty UNIX E_ error codes that lets a common code + * base of error handling to be used for various types of transports, i.e. + * pipes etc. + * + * @author Mark Slee + */ +class TTransportException : public facebook::thrift::TException { + public: + /** + * Error codes for the various types of exceptions. + */ + enum TTransportExceptionType { + UNKNOWN = 0, + NOT_OPEN = 1, + ALREADY_OPEN = 2, + TIMED_OUT = 3, + END_OF_FILE = 4, + INTERRUPTED = 5, + BAD_ARGS = 6, + CORRUPTED_DATA = 7, + INTERNAL_ERROR = 8, + }; + + TTransportException() : + facebook::thrift::TException(), + type_(UNKNOWN) {} + + TTransportException(TTransportExceptionType type) : + facebook::thrift::TException(), + type_(type) {} + + TTransportException(const std::string& message) : + facebook::thrift::TException(message), + type_(UNKNOWN) {} + + TTransportException(TTransportExceptionType type, const std::string& message) : + facebook::thrift::TException(message), + type_(type) {} + + TTransportException(TTransportExceptionType type, + const std::string& message, + int errno_copy) : + facebook::thrift::TException(message + ": " + strerror_s(errno_copy)), + type_(type) {} + + virtual ~TTransportException() throw() {} + + /** + * Returns an error code that provides information about the type of error + * that has occurred. + * + * @return Error code + */ + TTransportExceptionType getType() const throw() { + return type_; + } + + virtual const char* what() const throw() { + if (message_.empty()) { + switch (type_) { + case UNKNOWN : return "TTransportException: Unknown transport exception"; + case NOT_OPEN : return "TTransportException: Transport not open"; + case ALREADY_OPEN : return "TTransportException: Transport already open"; + case TIMED_OUT : return "TTransportException: Timed out"; + case END_OF_FILE : return "TTransportException: End of file"; + case INTERRUPTED : return "TTransportException: Interrupted"; + case BAD_ARGS : return "TTransportException: Invalid arguments"; + case CORRUPTED_DATA : return "TTransportException: Corrupted Data"; + case INTERNAL_ERROR : return "TTransportException: Internal error"; + default : return "TTransportException: (Invalid exception type)"; + } + } else { + return message_.c_str(); + } + } + + protected: + /** Just like strerror_r but returns a C++ string object. */ + std::string strerror_s(int errno_copy); + + /** Error code */ + TTransportExceptionType type_; + +}; + +}}} // facebook::thrift::transport + +#endif // #ifndef _THRIFT_TRANSPORT_TTRANSPORTEXCEPTION_H_ +// Copyright (c) 2006- Facebook +// Distributed under the Thrift Software License +// +// See accompanying file LICENSE or visit the Thrift site at: +// http://developers.facebook.com/thrift/ + +#ifndef _THRIFT_TRANSPORT_TTRANSPORTEXCEPTION_H_ +#define _THRIFT_TRANSPORT_TTRANSPORTEXCEPTION_H_ 1 + +#include +#include +#include + +namespace facebook { namespace thrift { namespace transport { + +/** + * Class to encapsulate all the possible types of transport errors that may + * occur in various transport systems. This provides a sort of generic + * wrapper around the shitty UNIX E_ error codes that lets a common code + * base of error handling to be used for various types of transports, i.e. + * pipes etc. + * + * @author Mark Slee + */ +class TTransportException : public facebook::thrift::TException { + public: + /** + * Error codes for the various types of exceptions. + */ + enum TTransportExceptionType { + UNKNOWN = 0, + NOT_OPEN = 1, + ALREADY_OPEN = 2, + TIMED_OUT = 3, + END_OF_FILE = 4, + INTERRUPTED = 5, + BAD_ARGS = 6, + CORRUPTED_DATA = 7, + INTERNAL_ERROR = 8, + }; + + TTransportException() : + facebook::thrift::TException(), + type_(UNKNOWN) {} + + TTransportException(TTransportExceptionType type) : + facebook::thrift::TException(), + type_(type) {} + + TTransportException(const std::string& message) : + facebook::thrift::TException(message), + type_(UNKNOWN) {} + + TTransportException(TTransportExceptionType type, const std::string& message) : + facebook::thrift::TException(message), + type_(type) {} + + TTransportException(TTransportExceptionType type, + const std::string& message, + int errno_copy) : + facebook::thrift::TException(message + ": " + strerror_s(errno_copy)), + type_(type) {} + + virtual ~TTransportException() throw() {} + + /** + * Returns an error code that provides information about the type of error + * that has occurred. + * + * @return Error code + */ + TTransportExceptionType getType() const throw() { + return type_; + } + + virtual const char* what() const throw() { + if (message_.empty()) { + switch (type_) { + case UNKNOWN : return "TTransportException: Unknown transport exception"; + case NOT_OPEN : return "TTransportException: Transport not open"; + case ALREADY_OPEN : return "TTransportException: Transport already open"; + case TIMED_OUT : return "TTransportException: Timed out"; + case END_OF_FILE : return "TTransportException: End of file"; + case INTERRUPTED : return "TTransportException: Interrupted"; + case BAD_ARGS : return "TTransportException: Invalid arguments"; + case CORRUPTED_DATA : return "TTransportException: Corrupted Data"; + case INTERNAL_ERROR : return "TTransportException: Internal error"; + default : return "TTransportException: (Invalid exception type)"; + } + } else { + return message_.c_str(); + } + } + + protected: + /** Just like strerror_r but returns a C++ string object. */ + std::string strerror_s(int errno_copy); + + /** Error code */ + TTransportExceptionType type_; + +}; + +}}} // facebook::thrift::transport + +#endif // #ifndef _THRIFT_TRANSPORT_TTRANSPORTEXCEPTION_H_ Index: service/include/thrift/transport/TFileTransport.h =================================================================== --- service/include/thrift/transport/TFileTransport.h (revision 0) +++ service/include/thrift/transport/TFileTransport.h (revision 0) @@ -0,0 +1,858 @@ +// Copyright (c) 2006- Facebook +// Distributed under the Thrift Software License +// +// See accompanying file LICENSE or visit the Thrift site at: +// http://developers.facebook.com/thrift/ + +#ifndef _THRIFT_TRANSPORT_TFILETRANSPORT_H_ +#define _THRIFT_TRANSPORT_TFILETRANSPORT_H_ 1 + +#include "TTransport.h" +#include "Thrift.h" +#include "TProcessor.h" + +#include +#include + +#include + +namespace facebook { namespace thrift { namespace transport { + +using facebook::thrift::TProcessor; +using facebook::thrift::protocol::TProtocolFactory; + +// Data pertaining to a single event +typedef struct eventInfo { + uint8_t* eventBuff_; + uint32_t eventSize_; + uint32_t eventBuffPos_; + + eventInfo():eventBuff_(NULL), eventSize_(0), eventBuffPos_(0){}; + ~eventInfo() { + if (eventBuff_) { + delete[] eventBuff_; + } + } +} eventInfo; + +// information about current read state +typedef struct readState { + eventInfo* event_; + + // keep track of event size + uint8_t eventSizeBuff_[4]; + uint8_t eventSizeBuffPos_; + bool readingSize_; + + // read buffer variables + int32_t bufferPtr_; + int32_t bufferLen_; + + // last successful dispatch point + int32_t lastDispatchPtr_; + + void resetState(uint32_t lastDispatchPtr) { + readingSize_ = true; + eventSizeBuffPos_ = 0; + lastDispatchPtr_ = lastDispatchPtr; + } + + void resetAllValues() { + resetState(0); + bufferPtr_ = 0; + bufferLen_ = 0; + if (event_) { + delete(event_); + } + event_ = 0; + } + + readState() { + event_ = 0; + resetAllValues(); + } + + ~readState() { + if (event_) { + delete(event_); + } + } + +} readState; + +/** + * TFileTransportBuffer - buffer class used by TFileTransport for queueing up events + * to be written to disk. Should be used in the following way: + * 1) Buffer created + * 2) Buffer written to (addEvent) + * 3) Buffer read from (getNext) + * 4) Buffer reset (reset) + * 5) Go back to 2, or destroy buffer + * + * The buffer should never be written to after it is read from, unless it is reset first. + * Note: The above rules are enforced mainly for debugging its sole client TFileTransport + * which uses the buffer in this way. + * + * @author James Wang + */ +class TFileTransportBuffer { + public: + TFileTransportBuffer(uint32_t size); + ~TFileTransportBuffer(); + + bool addEvent(eventInfo *event); + eventInfo* getNext(); + void reset(); + bool isFull(); + bool isEmpty(); + + private: + TFileTransportBuffer(); // should not be used + + enum mode { + WRITE, + READ + }; + mode bufferMode_; + + uint32_t writePoint_; + uint32_t readPoint_; + uint32_t size_; + eventInfo** buffer_; +}; + +/** + * Abstract interface for transports used to read files + */ +class TFileReaderTransport : virtual public TTransport { + public: + virtual int32_t getReadTimeout() = 0; + virtual void setReadTimeout(int32_t readTimeout) = 0; + + virtual uint32_t getNumChunks() = 0; + virtual uint32_t getCurChunk() = 0; + virtual void seekToChunk(int32_t chunk) = 0; + virtual void seekToEnd() = 0; +}; + +/** + * Abstract interface for transports used to write files + */ +class TFileWriterTransport : virtual public TTransport { + public: + virtual uint32_t getChunkSize() = 0; + virtual void setChunkSize(uint32_t chunkSize) = 0; +}; + +/** + * File implementation of a transport. Reads and writes are done to a + * file on disk. + * + * @author Aditya Agarwal + */ +class TFileTransport : public TFileReaderTransport, + public TFileWriterTransport { + public: + TFileTransport(std::string path, bool readOnly=false); + ~TFileTransport(); + + // TODO: what is the correct behaviour for this? + // the log file is generally always open + bool isOpen() { + return true; + } + + void write(const uint8_t* buf, uint32_t len); + void flush(); + + uint32_t readAll(uint8_t* buf, uint32_t len); + uint32_t read(uint8_t* buf, uint32_t len); + + // log-file specific functions + void seekToChunk(int32_t chunk); + void seekToEnd(); + uint32_t getNumChunks(); + uint32_t getCurChunk(); + + // for changing the output file + void resetOutputFile(int fd, std::string filename, int64_t offset); + + // Setter/Getter functions for user-controllable options + void setReadBuffSize(uint32_t readBuffSize) { + if (readBuffSize) { + readBuffSize_ = readBuffSize; + } + } + uint32_t getReadBuffSize() { + return readBuffSize_; + } + + static const int32_t TAIL_READ_TIMEOUT = -1; + static const int32_t NO_TAIL_READ_TIMEOUT = 0; + void setReadTimeout(int32_t readTimeout) { + readTimeout_ = readTimeout; + } + int32_t getReadTimeout() { + return readTimeout_; + } + + void setChunkSize(uint32_t chunkSize) { + if (chunkSize) { + chunkSize_ = chunkSize; + } + } + uint32_t getChunkSize() { + return chunkSize_; + } + + void setEventBufferSize(uint32_t bufferSize) { + if (bufferAndThreadInitialized_) { + GlobalOutput("Cannot change the buffer size after writer thread started"); + return; + } + eventBufferSize_ = bufferSize; + } + + uint32_t getEventBufferSize() { + return eventBufferSize_; + } + + void setFlushMaxUs(uint32_t flushMaxUs) { + if (flushMaxUs) { + flushMaxUs_ = flushMaxUs; + } + } + uint32_t getFlushMaxUs() { + return flushMaxUs_; + } + + void setFlushMaxBytes(uint32_t flushMaxBytes) { + if (flushMaxBytes) { + flushMaxBytes_ = flushMaxBytes; + } + } + uint32_t getFlushMaxBytes() { + return flushMaxBytes_; + } + + void setMaxEventSize(uint32_t maxEventSize) { + maxEventSize_ = maxEventSize; + } + uint32_t getMaxEventSize() { + return maxEventSize_; + } + + void setMaxCorruptedEvents(uint32_t maxCorruptedEvents) { + maxCorruptedEvents_ = maxCorruptedEvents; + } + uint32_t getMaxCorruptedEvents() { + return maxCorruptedEvents_; + } + + void setEofSleepTimeUs(uint32_t eofSleepTime) { + if (eofSleepTime) { + eofSleepTime_ = eofSleepTime; + } + } + uint32_t getEofSleepTimeUs() { + return eofSleepTime_; + } + + private: + // helper functions for writing to a file + void enqueueEvent(const uint8_t* buf, uint32_t eventLen, bool blockUntilFlush); + bool swapEventBuffers(struct timespec* deadline); + bool initBufferAndWriteThread(); + + // control for writer thread + static void* startWriterThread(void* ptr) { + (((TFileTransport*)ptr)->writerThread()); + return 0; + } + void writerThread(); + + // helper functions for reading from a file + eventInfo* readEvent(); + + // event corruption-related functions + bool isEventCorrupted(); + void performRecovery(); + + // Utility functions + void openLogFile(); + void getNextFlushTime(struct timespec* ts_next_flush); + + // Class variables + readState readState_; + uint8_t* readBuff_; + eventInfo* currentEvent_; + + uint32_t readBuffSize_; + static const uint32_t DEFAULT_READ_BUFF_SIZE = 1 * 1024 * 1024; + + int32_t readTimeout_; + static const int32_t DEFAULT_READ_TIMEOUT_MS = 200; + + // size of chunks that file will be split up into + uint32_t chunkSize_; + static const uint32_t DEFAULT_CHUNK_SIZE = 16 * 1024 * 1024; + + // size of event buffers + uint32_t eventBufferSize_; + static const uint32_t DEFAULT_EVENT_BUFFER_SIZE = 10000; + + // max number of microseconds that can pass without flushing + uint32_t flushMaxUs_; + static const uint32_t DEFAULT_FLUSH_MAX_US = 3000000; + + // max number of bytes that can be written without flushing + uint32_t flushMaxBytes_; + static const uint32_t DEFAULT_FLUSH_MAX_BYTES = 1000 * 1024; + + // max event size + uint32_t maxEventSize_; + static const uint32_t DEFAULT_MAX_EVENT_SIZE = 0; + + // max number of corrupted events per chunk + uint32_t maxCorruptedEvents_; + static const uint32_t DEFAULT_MAX_CORRUPTED_EVENTS = 0; + + // sleep duration when EOF is hit + uint32_t eofSleepTime_; + static const uint32_t DEFAULT_EOF_SLEEP_TIME_US = 500 * 1000; + + // sleep duration when a corrupted event is encountered + uint32_t corruptedEventSleepTime_; + static const uint32_t DEFAULT_CORRUPTED_SLEEP_TIME_US = 1 * 1000 * 1000; + + // writer thread id + pthread_t writerThreadId_; + + // buffers to hold data before it is flushed. Each element of the buffer stores a msg that + // needs to be written to the file. The buffers are swapped by the writer thread. + TFileTransportBuffer *dequeueBuffer_; + TFileTransportBuffer *enqueueBuffer_; + + // conditions used to block when the buffer is full or empty + pthread_cond_t notFull_, notEmpty_; + volatile bool closing_; + + // To keep track of whether the buffer has been flushed + pthread_cond_t flushed_; + volatile bool forceFlush_; + + // Mutex that is grabbed when enqueueing and swapping the read/write buffers + pthread_mutex_t mutex_; + + // File information + std::string filename_; + int fd_; + + // Whether the writer thread and buffers have been initialized + bool bufferAndThreadInitialized_; + + // Offset within the file + off_t offset_; + + // event corruption information + uint32_t lastBadChunk_; + uint32_t numCorruptedEventsInChunk_; + + bool readOnly_; +}; + +// Exception thrown when EOF is hit +class TEOFException : public TTransportException { + public: + TEOFException(): + TTransportException(TTransportException::END_OF_FILE) {}; +}; + + +// wrapper class to process events from a file containing thrift events +class TFileProcessor { + public: + /** + * Constructor that defaults output transport to null transport + * + * @param processor processes log-file events + * @param protocolFactory protocol factory + * @param inputTransport file transport + */ + TFileProcessor(boost::shared_ptr processor, + boost::shared_ptr protocolFactory, + boost::shared_ptr inputTransport); + + TFileProcessor(boost::shared_ptr processor, + boost::shared_ptr inputProtocolFactory, + boost::shared_ptr outputProtocolFactory, + boost::shared_ptr inputTransport); + + /** + * Constructor + * + * @param processor processes log-file events + * @param protocolFactory protocol factory + * @param inputTransport input file transport + * @param output output transport + */ + TFileProcessor(boost::shared_ptr processor, + boost::shared_ptr protocolFactory, + boost::shared_ptr inputTransport, + boost::shared_ptr outputTransport); + + /** + * processes events from the file + * + * @param numEvents number of events to process (0 for unlimited) + * @param tail tails the file if true + */ + void process(uint32_t numEvents, bool tail); + + /** + * process events until the end of the chunk + * + */ + void processChunk(); + + private: + boost::shared_ptr processor_; + boost::shared_ptr inputProtocolFactory_; + boost::shared_ptr outputProtocolFactory_; + boost::shared_ptr inputTransport_; + boost::shared_ptr outputTransport_; +}; + + +}}} // facebook::thrift::transport + +#endif // _THRIFT_TRANSPORT_TFILETRANSPORT_H_ +// Copyright (c) 2006- Facebook +// Distributed under the Thrift Software License +// +// See accompanying file LICENSE or visit the Thrift site at: +// http://developers.facebook.com/thrift/ + +#ifndef _THRIFT_TRANSPORT_TFILETRANSPORT_H_ +#define _THRIFT_TRANSPORT_TFILETRANSPORT_H_ 1 + +#include "TTransport.h" +#include "Thrift.h" +#include "TProcessor.h" + +#include +#include + +#include + +namespace facebook { namespace thrift { namespace transport { + +using facebook::thrift::TProcessor; +using facebook::thrift::protocol::TProtocolFactory; + +// Data pertaining to a single event +typedef struct eventInfo { + uint8_t* eventBuff_; + uint32_t eventSize_; + uint32_t eventBuffPos_; + + eventInfo():eventBuff_(NULL), eventSize_(0), eventBuffPos_(0){}; + ~eventInfo() { + if (eventBuff_) { + delete[] eventBuff_; + } + } +} eventInfo; + +// information about current read state +typedef struct readState { + eventInfo* event_; + + // keep track of event size + uint8_t eventSizeBuff_[4]; + uint8_t eventSizeBuffPos_; + bool readingSize_; + + // read buffer variables + int32_t bufferPtr_; + int32_t bufferLen_; + + // last successful dispatch point + int32_t lastDispatchPtr_; + + void resetState(uint32_t lastDispatchPtr) { + readingSize_ = true; + eventSizeBuffPos_ = 0; + lastDispatchPtr_ = lastDispatchPtr; + } + + void resetAllValues() { + resetState(0); + bufferPtr_ = 0; + bufferLen_ = 0; + if (event_) { + delete(event_); + } + event_ = 0; + } + + readState() { + event_ = 0; + resetAllValues(); + } + + ~readState() { + if (event_) { + delete(event_); + } + } + +} readState; + +/** + * TFileTransportBuffer - buffer class used by TFileTransport for queueing up events + * to be written to disk. Should be used in the following way: + * 1) Buffer created + * 2) Buffer written to (addEvent) + * 3) Buffer read from (getNext) + * 4) Buffer reset (reset) + * 5) Go back to 2, or destroy buffer + * + * The buffer should never be written to after it is read from, unless it is reset first. + * Note: The above rules are enforced mainly for debugging its sole client TFileTransport + * which uses the buffer in this way. + * + * @author James Wang + */ +class TFileTransportBuffer { + public: + TFileTransportBuffer(uint32_t size); + ~TFileTransportBuffer(); + + bool addEvent(eventInfo *event); + eventInfo* getNext(); + void reset(); + bool isFull(); + bool isEmpty(); + + private: + TFileTransportBuffer(); // should not be used + + enum mode { + WRITE, + READ + }; + mode bufferMode_; + + uint32_t writePoint_; + uint32_t readPoint_; + uint32_t size_; + eventInfo** buffer_; +}; + +/** + * Abstract interface for transports used to read files + */ +class TFileReaderTransport : virtual public TTransport { + public: + virtual int32_t getReadTimeout() = 0; + virtual void setReadTimeout(int32_t readTimeout) = 0; + + virtual uint32_t getNumChunks() = 0; + virtual uint32_t getCurChunk() = 0; + virtual void seekToChunk(int32_t chunk) = 0; + virtual void seekToEnd() = 0; +}; + +/** + * Abstract interface for transports used to write files + */ +class TFileWriterTransport : virtual public TTransport { + public: + virtual uint32_t getChunkSize() = 0; + virtual void setChunkSize(uint32_t chunkSize) = 0; +}; + +/** + * File implementation of a transport. Reads and writes are done to a + * file on disk. + * + * @author Aditya Agarwal + */ +class TFileTransport : public TFileReaderTransport, + public TFileWriterTransport { + public: + TFileTransport(std::string path, bool readOnly=false); + ~TFileTransport(); + + // TODO: what is the correct behaviour for this? + // the log file is generally always open + bool isOpen() { + return true; + } + + void write(const uint8_t* buf, uint32_t len); + void flush(); + + uint32_t readAll(uint8_t* buf, uint32_t len); + uint32_t read(uint8_t* buf, uint32_t len); + + // log-file specific functions + void seekToChunk(int32_t chunk); + void seekToEnd(); + uint32_t getNumChunks(); + uint32_t getCurChunk(); + + // for changing the output file + void resetOutputFile(int fd, std::string filename, int64_t offset); + + // Setter/Getter functions for user-controllable options + void setReadBuffSize(uint32_t readBuffSize) { + if (readBuffSize) { + readBuffSize_ = readBuffSize; + } + } + uint32_t getReadBuffSize() { + return readBuffSize_; + } + + static const int32_t TAIL_READ_TIMEOUT = -1; + static const int32_t NO_TAIL_READ_TIMEOUT = 0; + void setReadTimeout(int32_t readTimeout) { + readTimeout_ = readTimeout; + } + int32_t getReadTimeout() { + return readTimeout_; + } + + void setChunkSize(uint32_t chunkSize) { + if (chunkSize) { + chunkSize_ = chunkSize; + } + } + uint32_t getChunkSize() { + return chunkSize_; + } + + void setEventBufferSize(uint32_t bufferSize) { + if (bufferAndThreadInitialized_) { + GlobalOutput("Cannot change the buffer size after writer thread started"); + return; + } + eventBufferSize_ = bufferSize; + } + + uint32_t getEventBufferSize() { + return eventBufferSize_; + } + + void setFlushMaxUs(uint32_t flushMaxUs) { + if (flushMaxUs) { + flushMaxUs_ = flushMaxUs; + } + } + uint32_t getFlushMaxUs() { + return flushMaxUs_; + } + + void setFlushMaxBytes(uint32_t flushMaxBytes) { + if (flushMaxBytes) { + flushMaxBytes_ = flushMaxBytes; + } + } + uint32_t getFlushMaxBytes() { + return flushMaxBytes_; + } + + void setMaxEventSize(uint32_t maxEventSize) { + maxEventSize_ = maxEventSize; + } + uint32_t getMaxEventSize() { + return maxEventSize_; + } + + void setMaxCorruptedEvents(uint32_t maxCorruptedEvents) { + maxCorruptedEvents_ = maxCorruptedEvents; + } + uint32_t getMaxCorruptedEvents() { + return maxCorruptedEvents_; + } + + void setEofSleepTimeUs(uint32_t eofSleepTime) { + if (eofSleepTime) { + eofSleepTime_ = eofSleepTime; + } + } + uint32_t getEofSleepTimeUs() { + return eofSleepTime_; + } + + private: + // helper functions for writing to a file + void enqueueEvent(const uint8_t* buf, uint32_t eventLen, bool blockUntilFlush); + bool swapEventBuffers(struct timespec* deadline); + bool initBufferAndWriteThread(); + + // control for writer thread + static void* startWriterThread(void* ptr) { + (((TFileTransport*)ptr)->writerThread()); + return 0; + } + void writerThread(); + + // helper functions for reading from a file + eventInfo* readEvent(); + + // event corruption-related functions + bool isEventCorrupted(); + void performRecovery(); + + // Utility functions + void openLogFile(); + void getNextFlushTime(struct timespec* ts_next_flush); + + // Class variables + readState readState_; + uint8_t* readBuff_; + eventInfo* currentEvent_; + + uint32_t readBuffSize_; + static const uint32_t DEFAULT_READ_BUFF_SIZE = 1 * 1024 * 1024; + + int32_t readTimeout_; + static const int32_t DEFAULT_READ_TIMEOUT_MS = 200; + + // size of chunks that file will be split up into + uint32_t chunkSize_; + static const uint32_t DEFAULT_CHUNK_SIZE = 16 * 1024 * 1024; + + // size of event buffers + uint32_t eventBufferSize_; + static const uint32_t DEFAULT_EVENT_BUFFER_SIZE = 10000; + + // max number of microseconds that can pass without flushing + uint32_t flushMaxUs_; + static const uint32_t DEFAULT_FLUSH_MAX_US = 3000000; + + // max number of bytes that can be written without flushing + uint32_t flushMaxBytes_; + static const uint32_t DEFAULT_FLUSH_MAX_BYTES = 1000 * 1024; + + // max event size + uint32_t maxEventSize_; + static const uint32_t DEFAULT_MAX_EVENT_SIZE = 0; + + // max number of corrupted events per chunk + uint32_t maxCorruptedEvents_; + static const uint32_t DEFAULT_MAX_CORRUPTED_EVENTS = 0; + + // sleep duration when EOF is hit + uint32_t eofSleepTime_; + static const uint32_t DEFAULT_EOF_SLEEP_TIME_US = 500 * 1000; + + // sleep duration when a corrupted event is encountered + uint32_t corruptedEventSleepTime_; + static const uint32_t DEFAULT_CORRUPTED_SLEEP_TIME_US = 1 * 1000 * 1000; + + // writer thread id + pthread_t writerThreadId_; + + // buffers to hold data before it is flushed. Each element of the buffer stores a msg that + // needs to be written to the file. The buffers are swapped by the writer thread. + TFileTransportBuffer *dequeueBuffer_; + TFileTransportBuffer *enqueueBuffer_; + + // conditions used to block when the buffer is full or empty + pthread_cond_t notFull_, notEmpty_; + volatile bool closing_; + + // To keep track of whether the buffer has been flushed + pthread_cond_t flushed_; + volatile bool forceFlush_; + + // Mutex that is grabbed when enqueueing and swapping the read/write buffers + pthread_mutex_t mutex_; + + // File information + std::string filename_; + int fd_; + + // Whether the writer thread and buffers have been initialized + bool bufferAndThreadInitialized_; + + // Offset within the file + off_t offset_; + + // event corruption information + uint32_t lastBadChunk_; + uint32_t numCorruptedEventsInChunk_; + + bool readOnly_; +}; + +// Exception thrown when EOF is hit +class TEOFException : public TTransportException { + public: + TEOFException(): + TTransportException(TTransportException::END_OF_FILE) {}; +}; + + +// wrapper class to process events from a file containing thrift events +class TFileProcessor { + public: + /** + * Constructor that defaults output transport to null transport + * + * @param processor processes log-file events + * @param protocolFactory protocol factory + * @param inputTransport file transport + */ + TFileProcessor(boost::shared_ptr processor, + boost::shared_ptr protocolFactory, + boost::shared_ptr inputTransport); + + TFileProcessor(boost::shared_ptr processor, + boost::shared_ptr inputProtocolFactory, + boost::shared_ptr outputProtocolFactory, + boost::shared_ptr inputTransport); + + /** + * Constructor + * + * @param processor processes log-file events + * @param protocolFactory protocol factory + * @param inputTransport input file transport + * @param output output transport + */ + TFileProcessor(boost::shared_ptr processor, + boost::shared_ptr protocolFactory, + boost::shared_ptr inputTransport, + boost::shared_ptr outputTransport); + + /** + * processes events from the file + * + * @param numEvents number of events to process (0 for unlimited) + * @param tail tails the file if true + */ + void process(uint32_t numEvents, bool tail); + + /** + * process events until the end of the chunk + * + */ + void processChunk(); + + private: + boost::shared_ptr processor_; + boost::shared_ptr inputProtocolFactory_; + boost::shared_ptr outputProtocolFactory_; + boost::shared_ptr inputTransport_; + boost::shared_ptr outputTransport_; +}; + + +}}} // facebook::thrift::transport + +#endif // _THRIFT_TRANSPORT_TFILETRANSPORT_H_ Index: service/include/thrift/transport/TTransport.h =================================================================== --- service/include/thrift/transport/TTransport.h (revision 0) +++ service/include/thrift/transport/TTransport.h (revision 0) @@ -0,0 +1,406 @@ +// Copyright (c) 2006- Facebook +// Distributed under the Thrift Software License +// +// See accompanying file LICENSE or visit the Thrift site at: +// http://developers.facebook.com/thrift/ + +#ifndef _THRIFT_TRANSPORT_TTRANSPORT_H_ +#define _THRIFT_TRANSPORT_TTRANSPORT_H_ 1 + +#include +#include +#include +#include + +namespace facebook { namespace thrift { namespace transport { + +/** + * Generic interface for a method of transporting data. A TTransport may be + * capable of either reading or writing, but not necessarily both. + * + * @author Mark Slee + */ +class TTransport { + public: + /** + * Virtual deconstructor. + */ + virtual ~TTransport() {} + + /** + * Whether this transport is open. + */ + virtual bool isOpen() { + return false; + } + + /** + * Tests whether there is more data to read or if the remote side is + * still open. By default this is true whenever the transport is open, + * but implementations should add logic to test for this condition where + * possible (i.e. on a socket). + * This is used by a server to check if it should listen for another + * request. + */ + virtual bool peek() { + return isOpen(); + } + + /** + * Opens the transport for communications. + * + * @return bool Whether the transport was successfully opened + * @throws TTransportException if opening failed + */ + virtual void open() { + throw TTransportException(TTransportException::NOT_OPEN, "Cannot open base TTransport."); + } + + /** + * Closes the transport. + */ + virtual void close() { + throw TTransportException(TTransportException::NOT_OPEN, "Cannot close base TTransport."); + } + + /** + * Attempt to read up to the specified number of bytes into the string. + * + * @param buf Reference to the location to write the data + * @param len How many bytes to read + * @return How many bytes were actually read + * @throws TTransportException If an error occurs + */ + virtual uint32_t read(uint8_t* buf, uint32_t len) { + throw TTransportException(TTransportException::NOT_OPEN, "Base TTransport cannot read."); + } + + /** + * Reads the given amount of data in its entirety no matter what. + * + * @param s Reference to location for read data + * @param len How many bytes to read + * @return How many bytes read, which must be equal to size + * @throws TTransportException If insufficient data was read + */ + virtual uint32_t readAll(uint8_t* buf, uint32_t len) { + uint32_t have = 0; + uint32_t get = 0; + + while (have < len) { + get = read(buf+have, len-have); + if (get <= 0) { + throw TTransportException("No more data to read."); + } + have += get; + } + + return have; + } + + /** + * Called when read is completed. + * This can be over-ridden to perform a transport-specific action + * e.g. logging the request to a file + * + */ + virtual void readEnd() { + // default behaviour is to do nothing + return; + } + + /** + * Writes the string in its entirety to the buffer. + * + * @param buf The data to write out + * @throws TTransportException if an error occurs + */ + virtual void write(const uint8_t* buf, uint32_t len) { + throw TTransportException(TTransportException::NOT_OPEN, "Base TTransport cannot write."); + } + + /** + * Called when write is completed. + * This can be over-ridden to perform a transport-specific action + * at the end of a request. + * + */ + virtual void writeEnd() { + // default behaviour is to do nothing + return; + } + + /** + * Flushes any pending data to be written. Typically used with buffered + * transport mechanisms. + * + * @throws TTransportException if an error occurs + */ + virtual void flush() {} + + /** + * Attempts to copy len bytes from the transport into buf. Does not consume + * the bytes read (i.e.: a later read will return the same data). This + * method is meant to support protocols that need to read variable-length + * fields. They can attempt to borrow the maximum amount of data that they + * will need, then consume (see next method) what they actually use. Some + * transports will not support this method and others will fail occasionally, + * so protocols must be prepared to use read if borrow fails. + * + * @oaram buf The buffer to store the data + * @param len How much data to borrow + * @return true if the requested data has been borrowed, false otherwise + * @throws TTransportException if an error occurs + */ + virtual bool borrow(uint8_t* buf, uint32_t len) { + return false; + } + + /** + * Remove len bytes from the transport. This should always follow a borrow + * of at least len bytes, and should always succeed. + * TODO(dreiss): Is there any transport that could borrow but fail to + * consume, or that would require a buffer to dump the consumed data? + * + * @param len How many bytes to consume + * @throws TTransportException If an error occurs + */ + virtual void consume(uint32_t len) { + throw TTransportException(TTransportException::NOT_OPEN, "Base TTransport cannot consume."); + } + + protected: + /** + * Simple constructor. + */ + TTransport() {} +}; + +/** + * Generic factory class to make an input and output transport out of a + * source transport. Commonly used inside servers to make input and output + * streams out of raw clients. + * + * @author Mark Slee + */ +class TTransportFactory { + public: + TTransportFactory() {} + + virtual ~TTransportFactory() {} + + /** + * Default implementation does nothing, just returns the transport given. + */ + virtual boost::shared_ptr getTransport(boost::shared_ptr trans) { + return trans; + } + +}; + +}}} // facebook::thrift::transport + +#endif // #ifndef _THRIFT_TRANSPORT_TTRANSPORT_H_ +// Copyright (c) 2006- Facebook +// Distributed under the Thrift Software License +// +// See accompanying file LICENSE or visit the Thrift site at: +// http://developers.facebook.com/thrift/ + +#ifndef _THRIFT_TRANSPORT_TTRANSPORT_H_ +#define _THRIFT_TRANSPORT_TTRANSPORT_H_ 1 + +#include +#include +#include +#include + +namespace facebook { namespace thrift { namespace transport { + +/** + * Generic interface for a method of transporting data. A TTransport may be + * capable of either reading or writing, but not necessarily both. + * + * @author Mark Slee + */ +class TTransport { + public: + /** + * Virtual deconstructor. + */ + virtual ~TTransport() {} + + /** + * Whether this transport is open. + */ + virtual bool isOpen() { + return false; + } + + /** + * Tests whether there is more data to read or if the remote side is + * still open. By default this is true whenever the transport is open, + * but implementations should add logic to test for this condition where + * possible (i.e. on a socket). + * This is used by a server to check if it should listen for another + * request. + */ + virtual bool peek() { + return isOpen(); + } + + /** + * Opens the transport for communications. + * + * @return bool Whether the transport was successfully opened + * @throws TTransportException if opening failed + */ + virtual void open() { + throw TTransportException(TTransportException::NOT_OPEN, "Cannot open base TTransport."); + } + + /** + * Closes the transport. + */ + virtual void close() { + throw TTransportException(TTransportException::NOT_OPEN, "Cannot close base TTransport."); + } + + /** + * Attempt to read up to the specified number of bytes into the string. + * + * @param buf Reference to the location to write the data + * @param len How many bytes to read + * @return How many bytes were actually read + * @throws TTransportException If an error occurs + */ + virtual uint32_t read(uint8_t* buf, uint32_t len) { + throw TTransportException(TTransportException::NOT_OPEN, "Base TTransport cannot read."); + } + + /** + * Reads the given amount of data in its entirety no matter what. + * + * @param s Reference to location for read data + * @param len How many bytes to read + * @return How many bytes read, which must be equal to size + * @throws TTransportException If insufficient data was read + */ + virtual uint32_t readAll(uint8_t* buf, uint32_t len) { + uint32_t have = 0; + uint32_t get = 0; + + while (have < len) { + get = read(buf+have, len-have); + if (get <= 0) { + throw TTransportException("No more data to read."); + } + have += get; + } + + return have; + } + + /** + * Called when read is completed. + * This can be over-ridden to perform a transport-specific action + * e.g. logging the request to a file + * + */ + virtual void readEnd() { + // default behaviour is to do nothing + return; + } + + /** + * Writes the string in its entirety to the buffer. + * + * @param buf The data to write out + * @throws TTransportException if an error occurs + */ + virtual void write(const uint8_t* buf, uint32_t len) { + throw TTransportException(TTransportException::NOT_OPEN, "Base TTransport cannot write."); + } + + /** + * Called when write is completed. + * This can be over-ridden to perform a transport-specific action + * at the end of a request. + * + */ + virtual void writeEnd() { + // default behaviour is to do nothing + return; + } + + /** + * Flushes any pending data to be written. Typically used with buffered + * transport mechanisms. + * + * @throws TTransportException if an error occurs + */ + virtual void flush() {} + + /** + * Attempts to copy len bytes from the transport into buf. Does not consume + * the bytes read (i.e.: a later read will return the same data). This + * method is meant to support protocols that need to read variable-length + * fields. They can attempt to borrow the maximum amount of data that they + * will need, then consume (see next method) what they actually use. Some + * transports will not support this method and others will fail occasionally, + * so protocols must be prepared to use read if borrow fails. + * + * @oaram buf The buffer to store the data + * @param len How much data to borrow + * @return true if the requested data has been borrowed, false otherwise + * @throws TTransportException if an error occurs + */ + virtual bool borrow(uint8_t* buf, uint32_t len) { + return false; + } + + /** + * Remove len bytes from the transport. This should always follow a borrow + * of at least len bytes, and should always succeed. + * TODO(dreiss): Is there any transport that could borrow but fail to + * consume, or that would require a buffer to dump the consumed data? + * + * @param len How many bytes to consume + * @throws TTransportException If an error occurs + */ + virtual void consume(uint32_t len) { + throw TTransportException(TTransportException::NOT_OPEN, "Base TTransport cannot consume."); + } + + protected: + /** + * Simple constructor. + */ + TTransport() {} +}; + +/** + * Generic factory class to make an input and output transport out of a + * source transport. Commonly used inside servers to make input and output + * streams out of raw clients. + * + * @author Mark Slee + */ +class TTransportFactory { + public: + TTransportFactory() {} + + virtual ~TTransportFactory() {} + + /** + * Default implementation does nothing, just returns the transport given. + */ + virtual boost::shared_ptr getTransport(boost::shared_ptr trans) { + return trans; + } + +}; + +}}} // facebook::thrift::transport + +#endif // #ifndef _THRIFT_TRANSPORT_TTRANSPORT_H_ Index: service/include/thrift/transport/TTransportUtils.h =================================================================== --- service/include/thrift/transport/TTransportUtils.h (revision 0) +++ service/include/thrift/transport/TTransportUtils.h (revision 0) @@ -0,0 +1,1354 @@ +// Copyright (c) 2006- Facebook +// Distributed under the Thrift Software License +// +// See accompanying file LICENSE or visit the Thrift site at: +// http://developers.facebook.com/thrift/ + +#ifndef _THRIFT_TRANSPORT_TTRANSPORTUTILS_H_ +#define _THRIFT_TRANSPORT_TTRANSPORTUTILS_H_ 1 + +#include +#include +#include +#include + +namespace facebook { namespace thrift { namespace transport { + +/** + * The null transport is a dummy transport that doesn't actually do anything. + * It's sort of an analogy to /dev/null, you can never read anything from it + * and it will let you write anything you want to it, though it won't actually + * go anywhere. + * + * @author Mark Slee + */ +class TNullTransport : public TTransport { + public: + TNullTransport() {} + + ~TNullTransport() {} + + bool isOpen() { + return true; + } + + void open() {} + + void write(const uint8_t* buf, uint32_t len) { + return; + } + +}; + + +/** + * 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. + * + * @author Mark Slee + */ +class TBufferedTransport : public TTransport { + public: + TBufferedTransport(boost::shared_ptr transport) : + transport_(transport), + rBufSize_(512), rPos_(0), rLen_(0), + wBufSize_(512), wLen_(0) { + rBuf_ = new uint8_t[rBufSize_]; + wBuf_ = new uint8_t[wBufSize_]; + } + + TBufferedTransport(boost::shared_ptr transport, uint32_t sz) : + transport_(transport), + rBufSize_(sz), rPos_(0), rLen_(0), + wBufSize_(sz), wLen_(0) { + rBuf_ = new uint8_t[rBufSize_]; + wBuf_ = new uint8_t[wBufSize_]; + } + + TBufferedTransport(boost::shared_ptr transport, uint32_t rsz, uint32_t wsz) : + transport_(transport), + rBufSize_(rsz), rPos_(0), rLen_(0), + wBufSize_(wsz), wLen_(0) { + rBuf_ = new uint8_t[rBufSize_]; + wBuf_ = new uint8_t[wBufSize_]; + } + + ~TBufferedTransport() { + delete [] rBuf_; + delete [] wBuf_; + } + + bool isOpen() { + return transport_->isOpen(); + } + + bool peek() { + if (rPos_ >= rLen_) { + rLen_ = transport_->read(rBuf_, rBufSize_); + rPos_ = 0; + } + return (rLen_ > rPos_); + } + + void open() { + transport_->open(); + } + + void close() { + flush(); + transport_->close(); + } + + uint32_t read(uint8_t* buf, uint32_t len); + + void write(const uint8_t* buf, uint32_t len); + + void flush(); + + bool borrow(uint8_t* buf, uint32_t len); + + void consume(uint32_t len); + + boost::shared_ptr getUnderlyingTransport() { + return transport_; + } + + protected: + boost::shared_ptr transport_; + uint8_t* rBuf_; + uint32_t rBufSize_; + uint32_t rPos_; + uint32_t rLen_; + + uint8_t* wBuf_; + uint32_t wBufSize_; + uint32_t wLen_; +}; + +/** + * Wraps a transport into a buffered one. + * + * @author Mark Slee + */ +class TBufferedTransportFactory : public TTransportFactory { + public: + TBufferedTransportFactory() {} + + virtual ~TBufferedTransportFactory() {} + + /** + * Wraps the transport into a buffered one. + */ + virtual boost::shared_ptr getTransport(boost::shared_ptr trans) { + return boost::shared_ptr(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. + * + * @author Mark Slee + */ +class TFramedTransport : public TTransport { + public: + TFramedTransport(boost::shared_ptr transport) : + transport_(transport), + rPos_(0), + rLen_(0), + read_(true), + wBufSize_(512), + wLen_(0), + write_(true) { + rBuf_ = NULL; + wBuf_ = new uint8_t[wBufSize_]; + } + + TFramedTransport(boost::shared_ptr transport, uint32_t sz) : + transport_(transport), + rPos_(0), + rLen_(0), + read_(true), + wBufSize_(sz), + wLen_(0), + write_(true) { + rBuf_ = NULL; + wBuf_ = new uint8_t[wBufSize_]; + } + + ~TFramedTransport() { + if (rBuf_ != NULL) { + delete [] rBuf_; + } + if (wBuf_ != NULL) { + delete [] wBuf_; + } + } + + void setRead(bool read) { + read_ = read; + } + + void setWrite(bool write) { + write_ = write; + } + + void open() { + transport_->open(); + } + + bool isOpen() { + return transport_->isOpen(); + } + + bool peek() { + if (rPos_ < rLen_) { + return true; + } + return transport_->peek(); + } + + void close() { + if (wLen_ > 0) { + flush(); + } + transport_->close(); + } + + uint32_t read(uint8_t* buf, uint32_t len); + + void write(const uint8_t* buf, uint32_t len); + + void flush(); + + bool borrow(uint8_t* buf, uint32_t len); + + void consume(uint32_t len); + + boost::shared_ptr getUnderlyingTransport() { + return transport_; + } + + protected: + boost::shared_ptr transport_; + uint8_t* rBuf_; + uint32_t rPos_; + uint32_t rLen_; + bool read_; + + uint8_t* wBuf_; + uint32_t wBufSize_; + uint32_t wLen_; + bool write_; + + /** + * Reads a frame of input from the underlying stream. + */ + void readFrame(); +}; + +/** + * Wraps a transport into a framed one. + * + * @author Dave Simpson + */ +class TFramedTransportFactory : public TTransportFactory { + public: + TFramedTransportFactory() {} + + virtual ~TFramedTransportFactory() {} + + /** + * Wraps the transport into a framed one. + */ + virtual boost::shared_ptr getTransport(boost::shared_ptr trans) { + return boost::shared_ptr(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. + * + * @author Mark Slee + */ +class TMemoryBuffer : public TTransport { + 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*)malloc(size); + if (buf == NULL) { + throw TTransportException("Out of memory"); + } + } + + buffer_ = buf; + bufferSize_ = size; + owner_ = owner; + wPos_ = wPos; + rPos_ = 0; + } + + public: + static const uint32_t defaultSize = 1024; + + TMemoryBuffer() { + initCommon(NULL, defaultSize, true, 0); + } + + TMemoryBuffer(uint32_t sz) { + initCommon(NULL, sz, true, 0); + } + + // transferOwnership should be true if you want TMemoryBuffer to call free(buf). + TMemoryBuffer(uint8_t* buf, int sz, bool transferOwnership = false) { + initCommon(buf, sz, transferOwnership, sz); + } + + // copy should be true if you want TMemoryBuffer to make a copy of the string. + // If you set copy to false, the string must not be destroyed before you are + // done with the TMemoryBuffer. + TMemoryBuffer(const std::string& str, bool copy = false) { + if (copy) { + initCommon(NULL, str.length(), true, 0); + this->write(reinterpret_cast(str.data()), str.length()); + } else { + // This first argument should be equivalent to the following: + // const_cast(reinterpret_cast(str.data())) + initCommon((uint8_t*)str.data(), str.length(), false, str.length()); + } + } + + ~TMemoryBuffer() { + if (owner_) { + free(buffer_); + buffer_ = NULL; + } + } + + bool isOpen() { + return true; + } + + bool peek() { + return (rPos_ < wPos_); + } + + void open() {} + + void close() {} + + void getBuffer(uint8_t** bufPtr, uint32_t* sz) { + *bufPtr = buffer_; + *sz = wPos_; + } + + std::string getBufferAsString() { + if (buffer_ == NULL) { + return ""; + } + return std::string((char*)buffer_, (std::string::size_type)wPos_); + } + + void appendBufferToString(std::string& str) { + if (buffer_ == NULL) { + return; + } + str.append((char*)buffer_, wPos_); + } + + void resetBuffer() { + wPos_ = 0; + rPos_ = 0; + } + + // transferOwnership should be true if you want TMemoryBuffer to call free(buf). + void resetBuffer(uint8_t* buf, uint32_t sz, bool transferOwnership = false) { + if (owner_) { + free(buffer_); + } + owner_ = transferOwnership; + buffer_ = buf; + bufferSize_ = sz; + wPos_ = sz; + rPos_ = 0; + } + + // See the constructor that takes a string. + void resetFromString(const std::string& str, bool copy = false) { + if (copy) { + uint8_t* buf = (uint8_t*)malloc(str.length()); + if (buf == NULL) { + throw TTransportException("Out of memory"); + } + std::copy(str.begin(), str.end(), buf); + resetBuffer(buf, str.length(), true); + } else { + // See the above comment about const_cast. + resetBuffer((uint8_t*)str.data(), str.length(), false); + } + } + + uint32_t read(uint8_t* buf, uint32_t len); + + std::string readAsString(uint32_t len) { + std::string str; + (void)readAppendToString(str, len); + return str; + } + + uint32_t readAppendToString(std::string& str, uint32_t len); + + void readEnd() { + if (rPos_ == wPos_) { + resetBuffer(); + } + } + + void write(const uint8_t* buf, uint32_t len); + + uint32_t available() { + return wPos_ - rPos_; + } + + bool borrow(uint8_t* buf, uint32_t len); + + void consume(uint32_t len); + + private: + // Data buffer + uint8_t* buffer_; + + // Allocated buffer size + uint32_t bufferSize_; + + // Where the write is at + uint32_t wPos_; + + // Where the reader is at + uint32_t rPos_; + + // Is this object the owner of the buffer? + bool owner_; + +}; + +/** + * TPipedTransport. This transport allows piping of a request from one + * transport to another either when readEnd() or writeEnd(). The typical + * use case for this is to log a request or a reply to disk. + * The underlying buffer expands to a keep a copy of the entire + * request/response. + * + * @author Aditya Agarwal + */ +class TPipedTransport : virtual public TTransport { + public: + TPipedTransport(boost::shared_ptr srcTrans, + boost::shared_ptr dstTrans) : + srcTrans_(srcTrans), + dstTrans_(dstTrans), + rBufSize_(512), rPos_(0), rLen_(0), + wBufSize_(512), wLen_(0) { + + // default is to to pipe the request when readEnd() is called + pipeOnRead_ = true; + pipeOnWrite_ = false; + + rBuf_ = (uint8_t*) malloc(sizeof(uint8_t) * rBufSize_); + wBuf_ = (uint8_t*) malloc(sizeof(uint8_t) * wBufSize_); + } + + TPipedTransport(boost::shared_ptr srcTrans, + boost::shared_ptr dstTrans, + uint32_t sz) : + srcTrans_(srcTrans), + dstTrans_(dstTrans), + rBufSize_(512), rPos_(0), rLen_(0), + wBufSize_(sz), wLen_(0) { + + rBuf_ = (uint8_t*) malloc(sizeof(uint8_t) * rBufSize_); + wBuf_ = (uint8_t*) malloc(sizeof(uint8_t) * wBufSize_); + } + + ~TPipedTransport() { + free(rBuf_); + free(wBuf_); + } + + bool isOpen() { + return srcTrans_->isOpen(); + } + + bool peek() { + if (rPos_ >= rLen_) { + // Double the size of the underlying buffer if it is full + if (rLen_ == rBufSize_) { + rBufSize_ *=2; + rBuf_ = (uint8_t *)realloc(rBuf_, sizeof(uint8_t) * rBufSize_); + } + + // try to fill up the buffer + rLen_ += srcTrans_->read(rBuf_+rPos_, rBufSize_ - rPos_); + } + return (rLen_ > rPos_); + } + + + void open() { + srcTrans_->open(); + } + + void close() { + srcTrans_->close(); + } + + void setPipeOnRead(bool pipeVal) { + pipeOnRead_ = pipeVal; + } + + void setPipeOnWrite(bool pipeVal) { + pipeOnWrite_ = pipeVal; + } + + uint32_t read(uint8_t* buf, uint32_t len); + + void readEnd() { + + if (pipeOnRead_) { + dstTrans_->write(rBuf_, rLen_); + dstTrans_->flush(); + } + + srcTrans_->readEnd(); + + // reset state + rLen_ = 0; + rPos_ = 0; + } + + void write(const uint8_t* buf, uint32_t len); + + void writeEnd() { + if (pipeOnWrite_) { + dstTrans_->write(wBuf_, wLen_); + dstTrans_->flush(); + } + } + + void flush(); + + boost::shared_ptr getTargetTransport() { + return dstTrans_; + } + + protected: + boost::shared_ptr srcTrans_; + boost::shared_ptr dstTrans_; + + uint8_t* rBuf_; + uint32_t rBufSize_; + uint32_t rPos_; + uint32_t rLen_; + + uint8_t* wBuf_; + uint32_t wBufSize_; + uint32_t wLen_; + + bool pipeOnRead_; + bool pipeOnWrite_; +}; + + +/** + * Wraps a transport into a pipedTransport instance. + * + * @author Aditya Agarwal + */ +class TPipedTransportFactory : public TTransportFactory { + public: + TPipedTransportFactory() {} + TPipedTransportFactory(boost::shared_ptr dstTrans) { + initializeTargetTransport(dstTrans); + } + virtual ~TPipedTransportFactory() {} + + /** + * Wraps the base transport into a piped transport. + */ + virtual boost::shared_ptr getTransport(boost::shared_ptr srcTrans) { + return boost::shared_ptr(new TPipedTransport(srcTrans, dstTrans_)); + } + + virtual void initializeTargetTransport(boost::shared_ptr dstTrans) { + if (dstTrans_.get() == NULL) { + dstTrans_ = dstTrans; + } else { + throw TException("Target transport already initialized"); + } + } + + protected: + boost::shared_ptr dstTrans_; +}; + +/** + * TPipedFileTransport. This is just like a TTransport, except that + * it is a templatized class, so that clients who rely on a specific + * TTransport can still access the original transport. + * + * @author James Wang + */ +class TPipedFileReaderTransport : public TPipedTransport, + public TFileReaderTransport { + public: + TPipedFileReaderTransport(boost::shared_ptr srcTrans, boost::shared_ptr dstTrans); + + ~TPipedFileReaderTransport(); + + // TTransport functions + bool isOpen(); + bool peek(); + void open(); + void close(); + uint32_t read(uint8_t* buf, uint32_t len); + uint32_t readAll(uint8_t* buf, uint32_t len); + void readEnd(); + void write(const uint8_t* buf, uint32_t len); + void writeEnd(); + void flush(); + + // TFileReaderTransport functions + int32_t getReadTimeout(); + void setReadTimeout(int32_t readTimeout); + uint32_t getNumChunks(); + uint32_t getCurChunk(); + void seekToChunk(int32_t chunk); + void seekToEnd(); + + protected: + // shouldn't be used + TPipedFileReaderTransport(); + boost::shared_ptr srcTrans_; +}; + +/** + * Creates a TPipedFileReaderTransport from a filepath and a destination transport + * + * @author James Wang + */ +class TPipedFileReaderTransportFactory : public TPipedTransportFactory { + public: + TPipedFileReaderTransportFactory() {} + TPipedFileReaderTransportFactory(boost::shared_ptr dstTrans) + : TPipedTransportFactory(dstTrans) + {} + virtual ~TPipedFileReaderTransportFactory() {} + + boost::shared_ptr getTransport(boost::shared_ptr srcTrans) { + boost::shared_ptr pFileReaderTransport = boost::dynamic_pointer_cast(srcTrans); + if (pFileReaderTransport.get() != NULL) { + return getFileReaderTransport(pFileReaderTransport); + } else { + return boost::shared_ptr(); + } + } + + boost::shared_ptr getFileReaderTransport(boost::shared_ptr srcTrans) { + return boost::shared_ptr(new TPipedFileReaderTransport(srcTrans, dstTrans_)); + } +}; + +}}} // facebook::thrift::transport + +#endif // #ifndef _THRIFT_TRANSPORT_TTRANSPORTUTILS_H_ +// Copyright (c) 2006- Facebook +// Distributed under the Thrift Software License +// +// See accompanying file LICENSE or visit the Thrift site at: +// http://developers.facebook.com/thrift/ + +#ifndef _THRIFT_TRANSPORT_TTRANSPORTUTILS_H_ +#define _THRIFT_TRANSPORT_TTRANSPORTUTILS_H_ 1 + +#include +#include +#include +#include + +namespace facebook { namespace thrift { namespace transport { + +/** + * The null transport is a dummy transport that doesn't actually do anything. + * It's sort of an analogy to /dev/null, you can never read anything from it + * and it will let you write anything you want to it, though it won't actually + * go anywhere. + * + * @author Mark Slee + */ +class TNullTransport : public TTransport { + public: + TNullTransport() {} + + ~TNullTransport() {} + + bool isOpen() { + return true; + } + + void open() {} + + void write(const uint8_t* buf, uint32_t len) { + return; + } + +}; + + +/** + * 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. + * + * @author Mark Slee + */ +class TBufferedTransport : public TTransport { + public: + TBufferedTransport(boost::shared_ptr transport) : + transport_(transport), + rBufSize_(512), rPos_(0), rLen_(0), + wBufSize_(512), wLen_(0) { + rBuf_ = new uint8_t[rBufSize_]; + wBuf_ = new uint8_t[wBufSize_]; + } + + TBufferedTransport(boost::shared_ptr transport, uint32_t sz) : + transport_(transport), + rBufSize_(sz), rPos_(0), rLen_(0), + wBufSize_(sz), wLen_(0) { + rBuf_ = new uint8_t[rBufSize_]; + wBuf_ = new uint8_t[wBufSize_]; + } + + TBufferedTransport(boost::shared_ptr transport, uint32_t rsz, uint32_t wsz) : + transport_(transport), + rBufSize_(rsz), rPos_(0), rLen_(0), + wBufSize_(wsz), wLen_(0) { + rBuf_ = new uint8_t[rBufSize_]; + wBuf_ = new uint8_t[wBufSize_]; + } + + ~TBufferedTransport() { + delete [] rBuf_; + delete [] wBuf_; + } + + bool isOpen() { + return transport_->isOpen(); + } + + bool peek() { + if (rPos_ >= rLen_) { + rLen_ = transport_->read(rBuf_, rBufSize_); + rPos_ = 0; + } + return (rLen_ > rPos_); + } + + void open() { + transport_->open(); + } + + void close() { + flush(); + transport_->close(); + } + + uint32_t read(uint8_t* buf, uint32_t len); + + void write(const uint8_t* buf, uint32_t len); + + void flush(); + + bool borrow(uint8_t* buf, uint32_t len); + + void consume(uint32_t len); + + boost::shared_ptr getUnderlyingTransport() { + return transport_; + } + + protected: + boost::shared_ptr transport_; + uint8_t* rBuf_; + uint32_t rBufSize_; + uint32_t rPos_; + uint32_t rLen_; + + uint8_t* wBuf_; + uint32_t wBufSize_; + uint32_t wLen_; +}; + +/** + * Wraps a transport into a buffered one. + * + * @author Mark Slee + */ +class TBufferedTransportFactory : public TTransportFactory { + public: + TBufferedTransportFactory() {} + + virtual ~TBufferedTransportFactory() {} + + /** + * Wraps the transport into a buffered one. + */ + virtual boost::shared_ptr getTransport(boost::shared_ptr trans) { + return boost::shared_ptr(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. + * + * @author Mark Slee + */ +class TFramedTransport : public TTransport { + public: + TFramedTransport(boost::shared_ptr transport) : + transport_(transport), + rPos_(0), + rLen_(0), + read_(true), + wBufSize_(512), + wLen_(0), + write_(true) { + rBuf_ = NULL; + wBuf_ = new uint8_t[wBufSize_]; + } + + TFramedTransport(boost::shared_ptr transport, uint32_t sz) : + transport_(transport), + rPos_(0), + rLen_(0), + read_(true), + wBufSize_(sz), + wLen_(0), + write_(true) { + rBuf_ = NULL; + wBuf_ = new uint8_t[wBufSize_]; + } + + ~TFramedTransport() { + if (rBuf_ != NULL) { + delete [] rBuf_; + } + if (wBuf_ != NULL) { + delete [] wBuf_; + } + } + + void setRead(bool read) { + read_ = read; + } + + void setWrite(bool write) { + write_ = write; + } + + void open() { + transport_->open(); + } + + bool isOpen() { + return transport_->isOpen(); + } + + bool peek() { + if (rPos_ < rLen_) { + return true; + } + return transport_->peek(); + } + + void close() { + if (wLen_ > 0) { + flush(); + } + transport_->close(); + } + + uint32_t read(uint8_t* buf, uint32_t len); + + void write(const uint8_t* buf, uint32_t len); + + void flush(); + + bool borrow(uint8_t* buf, uint32_t len); + + void consume(uint32_t len); + + boost::shared_ptr getUnderlyingTransport() { + return transport_; + } + + protected: + boost::shared_ptr transport_; + uint8_t* rBuf_; + uint32_t rPos_; + uint32_t rLen_; + bool read_; + + uint8_t* wBuf_; + uint32_t wBufSize_; + uint32_t wLen_; + bool write_; + + /** + * Reads a frame of input from the underlying stream. + */ + void readFrame(); +}; + +/** + * Wraps a transport into a framed one. + * + * @author Dave Simpson + */ +class TFramedTransportFactory : public TTransportFactory { + public: + TFramedTransportFactory() {} + + virtual ~TFramedTransportFactory() {} + + /** + * Wraps the transport into a framed one. + */ + virtual boost::shared_ptr getTransport(boost::shared_ptr trans) { + return boost::shared_ptr(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. + * + * @author Mark Slee + */ +class TMemoryBuffer : public TTransport { + 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*)malloc(size); + if (buf == NULL) { + throw TTransportException("Out of memory"); + } + } + + buffer_ = buf; + bufferSize_ = size; + owner_ = owner; + wPos_ = wPos; + rPos_ = 0; + } + + public: + static const uint32_t defaultSize = 1024; + + TMemoryBuffer() { + initCommon(NULL, defaultSize, true, 0); + } + + TMemoryBuffer(uint32_t sz) { + initCommon(NULL, sz, true, 0); + } + + // transferOwnership should be true if you want TMemoryBuffer to call free(buf). + TMemoryBuffer(uint8_t* buf, int sz, bool transferOwnership = false) { + initCommon(buf, sz, transferOwnership, sz); + } + + // copy should be true if you want TMemoryBuffer to make a copy of the string. + // If you set copy to false, the string must not be destroyed before you are + // done with the TMemoryBuffer. + TMemoryBuffer(const std::string& str, bool copy = false) { + if (copy) { + initCommon(NULL, str.length(), true, 0); + this->write(reinterpret_cast(str.data()), str.length()); + } else { + // This first argument should be equivalent to the following: + // const_cast(reinterpret_cast(str.data())) + initCommon((uint8_t*)str.data(), str.length(), false, str.length()); + } + } + + ~TMemoryBuffer() { + if (owner_) { + free(buffer_); + buffer_ = NULL; + } + } + + bool isOpen() { + return true; + } + + bool peek() { + return (rPos_ < wPos_); + } + + void open() {} + + void close() {} + + void getBuffer(uint8_t** bufPtr, uint32_t* sz) { + *bufPtr = buffer_; + *sz = wPos_; + } + + std::string getBufferAsString() { + if (buffer_ == NULL) { + return ""; + } + return std::string((char*)buffer_, (std::string::size_type)wPos_); + } + + void appendBufferToString(std::string& str) { + if (buffer_ == NULL) { + return; + } + str.append((char*)buffer_, wPos_); + } + + void resetBuffer() { + wPos_ = 0; + rPos_ = 0; + } + + // transferOwnership should be true if you want TMemoryBuffer to call free(buf). + void resetBuffer(uint8_t* buf, uint32_t sz, bool transferOwnership = false) { + if (owner_) { + free(buffer_); + } + owner_ = transferOwnership; + buffer_ = buf; + bufferSize_ = sz; + wPos_ = sz; + rPos_ = 0; + } + + // See the constructor that takes a string. + void resetFromString(const std::string& str, bool copy = false) { + if (copy) { + uint8_t* buf = (uint8_t*)malloc(str.length()); + if (buf == NULL) { + throw TTransportException("Out of memory"); + } + std::copy(str.begin(), str.end(), buf); + resetBuffer(buf, str.length(), true); + } else { + // See the above comment about const_cast. + resetBuffer((uint8_t*)str.data(), str.length(), false); + } + } + + uint32_t read(uint8_t* buf, uint32_t len); + + std::string readAsString(uint32_t len) { + std::string str; + (void)readAppendToString(str, len); + return str; + } + + uint32_t readAppendToString(std::string& str, uint32_t len); + + void readEnd() { + if (rPos_ == wPos_) { + resetBuffer(); + } + } + + void write(const uint8_t* buf, uint32_t len); + + uint32_t available() { + return wPos_ - rPos_; + } + + bool borrow(uint8_t* buf, uint32_t len); + + void consume(uint32_t len); + + private: + // Data buffer + uint8_t* buffer_; + + // Allocated buffer size + uint32_t bufferSize_; + + // Where the write is at + uint32_t wPos_; + + // Where the reader is at + uint32_t rPos_; + + // Is this object the owner of the buffer? + bool owner_; + +}; + +/** + * TPipedTransport. This transport allows piping of a request from one + * transport to another either when readEnd() or writeEnd(). The typical + * use case for this is to log a request or a reply to disk. + * The underlying buffer expands to a keep a copy of the entire + * request/response. + * + * @author Aditya Agarwal + */ +class TPipedTransport : virtual public TTransport { + public: + TPipedTransport(boost::shared_ptr srcTrans, + boost::shared_ptr dstTrans) : + srcTrans_(srcTrans), + dstTrans_(dstTrans), + rBufSize_(512), rPos_(0), rLen_(0), + wBufSize_(512), wLen_(0) { + + // default is to to pipe the request when readEnd() is called + pipeOnRead_ = true; + pipeOnWrite_ = false; + + rBuf_ = (uint8_t*) malloc(sizeof(uint8_t) * rBufSize_); + wBuf_ = (uint8_t*) malloc(sizeof(uint8_t) * wBufSize_); + } + + TPipedTransport(boost::shared_ptr srcTrans, + boost::shared_ptr dstTrans, + uint32_t sz) : + srcTrans_(srcTrans), + dstTrans_(dstTrans), + rBufSize_(512), rPos_(0), rLen_(0), + wBufSize_(sz), wLen_(0) { + + rBuf_ = (uint8_t*) malloc(sizeof(uint8_t) * rBufSize_); + wBuf_ = (uint8_t*) malloc(sizeof(uint8_t) * wBufSize_); + } + + ~TPipedTransport() { + free(rBuf_); + free(wBuf_); + } + + bool isOpen() { + return srcTrans_->isOpen(); + } + + bool peek() { + if (rPos_ >= rLen_) { + // Double the size of the underlying buffer if it is full + if (rLen_ == rBufSize_) { + rBufSize_ *=2; + rBuf_ = (uint8_t *)realloc(rBuf_, sizeof(uint8_t) * rBufSize_); + } + + // try to fill up the buffer + rLen_ += srcTrans_->read(rBuf_+rPos_, rBufSize_ - rPos_); + } + return (rLen_ > rPos_); + } + + + void open() { + srcTrans_->open(); + } + + void close() { + srcTrans_->close(); + } + + void setPipeOnRead(bool pipeVal) { + pipeOnRead_ = pipeVal; + } + + void setPipeOnWrite(bool pipeVal) { + pipeOnWrite_ = pipeVal; + } + + uint32_t read(uint8_t* buf, uint32_t len); + + void readEnd() { + + if (pipeOnRead_) { + dstTrans_->write(rBuf_, rLen_); + dstTrans_->flush(); + } + + srcTrans_->readEnd(); + + // reset state + rLen_ = 0; + rPos_ = 0; + } + + void write(const uint8_t* buf, uint32_t len); + + void writeEnd() { + if (pipeOnWrite_) { + dstTrans_->write(wBuf_, wLen_); + dstTrans_->flush(); + } + } + + void flush(); + + boost::shared_ptr getTargetTransport() { + return dstTrans_; + } + + protected: + boost::shared_ptr srcTrans_; + boost::shared_ptr dstTrans_; + + uint8_t* rBuf_; + uint32_t rBufSize_; + uint32_t rPos_; + uint32_t rLen_; + + uint8_t* wBuf_; + uint32_t wBufSize_; + uint32_t wLen_; + + bool pipeOnRead_; + bool pipeOnWrite_; +}; + + +/** + * Wraps a transport into a pipedTransport instance. + * + * @author Aditya Agarwal + */ +class TPipedTransportFactory : public TTransportFactory { + public: + TPipedTransportFactory() {} + TPipedTransportFactory(boost::shared_ptr dstTrans) { + initializeTargetTransport(dstTrans); + } + virtual ~TPipedTransportFactory() {} + + /** + * Wraps the base transport into a piped transport. + */ + virtual boost::shared_ptr getTransport(boost::shared_ptr srcTrans) { + return boost::shared_ptr(new TPipedTransport(srcTrans, dstTrans_)); + } + + virtual void initializeTargetTransport(boost::shared_ptr dstTrans) { + if (dstTrans_.get() == NULL) { + dstTrans_ = dstTrans; + } else { + throw TException("Target transport already initialized"); + } + } + + protected: + boost::shared_ptr dstTrans_; +}; + +/** + * TPipedFileTransport. This is just like a TTransport, except that + * it is a templatized class, so that clients who rely on a specific + * TTransport can still access the original transport. + * + * @author James Wang + */ +class TPipedFileReaderTransport : public TPipedTransport, + public TFileReaderTransport { + public: + TPipedFileReaderTransport(boost::shared_ptr srcTrans, boost::shared_ptr dstTrans); + + ~TPipedFileReaderTransport(); + + // TTransport functions + bool isOpen(); + bool peek(); + void open(); + void close(); + uint32_t read(uint8_t* buf, uint32_t len); + uint32_t readAll(uint8_t* buf, uint32_t len); + void readEnd(); + void write(const uint8_t* buf, uint32_t len); + void writeEnd(); + void flush(); + + // TFileReaderTransport functions + int32_t getReadTimeout(); + void setReadTimeout(int32_t readTimeout); + uint32_t getNumChunks(); + uint32_t getCurChunk(); + void seekToChunk(int32_t chunk); + void seekToEnd(); + + protected: + // shouldn't be used + TPipedFileReaderTransport(); + boost::shared_ptr srcTrans_; +}; + +/** + * Creates a TPipedFileReaderTransport from a filepath and a destination transport + * + * @author James Wang + */ +class TPipedFileReaderTransportFactory : public TPipedTransportFactory { + public: + TPipedFileReaderTransportFactory() {} + TPipedFileReaderTransportFactory(boost::shared_ptr dstTrans) + : TPipedTransportFactory(dstTrans) + {} + virtual ~TPipedFileReaderTransportFactory() {} + + boost::shared_ptr getTransport(boost::shared_ptr srcTrans) { + boost::shared_ptr pFileReaderTransport = boost::dynamic_pointer_cast(srcTrans); + if (pFileReaderTransport.get() != NULL) { + return getFileReaderTransport(pFileReaderTransport); + } else { + return boost::shared_ptr(); + } + } + + boost::shared_ptr getFileReaderTransport(boost::shared_ptr srcTrans) { + return boost::shared_ptr(new TPipedFileReaderTransport(srcTrans, dstTrans_)); + } +}; + +}}} // facebook::thrift::transport + +#endif // #ifndef _THRIFT_TRANSPORT_TTRANSPORTUTILS_H_ Index: service/include/thrift/transport/TZlibTransport.h =================================================================== --- service/include/thrift/transport/TZlibTransport.h (revision 0) +++ service/include/thrift/transport/TZlibTransport.h (revision 0) @@ -0,0 +1,414 @@ +// Copyright (c) 2006- Facebook +// Distributed under the Thrift Software License +// +// See accompanying file LICENSE or visit the Thrift site at: +// http://developers.facebook.com/thrift/ + +#ifndef _THRIFT_TRANSPORT_TZLIBTRANSPORT_H_ +#define _THRIFT_TRANSPORT_TZLIBTRANSPORT_H_ 1 + +#include +#include + +struct z_stream_s; + +namespace facebook { namespace thrift { namespace transport { + +class TZlibTransportException : public TTransportException { + public: + TZlibTransportException(int status, const char* msg) : + TTransportException(TTransportException::INTERNAL_ERROR, + errorMessage(status, msg)), + zlib_status_(status), + zlib_msg_(msg == NULL ? "(null)" : msg) {} + + virtual ~TZlibTransportException() throw() {} + + int getZlibStatus() { return zlib_status_; } + std::string getZlibMessage() { return zlib_msg_; } + + static std::string errorMessage(int status, const char* msg) { + std::string rv = "zlib error: "; + if (msg) { + rv += msg; + } else { + rv += "(no message)"; + } + rv += " (status = "; + rv += boost::lexical_cast(status); + rv += ")"; + return rv; + } + + int zlib_status_; + std::string zlib_msg_; +}; + +/** + * This transport uses zlib's compressed format on the "far" side. + * + * There are two kinds of TZlibTransport objects: + * - Standalone objects are used to encode self-contained chunks of data + * (like structures). They include checksums. + * - Non-standalone transports are used for RPC. They are not implemented yet. + * + * TODO(dreiss): Don't do an extra copy of the compressed data if + * the underlying transport is TBuffered or TMemory. + * + * @author David Reiss + */ +class TZlibTransport : public TTransport { + public: + + /** + * @param transport The transport to read compressed data from + * and write compressed data to. + * @param use_for_rpc True if this object will be used for RPC, + * false if this is a standalone object. + * @param urbuf_size Uncompressed buffer size for reading. + * @param crbuf_size Compressed buffer size for reading. + * @param uwbuf_size Uncompressed buffer size for writing. + * @param cwbuf_size Compressed buffer size for writing. + * + * TODO(dreiss): Write a constructor that isn't a pain. + */ + TZlibTransport(boost::shared_ptr transport, + bool use_for_rpc, + int urbuf_size = DEFAULT_URBUF_SIZE, + int crbuf_size = DEFAULT_CRBUF_SIZE, + int uwbuf_size = DEFAULT_UWBUF_SIZE, + int cwbuf_size = DEFAULT_CWBUF_SIZE) : + transport_(transport), + standalone_(!use_for_rpc), + urpos_(0), + uwpos_(0), + input_ended_(false), + output_flushed_(false), + urbuf_size_(urbuf_size), + crbuf_size_(crbuf_size), + uwbuf_size_(uwbuf_size), + cwbuf_size_(cwbuf_size), + urbuf_(NULL), + crbuf_(NULL), + uwbuf_(NULL), + cwbuf_(NULL), + rstream_(NULL), + wstream_(NULL) + { + + if (!standalone_) { + throw TTransportException( + TTransportException::BAD_ARGS, + "TZLibTransport has not been tested for RPC."); + } + + if (uwbuf_size_ < MIN_DIRECT_DEFLATE_SIZE) { + // Have to copy this into a local because of a linking issue. + int minimum = MIN_DIRECT_DEFLATE_SIZE; + throw TTransportException( + TTransportException::BAD_ARGS, + "TZLibTransport: uncompressed write buffer must be at least" + + boost::lexical_cast(minimum) + "."); + } + + try { + urbuf_ = new uint8_t[urbuf_size]; + crbuf_ = new uint8_t[crbuf_size]; + uwbuf_ = new uint8_t[uwbuf_size]; + cwbuf_ = new uint8_t[cwbuf_size]; + + // Don't call this outside of the constructor. + initZlib(); + + } catch (...) { + delete[] urbuf_; + delete[] crbuf_; + delete[] uwbuf_; + delete[] cwbuf_; + throw; + } + } + + // Don't call this outside of the constructor. + void initZlib(); + + ~TZlibTransport(); + + bool isOpen(); + + void open() { + transport_->open(); + } + + void close() { + transport_->close(); + } + + uint32_t read(uint8_t* buf, uint32_t len); + + void write(const uint8_t* buf, uint32_t len); + + void flush(); + + bool borrow(uint8_t* buf, uint32_t len); + + void consume(uint32_t len); + + void verifyChecksum(); + + /** + * TODO(someone_smart): Choose smart defaults. + */ + static const int DEFAULT_URBUF_SIZE = 128; + static const int DEFAULT_CRBUF_SIZE = 1024; + static const int DEFAULT_UWBUF_SIZE = 128; + static const int DEFAULT_CWBUF_SIZE = 1024; + + protected: + + inline void checkZlibRv(int status, const char* msg); + inline void checkZlibRvNothrow(int status, const char* msg); + inline int readAvail(); + void flushToZlib(const uint8_t* buf, int len, bool finish = false); + + // Writes smaller than this are buffered up. + // Larger (or equal) writes are dumped straight to zlib. + static const int MIN_DIRECT_DEFLATE_SIZE = 32; + + boost::shared_ptr transport_; + bool standalone_; + + int urpos_; + int uwpos_; + + /// True iff zlib has reached the end of a stream. + /// This is only ever true in standalone protcol objects. + bool input_ended_; + /// True iff we have flushed the output stream. + /// This is only ever true in standalone protcol objects. + bool output_flushed_; + + int urbuf_size_; + int crbuf_size_; + int uwbuf_size_; + int cwbuf_size_; + + uint8_t* urbuf_; + uint8_t* crbuf_; + uint8_t* uwbuf_; + uint8_t* cwbuf_; + + struct z_stream_s* rstream_; + struct z_stream_s* wstream_; +}; + +}}} // facebook::thrift::transport + +#endif // #ifndef _THRIFT_TRANSPORT_TZLIBTRANSPORT_H_ +// Copyright (c) 2006- Facebook +// Distributed under the Thrift Software License +// +// See accompanying file LICENSE or visit the Thrift site at: +// http://developers.facebook.com/thrift/ + +#ifndef _THRIFT_TRANSPORT_TZLIBTRANSPORT_H_ +#define _THRIFT_TRANSPORT_TZLIBTRANSPORT_H_ 1 + +#include +#include + +struct z_stream_s; + +namespace facebook { namespace thrift { namespace transport { + +class TZlibTransportException : public TTransportException { + public: + TZlibTransportException(int status, const char* msg) : + TTransportException(TTransportException::INTERNAL_ERROR, + errorMessage(status, msg)), + zlib_status_(status), + zlib_msg_(msg == NULL ? "(null)" : msg) {} + + virtual ~TZlibTransportException() throw() {} + + int getZlibStatus() { return zlib_status_; } + std::string getZlibMessage() { return zlib_msg_; } + + static std::string errorMessage(int status, const char* msg) { + std::string rv = "zlib error: "; + if (msg) { + rv += msg; + } else { + rv += "(no message)"; + } + rv += " (status = "; + rv += boost::lexical_cast(status); + rv += ")"; + return rv; + } + + int zlib_status_; + std::string zlib_msg_; +}; + +/** + * This transport uses zlib's compressed format on the "far" side. + * + * There are two kinds of TZlibTransport objects: + * - Standalone objects are used to encode self-contained chunks of data + * (like structures). They include checksums. + * - Non-standalone transports are used for RPC. They are not implemented yet. + * + * TODO(dreiss): Don't do an extra copy of the compressed data if + * the underlying transport is TBuffered or TMemory. + * + * @author David Reiss + */ +class TZlibTransport : public TTransport { + public: + + /** + * @param transport The transport to read compressed data from + * and write compressed data to. + * @param use_for_rpc True if this object will be used for RPC, + * false if this is a standalone object. + * @param urbuf_size Uncompressed buffer size for reading. + * @param crbuf_size Compressed buffer size for reading. + * @param uwbuf_size Uncompressed buffer size for writing. + * @param cwbuf_size Compressed buffer size for writing. + * + * TODO(dreiss): Write a constructor that isn't a pain. + */ + TZlibTransport(boost::shared_ptr transport, + bool use_for_rpc, + int urbuf_size = DEFAULT_URBUF_SIZE, + int crbuf_size = DEFAULT_CRBUF_SIZE, + int uwbuf_size = DEFAULT_UWBUF_SIZE, + int cwbuf_size = DEFAULT_CWBUF_SIZE) : + transport_(transport), + standalone_(!use_for_rpc), + urpos_(0), + uwpos_(0), + input_ended_(false), + output_flushed_(false), + urbuf_size_(urbuf_size), + crbuf_size_(crbuf_size), + uwbuf_size_(uwbuf_size), + cwbuf_size_(cwbuf_size), + urbuf_(NULL), + crbuf_(NULL), + uwbuf_(NULL), + cwbuf_(NULL), + rstream_(NULL), + wstream_(NULL) + { + + if (!standalone_) { + throw TTransportException( + TTransportException::BAD_ARGS, + "TZLibTransport has not been tested for RPC."); + } + + if (uwbuf_size_ < MIN_DIRECT_DEFLATE_SIZE) { + // Have to copy this into a local because of a linking issue. + int minimum = MIN_DIRECT_DEFLATE_SIZE; + throw TTransportException( + TTransportException::BAD_ARGS, + "TZLibTransport: uncompressed write buffer must be at least" + + boost::lexical_cast(minimum) + "."); + } + + try { + urbuf_ = new uint8_t[urbuf_size]; + crbuf_ = new uint8_t[crbuf_size]; + uwbuf_ = new uint8_t[uwbuf_size]; + cwbuf_ = new uint8_t[cwbuf_size]; + + // Don't call this outside of the constructor. + initZlib(); + + } catch (...) { + delete[] urbuf_; + delete[] crbuf_; + delete[] uwbuf_; + delete[] cwbuf_; + throw; + } + } + + // Don't call this outside of the constructor. + void initZlib(); + + ~TZlibTransport(); + + bool isOpen(); + + void open() { + transport_->open(); + } + + void close() { + transport_->close(); + } + + uint32_t read(uint8_t* buf, uint32_t len); + + void write(const uint8_t* buf, uint32_t len); + + void flush(); + + bool borrow(uint8_t* buf, uint32_t len); + + void consume(uint32_t len); + + void verifyChecksum(); + + /** + * TODO(someone_smart): Choose smart defaults. + */ + static const int DEFAULT_URBUF_SIZE = 128; + static const int DEFAULT_CRBUF_SIZE = 1024; + static const int DEFAULT_UWBUF_SIZE = 128; + static const int DEFAULT_CWBUF_SIZE = 1024; + + protected: + + inline void checkZlibRv(int status, const char* msg); + inline void checkZlibRvNothrow(int status, const char* msg); + inline int readAvail(); + void flushToZlib(const uint8_t* buf, int len, bool finish = false); + + // Writes smaller than this are buffered up. + // Larger (or equal) writes are dumped straight to zlib. + static const int MIN_DIRECT_DEFLATE_SIZE = 32; + + boost::shared_ptr transport_; + bool standalone_; + + int urpos_; + int uwpos_; + + /// True iff zlib has reached the end of a stream. + /// This is only ever true in standalone protcol objects. + bool input_ended_; + /// True iff we have flushed the output stream. + /// This is only ever true in standalone protcol objects. + bool output_flushed_; + + int urbuf_size_; + int crbuf_size_; + int uwbuf_size_; + int cwbuf_size_; + + uint8_t* urbuf_; + uint8_t* crbuf_; + uint8_t* uwbuf_; + uint8_t* cwbuf_; + + struct z_stream_s* rstream_; + struct z_stream_s* wstream_; +}; + +}}} // facebook::thrift::transport + +#endif // #ifndef _THRIFT_TRANSPORT_TZLIBTRANSPORT_H_ Index: service/include/thrift/transport/THttpClient.h =================================================================== --- service/include/thrift/transport/THttpClient.h (revision 0) +++ service/include/thrift/transport/THttpClient.h (revision 0) @@ -0,0 +1,198 @@ +// Copyright (c) 2006- Facebook +// Distributed under the Thrift Software License +// +// See accompanying file LICENSE or visit the Thrift site at: +// http://developers.facebook.com/thrift/ + +#ifndef _THRIFT_TRANSPORT_THTTPCLIENT_H_ +#define _THRIFT_TRANSPORT_THTTPCLIENT_H_ 1 + +#include + +namespace facebook { namespace thrift { namespace transport { + +/** + * HTTP client implementation of the thrift transport. This was irritating + * to write, but the alternatives in C++ land are daunting. Linking CURL + * requires 23 dynamic libraries last time I checked (WTF?!?). All we have + * here is a VERY basic HTTP/1.1 client which supports HTTP 100 Continue, + * chunked transfer encoding, keepalive, etc. Tested against Apache. + * + * @author Mark Slee + */ +class THttpClient : public TTransport { + public: + THttpClient(boost::shared_ptr transport, std::string host, std::string path=""); + + THttpClient(std::string host, int port, std::string path=""); + + virtual ~THttpClient(); + + void open() { + transport_->open(); + } + + bool isOpen() { + return transport_->isOpen(); + } + + bool peek() { + return transport_->peek(); + } + + void close() { + transport_->close(); + } + + uint32_t read(uint8_t* buf, uint32_t len); + + void readEnd(); + + void write(const uint8_t* buf, uint32_t len); + + void flush(); + + private: + void init(); + + protected: + + boost::shared_ptr transport_; + + TMemoryBuffer writeBuffer_; + TMemoryBuffer readBuffer_; + + std::string host_; + std::string path_; + + bool readHeaders_; + bool chunked_; + bool chunkedDone_; + uint32_t chunkSize_; + uint32_t contentLength_; + + char* httpBuf_; + uint32_t httpPos_; + uint32_t httpBufLen_; + uint32_t httpBufSize_; + + uint32_t readMoreData(); + char* readLine(); + + void readHeaders(); + void parseHeader(char* header); + bool parseStatusLine(char* status); + + uint32_t readChunked(); + void readChunkedFooters(); + uint32_t parseChunkSize(char* line); + + uint32_t readContent(uint32_t size); + + void refill(); + void shift(); + +}; + +}}} // facebook::thrift::transport + +#endif // #ifndef _THRIFT_TRANSPORT_THTTPCLIENT_H_ +// Copyright (c) 2006- Facebook +// Distributed under the Thrift Software License +// +// See accompanying file LICENSE or visit the Thrift site at: +// http://developers.facebook.com/thrift/ + +#ifndef _THRIFT_TRANSPORT_THTTPCLIENT_H_ +#define _THRIFT_TRANSPORT_THTTPCLIENT_H_ 1 + +#include + +namespace facebook { namespace thrift { namespace transport { + +/** + * HTTP client implementation of the thrift transport. This was irritating + * to write, but the alternatives in C++ land are daunting. Linking CURL + * requires 23 dynamic libraries last time I checked (WTF?!?). All we have + * here is a VERY basic HTTP/1.1 client which supports HTTP 100 Continue, + * chunked transfer encoding, keepalive, etc. Tested against Apache. + * + * @author Mark Slee + */ +class THttpClient : public TTransport { + public: + THttpClient(boost::shared_ptr transport, std::string host, std::string path=""); + + THttpClient(std::string host, int port, std::string path=""); + + virtual ~THttpClient(); + + void open() { + transport_->open(); + } + + bool isOpen() { + return transport_->isOpen(); + } + + bool peek() { + return transport_->peek(); + } + + void close() { + transport_->close(); + } + + uint32_t read(uint8_t* buf, uint32_t len); + + void readEnd(); + + void write(const uint8_t* buf, uint32_t len); + + void flush(); + + private: + void init(); + + protected: + + boost::shared_ptr transport_; + + TMemoryBuffer writeBuffer_; + TMemoryBuffer readBuffer_; + + std::string host_; + std::string path_; + + bool readHeaders_; + bool chunked_; + bool chunkedDone_; + uint32_t chunkSize_; + uint32_t contentLength_; + + char* httpBuf_; + uint32_t httpPos_; + uint32_t httpBufLen_; + uint32_t httpBufSize_; + + uint32_t readMoreData(); + char* readLine(); + + void readHeaders(); + void parseHeader(char* header); + bool parseStatusLine(char* status); + + uint32_t readChunked(); + void readChunkedFooters(); + uint32_t parseChunkSize(char* line); + + uint32_t readContent(uint32_t size); + + void refill(); + void shift(); + +}; + +}}} // facebook::thrift::transport + +#endif // #ifndef _THRIFT_TRANSPORT_THTTPCLIENT_H_ Index: service/include/thrift/transport/TServerSocket.h =================================================================== --- service/include/thrift/transport/TServerSocket.h (revision 0) +++ service/include/thrift/transport/TServerSocket.h (revision 0) @@ -0,0 +1,118 @@ +// Copyright (c) 2006- Facebook +// Distributed under the Thrift Software License +// +// See accompanying file LICENSE or visit the Thrift site at: +// http://developers.facebook.com/thrift/ + +#ifndef _THRIFT_TRANSPORT_TSERVERSOCKET_H_ +#define _THRIFT_TRANSPORT_TSERVERSOCKET_H_ 1 + +#include "TServerTransport.h" +#include + +namespace facebook { namespace thrift { namespace transport { + +class TSocket; + +/** + * Server socket implementation of TServerTransport. Wrapper around a unix + * socket listen and accept calls. + * + * @author Mark Slee + */ +class TServerSocket : public TServerTransport { + public: + TServerSocket(int port); + TServerSocket(int port, int sendTimeout, int recvTimeout); + + ~TServerSocket(); + + void setSendTimeout(int sendTimeout); + void setRecvTimeout(int recvTimeout); + + void setRetryLimit(int retryLimit); + void setRetryDelay(int retryDelay); + + void listen(); + void close(); + + void interrupt(); + + protected: + boost::shared_ptr acceptImpl(); + + private: + int port_; + int serverSocket_; + int acceptBacklog_; + int sendTimeout_; + int recvTimeout_; + int retryLimit_; + int retryDelay_; + + int intSock1_; + int intSock2_; +}; + +}}} // facebook::thrift::transport + +#endif // #ifndef _THRIFT_TRANSPORT_TSERVERSOCKET_H_ +// Copyright (c) 2006- Facebook +// Distributed under the Thrift Software License +// +// See accompanying file LICENSE or visit the Thrift site at: +// http://developers.facebook.com/thrift/ + +#ifndef _THRIFT_TRANSPORT_TSERVERSOCKET_H_ +#define _THRIFT_TRANSPORT_TSERVERSOCKET_H_ 1 + +#include "TServerTransport.h" +#include + +namespace facebook { namespace thrift { namespace transport { + +class TSocket; + +/** + * Server socket implementation of TServerTransport. Wrapper around a unix + * socket listen and accept calls. + * + * @author Mark Slee + */ +class TServerSocket : public TServerTransport { + public: + TServerSocket(int port); + TServerSocket(int port, int sendTimeout, int recvTimeout); + + ~TServerSocket(); + + void setSendTimeout(int sendTimeout); + void setRecvTimeout(int recvTimeout); + + void setRetryLimit(int retryLimit); + void setRetryDelay(int retryDelay); + + void listen(); + void close(); + + void interrupt(); + + protected: + boost::shared_ptr acceptImpl(); + + private: + int port_; + int serverSocket_; + int acceptBacklog_; + int sendTimeout_; + int recvTimeout_; + int retryLimit_; + int retryDelay_; + + int intSock1_; + int intSock2_; +}; + +}}} // facebook::thrift::transport + +#endif // #ifndef _THRIFT_TRANSPORT_TSERVERSOCKET_H_ Index: service/include/thrift/transport/TSocketPool.h =================================================================== --- service/include/thrift/transport/TSocketPool.h (revision 0) +++ service/include/thrift/transport/TSocketPool.h (revision 0) @@ -0,0 +1,226 @@ +// Copyright (c) 2006- Facebook +// Distributed under the Thrift Software License +// +// See accompanying file LICENSE or visit the Thrift site at: +// http://developers.facebook.com/thrift/ + +#ifndef _THRIFT_TRANSPORT_TSOCKETPOOL_H_ +#define _THRIFT_TRANSPORT_TSOCKETPOOL_H_ 1 + +#include +#include "TSocket.h" + +namespace facebook { namespace thrift { namespace transport { + +/** + * TCP Socket implementation of the TTransport interface. + * + * @author Mark Slee + */ +class TSocketPool : public TSocket { + + public: + /** + * Socket pool constructor + * + * @param hosts list of host names + * @param ports list of port names + */ + TSocketPool(const std::vector &hosts, + const std::vector &ports); + + /** + * Socket pool constructor + * + * @param servers list of pairs of host name and port + */ + TSocketPool(const std::vector > servers); + + /** + * Socket pool constructor + * + * @param host single host + * @param port single port + */ + TSocketPool(const std::string& host, int port); + + /** + * Destroyes the socket object, closing it if necessary. + */ + virtual ~TSocketPool(); + + /** + * Add a server to the pool + */ + void addServer(const std::string& host, int port); + + /** + * Sets how many times to keep retrying a host in the connect function. + */ + void setNumRetries(int numRetries); + + /** + * Sets how long to wait until retrying a host if it was marked down + */ + void setRetryInterval(int retryInterval); + + /** + * Sets how many times to keep retrying a host before marking it as down. + */ + void setMaxConsecutiveFailures(int maxConsecutiveFailures); + + /** + * Turns randomization in connect order on or off. + */ + void setRandomize(bool randomize); + + /** + * Whether to always try the last server. + */ + void setAlwaysTryLast(bool alwaysTryLast); + + /** + * Creates and opens the UNIX socket. + */ + void open(); + + protected: + + /** List of servers to connect to */ + std::vector > servers_; + + /** How many times to retry each host in connect */ + int numRetries_; + + /** Retry interval in seconds, how long to not try a host if it has been + * marked as down. + */ + int retryInterval_; + + /** Max consecutive failures before marking a host down. */ + int maxConsecutiveFailures_; + + /** Try hosts in order? or Randomized? */ + bool randomize_; + + /** Always try last host, even if marked down? */ + bool alwaysTryLast_; +}; + +}}} // facebook::thrift::transport + +#endif // #ifndef _THRIFT_TRANSPORT_TSOCKETPOOL_H_ + +// Copyright (c) 2006- Facebook +// Distributed under the Thrift Software License +// +// See accompanying file LICENSE or visit the Thrift site at: +// http://developers.facebook.com/thrift/ + +#ifndef _THRIFT_TRANSPORT_TSOCKETPOOL_H_ +#define _THRIFT_TRANSPORT_TSOCKETPOOL_H_ 1 + +#include +#include "TSocket.h" + +namespace facebook { namespace thrift { namespace transport { + +/** + * TCP Socket implementation of the TTransport interface. + * + * @author Mark Slee + */ +class TSocketPool : public TSocket { + + public: + /** + * Socket pool constructor + * + * @param hosts list of host names + * @param ports list of port names + */ + TSocketPool(const std::vector &hosts, + const std::vector &ports); + + /** + * Socket pool constructor + * + * @param servers list of pairs of host name and port + */ + TSocketPool(const std::vector > servers); + + /** + * Socket pool constructor + * + * @param host single host + * @param port single port + */ + TSocketPool(const std::string& host, int port); + + /** + * Destroyes the socket object, closing it if necessary. + */ + virtual ~TSocketPool(); + + /** + * Add a server to the pool + */ + void addServer(const std::string& host, int port); + + /** + * Sets how many times to keep retrying a host in the connect function. + */ + void setNumRetries(int numRetries); + + /** + * Sets how long to wait until retrying a host if it was marked down + */ + void setRetryInterval(int retryInterval); + + /** + * Sets how many times to keep retrying a host before marking it as down. + */ + void setMaxConsecutiveFailures(int maxConsecutiveFailures); + + /** + * Turns randomization in connect order on or off. + */ + void setRandomize(bool randomize); + + /** + * Whether to always try the last server. + */ + void setAlwaysTryLast(bool alwaysTryLast); + + /** + * Creates and opens the UNIX socket. + */ + void open(); + + protected: + + /** List of servers to connect to */ + std::vector > servers_; + + /** How many times to retry each host in connect */ + int numRetries_; + + /** Retry interval in seconds, how long to not try a host if it has been + * marked as down. + */ + int retryInterval_; + + /** Max consecutive failures before marking a host down. */ + int maxConsecutiveFailures_; + + /** Try hosts in order? or Randomized? */ + bool randomize_; + + /** Always try last host, even if marked down? */ + bool alwaysTryLast_; +}; + +}}} // facebook::thrift::transport + +#endif // #ifndef _THRIFT_TRANSPORT_TSOCKETPOOL_H_ + Index: service/include/thrift/transport/TServerTransport.h =================================================================== --- service/include/thrift/transport/TServerTransport.h (revision 0) +++ service/include/thrift/transport/TServerTransport.h (revision 0) @@ -0,0 +1,160 @@ +// Copyright (c) 2006- Facebook +// Distributed under the Thrift Software License +// +// See accompanying file LICENSE or visit the Thrift site at: +// http://developers.facebook.com/thrift/ + +#ifndef _THRIFT_TRANSPORT_TSERVERTRANSPORT_H_ +#define _THRIFT_TRANSPORT_TSERVERTRANSPORT_H_ 1 + +#include "TTransport.h" +#include "TTransportException.h" +#include + +namespace facebook { namespace thrift { namespace transport { + +/** + * Server transport framework. A server needs to have some facility for + * creating base transports to read/write from. + * + * @author Mark Slee + */ +class TServerTransport { + public: + virtual ~TServerTransport() {} + + /** + * Starts the server transport listening for new connections. Prior to this + * call most transports will not return anything when accept is called. + * + * @throws TTransportException if we were unable to listen + */ + virtual void listen() {} + + /** + * Gets a new dynamically allocated transport object and passes it to the + * caller. Note that it is the explicit duty of the caller to free the + * allocated object. The returned TTransport object must always be in the + * opened state. NULL should never be returned, instead an Exception should + * always be thrown. + * + * @return A new TTransport object + * @throws TTransportException if there is an error + */ + boost::shared_ptr accept() { + boost::shared_ptr result = acceptImpl(); + if (result == NULL) { + throw TTransportException("accept() may not return NULL"); + } + return result; + } + + /** + * For "smart" TServerTransport implementations that work in a multi + * threaded context this can be used to break out of an accept() call. + * It is expected that the transport will throw a TTransportException + * with the interrupted error code. + */ + virtual void interrupt() {} + + /** + * Closes this transport such that future calls to accept will do nothing. + */ + virtual void close() = 0; + + protected: + TServerTransport() {} + + /** + * Subclasses should implement this function for accept. + * + * @return A newly allocated TTransport object + * @throw TTransportException If an error occurs + */ + virtual boost::shared_ptr acceptImpl() = 0; + +}; + +}}} // facebook::thrift::transport + +#endif // #ifndef _THRIFT_TRANSPORT_TSERVERTRANSPORT_H_ +// Copyright (c) 2006- Facebook +// Distributed under the Thrift Software License +// +// See accompanying file LICENSE or visit the Thrift site at: +// http://developers.facebook.com/thrift/ + +#ifndef _THRIFT_TRANSPORT_TSERVERTRANSPORT_H_ +#define _THRIFT_TRANSPORT_TSERVERTRANSPORT_H_ 1 + +#include "TTransport.h" +#include "TTransportException.h" +#include + +namespace facebook { namespace thrift { namespace transport { + +/** + * Server transport framework. A server needs to have some facility for + * creating base transports to read/write from. + * + * @author Mark Slee + */ +class TServerTransport { + public: + virtual ~TServerTransport() {} + + /** + * Starts the server transport listening for new connections. Prior to this + * call most transports will not return anything when accept is called. + * + * @throws TTransportException if we were unable to listen + */ + virtual void listen() {} + + /** + * Gets a new dynamically allocated transport object and passes it to the + * caller. Note that it is the explicit duty of the caller to free the + * allocated object. The returned TTransport object must always be in the + * opened state. NULL should never be returned, instead an Exception should + * always be thrown. + * + * @return A new TTransport object + * @throws TTransportException if there is an error + */ + boost::shared_ptr accept() { + boost::shared_ptr result = acceptImpl(); + if (result == NULL) { + throw TTransportException("accept() may not return NULL"); + } + return result; + } + + /** + * For "smart" TServerTransport implementations that work in a multi + * threaded context this can be used to break out of an accept() call. + * It is expected that the transport will throw a TTransportException + * with the interrupted error code. + */ + virtual void interrupt() {} + + /** + * Closes this transport such that future calls to accept will do nothing. + */ + virtual void close() = 0; + + protected: + TServerTransport() {} + + /** + * Subclasses should implement this function for accept. + * + * @return A newly allocated TTransport object + * @throw TTransportException If an error occurs + */ + virtual boost::shared_ptr acceptImpl() = 0; + +}; + +}}} // facebook::thrift::transport + +#endif // #ifndef _THRIFT_TRANSPORT_TSERVERTRANSPORT_H_ Index: service/include/thrift/fb303/fb303_constants.h =================================================================== --- service/include/thrift/fb303/fb303_constants.h (revision 0) +++ service/include/thrift/fb303/fb303_constants.h (revision 0) @@ -0,0 +1,46 @@ +/** + * Autogenerated by Thrift + * + * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING + */ +#ifndef fb303_CONSTANTS_H +#define fb303_CONSTANTS_H + +#include "fb303_types.h" + +namespace facebook { namespace fb303 { + +class fb303Constants { + public: + fb303Constants(); + +}; + +extern const fb303Constants g_fb303_constants; + +}} // namespace + +#endif +/** + * Autogenerated by Thrift + * + * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING + */ +#ifndef fb303_CONSTANTS_H +#define fb303_CONSTANTS_H + +#include "fb303_types.h" + +namespace facebook { namespace fb303 { + +class fb303Constants { + public: + fb303Constants(); + +}; + +extern const fb303Constants g_fb303_constants; + +}} // namespace + +#endif Index: service/include/thrift/fb303/FacebookService.h =================================================================== --- service/include/thrift/fb303/FacebookService.h (revision 0) +++ service/include/thrift/fb303/FacebookService.h (revision 0) @@ -0,0 +1,3166 @@ +/** + * Autogenerated by Thrift + * + * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING + */ +#ifndef FacebookService_H +#define FacebookService_H + +#include +#include "fb303_types.h" + +namespace facebook { namespace fb303 { + +class FacebookServiceIf { + public: + virtual ~FacebookServiceIf() {} + virtual void getName(std::string& _return) = 0; + virtual void getVersion(std::string& _return) = 0; + virtual fb_status getStatus() = 0; + virtual void getStatusDetails(std::string& _return) = 0; + virtual void getCounters(std::map & _return) = 0; + virtual int64_t getCounter(const std::string& key) = 0; + virtual void setOption(const std::string& key, const std::string& value) = 0; + virtual void getOption(std::string& _return, const std::string& key) = 0; + virtual void getOptions(std::map & _return) = 0; + virtual int64_t aliveSince() = 0; + virtual void getLimitedReflection(facebook::thrift::reflection::limited::Service& _return) = 0; + virtual void reinitialize() = 0; + virtual void shutdown() = 0; + virtual void getSingleTimeseries(std::map & _return, const std::string& name, const int32_t series_length) = 0; + virtual void getTimeseries(std::map > & _return, const int32_t series_length) = 0; +}; + +class FacebookServiceNull : virtual public FacebookServiceIf { + public: + virtual ~FacebookServiceNull() {} + void getName(std::string& /* _return */) { + return; + } + void getVersion(std::string& /* _return */) { + return; + } + fb_status getStatus() { + fb_status _return = (fb_status)0; + return _return; + } + void getStatusDetails(std::string& /* _return */) { + return; + } + void getCounters(std::map & /* _return */) { + return; + } + int64_t getCounter(const std::string& /* key */) { + int64_t _return = 0; + return _return; + } + void setOption(const std::string& /* key */, const std::string& /* value */) { + return; + } + void getOption(std::string& /* _return */, const std::string& /* key */) { + return; + } + void getOptions(std::map & /* _return */) { + return; + } + int64_t aliveSince() { + int64_t _return = 0; + return _return; + } + void getLimitedReflection(facebook::thrift::reflection::limited::Service& /* _return */) { + return; + } + void reinitialize() { + return; + } + void shutdown() { + return; + } + void getSingleTimeseries(std::map & /* _return */, const std::string& /* name */, const int32_t /* series_length */) { + return; + } + void getTimeseries(std::map > & /* _return */, const int32_t /* series_length */) { + return; + } +}; + +class FacebookService_getName_args { + public: + + FacebookService_getName_args() { + } + + virtual ~FacebookService_getName_args() throw() {} + + + bool operator == (const FacebookService_getName_args & /* rhs */) const + { + return true; + } + bool operator != (const FacebookService_getName_args &rhs) const { + return !(*this == rhs); + } + + bool operator < (const FacebookService_getName_args & ) const; + + uint32_t read(facebook::thrift::protocol::TProtocol* iprot); + uint32_t write(facebook::thrift::protocol::TProtocol* oprot) const; + +}; + +class FacebookService_getName_pargs { + public: + + + virtual ~FacebookService_getName_pargs() throw() {} + + + uint32_t write(facebook::thrift::protocol::TProtocol* oprot) const; + +}; + +class FacebookService_getName_result { + public: + + FacebookService_getName_result() : success("") { + } + + virtual ~FacebookService_getName_result() throw() {} + + std::string success; + + struct __isset { + __isset() : success(false) {} + bool success; + } __isset; + + bool operator == (const FacebookService_getName_result & rhs) const + { + if (!(success == rhs.success)) + return false; + return true; + } + bool operator != (const FacebookService_getName_result &rhs) const { + return !(*this == rhs); + } + + bool operator < (const FacebookService_getName_result & ) const; + + uint32_t read(facebook::thrift::protocol::TProtocol* iprot); + uint32_t write(facebook::thrift::protocol::TProtocol* oprot) const; + +}; + +class FacebookService_getName_presult { + public: + + + virtual ~FacebookService_getName_presult() throw() {} + + std::string* success; + + struct __isset { + __isset() : success(false) {} + bool success; + } __isset; + + uint32_t read(facebook::thrift::protocol::TProtocol* iprot); + +}; + +class FacebookService_getVersion_args { + public: + + FacebookService_getVersion_args() { + } + + virtual ~FacebookService_getVersion_args() throw() {} + + + bool operator == (const FacebookService_getVersion_args & /* rhs */) const + { + return true; + } + bool operator != (const FacebookService_getVersion_args &rhs) const { + return !(*this == rhs); + } + + bool operator < (const FacebookService_getVersion_args & ) const; + + uint32_t read(facebook::thrift::protocol::TProtocol* iprot); + uint32_t write(facebook::thrift::protocol::TProtocol* oprot) const; + +}; + +class FacebookService_getVersion_pargs { + public: + + + virtual ~FacebookService_getVersion_pargs() throw() {} + + + uint32_t write(facebook::thrift::protocol::TProtocol* oprot) const; + +}; + +class FacebookService_getVersion_result { + public: + + FacebookService_getVersion_result() : success("") { + } + + virtual ~FacebookService_getVersion_result() throw() {} + + std::string success; + + struct __isset { + __isset() : success(false) {} + bool success; + } __isset; + + bool operator == (const FacebookService_getVersion_result & rhs) const + { + if (!(success == rhs.success)) + return false; + return true; + } + bool operator != (const FacebookService_getVersion_result &rhs) const { + return !(*this == rhs); + } + + bool operator < (const FacebookService_getVersion_result & ) const; + + uint32_t read(facebook::thrift::protocol::TProtocol* iprot); + uint32_t write(facebook::thrift::protocol::TProtocol* oprot) const; + +}; + +class FacebookService_getVersion_presult { + public: + + + virtual ~FacebookService_getVersion_presult() throw() {} + + std::string* success; + + struct __isset { + __isset() : success(false) {} + bool success; + } __isset; + + uint32_t read(facebook::thrift::protocol::TProtocol* iprot); + +}; + +class FacebookService_getStatus_args { + public: + + FacebookService_getStatus_args() { + } + + virtual ~FacebookService_getStatus_args() throw() {} + + + bool operator == (const FacebookService_getStatus_args & /* rhs */) const + { + return true; + } + bool operator != (const FacebookService_getStatus_args &rhs) const { + return !(*this == rhs); + } + + bool operator < (const FacebookService_getStatus_args & ) const; + + uint32_t read(facebook::thrift::protocol::TProtocol* iprot); + uint32_t write(facebook::thrift::protocol::TProtocol* oprot) const; + +}; + +class FacebookService_getStatus_pargs { + public: + + + virtual ~FacebookService_getStatus_pargs() throw() {} + + + uint32_t write(facebook::thrift::protocol::TProtocol* oprot) const; + +}; + +class FacebookService_getStatus_result { + public: + + FacebookService_getStatus_result() { + } + + virtual ~FacebookService_getStatus_result() throw() {} + + fb_status success; + + struct __isset { + __isset() : success(false) {} + bool success; + } __isset; + + bool operator == (const FacebookService_getStatus_result & rhs) const + { + if (!(success == rhs.success)) + return false; + return true; + } + bool operator != (const FacebookService_getStatus_result &rhs) const { + return !(*this == rhs); + } + + bool operator < (const FacebookService_getStatus_result & ) const; + + uint32_t read(facebook::thrift::protocol::TProtocol* iprot); + uint32_t write(facebook::thrift::protocol::TProtocol* oprot) const; + +}; + +class FacebookService_getStatus_presult { + public: + + + virtual ~FacebookService_getStatus_presult() throw() {} + + fb_status* success; + + struct __isset { + __isset() : success(false) {} + bool success; + } __isset; + + uint32_t read(facebook::thrift::protocol::TProtocol* iprot); + +}; + +class FacebookService_getStatusDetails_args { + public: + + FacebookService_getStatusDetails_args() { + } + + virtual ~FacebookService_getStatusDetails_args() throw() {} + + + bool operator == (const FacebookService_getStatusDetails_args & /* rhs */) const + { + return true; + } + bool operator != (const FacebookService_getStatusDetails_args &rhs) const { + return !(*this == rhs); + } + + bool operator < (const FacebookService_getStatusDetails_args & ) const; + + uint32_t read(facebook::thrift::protocol::TProtocol* iprot); + uint32_t write(facebook::thrift::protocol::TProtocol* oprot) const; + +}; + +class FacebookService_getStatusDetails_pargs { + public: + + + virtual ~FacebookService_getStatusDetails_pargs() throw() {} + + + uint32_t write(facebook::thrift::protocol::TProtocol* oprot) const; + +}; + +class FacebookService_getStatusDetails_result { + public: + + FacebookService_getStatusDetails_result() : success("") { + } + + virtual ~FacebookService_getStatusDetails_result() throw() {} + + std::string success; + + struct __isset { + __isset() : success(false) {} + bool success; + } __isset; + + bool operator == (const FacebookService_getStatusDetails_result & rhs) const + { + if (!(success == rhs.success)) + return false; + return true; + } + bool operator != (const FacebookService_getStatusDetails_result &rhs) const { + return !(*this == rhs); + } + + bool operator < (const FacebookService_getStatusDetails_result & ) const; + + uint32_t read(facebook::thrift::protocol::TProtocol* iprot); + uint32_t write(facebook::thrift::protocol::TProtocol* oprot) const; + +}; + +class FacebookService_getStatusDetails_presult { + public: + + + virtual ~FacebookService_getStatusDetails_presult() throw() {} + + std::string* success; + + struct __isset { + __isset() : success(false) {} + bool success; + } __isset; + + uint32_t read(facebook::thrift::protocol::TProtocol* iprot); + +}; + +class FacebookService_getCounters_args { + public: + + FacebookService_getCounters_args() { + } + + virtual ~FacebookService_getCounters_args() throw() {} + + + bool operator == (const FacebookService_getCounters_args & /* rhs */) const + { + return true; + } + bool operator != (const FacebookService_getCounters_args &rhs) const { + return !(*this == rhs); + } + + bool operator < (const FacebookService_getCounters_args & ) const; + + uint32_t read(facebook::thrift::protocol::TProtocol* iprot); + uint32_t write(facebook::thrift::protocol::TProtocol* oprot) const; + +}; + +class FacebookService_getCounters_pargs { + public: + + + virtual ~FacebookService_getCounters_pargs() throw() {} + + + uint32_t write(facebook::thrift::protocol::TProtocol* oprot) const; + +}; + +class FacebookService_getCounters_result { + public: + + FacebookService_getCounters_result() { + } + + virtual ~FacebookService_getCounters_result() throw() {} + + std::map success; + + struct __isset { + __isset() : success(false) {} + bool success; + } __isset; + + bool operator == (const FacebookService_getCounters_result & rhs) const + { + if (!(success == rhs.success)) + return false; + return true; + } + bool operator != (const FacebookService_getCounters_result &rhs) const { + return !(*this == rhs); + } + + bool operator < (const FacebookService_getCounters_result & ) const; + + uint32_t read(facebook::thrift::protocol::TProtocol* iprot); + uint32_t write(facebook::thrift::protocol::TProtocol* oprot) const; + +}; + +class FacebookService_getCounters_presult { + public: + + + virtual ~FacebookService_getCounters_presult() throw() {} + + std::map * success; + + struct __isset { + __isset() : success(false) {} + bool success; + } __isset; + + uint32_t read(facebook::thrift::protocol::TProtocol* iprot); + +}; + +class FacebookService_getCounter_args { + public: + + FacebookService_getCounter_args() : key("") { + } + + virtual ~FacebookService_getCounter_args() throw() {} + + std::string key; + + struct __isset { + __isset() : key(false) {} + bool key; + } __isset; + + bool operator == (const FacebookService_getCounter_args & rhs) const + { + if (!(key == rhs.key)) + return false; + return true; + } + bool operator != (const FacebookService_getCounter_args &rhs) const { + return !(*this == rhs); + } + + bool operator < (const FacebookService_getCounter_args & ) const; + + uint32_t read(facebook::thrift::protocol::TProtocol* iprot); + uint32_t write(facebook::thrift::protocol::TProtocol* oprot) const; + +}; + +class FacebookService_getCounter_pargs { + public: + + + virtual ~FacebookService_getCounter_pargs() throw() {} + + const std::string* key; + + uint32_t write(facebook::thrift::protocol::TProtocol* oprot) const; + +}; + +class FacebookService_getCounter_result { + public: + + FacebookService_getCounter_result() : success(0) { + } + + virtual ~FacebookService_getCounter_result() throw() {} + + int64_t success; + + struct __isset { + __isset() : success(false) {} + bool success; + } __isset; + + bool operator == (const FacebookService_getCounter_result & rhs) const + { + if (!(success == rhs.success)) + return false; + return true; + } + bool operator != (const FacebookService_getCounter_result &rhs) const { + return !(*this == rhs); + } + + bool operator < (const FacebookService_getCounter_result & ) const; + + uint32_t read(facebook::thrift::protocol::TProtocol* iprot); + uint32_t write(facebook::thrift::protocol::TProtocol* oprot) const; + +}; + +class FacebookService_getCounter_presult { + public: + + + virtual ~FacebookService_getCounter_presult() throw() {} + + int64_t* success; + + struct __isset { + __isset() : success(false) {} + bool success; + } __isset; + + uint32_t read(facebook::thrift::protocol::TProtocol* iprot); + +}; + +class FacebookService_setOption_args { + public: + + FacebookService_setOption_args() : key(""), value("") { + } + + virtual ~FacebookService_setOption_args() throw() {} + + std::string key; + std::string value; + + struct __isset { + __isset() : key(false), value(false) {} + bool key; + bool value; + } __isset; + + bool operator == (const FacebookService_setOption_args & rhs) const + { + if (!(key == rhs.key)) + return false; + if (!(value == rhs.value)) + return false; + return true; + } + bool operator != (const FacebookService_setOption_args &rhs) const { + return !(*this == rhs); + } + + bool operator < (const FacebookService_setOption_args & ) const; + + uint32_t read(facebook::thrift::protocol::TProtocol* iprot); + uint32_t write(facebook::thrift::protocol::TProtocol* oprot) const; + +}; + +class FacebookService_setOption_pargs { + public: + + + virtual ~FacebookService_setOption_pargs() throw() {} + + const std::string* key; + const std::string* value; + + uint32_t write(facebook::thrift::protocol::TProtocol* oprot) const; + +}; + +class FacebookService_setOption_result { + public: + + FacebookService_setOption_result() { + } + + virtual ~FacebookService_setOption_result() throw() {} + + + bool operator == (const FacebookService_setOption_result & /* rhs */) const + { + return true; + } + bool operator != (const FacebookService_setOption_result &rhs) const { + return !(*this == rhs); + } + + bool operator < (const FacebookService_setOption_result & ) const; + + uint32_t read(facebook::thrift::protocol::TProtocol* iprot); + uint32_t write(facebook::thrift::protocol::TProtocol* oprot) const; + +}; + +class FacebookService_setOption_presult { + public: + + + virtual ~FacebookService_setOption_presult() throw() {} + + + uint32_t read(facebook::thrift::protocol::TProtocol* iprot); + +}; + +class FacebookService_getOption_args { + public: + + FacebookService_getOption_args() : key("") { + } + + virtual ~FacebookService_getOption_args() throw() {} + + std::string key; + + struct __isset { + __isset() : key(false) {} + bool key; + } __isset; + + bool operator == (const FacebookService_getOption_args & rhs) const + { + if (!(key == rhs.key)) + return false; + return true; + } + bool operator != (const FacebookService_getOption_args &rhs) const { + return !(*this == rhs); + } + + bool operator < (const FacebookService_getOption_args & ) const; + + uint32_t read(facebook::thrift::protocol::TProtocol* iprot); + uint32_t write(facebook::thrift::protocol::TProtocol* oprot) const; + +}; + +class FacebookService_getOption_pargs { + public: + + + virtual ~FacebookService_getOption_pargs() throw() {} + + const std::string* key; + + uint32_t write(facebook::thrift::protocol::TProtocol* oprot) const; + +}; + +class FacebookService_getOption_result { + public: + + FacebookService_getOption_result() : success("") { + } + + virtual ~FacebookService_getOption_result() throw() {} + + std::string success; + + struct __isset { + __isset() : success(false) {} + bool success; + } __isset; + + bool operator == (const FacebookService_getOption_result & rhs) const + { + if (!(success == rhs.success)) + return false; + return true; + } + bool operator != (const FacebookService_getOption_result &rhs) const { + return !(*this == rhs); + } + + bool operator < (const FacebookService_getOption_result & ) const; + + uint32_t read(facebook::thrift::protocol::TProtocol* iprot); + uint32_t write(facebook::thrift::protocol::TProtocol* oprot) const; + +}; + +class FacebookService_getOption_presult { + public: + + + virtual ~FacebookService_getOption_presult() throw() {} + + std::string* success; + + struct __isset { + __isset() : success(false) {} + bool success; + } __isset; + + uint32_t read(facebook::thrift::protocol::TProtocol* iprot); + +}; + +class FacebookService_getOptions_args { + public: + + FacebookService_getOptions_args() { + } + + virtual ~FacebookService_getOptions_args() throw() {} + + + bool operator == (const FacebookService_getOptions_args & /* rhs */) const + { + return true; + } + bool operator != (const FacebookService_getOptions_args &rhs) const { + return !(*this == rhs); + } + + bool operator < (const FacebookService_getOptions_args & ) const; + + uint32_t read(facebook::thrift::protocol::TProtocol* iprot); + uint32_t write(facebook::thrift::protocol::TProtocol* oprot) const; + +}; + +class FacebookService_getOptions_pargs { + public: + + + virtual ~FacebookService_getOptions_pargs() throw() {} + + + uint32_t write(facebook::thrift::protocol::TProtocol* oprot) const; + +}; + +class FacebookService_getOptions_result { + public: + + FacebookService_getOptions_result() { + } + + virtual ~FacebookService_getOptions_result() throw() {} + + std::map success; + + struct __isset { + __isset() : success(false) {} + bool success; + } __isset; + + bool operator == (const FacebookService_getOptions_result & rhs) const + { + if (!(success == rhs.success)) + return false; + return true; + } + bool operator != (const FacebookService_getOptions_result &rhs) const { + return !(*this == rhs); + } + + bool operator < (const FacebookService_getOptions_result & ) const; + + uint32_t read(facebook::thrift::protocol::TProtocol* iprot); + uint32_t write(facebook::thrift::protocol::TProtocol* oprot) const; + +}; + +class FacebookService_getOptions_presult { + public: + + + virtual ~FacebookService_getOptions_presult() throw() {} + + std::map * success; + + struct __isset { + __isset() : success(false) {} + bool success; + } __isset; + + uint32_t read(facebook::thrift::protocol::TProtocol* iprot); + +}; + +class FacebookService_aliveSince_args { + public: + + FacebookService_aliveSince_args() { + } + + virtual ~FacebookService_aliveSince_args() throw() {} + + + bool operator == (const FacebookService_aliveSince_args & /* rhs */) const + { + return true; + } + bool operator != (const FacebookService_aliveSince_args &rhs) const { + return !(*this == rhs); + } + + bool operator < (const FacebookService_aliveSince_args & ) const; + + uint32_t read(facebook::thrift::protocol::TProtocol* iprot); + uint32_t write(facebook::thrift::protocol::TProtocol* oprot) const; + +}; + +class FacebookService_aliveSince_pargs { + public: + + + virtual ~FacebookService_aliveSince_pargs() throw() {} + + + uint32_t write(facebook::thrift::protocol::TProtocol* oprot) const; + +}; + +class FacebookService_aliveSince_result { + public: + + FacebookService_aliveSince_result() : success(0) { + } + + virtual ~FacebookService_aliveSince_result() throw() {} + + int64_t success; + + struct __isset { + __isset() : success(false) {} + bool success; + } __isset; + + bool operator == (const FacebookService_aliveSince_result & rhs) const + { + if (!(success == rhs.success)) + return false; + return true; + } + bool operator != (const FacebookService_aliveSince_result &rhs) const { + return !(*this == rhs); + } + + bool operator < (const FacebookService_aliveSince_result & ) const; + + uint32_t read(facebook::thrift::protocol::TProtocol* iprot); + uint32_t write(facebook::thrift::protocol::TProtocol* oprot) const; + +}; + +class FacebookService_aliveSince_presult { + public: + + + virtual ~FacebookService_aliveSince_presult() throw() {} + + int64_t* success; + + struct __isset { + __isset() : success(false) {} + bool success; + } __isset; + + uint32_t read(facebook::thrift::protocol::TProtocol* iprot); + +}; + +class FacebookService_getLimitedReflection_args { + public: + + FacebookService_getLimitedReflection_args() { + } + + virtual ~FacebookService_getLimitedReflection_args() throw() {} + + + bool operator == (const FacebookService_getLimitedReflection_args & /* rhs */) const + { + return true; + } + bool operator != (const FacebookService_getLimitedReflection_args &rhs) const { + return !(*this == rhs); + } + + bool operator < (const FacebookService_getLimitedReflection_args & ) const; + + uint32_t read(facebook::thrift::protocol::TProtocol* iprot); + uint32_t write(facebook::thrift::protocol::TProtocol* oprot) const; + +}; + +class FacebookService_getLimitedReflection_pargs { + public: + + + virtual ~FacebookService_getLimitedReflection_pargs() throw() {} + + + uint32_t write(facebook::thrift::protocol::TProtocol* oprot) const; + +}; + +class FacebookService_getLimitedReflection_result { + public: + + FacebookService_getLimitedReflection_result() { + } + + virtual ~FacebookService_getLimitedReflection_result() throw() {} + + facebook::thrift::reflection::limited::Service success; + + struct __isset { + __isset() : success(false) {} + bool success; + } __isset; + + bool operator == (const FacebookService_getLimitedReflection_result & rhs) const + { + if (!(success == rhs.success)) + return false; + return true; + } + bool operator != (const FacebookService_getLimitedReflection_result &rhs) const { + return !(*this == rhs); + } + + bool operator < (const FacebookService_getLimitedReflection_result & ) const; + + uint32_t read(facebook::thrift::protocol::TProtocol* iprot); + uint32_t write(facebook::thrift::protocol::TProtocol* oprot) const; + +}; + +class FacebookService_getLimitedReflection_presult { + public: + + + virtual ~FacebookService_getLimitedReflection_presult() throw() {} + + facebook::thrift::reflection::limited::Service* success; + + struct __isset { + __isset() : success(false) {} + bool success; + } __isset; + + uint32_t read(facebook::thrift::protocol::TProtocol* iprot); + +}; + +class FacebookService_reinitialize_args { + public: + + FacebookService_reinitialize_args() { + } + + virtual ~FacebookService_reinitialize_args() throw() {} + + + bool operator == (const FacebookService_reinitialize_args & /* rhs */) const + { + return true; + } + bool operator != (const FacebookService_reinitialize_args &rhs) const { + return !(*this == rhs); + } + + bool operator < (const FacebookService_reinitialize_args & ) const; + + uint32_t read(facebook::thrift::protocol::TProtocol* iprot); + uint32_t write(facebook::thrift::protocol::TProtocol* oprot) const; + +}; + +class FacebookService_reinitialize_pargs { + public: + + + virtual ~FacebookService_reinitialize_pargs() throw() {} + + + uint32_t write(facebook::thrift::protocol::TProtocol* oprot) const; + +}; + +class FacebookService_shutdown_args { + public: + + FacebookService_shutdown_args() { + } + + virtual ~FacebookService_shutdown_args() throw() {} + + + bool operator == (const FacebookService_shutdown_args & /* rhs */) const + { + return true; + } + bool operator != (const FacebookService_shutdown_args &rhs) const { + return !(*this == rhs); + } + + bool operator < (const FacebookService_shutdown_args & ) const; + + uint32_t read(facebook::thrift::protocol::TProtocol* iprot); + uint32_t write(facebook::thrift::protocol::TProtocol* oprot) const; + +}; + +class FacebookService_shutdown_pargs { + public: + + + virtual ~FacebookService_shutdown_pargs() throw() {} + + + uint32_t write(facebook::thrift::protocol::TProtocol* oprot) const; + +}; + +class FacebookService_getSingleTimeseries_args { + public: + + FacebookService_getSingleTimeseries_args() : name(""), series_length(0) { + } + + virtual ~FacebookService_getSingleTimeseries_args() throw() {} + + std::string name; + int32_t series_length; + + struct __isset { + __isset() : name(false), series_length(false) {} + bool name; + bool series_length; + } __isset; + + bool operator == (const FacebookService_getSingleTimeseries_args & rhs) const + { + if (!(name == rhs.name)) + return false; + if (!(series_length == rhs.series_length)) + return false; + return true; + } + bool operator != (const FacebookService_getSingleTimeseries_args &rhs) const { + return !(*this == rhs); + } + + bool operator < (const FacebookService_getSingleTimeseries_args & ) const; + + uint32_t read(facebook::thrift::protocol::TProtocol* iprot); + uint32_t write(facebook::thrift::protocol::TProtocol* oprot) const; + +}; + +class FacebookService_getSingleTimeseries_pargs { + public: + + + virtual ~FacebookService_getSingleTimeseries_pargs() throw() {} + + const std::string* name; + const int32_t* series_length; + + uint32_t write(facebook::thrift::protocol::TProtocol* oprot) const; + +}; + +class FacebookService_getSingleTimeseries_result { + public: + + FacebookService_getSingleTimeseries_result() { + } + + virtual ~FacebookService_getSingleTimeseries_result() throw() {} + + std::map success; + + struct __isset { + __isset() : success(false) {} + bool success; + } __isset; + + bool operator == (const FacebookService_getSingleTimeseries_result & rhs) const + { + if (!(success == rhs.success)) + return false; + return true; + } + bool operator != (const FacebookService_getSingleTimeseries_result &rhs) const { + return !(*this == rhs); + } + + bool operator < (const FacebookService_getSingleTimeseries_result & ) const; + + uint32_t read(facebook::thrift::protocol::TProtocol* iprot); + uint32_t write(facebook::thrift::protocol::TProtocol* oprot) const; + +}; + +class FacebookService_getSingleTimeseries_presult { + public: + + + virtual ~FacebookService_getSingleTimeseries_presult() throw() {} + + std::map * success; + + struct __isset { + __isset() : success(false) {} + bool success; + } __isset; + + uint32_t read(facebook::thrift::protocol::TProtocol* iprot); + +}; + +class FacebookService_getTimeseries_args { + public: + + FacebookService_getTimeseries_args() : series_length(0) { + } + + virtual ~FacebookService_getTimeseries_args() throw() {} + + int32_t series_length; + + struct __isset { + __isset() : series_length(false) {} + bool series_length; + } __isset; + + bool operator == (const FacebookService_getTimeseries_args & rhs) const + { + if (!(series_length == rhs.series_length)) + return false; + return true; + } + bool operator != (const FacebookService_getTimeseries_args &rhs) const { + return !(*this == rhs); + } + + bool operator < (const FacebookService_getTimeseries_args & ) const; + + uint32_t read(facebook::thrift::protocol::TProtocol* iprot); + uint32_t write(facebook::thrift::protocol::TProtocol* oprot) const; + +}; + +class FacebookService_getTimeseries_pargs { + public: + + + virtual ~FacebookService_getTimeseries_pargs() throw() {} + + const int32_t* series_length; + + uint32_t write(facebook::thrift::protocol::TProtocol* oprot) const; + +}; + +class FacebookService_getTimeseries_result { + public: + + FacebookService_getTimeseries_result() { + } + + virtual ~FacebookService_getTimeseries_result() throw() {} + + std::map > success; + + struct __isset { + __isset() : success(false) {} + bool success; + } __isset; + + bool operator == (const FacebookService_getTimeseries_result & rhs) const + { + if (!(success == rhs.success)) + return false; + return true; + } + bool operator != (const FacebookService_getTimeseries_result &rhs) const { + return !(*this == rhs); + } + + bool operator < (const FacebookService_getTimeseries_result & ) const; + + uint32_t read(facebook::thrift::protocol::TProtocol* iprot); + uint32_t write(facebook::thrift::protocol::TProtocol* oprot) const; + +}; + +class FacebookService_getTimeseries_presult { + public: + + + virtual ~FacebookService_getTimeseries_presult() throw() {} + + std::map > * success; + + struct __isset { + __isset() : success(false) {} + bool success; + } __isset; + + uint32_t read(facebook::thrift::protocol::TProtocol* iprot); + +}; + +class FacebookServiceClient : virtual public FacebookServiceIf { + public: + FacebookServiceClient(boost::shared_ptr prot) : + piprot_(prot), + poprot_(prot) { + iprot_ = prot.get(); + oprot_ = prot.get(); + } + FacebookServiceClient(boost::shared_ptr iprot, boost::shared_ptr oprot) : + piprot_(iprot), + poprot_(oprot) { + iprot_ = iprot.get(); + oprot_ = oprot.get(); + } + boost::shared_ptr getInputProtocol() { + return piprot_; + } + boost::shared_ptr getOutputProtocol() { + return poprot_; + } + void getName(std::string& _return); + void send_getName(); + void recv_getName(std::string& _return); + void getVersion(std::string& _return); + void send_getVersion(); + void recv_getVersion(std::string& _return); + fb_status getStatus(); + void send_getStatus(); + fb_status recv_getStatus(); + void getStatusDetails(std::string& _return); + void send_getStatusDetails(); + void recv_getStatusDetails(std::string& _return); + void getCounters(std::map & _return); + void send_getCounters(); + void recv_getCounters(std::map & _return); + int64_t getCounter(const std::string& key); + void send_getCounter(const std::string& key); + int64_t recv_getCounter(); + void setOption(const std::string& key, const std::string& value); + void send_setOption(const std::string& key, const std::string& value); + void recv_setOption(); + void getOption(std::string& _return, const std::string& key); + void send_getOption(const std::string& key); + void recv_getOption(std::string& _return); + void getOptions(std::map & _return); + void send_getOptions(); + void recv_getOptions(std::map & _return); + int64_t aliveSince(); + void send_aliveSince(); + int64_t recv_aliveSince(); + void getLimitedReflection(facebook::thrift::reflection::limited::Service& _return); + void send_getLimitedReflection(); + void recv_getLimitedReflection(facebook::thrift::reflection::limited::Service& _return); + void reinitialize(); + void send_reinitialize(); + void shutdown(); + void send_shutdown(); + void getSingleTimeseries(std::map & _return, const std::string& name, const int32_t series_length); + void send_getSingleTimeseries(const std::string& name, const int32_t series_length); + void recv_getSingleTimeseries(std::map & _return); + void getTimeseries(std::map > & _return, const int32_t series_length); + void send_getTimeseries(const int32_t series_length); + void recv_getTimeseries(std::map > & _return); + protected: + boost::shared_ptr piprot_; + boost::shared_ptr poprot_; + facebook::thrift::protocol::TProtocol* iprot_; + facebook::thrift::protocol::TProtocol* oprot_; +}; + +class FacebookServiceProcessor : virtual public facebook::thrift::TProcessor { + protected: + boost::shared_ptr iface_; + virtual bool process_fn(facebook::thrift::protocol::TProtocol* iprot, facebook::thrift::protocol::TProtocol* oprot, std::string& fname, int32_t seqid); + private: + std::map processMap_; + void process_getName(int32_t seqid, facebook::thrift::protocol::TProtocol* iprot, facebook::thrift::protocol::TProtocol* oprot); + void process_getVersion(int32_t seqid, facebook::thrift::protocol::TProtocol* iprot, facebook::thrift::protocol::TProtocol* oprot); + void process_getStatus(int32_t seqid, facebook::thrift::protocol::TProtocol* iprot, facebook::thrift::protocol::TProtocol* oprot); + void process_getStatusDetails(int32_t seqid, facebook::thrift::protocol::TProtocol* iprot, facebook::thrift::protocol::TProtocol* oprot); + void process_getCounters(int32_t seqid, facebook::thrift::protocol::TProtocol* iprot, facebook::thrift::protocol::TProtocol* oprot); + void process_getCounter(int32_t seqid, facebook::thrift::protocol::TProtocol* iprot, facebook::thrift::protocol::TProtocol* oprot); + void process_setOption(int32_t seqid, facebook::thrift::protocol::TProtocol* iprot, facebook::thrift::protocol::TProtocol* oprot); + void process_getOption(int32_t seqid, facebook::thrift::protocol::TProtocol* iprot, facebook::thrift::protocol::TProtocol* oprot); + void process_getOptions(int32_t seqid, facebook::thrift::protocol::TProtocol* iprot, facebook::thrift::protocol::TProtocol* oprot); + void process_aliveSince(int32_t seqid, facebook::thrift::protocol::TProtocol* iprot, facebook::thrift::protocol::TProtocol* oprot); + void process_getLimitedReflection(int32_t seqid, facebook::thrift::protocol::TProtocol* iprot, facebook::thrift::protocol::TProtocol* oprot); + void process_reinitialize(int32_t seqid, facebook::thrift::protocol::TProtocol* iprot, facebook::thrift::protocol::TProtocol* oprot); + void process_shutdown(int32_t seqid, facebook::thrift::protocol::TProtocol* iprot, facebook::thrift::protocol::TProtocol* oprot); + void process_getSingleTimeseries(int32_t seqid, facebook::thrift::protocol::TProtocol* iprot, facebook::thrift::protocol::TProtocol* oprot); + void process_getTimeseries(int32_t seqid, facebook::thrift::protocol::TProtocol* iprot, facebook::thrift::protocol::TProtocol* oprot); + public: + FacebookServiceProcessor(boost::shared_ptr iface) : + iface_(iface) { + processMap_["getName"] = &FacebookServiceProcessor::process_getName; + processMap_["getVersion"] = &FacebookServiceProcessor::process_getVersion; + processMap_["getStatus"] = &FacebookServiceProcessor::process_getStatus; + processMap_["getStatusDetails"] = &FacebookServiceProcessor::process_getStatusDetails; + processMap_["getCounters"] = &FacebookServiceProcessor::process_getCounters; + processMap_["getCounter"] = &FacebookServiceProcessor::process_getCounter; + processMap_["setOption"] = &FacebookServiceProcessor::process_setOption; + processMap_["getOption"] = &FacebookServiceProcessor::process_getOption; + processMap_["getOptions"] = &FacebookServiceProcessor::process_getOptions; + processMap_["aliveSince"] = &FacebookServiceProcessor::process_aliveSince; + processMap_["getLimitedReflection"] = &FacebookServiceProcessor::process_getLimitedReflection; + processMap_["reinitialize"] = &FacebookServiceProcessor::process_reinitialize; + processMap_["shutdown"] = &FacebookServiceProcessor::process_shutdown; + processMap_["getSingleTimeseries"] = &FacebookServiceProcessor::process_getSingleTimeseries; + processMap_["getTimeseries"] = &FacebookServiceProcessor::process_getTimeseries; + } + + virtual bool process(boost::shared_ptr piprot, boost::shared_ptr poprot); + virtual ~FacebookServiceProcessor() {} +}; + +class FacebookServiceMultiface : virtual public FacebookServiceIf { + public: + FacebookServiceMultiface(std::vector >& ifaces) : ifaces_(ifaces) { + } + virtual ~FacebookServiceMultiface() {} + protected: + std::vector > ifaces_; + FacebookServiceMultiface() {} + void add(boost::shared_ptr iface) { + ifaces_.push_back(iface); + } + public: + void getName(std::string& _return) { + uint32_t sz = ifaces_.size(); + for (uint32_t i = 0; i < sz; ++i) { + if (i == sz - 1) { + ifaces_[i]->getName(_return); + return; + } else { + ifaces_[i]->getName(_return); + } + } + } + + void getVersion(std::string& _return) { + uint32_t sz = ifaces_.size(); + for (uint32_t i = 0; i < sz; ++i) { + if (i == sz - 1) { + ifaces_[i]->getVersion(_return); + return; + } else { + ifaces_[i]->getVersion(_return); + } + } + } + + fb_status getStatus() { + uint32_t sz = ifaces_.size(); + for (uint32_t i = 0; i < sz; ++i) { + if (i == sz - 1) { + return ifaces_[i]->getStatus(); + } else { + ifaces_[i]->getStatus(); + } + } + } + + void getStatusDetails(std::string& _return) { + uint32_t sz = ifaces_.size(); + for (uint32_t i = 0; i < sz; ++i) { + if (i == sz - 1) { + ifaces_[i]->getStatusDetails(_return); + return; + } else { + ifaces_[i]->getStatusDetails(_return); + } + } + } + + void getCounters(std::map & _return) { + uint32_t sz = ifaces_.size(); + for (uint32_t i = 0; i < sz; ++i) { + if (i == sz - 1) { + ifaces_[i]->getCounters(_return); + return; + } else { + ifaces_[i]->getCounters(_return); + } + } + } + + int64_t getCounter(const std::string& key) { + uint32_t sz = ifaces_.size(); + for (uint32_t i = 0; i < sz; ++i) { + if (i == sz - 1) { + return ifaces_[i]->getCounter(key); + } else { + ifaces_[i]->getCounter(key); + } + } + } + + void setOption(const std::string& key, const std::string& value) { + uint32_t sz = ifaces_.size(); + for (uint32_t i = 0; i < sz; ++i) { + ifaces_[i]->setOption(key, value); + } + } + + void getOption(std::string& _return, const std::string& key) { + uint32_t sz = ifaces_.size(); + for (uint32_t i = 0; i < sz; ++i) { + if (i == sz - 1) { + ifaces_[i]->getOption(_return, key); + return; + } else { + ifaces_[i]->getOption(_return, key); + } + } + } + + void getOptions(std::map & _return) { + uint32_t sz = ifaces_.size(); + for (uint32_t i = 0; i < sz; ++i) { + if (i == sz - 1) { + ifaces_[i]->getOptions(_return); + return; + } else { + ifaces_[i]->getOptions(_return); + } + } + } + + int64_t aliveSince() { + uint32_t sz = ifaces_.size(); + for (uint32_t i = 0; i < sz; ++i) { + if (i == sz - 1) { + return ifaces_[i]->aliveSince(); + } else { + ifaces_[i]->aliveSince(); + } + } + } + + void getLimitedReflection(facebook::thrift::reflection::limited::Service& _return) { + uint32_t sz = ifaces_.size(); + for (uint32_t i = 0; i < sz; ++i) { + if (i == sz - 1) { + ifaces_[i]->getLimitedReflection(_return); + return; + } else { + ifaces_[i]->getLimitedReflection(_return); + } + } + } + + void reinitialize() { + uint32_t sz = ifaces_.size(); + for (uint32_t i = 0; i < sz; ++i) { + ifaces_[i]->reinitialize(); + } + } + + void shutdown() { + uint32_t sz = ifaces_.size(); + for (uint32_t i = 0; i < sz; ++i) { + ifaces_[i]->shutdown(); + } + } + + void getSingleTimeseries(std::map & _return, const std::string& name, const int32_t series_length) { + uint32_t sz = ifaces_.size(); + for (uint32_t i = 0; i < sz; ++i) { + if (i == sz - 1) { + ifaces_[i]->getSingleTimeseries(_return, name, series_length); + return; + } else { + ifaces_[i]->getSingleTimeseries(_return, name, series_length); + } + } + } + + void getTimeseries(std::map > & _return, const int32_t series_length) { + uint32_t sz = ifaces_.size(); + for (uint32_t i = 0; i < sz; ++i) { + if (i == sz - 1) { + ifaces_[i]->getTimeseries(_return, series_length); + return; + } else { + ifaces_[i]->getTimeseries(_return, series_length); + } + } + } + +}; + +}} // namespace + +#endif +/** + * Autogenerated by Thrift + * + * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING + */ +#ifndef FacebookService_H +#define FacebookService_H + +#include +#include "fb303_types.h" + +namespace facebook { namespace fb303 { + +class FacebookServiceIf { + public: + virtual ~FacebookServiceIf() {} + virtual void getName(std::string& _return) = 0; + virtual void getVersion(std::string& _return) = 0; + virtual fb_status getStatus() = 0; + virtual void getStatusDetails(std::string& _return) = 0; + virtual void getCounters(std::map & _return) = 0; + virtual int64_t getCounter(const std::string& key) = 0; + virtual void setOption(const std::string& key, const std::string& value) = 0; + virtual void getOption(std::string& _return, const std::string& key) = 0; + virtual void getOptions(std::map & _return) = 0; + virtual int64_t aliveSince() = 0; + virtual void getLimitedReflection(facebook::thrift::reflection::limited::Service& _return) = 0; + virtual void reinitialize() = 0; + virtual void shutdown() = 0; + virtual void getSingleTimeseries(std::map & _return, const std::string& name, const int32_t series_length) = 0; + virtual void getTimeseries(std::map > & _return, const int32_t series_length) = 0; +}; + +class FacebookServiceNull : virtual public FacebookServiceIf { + public: + virtual ~FacebookServiceNull() {} + void getName(std::string& /* _return */) { + return; + } + void getVersion(std::string& /* _return */) { + return; + } + fb_status getStatus() { + fb_status _return = (fb_status)0; + return _return; + } + void getStatusDetails(std::string& /* _return */) { + return; + } + void getCounters(std::map & /* _return */) { + return; + } + int64_t getCounter(const std::string& /* key */) { + int64_t _return = 0; + return _return; + } + void setOption(const std::string& /* key */, const std::string& /* value */) { + return; + } + void getOption(std::string& /* _return */, const std::string& /* key */) { + return; + } + void getOptions(std::map & /* _return */) { + return; + } + int64_t aliveSince() { + int64_t _return = 0; + return _return; + } + void getLimitedReflection(facebook::thrift::reflection::limited::Service& /* _return */) { + return; + } + void reinitialize() { + return; + } + void shutdown() { + return; + } + void getSingleTimeseries(std::map & /* _return */, const std::string& /* name */, const int32_t /* series_length */) { + return; + } + void getTimeseries(std::map > & /* _return */, const int32_t /* series_length */) { + return; + } +}; + +class FacebookService_getName_args { + public: + + FacebookService_getName_args() { + } + + virtual ~FacebookService_getName_args() throw() {} + + + bool operator == (const FacebookService_getName_args & /* rhs */) const + { + return true; + } + bool operator != (const FacebookService_getName_args &rhs) const { + return !(*this == rhs); + } + + bool operator < (const FacebookService_getName_args & ) const; + + uint32_t read(facebook::thrift::protocol::TProtocol* iprot); + uint32_t write(facebook::thrift::protocol::TProtocol* oprot) const; + +}; + +class FacebookService_getName_pargs { + public: + + + virtual ~FacebookService_getName_pargs() throw() {} + + + uint32_t write(facebook::thrift::protocol::TProtocol* oprot) const; + +}; + +class FacebookService_getName_result { + public: + + FacebookService_getName_result() : success("") { + } + + virtual ~FacebookService_getName_result() throw() {} + + std::string success; + + struct __isset { + __isset() : success(false) {} + bool success; + } __isset; + + bool operator == (const FacebookService_getName_result & rhs) const + { + if (!(success == rhs.success)) + return false; + return true; + } + bool operator != (const FacebookService_getName_result &rhs) const { + return !(*this == rhs); + } + + bool operator < (const FacebookService_getName_result & ) const; + + uint32_t read(facebook::thrift::protocol::TProtocol* iprot); + uint32_t write(facebook::thrift::protocol::TProtocol* oprot) const; + +}; + +class FacebookService_getName_presult { + public: + + + virtual ~FacebookService_getName_presult() throw() {} + + std::string* success; + + struct __isset { + __isset() : success(false) {} + bool success; + } __isset; + + uint32_t read(facebook::thrift::protocol::TProtocol* iprot); + +}; + +class FacebookService_getVersion_args { + public: + + FacebookService_getVersion_args() { + } + + virtual ~FacebookService_getVersion_args() throw() {} + + + bool operator == (const FacebookService_getVersion_args & /* rhs */) const + { + return true; + } + bool operator != (const FacebookService_getVersion_args &rhs) const { + return !(*this == rhs); + } + + bool operator < (const FacebookService_getVersion_args & ) const; + + uint32_t read(facebook::thrift::protocol::TProtocol* iprot); + uint32_t write(facebook::thrift::protocol::TProtocol* oprot) const; + +}; + +class FacebookService_getVersion_pargs { + public: + + + virtual ~FacebookService_getVersion_pargs() throw() {} + + + uint32_t write(facebook::thrift::protocol::TProtocol* oprot) const; + +}; + +class FacebookService_getVersion_result { + public: + + FacebookService_getVersion_result() : success("") { + } + + virtual ~FacebookService_getVersion_result() throw() {} + + std::string success; + + struct __isset { + __isset() : success(false) {} + bool success; + } __isset; + + bool operator == (const FacebookService_getVersion_result & rhs) const + { + if (!(success == rhs.success)) + return false; + return true; + } + bool operator != (const FacebookService_getVersion_result &rhs) const { + return !(*this == rhs); + } + + bool operator < (const FacebookService_getVersion_result & ) const; + + uint32_t read(facebook::thrift::protocol::TProtocol* iprot); + uint32_t write(facebook::thrift::protocol::TProtocol* oprot) const; + +}; + +class FacebookService_getVersion_presult { + public: + + + virtual ~FacebookService_getVersion_presult() throw() {} + + std::string* success; + + struct __isset { + __isset() : success(false) {} + bool success; + } __isset; + + uint32_t read(facebook::thrift::protocol::TProtocol* iprot); + +}; + +class FacebookService_getStatus_args { + public: + + FacebookService_getStatus_args() { + } + + virtual ~FacebookService_getStatus_args() throw() {} + + + bool operator == (const FacebookService_getStatus_args & /* rhs */) const + { + return true; + } + bool operator != (const FacebookService_getStatus_args &rhs) const { + return !(*this == rhs); + } + + bool operator < (const FacebookService_getStatus_args & ) const; + + uint32_t read(facebook::thrift::protocol::TProtocol* iprot); + uint32_t write(facebook::thrift::protocol::TProtocol* oprot) const; + +}; + +class FacebookService_getStatus_pargs { + public: + + + virtual ~FacebookService_getStatus_pargs() throw() {} + + + uint32_t write(facebook::thrift::protocol::TProtocol* oprot) const; + +}; + +class FacebookService_getStatus_result { + public: + + FacebookService_getStatus_result() { + } + + virtual ~FacebookService_getStatus_result() throw() {} + + fb_status success; + + struct __isset { + __isset() : success(false) {} + bool success; + } __isset; + + bool operator == (const FacebookService_getStatus_result & rhs) const + { + if (!(success == rhs.success)) + return false; + return true; + } + bool operator != (const FacebookService_getStatus_result &rhs) const { + return !(*this == rhs); + } + + bool operator < (const FacebookService_getStatus_result & ) const; + + uint32_t read(facebook::thrift::protocol::TProtocol* iprot); + uint32_t write(facebook::thrift::protocol::TProtocol* oprot) const; + +}; + +class FacebookService_getStatus_presult { + public: + + + virtual ~FacebookService_getStatus_presult() throw() {} + + fb_status* success; + + struct __isset { + __isset() : success(false) {} + bool success; + } __isset; + + uint32_t read(facebook::thrift::protocol::TProtocol* iprot); + +}; + +class FacebookService_getStatusDetails_args { + public: + + FacebookService_getStatusDetails_args() { + } + + virtual ~FacebookService_getStatusDetails_args() throw() {} + + + bool operator == (const FacebookService_getStatusDetails_args & /* rhs */) const + { + return true; + } + bool operator != (const FacebookService_getStatusDetails_args &rhs) const { + return !(*this == rhs); + } + + bool operator < (const FacebookService_getStatusDetails_args & ) const; + + uint32_t read(facebook::thrift::protocol::TProtocol* iprot); + uint32_t write(facebook::thrift::protocol::TProtocol* oprot) const; + +}; + +class FacebookService_getStatusDetails_pargs { + public: + + + virtual ~FacebookService_getStatusDetails_pargs() throw() {} + + + uint32_t write(facebook::thrift::protocol::TProtocol* oprot) const; + +}; + +class FacebookService_getStatusDetails_result { + public: + + FacebookService_getStatusDetails_result() : success("") { + } + + virtual ~FacebookService_getStatusDetails_result() throw() {} + + std::string success; + + struct __isset { + __isset() : success(false) {} + bool success; + } __isset; + + bool operator == (const FacebookService_getStatusDetails_result & rhs) const + { + if (!(success == rhs.success)) + return false; + return true; + } + bool operator != (const FacebookService_getStatusDetails_result &rhs) const { + return !(*this == rhs); + } + + bool operator < (const FacebookService_getStatusDetails_result & ) const; + + uint32_t read(facebook::thrift::protocol::TProtocol* iprot); + uint32_t write(facebook::thrift::protocol::TProtocol* oprot) const; + +}; + +class FacebookService_getStatusDetails_presult { + public: + + + virtual ~FacebookService_getStatusDetails_presult() throw() {} + + std::string* success; + + struct __isset { + __isset() : success(false) {} + bool success; + } __isset; + + uint32_t read(facebook::thrift::protocol::TProtocol* iprot); + +}; + +class FacebookService_getCounters_args { + public: + + FacebookService_getCounters_args() { + } + + virtual ~FacebookService_getCounters_args() throw() {} + + + bool operator == (const FacebookService_getCounters_args & /* rhs */) const + { + return true; + } + bool operator != (const FacebookService_getCounters_args &rhs) const { + return !(*this == rhs); + } + + bool operator < (const FacebookService_getCounters_args & ) const; + + uint32_t read(facebook::thrift::protocol::TProtocol* iprot); + uint32_t write(facebook::thrift::protocol::TProtocol* oprot) const; + +}; + +class FacebookService_getCounters_pargs { + public: + + + virtual ~FacebookService_getCounters_pargs() throw() {} + + + uint32_t write(facebook::thrift::protocol::TProtocol* oprot) const; + +}; + +class FacebookService_getCounters_result { + public: + + FacebookService_getCounters_result() { + } + + virtual ~FacebookService_getCounters_result() throw() {} + + std::map success; + + struct __isset { + __isset() : success(false) {} + bool success; + } __isset; + + bool operator == (const FacebookService_getCounters_result & rhs) const + { + if (!(success == rhs.success)) + return false; + return true; + } + bool operator != (const FacebookService_getCounters_result &rhs) const { + return !(*this == rhs); + } + + bool operator < (const FacebookService_getCounters_result & ) const; + + uint32_t read(facebook::thrift::protocol::TProtocol* iprot); + uint32_t write(facebook::thrift::protocol::TProtocol* oprot) const; + +}; + +class FacebookService_getCounters_presult { + public: + + + virtual ~FacebookService_getCounters_presult() throw() {} + + std::map * success; + + struct __isset { + __isset() : success(false) {} + bool success; + } __isset; + + uint32_t read(facebook::thrift::protocol::TProtocol* iprot); + +}; + +class FacebookService_getCounter_args { + public: + + FacebookService_getCounter_args() : key("") { + } + + virtual ~FacebookService_getCounter_args() throw() {} + + std::string key; + + struct __isset { + __isset() : key(false) {} + bool key; + } __isset; + + bool operator == (const FacebookService_getCounter_args & rhs) const + { + if (!(key == rhs.key)) + return false; + return true; + } + bool operator != (const FacebookService_getCounter_args &rhs) const { + return !(*this == rhs); + } + + bool operator < (const FacebookService_getCounter_args & ) const; + + uint32_t read(facebook::thrift::protocol::TProtocol* iprot); + uint32_t write(facebook::thrift::protocol::TProtocol* oprot) const; + +}; + +class FacebookService_getCounter_pargs { + public: + + + virtual ~FacebookService_getCounter_pargs() throw() {} + + const std::string* key; + + uint32_t write(facebook::thrift::protocol::TProtocol* oprot) const; + +}; + +class FacebookService_getCounter_result { + public: + + FacebookService_getCounter_result() : success(0) { + } + + virtual ~FacebookService_getCounter_result() throw() {} + + int64_t success; + + struct __isset { + __isset() : success(false) {} + bool success; + } __isset; + + bool operator == (const FacebookService_getCounter_result & rhs) const + { + if (!(success == rhs.success)) + return false; + return true; + } + bool operator != (const FacebookService_getCounter_result &rhs) const { + return !(*this == rhs); + } + + bool operator < (const FacebookService_getCounter_result & ) const; + + uint32_t read(facebook::thrift::protocol::TProtocol* iprot); + uint32_t write(facebook::thrift::protocol::TProtocol* oprot) const; + +}; + +class FacebookService_getCounter_presult { + public: + + + virtual ~FacebookService_getCounter_presult() throw() {} + + int64_t* success; + + struct __isset { + __isset() : success(false) {} + bool success; + } __isset; + + uint32_t read(facebook::thrift::protocol::TProtocol* iprot); + +}; + +class FacebookService_setOption_args { + public: + + FacebookService_setOption_args() : key(""), value("") { + } + + virtual ~FacebookService_setOption_args() throw() {} + + std::string key; + std::string value; + + struct __isset { + __isset() : key(false), value(false) {} + bool key; + bool value; + } __isset; + + bool operator == (const FacebookService_setOption_args & rhs) const + { + if (!(key == rhs.key)) + return false; + if (!(value == rhs.value)) + return false; + return true; + } + bool operator != (const FacebookService_setOption_args &rhs) const { + return !(*this == rhs); + } + + bool operator < (const FacebookService_setOption_args & ) const; + + uint32_t read(facebook::thrift::protocol::TProtocol* iprot); + uint32_t write(facebook::thrift::protocol::TProtocol* oprot) const; + +}; + +class FacebookService_setOption_pargs { + public: + + + virtual ~FacebookService_setOption_pargs() throw() {} + + const std::string* key; + const std::string* value; + + uint32_t write(facebook::thrift::protocol::TProtocol* oprot) const; + +}; + +class FacebookService_setOption_result { + public: + + FacebookService_setOption_result() { + } + + virtual ~FacebookService_setOption_result() throw() {} + + + bool operator == (const FacebookService_setOption_result & /* rhs */) const + { + return true; + } + bool operator != (const FacebookService_setOption_result &rhs) const { + return !(*this == rhs); + } + + bool operator < (const FacebookService_setOption_result & ) const; + + uint32_t read(facebook::thrift::protocol::TProtocol* iprot); + uint32_t write(facebook::thrift::protocol::TProtocol* oprot) const; + +}; + +class FacebookService_setOption_presult { + public: + + + virtual ~FacebookService_setOption_presult() throw() {} + + + uint32_t read(facebook::thrift::protocol::TProtocol* iprot); + +}; + +class FacebookService_getOption_args { + public: + + FacebookService_getOption_args() : key("") { + } + + virtual ~FacebookService_getOption_args() throw() {} + + std::string key; + + struct __isset { + __isset() : key(false) {} + bool key; + } __isset; + + bool operator == (const FacebookService_getOption_args & rhs) const + { + if (!(key == rhs.key)) + return false; + return true; + } + bool operator != (const FacebookService_getOption_args &rhs) const { + return !(*this == rhs); + } + + bool operator < (const FacebookService_getOption_args & ) const; + + uint32_t read(facebook::thrift::protocol::TProtocol* iprot); + uint32_t write(facebook::thrift::protocol::TProtocol* oprot) const; + +}; + +class FacebookService_getOption_pargs { + public: + + + virtual ~FacebookService_getOption_pargs() throw() {} + + const std::string* key; + + uint32_t write(facebook::thrift::protocol::TProtocol* oprot) const; + +}; + +class FacebookService_getOption_result { + public: + + FacebookService_getOption_result() : success("") { + } + + virtual ~FacebookService_getOption_result() throw() {} + + std::string success; + + struct __isset { + __isset() : success(false) {} + bool success; + } __isset; + + bool operator == (const FacebookService_getOption_result & rhs) const + { + if (!(success == rhs.success)) + return false; + return true; + } + bool operator != (const FacebookService_getOption_result &rhs) const { + return !(*this == rhs); + } + + bool operator < (const FacebookService_getOption_result & ) const; + + uint32_t read(facebook::thrift::protocol::TProtocol* iprot); + uint32_t write(facebook::thrift::protocol::TProtocol* oprot) const; + +}; + +class FacebookService_getOption_presult { + public: + + + virtual ~FacebookService_getOption_presult() throw() {} + + std::string* success; + + struct __isset { + __isset() : success(false) {} + bool success; + } __isset; + + uint32_t read(facebook::thrift::protocol::TProtocol* iprot); + +}; + +class FacebookService_getOptions_args { + public: + + FacebookService_getOptions_args() { + } + + virtual ~FacebookService_getOptions_args() throw() {} + + + bool operator == (const FacebookService_getOptions_args & /* rhs */) const + { + return true; + } + bool operator != (const FacebookService_getOptions_args &rhs) const { + return !(*this == rhs); + } + + bool operator < (const FacebookService_getOptions_args & ) const; + + uint32_t read(facebook::thrift::protocol::TProtocol* iprot); + uint32_t write(facebook::thrift::protocol::TProtocol* oprot) const; + +}; + +class FacebookService_getOptions_pargs { + public: + + + virtual ~FacebookService_getOptions_pargs() throw() {} + + + uint32_t write(facebook::thrift::protocol::TProtocol* oprot) const; + +}; + +class FacebookService_getOptions_result { + public: + + FacebookService_getOptions_result() { + } + + virtual ~FacebookService_getOptions_result() throw() {} + + std::map success; + + struct __isset { + __isset() : success(false) {} + bool success; + } __isset; + + bool operator == (const FacebookService_getOptions_result & rhs) const + { + if (!(success == rhs.success)) + return false; + return true; + } + bool operator != (const FacebookService_getOptions_result &rhs) const { + return !(*this == rhs); + } + + bool operator < (const FacebookService_getOptions_result & ) const; + + uint32_t read(facebook::thrift::protocol::TProtocol* iprot); + uint32_t write(facebook::thrift::protocol::TProtocol* oprot) const; + +}; + +class FacebookService_getOptions_presult { + public: + + + virtual ~FacebookService_getOptions_presult() throw() {} + + std::map * success; + + struct __isset { + __isset() : success(false) {} + bool success; + } __isset; + + uint32_t read(facebook::thrift::protocol::TProtocol* iprot); + +}; + +class FacebookService_aliveSince_args { + public: + + FacebookService_aliveSince_args() { + } + + virtual ~FacebookService_aliveSince_args() throw() {} + + + bool operator == (const FacebookService_aliveSince_args & /* rhs */) const + { + return true; + } + bool operator != (const FacebookService_aliveSince_args &rhs) const { + return !(*this == rhs); + } + + bool operator < (const FacebookService_aliveSince_args & ) const; + + uint32_t read(facebook::thrift::protocol::TProtocol* iprot); + uint32_t write(facebook::thrift::protocol::TProtocol* oprot) const; + +}; + +class FacebookService_aliveSince_pargs { + public: + + + virtual ~FacebookService_aliveSince_pargs() throw() {} + + + uint32_t write(facebook::thrift::protocol::TProtocol* oprot) const; + +}; + +class FacebookService_aliveSince_result { + public: + + FacebookService_aliveSince_result() : success(0) { + } + + virtual ~FacebookService_aliveSince_result() throw() {} + + int64_t success; + + struct __isset { + __isset() : success(false) {} + bool success; + } __isset; + + bool operator == (const FacebookService_aliveSince_result & rhs) const + { + if (!(success == rhs.success)) + return false; + return true; + } + bool operator != (const FacebookService_aliveSince_result &rhs) const { + return !(*this == rhs); + } + + bool operator < (const FacebookService_aliveSince_result & ) const; + + uint32_t read(facebook::thrift::protocol::TProtocol* iprot); + uint32_t write(facebook::thrift::protocol::TProtocol* oprot) const; + +}; + +class FacebookService_aliveSince_presult { + public: + + + virtual ~FacebookService_aliveSince_presult() throw() {} + + int64_t* success; + + struct __isset { + __isset() : success(false) {} + bool success; + } __isset; + + uint32_t read(facebook::thrift::protocol::TProtocol* iprot); + +}; + +class FacebookService_getLimitedReflection_args { + public: + + FacebookService_getLimitedReflection_args() { + } + + virtual ~FacebookService_getLimitedReflection_args() throw() {} + + + bool operator == (const FacebookService_getLimitedReflection_args & /* rhs */) const + { + return true; + } + bool operator != (const FacebookService_getLimitedReflection_args &rhs) const { + return !(*this == rhs); + } + + bool operator < (const FacebookService_getLimitedReflection_args & ) const; + + uint32_t read(facebook::thrift::protocol::TProtocol* iprot); + uint32_t write(facebook::thrift::protocol::TProtocol* oprot) const; + +}; + +class FacebookService_getLimitedReflection_pargs { + public: + + + virtual ~FacebookService_getLimitedReflection_pargs() throw() {} + + + uint32_t write(facebook::thrift::protocol::TProtocol* oprot) const; + +}; + +class FacebookService_getLimitedReflection_result { + public: + + FacebookService_getLimitedReflection_result() { + } + + virtual ~FacebookService_getLimitedReflection_result() throw() {} + + facebook::thrift::reflection::limited::Service success; + + struct __isset { + __isset() : success(false) {} + bool success; + } __isset; + + bool operator == (const FacebookService_getLimitedReflection_result & rhs) const + { + if (!(success == rhs.success)) + return false; + return true; + } + bool operator != (const FacebookService_getLimitedReflection_result &rhs) const { + return !(*this == rhs); + } + + bool operator < (const FacebookService_getLimitedReflection_result & ) const; + + uint32_t read(facebook::thrift::protocol::TProtocol* iprot); + uint32_t write(facebook::thrift::protocol::TProtocol* oprot) const; + +}; + +class FacebookService_getLimitedReflection_presult { + public: + + + virtual ~FacebookService_getLimitedReflection_presult() throw() {} + + facebook::thrift::reflection::limited::Service* success; + + struct __isset { + __isset() : success(false) {} + bool success; + } __isset; + + uint32_t read(facebook::thrift::protocol::TProtocol* iprot); + +}; + +class FacebookService_reinitialize_args { + public: + + FacebookService_reinitialize_args() { + } + + virtual ~FacebookService_reinitialize_args() throw() {} + + + bool operator == (const FacebookService_reinitialize_args & /* rhs */) const + { + return true; + } + bool operator != (const FacebookService_reinitialize_args &rhs) const { + return !(*this == rhs); + } + + bool operator < (const FacebookService_reinitialize_args & ) const; + + uint32_t read(facebook::thrift::protocol::TProtocol* iprot); + uint32_t write(facebook::thrift::protocol::TProtocol* oprot) const; + +}; + +class FacebookService_reinitialize_pargs { + public: + + + virtual ~FacebookService_reinitialize_pargs() throw() {} + + + uint32_t write(facebook::thrift::protocol::TProtocol* oprot) const; + +}; + +class FacebookService_shutdown_args { + public: + + FacebookService_shutdown_args() { + } + + virtual ~FacebookService_shutdown_args() throw() {} + + + bool operator == (const FacebookService_shutdown_args & /* rhs */) const + { + return true; + } + bool operator != (const FacebookService_shutdown_args &rhs) const { + return !(*this == rhs); + } + + bool operator < (const FacebookService_shutdown_args & ) const; + + uint32_t read(facebook::thrift::protocol::TProtocol* iprot); + uint32_t write(facebook::thrift::protocol::TProtocol* oprot) const; + +}; + +class FacebookService_shutdown_pargs { + public: + + + virtual ~FacebookService_shutdown_pargs() throw() {} + + + uint32_t write(facebook::thrift::protocol::TProtocol* oprot) const; + +}; + +class FacebookService_getSingleTimeseries_args { + public: + + FacebookService_getSingleTimeseries_args() : name(""), series_length(0) { + } + + virtual ~FacebookService_getSingleTimeseries_args() throw() {} + + std::string name; + int32_t series_length; + + struct __isset { + __isset() : name(false), series_length(false) {} + bool name; + bool series_length; + } __isset; + + bool operator == (const FacebookService_getSingleTimeseries_args & rhs) const + { + if (!(name == rhs.name)) + return false; + if (!(series_length == rhs.series_length)) + return false; + return true; + } + bool operator != (const FacebookService_getSingleTimeseries_args &rhs) const { + return !(*this == rhs); + } + + bool operator < (const FacebookService_getSingleTimeseries_args & ) const; + + uint32_t read(facebook::thrift::protocol::TProtocol* iprot); + uint32_t write(facebook::thrift::protocol::TProtocol* oprot) const; + +}; + +class FacebookService_getSingleTimeseries_pargs { + public: + + + virtual ~FacebookService_getSingleTimeseries_pargs() throw() {} + + const std::string* name; + const int32_t* series_length; + + uint32_t write(facebook::thrift::protocol::TProtocol* oprot) const; + +}; + +class FacebookService_getSingleTimeseries_result { + public: + + FacebookService_getSingleTimeseries_result() { + } + + virtual ~FacebookService_getSingleTimeseries_result() throw() {} + + std::map success; + + struct __isset { + __isset() : success(false) {} + bool success; + } __isset; + + bool operator == (const FacebookService_getSingleTimeseries_result & rhs) const + { + if (!(success == rhs.success)) + return false; + return true; + } + bool operator != (const FacebookService_getSingleTimeseries_result &rhs) const { + return !(*this == rhs); + } + + bool operator < (const FacebookService_getSingleTimeseries_result & ) const; + + uint32_t read(facebook::thrift::protocol::TProtocol* iprot); + uint32_t write(facebook::thrift::protocol::TProtocol* oprot) const; + +}; + +class FacebookService_getSingleTimeseries_presult { + public: + + + virtual ~FacebookService_getSingleTimeseries_presult() throw() {} + + std::map * success; + + struct __isset { + __isset() : success(false) {} + bool success; + } __isset; + + uint32_t read(facebook::thrift::protocol::TProtocol* iprot); + +}; + +class FacebookService_getTimeseries_args { + public: + + FacebookService_getTimeseries_args() : series_length(0) { + } + + virtual ~FacebookService_getTimeseries_args() throw() {} + + int32_t series_length; + + struct __isset { + __isset() : series_length(false) {} + bool series_length; + } __isset; + + bool operator == (const FacebookService_getTimeseries_args & rhs) const + { + if (!(series_length == rhs.series_length)) + return false; + return true; + } + bool operator != (const FacebookService_getTimeseries_args &rhs) const { + return !(*this == rhs); + } + + bool operator < (const FacebookService_getTimeseries_args & ) const; + + uint32_t read(facebook::thrift::protocol::TProtocol* iprot); + uint32_t write(facebook::thrift::protocol::TProtocol* oprot) const; + +}; + +class FacebookService_getTimeseries_pargs { + public: + + + virtual ~FacebookService_getTimeseries_pargs() throw() {} + + const int32_t* series_length; + + uint32_t write(facebook::thrift::protocol::TProtocol* oprot) const; + +}; + +class FacebookService_getTimeseries_result { + public: + + FacebookService_getTimeseries_result() { + } + + virtual ~FacebookService_getTimeseries_result() throw() {} + + std::map > success; + + struct __isset { + __isset() : success(false) {} + bool success; + } __isset; + + bool operator == (const FacebookService_getTimeseries_result & rhs) const + { + if (!(success == rhs.success)) + return false; + return true; + } + bool operator != (const FacebookService_getTimeseries_result &rhs) const { + return !(*this == rhs); + } + + bool operator < (const FacebookService_getTimeseries_result & ) const; + + uint32_t read(facebook::thrift::protocol::TProtocol* iprot); + uint32_t write(facebook::thrift::protocol::TProtocol* oprot) const; + +}; + +class FacebookService_getTimeseries_presult { + public: + + + virtual ~FacebookService_getTimeseries_presult() throw() {} + + std::map > * success; + + struct __isset { + __isset() : success(false) {} + bool success; + } __isset; + + uint32_t read(facebook::thrift::protocol::TProtocol* iprot); + +}; + +class FacebookServiceClient : virtual public FacebookServiceIf { + public: + FacebookServiceClient(boost::shared_ptr prot) : + piprot_(prot), + poprot_(prot) { + iprot_ = prot.get(); + oprot_ = prot.get(); + } + FacebookServiceClient(boost::shared_ptr iprot, boost::shared_ptr oprot) : + piprot_(iprot), + poprot_(oprot) { + iprot_ = iprot.get(); + oprot_ = oprot.get(); + } + boost::shared_ptr getInputProtocol() { + return piprot_; + } + boost::shared_ptr getOutputProtocol() { + return poprot_; + } + void getName(std::string& _return); + void send_getName(); + void recv_getName(std::string& _return); + void getVersion(std::string& _return); + void send_getVersion(); + void recv_getVersion(std::string& _return); + fb_status getStatus(); + void send_getStatus(); + fb_status recv_getStatus(); + void getStatusDetails(std::string& _return); + void send_getStatusDetails(); + void recv_getStatusDetails(std::string& _return); + void getCounters(std::map & _return); + void send_getCounters(); + void recv_getCounters(std::map & _return); + int64_t getCounter(const std::string& key); + void send_getCounter(const std::string& key); + int64_t recv_getCounter(); + void setOption(const std::string& key, const std::string& value); + void send_setOption(const std::string& key, const std::string& value); + void recv_setOption(); + void getOption(std::string& _return, const std::string& key); + void send_getOption(const std::string& key); + void recv_getOption(std::string& _return); + void getOptions(std::map & _return); + void send_getOptions(); + void recv_getOptions(std::map & _return); + int64_t aliveSince(); + void send_aliveSince(); + int64_t recv_aliveSince(); + void getLimitedReflection(facebook::thrift::reflection::limited::Service& _return); + void send_getLimitedReflection(); + void recv_getLimitedReflection(facebook::thrift::reflection::limited::Service& _return); + void reinitialize(); + void send_reinitialize(); + void shutdown(); + void send_shutdown(); + void getSingleTimeseries(std::map & _return, const std::string& name, const int32_t series_length); + void send_getSingleTimeseries(const std::string& name, const int32_t series_length); + void recv_getSingleTimeseries(std::map & _return); + void getTimeseries(std::map > & _return, const int32_t series_length); + void send_getTimeseries(const int32_t series_length); + void recv_getTimeseries(std::map > & _return); + protected: + boost::shared_ptr piprot_; + boost::shared_ptr poprot_; + facebook::thrift::protocol::TProtocol* iprot_; + facebook::thrift::protocol::TProtocol* oprot_; +}; + +class FacebookServiceProcessor : virtual public facebook::thrift::TProcessor { + protected: + boost::shared_ptr iface_; + virtual bool process_fn(facebook::thrift::protocol::TProtocol* iprot, facebook::thrift::protocol::TProtocol* oprot, std::string& fname, int32_t seqid); + private: + std::map processMap_; + void process_getName(int32_t seqid, facebook::thrift::protocol::TProtocol* iprot, facebook::thrift::protocol::TProtocol* oprot); + void process_getVersion(int32_t seqid, facebook::thrift::protocol::TProtocol* iprot, facebook::thrift::protocol::TProtocol* oprot); + void process_getStatus(int32_t seqid, facebook::thrift::protocol::TProtocol* iprot, facebook::thrift::protocol::TProtocol* oprot); + void process_getStatusDetails(int32_t seqid, facebook::thrift::protocol::TProtocol* iprot, facebook::thrift::protocol::TProtocol* oprot); + void process_getCounters(int32_t seqid, facebook::thrift::protocol::TProtocol* iprot, facebook::thrift::protocol::TProtocol* oprot); + void process_getCounter(int32_t seqid, facebook::thrift::protocol::TProtocol* iprot, facebook::thrift::protocol::TProtocol* oprot); + void process_setOption(int32_t seqid, facebook::thrift::protocol::TProtocol* iprot, facebook::thrift::protocol::TProtocol* oprot); + void process_getOption(int32_t seqid, facebook::thrift::protocol::TProtocol* iprot, facebook::thrift::protocol::TProtocol* oprot); + void process_getOptions(int32_t seqid, facebook::thrift::protocol::TProtocol* iprot, facebook::thrift::protocol::TProtocol* oprot); + void process_aliveSince(int32_t seqid, facebook::thrift::protocol::TProtocol* iprot, facebook::thrift::protocol::TProtocol* oprot); + void process_getLimitedReflection(int32_t seqid, facebook::thrift::protocol::TProtocol* iprot, facebook::thrift::protocol::TProtocol* oprot); + void process_reinitialize(int32_t seqid, facebook::thrift::protocol::TProtocol* iprot, facebook::thrift::protocol::TProtocol* oprot); + void process_shutdown(int32_t seqid, facebook::thrift::protocol::TProtocol* iprot, facebook::thrift::protocol::TProtocol* oprot); + void process_getSingleTimeseries(int32_t seqid, facebook::thrift::protocol::TProtocol* iprot, facebook::thrift::protocol::TProtocol* oprot); + void process_getTimeseries(int32_t seqid, facebook::thrift::protocol::TProtocol* iprot, facebook::thrift::protocol::TProtocol* oprot); + public: + FacebookServiceProcessor(boost::shared_ptr iface) : + iface_(iface) { + processMap_["getName"] = &FacebookServiceProcessor::process_getName; + processMap_["getVersion"] = &FacebookServiceProcessor::process_getVersion; + processMap_["getStatus"] = &FacebookServiceProcessor::process_getStatus; + processMap_["getStatusDetails"] = &FacebookServiceProcessor::process_getStatusDetails; + processMap_["getCounters"] = &FacebookServiceProcessor::process_getCounters; + processMap_["getCounter"] = &FacebookServiceProcessor::process_getCounter; + processMap_["setOption"] = &FacebookServiceProcessor::process_setOption; + processMap_["getOption"] = &FacebookServiceProcessor::process_getOption; + processMap_["getOptions"] = &FacebookServiceProcessor::process_getOptions; + processMap_["aliveSince"] = &FacebookServiceProcessor::process_aliveSince; + processMap_["getLimitedReflection"] = &FacebookServiceProcessor::process_getLimitedReflection; + processMap_["reinitialize"] = &FacebookServiceProcessor::process_reinitialize; + processMap_["shutdown"] = &FacebookServiceProcessor::process_shutdown; + processMap_["getSingleTimeseries"] = &FacebookServiceProcessor::process_getSingleTimeseries; + processMap_["getTimeseries"] = &FacebookServiceProcessor::process_getTimeseries; + } + + virtual bool process(boost::shared_ptr piprot, boost::shared_ptr poprot); + virtual ~FacebookServiceProcessor() {} +}; + +class FacebookServiceMultiface : virtual public FacebookServiceIf { + public: + FacebookServiceMultiface(std::vector >& ifaces) : ifaces_(ifaces) { + } + virtual ~FacebookServiceMultiface() {} + protected: + std::vector > ifaces_; + FacebookServiceMultiface() {} + void add(boost::shared_ptr iface) { + ifaces_.push_back(iface); + } + public: + void getName(std::string& _return) { + uint32_t sz = ifaces_.size(); + for (uint32_t i = 0; i < sz; ++i) { + if (i == sz - 1) { + ifaces_[i]->getName(_return); + return; + } else { + ifaces_[i]->getName(_return); + } + } + } + + void getVersion(std::string& _return) { + uint32_t sz = ifaces_.size(); + for (uint32_t i = 0; i < sz; ++i) { + if (i == sz - 1) { + ifaces_[i]->getVersion(_return); + return; + } else { + ifaces_[i]->getVersion(_return); + } + } + } + + fb_status getStatus() { + uint32_t sz = ifaces_.size(); + for (uint32_t i = 0; i < sz; ++i) { + if (i == sz - 1) { + return ifaces_[i]->getStatus(); + } else { + ifaces_[i]->getStatus(); + } + } + } + + void getStatusDetails(std::string& _return) { + uint32_t sz = ifaces_.size(); + for (uint32_t i = 0; i < sz; ++i) { + if (i == sz - 1) { + ifaces_[i]->getStatusDetails(_return); + return; + } else { + ifaces_[i]->getStatusDetails(_return); + } + } + } + + void getCounters(std::map & _return) { + uint32_t sz = ifaces_.size(); + for (uint32_t i = 0; i < sz; ++i) { + if (i == sz - 1) { + ifaces_[i]->getCounters(_return); + return; + } else { + ifaces_[i]->getCounters(_return); + } + } + } + + int64_t getCounter(const std::string& key) { + uint32_t sz = ifaces_.size(); + for (uint32_t i = 0; i < sz; ++i) { + if (i == sz - 1) { + return ifaces_[i]->getCounter(key); + } else { + ifaces_[i]->getCounter(key); + } + } + } + + void setOption(const std::string& key, const std::string& value) { + uint32_t sz = ifaces_.size(); + for (uint32_t i = 0; i < sz; ++i) { + ifaces_[i]->setOption(key, value); + } + } + + void getOption(std::string& _return, const std::string& key) { + uint32_t sz = ifaces_.size(); + for (uint32_t i = 0; i < sz; ++i) { + if (i == sz - 1) { + ifaces_[i]->getOption(_return, key); + return; + } else { + ifaces_[i]->getOption(_return, key); + } + } + } + + void getOptions(std::map & _return) { + uint32_t sz = ifaces_.size(); + for (uint32_t i = 0; i < sz; ++i) { + if (i == sz - 1) { + ifaces_[i]->getOptions(_return); + return; + } else { + ifaces_[i]->getOptions(_return); + } + } + } + + int64_t aliveSince() { + uint32_t sz = ifaces_.size(); + for (uint32_t i = 0; i < sz; ++i) { + if (i == sz - 1) { + return ifaces_[i]->aliveSince(); + } else { + ifaces_[i]->aliveSince(); + } + } + } + + void getLimitedReflection(facebook::thrift::reflection::limited::Service& _return) { + uint32_t sz = ifaces_.size(); + for (uint32_t i = 0; i < sz; ++i) { + if (i == sz - 1) { + ifaces_[i]->getLimitedReflection(_return); + return; + } else { + ifaces_[i]->getLimitedReflection(_return); + } + } + } + + void reinitialize() { + uint32_t sz = ifaces_.size(); + for (uint32_t i = 0; i < sz; ++i) { + ifaces_[i]->reinitialize(); + } + } + + void shutdown() { + uint32_t sz = ifaces_.size(); + for (uint32_t i = 0; i < sz; ++i) { + ifaces_[i]->shutdown(); + } + } + + void getSingleTimeseries(std::map & _return, const std::string& name, const int32_t series_length) { + uint32_t sz = ifaces_.size(); + for (uint32_t i = 0; i < sz; ++i) { + if (i == sz - 1) { + ifaces_[i]->getSingleTimeseries(_return, name, series_length); + return; + } else { + ifaces_[i]->getSingleTimeseries(_return, name, series_length); + } + } + } + + void getTimeseries(std::map > & _return, const int32_t series_length) { + uint32_t sz = ifaces_.size(); + for (uint32_t i = 0; i < sz; ++i) { + if (i == sz - 1) { + ifaces_[i]->getTimeseries(_return, series_length); + return; + } else { + ifaces_[i]->getTimeseries(_return, series_length); + } + } + } + +}; + +}} // namespace + +#endif Index: service/include/thrift/fb303/ServiceTracker.h =================================================================== --- service/include/thrift/fb303/ServiceTracker.h (revision 0) +++ service/include/thrift/fb303/ServiceTracker.h (revision 0) @@ -0,0 +1,404 @@ +// Copyright (c) 2006- Facebook +// Distributed under the Thrift Software License +// +// See accompanying file LICENSE or visit the Thrift site at: +// http://developers.facebook.com/thrift/ + +/** + * ServiceTracker is a utility class for logging and timing service + * calls to a fb303 Thrift server. Currently, ServiceTracker offers + * the following features: + * + * . Logging of service method start, end (and duration), and + * optional steps in between. + * + * . Automatic check of server status via fb303::getStatus() + * with a ServiceException thrown if server not alive + * (at method start). + * + * . A periodic logged checkpoint reporting lifetime time, lifetime + * service count, and per-method statistics since the last checkpoint + * time (at method finish). + * + * . Export of fb303 counters for lifetime and checkpoint statistics + * (at method finish). + * + * . For TThreadPoolServers, a logged warning when all server threads + * are busy (at method start). (Must call setThreadManager() after + * ServiceTracker instantiation for this feature to be enabled.) + * + * Individual features may be enabled or disabled by arguments to the + * constructor. The constructor also accepts a pointer to a logging + * method -- if no pointer is passed, the tracker will log to stdout. + * + * ServiceTracker defines private methods for service start, finish, + * and step, which are designed to be accessed by instantiating a + * friend ServiceMethod object, as in the following example: + * + * #include + * class MyServiceHandler : virtual public MyServiceIf, + * public facebook::fb303::FacebookBase + * { + * public: + * MyServiceHandler::MyServiceHandler() : mServiceTracker(this) {} + * void MyServiceHandler::myServiceMethod(int userId) { + * // note: Instantiating a ServiceMethod object starts a timer + * // and tells the ServiceTracker to log the start. Might throw + * // a ServiceException. + * ServiceMethod serviceMethod(&mServiceTracker, + * "myServiceMethod", + * userId); + * ... + * // note: Calling the step method tells the ServiceTracker to + * // log the step, with a time elapsed since start. + * serviceMethod.step("post parsing, begin processing"); + * ... + * // note: When the ServiceMethod object goes out of scope, the + * // ServiceTracker will log the total elapsed time of the method. + * } + * ... + * private: + * ServiceTracker mServiceTracker; + * } + * + * The step() method call is optional; the startService() and + * finishService() methods are handled by the object's constructor and + * destructor. + * + * The ServiceTracker is (intended to be) thread-safe. + * + * Future: + * + * . Come up with something better for logging than passing a + * function pointer to the constructor. + * + * . Add methods for tracking errors from service methods, e.g. + * ServiceTracker::reportService(). + */ + +#ifndef SERVICETRACKER_H +#define SERVICETRACKER_H + + +#include +#include +#include +#include +#include +#include + +#include "thrift/concurrency/Mutex.h" + + +namespace facebook { namespace thrift { namespace concurrency { + class ThreadManager; +}}} + + +namespace facebook { namespace fb303 { + + +class FacebookBase; +class ServiceMethod; + + +class Stopwatch +{ +public: + enum Unit { UNIT_SECONDS, UNIT_MILLISECONDS, UNIT_MICROSECONDS }; + Stopwatch(); + uint64_t elapsedUnits(Unit unit, std::string *label = NULL) const; + void reset(); +private: + timeval startTime_; +}; + + +class ServiceTracker +{ + friend class ServiceMethod; + +public: + + static uint64_t CHECKPOINT_MINIMUM_INTERVAL_SECONDS; + static int LOG_LEVEL; + + ServiceTracker(facebook::fb303::FacebookBase *handler, + void (*logMethod)(int, const std::string &) + = &ServiceTracker::defaultLogMethod, + bool featureCheckpoint = true, + bool featureStatusCheck = true, + bool featureThreadCheck = true, + Stopwatch::Unit stopwatchUnit + = Stopwatch::UNIT_MILLISECONDS); + + void setThreadManager(boost::shared_ptr threadManager); + +private: + + facebook::fb303::FacebookBase *handler_; + void (*logMethod_)(int, const std::string &); + boost::shared_ptr threadManager_; + + bool featureCheckpoint_; + bool featureStatusCheck_; + bool featureThreadCheck_; + Stopwatch::Unit stopwatchUnit_; + + facebook::thrift::concurrency::Mutex statisticsMutex_; + time_t checkpointTime_; + uint64_t checkpointServices_; + uint64_t checkpointDuration_; + std::map > checkpointServiceDuration_; + + void startService(const ServiceMethod &serviceMethod); + int64_t stepService(const ServiceMethod &serviceMethod, + const std::string &stepName); + void finishService(const ServiceMethod &serviceMethod); + void reportCheckpoint(); + static void defaultLogMethod(int level, const std::string &message); +}; + + +class ServiceMethod +{ + friend class ServiceTracker; +public: + ServiceMethod(ServiceTracker *tracker, + const std::string &name, + const std::string &signature, + bool featureLogOnly = false); + ServiceMethod(ServiceTracker *tracker, + const std::string &name, + uint64_t id, + bool featureLogOnly = false); + ~ServiceMethod(); + uint64_t step(const std::string &stepName); +private: + ServiceTracker *tracker_; + std::string name_; + std::string signature_; + bool featureLogOnly_; + Stopwatch timer_; +}; + + +class ServiceException : public std::exception +{ +public: + explicit ServiceException(const std::string &message, int code = 0) + : message_(message), code_(code) {} + ~ServiceException() throw() {} + virtual const char *what() const throw() { return message_.c_str(); } + int code() const throw() { return code_; } +private: + std::string message_; + int code_; +}; + + +}} // facebook::fb303 + +#endif +// Copyright (c) 2006- Facebook +// Distributed under the Thrift Software License +// +// See accompanying file LICENSE or visit the Thrift site at: +// http://developers.facebook.com/thrift/ + +/** + * ServiceTracker is a utility class for logging and timing service + * calls to a fb303 Thrift server. Currently, ServiceTracker offers + * the following features: + * + * . Logging of service method start, end (and duration), and + * optional steps in between. + * + * . Automatic check of server status via fb303::getStatus() + * with a ServiceException thrown if server not alive + * (at method start). + * + * . A periodic logged checkpoint reporting lifetime time, lifetime + * service count, and per-method statistics since the last checkpoint + * time (at method finish). + * + * . Export of fb303 counters for lifetime and checkpoint statistics + * (at method finish). + * + * . For TThreadPoolServers, a logged warning when all server threads + * are busy (at method start). (Must call setThreadManager() after + * ServiceTracker instantiation for this feature to be enabled.) + * + * Individual features may be enabled or disabled by arguments to the + * constructor. The constructor also accepts a pointer to a logging + * method -- if no pointer is passed, the tracker will log to stdout. + * + * ServiceTracker defines private methods for service start, finish, + * and step, which are designed to be accessed by instantiating a + * friend ServiceMethod object, as in the following example: + * + * #include + * class MyServiceHandler : virtual public MyServiceIf, + * public facebook::fb303::FacebookBase + * { + * public: + * MyServiceHandler::MyServiceHandler() : mServiceTracker(this) {} + * void MyServiceHandler::myServiceMethod(int userId) { + * // note: Instantiating a ServiceMethod object starts a timer + * // and tells the ServiceTracker to log the start. Might throw + * // a ServiceException. + * ServiceMethod serviceMethod(&mServiceTracker, + * "myServiceMethod", + * userId); + * ... + * // note: Calling the step method tells the ServiceTracker to + * // log the step, with a time elapsed since start. + * serviceMethod.step("post parsing, begin processing"); + * ... + * // note: When the ServiceMethod object goes out of scope, the + * // ServiceTracker will log the total elapsed time of the method. + * } + * ... + * private: + * ServiceTracker mServiceTracker; + * } + * + * The step() method call is optional; the startService() and + * finishService() methods are handled by the object's constructor and + * destructor. + * + * The ServiceTracker is (intended to be) thread-safe. + * + * Future: + * + * . Come up with something better for logging than passing a + * function pointer to the constructor. + * + * . Add methods for tracking errors from service methods, e.g. + * ServiceTracker::reportService(). + */ + +#ifndef SERVICETRACKER_H +#define SERVICETRACKER_H + + +#include +#include +#include +#include +#include +#include + +#include "thrift/concurrency/Mutex.h" + + +namespace facebook { namespace thrift { namespace concurrency { + class ThreadManager; +}}} + + +namespace facebook { namespace fb303 { + + +class FacebookBase; +class ServiceMethod; + + +class Stopwatch +{ +public: + enum Unit { UNIT_SECONDS, UNIT_MILLISECONDS, UNIT_MICROSECONDS }; + Stopwatch(); + uint64_t elapsedUnits(Unit unit, std::string *label = NULL) const; + void reset(); +private: + timeval startTime_; +}; + + +class ServiceTracker +{ + friend class ServiceMethod; + +public: + + static uint64_t CHECKPOINT_MINIMUM_INTERVAL_SECONDS; + static int LOG_LEVEL; + + ServiceTracker(facebook::fb303::FacebookBase *handler, + void (*logMethod)(int, const std::string &) + = &ServiceTracker::defaultLogMethod, + bool featureCheckpoint = true, + bool featureStatusCheck = true, + bool featureThreadCheck = true, + Stopwatch::Unit stopwatchUnit + = Stopwatch::UNIT_MILLISECONDS); + + void setThreadManager(boost::shared_ptr threadManager); + +private: + + facebook::fb303::FacebookBase *handler_; + void (*logMethod_)(int, const std::string &); + boost::shared_ptr threadManager_; + + bool featureCheckpoint_; + bool featureStatusCheck_; + bool featureThreadCheck_; + Stopwatch::Unit stopwatchUnit_; + + facebook::thrift::concurrency::Mutex statisticsMutex_; + time_t checkpointTime_; + uint64_t checkpointServices_; + uint64_t checkpointDuration_; + std::map > checkpointServiceDuration_; + + void startService(const ServiceMethod &serviceMethod); + int64_t stepService(const ServiceMethod &serviceMethod, + const std::string &stepName); + void finishService(const ServiceMethod &serviceMethod); + void reportCheckpoint(); + static void defaultLogMethod(int level, const std::string &message); +}; + + +class ServiceMethod +{ + friend class ServiceTracker; +public: + ServiceMethod(ServiceTracker *tracker, + const std::string &name, + const std::string &signature, + bool featureLogOnly = false); + ServiceMethod(ServiceTracker *tracker, + const std::string &name, + uint64_t id, + bool featureLogOnly = false); + ~ServiceMethod(); + uint64_t step(const std::string &stepName); +private: + ServiceTracker *tracker_; + std::string name_; + std::string signature_; + bool featureLogOnly_; + Stopwatch timer_; +}; + + +class ServiceException : public std::exception +{ +public: + explicit ServiceException(const std::string &message, int code = 0) + : message_(message), code_(code) {} + ~ServiceException() throw() {} + virtual const char *what() const throw() { return message_.c_str(); } + int code() const throw() { return code_; } +private: + std::string message_; + int code_; +}; + + +}} // facebook::fb303 + +#endif Index: service/include/thrift/fb303/fb303_types.h =================================================================== --- service/include/thrift/fb303/fb303_types.h (revision 0) +++ service/include/thrift/fb303/fb303_types.h (revision 0) @@ -0,0 +1,60 @@ +/** + * Autogenerated by Thrift + * + * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING + */ +#ifndef fb303_TYPES_H +#define fb303_TYPES_H + +#include +#include +#include +#include + +#include "reflection_limited_types.h" + + +namespace facebook { namespace fb303 { + +enum fb_status { + DEAD = 0, + STARTING = 1, + ALIVE = 2, + STOPPING = 3, + STOPPED = 4, + WARNING = 5 +}; + +}} // namespace + +#endif +/** + * Autogenerated by Thrift + * + * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING + */ +#ifndef fb303_TYPES_H +#define fb303_TYPES_H + +#include +#include +#include +#include + +#include "reflection_limited_types.h" + + +namespace facebook { namespace fb303 { + +enum fb_status { + DEAD = 0, + STARTING = 1, + ALIVE = 2, + STOPPING = 3, + STOPPED = 4, + WARNING = 5 +}; + +}} // namespace + +#endif Index: service/include/thrift/fb303/FacebookBase.h =================================================================== --- service/include/thrift/fb303/FacebookBase.h (revision 0) +++ service/include/thrift/fb303/FacebookBase.h (revision 0) @@ -0,0 +1,192 @@ +// Copyright (c) 2006- Facebook +// Distributed under the Thrift Software License +// +// See accompanying file LICENSE or visit the Thrift site at: +// http://developers.facebook.com/thrift/ + +#ifndef _FACEBOOK_TB303_FACEBOOKBASE_H_ +#define _FACEBOOK_TB303_FACEBOOKBASE_H_ 1 + +#include "FacebookService.h" + +#include "thrift/server/TServer.h" +#include "thrift/concurrency/Mutex.h" + +#include +#include +#include + +namespace facebook { namespace fb303 { + +using facebook::thrift::concurrency::Mutex; +using facebook::thrift::concurrency::ReadWriteMutex; +using facebook::thrift::server::TServer; + +struct ReadWriteInt : ReadWriteMutex {int64_t value;}; +struct ReadWriteCounterMap : ReadWriteMutex, + std::map {}; + +typedef void (*get_static_limref_ptr)(facebook::thrift::reflection::limited::Service &); + +/** + * Base Facebook service implementation in C++. + * + * @author Mark Slee + */ +class FacebookBase : virtual public FacebookServiceIf { + protected: + FacebookBase(std::string name, get_static_limref_ptr reflect_lim = NULL); + virtual ~FacebookBase() {} + + public: + void getName(std::string& _return); + virtual void getVersion(std::string& _return) { _return = ""; } + + virtual fb_status getStatus() = 0; + virtual void getStatusDetails(std::string& _return) { _return = ""; } + + void setOption(const std::string& key, const std::string& value); + void getOption(std::string& _return, const std::string& key); + void getOptions(std::map & _return); + + int64_t aliveSince(); + + void getLimitedReflection(facebook::thrift::reflection::limited::Service& _return) { + _return = reflection_limited_; + } + + virtual void reinitialize() {} + + virtual void shutdown() { + if (server_.get() != NULL) { + server_->stop(); + } + } + + int64_t incrementCounter(const std::string& key, int64_t amount = 1); + int64_t setCounter(const std::string& key, int64_t value); + + void getCounters(std::map& _return); + int64_t getCounter(const std::string& key); + + /** + * Set server handle for shutdown method + */ + void setServer(boost::shared_ptr server) { + server_ = server; + } + + private: + + std::string name_; + facebook::thrift::reflection::limited::Service reflection_limited_; + int64_t aliveSince_; + + std::map options_; + Mutex optionsLock_; + + ReadWriteCounterMap counters_; + + boost::shared_ptr server_; + +}; + +}} // facebook::tb303 + +#endif // _FACEBOOK_TB303_FACEBOOKBASE_H_ +// Copyright (c) 2006- Facebook +// Distributed under the Thrift Software License +// +// See accompanying file LICENSE or visit the Thrift site at: +// http://developers.facebook.com/thrift/ + +#ifndef _FACEBOOK_TB303_FACEBOOKBASE_H_ +#define _FACEBOOK_TB303_FACEBOOKBASE_H_ 1 + +#include "FacebookService.h" + +#include "thrift/server/TServer.h" +#include "thrift/concurrency/Mutex.h" + +#include +#include +#include + +namespace facebook { namespace fb303 { + +using facebook::thrift::concurrency::Mutex; +using facebook::thrift::concurrency::ReadWriteMutex; +using facebook::thrift::server::TServer; + +struct ReadWriteInt : ReadWriteMutex {int64_t value;}; +struct ReadWriteCounterMap : ReadWriteMutex, + std::map {}; + +typedef void (*get_static_limref_ptr)(facebook::thrift::reflection::limited::Service &); + +/** + * Base Facebook service implementation in C++. + * + * @author Mark Slee + */ +class FacebookBase : virtual public FacebookServiceIf { + protected: + FacebookBase(std::string name, get_static_limref_ptr reflect_lim = NULL); + virtual ~FacebookBase() {} + + public: + void getName(std::string& _return); + virtual void getVersion(std::string& _return) { _return = ""; } + + virtual fb_status getStatus() = 0; + virtual void getStatusDetails(std::string& _return) { _return = ""; } + + void setOption(const std::string& key, const std::string& value); + void getOption(std::string& _return, const std::string& key); + void getOptions(std::map & _return); + + int64_t aliveSince(); + + void getLimitedReflection(facebook::thrift::reflection::limited::Service& _return) { + _return = reflection_limited_; + } + + virtual void reinitialize() {} + + virtual void shutdown() { + if (server_.get() != NULL) { + server_->stop(); + } + } + + int64_t incrementCounter(const std::string& key, int64_t amount = 1); + int64_t setCounter(const std::string& key, int64_t value); + + void getCounters(std::map& _return); + int64_t getCounter(const std::string& key); + + /** + * Set server handle for shutdown method + */ + void setServer(boost::shared_ptr server) { + server_ = server; + } + + private: + + std::string name_; + facebook::thrift::reflection::limited::Service reflection_limited_; + int64_t aliveSince_; + + std::map options_; + Mutex optionsLock_; + + ReadWriteCounterMap counters_; + + boost::shared_ptr server_; + +}; + +}} // facebook::tb303 + +#endif // _FACEBOOK_TB303_FACEBOOKBASE_H_ Index: service/include/thrift/fb303/if/fb303.thrift =================================================================== --- service/include/thrift/fb303/if/fb303.thrift (revision 0) +++ service/include/thrift/fb303/if/fb303.thrift (revision 0) @@ -0,0 +1,108 @@ +/** + * fb303.thrift + * + * Copyright (c) 2006- Facebook + * Distributed under the Thrift Software License + * + * See accompanying file LICENSE or visit the Thrift site at: + * http://developers.facebook.com/thrift/ + * + * + * Definition of common Facebook data types and status reporting mechanisms + * common to all Facebook services. In some cases, these methods are + * provided in the base implementation, and in other cases they simply define + * methods that inheriting applications should implement (i.e. status report) + * + * @author Mark Slee + */ + +include "thrift/if/reflection_limited.thrift" + +namespace java com.facebook.fb303 +namespace cpp facebook.fb303 + +/** + * Common status reporting mechanism across all services + */ +enum fb_status { + DEAD = 0, + STARTING = 1, + ALIVE = 2, + STOPPING = 3, + STOPPED = 4, + WARNING = 5, +} + +/** + * Standard base service + */ +service FacebookService { + + /** + * Returns a descriptive name of the service + */ + string getName(), + + /** + * Returns the version of the service + */ + string getVersion(), + + /** + * Gets the status of this service + */ + fb_status getStatus(), + + /** + * User friendly description of status, such as why the service is in + * the dead or warning state, or what is being started or stopped. + */ + string getStatusDetails(), + + /** + * Gets the counters for this service + */ + map getCounters(), + + /** + * Gets the value of a single counter + */ + i64 getCounter(1: string key), + + /** + * Sets an option + */ + void setOption(1: string key, 2: string value), + + /** + * Gets an option + */ + string getOption(1: string key), + + /** + * Gets all options + */ + map getOptions(), + + /** + * Returns the unix time that the server has been running since + */ + i64 aliveSince(), + + /** + * Returns a limited description of this service. + */ + reflection_limited.Service + getLimitedReflection(), + + /** + * Tell the server to reload its configuration, reopen log files, etc + */ + async void reinitialize() + + /** + * Suggest a shutdown to the server + */ + async void shutdown() + +} Index: service/include/thrift/if/reflection_limited.thrift =================================================================== --- service/include/thrift/if/reflection_limited.thrift (revision 0) +++ service/include/thrift/if/reflection_limited.thrift (revision 0) @@ -0,0 +1,71 @@ +#!/usr/local/bin/thrift -php -java -cpp -py + +// NOTICE!!! +// DO NOT FORGET to run regen.sh if you change this file +// (or if you change the compiler). + +// This interface is deprecated. +// There is no replacement yet, but I hate it so much that +// I'm deprecating it before it's done. +// @author I'm too ashamed to say. + +// dreiss naively thinks he knows how to do this better, +// so talk to him if you are interested in taking it on, +// or if you just want someone to make it better for you. + +namespace cpp facebook.thrift.reflection.limited +namespace java com.facebook.thrift.reflection.limited +namespace py thrift.reflection.limited + +enum TTypeTag { + T_VOID = 1, + T_BOOL = 2, + T_BYTE = 3, + T_I16 = 6, + T_I32 = 8, + T_I64 = 10, + T_DOUBLE = 4, + T_STRING = 11, + T_STRUCT = 12, + T_MAP = 13, + T_SET = 14, + T_LIST = 15, + // This doesn't exist in TBinaryProtocol, but it could be useful for reflection. + T_ENUM = 101, + T_NOT_REFLECTED = 102, +} + +struct SimpleType { + 1: TTypeTag ttype, + 2: string name, // For structs and emums. +} + +struct ContainerType { + 1: TTypeTag ttype, + 2: SimpleType subtype1, + 3: optional SimpleType subtype2, +} + +struct ThriftType { + 1: bool is_container, + 2: optional SimpleType simple_type, + 3: optional ContainerType container_type, +} + +struct Argument { + 1: i16 key, + 2: string name, + 3: ThriftType type, +} + +struct Method { + 1: string name, + 2: ThriftType return_type, + 3: list arguments, +} + +struct Service { + 1: string name, + 2: list methods, + 3: bool fully_reflected, +} Index: service/scripts/start_hive_thrift_server.sh =================================================================== --- service/scripts/start_hive_thrift_server.sh (revision 0) +++ service/scripts/start_hive_thrift_server.sh (revision 0) @@ -0,0 +1,50 @@ +#!/bin/sh + +if [ "$HADOOP_HOME" == '' ]; then + echo "Need to set HADOOP_HOME" + exit 1 +fi + +if [ "$HIVE_HOME" == '' ]; then + echo "Need to set HIVE_HOME" + exit 1 +fi + +if [ "$JAVA_HOME" == '' ]; then + echo "Need to set JAVA_HOME" + exit 1 +fi +CLASSPATH= + +# the dist lib libraries +for f in /usr/local/fbprojects/hive.metastore/lib/*.jar ; do + CLASSPATH=$CLASSPATH:$f +done + +# the hadoop libraries +for f in /mnt/hive/stable/cluster/*.jar ; do + CLASSPATH=$CLASSPATH:$f +done + +# the apache libraries +for f in /mnt/hive/stable/cluster/lib/*.jar ; do + CLASSPATH=$CLASSPATH:$f +done + +# for now, the fb_hive libraries +for f in /mnt/hive/stable/lib/hive/*.jar ; do + CLASSPATH=$CLASSPATH:$f +done + +for f in $HADOOP_HOME/lib/*.jar $HADOOP_HOME/*.jar ; do + CLASSPATH=$CLASSPATH:$f +done + +for f in $HIVE_HOME/lib/*.jar ; do + CLASSPATH=$CLASSPATH:$f +done + +CLASSPATH=$CLASSPATH:$HIVE_HOME/conf +echo $CLASSPATH +$JAVA_HOME/bin/java -Dcom.sun.management.jmxremote -Djava.library.path=/mnt/hive/production/cluster/lib/native/Linux-amd64-64/ \ + -cp $CLASSPATH org.apache.hadoop.hive.service.HiveServer 10000 Index: service/scripts/hive.service_daemon =================================================================== --- service/scripts/hive.service_daemon (revision 0) +++ service/scripts/hive.service_daemon (revision 0) @@ -0,0 +1,17 @@ +#!/usr/bin/python + +import os, sys +sys.path.append('/usr/local/fbprojects/fb303/scripts') + +import fb303_scripts + +if (len(sys.argv) > 1): + args = sys.argv[1] +else: + args = '' + +fb303_scripts.daemonize_with_restarts('hive.metastore', + False, + binary_name = 'start_meta_store_thrift_server.sh', + libs = '', + args = args) Index: service/scripts/hive.service_ctrl =================================================================== --- service/scripts/hive.service_ctrl (revision 0) +++ service/scripts/hive.service_ctrl (revision 0) @@ -0,0 +1,31 @@ +#!/usr/bin/env python +# chkconfig: 2345 90 20 +# description: hive metastore + +import sys +import fb303_scripts +from fb303_scripts import fb303_simple_mgmt + +# thrift python packages need to be installed +import thrift +from thrift import protocol, transport +from thrift.transport import TTransport +from thrift.protocol import TBinaryProtocol +from thrift.transport import * + +if (len(sys.argv) > 2): + port = int(sys.argv[2]) +else: + port = 9082 + +if (len(sys.argv) > 1): + retval = fb303_simple_mgmt.service_ctrl('hive.metastore', + port, + sys.argv[1], + binary_name = "start_meta_store_thrift_server.sh", + trans_factory = thrift.transport.TTransport.TBufferedTransportFactory(), + prot_factory = TBinaryProtocol.TBinaryProtocolFactory()) + sys.exit(retval) +else: + print 'metastore_ctrl requires a command: start, stop, restart, reload, force-reload, status, or version' + sys.exit(2) Index: service/src/gen-py/__init__.py =================================================================== Index: service/src/gen-py/hive_service/ttypes.py =================================================================== --- service/src/gen-py/hive_service/ttypes.py (revision 0) +++ service/src/gen-py/hive_service/ttypes.py (revision 0) @@ -0,0 +1,71 @@ +# +# Autogenerated by Thrift +# +# DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING +# + +from thrift.Thrift import * +import fb303.ttypes +import hive_metastore.ttypes + + +from thrift.transport import TTransport +from thrift.protocol import TBinaryProtocol +try: + from thrift.protocol import fastbinary +except: + fastbinary = None + + +class HiveServerException(Exception): + + thrift_spec = None + def __init__(self, d=None): + self.message = None + if isinstance(d, dict): + if 'message' in d: + self.message = d['message'] + + def read(self, iprot): + if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: + fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) + return + iprot.readStructBegin() + while True: + (fname, ftype, fid) = iprot.readFieldBegin() + if ftype == TType.STOP: + break + if fid == -1: + if ftype == TType.STRING: + self.message = iprot.readString(); + else: + iprot.skip(ftype) + else: + iprot.skip(ftype) + iprot.readFieldEnd() + iprot.readStructEnd() + + def write(self, oprot): + if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: + oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) + return + oprot.writeStructBegin('HiveServerException') + if self.message != None: + oprot.writeFieldBegin('message', TType.STRING, -1) + oprot.writeString(self.message) + oprot.writeFieldEnd() + oprot.writeFieldStop() + oprot.writeStructEnd() + + def __str__(self): + return str(self.__dict__) + + def __repr__(self): + return repr(self.__dict__) + + def __eq__(self, other): + return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ + + def __ne__(self, other): + return not (self == other) + Index: service/src/gen-py/hive_service/constants.py =================================================================== --- service/src/gen-py/hive_service/constants.py (revision 0) +++ service/src/gen-py/hive_service/constants.py (revision 0) @@ -0,0 +1,9 @@ +# +# Autogenerated by Thrift +# +# DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING +# + +from thrift.Thrift import * +from ttypes import * + Index: service/src/gen-py/hive_service/ThriftHive.py =================================================================== --- service/src/gen-py/hive_service/ThriftHive.py (revision 0) +++ service/src/gen-py/hive_service/ThriftHive.py (revision 0) @@ -0,0 +1,860 @@ +# +# Autogenerated by Thrift +# +# DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING +# + +from thrift.Thrift import * +import hive_metastore.ThriftHiveMetastore +from ttypes import * +from thrift.Thrift import TProcessor +from thrift.transport import TTransport +from thrift.protocol import TBinaryProtocol +try: + from thrift.protocol import fastbinary +except: + fastbinary = None + + +class Iface(hive_metastore.ThriftHiveMetastore.Iface): + def execute(self, query): + pass + + def fetchOne(self, ): + pass + + def fetchN(self, numRows): + pass + + def fetchAll(self, ): + pass + + def getSchema(self, ): + pass + + +class Client(hive_metastore.ThriftHiveMetastore.Client, Iface): + def __init__(self, iprot, oprot=None): + hive_metastore.ThriftHiveMetastore.Client.__init__(self, iprot, oprot) + + def execute(self, query): + self.send_execute(query) + self.recv_execute() + + def send_execute(self, query): + self._oprot.writeMessageBegin('execute', TMessageType.CALL, self._seqid) + args = execute_args() + args.query = query + args.write(self._oprot) + self._oprot.writeMessageEnd() + self._oprot.trans.flush() + + def recv_execute(self, ): + (fname, mtype, rseqid) = self._iprot.readMessageBegin() + if mtype == TMessageType.EXCEPTION: + x = TApplicationException() + x.read(self._iprot) + self._iprot.readMessageEnd() + raise x + result = execute_result() + result.read(self._iprot) + self._iprot.readMessageEnd() + if result.ex != None: + raise result.ex + return + + def fetchOne(self, ): + self.send_fetchOne() + return self.recv_fetchOne() + + def send_fetchOne(self, ): + self._oprot.writeMessageBegin('fetchOne', TMessageType.CALL, self._seqid) + args = fetchOne_args() + args.write(self._oprot) + self._oprot.writeMessageEnd() + self._oprot.trans.flush() + + def recv_fetchOne(self, ): + (fname, mtype, rseqid) = self._iprot.readMessageBegin() + if mtype == TMessageType.EXCEPTION: + x = TApplicationException() + x.read(self._iprot) + self._iprot.readMessageEnd() + raise x + result = fetchOne_result() + result.read(self._iprot) + self._iprot.readMessageEnd() + if result.success != None: + return result.success + if result.ex != None: + raise result.ex + raise TApplicationException(TApplicationException.MISSING_RESULT, "fetchOne failed: unknown result"); + + def fetchN(self, numRows): + self.send_fetchN(numRows) + return self.recv_fetchN() + + def send_fetchN(self, numRows): + self._oprot.writeMessageBegin('fetchN', TMessageType.CALL, self._seqid) + args = fetchN_args() + args.numRows = numRows + args.write(self._oprot) + self._oprot.writeMessageEnd() + self._oprot.trans.flush() + + def recv_fetchN(self, ): + (fname, mtype, rseqid) = self._iprot.readMessageBegin() + if mtype == TMessageType.EXCEPTION: + x = TApplicationException() + x.read(self._iprot) + self._iprot.readMessageEnd() + raise x + result = fetchN_result() + result.read(self._iprot) + self._iprot.readMessageEnd() + if result.success != None: + return result.success + if result.ex != None: + raise result.ex + raise TApplicationException(TApplicationException.MISSING_RESULT, "fetchN failed: unknown result"); + + def fetchAll(self, ): + self.send_fetchAll() + return self.recv_fetchAll() + + def send_fetchAll(self, ): + self._oprot.writeMessageBegin('fetchAll', TMessageType.CALL, self._seqid) + args = fetchAll_args() + args.write(self._oprot) + self._oprot.writeMessageEnd() + self._oprot.trans.flush() + + def recv_fetchAll(self, ): + (fname, mtype, rseqid) = self._iprot.readMessageBegin() + if mtype == TMessageType.EXCEPTION: + x = TApplicationException() + x.read(self._iprot) + self._iprot.readMessageEnd() + raise x + result = fetchAll_result() + result.read(self._iprot) + self._iprot.readMessageEnd() + if result.success != None: + return result.success + if result.ex != None: + raise result.ex + raise TApplicationException(TApplicationException.MISSING_RESULT, "fetchAll failed: unknown result"); + + def getSchema(self, ): + self.send_getSchema() + return self.recv_getSchema() + + def send_getSchema(self, ): + self._oprot.writeMessageBegin('getSchema', TMessageType.CALL, self._seqid) + args = getSchema_args() + args.write(self._oprot) + self._oprot.writeMessageEnd() + self._oprot.trans.flush() + + def recv_getSchema(self, ): + (fname, mtype, rseqid) = self._iprot.readMessageBegin() + if mtype == TMessageType.EXCEPTION: + x = TApplicationException() + x.read(self._iprot) + self._iprot.readMessageEnd() + raise x + result = getSchema_result() + result.read(self._iprot) + self._iprot.readMessageEnd() + if result.success != None: + return result.success + if result.ex != None: + raise result.ex + raise TApplicationException(TApplicationException.MISSING_RESULT, "getSchema failed: unknown result"); + + +class Processor(hive_metastore.ThriftHiveMetastore.Processor, Iface, TProcessor): + def __init__(self, handler): + hive_metastore.ThriftHiveMetastore.Processor.__init__(self, handler) + self._processMap["execute"] = Processor.process_execute + self._processMap["fetchOne"] = Processor.process_fetchOne + self._processMap["fetchN"] = Processor.process_fetchN + self._processMap["fetchAll"] = Processor.process_fetchAll + self._processMap["getSchema"] = Processor.process_getSchema + + def process(self, iprot, oprot): + (name, type, seqid) = iprot.readMessageBegin() + if name not in self._processMap: + iprot.skip(TType.STRUCT) + iprot.readMessageEnd() + x = TApplicationException(TApplicationException.UNKNOWN_METHOD, 'Unknown function %s' % (name)) + oprot.writeMessageBegin(name, TMessageType.EXCEPTION, seqid) + x.write(oprot) + oprot.writeMessageEnd() + oprot.trans.flush() + return + else: + self._processMap[name](self, seqid, iprot, oprot) + return True + + def process_execute(self, seqid, iprot, oprot): + args = execute_args() + args.read(iprot) + iprot.readMessageEnd() + result = execute_result() + try: + self._handler.execute(args.query) + except HiveServerException, ex: + result.ex = ex + oprot.writeMessageBegin("execute", TMessageType.REPLY, seqid) + result.write(oprot) + oprot.writeMessageEnd() + oprot.trans.flush() + + def process_fetchOne(self, seqid, iprot, oprot): + args = fetchOne_args() + args.read(iprot) + iprot.readMessageEnd() + result = fetchOne_result() + try: + result.success = self._handler.fetchOne() + except HiveServerException, ex: + result.ex = ex + oprot.writeMessageBegin("fetchOne", TMessageType.REPLY, seqid) + result.write(oprot) + oprot.writeMessageEnd() + oprot.trans.flush() + + def process_fetchN(self, seqid, iprot, oprot): + args = fetchN_args() + args.read(iprot) + iprot.readMessageEnd() + result = fetchN_result() + try: + result.success = self._handler.fetchN(args.numRows) + except HiveServerException, ex: + result.ex = ex + oprot.writeMessageBegin("fetchN", TMessageType.REPLY, seqid) + result.write(oprot) + oprot.writeMessageEnd() + oprot.trans.flush() + + def process_fetchAll(self, seqid, iprot, oprot): + args = fetchAll_args() + args.read(iprot) + iprot.readMessageEnd() + result = fetchAll_result() + try: + result.success = self._handler.fetchAll() + except HiveServerException, ex: + result.ex = ex + oprot.writeMessageBegin("fetchAll", TMessageType.REPLY, seqid) + result.write(oprot) + oprot.writeMessageEnd() + oprot.trans.flush() + + def process_getSchema(self, seqid, iprot, oprot): + args = getSchema_args() + args.read(iprot) + iprot.readMessageEnd() + result = getSchema_result() + try: + result.success = self._handler.getSchema() + except HiveServerException, ex: + result.ex = ex + oprot.writeMessageBegin("getSchema", TMessageType.REPLY, seqid) + result.write(oprot) + oprot.writeMessageEnd() + oprot.trans.flush() + + +# HELPER FUNCTIONS AND STRUCTURES + +class execute_args: + + thrift_spec = ( + None, # 0 + (1, TType.STRING, 'query', None, None, ), # 1 + ) + + def __init__(self, d=None): + self.query = None + if isinstance(d, dict): + if 'query' in d: + self.query = d['query'] + + def read(self, iprot): + if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: + fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) + return + iprot.readStructBegin() + while True: + (fname, ftype, fid) = iprot.readFieldBegin() + if ftype == TType.STOP: + break + if fid == 1: + if ftype == TType.STRING: + self.query = iprot.readString(); + else: + iprot.skip(ftype) + else: + iprot.skip(ftype) + iprot.readFieldEnd() + iprot.readStructEnd() + + def write(self, oprot): + if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: + oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) + return + oprot.writeStructBegin('execute_args') + if self.query != None: + oprot.writeFieldBegin('query', TType.STRING, 1) + oprot.writeString(self.query) + oprot.writeFieldEnd() + oprot.writeFieldStop() + oprot.writeStructEnd() + + def __str__(self): + return str(self.__dict__) + + def __repr__(self): + return repr(self.__dict__) + + def __eq__(self, other): + return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ + + def __ne__(self, other): + return not (self == other) + +class execute_result: + + thrift_spec = ( + None, # 0 + (1, TType.STRUCT, 'ex', (HiveServerException, HiveServerException.thrift_spec), None, ), # 1 + ) + + def __init__(self, d=None): + self.ex = None + if isinstance(d, dict): + if 'ex' in d: + self.ex = d['ex'] + + def read(self, iprot): + if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: + fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) + return + iprot.readStructBegin() + while True: + (fname, ftype, fid) = iprot.readFieldBegin() + if ftype == TType.STOP: + break + if fid == 1: + if ftype == TType.STRUCT: + self.ex = HiveServerException() + self.ex.read(iprot) + else: + iprot.skip(ftype) + else: + iprot.skip(ftype) + iprot.readFieldEnd() + iprot.readStructEnd() + + def write(self, oprot): + if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: + oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) + return + oprot.writeStructBegin('execute_result') + if self.ex != None: + oprot.writeFieldBegin('ex', TType.STRUCT, 1) + self.ex.write(oprot) + oprot.writeFieldEnd() + oprot.writeFieldStop() + oprot.writeStructEnd() + + def __str__(self): + return str(self.__dict__) + + def __repr__(self): + return repr(self.__dict__) + + def __eq__(self, other): + return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ + + def __ne__(self, other): + return not (self == other) + +class fetchOne_args: + + thrift_spec = ( + ) + + def __init__(self, d=None): + pass + + def read(self, iprot): + if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: + fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) + return + iprot.readStructBegin() + while True: + (fname, ftype, fid) = iprot.readFieldBegin() + if ftype == TType.STOP: + break + else: + iprot.skip(ftype) + iprot.readFieldEnd() + iprot.readStructEnd() + + def write(self, oprot): + if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: + oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) + return + oprot.writeStructBegin('fetchOne_args') + oprot.writeFieldStop() + oprot.writeStructEnd() + + def __str__(self): + return str(self.__dict__) + + def __repr__(self): + return repr(self.__dict__) + + def __eq__(self, other): + return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ + + def __ne__(self, other): + return not (self == other) + +class fetchOne_result: + + thrift_spec = ( + (0, TType.STRING, 'success', None, None, ), # 0 + (1, TType.STRUCT, 'ex', (HiveServerException, HiveServerException.thrift_spec), None, ), # 1 + ) + + def __init__(self, d=None): + self.success = None + self.ex = None + if isinstance(d, dict): + if 'success' in d: + self.success = d['success'] + if 'ex' in d: + self.ex = d['ex'] + + def read(self, iprot): + if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: + fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) + return + iprot.readStructBegin() + while True: + (fname, ftype, fid) = iprot.readFieldBegin() + if ftype == TType.STOP: + break + if fid == 0: + if ftype == TType.STRING: + self.success = iprot.readString(); + else: + iprot.skip(ftype) + elif fid == 1: + if ftype == TType.STRUCT: + self.ex = HiveServerException() + self.ex.read(iprot) + else: + iprot.skip(ftype) + else: + iprot.skip(ftype) + iprot.readFieldEnd() + iprot.readStructEnd() + + def write(self, oprot): + if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: + oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) + return + oprot.writeStructBegin('fetchOne_result') + if self.success != None: + oprot.writeFieldBegin('success', TType.STRING, 0) + oprot.writeString(self.success) + oprot.writeFieldEnd() + if self.ex != None: + oprot.writeFieldBegin('ex', TType.STRUCT, 1) + self.ex.write(oprot) + oprot.writeFieldEnd() + oprot.writeFieldStop() + oprot.writeStructEnd() + + def __str__(self): + return str(self.__dict__) + + def __repr__(self): + return repr(self.__dict__) + + def __eq__(self, other): + return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ + + def __ne__(self, other): + return not (self == other) + +class fetchN_args: + + thrift_spec = ( + None, # 0 + (1, TType.I32, 'numRows', None, None, ), # 1 + ) + + def __init__(self, d=None): + self.numRows = None + if isinstance(d, dict): + if 'numRows' in d: + self.numRows = d['numRows'] + + def read(self, iprot): + if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: + fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) + return + iprot.readStructBegin() + while True: + (fname, ftype, fid) = iprot.readFieldBegin() + if ftype == TType.STOP: + break + if fid == 1: + if ftype == TType.I32: + self.numRows = iprot.readI32(); + else: + iprot.skip(ftype) + else: + iprot.skip(ftype) + iprot.readFieldEnd() + iprot.readStructEnd() + + def write(self, oprot): + if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: + oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) + return + oprot.writeStructBegin('fetchN_args') + if self.numRows != None: + oprot.writeFieldBegin('numRows', TType.I32, 1) + oprot.writeI32(self.numRows) + oprot.writeFieldEnd() + oprot.writeFieldStop() + oprot.writeStructEnd() + + def __str__(self): + return str(self.__dict__) + + def __repr__(self): + return repr(self.__dict__) + + def __eq__(self, other): + return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ + + def __ne__(self, other): + return not (self == other) + +class fetchN_result: + + thrift_spec = ( + (0, TType.LIST, 'success', (TType.STRING,None), None, ), # 0 + (1, TType.STRUCT, 'ex', (HiveServerException, HiveServerException.thrift_spec), None, ), # 1 + ) + + def __init__(self, d=None): + self.success = None + self.ex = None + if isinstance(d, dict): + if 'success' in d: + self.success = d['success'] + if 'ex' in d: + self.ex = d['ex'] + + def read(self, iprot): + if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: + fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) + return + iprot.readStructBegin() + while True: + (fname, ftype, fid) = iprot.readFieldBegin() + if ftype == TType.STOP: + break + if fid == 0: + if ftype == TType.LIST: + self.success = [] + (_etype3, _size0) = iprot.readListBegin() + for _i4 in xrange(_size0): + _elem5 = iprot.readString(); + self.success.append(_elem5) + iprot.readListEnd() + else: + iprot.skip(ftype) + elif fid == 1: + if ftype == TType.STRUCT: + self.ex = HiveServerException() + self.ex.read(iprot) + else: + iprot.skip(ftype) + else: + iprot.skip(ftype) + iprot.readFieldEnd() + iprot.readStructEnd() + + def write(self, oprot): + if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: + oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) + return + oprot.writeStructBegin('fetchN_result') + if self.success != None: + oprot.writeFieldBegin('success', TType.LIST, 0) + oprot.writeListBegin(TType.STRING, len(self.success)) + for iter6 in self.success: + oprot.writeString(iter6) + oprot.writeListEnd() + oprot.writeFieldEnd() + if self.ex != None: + oprot.writeFieldBegin('ex', TType.STRUCT, 1) + self.ex.write(oprot) + oprot.writeFieldEnd() + oprot.writeFieldStop() + oprot.writeStructEnd() + + def __str__(self): + return str(self.__dict__) + + def __repr__(self): + return repr(self.__dict__) + + def __eq__(self, other): + return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ + + def __ne__(self, other): + return not (self == other) + +class fetchAll_args: + + thrift_spec = ( + ) + + def __init__(self, d=None): + pass + + def read(self, iprot): + if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: + fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) + return + iprot.readStructBegin() + while True: + (fname, ftype, fid) = iprot.readFieldBegin() + if ftype == TType.STOP: + break + else: + iprot.skip(ftype) + iprot.readFieldEnd() + iprot.readStructEnd() + + def write(self, oprot): + if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: + oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) + return + oprot.writeStructBegin('fetchAll_args') + oprot.writeFieldStop() + oprot.writeStructEnd() + + def __str__(self): + return str(self.__dict__) + + def __repr__(self): + return repr(self.__dict__) + + def __eq__(self, other): + return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ + + def __ne__(self, other): + return not (self == other) + +class fetchAll_result: + + thrift_spec = ( + (0, TType.LIST, 'success', (TType.STRING,None), None, ), # 0 + (1, TType.STRUCT, 'ex', (HiveServerException, HiveServerException.thrift_spec), None, ), # 1 + ) + + def __init__(self, d=None): + self.success = None + self.ex = None + if isinstance(d, dict): + if 'success' in d: + self.success = d['success'] + if 'ex' in d: + self.ex = d['ex'] + + def read(self, iprot): + if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: + fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) + return + iprot.readStructBegin() + while True: + (fname, ftype, fid) = iprot.readFieldBegin() + if ftype == TType.STOP: + break + if fid == 0: + if ftype == TType.LIST: + self.success = [] + (_etype10, _size7) = iprot.readListBegin() + for _i11 in xrange(_size7): + _elem12 = iprot.readString(); + self.success.append(_elem12) + iprot.readListEnd() + else: + iprot.skip(ftype) + elif fid == 1: + if ftype == TType.STRUCT: + self.ex = HiveServerException() + self.ex.read(iprot) + else: + iprot.skip(ftype) + else: + iprot.skip(ftype) + iprot.readFieldEnd() + iprot.readStructEnd() + + def write(self, oprot): + if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: + oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) + return + oprot.writeStructBegin('fetchAll_result') + if self.success != None: + oprot.writeFieldBegin('success', TType.LIST, 0) + oprot.writeListBegin(TType.STRING, len(self.success)) + for iter13 in self.success: + oprot.writeString(iter13) + oprot.writeListEnd() + oprot.writeFieldEnd() + if self.ex != None: + oprot.writeFieldBegin('ex', TType.STRUCT, 1) + self.ex.write(oprot) + oprot.writeFieldEnd() + oprot.writeFieldStop() + oprot.writeStructEnd() + + def __str__(self): + return str(self.__dict__) + + def __repr__(self): + return repr(self.__dict__) + + def __eq__(self, other): + return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ + + def __ne__(self, other): + return not (self == other) + +class getSchema_args: + + thrift_spec = ( + ) + + def __init__(self, d=None): + pass + + def read(self, iprot): + if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: + fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) + return + iprot.readStructBegin() + while True: + (fname, ftype, fid) = iprot.readFieldBegin() + if ftype == TType.STOP: + break + else: + iprot.skip(ftype) + iprot.readFieldEnd() + iprot.readStructEnd() + + def write(self, oprot): + if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: + oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) + return + oprot.writeStructBegin('getSchema_args') + oprot.writeFieldStop() + oprot.writeStructEnd() + + def __str__(self): + return str(self.__dict__) + + def __repr__(self): + return repr(self.__dict__) + + def __eq__(self, other): + return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ + + def __ne__(self, other): + return not (self == other) + +class getSchema_result: + + thrift_spec = ( + (0, TType.STRING, 'success', None, None, ), # 0 + (1, TType.STRUCT, 'ex', (HiveServerException, HiveServerException.thrift_spec), None, ), # 1 + ) + + def __init__(self, d=None): + self.success = None + self.ex = None + if isinstance(d, dict): + if 'success' in d: + self.success = d['success'] + if 'ex' in d: + self.ex = d['ex'] + + def read(self, iprot): + if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: + fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) + return + iprot.readStructBegin() + while True: + (fname, ftype, fid) = iprot.readFieldBegin() + if ftype == TType.STOP: + break + if fid == 0: + if ftype == TType.STRING: + self.success = iprot.readString(); + else: + iprot.skip(ftype) + elif fid == 1: + if ftype == TType.STRUCT: + self.ex = HiveServerException() + self.ex.read(iprot) + else: + iprot.skip(ftype) + else: + iprot.skip(ftype) + iprot.readFieldEnd() + iprot.readStructEnd() + + def write(self, oprot): + if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: + oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) + return + oprot.writeStructBegin('getSchema_result') + if self.success != None: + oprot.writeFieldBegin('success', TType.STRING, 0) + oprot.writeString(self.success) + oprot.writeFieldEnd() + if self.ex != None: + oprot.writeFieldBegin('ex', TType.STRUCT, 1) + self.ex.write(oprot) + oprot.writeFieldEnd() + oprot.writeFieldStop() + oprot.writeStructEnd() + + def __str__(self): + return str(self.__dict__) + + def __repr__(self): + return repr(self.__dict__) + + def __eq__(self, other): + return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ + + def __ne__(self, other): + return not (self == other) + + Index: service/src/gen-py/hive_service/ThriftHive-remote =================================================================== --- service/src/gen-py/hive_service/ThriftHive-remote (revision 0) +++ service/src/gen-py/hive_service/ThriftHive-remote (revision 0) @@ -0,0 +1,107 @@ +#!/usr/bin/env python +# +# Autogenerated by Thrift +# +# DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING +# + +import sys +import pprint +from urlparse import urlparse +from thrift.transport import TTransport +from thrift.transport import TSocket +from thrift.transport import THttpClient +from thrift.protocol import TBinaryProtocol + +import ThriftHive +from ttypes import * + +if len(sys.argv) <= 1 or sys.argv[1] == '--help': + print '' + print 'Usage: ' + sys.argv[0] + ' [-h host:port] [-u url] [-f[ramed]] function [arg1 [arg2...]]' + print '' + print 'Functions:' + print ' void execute(string query)' + print ' string fetchOne()' + print ' fetchN(i32 numRows)' + print ' fetchAll()' + print ' string getSchema()' + print '' + sys.exit(0) + +pp = pprint.PrettyPrinter(indent = 2) +host = 'localhost' +port = 9090 +uri = '' +framed = False +http = False +argi = 1 + +if sys.argv[argi] == '-h': + parts = sys.argv[argi+1].split(':') + host = parts[0] + port = int(parts[1]) + argi += 2 + +if sys.argv[argi] == '-u': + url = urlparse(sys.argv[argi+1]) + parts = url[1].split(':') + host = parts[0] + if len(parts) > 1: + port = int(parts[1]) + else: + port = 80 + uri = url[2] + http = True + argi += 2 + +if sys.argv[argi] == '-f' or sys.argv[argi] == '-framed': + framed = True + argi += 1 + +cmd = sys.argv[argi] +args = sys.argv[argi+1:] + +if http: + transport = THttpClient.THttpClient(host, port, uri) +else: + socket = TSocket.TSocket(host, port) + if framed: + transport = TTransport.TFramedTransport(socket) + else: + transport = TTransport.TBufferedTransport(socket) +protocol = TBinaryProtocol.TBinaryProtocol(transport) +client = ThriftHive.Client(protocol) +transport.open() + +if cmd == 'execute': + if len(args) != 1: + print 'execute requires 1 args' + sys.exit(1) + pp.pprint(client.execute(args[0],)) + +elif cmd == 'fetchOne': + if len(args) != 0: + print 'fetchOne requires 0 args' + sys.exit(1) + pp.pprint(client.fetchOne()) + +elif cmd == 'fetchN': + if len(args) != 1: + print 'fetchN requires 1 args' + sys.exit(1) + pp.pprint(client.fetchN(eval(args[0]),)) + +elif cmd == 'fetchAll': + if len(args) != 0: + print 'fetchAll requires 0 args' + sys.exit(1) + pp.pprint(client.fetchAll()) + +elif cmd == 'getSchema': + if len(args) != 0: + print 'getSchema requires 0 args' + sys.exit(1) + pp.pprint(client.getSchema()) + +transport.close() Property changes on: service/src/gen-py/hive_service/ThriftHive-remote ___________________________________________________________________ Name: svn:executable + * Index: service/src/gen-py/hive_service/__init__.py =================================================================== --- service/src/gen-py/hive_service/__init__.py (revision 0) +++ service/src/gen-py/hive_service/__init__.py (revision 0) @@ -0,0 +1 @@ +__all__ = ['ttypes', 'constants', 'ThriftHive'] Index: service/src/test/org/apache/hadoop/hive/service/TestHiveServer.java =================================================================== --- service/src/test/org/apache/hadoop/hive/service/TestHiveServer.java (revision 0) +++ service/src/test/org/apache/hadoop/hive/service/TestHiveServer.java (revision 0) @@ -0,0 +1,185 @@ +package org.apache.hadoop.hive.service; + +import java.util.*; +import org.apache.hadoop.fs.Path; +import junit.framework.TestCase; +import org.apache.hadoop.hive.service.HiveInterface; +import org.apache.hadoop.hive.service.HiveClient; +import org.apache.hadoop.hive.service.HiveServer; +import com.facebook.thrift.protocol.TProtocol; +import com.facebook.thrift.protocol.TBinaryProtocol; +import com.facebook.thrift.transport.TSocket; +import com.facebook.thrift.transport.TTransport; +import org.apache.hadoop.hive.conf.HiveConf; +import org.apache.hadoop.hive.serde2.dynamic_type.DynamicSerDe; +import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspector; +import org.apache.hadoop.hive.serde.Constants; +import org.apache.hadoop.conf.Configuration; +import org.apache.hadoop.io.BytesWritable; + +public class TestHiveServer extends TestCase { + + private HiveInterface client; + private final static String host = "localhost"; + private final static int port = 10000; + private Path dataFilePath; + + private static String tableName = "testhivedrivertable"; + private HiveConf conf; + + public TestHiveServer(String name) { + super(name); + conf = new HiveConf(TestHiveServer.class); + String dataFileDir = conf.get("test.data.files").replace('\\', '/').replace("c:", ""); + dataFilePath = new Path(dataFileDir, "kv1.txt"); + } + + protected void setUp() throws Exception { + super.setUp(); + } + + protected void tearDown() throws Exception { + super.tearDown(); + } + + public void testEmbeddedExecute() throws Exception { + client = new HiveServer.HiveServerHandler(); + try { + client.execute("drop table " + tableName); + } catch (Exception ex) { + } + + try { + client.execute("create table " + tableName + " (num int)"); + client.execute("load data local inpath '" + dataFilePath.toString() + "' into table " + tableName); + client.execute("select count(1) as cnt from " + tableName); + String row = client.fetchOne(); + assertEquals(row, "500"); + String schema = client.getSchema(); + assertEquals(schema, "struct result { bigint cnt }"); + client.execute("drop table " + tableName); + } + catch (Throwable t) { + t.printStackTrace(); + } + } + + public void notestExecute() throws Exception { + TTransport transport = new TSocket(host, port); + TProtocol protocol = new TBinaryProtocol(transport); + client = new HiveClient(protocol); + transport.open(); + try { + client.execute("drop table " + tableName); + } catch (Exception ex) { + } + + client.execute("create table " + tableName + " (num int)"); + client.execute("load data local inpath '" + dataFilePath.toString() + "' into table " + tableName); + client.execute("select count(1) from " + tableName); + String row = client.fetchOne(); + assertEquals(row, "500"); + client.execute("drop table " + tableName); + transport.close(); + } + + /** + * Test metastore call + */ + public void testEmbeddedMetastore() throws Exception { + client = new HiveServer.HiveServerHandler(); + try { + client.execute("drop table " + tableName); + } catch (Exception ex) { + } + + client.execute("create table " + tableName + " (num int)"); + List tabs = client.get_tables("default", tableName); + assertEquals(tabs.get(0), tableName); + client.execute("drop table " + tableName); + } + + /** + * Test metastore call + */ + public void notestMetastore() throws Exception { + TTransport transport = new TSocket(host, port); + TProtocol protocol = new TBinaryProtocol(transport); + client = new HiveClient(protocol); + transport.open(); + try { + client.execute("drop table " + tableName); + } catch (Exception ex) { + } + + client.execute("create table " + tableName + " (num int)"); + List tabs = client.get_tables("default", tableName); + assertEquals(tabs.get(0), tableName); + client.execute("drop table " + tableName); + transport.close(); + } + + /** + * + */ + public void testFetch() throws Exception { + client = new HiveServer.HiveServerHandler(); + + // create and populate a table with 500 rows. + try { + client.execute("drop table " + tableName); + } catch (Exception ex) { + } + client.execute("create table " + tableName + " (key int, value string)"); + client.execute("load data local inpath '" + dataFilePath.toString() + "' into table " + tableName); + + // fetchAll test + client.execute("select key, value from " + tableName); + assertEquals(client.fetchAll().size(), 500); + assertEquals(client.fetchAll().size(), 0); + + // fetchOne test + client.execute("select key, value from " + tableName); + for (int i = 0; i < 500; i++) { + assertNotNull(client.fetchOne()); + } + assertNull(client.fetchOne()); + + // fetchN test + client.execute("select key, value from " + tableName); + assertEquals(client.fetchN(499).size(), 499); + assertEquals(client.fetchN(499).size(), 1); + assertEquals(client.fetchN(499).size(), 0); + } + + public void testDynamicSerde() throws Exception { + client = new HiveServer.HiveServerHandler(); + try { + client.execute("drop table " + tableName); + } catch (Exception ex) { + } + + client.execute("create table " + tableName + " (key int, value string)"); + client.execute("load data local inpath '" + dataFilePath.toString() + "' into table " + tableName); + //client.execute("select key, count(1) from " + tableName + " where key > 10 group by key"); + client.execute("select key, value from " + tableName + " where key > 10"); + + // Instantiate DynamicSerDe + DynamicSerDe ds = new DynamicSerDe(); + Properties dsp = new Properties(); + dsp.setProperty(Constants.SERIALIZATION_FORMAT, org.apache.hadoop.hive.serde2.thrift.TCTLSeparatedProtocol.class.getName()); + dsp.setProperty(org.apache.hadoop.hive.metastore.api.Constants.META_TABLE_NAME, "result"); + dsp.setProperty(Constants.SERIALIZATION_DDL, client.getSchema()); + dsp.setProperty(Constants.SERIALIZATION_LIB, ds.getClass().toString()); + dsp.setProperty(Constants.FIELD_DELIM, "9"); + ds.initialize(new Configuration(), dsp); + + String row = client.fetchOne(); + Object o = ds.deserialize(new BytesWritable(row.getBytes())); + + assertEquals(o.getClass().toString(), "class java.util.ArrayList"); + List lst = (List)o; + assertEquals(lst.get(0), "238"); + } + +} Index: service/src/java/org/apache/hadoop/hive/service/HiveServer.java =================================================================== --- service/src/java/org/apache/hadoop/hive/service/HiveServer.java (revision 0) +++ service/src/java/org/apache/hadoop/hive/service/HiveServer.java (revision 0) @@ -0,0 +1,231 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.hadoop.hive.service; + +import java.util.List; +import java.util.Map; +import java.util.Vector; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.hadoop.conf.Configuration; +import org.apache.hadoop.fs.Path; +import org.apache.hadoop.hive.conf.HiveConf; +import org.apache.hadoop.hive.ql.plan.tableDesc; +import org.apache.hadoop.hive.ql.exec.ColumnInfo; +import org.apache.hadoop.hive.service.ThriftHive; +import org.apache.hadoop.hive.service.ThriftHive.*; +import org.apache.hadoop.hive.service.HiveServerException; +import org.apache.hadoop.hive.ql.session.SessionState; +import org.apache.hadoop.hive.serde2.Deserializer; +import org.apache.hadoop.hive.serde2.SerDeException; +import org.apache.hadoop.util.ReflectionUtils; +import org.apache.hadoop.util.StringUtils; + +import com.facebook.fb303.FacebookBase; +import com.facebook.fb303.FacebookService; +import com.facebook.fb303.fb_status; +import com.facebook.thrift.TException; +import com.facebook.thrift.protocol.TBinaryProtocol; +import com.facebook.thrift.server.TServer; +import com.facebook.thrift.server.TThreadPoolServer; +import com.facebook.thrift.transport.TServerSocket; +import com.facebook.thrift.transport.TServerTransport; +import com.facebook.thrift.transport.TTransportFactory; +import org.apache.hadoop.hive.ql.Driver; +import org.apache.hadoop.hive.metastore.api.*; +import org.apache.hadoop.hive.metastore.*; + +public class HiveServer extends ThriftHive { + private final static String VERSION = "0"; + + /** + * This class uses an environment variable HADOOP_HOME, which must point to the root + * of hadoop installation (e.g. export HADOOP_HOME=/home/you/hive/trunk/hadoopcore ). + */ + public static class HiveServerHandler extends HiveMetaStore.HMSHandler implements HiveInterface { + + /** + * Stores rows for fetchOne/fetchN methods. + */ + private Vector rows; + + /** + * Hadoop installation path. + */ + private static final String HADOOPBIN = System.getenv("HADOOP_HOME") + "/bin/hadoop"; + + /** + * Hive server uses org.apache.hadoop.hive.ql.Driver for run() and + * getResults() methods. + */ + private Driver driver; + private SessionState session; + + public static final Log LOG = LogFactory.getLog(HiveServer.class.getName()); + + /** + * A constructor. + */ + public HiveServerHandler() throws MetaException { + super(HiveServer.class.getName()); + session = new SessionState(new HiveConf(SessionState.class)); + SessionState.start(session); + HiveConf conf = session.get().getConf(); + conf.setVar(HiveConf.ConfVars.HADOOPBIN, HADOOPBIN); + session.in = null; + session.out = null; + session.err = null; + driver = new Driver(); + rows = new Vector(); + } + + /** + * Executes a query. + * + * @param query query to execute. + */ + @Override + public void execute(String query) throws HiveServerException, TException { + int rc = 0; + rows.clear(); + // TODO: driver.run should either return int or throw exception, not both. + try { + rc = driver.run(query); + } catch (Exception e) { + throw new HiveServerException(); + } + if (rc != 0) { + throw new HiveServerException(); + } + } + + /** + * TODO construct DynamicSerDe DDL + */ + @Override + public String getSchema() throws HiveServerException, TException { + Vector colInfos = driver.getResultColumnInfos(); + tableDesc td = driver.getResultTblDesc(); + String[] colNames = td.getProperties().getProperty("columns").split(","); + if (colInfos == null) { + throw new HiveServerException("Schema is null"); + } + String schema = "struct result { "; + schema += colInfos.get(0).getType() + " " + colNames[0]; + for (int i = 1; i < colInfos.size(); ++i) { + schema += ", " + colInfos.get(i).getType() + " " + colNames[i]; + } + schema += " }"; + return schema; + } + + /** + * Fetches the next row in a query result set. + * + * @return the next row in a query result set. null if there is no more row to fetch. + */ + @Override + public String fetchOne() throws HiveServerException, TException { + String row = null; + if (!rows.isEmpty()) { + row = rows.remove(0); + } else if (driver.getResults(rows)) { + row = rows.remove(0); + } + return row; + } + + /** + * Fetches numRows rows. + * + * @param numRows Number of rows to fetch. + * @return A list of rows. The size of the list is numRows if there are at least + * numRows rows available to return. The size is smaller than numRows if + * there aren't enough rows. The list will be empty if there is no more + * row to fetch or numRows == 0. + * @throws HiveServerException Invalid value for numRows (numRows < 0) + */ + @Override + public List fetchN(int numRows) throws HiveServerException, TException { + Vector result = new Vector(); + if (numRows < 0) { + throw new HiveServerException("Invalid argument for number of rows: " + numRows); + } + if (rows.size() < numRows) { + while (rows.size() < numRows && driver.getResults(result)) { + rows.addAll(result); + result.clear(); + } + } + int resultSize = Math.min(rows.size(), numRows); + + // create a copy because subList points to the original list. + result = new Vector(rows.subList(0, resultSize)); + rows.subList(0, resultSize).clear(); + return result; + } + + /** + * Fetches all the rows in a result set. + * + * @return All the rows in a result set of a query executed using execute method. + * + * TODO: Currently the server buffers all the rows before returning them + * to the client. Decide whether the buffering should be done in the client. + */ + @Override + public List fetchAll() throws HiveServerException, TException { + rows.clear(); + Vector result = new Vector(); + while (driver.getResults(result)) { + rows.addAll(result); + result.clear(); + } + return rows; + } + + @Override + public int getStatus() { + return 0; + } + + @Override + public String getVersion() { + return VERSION; + } + } + + public static void main(String[] args) { + try { + int port = Integer.valueOf(args[0]).intValue(); + TServerTransport serverTransport = new TServerSocket(port); + Iface handler = new HiveServerHandler(); + FacebookService.Processor processor = new ThriftHive.Processor(handler); + TThreadPoolServer.Options options = new TThreadPoolServer.Options(); + TServer server = new TThreadPoolServer(processor, serverTransport, + new TTransportFactory(), new TTransportFactory(), + new TBinaryProtocol.Factory(), new TBinaryProtocol.Factory(), options); + server.serve(); + HiveServerHandler.LOG.info("Started the new hive server on port " + port); + } catch (Exception x) { + x.printStackTrace(); + } + } +} Index: service/src/java/org/apache/hadoop/hive/service/HiveClient.java =================================================================== --- service/src/java/org/apache/hadoop/hive/service/HiveClient.java (revision 0) +++ service/src/java/org/apache/hadoop/hive/service/HiveClient.java (revision 0) @@ -0,0 +1,46 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.hadoop.hive.service; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.hadoop.conf.Configuration; +import org.apache.hadoop.fs.Path; +import org.apache.hadoop.hive.conf.HiveConf; +import org.apache.hadoop.hive.service.ThriftHive; +import org.apache.hadoop.hive.service.ThriftHive.*; +import org.apache.hadoop.hive.service.HiveServerException; +import org.apache.hadoop.hive.serde2.Deserializer; +import org.apache.hadoop.hive.serde2.SerDeException; +import org.apache.hadoop.util.ReflectionUtils; +import org.apache.hadoop.util.StringUtils; + +import com.facebook.fb303.FacebookBase; +import com.facebook.fb303.FacebookService; +import com.facebook.fb303.fb_status; +import com.facebook.thrift.TException; +import com.facebook.thrift.protocol.TProtocol; + +import org.apache.hadoop.hive.metastore.api.*; + +public class HiveClient extends ThriftHive.Client implements HiveInterface { + public HiveClient(TProtocol prot) { + super(prot, prot); + } +} Index: service/src/java/org/apache/hadoop/hive/service/HiveInterface.java =================================================================== --- service/src/java/org/apache/hadoop/hive/service/HiveInterface.java (revision 0) +++ service/src/java/org/apache/hadoop/hive/service/HiveInterface.java (revision 0) @@ -0,0 +1,34 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.hadoop.hive.service; + +/** + * HiveInterface extends 2 interfaces, ThriftHive and ThriftHiveMetastore. + * + * ThriftHive.Iface is defined in: + * service/src/gen-javabean/org/apache/hadoop/hive/service/ThriftHive.java + * ThriftHiveMetastore.Iface is defined in: + * metastore/src/gen-javabean/org/apache/hadoop/hive/metastore/api/ThriftHiveMetastore.java + * + * These interfaces are generated by Thrift. The thrift files are in: + * ThriftHive: service/if/hive_service.thrift + * ThriftHiveMetastore: metastore/if/hive_metastore.thrift + */ +public interface HiveInterface extends ThriftHive.Iface, org.apache.hadoop.hive.metastore.api.ThriftHiveMetastore.Iface { +} Index: service/src/gen-javabean/org/apache/hadoop/hive/service/HiveServerException.java =================================================================== --- service/src/gen-javabean/org/apache/hadoop/hive/service/HiveServerException.java (revision 0) +++ service/src/gen-javabean/org/apache/hadoop/hive/service/HiveServerException.java (revision 0) @@ -0,0 +1,158 @@ +/** + * Autogenerated by Thrift + * + * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING + */ +package org.apache.hadoop.hive.service; + +import java.util.List; +import java.util.ArrayList; +import java.util.Map; +import java.util.HashMap; +import java.util.Set; +import java.util.HashSet; +import com.facebook.thrift.*; + +import com.facebook.thrift.protocol.*; +import com.facebook.thrift.transport.*; + +public class HiveServerException extends Exception implements TBase, java.io.Serializable { + private String message; + public static final int MESSAGE = -1; + + public final Isset __isset = new Isset(); + public static final class Isset implements java.io.Serializable { + public boolean message = false; + } + + public HiveServerException() { + } + + public HiveServerException( + String message) + { + this(); + this.message = message; + this.__isset.message = (message != null); + } + + public String getMessage() { + return this.message; + } + + public void setMessage(String message) { + this.message = message; + this.__isset.message = (message != null); + } + + public void unsetMessage() { + this.__isset.message = false; + } + + public void setFieldValue(int fieldID, Object value) { + switch (fieldID) { + case MESSAGE: + setMessage((String)value); + break; + + default: + throw new IllegalArgumentException("Field " + fieldID + " doesn't exist!"); + } + } + + public Object getFieldValue(int fieldID) { + switch (fieldID) { + case MESSAGE: + return getMessage(); + + default: + throw new IllegalArgumentException("Field " + fieldID + " doesn't exist!"); + } + } + + public boolean equals(Object that) { + if (that == null) + return false; + if (that instanceof HiveServerException) + return this.equals((HiveServerException)that); + return false; + } + + public boolean equals(HiveServerException that) { + if (that == null) + return false; + + boolean this_present_message = true && (this.message != null); + boolean that_present_message = true && (that.message != null); + if (this_present_message || that_present_message) { + if (!(this_present_message && that_present_message)) + return false; + if (!this.message.equals(that.message)) + return false; + } + + return true; + } + + public int hashCode() { + return 0; + } + + public void read(TProtocol iprot) throws TException { + TField field; + iprot.readStructBegin(); + while (true) + { + field = iprot.readFieldBegin(); + if (field.type == TType.STOP) { + break; + } + switch (field.id) + { + case MESSAGE: + if (field.type == TType.STRING) { + this.message = iprot.readString(); + this.__isset.message = true; + } else { + TProtocolUtil.skip(iprot, field.type); + } + break; + default: + TProtocolUtil.skip(iprot, field.type); + break; + } + iprot.readFieldEnd(); + } + iprot.readStructEnd(); + } + + public void write(TProtocol oprot) throws TException { + TStruct struct = new TStruct("HiveServerException"); + oprot.writeStructBegin(struct); + TField field = new TField(); + if (this.message != null) { + field.name = "message"; + field.type = TType.STRING; + field.id = MESSAGE; + oprot.writeFieldBegin(field); + oprot.writeString(this.message); + oprot.writeFieldEnd(); + } + oprot.writeFieldStop(); + oprot.writeStructEnd(); + } + + public String toString() { + StringBuilder sb = new StringBuilder("HiveServerException("); + boolean first = true; + + if (!first) sb.append(", "); + sb.append("message:"); + sb.append(this.message); + first = false; + sb.append(")"); + return sb.toString(); + } + +} + Index: service/src/gen-javabean/org/apache/hadoop/hive/service/ThriftHive.java =================================================================== --- service/src/gen-javabean/org/apache/hadoop/hive/service/ThriftHive.java (revision 0) +++ service/src/gen-javabean/org/apache/hadoop/hive/service/ThriftHive.java (revision 0) @@ -0,0 +1,1879 @@ +/** + * Autogenerated by Thrift + * + * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING + */ +package org.apache.hadoop.hive.service; + +import java.util.List; +import java.util.ArrayList; +import java.util.Map; +import java.util.HashMap; +import java.util.Set; +import java.util.HashSet; +import com.facebook.thrift.*; + +import com.facebook.thrift.protocol.*; +import com.facebook.thrift.transport.*; + +public class ThriftHive { + + public interface Iface extends org.apache.hadoop.hive.metastore.api.ThriftHiveMetastore.Iface { + + public void execute(String query) throws HiveServerException, TException; + + public String fetchOne() throws HiveServerException, TException; + + public List fetchN(int numRows) throws HiveServerException, TException; + + public List fetchAll() throws HiveServerException, TException; + + public String getSchema() throws HiveServerException, TException; + + } + + public static class Client extends org.apache.hadoop.hive.metastore.api.ThriftHiveMetastore.Client implements Iface { + public Client(TProtocol prot) + { + this(prot, prot); + } + + public Client(TProtocol iprot, TProtocol oprot) + { + super(iprot, oprot); + } + + public void execute(String query) throws HiveServerException, TException + { + send_execute(query); + recv_execute(); + } + + public void send_execute(String query) throws TException + { + oprot_.writeMessageBegin(new TMessage("execute", TMessageType.CALL, seqid_)); + execute_args args = new execute_args(); + args.query = query; + args.write(oprot_); + oprot_.writeMessageEnd(); + oprot_.getTransport().flush(); + } + + public void recv_execute() throws HiveServerException, TException + { + TMessage msg = iprot_.readMessageBegin(); + if (msg.type == TMessageType.EXCEPTION) { + TApplicationException x = TApplicationException.read(iprot_); + iprot_.readMessageEnd(); + throw x; + } + execute_result result = new execute_result(); + result.read(iprot_); + iprot_.readMessageEnd(); + if (result.__isset.ex) { + throw result.ex; + } + return; + } + + public String fetchOne() throws HiveServerException, TException + { + send_fetchOne(); + return recv_fetchOne(); + } + + public void send_fetchOne() throws TException + { + oprot_.writeMessageBegin(new TMessage("fetchOne", TMessageType.CALL, seqid_)); + fetchOne_args args = new fetchOne_args(); + args.write(oprot_); + oprot_.writeMessageEnd(); + oprot_.getTransport().flush(); + } + + public String recv_fetchOne() throws HiveServerException, TException + { + TMessage msg = iprot_.readMessageBegin(); + if (msg.type == TMessageType.EXCEPTION) { + TApplicationException x = TApplicationException.read(iprot_); + iprot_.readMessageEnd(); + throw x; + } + fetchOne_result result = new fetchOne_result(); + result.read(iprot_); + iprot_.readMessageEnd(); + if (result.__isset.success) { + return result.success; + } + if (result.__isset.ex) { + throw result.ex; + } + throw new TApplicationException(TApplicationException.MISSING_RESULT, "fetchOne failed: unknown result"); + } + + public List fetchN(int numRows) throws HiveServerException, TException + { + send_fetchN(numRows); + return recv_fetchN(); + } + + public void send_fetchN(int numRows) throws TException + { + oprot_.writeMessageBegin(new TMessage("fetchN", TMessageType.CALL, seqid_)); + fetchN_args args = new fetchN_args(); + args.numRows = numRows; + args.write(oprot_); + oprot_.writeMessageEnd(); + oprot_.getTransport().flush(); + } + + public List recv_fetchN() throws HiveServerException, TException + { + TMessage msg = iprot_.readMessageBegin(); + if (msg.type == TMessageType.EXCEPTION) { + TApplicationException x = TApplicationException.read(iprot_); + iprot_.readMessageEnd(); + throw x; + } + fetchN_result result = new fetchN_result(); + result.read(iprot_); + iprot_.readMessageEnd(); + if (result.__isset.success) { + return result.success; + } + if (result.__isset.ex) { + throw result.ex; + } + throw new TApplicationException(TApplicationException.MISSING_RESULT, "fetchN failed: unknown result"); + } + + public List fetchAll() throws HiveServerException, TException + { + send_fetchAll(); + return recv_fetchAll(); + } + + public void send_fetchAll() throws TException + { + oprot_.writeMessageBegin(new TMessage("fetchAll", TMessageType.CALL, seqid_)); + fetchAll_args args = new fetchAll_args(); + args.write(oprot_); + oprot_.writeMessageEnd(); + oprot_.getTransport().flush(); + } + + public List recv_fetchAll() throws HiveServerException, TException + { + TMessage msg = iprot_.readMessageBegin(); + if (msg.type == TMessageType.EXCEPTION) { + TApplicationException x = TApplicationException.read(iprot_); + iprot_.readMessageEnd(); + throw x; + } + fetchAll_result result = new fetchAll_result(); + result.read(iprot_); + iprot_.readMessageEnd(); + if (result.__isset.success) { + return result.success; + } + if (result.__isset.ex) { + throw result.ex; + } + throw new TApplicationException(TApplicationException.MISSING_RESULT, "fetchAll failed: unknown result"); + } + + public String getSchema() throws HiveServerException, TException + { + send_getSchema(); + return recv_getSchema(); + } + + public void send_getSchema() throws TException + { + oprot_.writeMessageBegin(new TMessage("getSchema", TMessageType.CALL, seqid_)); + getSchema_args args = new getSchema_args(); + args.write(oprot_); + oprot_.writeMessageEnd(); + oprot_.getTransport().flush(); + } + + public String recv_getSchema() throws HiveServerException, TException + { + TMessage msg = iprot_.readMessageBegin(); + if (msg.type == TMessageType.EXCEPTION) { + TApplicationException x = TApplicationException.read(iprot_); + iprot_.readMessageEnd(); + throw x; + } + getSchema_result result = new getSchema_result(); + result.read(iprot_); + iprot_.readMessageEnd(); + if (result.__isset.success) { + return result.success; + } + if (result.__isset.ex) { + throw result.ex; + } + throw new TApplicationException(TApplicationException.MISSING_RESULT, "getSchema failed: unknown result"); + } + + } + public static class Processor extends org.apache.hadoop.hive.metastore.api.ThriftHiveMetastore.Processor implements TProcessor { + public Processor(Iface iface) + { + super(iface); + iface_ = iface; + processMap_.put("execute", new execute()); + processMap_.put("fetchOne", new fetchOne()); + processMap_.put("fetchN", new fetchN()); + processMap_.put("fetchAll", new fetchAll()); + processMap_.put("getSchema", new getSchema()); + } + + private Iface iface_; + + public boolean process(TProtocol iprot, TProtocol oprot) throws TException + { + TMessage msg = iprot.readMessageBegin(); + ProcessFunction fn = processMap_.get(msg.name); + if (fn == null) { + TProtocolUtil.skip(iprot, TType.STRUCT); + iprot.readMessageEnd(); + TApplicationException x = new TApplicationException(TApplicationException.UNKNOWN_METHOD, "Invalid method name: '"+msg.name+"'"); + oprot.writeMessageBegin(new TMessage(msg.name, TMessageType.EXCEPTION, msg.seqid)); + x.write(oprot); + oprot.writeMessageEnd(); + oprot.getTransport().flush(); + return true; + } + fn.process(msg.seqid, iprot, oprot); + return true; + } + + private class execute implements ProcessFunction { + public void process(int seqid, TProtocol iprot, TProtocol oprot) throws TException + { + execute_args args = new execute_args(); + args.read(iprot); + iprot.readMessageEnd(); + execute_result result = new execute_result(); + try { + iface_.execute(args.query); + } catch (HiveServerException ex) { + result.ex = ex; + result.__isset.ex = true; + } + oprot.writeMessageBegin(new TMessage("execute", TMessageType.REPLY, seqid)); + result.write(oprot); + oprot.writeMessageEnd(); + oprot.getTransport().flush(); + } + + } + + private class fetchOne implements ProcessFunction { + public void process(int seqid, TProtocol iprot, TProtocol oprot) throws TException + { + fetchOne_args args = new fetchOne_args(); + args.read(iprot); + iprot.readMessageEnd(); + fetchOne_result result = new fetchOne_result(); + try { + result.success = iface_.fetchOne(); + result.__isset.success = true; + } catch (HiveServerException ex) { + result.ex = ex; + result.__isset.ex = true; + } + oprot.writeMessageBegin(new TMessage("fetchOne", TMessageType.REPLY, seqid)); + result.write(oprot); + oprot.writeMessageEnd(); + oprot.getTransport().flush(); + } + + } + + private class fetchN implements ProcessFunction { + public void process(int seqid, TProtocol iprot, TProtocol oprot) throws TException + { + fetchN_args args = new fetchN_args(); + args.read(iprot); + iprot.readMessageEnd(); + fetchN_result result = new fetchN_result(); + try { + result.success = iface_.fetchN(args.numRows); + result.__isset.success = true; + } catch (HiveServerException ex) { + result.ex = ex; + result.__isset.ex = true; + } + oprot.writeMessageBegin(new TMessage("fetchN", TMessageType.REPLY, seqid)); + result.write(oprot); + oprot.writeMessageEnd(); + oprot.getTransport().flush(); + } + + } + + private class fetchAll implements ProcessFunction { + public void process(int seqid, TProtocol iprot, TProtocol oprot) throws TException + { + fetchAll_args args = new fetchAll_args(); + args.read(iprot); + iprot.readMessageEnd(); + fetchAll_result result = new fetchAll_result(); + try { + result.success = iface_.fetchAll(); + result.__isset.success = true; + } catch (HiveServerException ex) { + result.ex = ex; + result.__isset.ex = true; + } + oprot.writeMessageBegin(new TMessage("fetchAll", TMessageType.REPLY, seqid)); + result.write(oprot); + oprot.writeMessageEnd(); + oprot.getTransport().flush(); + } + + } + + private class getSchema implements ProcessFunction { + public void process(int seqid, TProtocol iprot, TProtocol oprot) throws TException + { + getSchema_args args = new getSchema_args(); + args.read(iprot); + iprot.readMessageEnd(); + getSchema_result result = new getSchema_result(); + try { + result.success = iface_.getSchema(); + result.__isset.success = true; + } catch (HiveServerException ex) { + result.ex = ex; + result.__isset.ex = true; + } + oprot.writeMessageBegin(new TMessage("getSchema", TMessageType.REPLY, seqid)); + result.write(oprot); + oprot.writeMessageEnd(); + oprot.getTransport().flush(); + } + + } + + } + + public static class execute_args implements TBase, java.io.Serializable { + private String query; + public static final int QUERY = 1; + + public final Isset __isset = new Isset(); + public static final class Isset implements java.io.Serializable { + public boolean query = false; + } + + public execute_args() { + } + + public execute_args( + String query) + { + this(); + this.query = query; + this.__isset.query = (query != null); + } + + public String getQuery() { + return this.query; + } + + public void setQuery(String query) { + this.query = query; + this.__isset.query = (query != null); + } + + public void unsetQuery() { + this.__isset.query = false; + } + + public void setFieldValue(int fieldID, Object value) { + switch (fieldID) { + case QUERY: + setQuery((String)value); + break; + + default: + throw new IllegalArgumentException("Field " + fieldID + " doesn't exist!"); + } + } + + public Object getFieldValue(int fieldID) { + switch (fieldID) { + case QUERY: + return getQuery(); + + default: + throw new IllegalArgumentException("Field " + fieldID + " doesn't exist!"); + } + } + + public boolean equals(Object that) { + if (that == null) + return false; + if (that instanceof execute_args) + return this.equals((execute_args)that); + return false; + } + + public boolean equals(execute_args that) { + if (that == null) + return false; + + boolean this_present_query = true && (this.query != null); + boolean that_present_query = true && (that.query != null); + if (this_present_query || that_present_query) { + if (!(this_present_query && that_present_query)) + return false; + if (!this.query.equals(that.query)) + return false; + } + + return true; + } + + public int hashCode() { + return 0; + } + + public void read(TProtocol iprot) throws TException { + TField field; + iprot.readStructBegin(); + while (true) + { + field = iprot.readFieldBegin(); + if (field.type == TType.STOP) { + break; + } + switch (field.id) + { + case QUERY: + if (field.type == TType.STRING) { + this.query = iprot.readString(); + this.__isset.query = true; + } else { + TProtocolUtil.skip(iprot, field.type); + } + break; + default: + TProtocolUtil.skip(iprot, field.type); + break; + } + iprot.readFieldEnd(); + } + iprot.readStructEnd(); + } + + public void write(TProtocol oprot) throws TException { + TStruct struct = new TStruct("execute_args"); + oprot.writeStructBegin(struct); + TField field = new TField(); + if (this.query != null) { + field.name = "query"; + field.type = TType.STRING; + field.id = QUERY; + oprot.writeFieldBegin(field); + oprot.writeString(this.query); + oprot.writeFieldEnd(); + } + oprot.writeFieldStop(); + oprot.writeStructEnd(); + } + + public String toString() { + StringBuilder sb = new StringBuilder("execute_args("); + boolean first = true; + + if (!first) sb.append(", "); + sb.append("query:"); + sb.append(this.query); + first = false; + sb.append(")"); + return sb.toString(); + } + + } + + public static class execute_result implements TBase, java.io.Serializable { + private HiveServerException ex; + public static final int EX = 1; + + public final Isset __isset = new Isset(); + public static final class Isset implements java.io.Serializable { + public boolean ex = false; + } + + public execute_result() { + } + + public execute_result( + HiveServerException ex) + { + this(); + this.ex = ex; + this.__isset.ex = (ex != null); + } + + public HiveServerException getEx() { + return this.ex; + } + + public void setEx(HiveServerException ex) { + this.ex = ex; + this.__isset.ex = (ex != null); + } + + public void unsetEx() { + this.ex = null; + this.__isset.ex = false; + } + + public void setFieldValue(int fieldID, Object value) { + switch (fieldID) { + case EX: + setEx((HiveServerException)value); + break; + + default: + throw new IllegalArgumentException("Field " + fieldID + " doesn't exist!"); + } + } + + public Object getFieldValue(int fieldID) { + switch (fieldID) { + case EX: + return getEx(); + + default: + throw new IllegalArgumentException("Field " + fieldID + " doesn't exist!"); + } + } + + public boolean equals(Object that) { + if (that == null) + return false; + if (that instanceof execute_result) + return this.equals((execute_result)that); + return false; + } + + public boolean equals(execute_result that) { + if (that == null) + return false; + + boolean this_present_ex = true && (this.ex != null); + boolean that_present_ex = true && (that.ex != null); + if (this_present_ex || that_present_ex) { + if (!(this_present_ex && that_present_ex)) + return false; + if (!this.ex.equals(that.ex)) + return false; + } + + return true; + } + + public int hashCode() { + return 0; + } + + public void read(TProtocol iprot) throws TException { + TField field; + iprot.readStructBegin(); + while (true) + { + field = iprot.readFieldBegin(); + if (field.type == TType.STOP) { + break; + } + switch (field.id) + { + case EX: + if (field.type == TType.STRUCT) { + this.ex = new HiveServerException(); + this.ex.read(iprot); + this.__isset.ex = true; + } else { + TProtocolUtil.skip(iprot, field.type); + } + break; + default: + TProtocolUtil.skip(iprot, field.type); + break; + } + iprot.readFieldEnd(); + } + iprot.readStructEnd(); + } + + public void write(TProtocol oprot) throws TException { + TStruct struct = new TStruct("execute_result"); + oprot.writeStructBegin(struct); + TField field = new TField(); + + if (this.__isset.ex) { + if (this.ex != null) { + field.name = "ex"; + field.type = TType.STRUCT; + field.id = EX; + oprot.writeFieldBegin(field); + this.ex.write(oprot); + oprot.writeFieldEnd(); + } + } + oprot.writeFieldStop(); + oprot.writeStructEnd(); + } + + public String toString() { + StringBuilder sb = new StringBuilder("execute_result("); + boolean first = true; + + if (!first) sb.append(", "); + sb.append("ex:"); + sb.append(this.ex); + first = false; + sb.append(")"); + return sb.toString(); + } + + } + + public static class fetchOne_args implements TBase, java.io.Serializable { + public fetchOne_args() { + } + + public void setFieldValue(int fieldID, Object value) { + switch (fieldID) { + default: + throw new IllegalArgumentException("Field " + fieldID + " doesn't exist!"); + } + } + + public Object getFieldValue(int fieldID) { + switch (fieldID) { + default: + throw new IllegalArgumentException("Field " + fieldID + " doesn't exist!"); + } + } + + public boolean equals(Object that) { + if (that == null) + return false; + if (that instanceof fetchOne_args) + return this.equals((fetchOne_args)that); + return false; + } + + public boolean equals(fetchOne_args that) { + if (that == null) + return false; + + return true; + } + + public int hashCode() { + return 0; + } + + public void read(TProtocol iprot) throws TException { + TField field; + iprot.readStructBegin(); + while (true) + { + field = iprot.readFieldBegin(); + if (field.type == TType.STOP) { + break; + } + switch (field.id) + { + default: + TProtocolUtil.skip(iprot, field.type); + break; + } + iprot.readFieldEnd(); + } + iprot.readStructEnd(); + } + + public void write(TProtocol oprot) throws TException { + TStruct struct = new TStruct("fetchOne_args"); + oprot.writeStructBegin(struct); + oprot.writeFieldStop(); + oprot.writeStructEnd(); + } + + public String toString() { + StringBuilder sb = new StringBuilder("fetchOne_args("); + boolean first = true; + + sb.append(")"); + return sb.toString(); + } + + } + + public static class fetchOne_result implements TBase, java.io.Serializable { + private String success; + public static final int SUCCESS = 0; + private HiveServerException ex; + public static final int EX = 1; + + public final Isset __isset = new Isset(); + public static final class Isset implements java.io.Serializable { + public boolean success = false; + public boolean ex = false; + } + + public fetchOne_result() { + } + + public fetchOne_result( + String success, + HiveServerException ex) + { + this(); + this.success = success; + this.__isset.success = (success != null); + this.ex = ex; + this.__isset.ex = (ex != null); + } + + public String getSuccess() { + return this.success; + } + + public void setSuccess(String success) { + this.success = success; + this.__isset.success = (success != null); + } + + public void unsetSuccess() { + this.__isset.success = false; + } + + public HiveServerException getEx() { + return this.ex; + } + + public void setEx(HiveServerException ex) { + this.ex = ex; + this.__isset.ex = (ex != null); + } + + public void unsetEx() { + this.ex = null; + this.__isset.ex = false; + } + + public void setFieldValue(int fieldID, Object value) { + switch (fieldID) { + case SUCCESS: + setSuccess((String)value); + break; + + case EX: + setEx((HiveServerException)value); + break; + + default: + throw new IllegalArgumentException("Field " + fieldID + " doesn't exist!"); + } + } + + public Object getFieldValue(int fieldID) { + switch (fieldID) { + case SUCCESS: + return getSuccess(); + + case EX: + return getEx(); + + default: + throw new IllegalArgumentException("Field " + fieldID + " doesn't exist!"); + } + } + + public boolean equals(Object that) { + if (that == null) + return false; + if (that instanceof fetchOne_result) + return this.equals((fetchOne_result)that); + return false; + } + + public boolean equals(fetchOne_result that) { + if (that == null) + return false; + + boolean this_present_success = true && (this.success != null); + boolean that_present_success = true && (that.success != null); + if (this_present_success || that_present_success) { + if (!(this_present_success && that_present_success)) + return false; + if (!this.success.equals(that.success)) + return false; + } + + boolean this_present_ex = true && (this.ex != null); + boolean that_present_ex = true && (that.ex != null); + if (this_present_ex || that_present_ex) { + if (!(this_present_ex && that_present_ex)) + return false; + if (!this.ex.equals(that.ex)) + return false; + } + + return true; + } + + public int hashCode() { + return 0; + } + + public void read(TProtocol iprot) throws TException { + TField field; + iprot.readStructBegin(); + while (true) + { + field = iprot.readFieldBegin(); + if (field.type == TType.STOP) { + break; + } + switch (field.id) + { + case SUCCESS: + if (field.type == TType.STRING) { + this.success = iprot.readString(); + this.__isset.success = true; + } else { + TProtocolUtil.skip(iprot, field.type); + } + break; + case EX: + if (field.type == TType.STRUCT) { + this.ex = new HiveServerException(); + this.ex.read(iprot); + this.__isset.ex = true; + } else { + TProtocolUtil.skip(iprot, field.type); + } + break; + default: + TProtocolUtil.skip(iprot, field.type); + break; + } + iprot.readFieldEnd(); + } + iprot.readStructEnd(); + } + + public void write(TProtocol oprot) throws TException { + TStruct struct = new TStruct("fetchOne_result"); + oprot.writeStructBegin(struct); + TField field = new TField(); + + if (this.__isset.success) { + if (this.success != null) { + field.name = "success"; + field.type = TType.STRING; + field.id = SUCCESS; + oprot.writeFieldBegin(field); + oprot.writeString(this.success); + oprot.writeFieldEnd(); + } + } else if (this.__isset.ex) { + if (this.ex != null) { + field.name = "ex"; + field.type = TType.STRUCT; + field.id = EX; + oprot.writeFieldBegin(field); + this.ex.write(oprot); + oprot.writeFieldEnd(); + } + } + oprot.writeFieldStop(); + oprot.writeStructEnd(); + } + + public String toString() { + StringBuilder sb = new StringBuilder("fetchOne_result("); + boolean first = true; + + if (!first) sb.append(", "); + sb.append("success:"); + sb.append(this.success); + first = false; + if (!first) sb.append(", "); + sb.append("ex:"); + sb.append(this.ex); + first = false; + sb.append(")"); + return sb.toString(); + } + + } + + public static class fetchN_args implements TBase, java.io.Serializable { + private int numRows; + public static final int NUMROWS = 1; + + public final Isset __isset = new Isset(); + public static final class Isset implements java.io.Serializable { + public boolean numRows = false; + } + + public fetchN_args() { + } + + public fetchN_args( + int numRows) + { + this(); + this.numRows = numRows; + this.__isset.numRows = true; + } + + public int getNumRows() { + return this.numRows; + } + + public void setNumRows(int numRows) { + this.numRows = numRows; + this.__isset.numRows = true; + } + + public void unsetNumRows() { + this.__isset.numRows = false; + } + + public void setFieldValue(int fieldID, Object value) { + switch (fieldID) { + case NUMROWS: + setNumRows((Integer)value); + break; + + default: + throw new IllegalArgumentException("Field " + fieldID + " doesn't exist!"); + } + } + + public Object getFieldValue(int fieldID) { + switch (fieldID) { + case NUMROWS: + return new Integer(getNumRows()); + + default: + throw new IllegalArgumentException("Field " + fieldID + " doesn't exist!"); + } + } + + public boolean equals(Object that) { + if (that == null) + return false; + if (that instanceof fetchN_args) + return this.equals((fetchN_args)that); + return false; + } + + public boolean equals(fetchN_args that) { + if (that == null) + return false; + + boolean this_present_numRows = true; + boolean that_present_numRows = true; + if (this_present_numRows || that_present_numRows) { + if (!(this_present_numRows && that_present_numRows)) + return false; + if (this.numRows != that.numRows) + return false; + } + + return true; + } + + public int hashCode() { + return 0; + } + + public void read(TProtocol iprot) throws TException { + TField field; + iprot.readStructBegin(); + while (true) + { + field = iprot.readFieldBegin(); + if (field.type == TType.STOP) { + break; + } + switch (field.id) + { + case NUMROWS: + if (field.type == TType.I32) { + this.numRows = iprot.readI32(); + this.__isset.numRows = true; + } else { + TProtocolUtil.skip(iprot, field.type); + } + break; + default: + TProtocolUtil.skip(iprot, field.type); + break; + } + iprot.readFieldEnd(); + } + iprot.readStructEnd(); + } + + public void write(TProtocol oprot) throws TException { + TStruct struct = new TStruct("fetchN_args"); + oprot.writeStructBegin(struct); + TField field = new TField(); + field.name = "numRows"; + field.type = TType.I32; + field.id = NUMROWS; + oprot.writeFieldBegin(field); + oprot.writeI32(this.numRows); + oprot.writeFieldEnd(); + oprot.writeFieldStop(); + oprot.writeStructEnd(); + } + + public String toString() { + StringBuilder sb = new StringBuilder("fetchN_args("); + boolean first = true; + + if (!first) sb.append(", "); + sb.append("numRows:"); + sb.append(this.numRows); + first = false; + sb.append(")"); + return sb.toString(); + } + + } + + public static class fetchN_result implements TBase, java.io.Serializable { + private List success; + public static final int SUCCESS = 0; + private HiveServerException ex; + public static final int EX = 1; + + public final Isset __isset = new Isset(); + public static final class Isset implements java.io.Serializable { + public boolean success = false; + public boolean ex = false; + } + + public fetchN_result() { + } + + public fetchN_result( + List success, + HiveServerException ex) + { + this(); + this.success = success; + this.__isset.success = (success != null); + this.ex = ex; + this.__isset.ex = (ex != null); + } + + public int getSuccessSize() { + return (this.success == null) ? 0 : this.success.size(); + } + + public java.util.Iterator getSuccessIterator() { + return (this.success == null) ? null : this.success.iterator(); + } + + public void addToSuccess(String elem) { + if (this.success == null) { + this.success = new ArrayList(); + } + this.success.add(elem); + this.__isset.success = true; + } + + public List getSuccess() { + return this.success; + } + + public void setSuccess(List success) { + this.success = success; + this.__isset.success = (success != null); + } + + public void unsetSuccess() { + this.success = null; + this.__isset.success = false; + } + + public HiveServerException getEx() { + return this.ex; + } + + public void setEx(HiveServerException ex) { + this.ex = ex; + this.__isset.ex = (ex != null); + } + + public void unsetEx() { + this.ex = null; + this.__isset.ex = false; + } + + public void setFieldValue(int fieldID, Object value) { + switch (fieldID) { + case SUCCESS: + setSuccess((List)value); + break; + + case EX: + setEx((HiveServerException)value); + break; + + default: + throw new IllegalArgumentException("Field " + fieldID + " doesn't exist!"); + } + } + + public Object getFieldValue(int fieldID) { + switch (fieldID) { + case SUCCESS: + return getSuccess(); + + case EX: + return getEx(); + + default: + throw new IllegalArgumentException("Field " + fieldID + " doesn't exist!"); + } + } + + public boolean equals(Object that) { + if (that == null) + return false; + if (that instanceof fetchN_result) + return this.equals((fetchN_result)that); + return false; + } + + public boolean equals(fetchN_result that) { + if (that == null) + return false; + + boolean this_present_success = true && (this.success != null); + boolean that_present_success = true && (that.success != null); + if (this_present_success || that_present_success) { + if (!(this_present_success && that_present_success)) + return false; + if (!this.success.equals(that.success)) + return false; + } + + boolean this_present_ex = true && (this.ex != null); + boolean that_present_ex = true && (that.ex != null); + if (this_present_ex || that_present_ex) { + if (!(this_present_ex && that_present_ex)) + return false; + if (!this.ex.equals(that.ex)) + return false; + } + + return true; + } + + public int hashCode() { + return 0; + } + + public void read(TProtocol iprot) throws TException { + TField field; + iprot.readStructBegin(); + while (true) + { + field = iprot.readFieldBegin(); + if (field.type == TType.STOP) { + break; + } + switch (field.id) + { + case SUCCESS: + if (field.type == TType.LIST) { + { + TList _list0 = iprot.readListBegin(); + this.success = new ArrayList(_list0.size); + for (int _i1 = 0; _i1 < _list0.size; ++_i1) + { + String _elem2 = null; + _elem2 = iprot.readString(); + this.success.add(_elem2); + } + iprot.readListEnd(); + } + this.__isset.success = true; + } else { + TProtocolUtil.skip(iprot, field.type); + } + break; + case EX: + if (field.type == TType.STRUCT) { + this.ex = new HiveServerException(); + this.ex.read(iprot); + this.__isset.ex = true; + } else { + TProtocolUtil.skip(iprot, field.type); + } + break; + default: + TProtocolUtil.skip(iprot, field.type); + break; + } + iprot.readFieldEnd(); + } + iprot.readStructEnd(); + } + + public void write(TProtocol oprot) throws TException { + TStruct struct = new TStruct("fetchN_result"); + oprot.writeStructBegin(struct); + TField field = new TField(); + + if (this.__isset.success) { + if (this.success != null) { + field.name = "success"; + field.type = TType.LIST; + field.id = SUCCESS; + oprot.writeFieldBegin(field); + { + oprot.writeListBegin(new TList(TType.STRING, this.success.size())); + for (String _iter3 : this.success) { + oprot.writeString(_iter3); + } + oprot.writeListEnd(); + } + oprot.writeFieldEnd(); + } + } else if (this.__isset.ex) { + if (this.ex != null) { + field.name = "ex"; + field.type = TType.STRUCT; + field.id = EX; + oprot.writeFieldBegin(field); + this.ex.write(oprot); + oprot.writeFieldEnd(); + } + } + oprot.writeFieldStop(); + oprot.writeStructEnd(); + } + + public String toString() { + StringBuilder sb = new StringBuilder("fetchN_result("); + boolean first = true; + + if (!first) sb.append(", "); + sb.append("success:"); + sb.append(this.success); + first = false; + if (!first) sb.append(", "); + sb.append("ex:"); + sb.append(this.ex); + first = false; + sb.append(")"); + return sb.toString(); + } + + } + + public static class fetchAll_args implements TBase, java.io.Serializable { + public fetchAll_args() { + } + + public void setFieldValue(int fieldID, Object value) { + switch (fieldID) { + default: + throw new IllegalArgumentException("Field " + fieldID + " doesn't exist!"); + } + } + + public Object getFieldValue(int fieldID) { + switch (fieldID) { + default: + throw new IllegalArgumentException("Field " + fieldID + " doesn't exist!"); + } + } + + public boolean equals(Object that) { + if (that == null) + return false; + if (that instanceof fetchAll_args) + return this.equals((fetchAll_args)that); + return false; + } + + public boolean equals(fetchAll_args that) { + if (that == null) + return false; + + return true; + } + + public int hashCode() { + return 0; + } + + public void read(TProtocol iprot) throws TException { + TField field; + iprot.readStructBegin(); + while (true) + { + field = iprot.readFieldBegin(); + if (field.type == TType.STOP) { + break; + } + switch (field.id) + { + default: + TProtocolUtil.skip(iprot, field.type); + break; + } + iprot.readFieldEnd(); + } + iprot.readStructEnd(); + } + + public void write(TProtocol oprot) throws TException { + TStruct struct = new TStruct("fetchAll_args"); + oprot.writeStructBegin(struct); + oprot.writeFieldStop(); + oprot.writeStructEnd(); + } + + public String toString() { + StringBuilder sb = new StringBuilder("fetchAll_args("); + boolean first = true; + + sb.append(")"); + return sb.toString(); + } + + } + + public static class fetchAll_result implements TBase, java.io.Serializable { + private List success; + public static final int SUCCESS = 0; + private HiveServerException ex; + public static final int EX = 1; + + public final Isset __isset = new Isset(); + public static final class Isset implements java.io.Serializable { + public boolean success = false; + public boolean ex = false; + } + + public fetchAll_result() { + } + + public fetchAll_result( + List success, + HiveServerException ex) + { + this(); + this.success = success; + this.__isset.success = (success != null); + this.ex = ex; + this.__isset.ex = (ex != null); + } + + public int getSuccessSize() { + return (this.success == null) ? 0 : this.success.size(); + } + + public java.util.Iterator getSuccessIterator() { + return (this.success == null) ? null : this.success.iterator(); + } + + public void addToSuccess(String elem) { + if (this.success == null) { + this.success = new ArrayList(); + } + this.success.add(elem); + this.__isset.success = true; + } + + public List getSuccess() { + return this.success; + } + + public void setSuccess(List success) { + this.success = success; + this.__isset.success = (success != null); + } + + public void unsetSuccess() { + this.success = null; + this.__isset.success = false; + } + + public HiveServerException getEx() { + return this.ex; + } + + public void setEx(HiveServerException ex) { + this.ex = ex; + this.__isset.ex = (ex != null); + } + + public void unsetEx() { + this.ex = null; + this.__isset.ex = false; + } + + public void setFieldValue(int fieldID, Object value) { + switch (fieldID) { + case SUCCESS: + setSuccess((List)value); + break; + + case EX: + setEx((HiveServerException)value); + break; + + default: + throw new IllegalArgumentException("Field " + fieldID + " doesn't exist!"); + } + } + + public Object getFieldValue(int fieldID) { + switch (fieldID) { + case SUCCESS: + return getSuccess(); + + case EX: + return getEx(); + + default: + throw new IllegalArgumentException("Field " + fieldID + " doesn't exist!"); + } + } + + public boolean equals(Object that) { + if (that == null) + return false; + if (that instanceof fetchAll_result) + return this.equals((fetchAll_result)that); + return false; + } + + public boolean equals(fetchAll_result that) { + if (that == null) + return false; + + boolean this_present_success = true && (this.success != null); + boolean that_present_success = true && (that.success != null); + if (this_present_success || that_present_success) { + if (!(this_present_success && that_present_success)) + return false; + if (!this.success.equals(that.success)) + return false; + } + + boolean this_present_ex = true && (this.ex != null); + boolean that_present_ex = true && (that.ex != null); + if (this_present_ex || that_present_ex) { + if (!(this_present_ex && that_present_ex)) + return false; + if (!this.ex.equals(that.ex)) + return false; + } + + return true; + } + + public int hashCode() { + return 0; + } + + public void read(TProtocol iprot) throws TException { + TField field; + iprot.readStructBegin(); + while (true) + { + field = iprot.readFieldBegin(); + if (field.type == TType.STOP) { + break; + } + switch (field.id) + { + case SUCCESS: + if (field.type == TType.LIST) { + { + TList _list4 = iprot.readListBegin(); + this.success = new ArrayList(_list4.size); + for (int _i5 = 0; _i5 < _list4.size; ++_i5) + { + String _elem6 = null; + _elem6 = iprot.readString(); + this.success.add(_elem6); + } + iprot.readListEnd(); + } + this.__isset.success = true; + } else { + TProtocolUtil.skip(iprot, field.type); + } + break; + case EX: + if (field.type == TType.STRUCT) { + this.ex = new HiveServerException(); + this.ex.read(iprot); + this.__isset.ex = true; + } else { + TProtocolUtil.skip(iprot, field.type); + } + break; + default: + TProtocolUtil.skip(iprot, field.type); + break; + } + iprot.readFieldEnd(); + } + iprot.readStructEnd(); + } + + public void write(TProtocol oprot) throws TException { + TStruct struct = new TStruct("fetchAll_result"); + oprot.writeStructBegin(struct); + TField field = new TField(); + + if (this.__isset.success) { + if (this.success != null) { + field.name = "success"; + field.type = TType.LIST; + field.id = SUCCESS; + oprot.writeFieldBegin(field); + { + oprot.writeListBegin(new TList(TType.STRING, this.success.size())); + for (String _iter7 : this.success) { + oprot.writeString(_iter7); + } + oprot.writeListEnd(); + } + oprot.writeFieldEnd(); + } + } else if (this.__isset.ex) { + if (this.ex != null) { + field.name = "ex"; + field.type = TType.STRUCT; + field.id = EX; + oprot.writeFieldBegin(field); + this.ex.write(oprot); + oprot.writeFieldEnd(); + } + } + oprot.writeFieldStop(); + oprot.writeStructEnd(); + } + + public String toString() { + StringBuilder sb = new StringBuilder("fetchAll_result("); + boolean first = true; + + if (!first) sb.append(", "); + sb.append("success:"); + sb.append(this.success); + first = false; + if (!first) sb.append(", "); + sb.append("ex:"); + sb.append(this.ex); + first = false; + sb.append(")"); + return sb.toString(); + } + + } + + public static class getSchema_args implements TBase, java.io.Serializable { + public getSchema_args() { + } + + public void setFieldValue(int fieldID, Object value) { + switch (fieldID) { + default: + throw new IllegalArgumentException("Field " + fieldID + " doesn't exist!"); + } + } + + public Object getFieldValue(int fieldID) { + switch (fieldID) { + default: + throw new IllegalArgumentException("Field " + fieldID + " doesn't exist!"); + } + } + + public boolean equals(Object that) { + if (that == null) + return false; + if (that instanceof getSchema_args) + return this.equals((getSchema_args)that); + return false; + } + + public boolean equals(getSchema_args that) { + if (that == null) + return false; + + return true; + } + + public int hashCode() { + return 0; + } + + public void read(TProtocol iprot) throws TException { + TField field; + iprot.readStructBegin(); + while (true) + { + field = iprot.readFieldBegin(); + if (field.type == TType.STOP) { + break; + } + switch (field.id) + { + default: + TProtocolUtil.skip(iprot, field.type); + break; + } + iprot.readFieldEnd(); + } + iprot.readStructEnd(); + } + + public void write(TProtocol oprot) throws TException { + TStruct struct = new TStruct("getSchema_args"); + oprot.writeStructBegin(struct); + oprot.writeFieldStop(); + oprot.writeStructEnd(); + } + + public String toString() { + StringBuilder sb = new StringBuilder("getSchema_args("); + boolean first = true; + + sb.append(")"); + return sb.toString(); + } + + } + + public static class getSchema_result implements TBase, java.io.Serializable { + private String success; + public static final int SUCCESS = 0; + private HiveServerException ex; + public static final int EX = 1; + + public final Isset __isset = new Isset(); + public static final class Isset implements java.io.Serializable { + public boolean success = false; + public boolean ex = false; + } + + public getSchema_result() { + } + + public getSchema_result( + String success, + HiveServerException ex) + { + this(); + this.success = success; + this.__isset.success = (success != null); + this.ex = ex; + this.__isset.ex = (ex != null); + } + + public String getSuccess() { + return this.success; + } + + public void setSuccess(String success) { + this.success = success; + this.__isset.success = (success != null); + } + + public void unsetSuccess() { + this.__isset.success = false; + } + + public HiveServerException getEx() { + return this.ex; + } + + public void setEx(HiveServerException ex) { + this.ex = ex; + this.__isset.ex = (ex != null); + } + + public void unsetEx() { + this.ex = null; + this.__isset.ex = false; + } + + public void setFieldValue(int fieldID, Object value) { + switch (fieldID) { + case SUCCESS: + setSuccess((String)value); + break; + + case EX: + setEx((HiveServerException)value); + break; + + default: + throw new IllegalArgumentException("Field " + fieldID + " doesn't exist!"); + } + } + + public Object getFieldValue(int fieldID) { + switch (fieldID) { + case SUCCESS: + return getSuccess(); + + case EX: + return getEx(); + + default: + throw new IllegalArgumentException("Field " + fieldID + " doesn't exist!"); + } + } + + public boolean equals(Object that) { + if (that == null) + return false; + if (that instanceof getSchema_result) + return this.equals((getSchema_result)that); + return false; + } + + public boolean equals(getSchema_result that) { + if (that == null) + return false; + + boolean this_present_success = true && (this.success != null); + boolean that_present_success = true && (that.success != null); + if (this_present_success || that_present_success) { + if (!(this_present_success && that_present_success)) + return false; + if (!this.success.equals(that.success)) + return false; + } + + boolean this_present_ex = true && (this.ex != null); + boolean that_present_ex = true && (that.ex != null); + if (this_present_ex || that_present_ex) { + if (!(this_present_ex && that_present_ex)) + return false; + if (!this.ex.equals(that.ex)) + return false; + } + + return true; + } + + public int hashCode() { + return 0; + } + + public void read(TProtocol iprot) throws TException { + TField field; + iprot.readStructBegin(); + while (true) + { + field = iprot.readFieldBegin(); + if (field.type == TType.STOP) { + break; + } + switch (field.id) + { + case SUCCESS: + if (field.type == TType.STRING) { + this.success = iprot.readString(); + this.__isset.success = true; + } else { + TProtocolUtil.skip(iprot, field.type); + } + break; + case EX: + if (field.type == TType.STRUCT) { + this.ex = new HiveServerException(); + this.ex.read(iprot); + this.__isset.ex = true; + } else { + TProtocolUtil.skip(iprot, field.type); + } + break; + default: + TProtocolUtil.skip(iprot, field.type); + break; + } + iprot.readFieldEnd(); + } + iprot.readStructEnd(); + } + + public void write(TProtocol oprot) throws TException { + TStruct struct = new TStruct("getSchema_result"); + oprot.writeStructBegin(struct); + TField field = new TField(); + + if (this.__isset.success) { + if (this.success != null) { + field.name = "success"; + field.type = TType.STRING; + field.id = SUCCESS; + oprot.writeFieldBegin(field); + oprot.writeString(this.success); + oprot.writeFieldEnd(); + } + } else if (this.__isset.ex) { + if (this.ex != null) { + field.name = "ex"; + field.type = TType.STRUCT; + field.id = EX; + oprot.writeFieldBegin(field); + this.ex.write(oprot); + oprot.writeFieldEnd(); + } + } + oprot.writeFieldStop(); + oprot.writeStructEnd(); + } + + public String toString() { + StringBuilder sb = new StringBuilder("getSchema_result("); + boolean first = true; + + if (!first) sb.append(", "); + sb.append("success:"); + sb.append(this.success); + first = false; + if (!first) sb.append(", "); + sb.append("ex:"); + sb.append(this.ex); + first = false; + sb.append(")"); + return sb.toString(); + } + + } + +} Index: service/src/gen-php/ThriftHive.php =================================================================== --- service/src/gen-php/ThriftHive.php (revision 0) +++ service/src/gen-php/ThriftHive.php (revision 0) @@ -0,0 +1,1186 @@ +send_execute($query); + $this->recv_execute(); + } + + public function send_execute($query) + { + $args = new ThriftHive_execute_args(); + $args->query = $query; + $bin_accel = ($this->output_ instanceof TProtocol::$TBINARYPROTOCOLACCELERATED) && function_exists('thrift_protocol_write_binary'); + if ($bin_accel) + { + thrift_protocol_write_binary($this->output_, 'execute', TMessageType::CALL, $args, $this->seqid_, $this->output_->isStrictWrite()); + } + else + { + $this->output_->writeMessageBegin('execute', TMessageType::CALL, $this->seqid_); + $args->write($this->output_); + $this->output_->writeMessageEnd(); + $this->output_->getTransport()->flush(); + } + } + + public function recv_execute() + { + $bin_accel = ($this->input_ instanceof TProtocol::$TBINARYPROTOCOLACCELERATED) && function_exists('thrift_protocol_read_binary'); + if ($bin_accel) $result = thrift_protocol_read_binary($this->input_, 'ThriftHive_execute_result', $this->input_->isStrictRead()); + else + { + $rseqid = 0; + $fname = null; + $mtype = 0; + + $this->input_->readMessageBegin($fname, $mtype, $rseqid); + if ($mtype == TMessageType::EXCEPTION) { + $x = new TApplicationException(); + $x->read($this->input_); + $this->input_->readMessageEnd(); + throw $x; + } + $result = new ThriftHive_execute_result(); + $result->read($this->input_); + $this->input_->readMessageEnd(); + } + if ($result->ex !== null) { + throw $result->ex; + } + return; + } + + public function fetchOne() + { + $this->send_fetchOne(); + return $this->recv_fetchOne(); + } + + public function send_fetchOne() + { + $args = new ThriftHive_fetchOne_args(); + $bin_accel = ($this->output_ instanceof TProtocol::$TBINARYPROTOCOLACCELERATED) && function_exists('thrift_protocol_write_binary'); + if ($bin_accel) + { + thrift_protocol_write_binary($this->output_, 'fetchOne', TMessageType::CALL, $args, $this->seqid_, $this->output_->isStrictWrite()); + } + else + { + $this->output_->writeMessageBegin('fetchOne', TMessageType::CALL, $this->seqid_); + $args->write($this->output_); + $this->output_->writeMessageEnd(); + $this->output_->getTransport()->flush(); + } + } + + public function recv_fetchOne() + { + $bin_accel = ($this->input_ instanceof TProtocol::$TBINARYPROTOCOLACCELERATED) && function_exists('thrift_protocol_read_binary'); + if ($bin_accel) $result = thrift_protocol_read_binary($this->input_, 'ThriftHive_fetchOne_result', $this->input_->isStrictRead()); + else + { + $rseqid = 0; + $fname = null; + $mtype = 0; + + $this->input_->readMessageBegin($fname, $mtype, $rseqid); + if ($mtype == TMessageType::EXCEPTION) { + $x = new TApplicationException(); + $x->read($this->input_); + $this->input_->readMessageEnd(); + throw $x; + } + $result = new ThriftHive_fetchOne_result(); + $result->read($this->input_); + $this->input_->readMessageEnd(); + } + if ($result->success !== null) { + return $result->success; + } + if ($result->ex !== null) { + throw $result->ex; + } + throw new Exception("fetchOne failed: unknown result"); + } + + public function fetchN($numRows) + { + $this->send_fetchN($numRows); + return $this->recv_fetchN(); + } + + public function send_fetchN($numRows) + { + $args = new ThriftHive_fetchN_args(); + $args->numRows = $numRows; + $bin_accel = ($this->output_ instanceof TProtocol::$TBINARYPROTOCOLACCELERATED) && function_exists('thrift_protocol_write_binary'); + if ($bin_accel) + { + thrift_protocol_write_binary($this->output_, 'fetchN', TMessageType::CALL, $args, $this->seqid_, $this->output_->isStrictWrite()); + } + else + { + $this->output_->writeMessageBegin('fetchN', TMessageType::CALL, $this->seqid_); + $args->write($this->output_); + $this->output_->writeMessageEnd(); + $this->output_->getTransport()->flush(); + } + } + + public function recv_fetchN() + { + $bin_accel = ($this->input_ instanceof TProtocol::$TBINARYPROTOCOLACCELERATED) && function_exists('thrift_protocol_read_binary'); + if ($bin_accel) $result = thrift_protocol_read_binary($this->input_, 'ThriftHive_fetchN_result', $this->input_->isStrictRead()); + else + { + $rseqid = 0; + $fname = null; + $mtype = 0; + + $this->input_->readMessageBegin($fname, $mtype, $rseqid); + if ($mtype == TMessageType::EXCEPTION) { + $x = new TApplicationException(); + $x->read($this->input_); + $this->input_->readMessageEnd(); + throw $x; + } + $result = new ThriftHive_fetchN_result(); + $result->read($this->input_); + $this->input_->readMessageEnd(); + } + if ($result->success !== null) { + return $result->success; + } + if ($result->ex !== null) { + throw $result->ex; + } + throw new Exception("fetchN failed: unknown result"); + } + + public function fetchAll() + { + $this->send_fetchAll(); + return $this->recv_fetchAll(); + } + + public function send_fetchAll() + { + $args = new ThriftHive_fetchAll_args(); + $bin_accel = ($this->output_ instanceof TProtocol::$TBINARYPROTOCOLACCELERATED) && function_exists('thrift_protocol_write_binary'); + if ($bin_accel) + { + thrift_protocol_write_binary($this->output_, 'fetchAll', TMessageType::CALL, $args, $this->seqid_, $this->output_->isStrictWrite()); + } + else + { + $this->output_->writeMessageBegin('fetchAll', TMessageType::CALL, $this->seqid_); + $args->write($this->output_); + $this->output_->writeMessageEnd(); + $this->output_->getTransport()->flush(); + } + } + + public function recv_fetchAll() + { + $bin_accel = ($this->input_ instanceof TProtocol::$TBINARYPROTOCOLACCELERATED) && function_exists('thrift_protocol_read_binary'); + if ($bin_accel) $result = thrift_protocol_read_binary($this->input_, 'ThriftHive_fetchAll_result', $this->input_->isStrictRead()); + else + { + $rseqid = 0; + $fname = null; + $mtype = 0; + + $this->input_->readMessageBegin($fname, $mtype, $rseqid); + if ($mtype == TMessageType::EXCEPTION) { + $x = new TApplicationException(); + $x->read($this->input_); + $this->input_->readMessageEnd(); + throw $x; + } + $result = new ThriftHive_fetchAll_result(); + $result->read($this->input_); + $this->input_->readMessageEnd(); + } + if ($result->success !== null) { + return $result->success; + } + if ($result->ex !== null) { + throw $result->ex; + } + throw new Exception("fetchAll failed: unknown result"); + } + + public function getSchema() + { + $this->send_getSchema(); + return $this->recv_getSchema(); + } + + public function send_getSchema() + { + $args = new ThriftHive_getSchema_args(); + $bin_accel = ($this->output_ instanceof TProtocol::$TBINARYPROTOCOLACCELERATED) && function_exists('thrift_protocol_write_binary'); + if ($bin_accel) + { + thrift_protocol_write_binary($this->output_, 'getSchema', TMessageType::CALL, $args, $this->seqid_, $this->output_->isStrictWrite()); + } + else + { + $this->output_->writeMessageBegin('getSchema', TMessageType::CALL, $this->seqid_); + $args->write($this->output_); + $this->output_->writeMessageEnd(); + $this->output_->getTransport()->flush(); + } + } + + public function recv_getSchema() + { + $bin_accel = ($this->input_ instanceof TProtocol::$TBINARYPROTOCOLACCELERATED) && function_exists('thrift_protocol_read_binary'); + if ($bin_accel) $result = thrift_protocol_read_binary($this->input_, 'ThriftHive_getSchema_result', $this->input_->isStrictRead()); + else + { + $rseqid = 0; + $fname = null; + $mtype = 0; + + $this->input_->readMessageBegin($fname, $mtype, $rseqid); + if ($mtype == TMessageType::EXCEPTION) { + $x = new TApplicationException(); + $x->read($this->input_); + $this->input_->readMessageEnd(); + throw $x; + } + $result = new ThriftHive_getSchema_result(); + $result->read($this->input_); + $this->input_->readMessageEnd(); + } + if ($result->success !== null) { + return $result->success; + } + if ($result->ex !== null) { + throw $result->ex; + } + throw new Exception("getSchema failed: unknown result"); + } + +} + +// HELPER FUNCTIONS AND STRUCTURES + +class ThriftHive_execute_args { + static $_TSPEC; + + public $query = null; + + public function __construct($vals=null) { + if (!isset(self::$_TSPEC)) { + self::$_TSPEC = array( + 1 => array( + 'var' => 'query', + 'type' => TType::STRING, + ), + ); + } + if (is_array($vals)) { + if (isset($vals['query'])) { + $this->query = $vals['query']; + } + } + } + + public function getName() { + return 'ThriftHive_execute_args'; + } + + public function read($input) + { + $xfer = 0; + $fname = null; + $ftype = 0; + $fid = 0; + $xfer += $input->readStructBegin($fname); + while (true) + { + $xfer += $input->readFieldBegin($fname, $ftype, $fid); + if ($ftype == TType::STOP) { + break; + } + switch ($fid) + { + case 1: + if ($ftype == TType::STRING) { + $xfer += $input->readString($this->query); + } else { + $xfer += $input->skip($ftype); + } + break; + default: + $xfer += $input->skip($ftype); + break; + } + $xfer += $input->readFieldEnd(); + } + $xfer += $input->readStructEnd(); + return $xfer; + } + + public function write($output) { + $xfer = 0; + $xfer += $output->writeStructBegin('ThriftHive_execute_args'); + if ($this->query !== null) { + $xfer += $output->writeFieldBegin('query', TType::STRING, 1); + $xfer += $output->writeString($this->query); + $xfer += $output->writeFieldEnd(); + } + $xfer += $output->writeFieldStop(); + $xfer += $output->writeStructEnd(); + return $xfer; + } + +} + +class ThriftHive_execute_result { + static $_TSPEC; + + public $ex = null; + + public function __construct($vals=null) { + if (!isset(self::$_TSPEC)) { + self::$_TSPEC = array( + 1 => array( + 'var' => 'ex', + 'type' => TType::STRUCT, + 'class' => 'HiveServerException', + ), + ); + } + if (is_array($vals)) { + if (isset($vals['ex'])) { + $this->ex = $vals['ex']; + } + } + } + + public function getName() { + return 'ThriftHive_execute_result'; + } + + public function read($input) + { + $xfer = 0; + $fname = null; + $ftype = 0; + $fid = 0; + $xfer += $input->readStructBegin($fname); + while (true) + { + $xfer += $input->readFieldBegin($fname, $ftype, $fid); + if ($ftype == TType::STOP) { + break; + } + switch ($fid) + { + case 1: + if ($ftype == TType::STRUCT) { + $this->ex = new HiveServerException(); + $xfer += $this->ex->read($input); + } else { + $xfer += $input->skip($ftype); + } + break; + default: + $xfer += $input->skip($ftype); + break; + } + $xfer += $input->readFieldEnd(); + } + $xfer += $input->readStructEnd(); + return $xfer; + } + + public function write($output) { + $xfer = 0; + $xfer += $output->writeStructBegin('ThriftHive_execute_result'); + if ($this->ex !== null) { + $xfer += $output->writeFieldBegin('ex', TType::STRUCT, 1); + $xfer += $this->ex->write($output); + $xfer += $output->writeFieldEnd(); + } + $xfer += $output->writeFieldStop(); + $xfer += $output->writeStructEnd(); + return $xfer; + } + +} + +class ThriftHive_fetchOne_args { + static $_TSPEC; + + + public function __construct() { + if (!isset(self::$_TSPEC)) { + self::$_TSPEC = array( + ); + } + } + + public function getName() { + return 'ThriftHive_fetchOne_args'; + } + + public function read($input) + { + $xfer = 0; + $fname = null; + $ftype = 0; + $fid = 0; + $xfer += $input->readStructBegin($fname); + while (true) + { + $xfer += $input->readFieldBegin($fname, $ftype, $fid); + if ($ftype == TType::STOP) { + break; + } + switch ($fid) + { + default: + $xfer += $input->skip($ftype); + break; + } + $xfer += $input->readFieldEnd(); + } + $xfer += $input->readStructEnd(); + return $xfer; + } + + public function write($output) { + $xfer = 0; + $xfer += $output->writeStructBegin('ThriftHive_fetchOne_args'); + $xfer += $output->writeFieldStop(); + $xfer += $output->writeStructEnd(); + return $xfer; + } + +} + +class ThriftHive_fetchOne_result { + static $_TSPEC; + + public $success = null; + public $ex = null; + + public function __construct($vals=null) { + if (!isset(self::$_TSPEC)) { + self::$_TSPEC = array( + 0 => array( + 'var' => 'success', + 'type' => TType::STRING, + ), + 1 => array( + 'var' => 'ex', + 'type' => TType::STRUCT, + 'class' => 'HiveServerException', + ), + ); + } + if (is_array($vals)) { + if (isset($vals['success'])) { + $this->success = $vals['success']; + } + if (isset($vals['ex'])) { + $this->ex = $vals['ex']; + } + } + } + + public function getName() { + return 'ThriftHive_fetchOne_result'; + } + + public function read($input) + { + $xfer = 0; + $fname = null; + $ftype = 0; + $fid = 0; + $xfer += $input->readStructBegin($fname); + while (true) + { + $xfer += $input->readFieldBegin($fname, $ftype, $fid); + if ($ftype == TType::STOP) { + break; + } + switch ($fid) + { + case 0: + if ($ftype == TType::STRING) { + $xfer += $input->readString($this->success); + } else { + $xfer += $input->skip($ftype); + } + break; + case 1: + if ($ftype == TType::STRUCT) { + $this->ex = new HiveServerException(); + $xfer += $this->ex->read($input); + } else { + $xfer += $input->skip($ftype); + } + break; + default: + $xfer += $input->skip($ftype); + break; + } + $xfer += $input->readFieldEnd(); + } + $xfer += $input->readStructEnd(); + return $xfer; + } + + public function write($output) { + $xfer = 0; + $xfer += $output->writeStructBegin('ThriftHive_fetchOne_result'); + if ($this->success !== null) { + $xfer += $output->writeFieldBegin('success', TType::STRING, 0); + $xfer += $output->writeString($this->success); + $xfer += $output->writeFieldEnd(); + } + if ($this->ex !== null) { + $xfer += $output->writeFieldBegin('ex', TType::STRUCT, 1); + $xfer += $this->ex->write($output); + $xfer += $output->writeFieldEnd(); + } + $xfer += $output->writeFieldStop(); + $xfer += $output->writeStructEnd(); + return $xfer; + } + +} + +class ThriftHive_fetchN_args { + static $_TSPEC; + + public $numRows = null; + + public function __construct($vals=null) { + if (!isset(self::$_TSPEC)) { + self::$_TSPEC = array( + 1 => array( + 'var' => 'numRows', + 'type' => TType::I32, + ), + ); + } + if (is_array($vals)) { + if (isset($vals['numRows'])) { + $this->numRows = $vals['numRows']; + } + } + } + + public function getName() { + return 'ThriftHive_fetchN_args'; + } + + public function read($input) + { + $xfer = 0; + $fname = null; + $ftype = 0; + $fid = 0; + $xfer += $input->readStructBegin($fname); + while (true) + { + $xfer += $input->readFieldBegin($fname, $ftype, $fid); + if ($ftype == TType::STOP) { + break; + } + switch ($fid) + { + case 1: + if ($ftype == TType::I32) { + $xfer += $input->readI32($this->numRows); + } else { + $xfer += $input->skip($ftype); + } + break; + default: + $xfer += $input->skip($ftype); + break; + } + $xfer += $input->readFieldEnd(); + } + $xfer += $input->readStructEnd(); + return $xfer; + } + + public function write($output) { + $xfer = 0; + $xfer += $output->writeStructBegin('ThriftHive_fetchN_args'); + if ($this->numRows !== null) { + $xfer += $output->writeFieldBegin('numRows', TType::I32, 1); + $xfer += $output->writeI32($this->numRows); + $xfer += $output->writeFieldEnd(); + } + $xfer += $output->writeFieldStop(); + $xfer += $output->writeStructEnd(); + return $xfer; + } + +} + +class ThriftHive_fetchN_result { + static $_TSPEC; + + public $success = null; + public $ex = null; + + public function __construct($vals=null) { + if (!isset(self::$_TSPEC)) { + self::$_TSPEC = array( + 0 => array( + 'var' => 'success', + 'type' => TType::LST, + 'etype' => TType::STRING, + 'elem' => array( + 'type' => TType::STRING, + ), + ), + 1 => array( + 'var' => 'ex', + 'type' => TType::STRUCT, + 'class' => 'HiveServerException', + ), + ); + } + if (is_array($vals)) { + if (isset($vals['success'])) { + $this->success = $vals['success']; + } + if (isset($vals['ex'])) { + $this->ex = $vals['ex']; + } + } + } + + public function getName() { + return 'ThriftHive_fetchN_result'; + } + + public function read($input) + { + $xfer = 0; + $fname = null; + $ftype = 0; + $fid = 0; + $xfer += $input->readStructBegin($fname); + while (true) + { + $xfer += $input->readFieldBegin($fname, $ftype, $fid); + if ($ftype == TType::STOP) { + break; + } + switch ($fid) + { + case 0: + if ($ftype == TType::LST) { + $this->success = array(); + $_size0 = 0; + $_etype3 = 0; + $xfer += $input->readListBegin($_etype3, $_size0); + for ($_i4 = 0; $_i4 < $_size0; ++$_i4) + { + $elem5 = null; + $xfer += $input->readString($elem5); + $this->success []= $elem5; + } + $xfer += $input->readListEnd(); + } else { + $xfer += $input->skip($ftype); + } + break; + case 1: + if ($ftype == TType::STRUCT) { + $this->ex = new HiveServerException(); + $xfer += $this->ex->read($input); + } else { + $xfer += $input->skip($ftype); + } + break; + default: + $xfer += $input->skip($ftype); + break; + } + $xfer += $input->readFieldEnd(); + } + $xfer += $input->readStructEnd(); + return $xfer; + } + + public function write($output) { + $xfer = 0; + $xfer += $output->writeStructBegin('ThriftHive_fetchN_result'); + if ($this->success !== null) { + if (!is_array($this->success)) { + throw new TProtocolException('Bad type in structure.', TProtocolException::INVALID_DATA); + } + $xfer += $output->writeFieldBegin('success', TType::LST, 0); + { + $output->writeListBegin(TType::STRING, count($this->success)); + { + foreach ($this->success as $iter6) + { + $xfer += $output->writeString($iter6); + } + } + $output->writeListEnd(); + } + $xfer += $output->writeFieldEnd(); + } + if ($this->ex !== null) { + $xfer += $output->writeFieldBegin('ex', TType::STRUCT, 1); + $xfer += $this->ex->write($output); + $xfer += $output->writeFieldEnd(); + } + $xfer += $output->writeFieldStop(); + $xfer += $output->writeStructEnd(); + return $xfer; + } + +} + +class ThriftHive_fetchAll_args { + static $_TSPEC; + + + public function __construct() { + if (!isset(self::$_TSPEC)) { + self::$_TSPEC = array( + ); + } + } + + public function getName() { + return 'ThriftHive_fetchAll_args'; + } + + public function read($input) + { + $xfer = 0; + $fname = null; + $ftype = 0; + $fid = 0; + $xfer += $input->readStructBegin($fname); + while (true) + { + $xfer += $input->readFieldBegin($fname, $ftype, $fid); + if ($ftype == TType::STOP) { + break; + } + switch ($fid) + { + default: + $xfer += $input->skip($ftype); + break; + } + $xfer += $input->readFieldEnd(); + } + $xfer += $input->readStructEnd(); + return $xfer; + } + + public function write($output) { + $xfer = 0; + $xfer += $output->writeStructBegin('ThriftHive_fetchAll_args'); + $xfer += $output->writeFieldStop(); + $xfer += $output->writeStructEnd(); + return $xfer; + } + +} + +class ThriftHive_fetchAll_result { + static $_TSPEC; + + public $success = null; + public $ex = null; + + public function __construct($vals=null) { + if (!isset(self::$_TSPEC)) { + self::$_TSPEC = array( + 0 => array( + 'var' => 'success', + 'type' => TType::LST, + 'etype' => TType::STRING, + 'elem' => array( + 'type' => TType::STRING, + ), + ), + 1 => array( + 'var' => 'ex', + 'type' => TType::STRUCT, + 'class' => 'HiveServerException', + ), + ); + } + if (is_array($vals)) { + if (isset($vals['success'])) { + $this->success = $vals['success']; + } + if (isset($vals['ex'])) { + $this->ex = $vals['ex']; + } + } + } + + public function getName() { + return 'ThriftHive_fetchAll_result'; + } + + public function read($input) + { + $xfer = 0; + $fname = null; + $ftype = 0; + $fid = 0; + $xfer += $input->readStructBegin($fname); + while (true) + { + $xfer += $input->readFieldBegin($fname, $ftype, $fid); + if ($ftype == TType::STOP) { + break; + } + switch ($fid) + { + case 0: + if ($ftype == TType::LST) { + $this->success = array(); + $_size7 = 0; + $_etype10 = 0; + $xfer += $input->readListBegin($_etype10, $_size7); + for ($_i11 = 0; $_i11 < $_size7; ++$_i11) + { + $elem12 = null; + $xfer += $input->readString($elem12); + $this->success []= $elem12; + } + $xfer += $input->readListEnd(); + } else { + $xfer += $input->skip($ftype); + } + break; + case 1: + if ($ftype == TType::STRUCT) { + $this->ex = new HiveServerException(); + $xfer += $this->ex->read($input); + } else { + $xfer += $input->skip($ftype); + } + break; + default: + $xfer += $input->skip($ftype); + break; + } + $xfer += $input->readFieldEnd(); + } + $xfer += $input->readStructEnd(); + return $xfer; + } + + public function write($output) { + $xfer = 0; + $xfer += $output->writeStructBegin('ThriftHive_fetchAll_result'); + if ($this->success !== null) { + if (!is_array($this->success)) { + throw new TProtocolException('Bad type in structure.', TProtocolException::INVALID_DATA); + } + $xfer += $output->writeFieldBegin('success', TType::LST, 0); + { + $output->writeListBegin(TType::STRING, count($this->success)); + { + foreach ($this->success as $iter13) + { + $xfer += $output->writeString($iter13); + } + } + $output->writeListEnd(); + } + $xfer += $output->writeFieldEnd(); + } + if ($this->ex !== null) { + $xfer += $output->writeFieldBegin('ex', TType::STRUCT, 1); + $xfer += $this->ex->write($output); + $xfer += $output->writeFieldEnd(); + } + $xfer += $output->writeFieldStop(); + $xfer += $output->writeStructEnd(); + return $xfer; + } + +} + +class ThriftHive_getSchema_args { + static $_TSPEC; + + + public function __construct() { + if (!isset(self::$_TSPEC)) { + self::$_TSPEC = array( + ); + } + } + + public function getName() { + return 'ThriftHive_getSchema_args'; + } + + public function read($input) + { + $xfer = 0; + $fname = null; + $ftype = 0; + $fid = 0; + $xfer += $input->readStructBegin($fname); + while (true) + { + $xfer += $input->readFieldBegin($fname, $ftype, $fid); + if ($ftype == TType::STOP) { + break; + } + switch ($fid) + { + default: + $xfer += $input->skip($ftype); + break; + } + $xfer += $input->readFieldEnd(); + } + $xfer += $input->readStructEnd(); + return $xfer; + } + + public function write($output) { + $xfer = 0; + $xfer += $output->writeStructBegin('ThriftHive_getSchema_args'); + $xfer += $output->writeFieldStop(); + $xfer += $output->writeStructEnd(); + return $xfer; + } + +} + +class ThriftHive_getSchema_result { + static $_TSPEC; + + public $success = null; + public $ex = null; + + public function __construct($vals=null) { + if (!isset(self::$_TSPEC)) { + self::$_TSPEC = array( + 0 => array( + 'var' => 'success', + 'type' => TType::STRING, + ), + 1 => array( + 'var' => 'ex', + 'type' => TType::STRUCT, + 'class' => 'HiveServerException', + ), + ); + } + if (is_array($vals)) { + if (isset($vals['success'])) { + $this->success = $vals['success']; + } + if (isset($vals['ex'])) { + $this->ex = $vals['ex']; + } + } + } + + public function getName() { + return 'ThriftHive_getSchema_result'; + } + + public function read($input) + { + $xfer = 0; + $fname = null; + $ftype = 0; + $fid = 0; + $xfer += $input->readStructBegin($fname); + while (true) + { + $xfer += $input->readFieldBegin($fname, $ftype, $fid); + if ($ftype == TType::STOP) { + break; + } + switch ($fid) + { + case 0: + if ($ftype == TType::STRING) { + $xfer += $input->readString($this->success); + } else { + $xfer += $input->skip($ftype); + } + break; + case 1: + if ($ftype == TType::STRUCT) { + $this->ex = new HiveServerException(); + $xfer += $this->ex->read($input); + } else { + $xfer += $input->skip($ftype); + } + break; + default: + $xfer += $input->skip($ftype); + break; + } + $xfer += $input->readFieldEnd(); + } + $xfer += $input->readStructEnd(); + return $xfer; + } + + public function write($output) { + $xfer = 0; + $xfer += $output->writeStructBegin('ThriftHive_getSchema_result'); + if ($this->success !== null) { + $xfer += $output->writeFieldBegin('success', TType::STRING, 0); + $xfer += $output->writeString($this->success); + $xfer += $output->writeFieldEnd(); + } + if ($this->ex !== null) { + $xfer += $output->writeFieldBegin('ex', TType::STRUCT, 1); + $xfer += $this->ex->write($output); + $xfer += $output->writeFieldEnd(); + } + $xfer += $output->writeFieldStop(); + $xfer += $output->writeStructEnd(); + return $xfer; + } + +} + +class ThriftHiveProcessor extends ThriftHiveMetastoreProcessor { + public function __construct($handler) { + parent::__construct($handler); + } + + public function process($input, $output) { + $rseqid = 0; + $fname = null; + $mtype = 0; + + $input->readMessageBegin($fname, $mtype, $rseqid); + $methodname = 'process_'.$fname; + if (!method_exists($this, $methodname)) { + $input->skip(TType::STRUCT); + $input->readMessageEnd(); + $x = new TApplicationException('Function '.$fname.' not implemented.', TApplicationException::UNKNOWN_METHOD); + $output->writeMessageBegin($fname, TMessageType::EXCEPTION, $rseqid); + $x->write($output); + $output->writeMessageEnd(); + $output->getTransport()->flush(); + return; + } + $this->$methodname($rseqid, $input, $output); + return true; + } + + protected function process_execute($seqid, $input, $output) { + $args = new ThriftHive_execute_args(); + $args->read($input); + $input->readMessageEnd(); + $result = new ThriftHive_execute_result(); + try { + $this->handler_->execute($args->query); + } catch (HiveServerException $ex) { + $result->ex = $ex; + } + $output->writeMessageBegin('execute', TMessageType::REPLY, $seqid); + $result->write($output); + $output->getTransport()->flush(); + } + protected function process_fetchOne($seqid, $input, $output) { + $args = new ThriftHive_fetchOne_args(); + $args->read($input); + $input->readMessageEnd(); + $result = new ThriftHive_fetchOne_result(); + try { + $result->success = $this->handler_->fetchOne(); + } catch (HiveServerException $ex) { + $result->ex = $ex; + } + $output->writeMessageBegin('fetchOne', TMessageType::REPLY, $seqid); + $result->write($output); + $output->getTransport()->flush(); + } + protected function process_fetchN($seqid, $input, $output) { + $args = new ThriftHive_fetchN_args(); + $args->read($input); + $input->readMessageEnd(); + $result = new ThriftHive_fetchN_result(); + try { + $result->success = $this->handler_->fetchN($args->numRows); + } catch (HiveServerException $ex) { + $result->ex = $ex; + } + $output->writeMessageBegin('fetchN', TMessageType::REPLY, $seqid); + $result->write($output); + $output->getTransport()->flush(); + } + protected function process_fetchAll($seqid, $input, $output) { + $args = new ThriftHive_fetchAll_args(); + $args->read($input); + $input->readMessageEnd(); + $result = new ThriftHive_fetchAll_result(); + try { + $result->success = $this->handler_->fetchAll(); + } catch (HiveServerException $ex) { + $result->ex = $ex; + } + $output->writeMessageBegin('fetchAll', TMessageType::REPLY, $seqid); + $result->write($output); + $output->getTransport()->flush(); + } + protected function process_getSchema($seqid, $input, $output) { + $args = new ThriftHive_getSchema_args(); + $args->read($input); + $input->readMessageEnd(); + $result = new ThriftHive_getSchema_result(); + try { + $result->success = $this->handler_->getSchema(); + } catch (HiveServerException $ex) { + $result->ex = $ex; + } + $output->writeMessageBegin('getSchema', TMessageType::REPLY, $seqid); + $result->write($output); + $output->getTransport()->flush(); + } +} +?> Index: service/src/gen-php/hive_service_types.php =================================================================== --- service/src/gen-php/hive_service_types.php (revision 0) +++ service/src/gen-php/hive_service_types.php (revision 0) @@ -0,0 +1,84 @@ + array( + 'var' => 'message', + 'type' => TType::STRING, + ), + ); + } + if (is_array($vals)) { + if (isset($vals['message'])) { + $this->message = $vals['message']; + } + } + } + + public function getName() { + return 'HiveServerException'; + } + + public function read($input) + { + $xfer = 0; + $fname = null; + $ftype = 0; + $fid = 0; + $xfer += $input->readStructBegin($fname); + while (true) + { + $xfer += $input->readFieldBegin($fname, $ftype, $fid); + if ($ftype == TType::STOP) { + break; + } + switch ($fid) + { + case -1: + if ($ftype == TType::STRING) { + $xfer += $input->readString($this->message); + } else { + $xfer += $input->skip($ftype); + } + break; + default: + $xfer += $input->skip($ftype); + break; + } + $xfer += $input->readFieldEnd(); + } + $xfer += $input->readStructEnd(); + return $xfer; + } + + public function write($output) { + $xfer = 0; + $xfer += $output->writeStructBegin('HiveServerException'); + if ($this->message !== null) { + $xfer += $output->writeFieldBegin('message', TType::STRING, -1); + $xfer += $output->writeString($this->message); + $xfer += $output->writeFieldEnd(); + } + $xfer += $output->writeFieldStop(); + $xfer += $output->writeStructEnd(); + return $xfer; + } + +} + +?> Index: service/build.xml =================================================================== --- service/build.xml (revision 0) +++ service/build.xml (revision 0) @@ -0,0 +1,51 @@ + + + + + + + + + + Executing thrift (which needs to be in your path) to build java metastore APIs.... + + + + + + + + + + + + + + + + + + + Index: service/if/hive_service.thrift =================================================================== --- service/if/hive_service.thrift (revision 0) +++ service/if/hive_service.thrift (revision 0) @@ -0,0 +1,26 @@ +#!/usr/local/bin/thrift -java +# +# Thrift Service that the hive service is built on +# + +# +# TODO: include/thrift is shared among different components. It +# should not be under metastore. + +include "thrift/fb303/if/fb303.thrift" +include "metastore/if/hive_metastore.thrift" + +namespace java org.apache.hadoop.hive.service +namespace php hive + +exception HiveServerException { + string message +} + +service ThriftHive extends hive_metastore.ThriftHiveMetastore { + void execute(1:string query) throws(1:HiveServerException ex) + string fetchOne() throws(1:HiveServerException ex) + list fetchN(1:i32 numRows) throws(1:HiveServerException ex) + list fetchAll() throws(1:HiveServerException ex) + string getSchema() throws(1:HiveServerException ex) +} Index: data/conf/hive-site.xml =================================================================== --- data/conf/hive-site.xml (revision 720079) +++ data/conf/hive-site.xml (working copy) @@ -97,7 +97,7 @@ test.data.files - ${user.dir}/../build/ql/test/data/files + ${user.dir}/../data/files Index: ql/src/java/org/apache/hadoop/hive/ql/exec/FetchTask.java =================================================================== --- ql/src/java/org/apache/hadoop/hive/ql/exec/FetchTask.java (revision 720079) +++ ql/src/java/org/apache/hadoop/hive/ql/exec/FetchTask.java (working copy) @@ -99,7 +99,15 @@ assert false; return 0; } - + + public tableDesc getTblDesc() { + return work.getTblDesc(); + } + + public Vector getColumnInfos() { + return work.getColumnInfos(); + } + /** * A cache of InputFormat instances. */ Index: ql/src/java/org/apache/hadoop/hive/ql/parse/SemanticAnalyzer.java =================================================================== --- ql/src/java/org/apache/hadoop/hive/ql/parse/SemanticAnalyzer.java (revision 720079) +++ ql/src/java/org/apache/hadoop/hive/ql/parse/SemanticAnalyzer.java (working copy) @@ -1873,7 +1873,7 @@ } this.loadFileWork.add(new loadFileDesc(queryTmpdir, dest_path, - (dest_type.intValue() == QBMetaData.DEST_DFS_FILE), cols)); + (dest_type.intValue() == QBMetaData.DEST_DFS_FILE), cols, colInfos)); table_desc = PlanUtils.getDefaultTableDesc(Integer.toString(Utilities.ctrlaCode), cols); break; @@ -2867,7 +2867,7 @@ Table tab = ((Map.Entry)iter.next()).getValue(); if (!tab.isPartitioned()) { if (qb.getParseInfo().getDestToWhereExpr().isEmpty()) - fetch = new fetchWork(tab.getPath(), Utilities.getTableDesc(tab), qb.getParseInfo().getOuterQueryLimit()); + fetch = new fetchWork(tab.getPath(), Utilities.getTableDesc(tab), qb.getParseInfo().getOuterQueryLimit(), null); } else { if (aliasToPruner.size() == 1) { @@ -2918,7 +2918,8 @@ Utilities.makeProperties( org.apache.hadoop.hive.serde.Constants.SERIALIZATION_FORMAT, "" + Utilities.ctrlaCode, "columns", cols)), - qb.getParseInfo().getOuterQueryLimit()); + qb.getParseInfo().getOuterQueryLimit(), + loadFileWork.get(0).getColumnInfos()); fetchTask = TaskFactory.get(fetch, this.conf); setFetchTask(fetchTask); Index: ql/src/java/org/apache/hadoop/hive/ql/plan/loadFileDesc.java =================================================================== --- ql/src/java/org/apache/hadoop/hive/ql/plan/loadFileDesc.java (revision 720079) +++ ql/src/java/org/apache/hadoop/hive/ql/plan/loadFileDesc.java (working copy) @@ -20,8 +20,10 @@ import java.io.Serializable; import java.util.List; +import java.util.Vector; import org.apache.hadoop.hive.ql.plan.loadDesc; +import org.apache.hadoop.hive.ql.exec.ColumnInfo; public class loadFileDesc extends loadDesc implements Serializable { private static final long serialVersionUID = 1L; @@ -29,18 +31,21 @@ private boolean isDfsDir; // list of columns, comma separated private String columns; + private Vector colInfos; public loadFileDesc() { } public loadFileDesc( final String sourceDir, final String targetDir, final boolean isDfsDir, - final String columns) { + final String columns, + final Vector colInfos) { super(sourceDir); this.targetDir = targetDir; this.isDfsDir = isDfsDir; this.columns = columns; + this.colInfos = colInfos; } @explain(displayName="destination") @@ -66,6 +71,14 @@ return columns; } + public Vector getColumnInfos() { + return colInfos; + } + + public void setColumnInfos(Vector colInfos) { + this.colInfos = colInfos; + } + /** * @param columns the columns to set */ Index: ql/src/java/org/apache/hadoop/hive/ql/plan/fetchWork.java =================================================================== --- ql/src/java/org/apache/hadoop/hive/ql/plan/fetchWork.java (revision 720079) +++ ql/src/java/org/apache/hadoop/hive/ql/plan/fetchWork.java (working copy) @@ -20,9 +20,11 @@ import java.io.Serializable; import java.util.List; +import java.util.Vector; import org.apache.hadoop.fs.Path; import org.apache.hadoop.hive.ql.plan.tableDesc; +import org.apache.hadoop.hive.ql.exec.ColumnInfo; @explain(displayName="Fetch Operator") public class fetchWork implements Serializable { @@ -33,15 +35,17 @@ private List partDir; private List partDesc; + private Vector colInfos; private int limit; public fetchWork() { } - public fetchWork(Path tblDir, tableDesc tblDesc, int limit) { + public fetchWork(Path tblDir, tableDesc tblDesc, int limit, Vector colInfos) { this.tblDir = tblDir; this.tblDesc = tblDesc; this.limit = limit; + this.colInfos = colInfos; } public fetchWork(List partDir, List partDesc, int limit) { @@ -49,7 +53,15 @@ this.partDesc = partDesc; this.limit = limit; } - + + public Vector getColumnInfos() { + return colInfos; + } + + public void setColumnInfos(Vector colInfos) { + this.colInfos = colInfos; + } + /** * @return the tblDir */ Index: ql/src/java/org/apache/hadoop/hive/ql/Driver.java =================================================================== --- ql/src/java/org/apache/hadoop/hive/ql/Driver.java (revision 720079) +++ ql/src/java/org/apache/hadoop/hive/ql/Driver.java (working copy) @@ -34,8 +34,11 @@ import org.apache.hadoop.hive.ql.session.SessionState; import org.apache.hadoop.hive.ql.session.SessionState.LogHelper; import org.apache.hadoop.hive.ql.exec.Task; +import org.apache.hadoop.hive.ql.exec.FetchTask; +import org.apache.hadoop.hive.ql.exec.ColumnInfo; import org.apache.hadoop.hive.ql.exec.TaskFactory; import org.apache.hadoop.hive.ql.exec.Utilities; +import org.apache.hadoop.hive.ql.plan.tableDesc; import org.apache.hadoop.hive.serde.ByteStream; import org.apache.hadoop.hive.conf.HiveConf; @@ -68,6 +71,30 @@ return jobs; } + public tableDesc getResultTblDesc() { + if (sem != null && sem.getFetchTask() != null) { + if (!sem.getFetchTaskInit()) { + sem.setFetchTaskInit(true); + sem.getFetchTask().initialize(conf); + } + FetchTask ft = (FetchTask)sem.getFetchTask(); + return ft.getTblDesc(); + } + return null; + } + + public Vector getResultColumnInfos() { + if (sem != null && sem.getFetchTask() != null) { + if (!sem.getFetchTaskInit()) { + sem.setFetchTaskInit(true); + sem.getFetchTask().initialize(conf); + } + FetchTask ft = (FetchTask)sem.getFetchTask(); + return ft.getColumnInfos(); + } + return null; + } + public boolean hasReduceTasks(List> tasks) { if (tasks == null) return false;