should be it

This commit is contained in:
2025-10-24 19:21:19 -05:00
parent a4b23fc57c
commit f09560c7b1
14047 changed files with 3161551 additions and 1 deletions

View File

@@ -0,0 +1,239 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
--------------------------------------------------
SOFTWARE DISTRIBUTED WITH THRIFT:
The Apache Thrift software includes a number of subcomponents with
separate copyright notices and license terms. Your use of the source
code for the these subcomponents is subject to the terms and
conditions of the following licenses.
--------------------------------------------------
Portions of the following files are licensed under the MIT License:
lib/erl/src/Makefile.am
Please see doc/otp-base-license.txt for the full terms of this license.
--------------------------------------------------
For the aclocal/ax_boost_base.m4 and contrib/fb303/aclocal/ax_boost_base.m4 components:
# Copyright (c) 2007 Thomas Porschberg <thomas@randspringer.de>
#
# Copying and distribution of this file, with or without
# modification, are permitted in any medium without royalty provided
# the copyright notice and this notice are preserved.
--------------------------------------------------
For the lib/nodejs/lib/thrift/json_parse.js:
/*
json_parse.js
2015-05-02
Public Domain.
NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
*/
(By Douglas Crockford <douglas@crockford.com>)
--------------------------------------------------

View File

@@ -0,0 +1,112 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
#ifndef _DUCKDB_THRIFT_TAPPLICATIONEXCEPTION_H_
#define _DUCKDB_THRIFT_TAPPLICATIONEXCEPTION_H_ 1
#include "thrift/Thrift.h"
namespace duckdb_apache {
namespace thrift {
namespace protocol {
class TProtocol;
}
class TApplicationException : public TException {
public:
/**
* Error codes for the various types of exceptions.
*/
enum TApplicationExceptionType {
UNKNOWN = 0,
UNKNOWN_METHOD = 1,
INVALID_MESSAGE_TYPE = 2,
WRONG_METHOD_NAME = 3,
BAD_SEQUENCE_ID = 4,
MISSING_RESULT = 5,
INTERNAL_ERROR = 6,
PROTOCOL_ERROR = 7,
INVALID_TRANSFORM = 8,
INVALID_PROTOCOL = 9,
UNSUPPORTED_CLIENT_TYPE = 10
};
TApplicationException() : TException(), type_(UNKNOWN) {}
TApplicationException(TApplicationExceptionType type) : TException(), type_(type) {}
TApplicationException(const std::string& message) : TException(message), type_(UNKNOWN) {}
TApplicationException(TApplicationExceptionType type, const std::string& message)
: TException(message), type_(type) {}
~TApplicationException() noexcept override = default;
/**
* Returns an error code that provides information about the type of error
* that has occurred.
*
* @return Error code
*/
TApplicationExceptionType getType() const { return type_; }
const char* what() const noexcept override {
if (message_.empty()) {
switch (type_) {
case UNKNOWN:
return "TApplicationException: Unknown application exception";
case UNKNOWN_METHOD:
return "TApplicationException: Unknown method";
case INVALID_MESSAGE_TYPE:
return "TApplicationException: Invalid message type";
case WRONG_METHOD_NAME:
return "TApplicationException: Wrong method name";
case BAD_SEQUENCE_ID:
return "TApplicationException: Bad sequence identifier";
case MISSING_RESULT:
return "TApplicationException: Missing result";
case INTERNAL_ERROR:
return "TApplicationException: Internal error";
case PROTOCOL_ERROR:
return "TApplicationException: Protocol error";
case INVALID_TRANSFORM:
return "TApplicationException: Invalid transform";
case INVALID_PROTOCOL:
return "TApplicationException: Invalid protocol";
case UNSUPPORTED_CLIENT_TYPE:
return "TApplicationException: Unsupported client type";
default:
return "TApplicationException: (Invalid exception type)";
};
} else {
return message_.c_str();
}
}
protected:
/**
* Error code
*/
TApplicationExceptionType type_;
};
}
} // duckdb_apache::thrift
#endif // #ifndef _DUCKDB_THRIFT_TAPPLICATIONEXCEPTION_H_

View File

@@ -0,0 +1,38 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
#ifndef _DUCKDB_THRIFT_TBASE_H_
#define _DUCKDB_THRIFT_TBASE_H_ 1
#include "thrift/Thrift.h"
#include "thrift/protocol/TProtocol.h"
namespace duckdb_apache {
namespace thrift {
class TBase {
public:
virtual ~TBase() = default;
virtual uint32_t read(protocol::TProtocol* iprot) = 0;
virtual uint32_t write(protocol::TProtocol* oprot) const = 0;
};
}
} // duckdb_apache::thrift
#endif // #ifndef _DUCKDB_THRIFT_TBASE_H_

View File

@@ -0,0 +1,145 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
#ifndef _DUCKDB_THRIFT_TLOGGING_H_
#define _DUCKDB_THRIFT_TLOGGING_H_ 1
#include "thrift/thrift-config.h"
/**
* Contains utility macros for debugging and logging.
*
*/
#include <time.h>
#ifdef HAVE_STDINT_H
#include <stdint.h>
#endif
/**
* T_GLOBAL_DEBUGGING_LEVEL = 0: all debugging turned off, debug macros undefined
* T_GLOBAL_DEBUGGING_LEVEL = 1: all debugging turned on
*/
#define T_GLOBAL_DEBUGGING_LEVEL 0
/**
* T_GLOBAL_LOGGING_LEVEL = 0: all logging turned off, logging macros undefined
* T_GLOBAL_LOGGING_LEVEL = 1: all logging turned on
*/
#define T_GLOBAL_LOGGING_LEVEL 0
/**
* Standard wrapper around fprintf what will prefix the file name and line
* number to the line. Uses T_GLOBAL_DEBUGGING_LEVEL to control whether it is
* turned on or off.
*
* @param format_string
*/
#if T_GLOBAL_DEBUGGING_LEVEL > 0
#define T_DEBUG(format_string, ...) \
if (T_GLOBAL_DEBUGGING_LEVEL > 0) { \
fprintf(stderr, "[%s,%d] " format_string " \n", __FILE__, __LINE__, ##__VA_ARGS__); \
}
#else
#define T_DEBUG(format_string, ...)
#endif
/**
* analogous to T_DEBUG but also prints the time
*
* @param string format_string input: printf style format string
*/
#if T_GLOBAL_DEBUGGING_LEVEL > 0
#define T_DEBUG_T(format_string, ...) \
{ \
if (T_GLOBAL_DEBUGGING_LEVEL > 0) { \
time_t now; \
char dbgtime[26]; \
time(&now); \
THRIFT_CTIME_R(&now, dbgtime); \
dbgtime[24] = '\0'; \
fprintf(stderr, \
"[%s,%d] [%s] " format_string " \n", \
__FILE__, \
__LINE__, \
dbgtime, \
##__VA_ARGS__); \
} \
}
#else
#define T_DEBUG_T(format_string, ...)
#endif
/**
* Log input message
*
* @param string format_string input: printf style format string
*/
#if T_GLOBAL_LOGGING_LEVEL > 0
#define T_LOG_OPER(format_string, ...) \
{ \
if (T_GLOBAL_LOGGING_LEVEL > 0) { \
time_t now; \
char dbgtime[26]; \
time(&now); \
THRIFT_CTIME_R(&now, dbgtime); \
dbgtime[24] = '\0'; \
fprintf(stderr, "[%s] " format_string " \n", dbgtime, ##__VA_ARGS__); \
} \
}
#else
#define T_LOG_OPER(format_string, ...)
#endif
/**
* T_GLOBAL_DEBUG_VIRTUAL = 0 or unset: normal operation,
* virtual call debug messages disabled
* T_GLOBAL_DEBUG_VIRTUAL = 1: log a debug messages whenever an
* avoidable virtual call is made
* T_GLOBAL_DEBUG_VIRTUAL = 2: record detailed info that can be
* printed by calling
* duckdb_apache::thrift::profile_print_info()
*/
#if T_GLOBAL_DEBUG_VIRTUAL > 1
#define T_VIRTUAL_CALL() ::duckdb_apache::thrift::profile_virtual_call(typeid(*this))
#define T_GENERIC_PROTOCOL(template_class, generic_prot, specific_prot) \
do { \
if (!(specific_prot)) { \
::duckdb_apache::thrift::profile_generic_protocol(typeid(*template_class), typeid(*generic_prot)); \
} \
} while (0)
#elif T_GLOBAL_DEBUG_VIRTUAL == 1
#define T_VIRTUAL_CALL() fprintf(stderr, "[%s,%d] virtual call\n", __FILE__, __LINE__)
#define T_GENERIC_PROTOCOL(template_class, generic_prot, specific_prot) \
do { \
if (!(specific_prot)) { \
fprintf(stderr, "[%s,%d] failed to cast to specific protocol type\n", __FILE__, __LINE__); \
} \
} while (0)
#else
#define T_VIRTUAL_CALL()
#define T_GENERIC_PROTOCOL(template_class, generic_prot, specific_prot)
#endif
#endif // #ifndef _DUCKDB_THRIFT_TLOGGING_H_

View File

@@ -0,0 +1,114 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
#ifndef _DUCKDB_THRIFT_TOSTRING_H_
#define _DUCKDB_THRIFT_TOSTRING_H_ 1
#include <cmath>
#include <limits>
#include <map>
#include <set>
#include <sstream>
#include <string>
#include "duckdb/common/vector.hpp"
namespace duckdb_apache {
namespace thrift {
template <typename T>
std::string to_string(const T& t) {
std::ostringstream o;
o << t;
return o.str();
}
// TODO: replace the computations below with std::numeric_limits::max_digits10 once C++11
// is enabled.
inline std::string to_string(const float& t) {
std::ostringstream o;
o.precision(static_cast<std::streamsize>(std::ceil(static_cast<double>(std::numeric_limits<float>::digits * std::log10(2.0f) + 1))));
o << t;
return o.str();
}
inline std::string to_string(const double& t) {
std::ostringstream o;
o.precision(static_cast<std::streamsize>(std::ceil(static_cast<double>(std::numeric_limits<double>::digits * std::log10(2.0f) + 1))));
o << t;
return o.str();
}
inline std::string to_string(const long double& t) {
std::ostringstream o;
o.precision(static_cast<std::streamsize>(std::ceil(static_cast<double>(std::numeric_limits<long double>::digits * std::log10(2.0f) + 1))));
o << t;
return o.str();
}
template <typename K, typename V>
std::string to_string(const std::map<K, V>& m);
template <typename T>
std::string to_string(const std::set<T>& s);
template <typename T>
std::string to_string(const duckdb::vector<T>& t);
template <typename K, typename V>
std::string to_string(const typename std::pair<K, V>& v) {
std::ostringstream o;
o << to_string(v.first) << ": " << to_string(v.second);
return o.str();
}
template <typename T>
std::string to_string(const T& beg, const T& end) {
std::ostringstream o;
for (T it = beg; it != end; ++it) {
if (it != beg)
o << ", ";
o << to_string(*it);
}
return o.str();
}
template <typename T>
std::string to_string(const duckdb::vector<T>& t) {
std::ostringstream o;
o << "[" << to_string(t.begin(), t.end()) << "]";
return o.str();
}
template <typename K, typename V>
std::string to_string(const std::map<K, V>& m) {
std::ostringstream o;
o << "{" << to_string(m.begin(), m.end()) << "}";
return o.str();
}
template <typename T>
std::string to_string(const std::set<T>& s) {
std::ostringstream o;
o << "{" << to_string(s.begin(), s.end()) << "}";
return o.str();
}
}
} // duckdb_apache::thrift
#endif // _DUCKDB_THRIFT_TOSTRING_H_

View File

@@ -0,0 +1,139 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
#ifndef _DUCKDB_THRIFT_THRIFT_H_
#define _DUCKDB_THRIFT_THRIFT_H_ 1
#include "thrift/transport/PlatformSocket.h"
#include "thrift/thrift-config.h"
#include <stdio.h>
#include <assert.h>
#include <sys/types.h>
#ifdef HAVE_NETINET_IN_H
#include <netinet/in.h>
#endif
#ifdef HAVE_INTTYPES_H
#include <inttypes.h>
#endif
#include <string>
#include <map>
#include <list>
#include <set>
#include <vector>
#include <exception>
#include <typeinfo>
#include <cstddef>
#include "thrift/TLogging.h"
//#include <thrift/TOutput.h>
#define THRIFT_UNUSED_VARIABLE(x) ((void)(x))
namespace duckdb_apache {
namespace thrift {
class TEnumIterator {
public:
using value_type = std::pair<int, const char*>;
using difference_type = std::ptrdiff_t;
using pointer = value_type*;
using reference = value_type&;
using iterator_category = std::forward_iterator_tag;
TEnumIterator(int n, int* enums, const char** names)
: ii_(0), n_(n), enums_(enums), names_(names) {}
int operator++() { return ++ii_; }
bool operator!=(const TEnumIterator& end) {
THRIFT_UNUSED_VARIABLE(end);
assert(end.n_ == -1);
return (ii_ != n_);
}
std::pair<int, const char*> operator*() const { return std::make_pair(enums_[ii_], names_[ii_]); }
private:
int ii_;
const int n_;
int* enums_;
const char** names_;
};
class TException : public std::exception {
public:
TException() : message_() {}
TException(const std::string& message) : message_(message) {}
~TException() noexcept override = default;
const char* what() const noexcept override {
if (message_.empty()) {
return "Default TException.";
} else {
return message_.c_str();
}
}
protected:
std::string message_;
};
class TDelayedException {
public:
template <class E>
static TDelayedException* delayException(const E& e);
virtual void throw_it() = 0;
virtual ~TDelayedException() = default;
};
template <class E>
class TExceptionWrapper : public TDelayedException {
public:
TExceptionWrapper(const E& e) : e_(e) {}
void throw_it() override {
E temp(e_);
delete this;
throw temp;
}
private:
E e_;
};
template <class E>
TDelayedException* TDelayedException::delayException(const E& e) {
return new TExceptionWrapper<E>(e);
}
#if T_GLOBAL_DEBUG_VIRTUAL > 1
void profile_virtual_call(const std::type_info& info);
void profile_generic_protocol(const std::type_info& template_type, const std::type_info& prot_type);
void profile_print_info(FILE* f);
void profile_print_info();
void profile_write_pprof(FILE* gen_calls_f, FILE* virtual_calls_f);
#endif
}
} // duckdb_apache::thrift
#endif // #ifndef _DUCKDB_THRIFT_THRIFT_H_

View File

@@ -0,0 +1,266 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
#ifndef _DUCKDB_THRIFT_PROTOCOL_TCOMPACTPROTOCOL_H_
#define _DUCKDB_THRIFT_PROTOCOL_TCOMPACTPROTOCOL_H_ 1
#include "thrift/protocol/TVirtualProtocol.h"
#include <stack>
#include <memory>
namespace duckdb_apache {
namespace thrift {
namespace protocol {
/**
* C++ Implementation of the Compact Protocol as described in THRIFT-110
*/
template <class Transport_>
class TCompactProtocolT : public TVirtualProtocol<TCompactProtocolT<Transport_> > {
public:
static const int8_t PROTOCOL_ID = (int8_t)0x82u;
static const int8_t VERSION_N = 1;
static const int8_t VERSION_MASK = 0x1f; // 0001 1111
protected:
static const int8_t TYPE_MASK = (int8_t)0xE0u; // 1110 0000
static const int8_t TYPE_BITS = 0x07; // 0000 0111
static const int32_t TYPE_SHIFT_AMOUNT = 5;
Transport_* trans_;
/**
* (Writing) If we encounter a boolean field begin, save the TField here
* so it can have the value incorporated.
*/
struct {
const char* name;
TType fieldType;
int16_t fieldId;
} booleanField_;
/**
* (Reading) If we read a field header, and it's a boolean field, save
* the boolean value here so that readBool can use it.
*/
struct {
bool hasBoolValue;
bool boolValue;
} boolValue_;
/**
* Used to keep track of the last field for the current and previous structs,
* so we can do the delta stuff.
*/
std::stack<int16_t> lastField_;
int16_t lastFieldId_;
public:
TCompactProtocolT(std::shared_ptr<Transport_> trans)
: TVirtualProtocol<TCompactProtocolT<Transport_> >(trans),
trans_(trans.get()),
lastFieldId_(0),
string_limit_(0),
string_buf_(nullptr),
string_buf_size_(0),
container_limit_(0) {
booleanField_.name = nullptr;
boolValue_.hasBoolValue = false;
}
TCompactProtocolT(std::shared_ptr<Transport_> trans,
int32_t string_limit,
int32_t container_limit)
: TVirtualProtocol<TCompactProtocolT<Transport_> >(trans),
trans_(trans.get()),
lastFieldId_(0),
string_limit_(string_limit),
string_buf_(nullptr),
string_buf_size_(0),
container_limit_(container_limit) {
booleanField_.name = nullptr;
boolValue_.hasBoolValue = false;
}
~TCompactProtocolT() override { free(string_buf_); }
/**
* Writing functions
*/
virtual uint32_t writeMessageBegin(const std::string& name,
const TMessageType messageType,
const int32_t seqid);
uint32_t writeStructBegin(const char* name);
uint32_t writeStructEnd();
uint32_t writeFieldBegin(const char* name, const TType fieldType, const int16_t fieldId);
uint32_t writeFieldStop();
uint32_t writeListBegin(const TType elemType, const uint32_t size);
uint32_t writeSetBegin(const TType elemType, const uint32_t size);
virtual uint32_t writeMapBegin(const TType keyType, const TType valType, const uint32_t size);
uint32_t writeBool(const bool value);
uint32_t writeByte(const int8_t byte);
uint32_t writeI16(const int16_t i16);
uint32_t writeI32(const int32_t i32);
uint32_t writeI64(const int64_t i64);
uint32_t writeDouble(const double dub);
uint32_t writeString(const std::string& str);
uint32_t writeBinary(const std::string& str);
/**
* These methods are called by structs, but don't actually have any wired
* output or purpose
*/
virtual uint32_t writeMessageEnd() { return 0; }
uint32_t writeMapEnd() { return 0; }
uint32_t writeListEnd() { return 0; }
uint32_t writeSetEnd() { return 0; }
uint32_t writeFieldEnd() { return 0; }
protected:
int32_t writeFieldBeginInternal(const char* name,
const TType fieldType,
const int16_t fieldId,
int8_t typeOverride);
uint32_t writeCollectionBegin(const TType elemType, int32_t size);
uint32_t writeBignum32(uint32_t n);
uint32_t writeBignum64(uint64_t n);
uint64_t i64ToZigzag(const int64_t l);
uint32_t i32ToZigzag(const int32_t n);
inline int8_t getCompactType(const TType ttype);
public:
uint32_t readMessageBegin(std::string& name, TMessageType& messageType, int32_t& seqid);
uint32_t readStructBegin(std::string& name);
uint32_t readStructEnd();
uint32_t readFieldBegin(std::string& name, TType& fieldType, int16_t& fieldId);
uint32_t readMapBegin(TType& keyType, TType& valType, uint32_t& size);
uint32_t readListBegin(TType& elemType, uint32_t& size);
uint32_t readSetBegin(TType& elemType, uint32_t& size);
uint32_t readBool(bool& value);
// Provide the default readBool() implementation for std::vector<bool>
using TVirtualProtocol<TCompactProtocolT<Transport_> >::readBool;
uint32_t readByte(int8_t& byte);
uint32_t readI16(int16_t& i16);
uint32_t readI32(int32_t& i32);
uint32_t readI64(int64_t& i64);
uint32_t readDouble(double& dub);
uint32_t readString(std::string& str);
uint32_t readBinary(std::string& str);
/*
*These methods are here for the struct to call, but don't have any wire
* encoding.
*/
uint32_t readMessageEnd() { return 0; }
uint32_t readFieldEnd() { return 0; }
uint32_t readMapEnd() { return 0; }
uint32_t readListEnd() { return 0; }
uint32_t readSetEnd() { return 0; }
protected:
uint32_t readBignum32(int32_t& i32);
uint32_t readBignum64(int64_t& i64);
int32_t zigzagToI32(uint32_t n);
int64_t zigzagToI64(uint64_t n);
TType getTType(int8_t type);
// Buffer for reading strings, save for the lifetime of the protocol to
// avoid memory churn allocating memory on every string read
int32_t string_limit_;
uint8_t* string_buf_;
int32_t string_buf_size_;
int32_t container_limit_;
};
typedef TCompactProtocolT<TTransport> TCompactProtocol;
/**
* Constructs compact protocol handlers
*/
template <class Transport_>
class TCompactProtocolFactoryT : public TProtocolFactory {
public:
TCompactProtocolFactoryT() : string_limit_(0), container_limit_(0) {}
TCompactProtocolFactoryT(int32_t string_limit, int32_t container_limit)
: string_limit_(string_limit), container_limit_(container_limit) {}
~TCompactProtocolFactoryT() override = default;
void setStringSizeLimit(int32_t string_limit) { string_limit_ = string_limit; }
void setContainerSizeLimit(int32_t container_limit) { container_limit_ = container_limit; }
std::shared_ptr<TProtocol> getProtocol(std::shared_ptr<TTransport> trans) override {
std::shared_ptr<Transport_> specific_trans = std::static_pointer_cast<Transport_>(trans);
TProtocol* prot;
if (specific_trans) {
prot = new TCompactProtocolT<Transport_>(specific_trans, string_limit_, container_limit_);
} else {
prot = new TCompactProtocol(trans, string_limit_, container_limit_);
}
return std::shared_ptr<TProtocol>(prot);
}
private:
int32_t string_limit_;
int32_t container_limit_;
};
typedef TCompactProtocolFactoryT<TTransport> TCompactProtocolFactory;
}
}
} // duckdb_apache::thrift::protocol
#include "thrift/protocol/TCompactProtocol.tcc"
#endif

View File

@@ -0,0 +1,826 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
#ifndef _DUCKDB_THRIFT_PROTOCOL_TCOMPACTPROTOCOL_TCC_
#define _DUCKDB_THRIFT_PROTOCOL_TCOMPACTPROTOCOL_TCC_ 1
#include <limits>
/*
* TCompactProtocol::i*ToZigzag depend on the fact that the right shift
* operator on a signed integer is an arithmetic (sign-extending) shift.
* If this is not the case, the current implementation will not work.
* If anyone encounters this error, we can try to figure out the best
* way to implement an arithmetic right shift on their platform.
*/
#if !defined(SIGNED_RIGHT_SHIFT_IS) || !defined(ARITHMETIC_RIGHT_SHIFT)
# error "Unable to determine the behavior of a signed right shift"
#endif
#if SIGNED_RIGHT_SHIFT_IS != ARITHMETIC_RIGHT_SHIFT
# error "TCompactProtocol currently only works if a signed right shift is arithmetic"
#endif
#ifndef UNLIKELY
#ifdef __GNUC__
#define UNLIKELY(val) (__builtin_expect((val), 0))
#else
#define UNLIKELY(val) (val)
#endif
#endif
namespace duckdb_apache { namespace thrift { namespace protocol {
namespace detail { namespace compact {
enum Types {
CT_STOP = 0x00,
CT_BOOLEAN_TRUE = 0x01,
CT_BOOLEAN_FALSE = 0x02,
CT_BYTE = 0x03,
CT_I16 = 0x04,
CT_I32 = 0x05,
CT_I64 = 0x06,
CT_DOUBLE = 0x07,
CT_BINARY = 0x08,
CT_LIST = 0x09,
CT_SET = 0x0A,
CT_MAP = 0x0B,
CT_STRUCT = 0x0C
};
const int8_t TTypeToCType[16] = {
CT_STOP, // T_STOP
0, // unused
CT_BOOLEAN_TRUE, // T_BOOL
CT_BYTE, // T_BYTE
CT_DOUBLE, // T_DOUBLE
0, // unused
CT_I16, // T_I16
0, // unused
CT_I32, // T_I32
0, // unused
CT_I64, // T_I64
CT_BINARY, // T_STRING
CT_STRUCT, // T_STRUCT
CT_MAP, // T_MAP
CT_SET, // T_SET
CT_LIST, // T_LIST
};
}} // end detail::compact namespace
template <class Transport_>
uint32_t TCompactProtocolT<Transport_>::writeMessageBegin(
const std::string& name,
const TMessageType messageType,
const int32_t seqid) {
uint32_t wsize = 0;
wsize += writeByte(PROTOCOL_ID);
wsize += writeByte((VERSION_N & VERSION_MASK) | (((int32_t)messageType << TYPE_SHIFT_AMOUNT) & TYPE_MASK));
wsize += writeBignum32(seqid);
wsize += writeString(name);
return wsize;
}
/**
* Write a field header containing the field id and field type. If the
* difference between the current field id and the last one is small (< 15),
* then the field id will be encoded in the 4 MSB as a delta. Otherwise, the
* field id will follow the type header as a zigzag bignum.
*/
template <class Transport_>
uint32_t TCompactProtocolT<Transport_>::writeFieldBegin(const char* name,
const TType fieldType,
const int16_t fieldId) {
if (fieldType == T_BOOL) {
booleanField_.name = name;
booleanField_.fieldType = fieldType;
booleanField_.fieldId = fieldId;
} else {
return writeFieldBeginInternal(name, fieldType, fieldId, -1);
}
return 0;
}
/**
* Write the STOP symbol so we know there are no more fields in this struct.
*/
template <class Transport_>
uint32_t TCompactProtocolT<Transport_>::writeFieldStop() {
return writeByte(T_STOP);
}
/**
* Write a struct begin. This doesn't actually put anything on the wire. We
* use it as an opportunity to put special placeholder markers on the field
* stack so we can get the field id deltas correct.
*/
template <class Transport_>
uint32_t TCompactProtocolT<Transport_>::writeStructBegin(const char* name) {
(void) name;
lastField_.push(lastFieldId_);
lastFieldId_ = 0;
return 0;
}
/**
* Write a struct end. This doesn't actually put anything on the wire. We use
* this as an opportunity to pop the last field from the current struct off
* of the field stack.
*/
template <class Transport_>
uint32_t TCompactProtocolT<Transport_>::writeStructEnd() {
lastFieldId_ = lastField_.top();
lastField_.pop();
return 0;
}
/**
* Write a List header.
*/
template <class Transport_>
uint32_t TCompactProtocolT<Transport_>::writeListBegin(const TType elemType,
const uint32_t size) {
return writeCollectionBegin(elemType, size);
}
/**
* Write a set header.
*/
template <class Transport_>
uint32_t TCompactProtocolT<Transport_>::writeSetBegin(const TType elemType,
const uint32_t size) {
return writeCollectionBegin(elemType, size);
}
/**
* Write a map header. If the map is empty, omit the key and value type
* headers, as we don't need any additional information to skip it.
*/
template <class Transport_>
uint32_t TCompactProtocolT<Transport_>::writeMapBegin(const TType keyType,
const TType valType,
const uint32_t size) {
uint32_t wsize = 0;
if (size == 0) {
wsize += writeByte(0);
} else {
wsize += writeBignum32(size);
wsize += writeByte(getCompactType(keyType) << 4 | getCompactType(valType));
}
return wsize;
}
/**
* Write a boolean value. Potentially, this could be a boolean field, in
* which case the field header info isn't written yet. If so, decide what the
* right type header is for the value and then write the field header.
* Otherwise, write a single byte.
*/
template <class Transport_>
uint32_t TCompactProtocolT<Transport_>::writeBool(const bool value) {
uint32_t wsize = 0;
if (booleanField_.name != NULL) {
// we haven't written the field header yet
wsize
+= writeFieldBeginInternal(booleanField_.name,
booleanField_.fieldType,
booleanField_.fieldId,
static_cast<int8_t>(value
? detail::compact::CT_BOOLEAN_TRUE
: detail::compact::CT_BOOLEAN_FALSE));
booleanField_.name = NULL;
} else {
// we're not part of a field, so just write the value
wsize
+= writeByte(static_cast<int8_t>(value
? detail::compact::CT_BOOLEAN_TRUE
: detail::compact::CT_BOOLEAN_FALSE));
}
return wsize;
}
template <class Transport_>
uint32_t TCompactProtocolT<Transport_>::writeByte(const int8_t byte) {
trans_->write((uint8_t*)&byte, 1);
return 1;
}
/**
* Write an i16 as a zigzag bignum.
*/
template <class Transport_>
uint32_t TCompactProtocolT<Transport_>::writeI16(const int16_t i16) {
return writeBignum32(i32ToZigzag(i16));
}
/**
* Write an i32 as a zigzag bignum.
*/
template <class Transport_>
uint32_t TCompactProtocolT<Transport_>::writeI32(const int32_t i32) {
return writeBignum32(i32ToZigzag(i32));
}
/**
* Write an i64 as a zigzag bignum.
*/
template <class Transport_>
uint32_t TCompactProtocolT<Transport_>::writeI64(const int64_t i64) {
return writeBignum64(i64ToZigzag(i64));
}
/**
* Write a double to the wire as 8 bytes.
*/
template <class Transport_>
uint32_t TCompactProtocolT<Transport_>::writeDouble(const double dub) {
//BOOST_STATIC_ASSERT(sizeof(double) == sizeof(uint64_t));
//BOOST_STATIC_ASSERT(std::numeric_limits<double>::is_iec559);
uint64_t bits = bitwise_cast<uint64_t>(dub);
bits = THRIFT_htolell(bits);
trans_->write((uint8_t*)&bits, 8);
return 8;
}
/**
* Write a string to the wire with a bignum size preceding.
*/
template <class Transport_>
uint32_t TCompactProtocolT<Transport_>::writeString(const std::string& str) {
return writeBinary(str);
}
template <class Transport_>
uint32_t TCompactProtocolT<Transport_>::writeBinary(const std::string& str) {
if(str.size() > (std::numeric_limits<uint32_t>::max)())
throw TProtocolException(TProtocolException::SIZE_LIMIT);
uint32_t ssize = static_cast<uint32_t>(str.size());
uint32_t wsize = writeBignum32(ssize) ;
// checking ssize + wsize > uint_max, but we don't want to overflow while checking for overflows.
// transforming the check to ssize > uint_max - wsize
if(ssize > (std::numeric_limits<uint32_t>::max)() - wsize)
throw TProtocolException(TProtocolException::SIZE_LIMIT);
wsize += ssize;
trans_->write((uint8_t*)str.data(), ssize);
return wsize;
}
//
// Internal Writing methods
//
/**
* The workhorse of writeFieldBegin. It has the option of doing a
* 'type override' of the type header. This is used specifically in the
* boolean field case.
*/
template <class Transport_>
int32_t TCompactProtocolT<Transport_>::writeFieldBeginInternal(
const char* name,
const TType fieldType,
const int16_t fieldId,
int8_t typeOverride) {
(void) name;
uint32_t wsize = 0;
// if there's a type override, use that.
int8_t typeToWrite = (typeOverride == -1 ? getCompactType(fieldType) : typeOverride);
// check if we can use delta encoding for the field id
if (fieldId > lastFieldId_ && fieldId - lastFieldId_ <= 15) {
// write them together
wsize += writeByte(static_cast<int8_t>((fieldId - lastFieldId_)
<< 4 | typeToWrite));
} else {
// write them separate
wsize += writeByte(typeToWrite);
wsize += writeI16(fieldId);
}
lastFieldId_ = fieldId;
return wsize;
}
/**
* Abstract method for writing the start of lists and sets. List and sets on
* the wire differ only by the type indicator.
*/
template <class Transport_>
uint32_t TCompactProtocolT<Transport_>::writeCollectionBegin(const TType elemType,
int32_t size) {
uint32_t wsize = 0;
if (size <= 14) {
wsize += writeByte(static_cast<int8_t>(size
<< 4 | getCompactType(elemType)));
} else {
wsize += writeByte(0xf0 | getCompactType(elemType));
wsize += writeBignum32(size);
}
return wsize;
}
/**
* Write an i32 as a bignum. Results in 1-5 bytes on the wire.
*/
template <class Transport_>
uint32_t TCompactProtocolT<Transport_>::writeBignum32(uint32_t n) {
uint8_t buf[5];
uint32_t wsize = 0;
while (true) {
if ((n & ~0x7F) == 0) {
buf[wsize++] = (int8_t)n;
break;
} else {
buf[wsize++] = (int8_t)((n & 0x7F) | 0x80);
n >>= 7;
}
}
trans_->write(buf, wsize);
return wsize;
}
/**
* Write an i64 as a bignum. Results in 1-10 bytes on the wire.
*/
template <class Transport_>
uint32_t TCompactProtocolT<Transport_>::writeBignum64(uint64_t n) {
uint8_t buf[10];
uint32_t wsize = 0;
while (true) {
if ((n & ~0x7FL) == 0) {
buf[wsize++] = (int8_t)n;
break;
} else {
buf[wsize++] = (int8_t)((n & 0x7F) | 0x80);
n >>= 7;
}
}
trans_->write(buf, wsize);
return wsize;
}
/**
* Convert l into a zigzag long. This allows negative numbers to be
* represented compactly as a bignum.
*/
template <class Transport_>
uint64_t TCompactProtocolT<Transport_>::i64ToZigzag(const int64_t l) {
return (static_cast<uint64_t>(l) << 1) ^ (l >> 63);
}
/**
* Convert n into a zigzag int. This allows negative numbers to be
* represented compactly as a bignum.
*/
template <class Transport_>
uint32_t TCompactProtocolT<Transport_>::i32ToZigzag(const int32_t n) {
return (static_cast<uint32_t>(n) << 1) ^ (n >> 31);
}
/**
* Given a TType value, find the appropriate detail::compact::Types value
*/
template <class Transport_>
int8_t TCompactProtocolT<Transport_>::getCompactType(const TType ttype) {
return detail::compact::TTypeToCType[ttype];
}
//
// Reading Methods
//
/**
* Read a message header.
*/
template <class Transport_>
uint32_t TCompactProtocolT<Transport_>::readMessageBegin(
std::string& name,
TMessageType& messageType,
int32_t& seqid) {
uint32_t rsize = 0;
int8_t protocolId;
int8_t versionAndType;
int8_t version;
rsize += readByte(protocolId);
if (protocolId != PROTOCOL_ID) {
throw TProtocolException(TProtocolException::BAD_VERSION, "Bad protocol identifier");
}
rsize += readByte(versionAndType);
version = (int8_t)(versionAndType & VERSION_MASK);
if (version != VERSION_N) {
throw TProtocolException(TProtocolException::BAD_VERSION, "Bad protocol version");
}
messageType = (TMessageType)((versionAndType >> TYPE_SHIFT_AMOUNT) & TYPE_BITS);
rsize += readBignum32(seqid);
rsize += readString(name);
return rsize;
}
/**
* Read a struct begin. There's nothing on the wire for this, but it is our
* opportunity to push a new struct begin marker on the field stack.
*/
template <class Transport_>
uint32_t TCompactProtocolT<Transport_>::readStructBegin(std::string& name) {
name = "";
lastField_.push(lastFieldId_);
lastFieldId_ = 0;
return 0;
}
/**
* Doesn't actually consume any wire data, just removes the last field for
* this struct from the field stack.
*/
template <class Transport_>
uint32_t TCompactProtocolT<Transport_>::readStructEnd() {
lastFieldId_ = lastField_.top();
lastField_.pop();
return 0;
}
/**
* Read a field header off the wire.
*/
template <class Transport_>
uint32_t TCompactProtocolT<Transport_>::readFieldBegin(std::string& name,
TType& fieldType,
int16_t& fieldId) {
(void) name;
uint32_t rsize = 0;
int8_t byte;
int8_t type;
rsize += readByte(byte);
type = (byte & 0x0f);
// if it's a stop, then we can return immediately, as the struct is over.
if (type == T_STOP) {
fieldType = T_STOP;
fieldId = 0;
return rsize;
}
// mask off the 4 MSB of the type header. it could contain a field id delta.
int16_t modifier = (int16_t)(((uint8_t)byte & 0xf0) >> 4);
if (modifier == 0) {
// not a delta, look ahead for the zigzag bignum field id.
rsize += readI16(fieldId);
} else {
fieldId = (int16_t)(lastFieldId_ + modifier);
}
fieldType = getTType(type);
// if this happens to be a boolean field, the value is encoded in the type
if (type == detail::compact::CT_BOOLEAN_TRUE ||
type == detail::compact::CT_BOOLEAN_FALSE) {
// save the boolean value in a special instance variable.
boolValue_.hasBoolValue = true;
boolValue_.boolValue =
(type == detail::compact::CT_BOOLEAN_TRUE ? true : false);
}
// push the new field onto the field stack so we can keep the deltas going.
lastFieldId_ = fieldId;
return rsize;
}
/**
* Read a map header off the wire. If the size is zero, skip reading the key
* and value type. This means that 0-length maps will yield TMaps without the
* "correct" types.
*/
template <class Transport_>
uint32_t TCompactProtocolT<Transport_>::readMapBegin(TType& keyType,
TType& valType,
uint32_t& size) {
uint32_t rsize = 0;
int8_t kvType = 0;
int32_t msize = 0;
rsize += readBignum32(msize);
if (msize != 0)
rsize += readByte(kvType);
if (msize < 0) {
throw TProtocolException(TProtocolException::NEGATIVE_SIZE);
} else if (container_limit_ && msize > container_limit_) {
throw TProtocolException(TProtocolException::SIZE_LIMIT);
}
keyType = getTType((int8_t)((uint8_t)kvType >> 4));
valType = getTType((int8_t)((uint8_t)kvType & 0xf));
size = (uint32_t)msize;
return rsize;
}
/**
* Read a list header off the wire. If the list size is 0-14, the size will
* be packed into the element type header. If it's a longer list, the 4 MSB
* of the element type header will be 0xF, and a bignum will follow with the
* true size.
*/
template <class Transport_>
uint32_t TCompactProtocolT<Transport_>::readListBegin(TType& elemType,
uint32_t& size) {
int8_t size_and_type;
uint32_t rsize = 0;
int32_t lsize;
rsize += readByte(size_and_type);
lsize = ((uint8_t)size_and_type >> 4) & 0x0f;
if (lsize == 15) {
rsize += readBignum32(lsize);
}
if (lsize < 0) {
throw TProtocolException(TProtocolException::NEGATIVE_SIZE);
} else if (container_limit_ && lsize > container_limit_) {
throw TProtocolException(TProtocolException::SIZE_LIMIT);
}
elemType = getTType((int8_t)(size_and_type & 0x0f));
size = (uint32_t)lsize;
return rsize;
}
/**
* Read a set header off the wire. If the set size is 0-14, the size will
* be packed into the element type header. If it's a longer set, the 4 MSB
* of the element type header will be 0xF, and a bignum will follow with the
* true size.
*/
template <class Transport_>
uint32_t TCompactProtocolT<Transport_>::readSetBegin(TType& elemType,
uint32_t& size) {
return readListBegin(elemType, size);
}
/**
* Read a boolean off the wire. If this is a boolean field, the value should
* already have been read during readFieldBegin, so we'll just consume the
* pre-stored value. Otherwise, read a byte.
*/
template <class Transport_>
uint32_t TCompactProtocolT<Transport_>::readBool(bool& value) {
if (boolValue_.hasBoolValue == true) {
value = boolValue_.boolValue;
boolValue_.hasBoolValue = false;
return 0;
} else {
int8_t val;
readByte(val);
value = (val == detail::compact::CT_BOOLEAN_TRUE);
return 1;
}
}
/**
* Read a single byte off the wire. Nothing interesting here.
*/
template <class Transport_>
uint32_t TCompactProtocolT<Transport_>::readByte(int8_t& byte) {
uint8_t b[1];
trans_->readAll(b, 1);
byte = *(int8_t*)b;
return 1;
}
/**
* Read an i16 from the wire as a zigzag bignum.
*/
template <class Transport_>
uint32_t TCompactProtocolT<Transport_>::readI16(int16_t& i16) {
int32_t value;
uint32_t rsize = readBignum32(value);
i16 = (int16_t)zigzagToI32(value);
return rsize;
}
/**
* Read an i32 from the wire as a zigzag bignum.
*/
template <class Transport_>
uint32_t TCompactProtocolT<Transport_>::readI32(int32_t& i32) {
int32_t value;
uint32_t rsize = readBignum32(value);
i32 = zigzagToI32(value);
return rsize;
}
/**
* Read an i64 from the wire as a zigzag bignum.
*/
template <class Transport_>
uint32_t TCompactProtocolT<Transport_>::readI64(int64_t& i64) {
int64_t value;
uint32_t rsize = readBignum64(value);
i64 = zigzagToI64(value);
return rsize;
}
/**
* No magic here - just read a double off the wire.
*/
template <class Transport_>
uint32_t TCompactProtocolT<Transport_>::readDouble(double& dub) {
//BOOST_STATIC_ASSERT(sizeof(double) == sizeof(uint64_t));
//BOOST_STATIC_ASSERT(std::numeric_limits<double>::is_iec559);
union {
uint64_t bits;
uint8_t b[8];
} u;
trans_->readAll(u.b, 8);
u.bits = THRIFT_letohll(u.bits);
dub = bitwise_cast<double>(u.bits);
return 8;
}
template <class Transport_>
uint32_t TCompactProtocolT<Transport_>::readString(std::string& str) {
return readBinary(str);
}
/**
* Read a byte[] from the wire.
*/
template <class Transport_>
uint32_t TCompactProtocolT<Transport_>::readBinary(std::string& str) {
int32_t rsize = 0;
int32_t size;
rsize += readBignum32(size);
// Catch empty string case
if (size == 0) {
str = "";
return rsize;
}
// Catch error cases
if (size < 0) {
throw TProtocolException(TProtocolException::NEGATIVE_SIZE);
}
if (string_limit_ > 0 && size > string_limit_) {
throw TProtocolException(TProtocolException::SIZE_LIMIT);
}
// Use the heap here to prevent stack overflow for v. large strings
if (size > string_buf_size_ || string_buf_ == NULL) {
void* new_string_buf = std::realloc(string_buf_, (uint32_t)size);
if (new_string_buf == NULL) {
throw std::bad_alloc();
}
string_buf_ = (uint8_t*)new_string_buf;
string_buf_size_ = size;
}
trans_->readAll(string_buf_, size);
str.assign((char*)string_buf_, size);
return rsize + (uint32_t)size;
}
/**
* Read an i32 from the wire as a bignum. The MSB of each byte is set
* if there is another byte to follow. This can read up to 5 bytes.
*/
template <class Transport_>
uint32_t TCompactProtocolT<Transport_>::readBignum32(int32_t& i32) {
int64_t val;
uint32_t rsize = readBignum64(val);
i32 = (int32_t)val;
return rsize;
}
/**
* Read an i64 from the wire as a proper bignum. The MSB of each byte is set
* if there is another byte to follow. This can read up to 10 bytes.
*/
template <class Transport_>
uint32_t TCompactProtocolT<Transport_>::readBignum64(int64_t& i64) {
uint32_t rsize = 0;
uint64_t val = 0;
int shift = 0;
uint8_t buf[10]; // 64 bits / (7 bits/byte) = 10 bytes.
uint32_t buf_size = sizeof(buf);
const uint8_t* borrowed = trans_->borrow(buf, &buf_size);
// Fast path.
if (borrowed != NULL) {
while (true) {
uint8_t byte = borrowed[rsize];
rsize++;
val |= (uint64_t)(byte & 0x7f) << shift;
shift += 7;
if (!(byte & 0x80)) {
i64 = val;
trans_->consume(rsize);
return rsize;
}
// Have to check for invalid data so we don't crash.
if (UNLIKELY(rsize == sizeof(buf))) {
throw TProtocolException(TProtocolException::INVALID_DATA, "Variable-length int over 10 bytes.");
}
}
}
// Slow path.
else {
while (true) {
uint8_t byte;
rsize += trans_->readAll(&byte, 1);
val |= (uint64_t)(byte & 0x7f) << shift;
shift += 7;
if (!(byte & 0x80)) {
i64 = val;
return rsize;
}
// Might as well check for invalid data on the slow path too.
if (UNLIKELY(rsize >= sizeof(buf))) {
throw TProtocolException(TProtocolException::INVALID_DATA, "Variable-length int over 10 bytes.");
}
}
}
}
/**
* Convert from zigzag int to int.
*/
template <class Transport_>
int32_t TCompactProtocolT<Transport_>::zigzagToI32(uint32_t n) {
return (n >> 1) ^ static_cast<uint32_t>(-static_cast<int32_t>(n & 1));
}
/**
* Convert from zigzag long to long.
*/
template <class Transport_>
int64_t TCompactProtocolT<Transport_>::zigzagToI64(uint64_t n) {
return (n >> 1) ^ static_cast<uint64_t>(-static_cast<int64_t>(n & 1));
}
template <class Transport_>
TType TCompactProtocolT<Transport_>::getTType(int8_t type) {
switch (type) {
case T_STOP:
return T_STOP;
case detail::compact::CT_BOOLEAN_FALSE:
case detail::compact::CT_BOOLEAN_TRUE:
return T_BOOL;
case detail::compact::CT_BYTE:
return T_BYTE;
case detail::compact::CT_I16:
return T_I16;
case detail::compact::CT_I32:
return T_I32;
case detail::compact::CT_I64:
return T_I64;
case detail::compact::CT_DOUBLE:
return T_DOUBLE;
case detail::compact::CT_BINARY:
return T_STRING;
case detail::compact::CT_LIST:
return T_LIST;
case detail::compact::CT_SET:
return T_SET;
case detail::compact::CT_MAP:
return T_MAP;
case detail::compact::CT_STRUCT:
return T_STRUCT;
default:
throw TException(std::string("don't know what type: ") + (char)type);
}
}
}}} // duckdb_apache::thrift::protocol
#endif // _DUCKDB_THRIFT_PROTOCOL_TCOMPACTPROTOCOL_TCC_

View File

@@ -0,0 +1,33 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
#include "thrift/protocol/TProtocol.h"
namespace duckdb_apache {
namespace thrift {
namespace protocol {
TProtocol::~TProtocol() = default;
uint32_t TProtocol::skip_virt(TType type) {
return ::duckdb_apache::thrift::protocol::skip(*this, type);
}
TProtocolFactory::~TProtocolFactory() = default;
}}} // duckdb_apache::thrift::protocol

View File

@@ -0,0 +1,766 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
#ifndef _DUCKDB_THRIFT_PROTOCOL_TPROTOCOL_H_
#define _DUCKDB_THRIFT_PROTOCOL_TPROTOCOL_H_ 1
#ifdef _WIN32
// Need to come before any Windows.h includes
#include <winsock2.h>
#endif
#include "thrift/transport/TTransport.h"
#include "thrift/protocol/TProtocolException.h"
#include <memory>
#ifdef HAVE_NETINET_IN_H
#include <netinet/in.h>
#endif
#include <sys/types.h>
#include <string>
#include <map>
#include "duckdb/common/vector.hpp"
#include <climits>
// Use this to get around strict aliasing rules.
// For example, uint64_t i = bitwise_cast<uint64_t>(returns_double());
// The most obvious implementation is to just cast a pointer,
// but that doesn't work.
// For a pretty in-depth explanation of the problem, see
// http://cellperformance.beyond3d.com/articles/2006/06/understanding-strict-aliasing.html
namespace duckdb_apache { namespace thrift {
template <typename To, typename From>
static inline To bitwise_cast(From from) {
static_assert(sizeof(From) == sizeof(To), "sizeof(From) == sizeof(To)");
// BAD!!! These are all broken with -O2.
// return *reinterpret_cast<To*>(&from); // BAD!!!
// return *static_cast<To*>(static_cast<void*>(&from)); // BAD!!!
// return *(To*)(void*)&from; // BAD!!!
// Super clean and paritally blessed by section 3.9 of the standard.
// unsigned char c[sizeof(from)];
// memcpy(c, &from, sizeof(from));
// To to;
// memcpy(&to, c, sizeof(c));
// return to;
// Slightly more questionable.
// Same code emitted by GCC.
// To to;
// memcpy(&to, &from, sizeof(from));
// return to;
// Technically undefined, but almost universally supported,
// and the most efficient implementation.
union {
From f;
To t;
} u;
u.f = from;
return u.t;
}
}} // namespace duckdb_apache::thrift
#ifdef HAVE_SYS_PARAM_H
#include <sys/param.h>
#endif
#ifndef __THRIFT_BYTE_ORDER
# if defined(BYTE_ORDER) && defined(LITTLE_ENDIAN) && defined(BIG_ENDIAN)
# define __THRIFT_BYTE_ORDER BYTE_ORDER
# define __THRIFT_LITTLE_ENDIAN LITTLE_ENDIAN
# define __THRIFT_BIG_ENDIAN BIG_ENDIAN
# else
//# include <boost/predef/other/endian.h>
# if BOOST_ENDIAN_BIG_BYTE
# define __THRIFT_BYTE_ORDER 4321
# define __THRIFT_LITTLE_ENDIAN 0
# define __THRIFT_BIG_ENDIAN __THRIFT_BYTE_ORDER
# elif BOOST_ENDIAN_LITTLE_BYTE
# define __THRIFT_BYTE_ORDER 1234
# define __THRIFT_LITTLE_ENDIAN __THRIFT_BYTE_ORDER
# define __THRIFT_BIG_ENDIAN 0
# endif
# ifdef BOOST_LITTLE_ENDIAN
# else
# endif
# endif
#endif
#if __THRIFT_BYTE_ORDER == __THRIFT_BIG_ENDIAN
# if !defined(THRIFT_ntohll)
# define THRIFT_ntohll(n) (n)
# define THRIFT_htonll(n) (n)
# endif
# if defined(__GNUC__) && defined(__GLIBC__)
# include <byteswap.h>
# define THRIFT_htolell(n) bswap_64(n)
# define THRIFT_letohll(n) bswap_64(n)
# define THRIFT_htolel(n) bswap_32(n)
# define THRIFT_letohl(n) bswap_32(n)
# define THRIFT_htoles(n) bswap_16(n)
# define THRIFT_letohs(n) bswap_16(n)
# else /* GNUC & GLIBC */
# define bswap_64(n) \
( (((n) & 0xff00000000000000ull) >> 56) \
| (((n) & 0x00ff000000000000ull) >> 40) \
| (((n) & 0x0000ff0000000000ull) >> 24) \
| (((n) & 0x000000ff00000000ull) >> 8) \
| (((n) & 0x00000000ff000000ull) << 8) \
| (((n) & 0x0000000000ff0000ull) << 24) \
| (((n) & 0x000000000000ff00ull) << 40) \
| (((n) & 0x00000000000000ffull) << 56) )
# define bswap_32(n) \
( (((n) & 0xff000000ul) >> 24) \
| (((n) & 0x00ff0000ul) >> 8) \
| (((n) & 0x0000ff00ul) << 8) \
| (((n) & 0x000000fful) << 24) )
# define bswap_16(n) \
( (((n) & ((unsigned short)0xff00ul)) >> 8) \
| (((n) & ((unsigned short)0x00fful)) << 8) )
# define THRIFT_htolell(n) bswap_64(n)
# define THRIFT_letohll(n) bswap_64(n)
# define THRIFT_htolel(n) bswap_32(n)
# define THRIFT_letohl(n) bswap_32(n)
# define THRIFT_htoles(n) bswap_16(n)
# define THRIFT_letohs(n) bswap_16(n)
# endif /* GNUC & GLIBC */
#elif __THRIFT_BYTE_ORDER == __THRIFT_LITTLE_ENDIAN
# define THRIFT_htolell(n) (n)
# define THRIFT_letohll(n) (n)
# define THRIFT_htolel(n) (n)
# define THRIFT_letohl(n) (n)
# define THRIFT_htoles(n) (n)
# define THRIFT_letohs(n) (n)
# if defined(__GNUC__) && defined(__GLIBC__)
# include <byteswap.h>
# define THRIFT_ntohll(n) bswap_64(n)
# define THRIFT_htonll(n) bswap_64(n)
# elif defined(_MSC_VER) /* Microsoft Visual C++ */
# define THRIFT_ntohll(n) ( _byteswap_uint64((uint64_t)n) )
# define THRIFT_htonll(n) ( _byteswap_uint64((uint64_t)n) )
# elif !defined(THRIFT_ntohll) /* Not GNUC/GLIBC or MSVC */
# define THRIFT_ntohll(n) ( (((uint64_t)ntohl((uint32_t)n)) << 32) + ntohl((uint32_t)(n >> 32)) )
# define THRIFT_htonll(n) ( (((uint64_t)htonl((uint32_t)n)) << 32) + htonl((uint32_t)(n >> 32)) )
# endif /* GNUC/GLIBC or MSVC or something else */
#else /* __THRIFT_BYTE_ORDER */
# error "Can't define THRIFT_htonll or THRIFT_ntohll!"
#endif
namespace duckdb_apache {
namespace thrift {
namespace protocol {
using duckdb_apache::thrift::transport::TTransport;
/**
* Enumerated definition of the types that the Thrift protocol supports.
* Take special note of the T_END type which is used specifically to mark
* the end of a sequence of fields.
*/
enum TType {
T_STOP = 0,
T_VOID = 1,
T_BOOL = 2,
T_BYTE = 3,
T_I08 = 3,
T_I16 = 6,
T_I32 = 8,
T_U64 = 9,
T_I64 = 10,
T_DOUBLE = 4,
T_STRING = 11,
T_UTF7 = 11,
T_STRUCT = 12,
T_MAP = 13,
T_SET = 14,
T_LIST = 15,
T_UTF8 = 16,
T_UTF16 = 17
};
/**
* Enumerated definition of the message types that the Thrift protocol
* supports.
*/
enum TMessageType {
T_CALL = 1,
T_REPLY = 2,
T_EXCEPTION = 3,
T_ONEWAY = 4
};
static const uint32_t DEFAULT_RECURSION_LIMIT = 64;
/**
* Abstract class for a thrift protocol driver. These are all the methods that
* a protocol must implement. Essentially, there must be some way of reading
* and writing all the base types, plus a mechanism for writing out structs
* with indexed fields.
*
* TProtocol objects should not be shared across multiple encoding contexts,
* as they may need to maintain internal state in some protocols (i.e. XML).
* Note that is is acceptable for the TProtocol module to do its own internal
* buffered reads/writes to the underlying TTransport where appropriate (i.e.
* when parsing an input XML stream, reading should be batched rather than
* looking ahead character by character for a close tag).
*
*/
class TProtocol {
public:
virtual ~TProtocol();
/**
* Writing functions.
*/
virtual uint32_t writeMessageBegin_virt(const std::string& name,
const TMessageType messageType,
const int32_t seqid) = 0;
virtual uint32_t writeMessageEnd_virt() = 0;
virtual uint32_t writeStructBegin_virt(const char* name) = 0;
virtual uint32_t writeStructEnd_virt() = 0;
virtual uint32_t writeFieldBegin_virt(const char* name,
const TType fieldType,
const int16_t fieldId) = 0;
virtual uint32_t writeFieldEnd_virt() = 0;
virtual uint32_t writeFieldStop_virt() = 0;
virtual uint32_t writeMapBegin_virt(const TType keyType, const TType valType, const uint32_t size)
= 0;
virtual uint32_t writeMapEnd_virt() = 0;
virtual uint32_t writeListBegin_virt(const TType elemType, const uint32_t size) = 0;
virtual uint32_t writeListEnd_virt() = 0;
virtual uint32_t writeSetBegin_virt(const TType elemType, const uint32_t size) = 0;
virtual uint32_t writeSetEnd_virt() = 0;
virtual uint32_t writeBool_virt(const bool value) = 0;
virtual uint32_t writeByte_virt(const int8_t byte) = 0;
virtual uint32_t writeI16_virt(const int16_t i16) = 0;
virtual uint32_t writeI32_virt(const int32_t i32) = 0;
virtual uint32_t writeI64_virt(const int64_t i64) = 0;
virtual uint32_t writeDouble_virt(const double dub) = 0;
virtual uint32_t writeString_virt(const std::string& str) = 0;
virtual uint32_t writeBinary_virt(const std::string& str) = 0;
uint32_t writeMessageBegin(const std::string& name,
const TMessageType messageType,
const int32_t seqid) {
T_VIRTUAL_CALL();
return writeMessageBegin_virt(name, messageType, seqid);
}
uint32_t writeMessageEnd() {
T_VIRTUAL_CALL();
return writeMessageEnd_virt();
}
uint32_t writeStructBegin(const char* name) {
T_VIRTUAL_CALL();
return writeStructBegin_virt(name);
}
uint32_t writeStructEnd() {
T_VIRTUAL_CALL();
return writeStructEnd_virt();
}
uint32_t writeFieldBegin(const char* name, const TType fieldType, const int16_t fieldId) {
T_VIRTUAL_CALL();
return writeFieldBegin_virt(name, fieldType, fieldId);
}
uint32_t writeFieldEnd() {
T_VIRTUAL_CALL();
return writeFieldEnd_virt();
}
uint32_t writeFieldStop() {
T_VIRTUAL_CALL();
return writeFieldStop_virt();
}
uint32_t writeMapBegin(const TType keyType, const TType valType, const uint32_t size) {
T_VIRTUAL_CALL();
return writeMapBegin_virt(keyType, valType, size);
}
uint32_t writeMapEnd() {
T_VIRTUAL_CALL();
return writeMapEnd_virt();
}
uint32_t writeListBegin(const TType elemType, const uint32_t size) {
T_VIRTUAL_CALL();
return writeListBegin_virt(elemType, size);
}
uint32_t writeListEnd() {
T_VIRTUAL_CALL();
return writeListEnd_virt();
}
uint32_t writeSetBegin(const TType elemType, const uint32_t size) {
T_VIRTUAL_CALL();
return writeSetBegin_virt(elemType, size);
}
uint32_t writeSetEnd() {
T_VIRTUAL_CALL();
return writeSetEnd_virt();
}
uint32_t writeBool(const bool value) {
T_VIRTUAL_CALL();
return writeBool_virt(value);
}
uint32_t writeByte(const int8_t byte) {
T_VIRTUAL_CALL();
return writeByte_virt(byte);
}
uint32_t writeI16(const int16_t i16) {
T_VIRTUAL_CALL();
return writeI16_virt(i16);
}
uint32_t writeI32(const int32_t i32) {
T_VIRTUAL_CALL();
return writeI32_virt(i32);
}
uint32_t writeI64(const int64_t i64) {
T_VIRTUAL_CALL();
return writeI64_virt(i64);
}
uint32_t writeDouble(const double dub) {
T_VIRTUAL_CALL();
return writeDouble_virt(dub);
}
uint32_t writeString(const std::string& str) {
T_VIRTUAL_CALL();
return writeString_virt(str);
}
uint32_t writeBinary(const std::string& str) {
T_VIRTUAL_CALL();
return writeBinary_virt(str);
}
/**
* Reading functions
*/
virtual uint32_t readMessageBegin_virt(std::string& name,
TMessageType& messageType,
int32_t& seqid) = 0;
virtual uint32_t readMessageEnd_virt() = 0;
virtual uint32_t readStructBegin_virt(std::string& name) = 0;
virtual uint32_t readStructEnd_virt() = 0;
virtual uint32_t readFieldBegin_virt(std::string& name, TType& fieldType, int16_t& fieldId) = 0;
virtual uint32_t readFieldEnd_virt() = 0;
virtual uint32_t readMapBegin_virt(TType& keyType, TType& valType, uint32_t& size) = 0;
virtual uint32_t readMapEnd_virt() = 0;
virtual uint32_t readListBegin_virt(TType& elemType, uint32_t& size) = 0;
virtual uint32_t readListEnd_virt() = 0;
virtual uint32_t readSetBegin_virt(TType& elemType, uint32_t& size) = 0;
virtual uint32_t readSetEnd_virt() = 0;
virtual uint32_t readBool_virt(bool& value) = 0;
virtual uint32_t readBool_virt(std::vector<bool>::reference value) = 0;
virtual uint32_t readByte_virt(int8_t& byte) = 0;
virtual uint32_t readI16_virt(int16_t& i16) = 0;
virtual uint32_t readI32_virt(int32_t& i32) = 0;
virtual uint32_t readI64_virt(int64_t& i64) = 0;
virtual uint32_t readDouble_virt(double& dub) = 0;
virtual uint32_t readString_virt(std::string& str) = 0;
virtual uint32_t readBinary_virt(std::string& str) = 0;
uint32_t readMessageBegin(std::string& name, TMessageType& messageType, int32_t& seqid) {
T_VIRTUAL_CALL();
return readMessageBegin_virt(name, messageType, seqid);
}
uint32_t readMessageEnd() {
T_VIRTUAL_CALL();
return readMessageEnd_virt();
}
uint32_t readStructBegin(std::string& name) {
T_VIRTUAL_CALL();
return readStructBegin_virt(name);
}
uint32_t readStructEnd() {
T_VIRTUAL_CALL();
return readStructEnd_virt();
}
uint32_t readFieldBegin(std::string& name, TType& fieldType, int16_t& fieldId) {
T_VIRTUAL_CALL();
return readFieldBegin_virt(name, fieldType, fieldId);
}
uint32_t readFieldEnd() {
T_VIRTUAL_CALL();
return readFieldEnd_virt();
}
uint32_t readMapBegin(TType& keyType, TType& valType, uint32_t& size) {
T_VIRTUAL_CALL();
return readMapBegin_virt(keyType, valType, size);
}
uint32_t readMapEnd() {
T_VIRTUAL_CALL();
return readMapEnd_virt();
}
uint32_t readListBegin(TType& elemType, uint32_t& size) {
T_VIRTUAL_CALL();
return readListBegin_virt(elemType, size);
}
uint32_t readListEnd() {
T_VIRTUAL_CALL();
return readListEnd_virt();
}
uint32_t readSetBegin(TType& elemType, uint32_t& size) {
T_VIRTUAL_CALL();
return readSetBegin_virt(elemType, size);
}
uint32_t readSetEnd() {
T_VIRTUAL_CALL();
return readSetEnd_virt();
}
uint32_t readBool(bool& value) {
T_VIRTUAL_CALL();
return readBool_virt(value);
}
uint32_t readByte(int8_t& byte) {
T_VIRTUAL_CALL();
return readByte_virt(byte);
}
uint32_t readI16(int16_t& i16) {
T_VIRTUAL_CALL();
return readI16_virt(i16);
}
uint32_t readI32(int32_t& i32) {
T_VIRTUAL_CALL();
return readI32_virt(i32);
}
uint32_t readI64(int64_t& i64) {
T_VIRTUAL_CALL();
return readI64_virt(i64);
}
uint32_t readDouble(double& dub) {
T_VIRTUAL_CALL();
return readDouble_virt(dub);
}
uint32_t readString(std::string& str) {
T_VIRTUAL_CALL();
return readString_virt(str);
}
uint32_t readBinary(std::string& str) {
T_VIRTUAL_CALL();
return readBinary_virt(str);
}
/*
* std::vector is specialized for bool, and its elements are individual bits
* rather than bools. We need to define a different version of readBool()
* to work with std::vector<bool>.
*/
uint32_t readBool(std::vector<bool>::reference value) {
T_VIRTUAL_CALL();
return readBool_virt(value);
}
/**
* Method to arbitrarily skip over data.
*/
uint32_t skip(TType type) {
T_VIRTUAL_CALL();
return skip_virt(type);
}
virtual uint32_t skip_virt(TType type);
inline std::shared_ptr<TTransport> getTransport() { return ptrans_; }
// TODO: remove these two calls, they are for backwards
// compatibility
inline std::shared_ptr<TTransport> getInputTransport() { return ptrans_; }
inline std::shared_ptr<TTransport> getOutputTransport() { return ptrans_; }
// input and output recursion depth are kept separate so that one protocol
// can be used concurrently for both input and output.
void incrementInputRecursionDepth() {
if (recursion_limit_ < ++input_recursion_depth_) {
throw TProtocolException(TProtocolException::DEPTH_LIMIT);
}
}
void decrementInputRecursionDepth() { --input_recursion_depth_; }
void incrementOutputRecursionDepth() {
if (recursion_limit_ < ++output_recursion_depth_) {
throw TProtocolException(TProtocolException::DEPTH_LIMIT);
}
}
void decrementOutputRecursionDepth() { --output_recursion_depth_; }
uint32_t getRecursionLimit() const {return recursion_limit_;}
void setRecurisionLimit(uint32_t depth) {recursion_limit_ = depth;}
protected:
TProtocol(std::shared_ptr<TTransport> ptrans)
: ptrans_(ptrans), input_recursion_depth_(0), output_recursion_depth_(0), recursion_limit_(DEFAULT_RECURSION_LIMIT)
{}
std::shared_ptr<TTransport> ptrans_;
private:
TProtocol() = default;
uint32_t input_recursion_depth_;
uint32_t output_recursion_depth_;
uint32_t recursion_limit_;
};
/**
* Constructs input and output protocol objects given transports.
*/
class TProtocolFactory {
public:
TProtocolFactory() = default;
virtual ~TProtocolFactory();
virtual std::shared_ptr<TProtocol> getProtocol(std::shared_ptr<TTransport> trans) = 0;
virtual std::shared_ptr<TProtocol> getProtocol(std::shared_ptr<TTransport> inTrans,
std::shared_ptr<TTransport> outTrans) {
(void)outTrans;
return getProtocol(inTrans);
}
};
/**
* Dummy protocol class.
*
* This class does nothing, and should never be instantiated.
* It is used only by the generator code.
*/
class TDummyProtocol : public TProtocol {};
// HM: this is sub-optimal since it creates a depencency even for memory-only struct
//// This is the default / legacy choice
//struct TNetworkBigEndian
//{
// static uint16_t toWire16(uint16_t x) {return htons(x);}
// static uint32_t toWire32(uint32_t x) {return htonl(x);}
// static uint64_t toWire64(uint64_t x) {return THRIFT_htonll(x);}
// static uint16_t fromWire16(uint16_t x) {return ntohs(x);}
// static uint32_t fromWire32(uint32_t x) {return ntohl(x);}
// static uint64_t fromWire64(uint64_t x) {return THRIFT_ntohll(x);}
//};
//
//// On most systems, this will be a bit faster than TNetworkBigEndian
//struct TNetworkLittleEndian
//{
// static uint16_t toWire16(uint16_t x) {return THRIFT_htoles(x);}
// static uint32_t toWire32(uint32_t x) {return THRIFT_htolel(x);}
// static uint64_t toWire64(uint64_t x) {return THRIFT_htolell(x);}
// static uint16_t fromWire16(uint16_t x) {return THRIFT_letohs(x);}
// static uint32_t fromWire32(uint32_t x) {return THRIFT_letohl(x);}
// static uint64_t fromWire64(uint64_t x) {return THRIFT_letohll(x);}
//};
struct TOutputRecursionTracker {
TProtocol &prot_;
TOutputRecursionTracker(TProtocol &prot) : prot_(prot) {
prot_.incrementOutputRecursionDepth();
}
~TOutputRecursionTracker() {
prot_.decrementOutputRecursionDepth();
}
};
struct TInputRecursionTracker {
TProtocol &prot_;
TInputRecursionTracker(TProtocol &prot) : prot_(prot) {
prot_.incrementInputRecursionDepth();
}
~TInputRecursionTracker() {
prot_.decrementInputRecursionDepth();
}
};
/**
* Helper template for implementing TProtocol::skip().
*
* Templatized to avoid having to make virtual function calls.
*/
template <class Protocol_>
uint32_t skip(Protocol_& prot, TType type) {
TInputRecursionTracker tracker(prot);
switch (type) {
case T_BOOL: {
bool boolv;
return prot.readBool(boolv);
}
case T_BYTE: {
int8_t bytev = 0;
return prot.readByte(bytev);
}
case T_I16: {
int16_t i16;
return prot.readI16(i16);
}
case T_I32: {
int32_t i32;
return prot.readI32(i32);
}
case T_I64: {
int64_t i64;
return prot.readI64(i64);
}
case T_DOUBLE: {
double dub;
return prot.readDouble(dub);
}
case T_STRING: {
std::string str;
return prot.readBinary(str);
}
case T_STRUCT: {
uint32_t result = 0;
std::string name;
int16_t fid;
TType ftype;
result += prot.readStructBegin(name);
while (true) {
result += prot.readFieldBegin(name, ftype, fid);
if (ftype == T_STOP) {
break;
}
result += skip(prot, ftype);
result += prot.readFieldEnd();
}
result += prot.readStructEnd();
return result;
}
case T_MAP: {
uint32_t result = 0;
TType keyType;
TType valType;
uint32_t i, size;
result += prot.readMapBegin(keyType, valType, size);
for (i = 0; i < size; i++) {
result += skip(prot, keyType);
result += skip(prot, valType);
}
result += prot.readMapEnd();
return result;
}
case T_SET: {
uint32_t result = 0;
TType elemType;
uint32_t i, size;
result += prot.readSetBegin(elemType, size);
for (i = 0; i < size; i++) {
result += skip(prot, elemType);
}
result += prot.readSetEnd();
return result;
}
case T_LIST: {
uint32_t result = 0;
TType elemType;
uint32_t i, size;
result += prot.readListBegin(elemType, size);
for (i = 0; i < size; i++) {
result += skip(prot, elemType);
}
result += prot.readListEnd();
return result;
}
default:
break;
}
throw TProtocolException(TProtocolException::INVALID_DATA,
"invalid TType");
}
}}} // duckdb_apache::thrift::protocol
#endif // #define _DUCKDB_THRIFT_PROTOCOL_TPROTOCOL_H_ 1

View File

@@ -0,0 +1,152 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
#ifndef THRIFT_TPROTOCOLDECORATOR_H_
#define THRIFT_TPROTOCOLDECORATOR_H_ 1
#include "thrift/protocol/TProtocol.h"
#include <memory>
#include "duckdb/common/vector.hpp"
namespace duckdb_apache {
namespace thrift {
namespace protocol {
using std::shared_ptr;
/**
* <code>TProtocolDecorator</code> forwards all requests to an enclosed
* <code>TProtocol</code> instance, providing a way to author concise
* concrete decorator subclasses.
*
* <p>See p.175 of Design Patterns (by Gamma et al.)</p>
*
* @see duckdb_apache::thrift::protocol::TMultiplexedProtocol
*/
class TProtocolDecorator : public TProtocol {
public:
~TProtocolDecorator() override = default;
// Desc: Initializes the protocol decorator object.
TProtocolDecorator(shared_ptr<TProtocol> proto)
: TProtocol(proto->getTransport()), protocol(proto) {}
uint32_t writeMessageBegin_virt(const std::string& name,
const TMessageType messageType,
const int32_t seqid) override {
return protocol->writeMessageBegin(name, messageType, seqid);
}
uint32_t writeMessageEnd_virt() override { return protocol->writeMessageEnd(); }
uint32_t writeStructBegin_virt(const char* name) override {
return protocol->writeStructBegin(name);
}
uint32_t writeStructEnd_virt() override { return protocol->writeStructEnd(); }
uint32_t writeFieldBegin_virt(const char* name,
const TType fieldType,
const int16_t fieldId) override {
return protocol->writeFieldBegin(name, fieldType, fieldId);
}
uint32_t writeFieldEnd_virt() override { return protocol->writeFieldEnd(); }
uint32_t writeFieldStop_virt() override { return protocol->writeFieldStop(); }
uint32_t writeMapBegin_virt(const TType keyType,
const TType valType,
const uint32_t size) override {
return protocol->writeMapBegin(keyType, valType, size);
}
uint32_t writeMapEnd_virt() override { return protocol->writeMapEnd(); }
uint32_t writeListBegin_virt(const TType elemType, const uint32_t size) override {
return protocol->writeListBegin(elemType, size);
}
uint32_t writeListEnd_virt() override { return protocol->writeListEnd(); }
uint32_t writeSetBegin_virt(const TType elemType, const uint32_t size) override {
return protocol->writeSetBegin(elemType, size);
}
uint32_t writeSetEnd_virt() override { return protocol->writeSetEnd(); }
uint32_t writeBool_virt(const bool value) override { return protocol->writeBool(value); }
uint32_t writeByte_virt(const int8_t byte) override { return protocol->writeByte(byte); }
uint32_t writeI16_virt(const int16_t i16) override { return protocol->writeI16(i16); }
uint32_t writeI32_virt(const int32_t i32) override { return protocol->writeI32(i32); }
uint32_t writeI64_virt(const int64_t i64) override { return protocol->writeI64(i64); }
uint32_t writeDouble_virt(const double dub) override { return protocol->writeDouble(dub); }
uint32_t writeString_virt(const std::string& str) override { return protocol->writeString(str); }
uint32_t writeBinary_virt(const std::string& str) override { return protocol->writeBinary(str); }
uint32_t readMessageBegin_virt(std::string& name,
TMessageType& messageType,
int32_t& seqid) override {
return protocol->readMessageBegin(name, messageType, seqid);
}
uint32_t readMessageEnd_virt() override { return protocol->readMessageEnd(); }
uint32_t readStructBegin_virt(std::string& name) override {
return protocol->readStructBegin(name);
}
uint32_t readStructEnd_virt() override { return protocol->readStructEnd(); }
uint32_t readFieldBegin_virt(std::string& name, TType& fieldType, int16_t& fieldId) override {
return protocol->readFieldBegin(name, fieldType, fieldId);
}
uint32_t readFieldEnd_virt() override { return protocol->readFieldEnd(); }
uint32_t readMapBegin_virt(TType& keyType, TType& valType, uint32_t& size) override {
return protocol->readMapBegin(keyType, valType, size);
}
uint32_t readMapEnd_virt() override { return protocol->readMapEnd(); }
uint32_t readListBegin_virt(TType& elemType, uint32_t& size) override {
return protocol->readListBegin(elemType, size);
}
uint32_t readListEnd_virt() override { return protocol->readListEnd(); }
uint32_t readSetBegin_virt(TType& elemType, uint32_t& size) override {
return protocol->readSetBegin(elemType, size);
}
uint32_t readSetEnd_virt() override { return protocol->readSetEnd(); }
uint32_t readBool_virt(bool& value) override { return protocol->readBool(value); }
uint32_t readBool_virt(duckdb::vector<bool>::reference value) override {
return protocol->readBool(value);
}
uint32_t readByte_virt(int8_t& byte) override { return protocol->readByte(byte); }
uint32_t readI16_virt(int16_t& i16) override { return protocol->readI16(i16); }
uint32_t readI32_virt(int32_t& i32) override { return protocol->readI32(i32); }
uint32_t readI64_virt(int64_t& i64) override { return protocol->readI64(i64); }
uint32_t readDouble_virt(double& dub) override { return protocol->readDouble(dub); }
uint32_t readString_virt(std::string& str) override { return protocol->readString(str); }
uint32_t readBinary_virt(std::string& str) override { return protocol->readBinary(str); }
private:
shared_ptr<TProtocol> protocol;
};
}
}
}
#endif // THRIFT_TPROTOCOLDECORATOR_H_

View File

@@ -0,0 +1,105 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
#ifndef _DUCKDB_THRIFT_PROTOCOL_TPROTOCOLEXCEPTION_H_
#define _DUCKDB_THRIFT_PROTOCOL_TPROTOCOLEXCEPTION_H_ 1
#include <string>
namespace duckdb_apache {
namespace thrift {
namespace protocol {
/**
* Class to encapsulate all the possible types of protocol errors that may
* occur in various protocol systems. This provides a sort of generic
* wrapper around the vague UNIX E_ error codes that lets a common code
* base of error handling to be used for various types of protocols, i.e.
* pipes etc.
*
*/
class TProtocolException : public duckdb_apache::thrift::TException {
public:
/**
* Error codes for the various types of exceptions.
*/
enum TProtocolExceptionType {
UNKNOWN = 0,
INVALID_DATA = 1,
NEGATIVE_SIZE = 2,
SIZE_LIMIT = 3,
BAD_VERSION = 4,
NOT_IMPLEMENTED = 5,
DEPTH_LIMIT = 6
};
TProtocolException() : duckdb_apache::thrift::TException(), type_(UNKNOWN) {}
TProtocolException(TProtocolExceptionType type) : duckdb_apache::thrift::TException(), type_(type) {}
TProtocolException(const std::string& message)
: duckdb_apache::thrift::TException(message), type_(UNKNOWN) {}
TProtocolException(TProtocolExceptionType type, const std::string& message)
: duckdb_apache::thrift::TException(message), type_(type) {}
~TProtocolException() noexcept override = default;
/**
* Returns an error code that provides information about the type of error
* that has occurred.
*
* @return Error code
*/
TProtocolExceptionType getType() const { return type_; }
const char* what() const noexcept override {
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_;
};
}
}
} // duckdb_apache::thrift::protocol
#endif // #ifndef _DUCKDB_THRIFT_PROTOCOL_TPROTOCOLEXCEPTION_H_

View File

@@ -0,0 +1,36 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
#ifndef THRIFT_PROTOCOL_TPROTOCOLTYPES_H_
#define THRIFT_PROTOCOL_TPROTOCOLTYPES_H_ 1
namespace duckdb_apache {
namespace thrift {
namespace protocol {
enum PROTOCOL_TYPES {
T_BINARY_PROTOCOL = 0,
T_JSON_PROTOCOL = 1,
T_COMPACT_PROTOCOL = 2,
};
}
}
} // duckdb_apache::thrift::protocol
#endif // #define _THRIFT_PROTOCOL_TPROTOCOLTYPES_H_ 1

View File

@@ -0,0 +1,514 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
#ifndef _DUCKDB_THRIFT_PROTOCOL_TVIRTUALPROTOCOL_H_
#define _DUCKDB_THRIFT_PROTOCOL_TVIRTUALPROTOCOL_H_ 1
#include "thrift/protocol/TProtocol.h"
#include "duckdb/common/vector.hpp"
namespace duckdb_apache {
namespace thrift {
namespace protocol {
using duckdb_apache::thrift::transport::TTransport;
/**
* Helper class that provides default implementations of TProtocol methods.
*
* This class provides default implementations of the non-virtual TProtocol
* methods. It exists primarily so TVirtualProtocol can derive from it. It
* prevents TVirtualProtocol methods from causing infinite recursion if the
* non-virtual methods are not overridden by the TVirtualProtocol subclass.
*
* You probably don't want to use this class directly. Use TVirtualProtocol
* instead.
*/
class TProtocolDefaults : public TProtocol {
public:
uint32_t readMessageBegin(std::string& name, TMessageType& messageType, int32_t& seqid) {
(void)name;
(void)messageType;
(void)seqid;
throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
"this protocol does not support reading (yet).");
}
uint32_t readMessageEnd() {
throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
"this protocol does not support reading (yet).");
}
uint32_t readStructBegin(std::string& name) {
(void)name;
throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
"this protocol does not support reading (yet).");
}
uint32_t readStructEnd() {
throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
"this protocol does not support reading (yet).");
}
uint32_t readFieldBegin(std::string& name, TType& fieldType, int16_t& fieldId) {
(void)name;
(void)fieldType;
(void)fieldId;
throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
"this protocol does not support reading (yet).");
}
uint32_t readFieldEnd() {
throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
"this protocol does not support reading (yet).");
}
uint32_t readMapBegin(TType& keyType, TType& valType, uint32_t& size) {
(void)keyType;
(void)valType;
(void)size;
throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
"this protocol does not support reading (yet).");
}
uint32_t readMapEnd() {
throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
"this protocol does not support reading (yet).");
}
uint32_t readListBegin(TType& elemType, uint32_t& size) {
(void)elemType;
(void)size;
throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
"this protocol does not support reading (yet).");
}
uint32_t readListEnd() {
throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
"this protocol does not support reading (yet).");
}
uint32_t readSetBegin(TType& elemType, uint32_t& size) {
(void)elemType;
(void)size;
throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
"this protocol does not support reading (yet).");
}
uint32_t readSetEnd() {
throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
"this protocol does not support reading (yet).");
}
uint32_t readBool(bool& value) {
(void)value;
throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
"this protocol does not support reading (yet).");
}
uint32_t readBool(duckdb::vector<bool>::reference value) {
(void)value;
throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
"this protocol does not support reading (yet).");
}
uint32_t readByte(int8_t& byte) {
(void)byte;
throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
"this protocol does not support reading (yet).");
}
uint32_t readI16(int16_t& i16) {
(void)i16;
throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
"this protocol does not support reading (yet).");
}
uint32_t readI32(int32_t& i32) {
(void)i32;
throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
"this protocol does not support reading (yet).");
}
uint32_t readI64(int64_t& i64) {
(void)i64;
throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
"this protocol does not support reading (yet).");
}
uint32_t readDouble(double& dub) {
(void)dub;
throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
"this protocol does not support reading (yet).");
}
uint32_t readString(std::string& str) {
(void)str;
throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
"this protocol does not support reading (yet).");
}
uint32_t readBinary(std::string& str) {
(void)str;
throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
"this protocol does not support reading (yet).");
}
uint32_t writeMessageBegin(const std::string& name,
const TMessageType messageType,
const int32_t seqid) {
(void)name;
(void)messageType;
(void)seqid;
throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
"this protocol does not support writing (yet).");
}
uint32_t writeMessageEnd() {
throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
"this protocol does not support writing (yet).");
}
uint32_t writeStructBegin(const char* name) {
(void)name;
throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
"this protocol does not support writing (yet).");
}
uint32_t writeStructEnd() {
throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
"this protocol does not support writing (yet).");
}
uint32_t writeFieldBegin(const char* name, const TType fieldType, const int16_t fieldId) {
(void)name;
(void)fieldType;
(void)fieldId;
throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
"this protocol does not support writing (yet).");
}
uint32_t writeFieldEnd() {
throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
"this protocol does not support writing (yet).");
}
uint32_t writeFieldStop() {
throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
"this protocol does not support writing (yet).");
}
uint32_t writeMapBegin(const TType keyType, const TType valType, const uint32_t size) {
(void)keyType;
(void)valType;
(void)size;
throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
"this protocol does not support writing (yet).");
}
uint32_t writeMapEnd() {
throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
"this protocol does not support writing (yet).");
}
uint32_t writeListBegin(const TType elemType, const uint32_t size) {
(void)elemType;
(void)size;
throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
"this protocol does not support writing (yet).");
}
uint32_t writeListEnd() {
throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
"this protocol does not support writing (yet).");
}
uint32_t writeSetBegin(const TType elemType, const uint32_t size) {
(void)elemType;
(void)size;
throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
"this protocol does not support writing (yet).");
}
uint32_t writeSetEnd() {
throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
"this protocol does not support writing (yet).");
}
uint32_t writeBool(const bool value) {
(void)value;
throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
"this protocol does not support writing (yet).");
}
uint32_t writeByte(const int8_t byte) {
(void)byte;
throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
"this protocol does not support writing (yet).");
}
uint32_t writeI16(const int16_t i16) {
(void)i16;
throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
"this protocol does not support writing (yet).");
}
uint32_t writeI32(const int32_t i32) {
(void)i32;
throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
"this protocol does not support writing (yet).");
}
uint32_t writeI64(const int64_t i64) {
(void)i64;
throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
"this protocol does not support writing (yet).");
}
uint32_t writeDouble(const double dub) {
(void)dub;
throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
"this protocol does not support writing (yet).");
}
uint32_t writeString(const std::string& str) {
(void)str;
throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
"this protocol does not support writing (yet).");
}
uint32_t writeBinary(const std::string& str) {
(void)str;
throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
"this protocol does not support writing (yet).");
}
uint32_t skip(TType type) { return ::duckdb_apache::thrift::protocol::skip(*this, type); }
protected:
TProtocolDefaults(std::shared_ptr<TTransport> ptrans) : TProtocol(ptrans) {}
};
/**
* Concrete TProtocol classes should inherit from TVirtualProtocol
* so they don't have to manually override virtual methods.
*/
template <class Protocol_, class Super_ = TProtocolDefaults>
class TVirtualProtocol : public Super_ {
public:
/**
* Writing functions.
*/
uint32_t writeMessageBegin_virt(const std::string& name,
const TMessageType messageType,
const int32_t seqid) override {
return static_cast<Protocol_*>(this)->writeMessageBegin(name, messageType, seqid);
}
uint32_t writeMessageEnd_virt() override {
return static_cast<Protocol_*>(this)->writeMessageEnd();
}
uint32_t writeStructBegin_virt(const char* name) override {
return static_cast<Protocol_*>(this)->writeStructBegin(name);
}
uint32_t writeStructEnd_virt() override { return static_cast<Protocol_*>(this)->writeStructEnd(); }
uint32_t writeFieldBegin_virt(const char* name,
const TType fieldType,
const int16_t fieldId) override {
return static_cast<Protocol_*>(this)->writeFieldBegin(name, fieldType, fieldId);
}
uint32_t writeFieldEnd_virt() override { return static_cast<Protocol_*>(this)->writeFieldEnd(); }
uint32_t writeFieldStop_virt() override { return static_cast<Protocol_*>(this)->writeFieldStop(); }
uint32_t writeMapBegin_virt(const TType keyType,
const TType valType,
const uint32_t size) override {
return static_cast<Protocol_*>(this)->writeMapBegin(keyType, valType, size);
}
uint32_t writeMapEnd_virt() override { return static_cast<Protocol_*>(this)->writeMapEnd(); }
uint32_t writeListBegin_virt(const TType elemType, const uint32_t size) override {
return static_cast<Protocol_*>(this)->writeListBegin(elemType, size);
}
uint32_t writeListEnd_virt() override { return static_cast<Protocol_*>(this)->writeListEnd(); }
uint32_t writeSetBegin_virt(const TType elemType, const uint32_t size) override {
return static_cast<Protocol_*>(this)->writeSetBegin(elemType, size);
}
uint32_t writeSetEnd_virt() override { return static_cast<Protocol_*>(this)->writeSetEnd(); }
uint32_t writeBool_virt(const bool value) override {
return static_cast<Protocol_*>(this)->writeBool(value);
}
uint32_t writeByte_virt(const int8_t byte) override {
return static_cast<Protocol_*>(this)->writeByte(byte);
}
uint32_t writeI16_virt(const int16_t i16) override {
return static_cast<Protocol_*>(this)->writeI16(i16);
}
uint32_t writeI32_virt(const int32_t i32) override {
return static_cast<Protocol_*>(this)->writeI32(i32);
}
uint32_t writeI64_virt(const int64_t i64) override {
return static_cast<Protocol_*>(this)->writeI64(i64);
}
uint32_t writeDouble_virt(const double dub) override {
return static_cast<Protocol_*>(this)->writeDouble(dub);
}
uint32_t writeString_virt(const std::string& str) override {
return static_cast<Protocol_*>(this)->writeString(str);
}
uint32_t writeBinary_virt(const std::string& str) override {
return static_cast<Protocol_*>(this)->writeBinary(str);
}
/**
* Reading functions
*/
uint32_t readMessageBegin_virt(std::string& name,
TMessageType& messageType,
int32_t& seqid) override {
return static_cast<Protocol_*>(this)->readMessageBegin(name, messageType, seqid);
}
uint32_t readMessageEnd_virt() override { return static_cast<Protocol_*>(this)->readMessageEnd(); }
uint32_t readStructBegin_virt(std::string& name) override {
return static_cast<Protocol_*>(this)->readStructBegin(name);
}
uint32_t readStructEnd_virt() override { return static_cast<Protocol_*>(this)->readStructEnd(); }
uint32_t readFieldBegin_virt(std::string& name, TType& fieldType, int16_t& fieldId) override {
return static_cast<Protocol_*>(this)->readFieldBegin(name, fieldType, fieldId);
}
uint32_t readFieldEnd_virt() override { return static_cast<Protocol_*>(this)->readFieldEnd(); }
uint32_t readMapBegin_virt(TType& keyType, TType& valType, uint32_t& size) override {
return static_cast<Protocol_*>(this)->readMapBegin(keyType, valType, size);
}
uint32_t readMapEnd_virt() override { return static_cast<Protocol_*>(this)->readMapEnd(); }
uint32_t readListBegin_virt(TType& elemType, uint32_t& size) override {
return static_cast<Protocol_*>(this)->readListBegin(elemType, size);
}
uint32_t readListEnd_virt() override { return static_cast<Protocol_*>(this)->readListEnd(); }
uint32_t readSetBegin_virt(TType& elemType, uint32_t& size) override {
return static_cast<Protocol_*>(this)->readSetBegin(elemType, size);
}
uint32_t readSetEnd_virt() override { return static_cast<Protocol_*>(this)->readSetEnd(); }
uint32_t readBool_virt(bool& value) override {
return static_cast<Protocol_*>(this)->readBool(value);
}
uint32_t readBool_virt(duckdb::vector<bool>::reference value) override {
return static_cast<Protocol_*>(this)->readBool(value);
}
uint32_t readByte_virt(int8_t& byte) override {
return static_cast<Protocol_*>(this)->readByte(byte);
}
uint32_t readI16_virt(int16_t& i16) override {
return static_cast<Protocol_*>(this)->readI16(i16);
}
uint32_t readI32_virt(int32_t& i32) override {
return static_cast<Protocol_*>(this)->readI32(i32);
}
uint32_t readI64_virt(int64_t& i64) override {
return static_cast<Protocol_*>(this)->readI64(i64);
}
uint32_t readDouble_virt(double& dub) override {
return static_cast<Protocol_*>(this)->readDouble(dub);
}
uint32_t readString_virt(std::string& str) override {
return static_cast<Protocol_*>(this)->readString(str);
}
uint32_t readBinary_virt(std::string& str) override {
return static_cast<Protocol_*>(this)->readBinary(str);
}
uint32_t skip_virt(TType type) override { return static_cast<Protocol_*>(this)->skip(type); }
/*
* Provide a default skip() implementation that uses non-virtual read
* methods.
*
* Note: subclasses that use TVirtualProtocol to derive from another protocol
* implementation (i.e., not TProtocolDefaults) should beware that this may
* override any non-default skip() implementation provided by the parent
* transport class. They may need to explicitly redefine skip() to call the
* correct parent implementation, if desired.
*/
uint32_t skip(TType type) {
auto* const prot = static_cast<Protocol_*>(this);
return ::duckdb_apache::thrift::protocol::skip(*prot, type);
}
/*
* Provide a default readBool() implementation for use with
* duckdb::vector<bool>, that behaves the same as reading into a normal bool.
*
* Subclasses can override this if desired, but there normally shouldn't
* be a need to.
*/
uint32_t readBool(duckdb::vector<bool>::reference value) {
bool b = false;
uint32_t ret = static_cast<Protocol_*>(this)->readBool(b);
value = b;
return ret;
}
using Super_::readBool; // so we don't hide readBool(bool&)
protected:
TVirtualProtocol(std::shared_ptr<TTransport> ptrans) : Super_(ptrans) {}
};
}
}
} // duckdb_apache::thrift::protocol
#endif // #define _DUCKDB_THRIFT_PROTOCOL_TVIRTUALPROTOCOL_H_ 1

View File

View File

@@ -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.
*/
#ifndef THRIFT_CONFIG_H
#define THRIFT_CONFIG_H
#ifdef _WIN32
#if defined(_M_IX86) || defined(_M_X64) || defined(_M_ARM) || defined(_M_ARM64)
#define ARITHMETIC_RIGHT_SHIFT 1
#define SIGNED_RIGHT_SHIFT_IS 1
#endif
#else
#define SIGNED_RIGHT_SHIFT_IS 1
#define ARITHMETIC_RIGHT_SHIFT 1
#endif
#endif

View File

@@ -0,0 +1,20 @@
#ifndef THRIFT_EXPORT_H
#define THRIFT_EXPORT_H
#ifdef THRIFT_STATIC_DEFINE
# define THRIFT_EXPORT
#elif defined(_MSC_VER )
# ifndef THRIFT_EXPORT
# ifdef thrift_EXPORTS
/* We are building this library */
# define THRIFT_EXPORT __declspec(dllexport)
# else
/* We are using this library */
# define THRIFT_EXPORT __declspec(dllimport)
# endif
# endif
#else
# define THRIFT_EXPORT
#endif
#endif /* THRIFT_EXPORT_H */

View File

@@ -0,0 +1,137 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
// clang-format off
#ifndef _DUCKDB_THRIFT_TRANSPORT_PLATFORM_SOCKET_H_
# define _DUCKDB_THRIFT_TRANSPORT_PLATFORM_SOCKET_H_
#ifdef _WIN32
#ifdef _WINSOCKAPI_
#undef _WINSOCKAPI_
#endif
# include <winsock2.h>
# define THRIFT_GET_SOCKET_ERROR ::WSAGetLastError()
# define THRIFT_ERRNO (*_errno())
# define THRIFT_EINPROGRESS WSAEINPROGRESS
# define THRIFT_EAGAIN WSAEWOULDBLOCK
# define THRIFT_EINTR WSAEINTR
# define THRIFT_ECONNRESET WSAECONNRESET
# define THRIFT_ENOTCONN WSAENOTCONN
# define THRIFT_ETIMEDOUT WSAETIMEDOUT
# define THRIFT_EWOULDBLOCK WSAEWOULDBLOCK
# define THRIFT_EPIPE WSAECONNRESET
# define THRIFT_NO_SOCKET_CACHING SO_EXCLUSIVEADDRUSE
# define THRIFT_SOCKET SOCKET
# define THRIFT_INVALID_SOCKET INVALID_SOCKET
# define THRIFT_SOCKETPAIR thrift_socketpair
# define THRIFT_FCNTL thrift_fcntl
# define THRIFT_O_NONBLOCK 1
# define THRIFT_F_GETFL 0
# define THRIFT_F_SETFL 1
# define THRIFT_GETTIMEOFDAY thrift_gettimeofday
# define THRIFT_CLOSESOCKET closesocket
# define THRIFT_CLOSE _close
# define THRIFT_OPEN _open
# define THRIFT_FTRUNCATE _chsize_s
# define THRIFT_FSYNC _commit
# define THRIFT_LSEEK _lseek
# define THRIFT_WRITE _write
# define THRIFT_READ _read
# define THRIFT_IOCTL_SOCKET ioctlsocket
# define THRIFT_IOCTL_SOCKET_NUM_BYTES_TYPE u_long
# define THRIFT_FSTAT _fstat
# define THRIFT_STAT _stat
# ifdef _WIN32_WCE
# define THRIFT_GAI_STRERROR(...) thrift_wstr2str(gai_strerrorW(__VA_ARGS__))
# else
# define THRIFT_GAI_STRERROR gai_strerrorA
# endif
# define THRIFT_SSIZET ptrdiff_t
# if (_MSC_VER < 1900)
# define THRIFT_SNPRINTF _snprintf
# else
# define THRIFT_SNPRINTF snprintf
# endif
# define THRIFT_SLEEP_SEC thrift_sleep
# define THRIFT_SLEEP_USEC thrift_usleep
# define THRIFT_TIMESPEC thrift_timespec
# define THRIFT_CTIME_R thrift_ctime_r
# define THRIFT_POLL thrift_poll
# if WINVER <= 0x0502 //XP, Server2003
# define THRIFT_POLLFD thrift_pollfd
# define THRIFT_POLLIN 0x0300
# define THRIFT_POLLOUT 0x0010
# else //Vista, Win7...
# define THRIFT_POLLFD pollfd
# define THRIFT_POLLIN POLLIN
# define THRIFT_POLLOUT POLLOUT
# endif //WINVER
# define THRIFT_SHUT_RDWR SD_BOTH
# if !defined(AI_ADDRCONFIG)
# define AI_ADDRCONFIG 0x00000400
# endif
#else //not _WIN32
# include <errno.h>
# define THRIFT_GET_SOCKET_ERROR errno
# define THRIFT_ERRNO errno
# define THRIFT_EINTR EINTR
# define THRIFT_EINPROGRESS EINPROGRESS
# define THRIFT_ECONNRESET ECONNRESET
# define THRIFT_ENOTCONN ENOTCONN
# define THRIFT_ETIMEDOUT ETIMEDOUT
# define THRIFT_EWOULDBLOCK EWOULDBLOCK
# define THRIFT_EAGAIN EAGAIN
# define THRIFT_EPIPE EPIPE
# define THRIFT_NO_SOCKET_CACHING SO_REUSEADDR
# define THRIFT_SOCKET int
# define THRIFT_INVALID_SOCKET (-1)
# define THRIFT_SOCKETPAIR socketpair
# define THRIFT_FCNTL fcntl
# define THRIFT_O_NONBLOCK O_NONBLOCK
# define THRIFT_F_GETFL F_GETFL
# define THRIFT_F_SETFL F_SETFL
# define THRIFT_GETTIMEOFDAY gettimeofday
# define THRIFT_CLOSESOCKET close
# define THRIFT_CLOSE close
# define THRIFT_OPEN open
# define THRIFT_FTRUNCATE ftruncate
# define THRIFT_FSYNC fsync
# define THRIFT_LSEEK lseek
# define THRIFT_WRITE write
# define THRIFT_READ read
# define THRIFT_IOCTL_SOCKET ioctl
# define THRIFT_IOCTL_SOCKET_NUM_BYTES_TYPE int
# define THRIFT_STAT stat
# define THRIFT_FSTAT fstat
# define THRIFT_GAI_STRERROR gai_strerror
# define THRIFT_SSIZET ssize_t
# define THRIFT_SNPRINTF snprintf
# define THRIFT_SLEEP_SEC sleep
# define THRIFT_SLEEP_USEC usleep
# define THRIFT_TIMESPEC timespec
# define THRIFT_CTIME_R ctime_r
# define THRIFT_POLL poll
# define THRIFT_POLLFD pollfd
# define THRIFT_POLLIN POLLIN
# define THRIFT_POLLOUT POLLOUT
# define THRIFT_SHUT_RDWR SHUT_RDWR
#endif
#endif // _DUCKDB_THRIFT_TRANSPORT_PLATFORM_SOCKET_H_

View File

@@ -0,0 +1,139 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
#include <cassert>
#include <algorithm>
#include "thrift/thrift_export.h"
#include "thrift/transport/TBufferTransports.h"
using std::string;
namespace duckdb_apache {
namespace thrift {
namespace transport {
void TMemoryBuffer::computeRead(uint32_t len, uint8_t** out_start, uint32_t* out_give) {
// Correct rBound_ so we can use the fast path in the future.
rBound_ = wBase_;
// Decide how much to give.
uint32_t give = (std::min)(len, available_read());
*out_start = rBase_;
*out_give = give;
// Preincrement rBase_ so the caller doesn't have to.
rBase_ += give;
}
uint32_t TMemoryBuffer::readSlow(uint8_t* buf, uint32_t len) {
uint8_t* start;
uint32_t give;
computeRead(len, &start, &give);
// Copy into the provided buffer.
memcpy(buf, start, give);
return give;
}
uint32_t TMemoryBuffer::readAppendToString(std::string& str, uint32_t len) {
// Don't get some stupid assertion failure.
if (buffer_ == nullptr) {
return 0;
}
uint8_t* start;
uint32_t give;
computeRead(len, &start, &give);
// Append to the provided string.
str.append((char*)start, give);
return give;
}
void TMemoryBuffer::ensureCanWrite(uint32_t len) {
// Check available space
uint32_t avail = available_write();
if (len <= avail) {
return;
}
if (!owner_) {
throw TTransportException("Insufficient space in external MemoryBuffer");
}
// Grow the buffer as necessary.
uint64_t new_size = bufferSize_;
while (len > avail) {
new_size = new_size > 0 ? new_size * 2 : 1;
if (new_size > maxBufferSize_) {
throw TTransportException(TTransportException::BAD_ARGS,
"Internal buffer size overflow");
}
avail = available_write() + (static_cast<uint32_t>(new_size) - bufferSize_);
}
// Allocate into a new pointer so we don't bork ours if it fails.
auto* new_buffer = static_cast<uint8_t*>(std::realloc(buffer_, new_size));
if (new_buffer == nullptr) {
throw std::bad_alloc();
}
rBase_ = new_buffer + (rBase_ - buffer_);
rBound_ = new_buffer + (rBound_ - buffer_);
wBase_ = new_buffer + (wBase_ - buffer_);
wBound_ = new_buffer + new_size;
buffer_ = new_buffer;
bufferSize_ = static_cast<uint32_t>(new_size);
}
void TMemoryBuffer::writeSlow(const uint8_t* buf, uint32_t len) {
ensureCanWrite(len);
// Copy into the buffer and increment wBase_.
memcpy(wBase_, buf, len);
wBase_ += len;
}
void TMemoryBuffer::wroteBytes(uint32_t len) {
uint32_t avail = available_write();
if (len > avail) {
throw TTransportException("Client wrote more bytes than size of buffer.");
}
wBase_ += len;
}
const uint8_t* TMemoryBuffer::borrowSlow(uint8_t* buf, uint32_t* len) {
(void)buf;
rBound_ = wBase_;
if (available_read() >= *len) {
*len = available_read();
return rBase_;
}
return nullptr;
}
}
}
} // duckdb_apache::thrift::transport

View File

@@ -0,0 +1,488 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
#ifndef _DUCKDB_THRIFT_TRANSPORT_TBUFFERTRANSPORTS_H_
#define _DUCKDB_THRIFT_TRANSPORT_TBUFFERTRANSPORTS_H_ 1
#include <cstdlib>
#include <cstddef>
#include <cstring>
#include <limits>
#include "thrift/transport/TTransport.h"
#include "thrift/transport/TVirtualTransport.h"
#ifdef __GNUC__
#define TDB_LIKELY(val) (__builtin_expect((val), 1))
#define TDB_UNLIKELY(val) (__builtin_expect((val), 0))
#else
#define TDB_LIKELY(val) (val)
#define TDB_UNLIKELY(val) (val)
#endif
namespace duckdb_apache {
namespace thrift {
namespace transport {
/**
* Base class for all transports that use read/write buffers for performance.
*
* TBufferBase is designed to implement the fast-path "memcpy" style
* operations that work in the common case. It does so with small and
* (eventually) nonvirtual, inlinable methods. TBufferBase is an abstract
* class. Subclasses are expected to define the "slow path" operations
* that have to be done when the buffers are full or empty.
*
*/
class TBufferBase : public TVirtualTransport<TBufferBase> {
public:
/**
* Fast-path read.
*
* When we have enough data buffered to fulfill the read, we can satisfy it
* with a single memcpy, then adjust our internal pointers. If the buffer
* is empty, we call out to our slow path, implemented by a subclass.
* This method is meant to eventually be nonvirtual and inlinable.
*/
uint32_t read(uint8_t* buf, uint32_t len) {
uint8_t* new_rBase = rBase_ + len;
if (TDB_LIKELY(new_rBase <= rBound_)) {
std::memcpy(buf, rBase_, len);
rBase_ = new_rBase;
return len;
}
return readSlow(buf, len);
}
/**
* Shortcutted version of readAll.
*/
uint32_t readAll(uint8_t* buf, uint32_t len) {
uint8_t* new_rBase = rBase_ + len;
if (TDB_LIKELY(new_rBase <= rBound_)) {
std::memcpy(buf, rBase_, len);
rBase_ = new_rBase;
return len;
}
return duckdb_apache::thrift::transport::readAll(*this, buf, len);
}
/**
* Fast-path write.
*
* When we have enough empty space in our buffer to accommodate the write, we
* can satisfy it with a single memcpy, then adjust our internal pointers.
* If the buffer is full, we call out to our slow path, implemented by a
* subclass. This method is meant to eventually be nonvirtual and
* inlinable.
*/
void write(const uint8_t* buf, uint32_t len) {
uint8_t* new_wBase = wBase_ + len;
if (TDB_LIKELY(new_wBase <= wBound_)) {
std::memcpy(wBase_, buf, len);
wBase_ = new_wBase;
return;
}
writeSlow(buf, len);
}
/**
* Fast-path borrow. A lot like the fast-path read.
*/
const uint8_t* borrow(uint8_t* buf, uint32_t* len) {
if (TDB_LIKELY(static_cast<ptrdiff_t>(*len) <= rBound_ - rBase_)) {
// With strict aliasing, writing to len shouldn't force us to
// refetch rBase_ from memory. TODO(dreiss): Verify this.
*len = static_cast<uint32_t>(rBound_ - rBase_);
return rBase_;
}
return borrowSlow(buf, len);
}
/**
* Consume doesn't require a slow path.
*/
void consume(uint32_t len) {
if (TDB_LIKELY(static_cast<ptrdiff_t>(len) <= rBound_ - rBase_)) {
rBase_ += len;
} else {
throw TTransportException(TTransportException::BAD_ARGS, "consume did not follow a borrow.");
}
}
protected:
/// Slow path read.
virtual uint32_t readSlow(uint8_t* buf, uint32_t len) = 0;
/// Slow path write.
virtual void writeSlow(const uint8_t* buf, uint32_t len) = 0;
/**
* Slow path borrow.
*
* POSTCONDITION: return == NULL || rBound_ - rBase_ >= *len
*/
virtual const uint8_t* borrowSlow(uint8_t* buf, uint32_t* len) = 0;
/**
* Trivial constructor.
*
* Initialize pointers safely. Constructing is not a very
* performance-sensitive operation, so it is okay to just leave it to
* the concrete class to set up pointers correctly.
*/
TBufferBase() : rBase_(nullptr), rBound_(nullptr), wBase_(nullptr), wBound_(nullptr) {}
/// Convenience mutator for setting the read buffer.
void setReadBuffer(uint8_t* buf, uint32_t len) {
rBase_ = buf;
rBound_ = buf + len;
}
/// Convenience mutator for setting the write buffer.
void setWriteBuffer(uint8_t* buf, uint32_t len) {
wBase_ = buf;
wBound_ = buf + len;
}
~TBufferBase() override = default;
/// Reads begin here.
uint8_t* rBase_;
/// Reads may extend to just before here.
uint8_t* rBound_;
/// Writes begin here.
uint8_t* wBase_;
/// Writes may extend to just before here.
uint8_t* wBound_;
};
/**
* A memory buffer is a transport that simply reads from and writes to an
* in memory buffer. Anytime you call write on it, the data is simply placed
* into a buffer, and anytime you call read, data is read from that buffer.
*
* The buffers are allocated using C constructs malloc,realloc, and the size
* doubles as necessary. We've considered using scoped
*
*/
class TMemoryBuffer : public TVirtualTransport<TMemoryBuffer, TBufferBase> {
private:
// Common initialization done by all constructors.
void initCommon(uint8_t* buf, uint32_t size, bool owner, uint32_t wPos) {
maxBufferSize_ = (std::numeric_limits<uint32_t>::max)();
if (buf == nullptr && size != 0) {
assert(owner);
buf = (uint8_t*)std::malloc(size);
if (buf == nullptr) {
throw std::bad_alloc();
}
}
buffer_ = buf;
bufferSize_ = size;
rBase_ = buffer_;
rBound_ = buffer_ + wPos;
// TODO(dreiss): Investigate NULL-ing this if !owner.
wBase_ = buffer_ + wPos;
wBound_ = buffer_ + bufferSize_;
owner_ = owner;
// rBound_ is really an artifact. In principle, it should always be
// equal to wBase_. We update it in a few places (computeRead, etc.).
}
public:
static const uint32_t defaultSize = 1024;
/**
* This enum specifies how a TMemoryBuffer should treat
* memory passed to it via constructors or resetBuffer.
*
* OBSERVE:
* TMemoryBuffer will simply store a pointer to the memory.
* It is the callers responsibility to ensure that the pointer
* remains valid for the lifetime of the TMemoryBuffer,
* and that it is properly cleaned up.
* Note that no data can be written to observed buffers.
*
* COPY:
* TMemoryBuffer will make an internal copy of the buffer.
* The caller has no responsibilities.
*
* TAKE_OWNERSHIP:
* TMemoryBuffer will become the "owner" of the buffer,
* and will be responsible for freeing it.
* The membory must have been allocated with malloc.
*/
enum MemoryPolicy { OBSERVE = 1, COPY = 2, TAKE_OWNERSHIP = 3 };
/**
* Construct a TMemoryBuffer with a default-sized buffer,
* owned by the TMemoryBuffer object.
*/
TMemoryBuffer() { initCommon(nullptr, defaultSize, true, 0); }
/**
* Construct a TMemoryBuffer with a buffer of a specified size,
* owned by the TMemoryBuffer object.
*
* @param sz The initial size of the buffer.
*/
TMemoryBuffer(uint32_t sz) { initCommon(nullptr, sz, true, 0); }
/**
* Construct a TMemoryBuffer with buf as its initial contents.
*
* @param buf The initial contents of the buffer.
* Note that, while buf is a non-const pointer,
* TMemoryBuffer will not write to it if policy == OBSERVE,
* so it is safe to const_cast<uint8_t*>(whatever).
* @param sz The size of @c buf.
* @param policy See @link MemoryPolicy @endlink .
*/
TMemoryBuffer(uint8_t* buf, uint32_t sz, MemoryPolicy policy = OBSERVE) {
if (buf == nullptr && sz != 0) {
throw TTransportException(TTransportException::BAD_ARGS,
"TMemoryBuffer given null buffer with non-zero size.");
}
switch (policy) {
case OBSERVE:
case TAKE_OWNERSHIP:
initCommon(buf, sz, policy == TAKE_OWNERSHIP, sz);
break;
case COPY:
initCommon(nullptr, sz, true, 0);
this->write(buf, sz);
break;
default:
throw TTransportException(TTransportException::BAD_ARGS,
"Invalid MemoryPolicy for TMemoryBuffer");
}
}
~TMemoryBuffer() override {
if (owner_) {
std::free(buffer_);
}
}
bool isOpen() const override { return true; }
bool peek() override { return (rBase_ < wBase_); }
void open() override {}
void close() override {}
// TODO(dreiss): Make bufPtr const.
void getBuffer(uint8_t** bufPtr, uint32_t* sz) {
*bufPtr = rBase_;
*sz = static_cast<uint32_t>(wBase_ - rBase_);
}
std::string getBufferAsString() {
if (buffer_ == nullptr) {
return "";
}
uint8_t* buf;
uint32_t sz;
getBuffer(&buf, &sz);
return std::string((char*)buf, (std::string::size_type)sz);
}
void appendBufferToString(std::string& str) {
if (buffer_ == nullptr) {
return;
}
uint8_t* buf;
uint32_t sz;
getBuffer(&buf, &sz);
str.append((char*)buf, sz);
}
void resetBuffer() {
rBase_ = buffer_;
rBound_ = buffer_;
wBase_ = buffer_;
// It isn't safe to write into a buffer we don't own.
if (!owner_) {
wBound_ = wBase_;
bufferSize_ = 0;
}
}
/// See constructor documentation.
void resetBuffer(uint8_t* buf, uint32_t sz, MemoryPolicy policy = OBSERVE) {
// Use a variant of the copy-and-swap trick for assignment operators.
// This is sub-optimal in terms of performance for two reasons:
// 1/ The constructing and swapping of the (small) values
// in the temporary object takes some time, and is not necessary.
// 2/ If policy == COPY, we allocate the new buffer before
// freeing the old one, precluding the possibility of
// reusing that memory.
// I doubt that either of these problems could be optimized away,
// but the second is probably no a common case, and the first is minor.
// I don't expect resetBuffer to be a common operation, so I'm willing to
// bite the performance bullet to make the method this simple.
// Construct the new buffer.
TMemoryBuffer new_buffer(buf, sz, policy);
// Move it into ourself.
this->swap(new_buffer);
// Our old self gets destroyed.
}
/// See constructor documentation.
void resetBuffer(uint32_t sz) {
// Construct the new buffer.
TMemoryBuffer new_buffer(sz);
// Move it into ourself.
this->swap(new_buffer);
// Our old self gets destroyed.
}
std::string readAsString(uint32_t len) {
std::string str;
(void)readAppendToString(str, len);
return str;
}
uint32_t readAppendToString(std::string& str, uint32_t len);
// return number of bytes read
uint32_t readEnd() override {
// This cast should be safe, because buffer_'s size is a uint32_t
auto bytes = static_cast<uint32_t>(rBase_ - buffer_);
if (rBase_ == wBase_) {
resetBuffer();
}
return bytes;
}
// Return number of bytes written
uint32_t writeEnd() override {
// This cast should be safe, because buffer_'s size is a uint32_t
return static_cast<uint32_t>(wBase_ - buffer_);
}
uint32_t available_read() const {
// Remember, wBase_ is the real rBound_.
return static_cast<uint32_t>(wBase_ - rBase_);
}
uint32_t available_write() const { return static_cast<uint32_t>(wBound_ - wBase_); }
// Returns a pointer to where the client can write data to append to
// the TMemoryBuffer, and ensures the buffer is big enough to accommodate a
// write of the provided length. The returned pointer is very convenient for
// passing to read(), recv(), or similar. You must call wroteBytes() as soon
// as data is written or the buffer will not be aware that data has changed.
uint8_t* getWritePtr(uint32_t len) {
ensureCanWrite(len);
return wBase_;
}
// Informs the buffer that the client has written 'len' bytes into storage
// that had been provided by getWritePtr().
void wroteBytes(uint32_t len);
/*
* TVirtualTransport provides a default implementation of readAll().
* We want to use the TBufferBase version instead.
*/
uint32_t readAll(uint8_t* buf, uint32_t len) { return TBufferBase::readAll(buf, len); }
//! \brief Get the current buffer size
//! \returns the current buffer size
uint32_t getBufferSize() const {
return bufferSize_;
}
//! \brief Get the current maximum buffer size
//! \returns the current maximum buffer size
uint32_t getMaxBufferSize() const {
return maxBufferSize_;
}
//! \brief Change the maximum buffer size
//! \param[in] maxSize the new maximum buffer size allowed to grow to
//! \throws TTransportException(BAD_ARGS) if maxSize is less than the current buffer size
void setMaxBufferSize(uint32_t maxSize) {
if (maxSize < bufferSize_) {
throw TTransportException(TTransportException::BAD_ARGS,
"Maximum buffer size would be less than current buffer size");
}
maxBufferSize_ = maxSize;
}
protected:
void swap(TMemoryBuffer& that) {
using std::swap;
swap(buffer_, that.buffer_);
swap(bufferSize_, that.bufferSize_);
swap(rBase_, that.rBase_);
swap(rBound_, that.rBound_);
swap(wBase_, that.wBase_);
swap(wBound_, that.wBound_);
swap(owner_, that.owner_);
}
// Make sure there's at least 'len' bytes available for writing.
void ensureCanWrite(uint32_t len);
// Compute the position and available data for reading.
void computeRead(uint32_t len, uint8_t** out_start, uint32_t* out_give);
uint32_t readSlow(uint8_t* buf, uint32_t len) override;
void writeSlow(const uint8_t* buf, uint32_t len) override;
const uint8_t* borrowSlow(uint8_t* buf, uint32_t* len) override;
// Data buffer
uint8_t* buffer_;
// Allocated buffer size
uint32_t bufferSize_;
// Maximum allowed size
uint32_t maxBufferSize_;
// Is this object the owner of the buffer?
bool owner_;
// Don't forget to update constrctors, initCommon, and swap if
// you add new members.
};
}
}
} // duckdb_apache::thrift::transport
#endif // #ifndef _DUCKDB_THRIFT_TRANSPORT_TBUFFERTRANSPORTS_H_

View File

@@ -0,0 +1,272 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
#ifndef _DUCKDB_THRIFT_TRANSPORT_TTRANSPORT_H_
#define _DUCKDB_THRIFT_TRANSPORT_TTRANSPORT_H_ 1
#include "thrift/Thrift.h"
#include "thrift/transport/TTransportException.h"
#include <memory>
#include <cstdint>
#include <string>
namespace duckdb_apache {
namespace thrift {
namespace transport {
/**
* Helper template to hoist readAll implementation out of TTransport
*/
template <class Transport_>
uint32_t readAll(Transport_& trans, uint8_t* buf, uint32_t len) {
uint32_t have = 0;
uint32_t get = 0;
while (have < len) {
get = trans.read(buf + have, len - have);
if (get <= 0) {
throw TTransportException(TTransportException::END_OF_FILE, "No more data to read.");
}
have += get;
}
return have;
}
/**
* Generic interface for a method of transporting data. A TTransport may be
* capable of either reading or writing, but not necessarily both.
*
*/
class TTransport {
public:
/**
* Virtual deconstructor.
*/
virtual ~TTransport() = default;
/**
* Whether this transport is open.
*/
virtual bool isOpen() const { return false; }
/**
* Tests whether there is more data to read or if the remote side is
* still open. By default this is true whenever the transport is open,
* but implementations should add logic to test for this condition where
* possible (i.e. on a socket).
* This is used by a server to check if it should listen for another
* request.
*/
virtual bool peek() { return isOpen(); }
/**
* Opens the transport for communications.
*
* @return bool Whether the transport was successfully opened
* @throws TTransportException if opening failed
*/
virtual void open() {
throw TTransportException(TTransportException::NOT_OPEN, "Cannot open base TTransport.");
}
/**
* Closes the transport.
*/
virtual void close() {
throw TTransportException(TTransportException::NOT_OPEN, "Cannot close base TTransport.");
}
/**
* Attempt to read up to the specified number of bytes into the string.
*
* @param buf Reference to the location to write the data
* @param len How many bytes to read
* @return How many bytes were actually read
* @throws TTransportException If an error occurs
*/
uint32_t read(uint8_t* buf, uint32_t len) {
T_VIRTUAL_CALL();
return read_virt(buf, len);
}
virtual uint32_t read_virt(uint8_t* /* buf */, uint32_t /* len */) {
throw TTransportException(TTransportException::NOT_OPEN, "Base TTransport cannot read.");
}
/**
* Reads the given amount of data in its entirety no matter what.
*
* @param s Reference to location for read data
* @param len How many bytes to read
* @return How many bytes read, which must be equal to size
* @throws TTransportException If insufficient data was read
*/
uint32_t readAll(uint8_t* buf, uint32_t len) {
T_VIRTUAL_CALL();
return readAll_virt(buf, len);
}
virtual uint32_t readAll_virt(uint8_t* buf, uint32_t len) {
return duckdb_apache::thrift::transport::readAll(*this, buf, len);
}
/**
* Called when read is completed.
* This can be over-ridden to perform a transport-specific action
* e.g. logging the request to a file
*
* @return number of bytes read if available, 0 otherwise.
*/
virtual uint32_t readEnd() {
// default behaviour is to do nothing
return 0;
}
/**
* Writes the string in its entirety to the buffer.
*
* Note: You must call flush() to ensure the data is actually written,
* and available to be read back in the future. Destroying a TTransport
* object does not automatically flush pending data--if you destroy a
* TTransport object with written but unflushed data, that data may be
* discarded.
*
* @param buf The data to write out
* @throws TTransportException if an error occurs
*/
void write(const uint8_t* buf, uint32_t len) {
T_VIRTUAL_CALL();
write_virt(buf, len);
}
virtual void write_virt(const uint8_t* /* buf */, uint32_t /* len */) {
throw TTransportException(TTransportException::NOT_OPEN, "Base TTransport cannot write.");
}
/**
* Called when write is completed.
* This can be over-ridden to perform a transport-specific action
* at the end of a request.
*
* @return number of bytes written if available, 0 otherwise
*/
virtual uint32_t writeEnd() {
// default behaviour is to do nothing
return 0;
}
/**
* Flushes any pending data to be written. Typically used with buffered
* transport mechanisms.
*
* @throws TTransportException if an error occurs
*/
virtual void flush() {
// default behaviour is to do nothing
}
/**
* Attempts to return a pointer to \c len bytes, possibly copied into \c buf.
* Does not consume the bytes read (i.e.: a later read will return the same
* data). This method is meant to support protocols that need to read
* variable-length fields. They can attempt to borrow the maximum amount of
* data that they will need, then consume (see next method) what they
* actually use. Some transports will not support this method and others
* will fail occasionally, so protocols must be prepared to use read if
* borrow fails.
*
* @oaram buf A buffer where the data can be stored if needed.
* If borrow doesn't return buf, then the contents of
* buf after the call are undefined. This parameter may be
* NULL to indicate that the caller is not supplying storage,
* but would like a pointer into an internal buffer, if
* available.
* @param len *len should initially contain the number of bytes to borrow.
* If borrow succeeds, *len will contain the number of bytes
* available in the returned pointer. This will be at least
* what was requested, but may be more if borrow returns
* a pointer to an internal buffer, rather than buf.
* If borrow fails, the contents of *len are undefined.
* @return If the borrow succeeds, return a pointer to the borrowed data.
* This might be equal to \c buf, or it might be a pointer into
* the transport's internal buffers.
* @throws TTransportException if an error occurs
*/
const uint8_t* borrow(uint8_t* buf, uint32_t* len) {
T_VIRTUAL_CALL();
return borrow_virt(buf, len);
}
virtual const uint8_t* borrow_virt(uint8_t* /* buf */, uint32_t* /* len */) { return nullptr; }
/**
* Remove len bytes from the transport. This should always follow a borrow
* of at least len bytes, and should always succeed.
* TODO(dreiss): Is there any transport that could borrow but fail to
* consume, or that would require a buffer to dump the consumed data?
*
* @param len How many bytes to consume
* @throws TTransportException If an error occurs
*/
void consume(uint32_t len) {
T_VIRTUAL_CALL();
consume_virt(len);
}
virtual void consume_virt(uint32_t /* len */) {
throw TTransportException(TTransportException::NOT_OPEN, "Base TTransport cannot consume.");
}
/**
* Returns the origin of the transports call. The value depends on the
* transport used. An IP based transport for example will return the
* IP address of the client making the request.
* If the transport doesn't know the origin Unknown is returned.
*
* The returned value can be used in a log message for example
*/
virtual const std::string getOrigin() const { return "Unknown"; }
protected:
/**
* Simple constructor.
*/
TTransport() = default;
};
/**
* Generic factory class to make an input and output transport out of a
* source transport. Commonly used inside servers to make input and output
* streams out of raw clients.
*
*/
class TTransportFactory {
public:
TTransportFactory() = default;
virtual ~TTransportFactory() = default;
/**
* Default implementation does nothing, just returns the transport given.
*/
virtual std::shared_ptr<TTransport> getTransport(std::shared_ptr<TTransport> trans) {
return trans;
}
};
}
}
} // duckdb_apache::thrift::transport
#endif // #ifndef _DUCKDB_THRIFT_TRANSPORT_TTRANSPORT_H_

View File

@@ -0,0 +1,59 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
#include "thrift/transport/TTransportException.h"
#include <cstring>
#include "thrift/thrift-config.h"
using std::string;
namespace duckdb_apache {
namespace thrift {
namespace transport {
const char* TTransportException::what() const noexcept {
if (message_.empty()) {
switch (type_) {
case UNKNOWN:
return "TTransportException: Unknown transport exception";
case NOT_OPEN:
return "TTransportException: Transport not open";
case TIMED_OUT:
return "TTransportException: Timed out";
case END_OF_FILE:
return "TTransportException: End of file";
case INTERRUPTED:
return "TTransportException: Interrupted";
case BAD_ARGS:
return "TTransportException: Invalid arguments";
case CORRUPTED_DATA:
return "TTransportException: Corrupted Data";
case INTERNAL_ERROR:
return "TTransportException: Internal error";
default:
return "TTransportException: (Invalid exception type)";
}
} else {
return message_.c_str();
}
}
}
}
} // duckdb_apache::thrift::transport

View File

@@ -0,0 +1,105 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
#ifndef _DUCKDB_THRIFT_TRANSPORT_TTRANSPORTEXCEPTION_H_
#define _DUCKDB_THRIFT_TRANSPORT_TTRANSPORTEXCEPTION_H_ 1
#include <string>
#include "thrift/Thrift.h"
namespace duckdb_apache {
namespace thrift {
namespace transport {
/**
* Class to encapsulate all the possible types of transport errors that may
* occur in various transport systems. This provides a sort of generic
* wrapper around the vague UNIX E_ error codes that lets a common code
* base of error handling to be used for various types of transports, i.e.
* pipes etc.
*
*/
class TTransportException : public duckdb_apache::thrift::TException {
public:
/**
* Error codes for the various types of exceptions.
*/
enum TTransportExceptionType {
UNKNOWN = 0,
NOT_OPEN = 1,
TIMED_OUT = 2,
END_OF_FILE = 3,
INTERRUPTED = 4,
BAD_ARGS = 5,
CORRUPTED_DATA = 6,
INTERNAL_ERROR = 7
};
TTransportException() : duckdb_apache::thrift::TException(), type_(UNKNOWN) {}
TTransportException(TTransportExceptionType type) : duckdb_apache::thrift::TException(), type_(type) {}
TTransportException(const std::string& message)
: duckdb_apache::thrift::TException(message), type_(UNKNOWN) {}
TTransportException(TTransportExceptionType type, const std::string& message)
: duckdb_apache::thrift::TException(message), type_(type) {}
TTransportException(TTransportExceptionType type, const std::string& message, int errno_copy)
: duckdb_apache::thrift::TException(message), type_(type) {}
~TTransportException() noexcept override = default;
/**
* Returns an error code that provides information about the type of error
* that has occurred.
*
* @return Error code
*/
TTransportExceptionType getType() const noexcept { return type_; }
const char* what() const noexcept override;
protected:
/** Just like strerror_r but returns a C++ string object. */
std::string strerror_s(int errno_copy);
/** Error code */
TTransportExceptionType type_;
};
///**
// * Legacy code in transport implementations have overflow issues
// * that need to be enforced.
// */
//template <typename To, typename From> To safe_numeric_cast(From i) {
// try {
// return boost::numeric_cast<To>(i);
// }
// catch (const std::bad_cast& bc) {
// throw TTransportException(TTransportException::CORRUPTED_DATA,
// bc.what());
// }
//}
}
}
} // duckdb_apache::thrift::transport
#endif // #ifndef _DUCKDB_THRIFT_TRANSPORT_TTRANSPORTEXCEPTION_H_

View File

@@ -0,0 +1,140 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
#ifndef _DUCKDB_THRIFT_TRANSPORT_TVIRTUALTRANSPORT_H_
#define _DUCKDB_THRIFT_TRANSPORT_TVIRTUALTRANSPORT_H_ 1
#include "thrift/transport/TTransport.h"
namespace duckdb_apache {
namespace thrift {
namespace transport {
/**
* Helper class that provides default implementations of TTransport methods.
*
* This class provides default implementations of read(), readAll(), write(),
* borrow() and consume().
*
* In the TTransport base class, each of these methods simply invokes its
* virtual counterpart. This class overrides them to always perform the
* default behavior, without a virtual function call.
*
* The primary purpose of this class is to serve as a base class for
* TVirtualTransport, and prevent infinite recursion if one of its subclasses
* does not override the TTransport implementation of these methods. (Since
* TVirtualTransport::read_virt() calls read(), and TTransport::read() calls
* read_virt().)
*/
class TTransportDefaults : public TTransport {
public:
/*
* TTransport *_virt() methods provide reasonable default implementations.
* Invoke them non-virtually.
*/
uint32_t read(uint8_t* buf, uint32_t len) { return this->TTransport::read_virt(buf, len); }
uint32_t readAll(uint8_t* buf, uint32_t len) { return this->TTransport::readAll_virt(buf, len); }
void write(const uint8_t* buf, uint32_t len) { this->TTransport::write_virt(buf, len); }
const uint8_t* borrow(uint8_t* buf, uint32_t* len) {
return this->TTransport::borrow_virt(buf, len);
}
void consume(uint32_t len) { this->TTransport::consume_virt(len); }
protected:
TTransportDefaults() = default;
};
/**
* Helper class to provide polymorphism for subclasses of TTransport.
*
* This class implements *_virt() methods of TTransport, to call the
* non-virtual versions of these functions in the proper subclass.
*
* To define your own transport class using TVirtualTransport:
* 1) Derive your subclass from TVirtualTransport<your class>
* e.g: class MyTransport : public TVirtualTransport<MyTransport> {
* 2) Provide your own implementations of read(), readAll(), etc.
* These methods should be non-virtual.
*
* Transport implementations that need to use virtual inheritance when
* inheriting from TTransport cannot use TVirtualTransport.
*
* @author Chad Walters <chad@powerset.com>
*/
template <class Transport_, class Super_ = TTransportDefaults>
class TVirtualTransport : public Super_ {
public:
/*
* Implementations of the *_virt() functions, to call the subclass's
* non-virtual implementation function.
*/
uint32_t read_virt(uint8_t* buf, uint32_t len) override {
return static_cast<Transport_*>(this)->read(buf, len);
}
uint32_t readAll_virt(uint8_t* buf, uint32_t len) override {
return static_cast<Transport_*>(this)->readAll(buf, len);
}
void write_virt(const uint8_t* buf, uint32_t len) override {
static_cast<Transport_*>(this)->write(buf, len);
}
const uint8_t* borrow_virt(uint8_t* buf, uint32_t* len) override {
return static_cast<Transport_*>(this)->borrow(buf, len);
}
void consume_virt(uint32_t len) override { static_cast<Transport_*>(this)->consume(len); }
/*
* Provide a default readAll() implementation that invokes
* read() non-virtually.
*
* Note: subclasses that use TVirtualTransport to derive from another
* transport implementation (i.e., not TTransportDefaults) should beware that
* this may override any non-default readAll() implementation provided by
* the parent transport class. They may need to redefine readAll() to call
* the correct parent implementation, if desired.
*/
uint32_t readAll(uint8_t* buf, uint32_t len) {
auto* trans = static_cast<Transport_*>(this);
return ::duckdb_apache::thrift::transport::readAll(*trans, buf, len);
}
protected:
TVirtualTransport() = default;
/*
* Templatized constructors, to allow arguments to be passed to the Super_
* constructor. Currently we only support 0, 1, or 2 arguments, but
* additional versions can be added as needed.
*/
template <typename Arg_>
TVirtualTransport(Arg_ const& arg)
: Super_(arg) {}
template <typename Arg1_, typename Arg2_>
TVirtualTransport(Arg1_ const& a1, Arg2_ const& a2)
: Super_(a1, a2) {}
};
}
}
} // duckdb_apache::thrift::transport
#endif // #ifndef _DUCKDB_THRIFT_TRANSPORT_TVIRTUALTRANSPORT_H_