From 6b98dedaefb54213a300dcdda94ec74185a41492 Mon Sep 17 00:00:00 2001 From: Tonis Tiigi Date: Fri, 5 Jan 2018 15:17:35 -0800 Subject: [PATCH] Add grpc opentracing support to the binaries Signed-off-by: Tonis Tiigi --- client/client.go | 15 + client/solve.go | 5 + cmd/buildctl/build.go | 3 +- cmd/buildctl/debug/workers.go | 8 +- cmd/buildctl/diskusage.go | 3 +- cmd/buildctl/main.go | 9 + cmd/buildctl/prune.go | 3 +- cmd/buildctl/trace.go | 92 + cmd/buildkitd/main.go | 14 +- cmd/buildkitd/trace.go | 31 + vendor.conf | 10 +- vendor/github.com/apache/thrift/LICENSE | 239 +++ vendor/github.com/apache/thrift/NOTICE | 5 + vendor/github.com/apache/thrift/README.md | 166 ++ .../apache/thrift/compiler/cpp/README.md | 83 + .../compiler/cpp/src/thrift/windows/config.h | 66 + .../apache/thrift/lib/c_glib/README.md | 34 + .../processor/thrift_dispatch_processor.c | 143 ++ .../processor/thrift_dispatch_processor.h | 95 + .../c_glib/processor/thrift_processor.c | 45 + .../c_glib/processor/thrift_processor.h | 76 + .../c_glib/protocol/thrift_binary_protocol.c | 904 ++++++++ .../c_glib/protocol/thrift_binary_protocol.h | 72 + .../protocol/thrift_binary_protocol_factory.c | 50 + .../protocol/thrift_binary_protocol_factory.h | 56 + .../c_glib/protocol/thrift_compact_protocol.c | 1609 +++++++++++++++ .../c_glib/protocol/thrift_compact_protocol.h | 107 + .../thrift_compact_protocol_factory.c | 140 ++ .../thrift_compact_protocol_factory.h | 70 + .../thrift/c_glib/protocol/thrift_protocol.c | 605 ++++++ .../thrift/c_glib/protocol/thrift_protocol.h | 341 +++ .../c_glib/protocol/thrift_protocol_factory.c | 43 + .../c_glib/protocol/thrift_protocol_factory.h | 73 + .../src/thrift/c_glib/server/thrift_server.c | 174 ++ .../src/thrift/c_glib/server/thrift_server.h | 93 + .../c_glib/server/thrift_simple_server.c | 138 ++ .../c_glib/server/thrift_simple_server.h | 70 + .../lib/c_glib/src/thrift/c_glib/thrift.c | 101 + .../lib/c_glib/src/thrift/c_glib/thrift.h | 49 + .../c_glib/thrift_application_exception.c | 277 +++ .../c_glib/thrift_application_exception.h | 86 + .../c_glib/src/thrift/c_glib/thrift_struct.c | 52 + .../c_glib/src/thrift/c_glib/thrift_struct.h | 68 + .../transport/thrift_buffered_transport.c | 391 ++++ .../transport/thrift_buffered_transport.h | 77 + .../thrift_buffered_transport_factory.c | 55 + .../thrift_buffered_transport_factory.h | 86 + .../c_glib/transport/thrift_fd_transport.c | 265 +++ .../c_glib/transport/thrift_fd_transport.h | 74 + .../transport/thrift_framed_transport.c | 384 ++++ .../transport/thrift_framed_transport.h | 77 + .../thrift_framed_transport_factory.c | 55 + .../thrift_framed_transport_factory.h | 86 + .../c_glib/transport/thrift_memory_buffer.c | 286 +++ .../c_glib/transport/thrift_memory_buffer.h | 72 + .../c_glib/transport/thrift_server_socket.c | 253 +++ .../c_glib/transport/thrift_server_socket.h | 90 + .../transport/thrift_server_transport.c | 62 + .../transport/thrift_server_transport.h | 89 + .../thrift/c_glib/transport/thrift_socket.c | 368 ++++ .../thrift/c_glib/transport/thrift_socket.h | 75 + .../c_glib/transport/thrift_transport.c | 162 ++ .../c_glib/transport/thrift_transport.h | 176 ++ .../transport/thrift_transport_factory.c | 44 + .../transport/thrift_transport_factory.h | 71 + .../apache/thrift/lib/cocoa/README.md | 21 + .../thrift/lib/cocoa/src/TApplicationError.h | 55 + .../apache/thrift/lib/cocoa/src/TBaseClient.h | 27 + .../apache/thrift/lib/cocoa/src/TError.h | 23 + .../apache/thrift/lib/cocoa/src/TProcessor.h | 35 + .../thrift/lib/cocoa/src/TProcessorFactory.h | 33 + .../lib/cocoa/src/TSharedProcessorFactory.h | 28 + .../apache/thrift/lib/cocoa/src/Thrift.h | 20 + .../thrift/lib/cocoa/src/protocol/TBase.h | 46 + .../lib/cocoa/src/protocol/TBinaryProtocol.h | 49 + .../lib/cocoa/src/protocol/TCompactProtocol.h | 42 + .../cocoa/src/protocol/TMultiplexedProtocol.h | 38 + .../thrift/lib/cocoa/src/protocol/TProtocol.h | 164 ++ .../cocoa/src/protocol/TProtocolDecorator.h | 34 + .../lib/cocoa/src/protocol/TProtocolError.h | 76 + .../lib/cocoa/src/protocol/TProtocolFactory.h | 36 + .../lib/cocoa/src/protocol/TProtocolUtil.h | 33 + .../lib/cocoa/src/server/TSocketServer.h | 47 + .../lib/cocoa/src/transport/TAsyncTransport.h | 46 + .../cocoa/src/transport/TFramedTransport.h | 33 + .../src/transport/THTTPSessionTransport.h | 47 + .../lib/cocoa/src/transport/THTTPTransport.h | 39 + .../lib/cocoa/src/transport/TMemoryBuffer.h | 37 + .../src/transport/TNSFileHandleTransport.h | 38 + .../cocoa/src/transport/TNSStreamTransport.h | 43 + .../cocoa/src/transport/TSSLSocketTransport.h | 37 + .../src/transport/TSSLSocketTransportError.h | 30 + .../cocoa/src/transport/TSocketTransport.h | 34 + .../lib/cocoa/src/transport/TTransport.h | 48 + .../lib/cocoa/src/transport/TTransportError.h | 43 + .../github.com/apache/thrift/lib/go/README.md | 81 + .../lib/go/thrift/application_exception.go | 142 ++ .../thrift/lib/go/thrift/binary_protocol.go | 514 +++++ .../lib/go/thrift/buffered_transport.go | 91 + .../thrift/lib/go/thrift/compact_protocol.go | 815 ++++++++ .../thrift/lib/go/thrift/debug_protocol.go | 269 +++ .../thrift/lib/go/thrift/deserializer.go | 58 + .../apache/thrift/lib/go/thrift/exception.go | 44 + .../apache/thrift/lib/go/thrift/field.go | 79 + .../thrift/lib/go/thrift/framed_transport.go | 167 ++ .../thrift/lib/go/thrift/http_client.go | 258 +++ .../thrift/lib/go/thrift/http_transport.go | 34 + .../lib/go/thrift/iostream_transport.go | 214 ++ .../thrift/lib/go/thrift/json_protocol.go | 583 ++++++ .../thrift/lib/go/thrift/memory_buffer.go | 79 + .../thrift/lib/go/thrift/messagetype.go | 31 + .../lib/go/thrift/multiplexed_protocol.go | 169 ++ .../apache/thrift/lib/go/thrift/numeric.go | 164 ++ .../apache/thrift/lib/go/thrift/pointerize.go | 50 + .../apache/thrift/lib/go/thrift/processor.go | 30 + .../thrift/lib/go/thrift/processor_factory.go | 58 + .../apache/thrift/lib/go/thrift/protocol.go | 175 ++ .../lib/go/thrift/protocol_exception.go | 78 + .../thrift/lib/go/thrift/protocol_factory.go | 25 + .../thrift/lib/go/thrift/rich_transport.go | 69 + .../apache/thrift/lib/go/thrift/serializer.go | 75 + .../apache/thrift/lib/go/thrift/server.go | 35 + .../thrift/lib/go/thrift/server_socket.go | 122 ++ .../thrift/lib/go/thrift/server_transport.go | 34 + .../lib/go/thrift/simple_json_protocol.go | 1337 ++++++++++++ .../thrift/lib/go/thrift/simple_server.go | 196 ++ .../apache/thrift/lib/go/thrift/socket.go | 166 ++ .../thrift/lib/go/thrift/ssl_server_socket.go | 109 + .../apache/thrift/lib/go/thrift/ssl_socket.go | 171 ++ .../apache/thrift/lib/go/thrift/transport.go | 68 + .../lib/go/thrift/transport_exception.go | 90 + .../thrift/lib/go/thrift/transport_factory.go | 39 + .../apache/thrift/lib/go/thrift/type.go | 69 + .../thrift/lib/go/thrift/zlib_transport.go | 117 ++ .../thrift/lib/lua/src/longnumberutils.c | 47 + .../apache/thrift/lib/lua/src/luabitwise.c | 83 + .../apache/thrift/lib/lua/src/luabpack.c | 308 +++ .../apache/thrift/lib/lua/src/lualongnumber.c | 228 ++ .../apache/thrift/lib/lua/src/luasocket.c | 380 ++++ .../apache/thrift/lib/lua/src/socket.h | 78 + .../apache/thrift/lib/lua/src/usocket.c | 370 ++++ .../github.com/apache/thrift/lib/py/README.md | 35 + .../thrift/lib/py/compat/win32/stdint.h | 247 +++ .../github.com/apache/thrift/lib/rb/README.md | 43 + .../lib/rb/ext/binary_protocol_accelerated.c | 460 +++++ .../lib/rb/ext/binary_protocol_accelerated.h | 20 + .../apache/thrift/lib/rb/ext/bytes.c | 36 + .../apache/thrift/lib/rb/ext/bytes.h | 31 + .../thrift/lib/rb/ext/compact_protocol.c | 637 ++++++ .../thrift/lib/rb/ext/compact_protocol.h | 20 + .../apache/thrift/lib/rb/ext/constants.h | 99 + .../apache/thrift/lib/rb/ext/macros.h | 41 + .../apache/thrift/lib/rb/ext/memory_buffer.c | 134 ++ .../apache/thrift/lib/rb/ext/memory_buffer.h | 20 + .../apache/thrift/lib/rb/ext/protocol.c | 0 .../apache/thrift/lib/rb/ext/protocol.h | 0 .../apache/thrift/lib/rb/ext/strlcpy.c | 41 + .../apache/thrift/lib/rb/ext/strlcpy.h | 34 + .../apache/thrift/lib/rb/ext/struct.c | 711 +++++++ .../apache/thrift/lib/rb/ext/struct.h | 25 + .../apache/thrift/lib/rb/ext/thrift_native.c | 201 ++ .../github.com/apache/thrift/test/README.md | 185 ++ .../thrift/test/c_glib/src/test_client.c | 1600 ++++++++++++++ .../thrift/test/c_glib/src/test_server.c | 227 ++ .../test/c_glib/src/thrift_test_handler.c | 837 ++++++++ .../test/c_glib/src/thrift_test_handler.h | 245 +++ .../github.com/codahale/hdrhistogram/LICENSE | 21 + .../codahale/hdrhistogram/README.md | 15 + .../github.com/codahale/hdrhistogram/hdr.go | 563 +++++ .../codahale/hdrhistogram/window.go | 45 + .../grpc-ecosystem/grpc-opentracing/LICENSE | 27 + .../grpc-ecosystem/grpc-opentracing/PATENTS | 23 + .../grpc-opentracing/README.rst | 25 + .../grpc-opentracing/go/otgrpc/README.md | 57 + .../grpc-opentracing/go/otgrpc/client.go | 239 +++ .../grpc-opentracing/go/otgrpc/errors.go | 69 + .../grpc-opentracing/go/otgrpc/options.go | 76 + .../grpc-opentracing/go/otgrpc/package.go | 5 + .../grpc-opentracing/go/otgrpc/server.go | 141 ++ .../grpc-opentracing/go/otgrpc/shared.go | 42 + .../grpc-opentracing/python/README.md | 73 + .../python/examples/protos/command_line.proto | 15 + .../python/examples/protos/store.proto | 37 + .../opentracing/opentracing-go/LICENSE | 21 + .../opentracing/opentracing-go/README.md | 163 ++ .../opentracing/opentracing-go/ext/tags.go | 210 ++ .../opentracing-go/globaltracer.go | 32 + .../opentracing/opentracing-go/gocontext.go | 57 + .../opentracing/opentracing-go/log/field.go | 269 +++ .../opentracing/opentracing-go/log/util.go | 54 + .../opentracing/opentracing-go/noop.go | 64 + .../opentracing/opentracing-go/propagation.go | 176 ++ .../opentracing/opentracing-go/span.go | 185 ++ .../opentracing/opentracing-go/tracer.go | 305 +++ .../github.com/uber/jaeger-client-go/LICENSE | 201 ++ .../uber/jaeger-client-go/README.md | 237 +++ .../uber/jaeger-client-go/baggage_setter.go | 77 + .../uber/jaeger-client-go/constants.go | 76 + .../uber/jaeger-client-go/context.go | 258 +++ .../uber/jaeger-client-go/contrib_observer.go | 56 + .../github.com/uber/jaeger-client-go/doc.go | 24 + .../uber/jaeger-client-go/header.go | 64 + .../internal/baggage/restriction_manager.go | 71 + .../jaeger-client-go/internal/spanlog/json.go | 81 + .../uber/jaeger-client-go/interop.go | 55 + .../uber/jaeger-client-go/jaeger_tag.go | 84 + .../jaeger-client-go/jaeger_thrift_span.go | 172 ++ .../uber/jaeger-client-go/log/logger.go | 83 + .../uber/jaeger-client-go/logger.go | 53 + .../uber/jaeger-client-go/metrics.go | 98 + .../uber/jaeger-client-go/observer.go | 88 + .../uber/jaeger-client-go/propagation.go | 300 +++ .../uber/jaeger-client-go/reference.go | 23 + .../uber/jaeger-client-go/reporter.go | 289 +++ .../uber/jaeger-client-go/reporter_options.go | 69 + .../uber/jaeger-client-go/sampler.go | 531 +++++ .../uber/jaeger-client-go/sampler_options.go | 81 + .../github.com/uber/jaeger-client-go/span.go | 242 +++ .../thrift-gen/agent/agent.go | 410 ++++ .../thrift-gen/agent/constants.go | 21 + .../thrift-gen/agent/ttypes.go | 19 + .../thrift-gen/jaeger/agent.go | 242 +++ .../thrift-gen/jaeger/constants.go | 18 + .../thrift-gen/jaeger/ttypes.go | 1838 +++++++++++++++++ .../thrift-gen/sampling/constants.go | 18 + .../thrift-gen/sampling/samplingmanager.go | 410 ++++ .../thrift-gen/sampling/ttypes.go | 873 ++++++++ .../thrift-gen/zipkincore/constants.go | 32 + .../thrift-gen/zipkincore/ttypes.go | 1247 +++++++++++ .../thrift-gen/zipkincore/zipkincollector.go | 446 ++++ .../uber/jaeger-client-go/tracer.go | 396 ++++ .../uber/jaeger-client-go/tracer_options.go | 146 ++ .../uber/jaeger-client-go/transport.go | 38 + .../uber/jaeger-client-go/transport_udp.go | 132 ++ .../uber/jaeger-client-go/utils/http_json.go | 54 + .../uber/jaeger-client-go/utils/localip.go | 84 + .../uber/jaeger-client-go/utils/rand.go | 46 + .../jaeger-client-go/utils/rate_limiter.go | 77 + .../uber/jaeger-client-go/utils/udp_client.go | 98 + .../uber/jaeger-client-go/utils/utils.go | 87 + .../uber/jaeger-client-go/zipkin.go | 76 + .../jaeger-client-go/zipkin_thrift_span.go | 325 +++ vendor/github.com/uber/jaeger-lib/LICENSE | 201 ++ vendor/github.com/uber/jaeger-lib/README.md | 22 + .../uber/jaeger-lib/metrics/counter.go | 28 + .../uber/jaeger-lib/metrics/factory.go | 35 + .../uber/jaeger-lib/metrics/gauge.go | 28 + .../uber/jaeger-lib/metrics/local.go | 332 +++ .../uber/jaeger-lib/metrics/metrics.go | 85 + .../uber/jaeger-lib/metrics/stopwatch.go | 43 + .../uber/jaeger-lib/metrics/timer.go | 33 + 251 files changed, 39482 insertions(+), 11 deletions(-) create mode 100644 cmd/buildctl/trace.go create mode 100644 cmd/buildkitd/trace.go create mode 100644 vendor/github.com/apache/thrift/LICENSE create mode 100644 vendor/github.com/apache/thrift/NOTICE create mode 100644 vendor/github.com/apache/thrift/README.md create mode 100644 vendor/github.com/apache/thrift/compiler/cpp/README.md create mode 100644 vendor/github.com/apache/thrift/compiler/cpp/src/thrift/windows/config.h create mode 100644 vendor/github.com/apache/thrift/lib/c_glib/README.md create mode 100644 vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/processor/thrift_dispatch_processor.c create mode 100644 vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/processor/thrift_dispatch_processor.h create mode 100644 vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/processor/thrift_processor.c create mode 100644 vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/processor/thrift_processor.h create mode 100644 vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/protocol/thrift_binary_protocol.c create mode 100644 vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/protocol/thrift_binary_protocol.h create mode 100644 vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/protocol/thrift_binary_protocol_factory.c create mode 100644 vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/protocol/thrift_binary_protocol_factory.h create mode 100644 vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/protocol/thrift_compact_protocol.c create mode 100644 vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/protocol/thrift_compact_protocol.h create mode 100644 vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/protocol/thrift_compact_protocol_factory.c create mode 100644 vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/protocol/thrift_compact_protocol_factory.h create mode 100644 vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/protocol/thrift_protocol.c create mode 100644 vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/protocol/thrift_protocol.h create mode 100644 vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/protocol/thrift_protocol_factory.c create mode 100644 vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/protocol/thrift_protocol_factory.h create mode 100644 vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/server/thrift_server.c create mode 100644 vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/server/thrift_server.h create mode 100644 vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/server/thrift_simple_server.c create mode 100644 vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/server/thrift_simple_server.h create mode 100644 vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/thrift.c create mode 100644 vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/thrift.h create mode 100644 vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/thrift_application_exception.c create mode 100644 vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/thrift_application_exception.h create mode 100644 vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/thrift_struct.c create mode 100644 vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/thrift_struct.h create mode 100644 vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/transport/thrift_buffered_transport.c create mode 100644 vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/transport/thrift_buffered_transport.h create mode 100644 vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/transport/thrift_buffered_transport_factory.c create mode 100644 vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/transport/thrift_buffered_transport_factory.h create mode 100644 vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/transport/thrift_fd_transport.c create mode 100644 vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/transport/thrift_fd_transport.h create mode 100644 vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/transport/thrift_framed_transport.c create mode 100644 vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/transport/thrift_framed_transport.h create mode 100644 vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/transport/thrift_framed_transport_factory.c create mode 100644 vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/transport/thrift_framed_transport_factory.h create mode 100644 vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/transport/thrift_memory_buffer.c create mode 100644 vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/transport/thrift_memory_buffer.h create mode 100644 vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/transport/thrift_server_socket.c create mode 100644 vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/transport/thrift_server_socket.h create mode 100644 vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/transport/thrift_server_transport.c create mode 100644 vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/transport/thrift_server_transport.h create mode 100644 vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/transport/thrift_socket.c create mode 100644 vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/transport/thrift_socket.h create mode 100644 vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/transport/thrift_transport.c create mode 100644 vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/transport/thrift_transport.h create mode 100644 vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/transport/thrift_transport_factory.c create mode 100644 vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/transport/thrift_transport_factory.h create mode 100644 vendor/github.com/apache/thrift/lib/cocoa/README.md create mode 100644 vendor/github.com/apache/thrift/lib/cocoa/src/TApplicationError.h create mode 100644 vendor/github.com/apache/thrift/lib/cocoa/src/TBaseClient.h create mode 100644 vendor/github.com/apache/thrift/lib/cocoa/src/TError.h create mode 100644 vendor/github.com/apache/thrift/lib/cocoa/src/TProcessor.h create mode 100644 vendor/github.com/apache/thrift/lib/cocoa/src/TProcessorFactory.h create mode 100644 vendor/github.com/apache/thrift/lib/cocoa/src/TSharedProcessorFactory.h create mode 100644 vendor/github.com/apache/thrift/lib/cocoa/src/Thrift.h create mode 100644 vendor/github.com/apache/thrift/lib/cocoa/src/protocol/TBase.h create mode 100644 vendor/github.com/apache/thrift/lib/cocoa/src/protocol/TBinaryProtocol.h create mode 100644 vendor/github.com/apache/thrift/lib/cocoa/src/protocol/TCompactProtocol.h create mode 100644 vendor/github.com/apache/thrift/lib/cocoa/src/protocol/TMultiplexedProtocol.h create mode 100644 vendor/github.com/apache/thrift/lib/cocoa/src/protocol/TProtocol.h create mode 100644 vendor/github.com/apache/thrift/lib/cocoa/src/protocol/TProtocolDecorator.h create mode 100644 vendor/github.com/apache/thrift/lib/cocoa/src/protocol/TProtocolError.h create mode 100644 vendor/github.com/apache/thrift/lib/cocoa/src/protocol/TProtocolFactory.h create mode 100644 vendor/github.com/apache/thrift/lib/cocoa/src/protocol/TProtocolUtil.h create mode 100644 vendor/github.com/apache/thrift/lib/cocoa/src/server/TSocketServer.h create mode 100644 vendor/github.com/apache/thrift/lib/cocoa/src/transport/TAsyncTransport.h create mode 100644 vendor/github.com/apache/thrift/lib/cocoa/src/transport/TFramedTransport.h create mode 100644 vendor/github.com/apache/thrift/lib/cocoa/src/transport/THTTPSessionTransport.h create mode 100644 vendor/github.com/apache/thrift/lib/cocoa/src/transport/THTTPTransport.h create mode 100644 vendor/github.com/apache/thrift/lib/cocoa/src/transport/TMemoryBuffer.h create mode 100644 vendor/github.com/apache/thrift/lib/cocoa/src/transport/TNSFileHandleTransport.h create mode 100644 vendor/github.com/apache/thrift/lib/cocoa/src/transport/TNSStreamTransport.h create mode 100644 vendor/github.com/apache/thrift/lib/cocoa/src/transport/TSSLSocketTransport.h create mode 100644 vendor/github.com/apache/thrift/lib/cocoa/src/transport/TSSLSocketTransportError.h create mode 100644 vendor/github.com/apache/thrift/lib/cocoa/src/transport/TSocketTransport.h create mode 100644 vendor/github.com/apache/thrift/lib/cocoa/src/transport/TTransport.h create mode 100644 vendor/github.com/apache/thrift/lib/cocoa/src/transport/TTransportError.h create mode 100644 vendor/github.com/apache/thrift/lib/go/README.md create mode 100644 vendor/github.com/apache/thrift/lib/go/thrift/application_exception.go create mode 100644 vendor/github.com/apache/thrift/lib/go/thrift/binary_protocol.go create mode 100644 vendor/github.com/apache/thrift/lib/go/thrift/buffered_transport.go create mode 100644 vendor/github.com/apache/thrift/lib/go/thrift/compact_protocol.go create mode 100644 vendor/github.com/apache/thrift/lib/go/thrift/debug_protocol.go create mode 100644 vendor/github.com/apache/thrift/lib/go/thrift/deserializer.go create mode 100644 vendor/github.com/apache/thrift/lib/go/thrift/exception.go create mode 100644 vendor/github.com/apache/thrift/lib/go/thrift/field.go create mode 100644 vendor/github.com/apache/thrift/lib/go/thrift/framed_transport.go create mode 100644 vendor/github.com/apache/thrift/lib/go/thrift/http_client.go create mode 100644 vendor/github.com/apache/thrift/lib/go/thrift/http_transport.go create mode 100644 vendor/github.com/apache/thrift/lib/go/thrift/iostream_transport.go create mode 100644 vendor/github.com/apache/thrift/lib/go/thrift/json_protocol.go create mode 100644 vendor/github.com/apache/thrift/lib/go/thrift/memory_buffer.go create mode 100644 vendor/github.com/apache/thrift/lib/go/thrift/messagetype.go create mode 100644 vendor/github.com/apache/thrift/lib/go/thrift/multiplexed_protocol.go create mode 100644 vendor/github.com/apache/thrift/lib/go/thrift/numeric.go create mode 100644 vendor/github.com/apache/thrift/lib/go/thrift/pointerize.go create mode 100644 vendor/github.com/apache/thrift/lib/go/thrift/processor.go create mode 100644 vendor/github.com/apache/thrift/lib/go/thrift/processor_factory.go create mode 100644 vendor/github.com/apache/thrift/lib/go/thrift/protocol.go create mode 100644 vendor/github.com/apache/thrift/lib/go/thrift/protocol_exception.go create mode 100644 vendor/github.com/apache/thrift/lib/go/thrift/protocol_factory.go create mode 100644 vendor/github.com/apache/thrift/lib/go/thrift/rich_transport.go create mode 100644 vendor/github.com/apache/thrift/lib/go/thrift/serializer.go create mode 100644 vendor/github.com/apache/thrift/lib/go/thrift/server.go create mode 100644 vendor/github.com/apache/thrift/lib/go/thrift/server_socket.go create mode 100644 vendor/github.com/apache/thrift/lib/go/thrift/server_transport.go create mode 100644 vendor/github.com/apache/thrift/lib/go/thrift/simple_json_protocol.go create mode 100644 vendor/github.com/apache/thrift/lib/go/thrift/simple_server.go create mode 100644 vendor/github.com/apache/thrift/lib/go/thrift/socket.go create mode 100644 vendor/github.com/apache/thrift/lib/go/thrift/ssl_server_socket.go create mode 100644 vendor/github.com/apache/thrift/lib/go/thrift/ssl_socket.go create mode 100644 vendor/github.com/apache/thrift/lib/go/thrift/transport.go create mode 100644 vendor/github.com/apache/thrift/lib/go/thrift/transport_exception.go create mode 100644 vendor/github.com/apache/thrift/lib/go/thrift/transport_factory.go create mode 100644 vendor/github.com/apache/thrift/lib/go/thrift/type.go create mode 100644 vendor/github.com/apache/thrift/lib/go/thrift/zlib_transport.go create mode 100644 vendor/github.com/apache/thrift/lib/lua/src/longnumberutils.c create mode 100644 vendor/github.com/apache/thrift/lib/lua/src/luabitwise.c create mode 100644 vendor/github.com/apache/thrift/lib/lua/src/luabpack.c create mode 100644 vendor/github.com/apache/thrift/lib/lua/src/lualongnumber.c create mode 100644 vendor/github.com/apache/thrift/lib/lua/src/luasocket.c create mode 100644 vendor/github.com/apache/thrift/lib/lua/src/socket.h create mode 100644 vendor/github.com/apache/thrift/lib/lua/src/usocket.c create mode 100644 vendor/github.com/apache/thrift/lib/py/README.md create mode 100644 vendor/github.com/apache/thrift/lib/py/compat/win32/stdint.h create mode 100644 vendor/github.com/apache/thrift/lib/rb/README.md create mode 100644 vendor/github.com/apache/thrift/lib/rb/ext/binary_protocol_accelerated.c create mode 100644 vendor/github.com/apache/thrift/lib/rb/ext/binary_protocol_accelerated.h create mode 100644 vendor/github.com/apache/thrift/lib/rb/ext/bytes.c create mode 100644 vendor/github.com/apache/thrift/lib/rb/ext/bytes.h create mode 100644 vendor/github.com/apache/thrift/lib/rb/ext/compact_protocol.c create mode 100644 vendor/github.com/apache/thrift/lib/rb/ext/compact_protocol.h create mode 100644 vendor/github.com/apache/thrift/lib/rb/ext/constants.h create mode 100644 vendor/github.com/apache/thrift/lib/rb/ext/macros.h create mode 100644 vendor/github.com/apache/thrift/lib/rb/ext/memory_buffer.c create mode 100644 vendor/github.com/apache/thrift/lib/rb/ext/memory_buffer.h create mode 100644 vendor/github.com/apache/thrift/lib/rb/ext/protocol.c create mode 100644 vendor/github.com/apache/thrift/lib/rb/ext/protocol.h create mode 100644 vendor/github.com/apache/thrift/lib/rb/ext/strlcpy.c create mode 100644 vendor/github.com/apache/thrift/lib/rb/ext/strlcpy.h create mode 100644 vendor/github.com/apache/thrift/lib/rb/ext/struct.c create mode 100644 vendor/github.com/apache/thrift/lib/rb/ext/struct.h create mode 100644 vendor/github.com/apache/thrift/lib/rb/ext/thrift_native.c create mode 100755 vendor/github.com/apache/thrift/test/README.md create mode 100644 vendor/github.com/apache/thrift/test/c_glib/src/test_client.c create mode 100644 vendor/github.com/apache/thrift/test/c_glib/src/test_server.c create mode 100644 vendor/github.com/apache/thrift/test/c_glib/src/thrift_test_handler.c create mode 100644 vendor/github.com/apache/thrift/test/c_glib/src/thrift_test_handler.h create mode 100644 vendor/github.com/codahale/hdrhistogram/LICENSE create mode 100644 vendor/github.com/codahale/hdrhistogram/README.md create mode 100644 vendor/github.com/codahale/hdrhistogram/hdr.go create mode 100644 vendor/github.com/codahale/hdrhistogram/window.go create mode 100644 vendor/github.com/grpc-ecosystem/grpc-opentracing/LICENSE create mode 100644 vendor/github.com/grpc-ecosystem/grpc-opentracing/PATENTS create mode 100644 vendor/github.com/grpc-ecosystem/grpc-opentracing/README.rst create mode 100644 vendor/github.com/grpc-ecosystem/grpc-opentracing/go/otgrpc/README.md create mode 100644 vendor/github.com/grpc-ecosystem/grpc-opentracing/go/otgrpc/client.go create mode 100644 vendor/github.com/grpc-ecosystem/grpc-opentracing/go/otgrpc/errors.go create mode 100644 vendor/github.com/grpc-ecosystem/grpc-opentracing/go/otgrpc/options.go create mode 100644 vendor/github.com/grpc-ecosystem/grpc-opentracing/go/otgrpc/package.go create mode 100644 vendor/github.com/grpc-ecosystem/grpc-opentracing/go/otgrpc/server.go create mode 100644 vendor/github.com/grpc-ecosystem/grpc-opentracing/go/otgrpc/shared.go create mode 100644 vendor/github.com/grpc-ecosystem/grpc-opentracing/python/README.md create mode 100644 vendor/github.com/grpc-ecosystem/grpc-opentracing/python/examples/protos/command_line.proto create mode 100644 vendor/github.com/grpc-ecosystem/grpc-opentracing/python/examples/protos/store.proto create mode 100644 vendor/github.com/opentracing/opentracing-go/LICENSE create mode 100644 vendor/github.com/opentracing/opentracing-go/README.md create mode 100644 vendor/github.com/opentracing/opentracing-go/ext/tags.go create mode 100644 vendor/github.com/opentracing/opentracing-go/globaltracer.go create mode 100644 vendor/github.com/opentracing/opentracing-go/gocontext.go create mode 100644 vendor/github.com/opentracing/opentracing-go/log/field.go create mode 100644 vendor/github.com/opentracing/opentracing-go/log/util.go create mode 100644 vendor/github.com/opentracing/opentracing-go/noop.go create mode 100644 vendor/github.com/opentracing/opentracing-go/propagation.go create mode 100644 vendor/github.com/opentracing/opentracing-go/span.go create mode 100644 vendor/github.com/opentracing/opentracing-go/tracer.go create mode 100644 vendor/github.com/uber/jaeger-client-go/LICENSE create mode 100644 vendor/github.com/uber/jaeger-client-go/README.md create mode 100644 vendor/github.com/uber/jaeger-client-go/baggage_setter.go create mode 100644 vendor/github.com/uber/jaeger-client-go/constants.go create mode 100644 vendor/github.com/uber/jaeger-client-go/context.go create mode 100644 vendor/github.com/uber/jaeger-client-go/contrib_observer.go create mode 100644 vendor/github.com/uber/jaeger-client-go/doc.go create mode 100644 vendor/github.com/uber/jaeger-client-go/header.go create mode 100644 vendor/github.com/uber/jaeger-client-go/internal/baggage/restriction_manager.go create mode 100644 vendor/github.com/uber/jaeger-client-go/internal/spanlog/json.go create mode 100644 vendor/github.com/uber/jaeger-client-go/interop.go create mode 100644 vendor/github.com/uber/jaeger-client-go/jaeger_tag.go create mode 100644 vendor/github.com/uber/jaeger-client-go/jaeger_thrift_span.go create mode 100644 vendor/github.com/uber/jaeger-client-go/log/logger.go create mode 100644 vendor/github.com/uber/jaeger-client-go/logger.go create mode 100644 vendor/github.com/uber/jaeger-client-go/metrics.go create mode 100644 vendor/github.com/uber/jaeger-client-go/observer.go create mode 100644 vendor/github.com/uber/jaeger-client-go/propagation.go create mode 100644 vendor/github.com/uber/jaeger-client-go/reference.go create mode 100644 vendor/github.com/uber/jaeger-client-go/reporter.go create mode 100644 vendor/github.com/uber/jaeger-client-go/reporter_options.go create mode 100644 vendor/github.com/uber/jaeger-client-go/sampler.go create mode 100644 vendor/github.com/uber/jaeger-client-go/sampler_options.go create mode 100644 vendor/github.com/uber/jaeger-client-go/span.go create mode 100644 vendor/github.com/uber/jaeger-client-go/thrift-gen/agent/agent.go create mode 100644 vendor/github.com/uber/jaeger-client-go/thrift-gen/agent/constants.go create mode 100644 vendor/github.com/uber/jaeger-client-go/thrift-gen/agent/ttypes.go create mode 100644 vendor/github.com/uber/jaeger-client-go/thrift-gen/jaeger/agent.go create mode 100644 vendor/github.com/uber/jaeger-client-go/thrift-gen/jaeger/constants.go create mode 100644 vendor/github.com/uber/jaeger-client-go/thrift-gen/jaeger/ttypes.go create mode 100644 vendor/github.com/uber/jaeger-client-go/thrift-gen/sampling/constants.go create mode 100644 vendor/github.com/uber/jaeger-client-go/thrift-gen/sampling/samplingmanager.go create mode 100644 vendor/github.com/uber/jaeger-client-go/thrift-gen/sampling/ttypes.go create mode 100644 vendor/github.com/uber/jaeger-client-go/thrift-gen/zipkincore/constants.go create mode 100644 vendor/github.com/uber/jaeger-client-go/thrift-gen/zipkincore/ttypes.go create mode 100644 vendor/github.com/uber/jaeger-client-go/thrift-gen/zipkincore/zipkincollector.go create mode 100644 vendor/github.com/uber/jaeger-client-go/tracer.go create mode 100644 vendor/github.com/uber/jaeger-client-go/tracer_options.go create mode 100644 vendor/github.com/uber/jaeger-client-go/transport.go create mode 100644 vendor/github.com/uber/jaeger-client-go/transport_udp.go create mode 100644 vendor/github.com/uber/jaeger-client-go/utils/http_json.go create mode 100644 vendor/github.com/uber/jaeger-client-go/utils/localip.go create mode 100644 vendor/github.com/uber/jaeger-client-go/utils/rand.go create mode 100644 vendor/github.com/uber/jaeger-client-go/utils/rate_limiter.go create mode 100644 vendor/github.com/uber/jaeger-client-go/utils/udp_client.go create mode 100644 vendor/github.com/uber/jaeger-client-go/utils/utils.go create mode 100644 vendor/github.com/uber/jaeger-client-go/zipkin.go create mode 100644 vendor/github.com/uber/jaeger-client-go/zipkin_thrift_span.go create mode 100644 vendor/github.com/uber/jaeger-lib/LICENSE create mode 100644 vendor/github.com/uber/jaeger-lib/README.md create mode 100644 vendor/github.com/uber/jaeger-lib/metrics/counter.go create mode 100644 vendor/github.com/uber/jaeger-lib/metrics/factory.go create mode 100644 vendor/github.com/uber/jaeger-lib/metrics/gauge.go create mode 100644 vendor/github.com/uber/jaeger-lib/metrics/local.go create mode 100644 vendor/github.com/uber/jaeger-lib/metrics/metrics.go create mode 100644 vendor/github.com/uber/jaeger-lib/metrics/stopwatch.go create mode 100644 vendor/github.com/uber/jaeger-lib/metrics/timer.go diff --git a/client/client.go b/client/client.go index 62bbdbd45..ca4b34fdd 100644 --- a/client/client.go +++ b/client/client.go @@ -6,8 +6,10 @@ import ( "io/ioutil" "time" + "github.com/grpc-ecosystem/grpc-opentracing/go/otgrpc" controlapi "github.com/moby/buildkit/api/services/control" "github.com/moby/buildkit/util/appdefaults" + opentracing "github.com/opentracing/opentracing-go" "github.com/pkg/errors" "google.golang.org/grpc" "google.golang.org/grpc/credentials" @@ -39,6 +41,11 @@ func New(address string, opts ...ClientOpt) (*Client, error) { gopts = append(gopts, opt) needWithInsecure = false } + if wt, ok := o.(*withTracer); ok { + gopts = append(gopts, + grpc.WithUnaryInterceptor(otgrpc.OpenTracingClientInterceptor(wt.tracer, otgrpc.LogPayloads())), + grpc.WithStreamInterceptor(otgrpc.OpenTracingStreamClientInterceptor(wt.tracer))) + } } if needWithInsecure { gopts = append(gopts, grpc.WithInsecure()) @@ -115,3 +122,11 @@ func loadCredentials(opts *withCredentials) (grpc.DialOption, error) { return grpc.WithTransportCredentials(credentials.NewTLS(cfg)), nil } + +func WithTracer(t opentracing.Tracer) ClientOpt { + return &withTracer{t} +} + +type withTracer struct { + tracer opentracing.Tracer +} diff --git a/client/solve.go b/client/solve.go index 630ffbda4..6a5f75fa4 100644 --- a/client/solve.go +++ b/client/solve.go @@ -17,6 +17,7 @@ import ( "github.com/moby/buildkit/session/filesync" "github.com/moby/buildkit/session/grpchijack" "github.com/moby/buildkit/solver/pb" + opentracing "github.com/opentracing/opentracing-go" "github.com/pkg/errors" "github.com/sirupsen/logrus" "golang.org/x/sync/errgroup" @@ -61,6 +62,10 @@ func (c *Client) Solve(ctx context.Context, def *llb.Definition, opt SolveOpt, s statusContext, cancelStatus := context.WithCancel(context.Background()) defer cancelStatus() + if span := opentracing.SpanFromContext(ctx); span != nil { + statusContext = opentracing.ContextWithSpan(statusContext, span) + } + s, err := session.NewSession(defaultSessionName(), opt.SharedKey) if err != nil { return errors.Wrap(err, "failed to create session") diff --git a/cmd/buildctl/build.go b/cmd/buildctl/build.go index e65425e16..8fe190387 100644 --- a/cmd/buildctl/build.go +++ b/cmd/buildctl/build.go @@ -12,7 +12,6 @@ import ( "github.com/moby/buildkit/client" "github.com/moby/buildkit/client/llb" "github.com/moby/buildkit/solver/pb" - "github.com/moby/buildkit/util/appcontext" "github.com/moby/buildkit/util/progress/progressui" "github.com/opencontainers/go-digest" "github.com/pkg/errors" @@ -116,7 +115,7 @@ func build(clicontext *cli.Context) error { ch := make(chan *client.SolveStatus) displayCh := make(chan *client.SolveStatus) - eg, ctx := errgroup.WithContext(appcontext.Context()) + eg, ctx := errgroup.WithContext(commandContext(clicontext)) exporterAttrs, err := attrMap(clicontext.StringSlice("exporter-opt")) if err != nil { diff --git a/cmd/buildctl/debug/workers.go b/cmd/buildctl/debug/workers.go index f8edcc4bd..e59e306ad 100644 --- a/cmd/buildctl/debug/workers.go +++ b/cmd/buildctl/debug/workers.go @@ -1,13 +1,13 @@ package debug import ( + "context" "fmt" "os" "sort" "text/tabwriter" "github.com/moby/buildkit/client" - "github.com/moby/buildkit/util/appcontext" "github.com/urfave/cli" ) @@ -37,7 +37,7 @@ func listWorkers(clicontext *cli.Context) error { return err } - workers, err := c.ListWorkers(appcontext.Context(), client.WithWorkerFilter(clicontext.StringSlice("filter"))) + workers, err := c.ListWorkers(commandContext(clicontext), client.WithWorkerFilter(clicontext.StringSlice("filter"))) if err != nil { return err } @@ -86,3 +86,7 @@ func sortedKeys(m map[string]string) []string { sort.Strings(s) return s } + +func commandContext(c *cli.Context) context.Context { + return c.App.Metadata["context"].(context.Context) +} diff --git a/cmd/buildctl/diskusage.go b/cmd/buildctl/diskusage.go index c08cf0cd1..9f6103421 100644 --- a/cmd/buildctl/diskusage.go +++ b/cmd/buildctl/diskusage.go @@ -7,7 +7,6 @@ import ( "text/tabwriter" "github.com/moby/buildkit/client" - "github.com/moby/buildkit/util/appcontext" "github.com/tonistiigi/units" "github.com/urfave/cli" ) @@ -34,7 +33,7 @@ func diskUsage(clicontext *cli.Context) error { return err } - du, err := c.DiskUsage(appcontext.Context(), client.WithFilter(clicontext.String("filter"))) + du, err := c.DiskUsage(commandContext(clicontext), client.WithFilter(clicontext.String("filter"))) if err != nil { return err } diff --git a/cmd/buildctl/main.go b/cmd/buildctl/main.go index 31fa954fb..6d825f97c 100644 --- a/cmd/buildctl/main.go +++ b/cmd/buildctl/main.go @@ -8,6 +8,7 @@ import ( "github.com/moby/buildkit/client" "github.com/moby/buildkit/util/appdefaults" "github.com/moby/buildkit/util/profiler" + opentracing "github.com/opentracing/opentracing-go" "github.com/sirupsen/logrus" "github.com/urfave/cli" ) @@ -71,6 +72,8 @@ func main() { return nil } + attachAppContext(app) + profiler.Attach(app) if err := app.Run(os.Args); err != nil { @@ -96,7 +99,13 @@ func resolveClient(c *cli.Context) (*client.Client, error) { caCert := c.GlobalString("tlscacert") cert := c.GlobalString("tlscert") key := c.GlobalString("tlskey") + opts := []client.ClientOpt{client.WithBlock()} + + if span := opentracing.SpanFromContext(commandContext(c)); span != nil { + opts = append(opts, client.WithTracer(span.Tracer())) + } + if caCert != "" || cert != "" || key != "" { opts = append(opts, client.WithCredentials(serverName, caCert, cert, key)) } diff --git a/cmd/buildctl/prune.go b/cmd/buildctl/prune.go index 30ac8e73e..3dda41b66 100644 --- a/cmd/buildctl/prune.go +++ b/cmd/buildctl/prune.go @@ -6,7 +6,6 @@ import ( "text/tabwriter" "github.com/moby/buildkit/client" - "github.com/moby/buildkit/util/appcontext" "github.com/tonistiigi/units" "github.com/urfave/cli" ) @@ -53,7 +52,7 @@ func prune(clicontext *cli.Context) error { } }() - err = c.Prune(appcontext.Context(), ch) + err = c.Prune(commandContext(clicontext), ch) close(ch) <-printed if err != nil { diff --git a/cmd/buildctl/trace.go b/cmd/buildctl/trace.go new file mode 100644 index 000000000..73ef15284 --- /dev/null +++ b/cmd/buildctl/trace.go @@ -0,0 +1,92 @@ +package main + +import ( + "context" + "io" + "os" + "strings" + + "github.com/moby/buildkit/util/appcontext" + opentracing "github.com/opentracing/opentracing-go" + "github.com/opentracing/opentracing-go/ext" + "github.com/opentracing/opentracing-go/log" + jaeger "github.com/uber/jaeger-client-go" + "github.com/urfave/cli" +) + +func getTracer() (opentracing.Tracer, io.Closer) { + if traceAddr := os.Getenv("JAEGER_TRACE"); traceAddr != "" { + tr, err := jaeger.NewUDPTransport(traceAddr, 0) + if err != nil { + panic(err) + } + + // metricsFactory := prometheus.New() + return jaeger.NewTracer( + "buildctl", + jaeger.NewConstSampler(true), + jaeger.NewRemoteReporter(tr), + ) + } + + return opentracing.NoopTracer{}, &nopCloser{} +} + +func attachAppContext(app *cli.App) { + ctx := appcontext.Context() + + tracer, closer := getTracer() + + var span opentracing.Span + + for i, cmd := range app.Commands { + func(before cli.BeforeFunc) { + name := cmd.Name + app.Commands[i].Before = func(clicontext *cli.Context) error { + if before != nil { + if err := before(clicontext); err != nil { + return err + } + } + + span = tracer.StartSpan(name) + span.LogFields(log.String("command", strings.Join(os.Args, " "))) + + ctx = opentracing.ContextWithSpan(ctx, span) + + clicontext.App.Metadata["context"] = ctx + return nil + } + }(cmd.Before) + } + + app.ExitErrHandler = func(clicontext *cli.Context, err error) { + ext.Error.Set(span, true) + cli.HandleExitCoder(err) + } + + after := app.After + app.After = func(clicontext *cli.Context) error { + if after != nil { + if err := after(clicontext); err != nil { + return err + } + } + if span != nil { + span.Finish() + } + return closer.Close() + } + +} + +func commandContext(c *cli.Context) context.Context { + return c.App.Metadata["context"].(context.Context) +} + +type nopCloser struct { +} + +func (*nopCloser) Close() error { + return nil +} diff --git a/cmd/buildkitd/main.go b/cmd/buildkitd/main.go index c02d9aad1..f07cd1554 100644 --- a/cmd/buildkitd/main.go +++ b/cmd/buildkitd/main.go @@ -13,6 +13,7 @@ import ( "github.com/containerd/containerd/sys" "github.com/docker/go-connections/sockets" + "github.com/grpc-ecosystem/grpc-opentracing/go/otgrpc" "github.com/moby/buildkit/cache/cacheimport" "github.com/moby/buildkit/control" "github.com/moby/buildkit/frontend" @@ -107,7 +108,7 @@ func main() { return err } } - opts := []grpc.ServerOption{unaryInterceptor(ctx)} + opts := []grpc.ServerOption{unaryInterceptor(ctx), grpc.StreamInterceptor(otgrpc.OpenTracingStreamServerInterceptor(tracer))} creds, err := serverCredentials(c) if err != nil { return err @@ -163,6 +164,13 @@ func main() { return nil } + app.After = func(context *cli.Context) error { + if closeTracer != nil { + return closeTracer.Close() + } + return nil + } + profiler.Attach(app) if err := app.Run(os.Args); err != nil { @@ -217,6 +225,8 @@ func getListener(addr string) (net.Listener, error) { } func unaryInterceptor(globalCtx context.Context) grpc.ServerOption { + withTrace := otgrpc.OpenTracingServerInterceptor(tracer, otgrpc.LogPayloads()) + return grpc.UnaryInterceptor(func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (resp interface{}, err error) { ctx, cancel := context.WithCancel(ctx) defer cancel() @@ -229,7 +239,7 @@ func unaryInterceptor(globalCtx context.Context) grpc.ServerOption { } }() - resp, err = handler(ctx, req) + resp, err = withTrace(ctx, req, info, handler) if err != nil { logrus.Errorf("%s returned error: %+v", info.FullMethod, err) } diff --git a/cmd/buildkitd/trace.go b/cmd/buildkitd/trace.go new file mode 100644 index 000000000..3d6fed83a --- /dev/null +++ b/cmd/buildkitd/trace.go @@ -0,0 +1,31 @@ +package main + +import ( + "io" + "os" + + opentracing "github.com/opentracing/opentracing-go" + jaeger "github.com/uber/jaeger-client-go" +) + +var tracer opentracing.Tracer +var closeTracer io.Closer + +func init() { + + tracer = opentracing.NoopTracer{} + + if traceAddr := os.Getenv("JAEGER_TRACE"); traceAddr != "" { + tr, err := jaeger.NewUDPTransport(traceAddr, 0) + if err != nil { + panic(err) + } + + tracer, closeTracer = jaeger.NewTracer( + "buildkitd", + jaeger.NewConstSampler(true), + jaeger.NewRemoteReporter(tr), + ) + } + +} diff --git a/vendor.conf b/vendor.conf index 362edac8a..7517cd20a 100644 --- a/vendor.conf +++ b/vendor.conf @@ -47,4 +47,12 @@ github.com/docker/distribution 30578ca32960a4d368bf6db67b0a33c2a1f3dc6f github.com/tonistiigi/units 29de085e9400559bd68aea2e7bc21566e7b8281d github.com/docker/cli 99576756eb3303b7af8102c502f21a912e3c1af6 https://github.com/tonistiigi/docker-cli.git github.com/docker/docker-credential-helpers d68f9aeca33f5fd3f08eeae5e9d175edf4e731d1 -github.com/docker/libnetwork 822e5b59d346b7ad0735df2c8e445e9787320e67 \ No newline at end of file +github.com/docker/libnetwork 822e5b59d346b7ad0735df2c8e445e9787320e67 + + +github.com/grpc-ecosystem/grpc-opentracing 420e5c3331a082e0c873adeeab1819fe1749dd0b git://github.com/tonistiigi/grpc-opentracing.git # pr#25 +github.com/opentracing/opentracing-go 1361b9cd60be79c4c3a7fa9841b3c132e40066a7 +github.com/uber/jaeger-client-go e02c85f9069ea625a96fc4e1afb5e9ac6c569a6d +github.com/apache/thrift b2a4d4ae21c789b689dd162deb819665567f481c +github.com/uber/jaeger-lib c48167d9cae5887393dd5e61efd06a4a48b7fbb3 +github.com/codahale/hdrhistogram f8ad88b59a584afeee9d334eff879b104439117b \ No newline at end of file diff --git a/vendor/github.com/apache/thrift/LICENSE b/vendor/github.com/apache/thrift/LICENSE new file mode 100644 index 000000000..3b6d7d74c --- /dev/null +++ b/vendor/github.com/apache/thrift/LICENSE @@ -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 +# +# 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 ) +-------------------------------------------------- diff --git a/vendor/github.com/apache/thrift/NOTICE b/vendor/github.com/apache/thrift/NOTICE new file mode 100644 index 000000000..c23995a23 --- /dev/null +++ b/vendor/github.com/apache/thrift/NOTICE @@ -0,0 +1,5 @@ +Apache Thrift +Copyright 2006-2010 The Apache Software Foundation. + +This product includes software developed at +The Apache Software Foundation (http://www.apache.org/). \ No newline at end of file diff --git a/vendor/github.com/apache/thrift/README.md b/vendor/github.com/apache/thrift/README.md new file mode 100644 index 000000000..07cd32f09 --- /dev/null +++ b/vendor/github.com/apache/thrift/README.md @@ -0,0 +1,166 @@ +Apache Thrift +============= + ++[![Build Status](https://travis-ci.org/apache/thrift.svg?branch=master)](https://travis-ci.org/apache/thrift) +- +[![AppVeyor Build status](https://ci.appveyor.com/api/projects/status/e2qks7enyp9gw7ma?svg=true)](https://ci.appveyor.com/project/apache/thrift) + + +Introduction +============ + +Thrift is a lightweight, language-independent software stack with an +associated code generation mechanism for RPC. Thrift provides clean +abstractions for data transport, data serialization, and application +level processing. The code generation system takes a simple definition +language as its input and generates code across programming languages that +uses the abstracted stack to build interoperable RPC clients and servers. + +Thrift is specifically designed to support non-atomic version changes +across client and server code. + +For more details on Thrift's design and implementation, take a gander at +the Thrift whitepaper included in this distribution or at the README.md files +in your particular subdirectory of interest. + +Hierarchy +========= + +thrift/ + + compiler/ + + Contains the Thrift compiler, implemented in C++. + + lib/ + + Contains the Thrift software library implementation, subdivided by + language of implementation. + + cpp/ + go/ + java/ + php/ + py/ + rb/ + + test/ + + Contains sample Thrift files and test code across the target programming + languages. + + tutorial/ + + Contains a basic tutorial that will teach you how to develop software + using Thrift. + +Requirements +============ + +See http://thrift.apache.org/docs/install for an up-to-date list of build requirements. + +Resources +========= + +More information about Thrift can be obtained on the Thrift webpage at: + + http://thrift.apache.org + +Acknowledgments +=============== + +Thrift was inspired by pillar, a lightweight RPC tool written by Adam D'Angelo, +and also by Google's protocol buffers. + +Installation +============ + +If you are building from the first time out of the source repository, you will +need to generate the configure scripts. (This is not necessary if you +downloaded a tarball.) From the top directory, do: + + ./bootstrap.sh + +Once the configure scripts are generated, thrift can be configured. +From the top directory, do: + + ./configure + +You may need to specify the location of the boost files explicitly. +If you installed boost in /usr/local, you would run configure as follows: + + ./configure --with-boost=/usr/local + +Note that by default the thrift C++ library is typically built with debugging +symbols included. If you want to customize these options you should use the +CXXFLAGS option in configure, as such: + + ./configure CXXFLAGS='-g -O2' + ./configure CFLAGS='-g -O2' + ./configure CPPFLAGS='-DDEBUG_MY_FEATURE' + +To enable gcov required options -fprofile-arcs -ftest-coverage enable them: + + ./configure --enable-coverage + +Run ./configure --help to see other configuration options + +Please be aware that the Python library will ignore the --prefix option +and just install wherever Python's distutils puts it (usually along +the lines of /usr/lib/pythonX.Y/site-packages/). If you need to control +where the Python modules are installed, set the PY_PREFIX variable. +(DESTDIR is respected for Python and C++.) + +Make thrift: + + make + +From the top directory, become superuser and do: + + make install + +Note that some language packages must be installed manually using build tools +better suited to those languages (at the time of this writing, this applies +to Java, Ruby, PHP). + +Look for the README.md file in the lib// folder for more details on the +installation of each language library package. + +Testing +======= + +There are a large number of client library tests that can all be run +from the top-level directory. + + make -k check + +This will make all of the libraries (as necessary), and run through +the unit tests defined in each of the client libraries. If a single +language fails, the make check will continue on and provide a synopsis +at the end. + +To run the cross-language test suite, please run: + + make cross + +This will run a set of tests that use different language clients and +servers. + +License +======= + +Licensed to the Apache Software Foundation (ASF) under one +or more contributor license agreements. See the NOTICE file +distributed with this work for additional information +regarding copyright ownership. The ASF licenses this file +to you under the Apache License, Version 2.0 (the +"License"); you may not use this file except in compliance +with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, +software distributed under the License is distributed on an +"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +KIND, either express or implied. See the License for the +specific language governing permissions and limitations +under the License. diff --git a/vendor/github.com/apache/thrift/compiler/cpp/README.md b/vendor/github.com/apache/thrift/compiler/cpp/README.md new file mode 100644 index 000000000..90300ac03 --- /dev/null +++ b/vendor/github.com/apache/thrift/compiler/cpp/README.md @@ -0,0 +1,83 @@ +# Build compiler using CMake + +Use the following steps to build using cmake: + + mkdir cmake-build + cd cmake-build + cmake .. + make + + +### Create an eclipse project + + mkdir cmake-ec && cd cmake-ec + cmake -G "Eclipse CDT4 - Unix Makefiles" .. + make + +Now open the folder cmake-ec using eclipse. + + +### Cross compile using mingw32 and generate a Windows Installer with CPack + + mkdir cmake-mingw32 && cd cmake-mingw32 + cmake -DCMAKE_TOOLCHAIN_FILE=../build/cmake/mingw32-toolchain.cmake -DBUILD_COMPILER=ON -DBUILD_LIBRARIES=OFF -DBUILD_TESTING=OFF -DBUILD_EXAMPLES=OFF .. + cpack + +## Build on windows + +### using Git Bash +Git Bash provides flex and bison, so you just need to do this: + + mkdir cmake-vs && cd cmake-vs + cmake -DWITH_SHARED_LIB=off .. + +### using Win flex-bison + +In order to build on windows with winflexbison a few additional steps are necessary: + +1. Download winflexbison from http://sourceforge.net/projects/winflexbison/ +2. Extract the winflex bison files to for e.g. C:\winflexbison +3. Make the CMake variables point to the correct binaries. + * FLEX_EXECUTABLE = C:/winbuild/win_flex.exe + * BISON_EXECUTABLE = C:/winbuild/win_bison.exe +4. Generate a Visual Studio project: +``` +mkdir cmake-vs && cd cmake-vs +cmake -G "Visual Studio 12" -DWITH_SHARED_LIB=off .. +``` +5. Now open the folder build_vs using Visual Studio 2013. + +# Building the Thrift IDL compiler in Windows + +If you don't want to use CMake you can use the already available Visual Studio +2010 solution. +The Visual Studio project contains pre-build commands to generate the +thriftl.cc, thrifty.cc and thrifty.hh files which are necessary to build +the compiler. These depend on bison, flex and their dependencies to +work properly. +Download flex & bison as described above. +Place these binaries somewhere in the path and +rename win_flex.exe and win_bison.exe to flex.exe and bison.exe respectively. + +If this doesn't work on a system, try these manual pre-build steps. + +Open compiler.sln and remove the Pre-build commands under the project's + Properties -> Build Events -> Pre-Build Events. + +From a command prompt: +> cd thrift/compiler/cpp +> flex -osrc\thrift\thriftl.cc src\thrift\thriftl.ll +In the generated thriftl.cc, comment out #include + +Place a copy of bison.simple in thrift/compiler/cpp +> bison -y -o "src/thrift/thrifty.cc" --defines src/thrift/thrifty.yy +> move src\thrift\thrifty.cc.hh src\thrift\thrifty.hh + +Bison might generate the yacc header file "thrifty.cc.h" with just one h ".h" extension; in this case you'll have to rename to "thrifty.h". + +> move src\thrift\version.h.in src\thrift\version.h + +Download inttypes.h from the interwebs and place it in an include path +location (e.g. thrift/compiler/cpp/src). + +Build the compiler in Visual Studio. diff --git a/vendor/github.com/apache/thrift/compiler/cpp/src/thrift/windows/config.h b/vendor/github.com/apache/thrift/compiler/cpp/src/thrift/windows/config.h new file mode 100644 index 000000000..5f057ca81 --- /dev/null +++ b/vendor/github.com/apache/thrift/compiler/cpp/src/thrift/windows/config.h @@ -0,0 +1,66 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT 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_WINDOWS_CONFIG_H_ +#define _THRIFT_WINDOWS_CONFIG_H_ 1 + +#if defined(_MSC_VER) && (_MSC_VER > 1200) +#pragma once +#endif // _MSC_VER + +#ifndef _WIN32 +#error "This is a Windows header only" +#endif + +#include +#include +#include + +#define strtoll(begin_ptr, end_ptr, length) _strtoi64(begin_ptr, end_ptr, length) + +#define PRIu64 "I64d" +#define PRIi64 "I64d" + +// squelch deprecation warnings +#pragma warning(disable : 4996) +// squelch bool conversion performance warning +#pragma warning(disable : 4800) + +// MSVC10 (2010) or later has stdint.h +#if _MSC_VER >= 1600 +#define HAVE_STDINT_H 1 +#endif + +// Must be using VS2010 or later, or boost, so that C99 types are defined in the global namespace +#ifdef HAVE_STDINT_H +#include +#else +#include + +typedef boost::int64_t int64_t; +typedef boost::uint64_t uint64_t; +typedef boost::int32_t int32_t; +typedef boost::uint32_t uint32_t; +typedef boost::int16_t int16_t; +typedef boost::uint16_t uint16_t; +typedef boost::int8_t int8_t; +typedef boost::uint8_t uint8_t; +#endif + +#endif // _THRIFT_WINDOWS_CONFIG_H_ diff --git a/vendor/github.com/apache/thrift/lib/c_glib/README.md b/vendor/github.com/apache/thrift/lib/c_glib/README.md new file mode 100644 index 000000000..fd70d089c --- /dev/null +++ b/vendor/github.com/apache/thrift/lib/c_glib/README.md @@ -0,0 +1,34 @@ +Thrift C Software Library + +License +======= + +Licensed to the Apache Software Foundation (ASF) under one +or more contributor license agreements. See the NOTICE file +distributed with this work for additional information +regarding copyright ownership. The ASF licenses this file +to you under the Apache License, Version 2.0 (the +"License"); you may not use this file except in compliance +with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, +software distributed under the License is distributed on an +"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +KIND, either express or implied. See the License for the +specific language governing permissions and limitations +under the License. + +Using Thrift with C +=================== + +The Thrift C libraries are built using the GNU tools. Follow the instructions +in the top-level README in order to generate the Makefiles. + +Dependencies +============ + +GLib +http://www.gtk.org/ + diff --git a/vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/processor/thrift_dispatch_processor.c b/vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/processor/thrift_dispatch_processor.c new file mode 100644 index 000000000..57d621751 --- /dev/null +++ b/vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/processor/thrift_dispatch_processor.c @@ -0,0 +1,143 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include +#include +#include + +G_DEFINE_ABSTRACT_TYPE (ThriftDispatchProcessor, + thrift_dispatch_processor, + THRIFT_TYPE_PROCESSOR) + +gboolean +thrift_dispatch_processor_process (ThriftProcessor *processor, + ThriftProtocol *in, + ThriftProtocol *out, + GError **error) +{ + gchar *fname; + ThriftMessageType mtype; + gint32 seqid; + ThriftDispatchProcessor *dispatch_processor = + THRIFT_DISPATCH_PROCESSOR (processor); + + /* Read the start of the message, which we expect to be a method call */ + if (thrift_protocol_read_message_begin (in, + &fname, + &mtype, + &seqid, + error) < 0) { + g_warning ("error reading start of message: %s", + (error != NULL) ? (*error)->message : "(null)"); + return FALSE; + } + else if (mtype != T_CALL && mtype != T_ONEWAY) { + g_warning ("received invalid message type %d from client", mtype); + return FALSE; + } + + /* Dispatch the method call */ + return THRIFT_DISPATCH_PROCESSOR_GET_CLASS (dispatch_processor) + ->dispatch_call (dispatch_processor, + in, + out, + fname, + seqid, + error); +} + +static gboolean +thrift_dispatch_processor_real_dispatch_call (ThriftDispatchProcessor *self, + ThriftProtocol *in, + ThriftProtocol *out, + gchar *fname, + gint32 seqid, + GError **error) +{ + ThriftTransport *transport; + ThriftApplicationException *xception; + gchar *message; + gint32 result; + gboolean dispatch_result = FALSE; + + THRIFT_UNUSED_VAR (self); + + /* By default, return an application exception to the client indicating the + method name is not recognized. */ + + if ((thrift_protocol_skip (in, T_STRUCT, error) < 0) || + (thrift_protocol_read_message_end (in, error) < 0)) + return FALSE; + + g_object_get (in, "transport", &transport, NULL); + result = thrift_transport_read_end (transport, error); + g_object_unref (transport); + if (result < 0) + return FALSE; + + if (thrift_protocol_write_message_begin (out, + fname, + T_EXCEPTION, + seqid, + error) < 0) + return FALSE; + message = g_strconcat ("Invalid method name: '", fname, "'", NULL); + g_free (fname); + xception = + g_object_new (THRIFT_TYPE_APPLICATION_EXCEPTION, + "type", THRIFT_APPLICATION_EXCEPTION_ERROR_UNKNOWN_METHOD, + "message", message, + NULL); + g_free (message); + result = thrift_struct_write (THRIFT_STRUCT (xception), + out, + error); + g_object_unref (xception); + if ((result < 0) || + (thrift_protocol_write_message_end (out, error) < 0)) + return FALSE; + + g_object_get (out, "transport", &transport, NULL); + dispatch_result = + ((thrift_transport_write_end (transport, error) >= 0) && + (thrift_transport_flush (transport, error) >= 0)); + g_object_unref (transport); + + return dispatch_result; +} + +static void +thrift_dispatch_processor_init (ThriftDispatchProcessor *self) +{ + THRIFT_UNUSED_VAR (self); +} + +static void +thrift_dispatch_processor_class_init (ThriftDispatchProcessorClass *klass) +{ + ThriftProcessorClass *processor_class = + THRIFT_PROCESSOR_CLASS (klass); + + /* Implement ThriftProcessor's process method */ + processor_class->process = thrift_dispatch_processor_process; + + /* Provide a default implement for dispatch_call, which returns an exception + to the client indicating the method name was not recognized */ + klass->dispatch_call = thrift_dispatch_processor_real_dispatch_call; +} diff --git a/vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/processor/thrift_dispatch_processor.h b/vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/processor/thrift_dispatch_processor.h new file mode 100644 index 000000000..5afb85ec8 --- /dev/null +++ b/vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/processor/thrift_dispatch_processor.h @@ -0,0 +1,95 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef _THRIFT_DISPATCH_PROCESSOR_H +#define _THRIFT_DISPATCH_PROCESSOR_H + +#include + +#include + +G_BEGIN_DECLS + +/*! \file thrift_dispatch_processor.h + * \brief Parses a method-call message header and invokes a function + * to dispatch the call by function name. + * + * ThriftDispatchProcessor is an abstract helper class that parses the + * header of a method-call message and invokes a member function, + * dispatch_call, with the method's name. + * + * Subclasses must implement dispatch_call to dispatch the method call + * to the implementing function. + */ + +/* Type macros */ +#define THRIFT_TYPE_DISPATCH_PROCESSOR (thrift_dispatch_processor_get_type ()) +#define THRIFT_DISPATCH_PROCESSOR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), THRIFT_TYPE_DISPATCH_PROCESSOR, ThriftDispatchProcessor)) +#define THRIFT_IS_DISPATCH_PROCESSOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), THRIFT_TYPE_DISPATCH_PROCESSOR)) +#define THRIFT_DISPATCH_PROCESSOR_CLASS(c) (G_TYPE_CHECK_CLASS_CAST ((c), THRIFT_TYPE_DISPATCH_PROCESSOR, ThriftDispatchProcessorClass)) +#define THRIFT_IS_DISPATCH_PROCESSOR_CLASS(c) (G_TYPE_CHECK_CLASS_TYPE ((c), THRIFT_TYPE_DISPATCH_PROCESSOR)) +#define THRIFT_DISPATCH_PROCESSOR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), THRIFT_TYPE_DISPATCH_PROCESSOR, ThriftDispatchProcessorClass)) + +/*! + * Thrift Dispatch Processor object + */ +struct _ThriftDispatchProcessor +{ + ThriftProcessor parent; +}; +typedef struct _ThriftDispatchProcessor ThriftDispatchProcessor; + +/*! + * Thrift Dispatch Processor class + */ +struct _ThriftDispatchProcessorClass +{ + ThriftProcessorClass parent; + + /* public */ + gboolean (*process) (ThriftProcessor *processor, + ThriftProtocol *in, + ThriftProtocol *out, + GError **error); + + /* protected */ + gboolean (*dispatch_call) (ThriftDispatchProcessor *self, + ThriftProtocol *in, + ThriftProtocol *out, + gchar *fname, + gint32 seqid, + GError **error); +}; +typedef struct _ThriftDispatchProcessorClass ThriftDispatchProcessorClass; + +/* Used by THRIFT_TYPE_DISPATCH_PROCESSOR */ +GType thrift_dispatch_processor_get_type (void); + +/*! + * Processes a request. + * \public \memberof ThriftDispatchProcessorClass + */ +gboolean thrift_dispatch_processor_process (ThriftProcessor *processor, + ThriftProtocol *in, + ThriftProtocol *out, + GError **error); + +G_END_DECLS + +#endif /* _THRIFT_DISPATCH_PROCESSOR_H */ diff --git a/vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/processor/thrift_processor.c b/vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/processor/thrift_processor.c new file mode 100644 index 000000000..c242c2503 --- /dev/null +++ b/vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/processor/thrift_processor.c @@ -0,0 +1,45 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include +#include + +G_DEFINE_ABSTRACT_TYPE(ThriftProcessor, thrift_processor, G_TYPE_OBJECT) + +gboolean +thrift_processor_process (ThriftProcessor *processor, ThriftProtocol *in, + ThriftProtocol *out, GError **error) +{ + return + THRIFT_PROCESSOR_GET_CLASS (processor)->process (processor, in, out, error); +} + +/* class initializer for ThriftProcessor */ +static void +thrift_processor_class_init (ThriftProcessorClass *cls) +{ + /* set these as virtual methods to be implemented by a subclass */ + cls->process = thrift_processor_process; +} + +static void +thrift_processor_init (ThriftProcessor *processor) +{ + THRIFT_UNUSED_VAR (processor); +} diff --git a/vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/processor/thrift_processor.h b/vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/processor/thrift_processor.h new file mode 100644 index 000000000..ff2d2dae4 --- /dev/null +++ b/vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/processor/thrift_processor.h @@ -0,0 +1,76 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT 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_PROCESSOR_H +#define _THRIFT_PROCESSOR_H + +#include + +#include + +G_BEGIN_DECLS + +/*! \file thrift_processor.h + * \brief Abstract class for Thrift processors. + */ + +/* type macros */ +#define THRIFT_TYPE_PROCESSOR (thrift_processor_get_type ()) +#define THRIFT_PROCESSOR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), THRIFT_TYPE_PROCESSOR, ThriftProcessor)) +#define THRIFT_IS_PROCESSOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), THRIFT_TYPE_PROCESSOR)) +#define THRIFT_PROCESSOR_CLASS(c) (G_TYPE_CHECK_CLASS_CAST ((c), THRIFT_TYPE_PROCESSOR, ThriftProcessorClass)) +#define THRIFT_IS_PROCESSOR_CLASS(c) (G_TYPE_CHECK_CLASS_TYPE ((c), THRIFT_TYPE_PROCESSOR)) +#define THRIFT_PROCESSOR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), THRIFT_TYPE_PROCESSOR, ThriftProcessorClass)) + +/*! + * Thrift Processorobject + */ +struct _ThriftProcessor +{ + GObject parent; +}; +typedef struct _ThriftProcessor ThriftProcessor; + +/*! + * Thrift Processor class + */ +struct _ThriftProcessorClass +{ + GObjectClass parent; + + /* vtable */ + gboolean (*process) (ThriftProcessor *processor, ThriftProtocol *in, + ThriftProtocol *out, GError **error); +}; +typedef struct _ThriftProcessorClass ThriftProcessorClass; + +/* used by THRIFT_TYPE_PROCESSOR */ +GType thrift_processor_get_type (void); + +/*! + * Processes the request. + * \public \memberof ThriftProcessorClass + */ +gboolean thrift_processor_process (ThriftProcessor *processor, + ThriftProtocol *in, ThriftProtocol *out, + GError **error); + +G_END_DECLS + +#endif /* _THRIFT_PROCESSOR_H */ diff --git a/vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/protocol/thrift_binary_protocol.c b/vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/protocol/thrift_binary_protocol.c new file mode 100644 index 000000000..48a2c5c62 --- /dev/null +++ b/vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/protocol/thrift_binary_protocol.c @@ -0,0 +1,904 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT 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 +#include + +#include +#include +#include + +G_DEFINE_TYPE(ThriftBinaryProtocol, thrift_binary_protocol, THRIFT_TYPE_PROTOCOL) + +static guint64 +thrift_bitwise_cast_guint64 (gdouble v) +{ + union { + gdouble from; + guint64 to; + } u; + u.from = v; + return u.to; +} + +static gdouble +thrift_bitwise_cast_gdouble (guint64 v) +{ + union { + guint64 from; + gdouble to; + } u; + u.from = v; + return u.to; +} + +gint32 +thrift_binary_protocol_write_message_begin (ThriftProtocol *protocol, + const gchar *name, const ThriftMessageType message_type, + const gint32 seqid, GError **error) +{ + gint32 version = (THRIFT_BINARY_PROTOCOL_VERSION_1) + | ((gint32) message_type); + gint32 ret; + gint32 xfer = 0; + + g_return_val_if_fail (THRIFT_IS_BINARY_PROTOCOL (protocol), -1); + + if ((ret = thrift_protocol_write_i32 (protocol, version, error)) < 0) + { + return -1; + } + xfer += ret; + if ((ret = thrift_protocol_write_string (protocol, name, error)) < 0) + { + return -1; + } + xfer += ret; + if ((ret = thrift_protocol_write_i32 (protocol, seqid, error)) < 0) + { + return -1; + } + xfer += ret; + return xfer; +} + +gint32 +thrift_binary_protocol_write_message_end (ThriftProtocol *protocol, + GError **error) +{ + /* satisfy -Wall */ + THRIFT_UNUSED_VAR (protocol); + THRIFT_UNUSED_VAR (error); + return 0; +} + +gint32 +thrift_binary_protocol_write_struct_begin (ThriftProtocol *protocol, + const gchar *name, + GError **error) +{ + /* satisfy -Wall */ + THRIFT_UNUSED_VAR (protocol); + THRIFT_UNUSED_VAR (name); + THRIFT_UNUSED_VAR (error); + return 0; +} + +gint32 +thrift_binary_protocol_write_struct_end (ThriftProtocol *protocol, + GError **error) +{ + /* satisfy -Wall */ + THRIFT_UNUSED_VAR (protocol); + THRIFT_UNUSED_VAR (error); + return 0; +} + +gint32 +thrift_binary_protocol_write_field_begin (ThriftProtocol *protocol, + const gchar *name, + const ThriftType field_type, + const gint16 field_id, + GError **error) +{ + gint32 ret; + gint32 xfer = 0; + + g_return_val_if_fail (THRIFT_IS_BINARY_PROTOCOL (protocol), -1); + + THRIFT_UNUSED_VAR (name); + + if ((ret = thrift_protocol_write_byte (protocol, (gint8) field_type, + error)) < 0) + { + return -1; + } + xfer += ret; + if ((ret = thrift_protocol_write_i16 (protocol, field_id, error)) < 0) + { + return -1; + } + xfer += ret; + return xfer; +} + +gint32 +thrift_binary_protocol_write_field_end (ThriftProtocol *protocol, + GError **error) +{ + /* satisfy -Wall */ + THRIFT_UNUSED_VAR (protocol); + THRIFT_UNUSED_VAR (error); + return 0; +} + +gint32 +thrift_binary_protocol_write_field_stop (ThriftProtocol *protocol, + GError **error) +{ + g_return_val_if_fail (THRIFT_IS_BINARY_PROTOCOL (protocol), -1); + return thrift_protocol_write_byte (protocol, (gint8) T_STOP, error); +} + +gint32 +thrift_binary_protocol_write_map_begin (ThriftProtocol *protocol, + const ThriftType key_type, + const ThriftType value_type, + const guint32 size, + GError **error) +{ + gint32 ret; + gint32 xfer = 0; + + g_return_val_if_fail (THRIFT_IS_BINARY_PROTOCOL (protocol), -1); + + if ((ret = thrift_protocol_write_byte (protocol, (gint8) key_type, + error)) < 0) + { + return -1; + } + xfer += ret; + if ((ret = thrift_protocol_write_byte (protocol, (gint8) value_type, + error)) < 0) + { + return -1; + } + xfer += ret; + if ((ret = thrift_protocol_write_i32 (protocol, (gint32) size, error)) < 0) + { + return -1; + } + xfer += ret; + return xfer; +} + +gint32 +thrift_binary_protocol_write_map_end (ThriftProtocol *protocol, + GError **error) +{ + THRIFT_UNUSED_VAR (protocol); + THRIFT_UNUSED_VAR (error); + return 0; +} + +gint32 +thrift_binary_protocol_write_list_begin (ThriftProtocol *protocol, + const ThriftType element_type, + const guint32 size, + GError **error) +{ + gint32 ret; + gint32 xfer = 0; + + g_return_val_if_fail (THRIFT_IS_BINARY_PROTOCOL (protocol), -1); + + if ((ret = thrift_protocol_write_byte (protocol, (gint8) element_type, + error)) < 0) + { + return -1; + } + xfer += ret; + + if ((ret = thrift_protocol_write_i32 (protocol, (gint32) size, error)) < 0) + { + return -1; + } + xfer += ret; + + return xfer; +} + +gint32 +thrift_binary_protocol_write_list_end (ThriftProtocol *protocol, + GError **error) +{ + THRIFT_UNUSED_VAR (protocol); + THRIFT_UNUSED_VAR (error); + return 0; +} + +gint32 +thrift_binary_protocol_write_set_begin (ThriftProtocol *protocol, + const ThriftType element_type, + const guint32 size, + GError **error) +{ + g_return_val_if_fail (THRIFT_IS_BINARY_PROTOCOL (protocol), -1); + + return thrift_protocol_write_list_begin (protocol, element_type, + size, error); +} + +gint32 +thrift_binary_protocol_write_set_end (ThriftProtocol *protocol, GError **error) +{ + THRIFT_UNUSED_VAR (protocol); + THRIFT_UNUSED_VAR (error); + return 0; +} + +gint32 +thrift_binary_protocol_write_bool (ThriftProtocol *protocol, + const gboolean value, GError **error) +{ + guint8 tmp; + + g_return_val_if_fail (THRIFT_IS_BINARY_PROTOCOL (protocol), -1); + + tmp = value ? 1 : 0; + return thrift_protocol_write_byte (protocol, tmp, error); +} + +gint32 +thrift_binary_protocol_write_byte (ThriftProtocol *protocol, const gint8 value, + GError **error) +{ + g_return_val_if_fail (THRIFT_IS_BINARY_PROTOCOL (protocol), -1); + + if (thrift_transport_write (protocol->transport, + (const gpointer) &value, 1, error)) + { + return 1; + } else { + return -1; + } +} + +gint32 +thrift_binary_protocol_write_i16 (ThriftProtocol *protocol, const gint16 value, + GError **error) +{ + gint16 net; + + g_return_val_if_fail (THRIFT_IS_BINARY_PROTOCOL (protocol), -1); + + net = g_htons (value); + if (thrift_transport_write (protocol->transport, + (const gpointer) &net, 2, error)) + { + return 2; + } else { + return -1; + } +} + +gint32 +thrift_binary_protocol_write_i32 (ThriftProtocol *protocol, const gint32 value, + GError **error) +{ + gint32 net; + + g_return_val_if_fail (THRIFT_IS_BINARY_PROTOCOL (protocol), -1); + + net = g_htonl (value); + if (thrift_transport_write (protocol->transport, + (const gpointer) &net, 4, error)) + { + return 4; + } else { + return -1; + } +} + +gint32 +thrift_binary_protocol_write_i64 (ThriftProtocol *protocol, const gint64 value, + GError **error) +{ + gint64 net; + + g_return_val_if_fail (THRIFT_IS_BINARY_PROTOCOL (protocol), -1); + + net = GUINT64_TO_BE (value); + if (thrift_transport_write (protocol->transport, + (const gpointer) &net, 8, error)) + { + return 8; + } else { + return -1; + } +} + +gint32 +thrift_binary_protocol_write_double (ThriftProtocol *protocol, + const gdouble value, GError **error) +{ + guint64 bits; + + g_return_val_if_fail (THRIFT_IS_BINARY_PROTOCOL (protocol), -1); + + bits = GUINT64_FROM_BE (thrift_bitwise_cast_guint64 (value)); + if (thrift_transport_write (protocol->transport, + (const gpointer) &bits, 8, error)) + { + return 8; + } else { + return -1; + } +} + +gint32 +thrift_binary_protocol_write_string (ThriftProtocol *protocol, + const gchar *str, GError **error) +{ + guint32 len; + + g_return_val_if_fail (THRIFT_IS_BINARY_PROTOCOL (protocol), -1); + + len = str != NULL ? strlen (str) : 0; + /* write the string length + 1 which includes the null terminator */ + return thrift_protocol_write_binary (protocol, (const gpointer) str, + len, error); +} + +gint32 +thrift_binary_protocol_write_binary (ThriftProtocol *protocol, + const gpointer buf, + const guint32 len, GError **error) +{ + gint32 ret; + gint32 xfer = 0; + + g_return_val_if_fail (THRIFT_IS_BINARY_PROTOCOL (protocol), -1); + + if ((ret = thrift_protocol_write_i32 (protocol, len, error)) < 0) + { + return -1; + } + xfer += ret; + + if (len > 0) + { + if (thrift_transport_write (protocol->transport, + (const gpointer) buf, len, error) == FALSE) + { + return -1; + } + xfer += len; + } + + return xfer; +} + +gint32 +thrift_binary_protocol_read_message_begin (ThriftProtocol *protocol, + gchar **name, + ThriftMessageType *message_type, + gint32 *seqid, GError **error) +{ + gint32 ret; + gint32 xfer = 0; + gint32 sz; + + g_return_val_if_fail (THRIFT_IS_BINARY_PROTOCOL (protocol), -1); + + if ((ret = thrift_protocol_read_i32 (protocol, &sz, error)) < 0) + { + return -1; + } + xfer += ret; + + if (sz < 0) + { + /* check for version */ + guint32 version = sz & THRIFT_BINARY_PROTOCOL_VERSION_MASK; + if (version != THRIFT_BINARY_PROTOCOL_VERSION_1) + { + g_set_error (error, THRIFT_PROTOCOL_ERROR, + THRIFT_PROTOCOL_ERROR_BAD_VERSION, + "expected version %d, got %d", + THRIFT_BINARY_PROTOCOL_VERSION_1, version); + return -1; + } + + *message_type = (ThriftMessageType) (sz & 0x000000ff); + + if ((ret = thrift_protocol_read_string (protocol, name, error)) < 0) + { + return -1; + } + xfer += ret; + + if ((ret = thrift_protocol_read_i32 (protocol, seqid, error)) < 0) + { + return -1; + } + xfer += ret; + } + return xfer; +} + +gint32 +thrift_binary_protocol_read_message_end (ThriftProtocol *protocol, + GError **error) +{ + THRIFT_UNUSED_VAR (protocol); + THRIFT_UNUSED_VAR (error); + return 0; +} + +gint32 +thrift_binary_protocol_read_struct_begin (ThriftProtocol *protocol, + gchar **name, + GError **error) +{ + THRIFT_UNUSED_VAR (protocol); + THRIFT_UNUSED_VAR (error); + *name = NULL; + return 0; +} + +gint32 +thrift_binary_protocol_read_struct_end (ThriftProtocol *protocol, + GError **error) +{ + THRIFT_UNUSED_VAR (protocol); + THRIFT_UNUSED_VAR (error); + return 0; +} + +gint32 +thrift_binary_protocol_read_field_begin (ThriftProtocol *protocol, + gchar **name, + ThriftType *field_type, + gint16 *field_id, + GError **error) +{ + gint32 ret; + gint32 xfer = 0; + gint8 type; + + g_return_val_if_fail (THRIFT_IS_BINARY_PROTOCOL (protocol), -1); + + THRIFT_UNUSED_VAR (name); + + if ((ret = thrift_protocol_read_byte (protocol, &type, error)) < 0) + { + return -1; + } + xfer += ret; + *field_type = (ThriftType) type; + if (*field_type == T_STOP) + { + *field_id = 0; + return xfer; + } + if ((ret = thrift_protocol_read_i16 (protocol, field_id, error)) < 0) + { + return -1; + } + xfer += ret; + return xfer; +} + +gint32 +thrift_binary_protocol_read_field_end (ThriftProtocol *protocol, + GError **error) +{ + THRIFT_UNUSED_VAR (protocol); + THRIFT_UNUSED_VAR (error); + return 0; +} + +gint32 +thrift_binary_protocol_read_map_begin (ThriftProtocol *protocol, + ThriftType *key_type, + ThriftType *value_type, + guint32 *size, + GError **error) +{ + gint32 ret; + gint32 xfer = 0; + gint8 k, v; + gint32 sizei; + + g_return_val_if_fail (THRIFT_IS_BINARY_PROTOCOL (protocol), -1); + + if ((ret = thrift_protocol_read_byte (protocol, &k, error)) < 0) + { + return -1; + } + xfer += ret; + *key_type = (ThriftType) k; + + if ((ret = thrift_protocol_read_byte (protocol, &v, error)) < 0) + { + return -1; + } + xfer += ret; + *value_type = (ThriftType) v; + + if ((ret = thrift_protocol_read_i32 (protocol, &sizei, error)) <0) + { + return -1; + } + xfer += ret; + + if (sizei < 0) + { + g_set_error (error, THRIFT_PROTOCOL_ERROR, + THRIFT_PROTOCOL_ERROR_NEGATIVE_SIZE, + "got negative size of %d", sizei); + return -1; + } + + *size = (guint32) sizei; + return xfer; +} + +gint32 +thrift_binary_protocol_read_map_end (ThriftProtocol *protocol, + GError **error) +{ + THRIFT_UNUSED_VAR (protocol); + THRIFT_UNUSED_VAR (error); + return 0; +} + +gint32 +thrift_binary_protocol_read_list_begin (ThriftProtocol *protocol, + ThriftType *element_type, + guint32 *size, GError **error) +{ + gint32 ret; + gint32 xfer = 0; + gint8 e; + gint32 sizei; + + g_return_val_if_fail (THRIFT_IS_BINARY_PROTOCOL (protocol), -1); + + if ((ret = thrift_protocol_read_byte (protocol, &e, error)) < 0) + { + return -1; + } + xfer += ret; + *element_type = (ThriftType) e; + + if ((ret = thrift_protocol_read_i32 (protocol, &sizei, error)) < 0) + { + return -1; + } + xfer += ret; + + if (sizei < 0) + { + g_set_error (error, THRIFT_PROTOCOL_ERROR, + THRIFT_PROTOCOL_ERROR_NEGATIVE_SIZE, + "got negative size of %d", sizei); + return -1; + } + + *size = (guint32) sizei; + return xfer; +} + +gint32 +thrift_binary_protocol_read_list_end (ThriftProtocol *protocol, + GError **error) +{ + THRIFT_UNUSED_VAR (protocol); + THRIFT_UNUSED_VAR (error); + return 0; +} + +gint32 +thrift_binary_protocol_read_set_begin (ThriftProtocol *protocol, + ThriftType *element_type, + guint32 *size, GError **error) +{ + g_return_val_if_fail (THRIFT_IS_BINARY_PROTOCOL (protocol), -1); + + return thrift_protocol_read_list_begin (protocol, element_type, size, error); +} + +gint32 +thrift_binary_protocol_read_set_end (ThriftProtocol *protocol, + GError **error) +{ + THRIFT_UNUSED_VAR (protocol); + THRIFT_UNUSED_VAR (error); + return 0; +} + +gint32 +thrift_binary_protocol_read_bool (ThriftProtocol *protocol, gboolean *value, + GError **error) +{ + gint32 ret; + gpointer b[1]; + + g_return_val_if_fail (THRIFT_IS_BINARY_PROTOCOL (protocol), -1); + + if ((ret = + thrift_transport_read_all (protocol->transport, + b, 1, error)) < 0) + { + return -1; + } + *value = *(gint8 *) b != 0; + return ret; +} + +gint32 +thrift_binary_protocol_read_byte (ThriftProtocol *protocol, gint8 *value, + GError **error) +{ + gint32 ret; + gpointer b[1]; + + g_return_val_if_fail (THRIFT_IS_BINARY_PROTOCOL (protocol), -1); + + if ((ret = + thrift_transport_read_all (protocol->transport, + b, 1, error)) < 0) + { + return -1; + } + *value = *(gint8 *) b; + return ret; +} + +gint32 +thrift_binary_protocol_read_i16 (ThriftProtocol *protocol, gint16 *value, + GError **error) +{ + gint32 ret; + union + { + gint8 byte_array[2]; + gint16 int16; + } b; + + g_return_val_if_fail (THRIFT_IS_BINARY_PROTOCOL (protocol), -1); + + if ((ret = + thrift_transport_read_all (protocol->transport, + b.byte_array, 2, error)) < 0) + { + return -1; + } + *value = g_ntohs (b.int16); + return ret; +} + +gint32 +thrift_binary_protocol_read_i32 (ThriftProtocol *protocol, gint32 *value, + GError **error) +{ + gint32 ret; + union + { + gint8 byte_array[4]; + gint32 int32; + } b; + + g_return_val_if_fail (THRIFT_IS_BINARY_PROTOCOL (protocol), -1); + + if ((ret = + thrift_transport_read_all (protocol->transport, + b.byte_array, 4, error)) < 0) + { + return -1; + } + *value = g_ntohl (b.int32); + return ret; +} + +gint32 +thrift_binary_protocol_read_i64 (ThriftProtocol *protocol, gint64 *value, + GError **error) +{ + gint32 ret; + union + { + gint8 byte_array[8]; + gint64 int64; + } b; + + g_return_val_if_fail (THRIFT_IS_BINARY_PROTOCOL (protocol), -1); + + if ((ret = + thrift_transport_read_all (protocol->transport, + b.byte_array, 8, error)) < 0) + { + return -1; + } + *value = GUINT64_FROM_BE (b.int64); + return ret; +} + +gint32 +thrift_binary_protocol_read_double (ThriftProtocol *protocol, + gdouble *value, GError **error) +{ + gint32 ret; + union + { + gint8 byte_array[8]; + guint64 uint64; + } b; + + g_return_val_if_fail (THRIFT_IS_BINARY_PROTOCOL (protocol), -1); + + if ((ret = + thrift_transport_read_all (protocol->transport, + b.byte_array, 8, error)) < 0) + { + return -1; + } + *value = thrift_bitwise_cast_gdouble (GUINT64_FROM_BE (b.uint64)); + return ret; +} + +gint32 +thrift_binary_protocol_read_string (ThriftProtocol *protocol, + gchar **str, GError **error) +{ + guint32 len; + gint32 ret; + gint32 xfer = 0; + gint32 read_len = 0; + + g_return_val_if_fail (THRIFT_IS_BINARY_PROTOCOL (protocol), -1); + + /* read the length into read_len */ + if ((ret = + thrift_protocol_read_i32 (protocol, &read_len, error)) < 0) + { + return -1; + } + xfer += ret; + + if (read_len > 0) + { + /* allocate the memory for the string */ + len = (guint32) read_len + 1; /* space for null terminator */ + *str = g_new0 (gchar, len); + if ((ret = + thrift_transport_read_all (protocol->transport, + *str, read_len, error)) < 0) + { + g_free (*str); + *str = NULL; + len = 0; + return -1; + } + xfer += ret; + } else { + *str = NULL; + } + + return xfer; +} + +gint32 +thrift_binary_protocol_read_binary (ThriftProtocol *protocol, + gpointer *buf, guint32 *len, + GError **error) +{ + gint32 ret; + gint32 xfer = 0; + gint32 read_len = 0; + + g_return_val_if_fail (THRIFT_IS_BINARY_PROTOCOL (protocol), -1); + + /* read the length into read_len */ + if ((ret = + thrift_protocol_read_i32 (protocol, &read_len, error)) < 0) + { + return -1; + } + xfer += ret; + + if (read_len > 0) + { + /* allocate the memory as an array of unsigned char for binary data */ + *len = (guint32) read_len; + *buf = g_new (guchar, *len); + if ((ret = + thrift_transport_read_all (protocol->transport, + *buf, *len, error)) < 0) + { + g_free (*buf); + *buf = NULL; + *len = 0; + return -1; + } + xfer += ret; + } else { + *len = (guint32) read_len; + *buf = NULL; + } + + return xfer; +} + +static void +thrift_binary_protocol_init (ThriftBinaryProtocol *protocol) +{ + THRIFT_UNUSED_VAR (protocol); +} + +/* initialize the class */ +static void +thrift_binary_protocol_class_init (ThriftBinaryProtocolClass *klass) +{ + ThriftProtocolClass *cls = THRIFT_PROTOCOL_CLASS (klass); + + cls->write_message_begin = thrift_binary_protocol_write_message_begin; + cls->write_message_end = thrift_binary_protocol_write_message_end; + cls->write_struct_begin = thrift_binary_protocol_write_struct_begin; + cls->write_struct_end = thrift_binary_protocol_write_struct_end; + cls->write_field_begin = thrift_binary_protocol_write_field_begin; + cls->write_field_end = thrift_binary_protocol_write_field_end; + cls->write_field_stop = thrift_binary_protocol_write_field_stop; + cls->write_map_begin = thrift_binary_protocol_write_map_begin; + cls->write_map_end = thrift_binary_protocol_write_map_end; + cls->write_list_begin = thrift_binary_protocol_write_list_begin; + cls->write_list_end = thrift_binary_protocol_write_list_end; + cls->write_set_begin = thrift_binary_protocol_write_set_begin; + cls->write_set_end = thrift_binary_protocol_write_set_end; + cls->write_bool = thrift_binary_protocol_write_bool; + cls->write_byte = thrift_binary_protocol_write_byte; + cls->write_i16 = thrift_binary_protocol_write_i16; + cls->write_i32 = thrift_binary_protocol_write_i32; + cls->write_i64 = thrift_binary_protocol_write_i64; + cls->write_double = thrift_binary_protocol_write_double; + cls->write_string = thrift_binary_protocol_write_string; + cls->write_binary = thrift_binary_protocol_write_binary; + cls->read_message_begin = thrift_binary_protocol_read_message_begin; + cls->read_message_end = thrift_binary_protocol_read_message_end; + cls->read_struct_begin = thrift_binary_protocol_read_struct_begin; + cls->read_struct_end = thrift_binary_protocol_read_struct_end; + cls->read_field_begin = thrift_binary_protocol_read_field_begin; + cls->read_field_end = thrift_binary_protocol_read_field_end; + cls->read_map_begin = thrift_binary_protocol_read_map_begin; + cls->read_map_end = thrift_binary_protocol_read_map_end; + cls->read_list_begin = thrift_binary_protocol_read_list_begin; + cls->read_list_end = thrift_binary_protocol_read_list_end; + cls->read_set_begin = thrift_binary_protocol_read_set_begin; + cls->read_set_end = thrift_binary_protocol_read_set_end; + cls->read_bool = thrift_binary_protocol_read_bool; + cls->read_byte = thrift_binary_protocol_read_byte; + cls->read_i16 = thrift_binary_protocol_read_i16; + cls->read_i32 = thrift_binary_protocol_read_i32; + cls->read_i64 = thrift_binary_protocol_read_i64; + cls->read_double = thrift_binary_protocol_read_double; + cls->read_string = thrift_binary_protocol_read_string; + cls->read_binary = thrift_binary_protocol_read_binary; +} diff --git a/vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/protocol/thrift_binary_protocol.h b/vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/protocol/thrift_binary_protocol.h new file mode 100644 index 000000000..5230bcced --- /dev/null +++ b/vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/protocol/thrift_binary_protocol.h @@ -0,0 +1,72 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT 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_BINARY_PROTOCOL_H +#define _THRIFT_BINARY_PROTOCOL_H + +#include + +#include +#include + +G_BEGIN_DECLS + +/*! \file thrift_binary_protocol.h + * \brief Binary protocol implementation of a Thrift protocol. Implements the + * ThriftProtocol interface. + */ + +/* type macros */ +#define THRIFT_TYPE_BINARY_PROTOCOL (thrift_binary_protocol_get_type ()) +#define THRIFT_BINARY_PROTOCOL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), THRIFT_TYPE_BINARY_PROTOCOL, ThriftBinaryProtocol)) +#define THRIFT_IS_BINARY_PROTOCOL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), THRIFT_TYPE_BINARY_PROTOCOL)) +#define THRIFT_BINARY_PROTOCOL_CLASS(c) (G_TYPE_CHECK_CLASS_CAST ((c), THRIFT_TYPE_BINARY_PROTOCOL, ThriftBinaryProtocolClass)) +#define THRIFT_IS_BINARY_PROTOCOL_CLASS(c) (G_TYPE_CHECK_CLASS_TYPE ((c), THRIFT_TYPE_BINARY_PROTOCOL)) +#define THRIFT_BINARY_PROTOCOL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), THRIFT_TYPE_BINARY_PROTOCOL, ThriftBinaryProtocolClass)) + +/* version numbers */ +#define THRIFT_BINARY_PROTOCOL_VERSION_1 0x80010000 +#define THRIFT_BINARY_PROTOCOL_VERSION_MASK 0xffff0000 + +typedef struct _ThriftBinaryProtocol ThriftBinaryProtocol; + +/*! + * Thrift Binary Protocol instance. + */ +struct _ThriftBinaryProtocol +{ + ThriftProtocol parent; +}; + +typedef struct _ThriftBinaryProtocolClass ThriftBinaryProtocolClass; + +/*! + * Thrift Binary Protocol class. + */ +struct _ThriftBinaryProtocolClass +{ + ThriftProtocolClass parent; +}; + +/* used by THRIFT_TYPE_BINARY_PROTOCOL */ +GType thrift_binary_protocol_get_type (void); + +G_END_DECLS + +#endif /* _THRIFT_BINARY_PROTOCOL_H */ diff --git a/vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/protocol/thrift_binary_protocol_factory.c b/vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/protocol/thrift_binary_protocol_factory.c new file mode 100644 index 000000000..774e9ad4a --- /dev/null +++ b/vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/protocol/thrift_binary_protocol_factory.c @@ -0,0 +1,50 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT 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 +#include +#include + +G_DEFINE_TYPE(ThriftBinaryProtocolFactory, thrift_binary_protocol_factory, THRIFT_TYPE_PROTOCOL_FACTORY) + +ThriftProtocol * +thrift_binary_protocol_factory_get_protocol (ThriftProtocolFactory *factory, + ThriftTransport *transport) +{ + ThriftBinaryProtocol *tb = g_object_new (THRIFT_TYPE_BINARY_PROTOCOL, + "transport", transport, NULL); + + THRIFT_UNUSED_VAR (factory); + + return THRIFT_PROTOCOL (tb); +} + +static void +thrift_binary_protocol_factory_class_init (ThriftBinaryProtocolFactoryClass *cls) +{ + ThriftProtocolFactoryClass *protocol_factory_class = THRIFT_PROTOCOL_FACTORY_CLASS (cls); + + protocol_factory_class->get_protocol = thrift_binary_protocol_factory_get_protocol; +} + +static void +thrift_binary_protocol_factory_init (ThriftBinaryProtocolFactory *factory) +{ + THRIFT_UNUSED_VAR (factory); +} diff --git a/vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/protocol/thrift_binary_protocol_factory.h b/vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/protocol/thrift_binary_protocol_factory.h new file mode 100644 index 000000000..eddc07390 --- /dev/null +++ b/vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/protocol/thrift_binary_protocol_factory.h @@ -0,0 +1,56 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT 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_BINARY_PROTOCOL_FACTORY_H +#define _THRIFT_BINARY_PROTOCOL_FACTORY_H + +#include + +#include + +G_BEGIN_DECLS + +/* type macros */ +#define THRIFT_TYPE_BINARY_PROTOCOL_FACTORY (thrift_binary_protocol_factory_get_type ()) +#define THRIFT_BINARY_PROTOCOL_FACTORY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), THRIFT_TYPE_BINARY_PROTOCOL_FACTORY, ThriftBinaryProtocolFactory)) +#define THRIFT_IS_BINARY_PROTOCOL_FACTORY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), THRIFT_TYPE_BINARY_PROTOCOL_FACTORY)) +#define THRIFT_BINARY_PROTOCOL_FACTORY_CLASS(c) (G_TYPE_CHECK_CLASS_CAST ((c), THRIFT_TYPE_BINARY_PROTOCOL_FACTORY, ThriftBinaryProtocolFactoryClass)) +#define THRIFT_IS_BINARY_PROTOCOL_FACTORY_CLASS(c) (G_TYPE_CHECK_CLASS_TYPE ((c), THRIFT_TYPE_BINARY_PROTOCOL_FACTORY)) +#define THRIFT_BINARY_PROTOCOL_FACTORY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), THRIFT_TYPE_BINARY_PROTOCOL_FACTORY, ThriftBinaryProtocolFactoryClass)) + +typedef struct _ThriftBinaryProtocolFactory ThriftBinaryProtocolFactory; + +struct _ThriftBinaryProtocolFactory +{ + ThriftProtocolFactory parent; +}; + +typedef struct _ThriftBinaryProtocolFactoryClass ThriftBinaryProtocolFactoryClass; + +struct _ThriftBinaryProtocolFactoryClass +{ + ThriftProtocolFactoryClass parent; +}; + +/* used by THRIFT_TYPE_BINARY_PROTOCOL_FACTORY */ +GType thrift_binary_protocol_factory_get_type (void); + +G_END_DECLS + +#endif /* _THRIFT_BINARY_PROTOCOL_FACTORY_H */ diff --git a/vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/protocol/thrift_compact_protocol.c b/vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/protocol/thrift_compact_protocol.c new file mode 100644 index 000000000..87b6b300f --- /dev/null +++ b/vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/protocol/thrift_compact_protocol.c @@ -0,0 +1,1609 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT 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 +#include + +#include +#include +#include + +#include + +/* + * *_to_zigzag 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 !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 "thrift_compact_protocol only works if signed right shift is arithmetic" +#endif + +/* object properties */ +enum _ThriftCompactProtocolProperties +{ + PROP_0, + PROP_THRIFT_COMPACT_PROTOCOL_STRING_LIMIT, + PROP_THRIFT_COMPACT_PROTOCOL_CONTAINER_LIMIT +}; + +G_DEFINE_TYPE (ThriftCompactProtocol, thrift_compact_protocol, + THRIFT_TYPE_PROTOCOL) + +static const gint8 PROTOCOL_ID = (gint8)0x82u; +static const gint8 VERSION_N = 1; +static const gint8 VERSION_MASK = 0x1f; /* 0001 1111 */ +static const gint8 TYPE_MASK = (gint8)0xe0u; /* 1110 0000 */ +static const gint8 TYPE_BITS = 0x07; /* 0000 0111 */ +static const gint32 TYPE_SHIFT_AMOUNT = 5; + +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 +}; + +static const gint8 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 */ +}; + +static guint64 +thrift_bitwise_cast_guint64 (const gdouble v) +{ + union { + gdouble from; + guint64 to; + } u; + u.from = v; + return u.to; +} + +static gdouble +thrift_bitwise_cast_gdouble (const guint64 v) +{ + union { + guint64 from; + gdouble to; + } u; + u.from = v; + return u.to; +} + +/** + * Convert l into a zigzag long. This allows negative numbers to be + * represented compactly as a varint. + */ +static guint64 +i64_to_zigzag (const gint64 l) +{ + return (l << 1) ^ (l >> 63); +} + +/** + * Convert n into a zigzag int. This allows negative numbers to be + * represented compactly as a varint. + */ +static guint32 +i32_to_zigzag (const gint32 n) +{ + return (n << 1) ^ (n >> 31); +} + +/** + * Convert from zigzag int to int. + */ +static gint32 +zigzag_to_i32 (guint32 n) +{ + return (n >> 1) ^ (guint32) (-(gint32) (n & 1)); +} + +/** + * Convert from zigzag long to long. + */ +static gint64 +zigzag_to_i64 (guint64 n) +{ + return (n >> 1) ^ (guint64) (-(gint64) (n & 1)); +} + +ThriftType thrift_compact_protocol_get_ttype (ThriftCompactProtocol *protocol, + const gint8 type, GError **error) +{ + THRIFT_UNUSED_VAR (protocol); + + switch (type) { + case T_STOP: + return T_STOP; + case CT_BOOLEAN_FALSE: + case CT_BOOLEAN_TRUE: + return T_BOOL; + case CT_BYTE: + return T_BYTE; + case CT_I16: + return T_I16; + case CT_I32: + return T_I32; + case CT_I64: + return T_I64; + case CT_DOUBLE: + return T_DOUBLE; + case CT_BINARY: + return T_STRING; + case CT_LIST: + return T_LIST; + case CT_SET: + return T_SET; + case CT_MAP: + return T_MAP; + case CT_STRUCT: + return T_STRUCT; + default: + g_set_error (error, THRIFT_PROTOCOL_ERROR, + THRIFT_PROTOCOL_ERROR_INVALID_DATA, + "unrecognized type"); + return -1; + } +} + +/** + * Write an i32 as a varint. Results in 1-5 bytes on the wire. + */ +gint32 +thrift_compact_protocol_write_varint32 (ThriftCompactProtocol *protocol, + const guint32 n, + GError **error) +{ + guint8 buf[5]; + gint32 xfer; + guint32 m; + + THRIFT_UNUSED_VAR (error); + + xfer = 0; + m = n; + + while (TRUE) { + if ((m & ~0x7F) == 0) { + buf[xfer++] = (gint8)m; + break; + } else { + buf[xfer++] = (gint8)((m & 0x7F) | 0x80); + m >>= 7; + } + } + + if (thrift_transport_write (THRIFT_PROTOCOL (protocol)->transport, + (const gpointer) buf, xfer, error)) { + return xfer; + } else { + return -1; + } +} + +/** + * Write an i64 as a varint. Results in 1-10 bytes on the wire. + */ +gint32 +thrift_compact_protocol_write_varint64 (ThriftCompactProtocol *protocol, + const guint64 n, + GError **error) +{ + guint8 buf[10]; + gint32 xfer; + guint64 m; + + THRIFT_UNUSED_VAR (error); + + xfer = 0; + m = n; + + while (TRUE) { + if ((m & ~0x7FL) == 0) { + buf[xfer++] = (gint8)m; + break; + } else { + buf[xfer++] = (gint8)((m & 0x7F) | 0x80); + m >>= 7; + } + } + + if (thrift_transport_write (THRIFT_PROTOCOL (protocol)->transport, + (const gpointer) buf, xfer, error)) { + return xfer; + } else { + return -1; + } +} + +/** + * Read an i64 from the wire as a proper varint. The MSB of each byte is set + * if there is another byte to follow. This can read up to 10 bytes. + */ +gint32 +thrift_compact_protocol_read_varint64 (ThriftCompactProtocol *protocol, + gint64 *i64, + GError **error) +{ + ThriftProtocol *tp; + gint32 ret; + gint32 xfer; + guint64 val; + gint shift; + guint8 byte; + + tp = THRIFT_PROTOCOL (protocol); + xfer = 0; + val = 0; + shift = 0; + byte = 0; + + while (TRUE) { + if ((ret = thrift_transport_read_all (tp->transport, + (gpointer) &byte, 1, error)) < 0) { + return -1; + } + ++xfer; + val |= (guint64)(byte & 0x7f) << shift; + shift += 7; + if (!(byte & 0x80)) { + *i64 = (gint64) val; + return xfer; + } + if (G_UNLIKELY (xfer == 10)) { /* 7 * 9 < 64 < 7 * 10 */ + g_set_error (error, THRIFT_PROTOCOL_ERROR, + THRIFT_PROTOCOL_ERROR_INVALID_DATA, + "variable-length int over 10 bytes"); + return -1; + } + } +} + +/** + * Read an i32 from the wire as a varint. The MSB of each byte is set + * if there is another byte to follow. This can read up to 5 bytes. + */ +gint32 +thrift_compact_protocol_read_varint32 (ThriftCompactProtocol *protocol, + gint32 *i32, + GError **error) +{ + gint64 val; + gint32 ret; + gint32 xfer; + + xfer = 0; + + if ((ret = thrift_compact_protocol_read_varint64 (protocol, &val, + error)) < 0) { + return -1; + } + xfer += ret; + + *i32 = (gint32)val; + + return xfer; +} + +gint32 +thrift_compact_protocol_write_field_begin_internal (ThriftCompactProtocol + *protocol, + const gchar *name, + const ThriftType field_type, + const gint16 field_id, + const gint8 type_override, + GError **error) +{ + gint32 ret; + gint32 xfer; + gint8 type_to_write; + + THRIFT_UNUSED_VAR (name); + + xfer = 0; + + /* if there's a type override, use that. */ + type_to_write + = (type_override == -1 ? TTypeToCType[field_type] : type_override); + + /* check if we can use delta encoding for the field id */ + if (field_id > protocol->_last_field_id + && field_id - protocol->_last_field_id <= 15) { + /* write them together */ + if ((ret = thrift_protocol_write_byte (THRIFT_PROTOCOL (protocol), + (gint8) ((field_id + - protocol->_last_field_id) + << 4 | type_to_write), + error)) < 0) { + return -1; + } + xfer += ret; + } else { + /* write them separate */ + if ((ret = thrift_protocol_write_byte (THRIFT_PROTOCOL (protocol), + type_to_write, error)) < 0) { + return -1; + } + xfer += ret; + + if ((ret = thrift_protocol_write_i16 (THRIFT_PROTOCOL (protocol), field_id, + error)) < 0) { + return -1; + } + xfer += ret; + } + + protocol->_last_field_id = field_id; + return xfer; +} + +/** + * Method for writing the start of lists and sets. List and sets on + * the wire differ only by the type indicator. + */ +gint32 +thrift_compact_protocol_write_collection_begin (ThriftCompactProtocol *protocol, + const ThriftType elem_type, + guint32 size, GError **error) +{ + gint32 ret; + gint32 xfer; + + xfer = 0; + + if (size <= 14) { + if ((ret = thrift_protocol_write_byte (THRIFT_PROTOCOL (protocol), + (gint8) (size << 4 + | TTypeToCType[elem_type]), + error)) < 0) { + return -1; + } + xfer += ret; + } else { + if ((ret = thrift_protocol_write_byte (THRIFT_PROTOCOL (protocol), + (gint8) (0xf0 + | TTypeToCType[elem_type]), + error)) < 0) { + return -1; + } + xfer += ret; + + if ((ret = thrift_compact_protocol_write_varint32 (protocol, + (guint32) size, + error)) < 0) { + return -1; + } + xfer += ret; + } + + return xfer; +} + +/* + * public methods + */ + +gint32 +thrift_compact_protocol_write_message_begin (ThriftProtocol *protocol, + const gchar *name, + const ThriftMessageType + message_type, + const gint32 seqid, GError **error) +{ + gint8 version; + gint32 ret; + gint32 xfer; + + ThriftCompactProtocol *cp; + + g_return_val_if_fail (THRIFT_IS_COMPACT_PROTOCOL (protocol), -1); + + cp = THRIFT_COMPACT_PROTOCOL (protocol); + + version = (VERSION_N & VERSION_MASK) + | (((gint32) message_type << TYPE_SHIFT_AMOUNT) & TYPE_MASK); + xfer = 0; + + if ((ret = thrift_protocol_write_byte (protocol, PROTOCOL_ID, error)) < 0) { + return -1; + } + xfer += ret; + + if ((ret = thrift_protocol_write_byte (protocol, version, error)) < 0) { + return -1; + } + xfer += ret; + + if ((ret = thrift_compact_protocol_write_varint32 (cp, + (guint32) seqid, + error)) < 0) { + return -1; + } + xfer += ret; + + if ((ret = thrift_protocol_write_string (protocol, name, error)) < 0) { + return -1; + } + xfer += ret; + + return xfer; +} + +gint32 +thrift_compact_protocol_write_message_end (ThriftProtocol *protocol, + GError **error) +{ + /* satisfy -Wall */ + THRIFT_UNUSED_VAR (protocol); + THRIFT_UNUSED_VAR (error); + return 0; +} + +gint32 +thrift_compact_protocol_write_struct_begin (ThriftProtocol *protocol, + const gchar *name, + GError **error) +{ + ThriftCompactProtocol *cp; + GQueue *q; + + /* satisfy -Wall */ + THRIFT_UNUSED_VAR (name); + THRIFT_UNUSED_VAR (error); + + g_return_val_if_fail (THRIFT_IS_COMPACT_PROTOCOL (protocol), -1); + + cp = THRIFT_COMPACT_PROTOCOL (protocol); + q = &(cp->_last_field); + + g_queue_push_tail (q, GINT_TO_POINTER ((gint) cp->_last_field_id)); + cp->_last_field_id = 0; + return 0; +} + +gint32 +thrift_compact_protocol_write_struct_end (ThriftProtocol *protocol, + GError **error) +{ + ThriftCompactProtocol *cp; + GQueue *q; + + /* satisfy -Wall */ + THRIFT_UNUSED_VAR (error); + + cp = THRIFT_COMPACT_PROTOCOL (protocol); + q = &(cp->_last_field); + + g_return_val_if_fail (THRIFT_IS_COMPACT_PROTOCOL (protocol), -1); + + cp->_last_field_id = (gint16) GPOINTER_TO_INT (g_queue_pop_tail (q)); + return 0; +} + +gint32 +thrift_compact_protocol_write_field_begin (ThriftProtocol *protocol, + const gchar *name, + const ThriftType field_type, + const gint16 field_id, + GError **error) +{ + ThriftCompactProtocol *cp; + + g_return_val_if_fail (THRIFT_IS_COMPACT_PROTOCOL (protocol), -1); + + cp = THRIFT_COMPACT_PROTOCOL (protocol); + + if (field_type == T_BOOL) { + cp->_bool_field_name = name; + cp->_bool_field_type = field_type; + cp->_bool_field_id = field_id; + return 0; + } else { + return thrift_compact_protocol_write_field_begin_internal (cp, name, + field_type, + field_id, -1, + error); + } +} + +gint32 +thrift_compact_protocol_write_field_end (ThriftProtocol *protocol, + GError **error) +{ + /* satisfy -Wall */ + THRIFT_UNUSED_VAR (protocol); + THRIFT_UNUSED_VAR (error); + return 0; +} + +gint32 +thrift_compact_protocol_write_field_stop (ThriftProtocol *protocol, + GError **error) +{ + g_return_val_if_fail (THRIFT_IS_COMPACT_PROTOCOL (protocol), -1); + return thrift_protocol_write_byte (protocol, (gint8) T_STOP, error); +} + +gint32 +thrift_compact_protocol_write_map_begin (ThriftProtocol *protocol, + const ThriftType key_type, + const ThriftType value_type, + const guint32 size, + GError **error) +{ + gint32 ret; + gint32 xfer; + + ThriftCompactProtocol *cp; + + g_return_val_if_fail (THRIFT_IS_COMPACT_PROTOCOL (protocol), -1); + + cp = THRIFT_COMPACT_PROTOCOL (protocol); + + xfer = 0; + + if ((ret = thrift_compact_protocol_write_varint32 (cp, (guint32) size, + error)) < 0) { + return -1; + } + xfer += ret; + + if (size > 0) { + if ((ret = thrift_protocol_write_byte (protocol, + (gint8) (TTypeToCType[key_type] << 4 + | TTypeToCType[value_type]), + error)) < 0) { + return -1; + } + xfer += ret; + } + + return xfer; +} + +gint32 +thrift_compact_protocol_write_map_end (ThriftProtocol *protocol, + GError **error) +{ + THRIFT_UNUSED_VAR (protocol); + THRIFT_UNUSED_VAR (error); + return 0; +} + +gint32 +thrift_compact_protocol_write_list_begin (ThriftProtocol *protocol, + const ThriftType element_type, + const guint32 size, + GError **error) +{ + ThriftCompactProtocol *cp; + + g_return_val_if_fail (THRIFT_IS_COMPACT_PROTOCOL (protocol), -1); + + cp = THRIFT_COMPACT_PROTOCOL (protocol); + + return thrift_compact_protocol_write_collection_begin (cp, element_type, + size, error); +} + +gint32 +thrift_compact_protocol_write_list_end (ThriftProtocol *protocol, + GError **error) +{ + THRIFT_UNUSED_VAR (protocol); + THRIFT_UNUSED_VAR (error); + return 0; +} + +gint32 +thrift_compact_protocol_write_set_begin (ThriftProtocol *protocol, + const ThriftType element_type, + const guint32 size, + GError **error) +{ + ThriftCompactProtocol *cp; + + g_return_val_if_fail (THRIFT_IS_COMPACT_PROTOCOL (protocol), -1); + + cp = THRIFT_COMPACT_PROTOCOL (protocol); + + return thrift_compact_protocol_write_collection_begin (cp, element_type, + size, error); +} + +gint32 +thrift_compact_protocol_write_set_end (ThriftProtocol *protocol, GError **error) +{ + THRIFT_UNUSED_VAR (protocol); + THRIFT_UNUSED_VAR (error); + return 0; +} + +gint32 +thrift_compact_protocol_write_bool (ThriftProtocol *protocol, + const gboolean value, GError **error) +{ + ThriftCompactProtocol *cp; + + gint32 ret; + gint32 xfer; + + g_return_val_if_fail (THRIFT_IS_COMPACT_PROTOCOL (protocol), -1); + + cp = THRIFT_COMPACT_PROTOCOL (protocol); + + xfer = 0; + + if (cp->_bool_field_name != NULL) { + /* we haven't written the field header yet */ + if ((ret = thrift_compact_protocol_write_field_begin_internal (cp, + cp->_bool_field_name, + cp->_bool_field_type, + cp->_bool_field_id, + (gint8) (value + ? CT_BOOLEAN_TRUE : CT_BOOLEAN_FALSE), + error)) < 0) { + return -1; + } + xfer += ret; + + cp->_bool_field_name = NULL; + } else { + /* we're not part of a field, so just write the value */ + if ((ret = thrift_protocol_write_byte (protocol, + (gint8) (value ? CT_BOOLEAN_TRUE + : CT_BOOLEAN_FALSE), + error)) < 0) { + return -1; + } + xfer += ret; + } + return xfer; +} + +gint32 +thrift_compact_protocol_write_byte (ThriftProtocol *protocol, const gint8 value, + GError **error) +{ + g_return_val_if_fail (THRIFT_IS_COMPACT_PROTOCOL (protocol), -1); + + if (thrift_transport_write (protocol->transport, + (const gpointer) &value, 1, error)) { + return 1; + } else { + return -1; + } +} + +gint32 +thrift_compact_protocol_write_i16 (ThriftProtocol *protocol, const gint16 value, + GError **error) +{ + ThriftCompactProtocol *cp; + + g_return_val_if_fail (THRIFT_IS_COMPACT_PROTOCOL (protocol), -1); + + cp = THRIFT_COMPACT_PROTOCOL (protocol); + + return thrift_compact_protocol_write_varint32 (cp, + i32_to_zigzag ((gint32) value), + error); +} + +gint32 +thrift_compact_protocol_write_i32 (ThriftProtocol *protocol, const gint32 value, + GError **error) +{ + ThriftCompactProtocol *cp; + + g_return_val_if_fail (THRIFT_IS_COMPACT_PROTOCOL (protocol), -1); + + cp = THRIFT_COMPACT_PROTOCOL (protocol); + + return thrift_compact_protocol_write_varint32 (cp, + i32_to_zigzag (value), + error); +} + +gint32 +thrift_compact_protocol_write_i64 (ThriftProtocol *protocol, const gint64 value, + GError **error) +{ + ThriftCompactProtocol *cp; + + g_return_val_if_fail (THRIFT_IS_COMPACT_PROTOCOL (protocol), -1); + + cp = THRIFT_COMPACT_PROTOCOL (protocol); + + return thrift_compact_protocol_write_varint64 (cp, + i64_to_zigzag (value), + error); +} + +gint32 +thrift_compact_protocol_write_double (ThriftProtocol *protocol, + const gdouble value, GError **error) +{ + guint64 bits; + + g_assert (sizeof (gdouble) == sizeof (guint64)); + + g_return_val_if_fail (THRIFT_IS_COMPACT_PROTOCOL (protocol), -1); + + bits = GUINT64_TO_LE (thrift_bitwise_cast_guint64 (value)); + if (thrift_transport_write (protocol->transport, + (const gpointer) &bits, 8, error)) { + return 8; + } else { + return -1; + } +} + +gint32 +thrift_compact_protocol_write_string (ThriftProtocol *protocol, + const gchar *str, GError **error) +{ + size_t len; + + g_return_val_if_fail (THRIFT_IS_COMPACT_PROTOCOL (protocol), -1); + + len = str != NULL ? strlen (str) : 0; + if (len > G_MAXINT32) { + g_set_error (error, THRIFT_PROTOCOL_ERROR, + THRIFT_PROTOCOL_ERROR_SIZE_LIMIT, + "string size (guess: %lu) is too large", (unsigned long) len); + return -1; + } + + /* write the string length + 1 which includes the null terminator */ + return thrift_protocol_write_binary (protocol, (const gpointer) str, + (const guint32) len, error); +} + +gint32 +thrift_compact_protocol_write_binary (ThriftProtocol *protocol, + const gpointer buf, + const guint32 len, GError **error) +{ + ThriftCompactProtocol *cp; + + gint32 ret; + gint32 xfer; + + g_return_val_if_fail (THRIFT_IS_COMPACT_PROTOCOL (protocol), -1); + + cp = THRIFT_COMPACT_PROTOCOL (protocol); + + xfer = 0; + + if ((ret = thrift_compact_protocol_write_varint32 (cp, len, error)) < 0) { + return -1; + } + xfer += ret; + + if (len > 0) { + /* checking len + xfer > uint_max, but we don't want to overflow while + * checking for overflows. transforming to len > uint_max - xfer. + */ + if (len > (guint32) (G_MAXINT32 - xfer)) { + g_set_error (error, THRIFT_PROTOCOL_ERROR, + THRIFT_PROTOCOL_ERROR_SIZE_LIMIT, + "size %d + %d is too large", len, xfer); + return -1; + } + + if (thrift_transport_write (protocol->transport, + (const gpointer) buf, len, error) == FALSE) { + return -1; + } + xfer += len; + } + + return xfer; +} + +gint32 +thrift_compact_protocol_read_message_begin (ThriftProtocol *protocol, + gchar **name, + ThriftMessageType *message_type, + gint32 *seqid, GError **error) +{ + ThriftCompactProtocol *cp; + + gint32 ret; + gint32 xfer; + + gint8 protocol_id, version_and_type, version; + + xfer = 0; + + g_return_val_if_fail (THRIFT_IS_COMPACT_PROTOCOL (protocol), -1); + + cp = THRIFT_COMPACT_PROTOCOL (protocol); + + if ((ret = thrift_protocol_read_byte (protocol, &protocol_id, error)) < 0) { + return -1; + } + xfer += ret; + + if (protocol_id != PROTOCOL_ID) { + g_set_error (error, THRIFT_PROTOCOL_ERROR, + THRIFT_PROTOCOL_ERROR_BAD_VERSION, + "bad protocol id"); + return -1; + } + + if ((ret = thrift_protocol_read_byte (protocol, &version_and_type, + error)) < 0) { + return -1; + } + xfer += ret; + + version = (gint8)(version_and_type & VERSION_MASK); + if (version != VERSION_N) { + g_set_error (error, THRIFT_PROTOCOL_ERROR, + THRIFT_PROTOCOL_ERROR_BAD_VERSION, + "bad version and/or type"); + return -1; + } + + *message_type + = (ThriftMessageType)((version_and_type >> TYPE_SHIFT_AMOUNT) & TYPE_BITS); + + if ((ret = thrift_compact_protocol_read_varint32 (cp, seqid, error)) < 0) { + return -1; + } + xfer += ret; + + if ((ret = thrift_protocol_read_string (protocol, name, error)) < 0) { + return -1; + } + xfer += ret; + + return xfer; +} + +gint32 +thrift_compact_protocol_read_message_end (ThriftProtocol *protocol, + GError **error) +{ + THRIFT_UNUSED_VAR (protocol); + THRIFT_UNUSED_VAR (error); + return 0; +} + +gint32 +thrift_compact_protocol_read_struct_begin (ThriftProtocol *protocol, + gchar **name, + GError **error) +{ + ThriftCompactProtocol *cp; + GQueue *q; + + THRIFT_UNUSED_VAR (error); + + g_return_val_if_fail (THRIFT_IS_COMPACT_PROTOCOL (protocol), -1); + + cp = THRIFT_COMPACT_PROTOCOL (protocol); + q = &(cp->_last_field); + + *name = NULL; + + g_queue_push_tail (q, GINT_TO_POINTER ((gint) cp->_last_field_id)); + cp->_last_field_id = 0; + + return 0; +} + +gint32 +thrift_compact_protocol_read_struct_end (ThriftProtocol *protocol, + GError **error) +{ + ThriftCompactProtocol *cp; + GQueue *q; + + THRIFT_UNUSED_VAR (error); + + g_return_val_if_fail (THRIFT_IS_COMPACT_PROTOCOL (protocol), -1); + + cp = THRIFT_COMPACT_PROTOCOL (protocol); + q = &(cp->_last_field); + + cp->_last_field_id = (gint16) GPOINTER_TO_INT (g_queue_pop_tail (q)); + + return 0; +} + +gint32 +thrift_compact_protocol_read_field_begin (ThriftProtocol *protocol, + gchar **name, + ThriftType *field_type, + gint16 *field_id, + GError **error) +{ + ThriftCompactProtocol *cp; + + gint32 ret; + gint32 xfer; + + gint16 modifier; + gint8 byte; + gint8 type; + + g_return_val_if_fail (THRIFT_IS_COMPACT_PROTOCOL (protocol), -1); + + cp = THRIFT_COMPACT_PROTOCOL (protocol); + + THRIFT_UNUSED_VAR (name); + + xfer = 0; + + if ((ret = thrift_protocol_read_byte (protocol, &byte, error)) < 0) { + return -1; + } + xfer += ret; + + type = (byte & 0x0f); + + /* if it's a stop, then we can return immediately, as the struct is over. */ + if (type == T_STOP) { + *field_type = T_STOP; + *field_id = 0; + return xfer; + } + + /* mask off the 4 MSB of the type header. + * it could contain a field id delta. + */ + modifier = (gint16)(((guint8)byte & 0xf0) >> 4); + if (modifier == 0) { + /* not a delta, look ahead for the zigzag varint field id. */ + if ((ret = thrift_protocol_read_i16 (protocol, field_id, error)) < 0) { + return -1; + } + xfer += ret; + } else { + *field_id = (gint16)(cp->_last_field_id + modifier); + } + if ((ret = thrift_compact_protocol_get_ttype (cp, type, error)) < 0) { + return -1; + } + *field_type = ret; + + /* if this happens to be a boolean field, the value is encoded in the type */ + if (type == CT_BOOLEAN_TRUE || type == CT_BOOLEAN_FALSE) { + /* save the boolean value in a special instance variable. */ + cp->_has_bool_value = TRUE; + cp->_bool_value = + (type == CT_BOOLEAN_TRUE ? TRUE : FALSE); + } + + /* push the new field onto the field stack so we can keep the deltas going. */ + cp->_last_field_id = *field_id; + + return xfer; +} + +gint32 +thrift_compact_protocol_read_field_end (ThriftProtocol *protocol, + GError **error) +{ + THRIFT_UNUSED_VAR (protocol); + THRIFT_UNUSED_VAR (error); + return 0; +} + +gint32 +thrift_compact_protocol_read_map_begin (ThriftProtocol *protocol, + ThriftType *key_type, + ThriftType *value_type, + guint32 *size, + GError **error) +{ + gint32 ret; + gint32 xfer; + + gint8 kv_type; + gint32 msize; + + ThriftCompactProtocol *cp; + + g_return_val_if_fail (THRIFT_IS_COMPACT_PROTOCOL (protocol), -1); + + kv_type = 0; + msize = 0; + + cp = THRIFT_COMPACT_PROTOCOL (protocol); + + xfer = 0; + + if ((ret = thrift_compact_protocol_read_varint32 (cp, &msize, error)) <0) { + return -1; + } + xfer += ret; + + /* still read the kv byte if negative size */ + if (msize != 0) { + if ((ret = thrift_protocol_read_byte (protocol, &kv_type, error)) < 0) { + return -1; + } + xfer += ret; + } + + if (cp->container_limit > 0 && msize > cp->container_limit) { + g_set_error (error, THRIFT_PROTOCOL_ERROR, + THRIFT_PROTOCOL_ERROR_SIZE_LIMIT, + "got size over limit (%d > %d)", msize, cp->container_limit); + return -1; + } else if (msize > 0) { + if ((ret = thrift_compact_protocol_get_ttype (cp, + (gint8)((guint8)kv_type + >> 4), + error)) < 0) { + return -1; + } + *key_type = ret; + if ((ret = thrift_compact_protocol_get_ttype (cp, + (gint8)((guint8)kv_type + & 0xf), + error)) < 0) { + return -1; + } + *value_type = ret; + *size = (guint32) msize; + } else if (msize == 0) { + *key_type = 0; + *value_type = 0; + *size = 0; + } else { + g_set_error (error, THRIFT_PROTOCOL_ERROR, + THRIFT_PROTOCOL_ERROR_NEGATIVE_SIZE, + "got negative size of %d", msize); + return -1; + } + + return xfer; +} + +gint32 +thrift_compact_protocol_read_map_end (ThriftProtocol *protocol, + GError **error) +{ + THRIFT_UNUSED_VAR (protocol); + THRIFT_UNUSED_VAR (error); + return 0; +} + +gint32 +thrift_compact_protocol_read_list_begin (ThriftProtocol *protocol, + ThriftType *element_type, + guint32 *size, GError **error) +{ + ThriftCompactProtocol *cp; + + gint32 ret; + gint32 xfer; + + gint8 size_and_type; + gint32 lsize; + + g_return_val_if_fail (THRIFT_IS_COMPACT_PROTOCOL (protocol), -1); + + cp = THRIFT_COMPACT_PROTOCOL (protocol); + + size_and_type = 0; + + xfer = 0; + + if ((ret = thrift_protocol_read_byte (protocol, &size_and_type, error)) < 0) { + return -1; + } + xfer += ret; + + lsize = ((guint8)size_and_type >> 4) & 0x0f; + if (lsize == 15) { + if ((ret = thrift_compact_protocol_read_varint32 (cp, &lsize, error)) < 0) { + return -1; + } + xfer += ret; + } + + if (lsize < 0) { + g_set_error (error, THRIFT_PROTOCOL_ERROR, + THRIFT_PROTOCOL_ERROR_NEGATIVE_SIZE, + "got negative size of %d", lsize); + return -1; + } else if (cp->container_limit > 0 && lsize > cp->container_limit) { + g_set_error (error, THRIFT_PROTOCOL_ERROR, + THRIFT_PROTOCOL_ERROR_SIZE_LIMIT, + "got size over limit (%d > %d)", lsize, cp->container_limit); + return -1; + } + + if ((ret = thrift_compact_protocol_get_ttype (cp, + (gint8)(size_and_type & 0x0f), + error)) < 0) { + return -1; + } + *element_type = ret; + *size = (guint32) lsize; + + return xfer; +} + +gint32 +thrift_compact_protocol_read_list_end (ThriftProtocol *protocol, + GError **error) +{ + THRIFT_UNUSED_VAR (protocol); + THRIFT_UNUSED_VAR (error); + return 0; +} + +gint32 +thrift_compact_protocol_read_set_begin (ThriftProtocol *protocol, + ThriftType *element_type, + guint32 *size, GError **error) +{ + g_return_val_if_fail (THRIFT_IS_COMPACT_PROTOCOL (protocol), -1); + + return thrift_protocol_read_list_begin (protocol, element_type, size, error); +} + +gint32 +thrift_compact_protocol_read_set_end (ThriftProtocol *protocol, + GError **error) +{ + THRIFT_UNUSED_VAR (protocol); + THRIFT_UNUSED_VAR (error); + return 0; +} + +gint32 +thrift_compact_protocol_read_bool (ThriftProtocol *protocol, gboolean *value, + GError **error) +{ + ThriftCompactProtocol *cp; + + gint32 ret; + gint32 xfer; + + gint8 val; + + g_return_val_if_fail (THRIFT_IS_COMPACT_PROTOCOL (protocol), -1); + + cp = THRIFT_COMPACT_PROTOCOL (protocol); + + xfer = 0; + + if (cp->_has_bool_value == TRUE) { + *value = cp->_bool_value; + cp->_has_bool_value = FALSE; + return 0; + } else { + if ((ret = thrift_protocol_read_byte (protocol, &val, error)) < 0) { + return -1; + } + xfer += ret; + + *value = (val == CT_BOOLEAN_TRUE); + return xfer; + } +} + +gint32 +thrift_compact_protocol_read_byte (ThriftProtocol *protocol, gint8 *value, + GError **error) +{ + gint32 ret; + gpointer b[1]; + + g_return_val_if_fail (THRIFT_IS_COMPACT_PROTOCOL (protocol), -1); + + if ((ret = + thrift_transport_read_all (protocol->transport, + b, 1, error)) < 0) { + return -1; + } + *value = *(gint8 *) b; + return ret; +} + +gint32 +thrift_compact_protocol_read_i16 (ThriftProtocol *protocol, gint16 *value, + GError **error) +{ + ThriftCompactProtocol *cp; + + gint32 ret; + gint32 val; + gint32 xfer; + + g_return_val_if_fail (THRIFT_IS_COMPACT_PROTOCOL (protocol), -1); + + cp = THRIFT_COMPACT_PROTOCOL (protocol); + + xfer = 0; + + if ((ret = thrift_compact_protocol_read_varint32 (cp, &val, error)) < 0) { + return -1; + } + xfer += ret; + + *value = (gint16) zigzag_to_i32 ((guint32) val); + + return xfer; +} + +gint32 +thrift_compact_protocol_read_i32 (ThriftProtocol *protocol, gint32 *value, + GError **error) +{ + ThriftCompactProtocol *cp; + + gint32 ret; + gint32 val; + gint32 xfer; + + g_return_val_if_fail (THRIFT_IS_COMPACT_PROTOCOL (protocol), -1); + + cp = THRIFT_COMPACT_PROTOCOL (protocol); + + xfer = 0; + + if ((ret = thrift_compact_protocol_read_varint32 (cp, &val, error)) < 0) { + return -1; + } + xfer += ret; + + *value = zigzag_to_i32 ((guint32) val); + + return xfer; +} + +gint32 +thrift_compact_protocol_read_i64 (ThriftProtocol *protocol, gint64 *value, + GError **error) +{ + ThriftCompactProtocol *cp; + + gint32 ret; + gint64 val; + gint32 xfer; + + g_return_val_if_fail (THRIFT_IS_COMPACT_PROTOCOL (protocol), -1); + + cp = THRIFT_COMPACT_PROTOCOL (protocol); + + xfer = 0; + + if ((ret = thrift_compact_protocol_read_varint64 (cp, &val, error)) < 0) { + return -1; + } + xfer += ret; + + *value = zigzag_to_i64 ((guint64) val); + + return xfer; +} + +gint32 +thrift_compact_protocol_read_double (ThriftProtocol *protocol, + gdouble *value, GError **error) +{ + gint32 ret; + union { + guint64 bits; + guint8 b[8]; + } u; + + g_assert (sizeof (gdouble) == sizeof (guint64)); + + g_return_val_if_fail (THRIFT_IS_COMPACT_PROTOCOL (protocol), -1); + + if ((ret = + thrift_transport_read_all (protocol->transport, + u.b, 8, error)) < 0) { + return -1; + } + u.bits = GUINT64_FROM_LE (u.bits); + *value = thrift_bitwise_cast_gdouble (u.bits); + return ret; +} + +gint32 +thrift_compact_protocol_read_string (ThriftProtocol *protocol, + gchar **str, GError **error) +{ + ThriftCompactProtocol *cp; + + gint32 ret; + gint32 xfer; + + gint32 read_len; + + g_return_val_if_fail (THRIFT_IS_COMPACT_PROTOCOL (protocol), -1); + + cp = THRIFT_COMPACT_PROTOCOL (protocol); + + xfer = 0; + read_len = 0; + + /* read the length into read_len */ + if ((ret = + thrift_compact_protocol_read_varint32 (cp, &read_len, error)) < 0) { + return -1; + } + xfer += ret; + + if (cp->string_limit > 0 && read_len > cp->string_limit) { + g_set_error (error, THRIFT_PROTOCOL_ERROR, + THRIFT_PROTOCOL_ERROR_SIZE_LIMIT, + "got size over limit (%d > %d)", read_len, cp->string_limit); + *str = NULL; + return -1; + } + + if (read_len > 0) { + /* allocate the memory as an array of unsigned char for binary data */ + *str = g_new0 (gchar, read_len + 1); + if ((ret = + thrift_transport_read_all (protocol->transport, + *str, read_len, error)) < 0) { + g_free (*str); + *str = NULL; + return -1; + } + xfer += ret; + + } else if (read_len == 0) { + *str = NULL; + + } else { + g_set_error (error, THRIFT_PROTOCOL_ERROR, + THRIFT_PROTOCOL_ERROR_NEGATIVE_SIZE, + "got negative size of %d", read_len); + *str = NULL; + return -1; + } + + return xfer; +} + +gint32 +thrift_compact_protocol_read_binary (ThriftProtocol *protocol, + gpointer *buf, guint32 *len, + GError **error) +{ + ThriftCompactProtocol *cp; + + gint32 ret; + gint32 xfer; + + gint32 read_len; + + g_return_val_if_fail (THRIFT_IS_COMPACT_PROTOCOL (protocol), -1); + + cp = THRIFT_COMPACT_PROTOCOL (protocol); + + xfer = 0; + read_len = 0; + + /* read the length into read_len */ + if ((ret = + thrift_compact_protocol_read_varint32 (cp, &read_len, error)) < 0) { + return -1; + } + xfer += ret; + + if (cp->string_limit > 0 && read_len > cp->string_limit) { + g_set_error (error, THRIFT_PROTOCOL_ERROR, + THRIFT_PROTOCOL_ERROR_SIZE_LIMIT, + "got size over limit (%d > %d)", read_len, cp->string_limit); + *buf = NULL; + *len = 0; + return -1; + } + + if (read_len > 0) { + /* allocate the memory as an array of unsigned char for binary data */ + *len = (guint32) read_len; + *buf = g_new (guchar, *len); + if ((ret = + thrift_transport_read_all (protocol->transport, + *buf, *len, error)) < 0) { + g_free (*buf); + *buf = NULL; + *len = 0; + return -1; + } + xfer += ret; + + } else if (read_len == 0) { + *len = (guint32) read_len; + *buf = NULL; + + } else { + g_set_error (error, THRIFT_PROTOCOL_ERROR, + THRIFT_PROTOCOL_ERROR_NEGATIVE_SIZE, + "got negative size of %d", read_len); + *buf = NULL; + *len = 0; + return -1; + } + + return xfer; +} + +/* property accessor */ +void +thrift_compact_protocol_get_property (GObject *object, guint property_id, + GValue *value, GParamSpec *pspec) +{ + ThriftCompactProtocol *tc; + + THRIFT_UNUSED_VAR (pspec); + + tc = THRIFT_COMPACT_PROTOCOL (object); + + switch (property_id) { + case PROP_THRIFT_COMPACT_PROTOCOL_STRING_LIMIT: + g_value_set_int (value, tc->string_limit); + break; + case PROP_THRIFT_COMPACT_PROTOCOL_CONTAINER_LIMIT: + g_value_set_int (value, tc->container_limit); + break; + } +} + +/* property mutator */ +void +thrift_compact_protocol_set_property (GObject *object, guint property_id, + const GValue *value, GParamSpec *pspec) +{ + ThriftCompactProtocol *tc; + + THRIFT_UNUSED_VAR (pspec); + + tc = THRIFT_COMPACT_PROTOCOL (object); + + switch (property_id) { + case PROP_THRIFT_COMPACT_PROTOCOL_STRING_LIMIT: + tc->string_limit = g_value_get_int (value); + break; + case PROP_THRIFT_COMPACT_PROTOCOL_CONTAINER_LIMIT: + tc->container_limit = g_value_get_int (value); + break; + } +} + +/* initialize the class */ +static void +thrift_compact_protocol_class_init (ThriftCompactProtocolClass *klass) +{ + ThriftProtocolClass *cls; + GObjectClass *gobject_class; + GParamSpec *param_spec; + + cls = THRIFT_PROTOCOL_CLASS (klass); + gobject_class = G_OBJECT_CLASS (klass); + param_spec = NULL; + + /* setup accessors and mutators */ + gobject_class->get_property = thrift_compact_protocol_get_property; + gobject_class->set_property = thrift_compact_protocol_set_property; + + param_spec = g_param_spec_int ("string_limit", + "Max allowed string size", + "Set the max string limit", + 0, /* min */ + G_MAXINT32, /* max */ + 0, /* default value */ + G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE); + g_object_class_install_property (gobject_class, + PROP_THRIFT_COMPACT_PROTOCOL_STRING_LIMIT, + param_spec); + + param_spec = g_param_spec_int ("container_limit", + "Max allowed container size", + "Set the max container limit", + 0, /* min */ + G_MAXINT32, /* max */ + 0, /* default value */ + G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE); + g_object_class_install_property (gobject_class, + PROP_THRIFT_COMPACT_PROTOCOL_CONTAINER_LIMIT, + param_spec); + + cls->write_message_begin = thrift_compact_protocol_write_message_begin; + cls->write_message_end = thrift_compact_protocol_write_message_end; + cls->write_struct_begin = thrift_compact_protocol_write_struct_begin; + cls->write_struct_end = thrift_compact_protocol_write_struct_end; + cls->write_field_begin = thrift_compact_protocol_write_field_begin; + cls->write_field_end = thrift_compact_protocol_write_field_end; + cls->write_field_stop = thrift_compact_protocol_write_field_stop; + cls->write_map_begin = thrift_compact_protocol_write_map_begin; + cls->write_map_end = thrift_compact_protocol_write_map_end; + cls->write_list_begin = thrift_compact_protocol_write_list_begin; + cls->write_list_end = thrift_compact_protocol_write_list_end; + cls->write_set_begin = thrift_compact_protocol_write_set_begin; + cls->write_set_end = thrift_compact_protocol_write_set_end; + cls->write_bool = thrift_compact_protocol_write_bool; + cls->write_byte = thrift_compact_protocol_write_byte; + cls->write_i16 = thrift_compact_protocol_write_i16; + cls->write_i32 = thrift_compact_protocol_write_i32; + cls->write_i64 = thrift_compact_protocol_write_i64; + cls->write_double = thrift_compact_protocol_write_double; + cls->write_string = thrift_compact_protocol_write_string; + cls->write_binary = thrift_compact_protocol_write_binary; + cls->read_message_begin = thrift_compact_protocol_read_message_begin; + cls->read_message_end = thrift_compact_protocol_read_message_end; + cls->read_struct_begin = thrift_compact_protocol_read_struct_begin; + cls->read_struct_end = thrift_compact_protocol_read_struct_end; + cls->read_field_begin = thrift_compact_protocol_read_field_begin; + cls->read_field_end = thrift_compact_protocol_read_field_end; + cls->read_map_begin = thrift_compact_protocol_read_map_begin; + cls->read_map_end = thrift_compact_protocol_read_map_end; + cls->read_list_begin = thrift_compact_protocol_read_list_begin; + cls->read_list_end = thrift_compact_protocol_read_list_end; + cls->read_set_begin = thrift_compact_protocol_read_set_begin; + cls->read_set_end = thrift_compact_protocol_read_set_end; + cls->read_bool = thrift_compact_protocol_read_bool; + cls->read_byte = thrift_compact_protocol_read_byte; + cls->read_i16 = thrift_compact_protocol_read_i16; + cls->read_i32 = thrift_compact_protocol_read_i32; + cls->read_i64 = thrift_compact_protocol_read_i64; + cls->read_double = thrift_compact_protocol_read_double; + cls->read_string = thrift_compact_protocol_read_string; + cls->read_binary = thrift_compact_protocol_read_binary; +} + +static void +thrift_compact_protocol_init (ThriftCompactProtocol *self) +{ + g_queue_init (&(self->_last_field)); +} diff --git a/vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/protocol/thrift_compact_protocol.h b/vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/protocol/thrift_compact_protocol.h new file mode 100644 index 000000000..effcaadf0 --- /dev/null +++ b/vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/protocol/thrift_compact_protocol.h @@ -0,0 +1,107 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef _THRIFT_COMPACT_PROTOCOL_H +#define _THRIFT_COMPACT_PROTOCOL_H + +#include +#include + +#include +#include + +G_BEGIN_DECLS + +/*! \file thrift_compact_protocol.h + * \brief Compact protocol implementation of a Thrift protocol. Implements the + * ThriftProtocol interface. + */ + +/* type macros */ +#define THRIFT_TYPE_COMPACT_PROTOCOL (thrift_compact_protocol_get_type ()) +#define THRIFT_COMPACT_PROTOCOL(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), THRIFT_TYPE_COMPACT_PROTOCOL, \ + ThriftCompactProtocol)) +#define THRIFT_IS_COMPACT_PROTOCOL(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), THRIFT_TYPE_COMPACT_PROTOCOL)) +#define THRIFT_COMPACT_PROTOCOL_CLASS(c) \ + (G_TYPE_CHECK_CLASS_CAST ((c), THRIFT_TYPE_COMPACT_PROTOCOL, \ + ThriftCompactProtocolClass)) +#define THRIFT_IS_COMPACT_PROTOCOL_CLASS(c) \ + (G_TYPE_CHECK_CLASS_TYPE ((c), THRIFT_TYPE_COMPACT_PROTOCOL)) +#define THRIFT_COMPACT_PROTOCOL_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), THRIFT_TYPE_COMPACT_PROTOCOL, \ + ThriftCompactProtocolClass)) + + +typedef struct _ThriftCompactProtocol ThriftCompactProtocol; + +/*! + * Thrift Compact Protocol instance. + */ +struct _ThriftCompactProtocol +{ + ThriftProtocol parent; + + /* protected */ + gint32 string_limit; + gint32 container_limit; + + /* private */ + + /** + * (Writing) If we encounter a boolean field begin, save the TField here + * so it can have the value incorporated. + */ + const gchar* _bool_field_name; + ThriftType _bool_field_type; + gint16 _bool_field_id; + + /** + * (Reading) If we read a field header, and it's a boolean field, save + * the boolean value here so that read_bool can use it. + */ + gboolean _has_bool_value; + gboolean _bool_value; + + /** + * Used to keep track of the last field for the current and previous structs, + * so we can do the delta stuff. + */ + + GQueue _last_field; + gint16 _last_field_id; +}; + +typedef struct _ThriftCompactProtocolClass ThriftCompactProtocolClass; + +/*! + * Thrift Compact Protocol class. + */ +struct _ThriftCompactProtocolClass +{ + ThriftProtocolClass parent; +}; + +/* used by THRIFT_TYPE_COMPACT_PROTOCOL */ +GType thrift_compact_protocol_get_type (void); + +G_END_DECLS + +#endif /* _THRIFT_COMPACT_PROTOCOL_H */ diff --git a/vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/protocol/thrift_compact_protocol_factory.c b/vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/protocol/thrift_compact_protocol_factory.c new file mode 100644 index 000000000..e725e1fd0 --- /dev/null +++ b/vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/protocol/thrift_compact_protocol_factory.c @@ -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. + */ + +#include +#include +#include + +/* object properties */ +enum _ThriftCompactProtocolFactoryProperties +{ + PROP_0, + PROP_THRIFT_COMPACT_PROTOCOL_FACTORY_STRING_LIMIT, + PROP_THRIFT_COMPACT_PROTOCOL_FACTORY_CONTAINER_LIMIT +}; + +G_DEFINE_TYPE (ThriftCompactProtocolFactory, thrift_compact_protocol_factory, + THRIFT_TYPE_PROTOCOL_FACTORY) + +ThriftProtocol * +thrift_compact_protocol_factory_get_protocol (ThriftProtocolFactory *factory, + ThriftTransport *transport) +{ + ThriftCompactProtocolFactory *tcf; + ThriftCompactProtocol *tc; + + tcf = THRIFT_COMPACT_PROTOCOL_FACTORY (factory); + + tc = g_object_new (THRIFT_TYPE_COMPACT_PROTOCOL, + "transport", transport, + "string_limit", tcf->string_limit, + "container_limit", tcf->container_limit, + NULL); + + return THRIFT_PROTOCOL (tc); +} + +/* property accessor */ +void +thrift_compact_protocol_factory_get_property (GObject *object, guint property_id, + GValue *value, GParamSpec *pspec) +{ + ThriftCompactProtocolFactory *tcf; + + THRIFT_UNUSED_VAR (pspec); + + tcf = THRIFT_COMPACT_PROTOCOL_FACTORY (object); + + switch (property_id) { + case PROP_THRIFT_COMPACT_PROTOCOL_FACTORY_STRING_LIMIT: + g_value_set_int (value, tcf->string_limit); + break; + case PROP_THRIFT_COMPACT_PROTOCOL_FACTORY_CONTAINER_LIMIT: + g_value_set_int (value, tcf->container_limit); + break; + } +} + +/* property mutator */ +void +thrift_compact_protocol_factory_set_property (GObject *object, guint property_id, + const GValue *value, GParamSpec + *pspec) +{ + ThriftCompactProtocolFactory *tcf; + + THRIFT_UNUSED_VAR (pspec); + + tcf = THRIFT_COMPACT_PROTOCOL_FACTORY (object); + + switch (property_id) { + case PROP_THRIFT_COMPACT_PROTOCOL_FACTORY_STRING_LIMIT: + tcf->string_limit = g_value_get_int (value); + break; + case PROP_THRIFT_COMPACT_PROTOCOL_FACTORY_CONTAINER_LIMIT: + tcf->container_limit = g_value_get_int (value); + break; + } +} + +static void +thrift_compact_protocol_factory_class_init (ThriftCompactProtocolFactoryClass + *klass) +{ + ThriftProtocolFactoryClass *cls; + GObjectClass *gobject_class; + GParamSpec *param_spec; + + cls = THRIFT_PROTOCOL_FACTORY_CLASS (klass); + gobject_class = G_OBJECT_CLASS (klass); + param_spec = NULL; + + /* setup accessors and mutators */ + gobject_class->get_property = thrift_compact_protocol_factory_get_property; + gobject_class->set_property = thrift_compact_protocol_factory_set_property; + + param_spec = g_param_spec_int ("string_limit", + "Max allowed string size", + "Set the max string limit", + 0, /* min */ + G_MAXINT32, /* max */ + 0, /* default value */ + G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE); + g_object_class_install_property (gobject_class, + PROP_THRIFT_COMPACT_PROTOCOL_FACTORY_STRING_LIMIT, + param_spec); + + param_spec = g_param_spec_int ("container_limit", + "Max allowed container size", + "Set the max container limit", + 0, /* min */ + G_MAXINT32, /* max */ + 0, /* default value */ + G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE); + g_object_class_install_property (gobject_class, + PROP_THRIFT_COMPACT_PROTOCOL_FACTORY_CONTAINER_LIMIT, param_spec); + + cls->get_protocol = thrift_compact_protocol_factory_get_protocol; +} + +static void +thrift_compact_protocol_factory_init (ThriftCompactProtocolFactory *factory) +{ + THRIFT_UNUSED_VAR (factory); +} diff --git a/vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/protocol/thrift_compact_protocol_factory.h b/vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/protocol/thrift_compact_protocol_factory.h new file mode 100644 index 000000000..3bf953b4c --- /dev/null +++ b/vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/protocol/thrift_compact_protocol_factory.h @@ -0,0 +1,70 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT 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_COMPACT_PROTOCOL_FACTORY_H +#define _THRIFT_COMPACT_PROTOCOL_FACTORY_H + +#include + +#include + +G_BEGIN_DECLS + +/* type macros */ +#define THRIFT_TYPE_COMPACT_PROTOCOL_FACTORY \ + (thrift_compact_protocol_factory_get_type ()) +#define THRIFT_COMPACT_PROTOCOL_FACTORY(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), THRIFT_TYPE_COMPACT_PROTOCOL_FACTORY, \ + ThriftCompactProtocolFactory)) +#define THRIFT_IS_COMPACT_PROTOCOL_FACTORY(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), THRIFT_TYPE_COMPACT_PROTOCOL_FACTORY)) +#define THRIFT_COMPACT_PROTOCOL_FACTORY_CLASS(c) \ + (G_TYPE_CHECK_CLASS_CAST ((c), THRIFT_TYPE_COMPACT_PROTOCOL_FACTORY, \ + ThriftCompactProtocolFactoryClass)) +#define THRIFT_IS_COMPACT_PROTOCOL_FACTORY_CLASS(c) \ + (G_TYPE_CHECK_CLASS_TYPE ((c), THRIFT_TYPE_COMPACT_PROTOCOL_FACTORY)) +#define THRIFT_COMPACT_PROTOCOL_FACTORY_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), THRIFT_TYPE_COMPACT_PROTOCOL_FACTORY, \ + ThriftCompactProtocolFactoryClass)) + +typedef struct _ThriftCompactProtocolFactory ThriftCompactProtocolFactory; + +struct _ThriftCompactProtocolFactory +{ + ThriftProtocolFactory parent; + + /* protected */ + gint32 string_limit; + gint32 container_limit; +}; + +typedef struct _ThriftCompactProtocolFactoryClass + ThriftCompactProtocolFactoryClass; + +struct _ThriftCompactProtocolFactoryClass +{ + ThriftProtocolFactoryClass parent; +}; + +/* used by THRIFT_TYPE_COMPACT_PROTOCOL_FACTORY */ +GType thrift_compact_protocol_factory_get_type (void); + +G_END_DECLS + +#endif /* _THRIFT_COMPACT_PROTOCOL_FACTORY_H */ diff --git a/vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/protocol/thrift_protocol.c b/vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/protocol/thrift_protocol.c new file mode 100644 index 000000000..8a560a9f2 --- /dev/null +++ b/vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/protocol/thrift_protocol.c @@ -0,0 +1,605 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT 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 +#include +#include + +/* define the GError domain string */ +#define THRIFT_PROTOCOL_ERROR_DOMAIN "thrift-protocol-error-quark" + +/* object properties */ +enum _ThriftProtocolProperties +{ + PROP_0, + PROP_THRIFT_PROTOCOL_TRANSPORT +}; + +G_DEFINE_ABSTRACT_TYPE(ThriftProtocol, thrift_protocol, G_TYPE_OBJECT) + +void +thrift_protocol_get_property (GObject *object, guint property_id, + GValue *value, GParamSpec *pspec) +{ + ThriftProtocol *protocol = THRIFT_PROTOCOL (object); + + THRIFT_UNUSED_VAR (pspec); + + switch (property_id) + { + case PROP_THRIFT_PROTOCOL_TRANSPORT: + g_value_set_object (value, protocol->transport); + break; + } +} + +void +thrift_protocol_set_property (GObject *object, guint property_id, + const GValue *value, GParamSpec *pspec) +{ + + ThriftProtocol *protocol = THRIFT_PROTOCOL (object); + + THRIFT_UNUSED_VAR (pspec); + + switch (property_id) + { + case PROP_THRIFT_PROTOCOL_TRANSPORT: + protocol->transport = g_value_get_object (value); + break; + } +} + + +gint32 +thrift_protocol_write_message_begin (ThriftProtocol *protocol, + const gchar *name, + const ThriftMessageType message_type, + const gint32 seqid, GError **error) +{ + return THRIFT_PROTOCOL_GET_CLASS (protocol)->write_message_begin + (protocol, name, + message_type, seqid, + error); +} + +gint32 +thrift_protocol_write_message_end (ThriftProtocol *protocol, GError **error) +{ + return THRIFT_PROTOCOL_GET_CLASS (protocol)->write_message_end (protocol, + error); +} + +gint32 +thrift_protocol_write_struct_begin (ThriftProtocol *protocol, const gchar *name, + GError **error) +{ + return THRIFT_PROTOCOL_GET_CLASS (protocol)->write_struct_begin (protocol, + name, error); +} + +gint32 +thrift_protocol_write_struct_end (ThriftProtocol *protocol, GError **error) +{ + return THRIFT_PROTOCOL_GET_CLASS (protocol)->write_struct_end (protocol, + error); +} + +gint32 +thrift_protocol_write_field_begin (ThriftProtocol *protocol, + const gchar *name, + const ThriftType field_type, + const gint16 field_id, + GError **error) +{ + return THRIFT_PROTOCOL_GET_CLASS (protocol)->write_field_begin (protocol, + name, field_type, + field_id, error); +} + +gint32 +thrift_protocol_write_field_end (ThriftProtocol *protocol, GError **error) +{ + return THRIFT_PROTOCOL_GET_CLASS (protocol)->write_field_end (protocol, + error); +} + +gint32 +thrift_protocol_write_field_stop (ThriftProtocol *protocol, GError **error) +{ + return THRIFT_PROTOCOL_GET_CLASS (protocol)->write_field_stop (protocol, + error); +} + +gint32 +thrift_protocol_write_map_begin (ThriftProtocol *protocol, + const ThriftType key_type, + const ThriftType value_type, + const guint32 size, GError **error) +{ + return THRIFT_PROTOCOL_GET_CLASS (protocol)->write_map_begin (protocol, + key_type, value_type, + size, error); +} + +gint32 +thrift_protocol_write_map_end (ThriftProtocol *protocol, GError **error) +{ + return THRIFT_PROTOCOL_GET_CLASS (protocol)->write_map_end (protocol, + error); +} + +gint32 +thrift_protocol_write_list_begin (ThriftProtocol *protocol, + const ThriftType element_type, + const guint32 size, GError **error) +{ + return THRIFT_PROTOCOL_GET_CLASS (protocol)->write_list_begin (protocol, + element_type, size, + error); +} + +gint32 +thrift_protocol_write_list_end (ThriftProtocol *protocol, GError **error) +{ + return THRIFT_PROTOCOL_GET_CLASS (protocol)->write_list_end (protocol, + error); +} + +gint32 +thrift_protocol_write_set_begin (ThriftProtocol *protocol, + const ThriftType element_type, + const guint32 size, GError **error) +{ + return THRIFT_PROTOCOL_GET_CLASS (protocol)->write_set_begin (protocol, + element_type, size, + error); +} + +gint32 +thrift_protocol_write_set_end (ThriftProtocol *protocol, GError **error) +{ + return THRIFT_PROTOCOL_GET_CLASS (protocol)->write_set_end (protocol, + error); +} + +gint32 +thrift_protocol_write_bool (ThriftProtocol *protocol, + const gboolean value, GError **error) +{ + return THRIFT_PROTOCOL_GET_CLASS (protocol)->write_bool (protocol, value, + error); +} + +gint32 +thrift_protocol_write_byte (ThriftProtocol *protocol, const gint8 value, + GError **error) +{ + return THRIFT_PROTOCOL_GET_CLASS (protocol)->write_byte (protocol, value, + error); +} + +gint32 +thrift_protocol_write_i16 (ThriftProtocol *protocol, const gint16 value, + GError **error) +{ + return THRIFT_PROTOCOL_GET_CLASS (protocol)->write_i16 (protocol, value, + error); +} + +gint32 +thrift_protocol_write_i32 (ThriftProtocol *protocol, const gint32 value, + GError **error) +{ + return THRIFT_PROTOCOL_GET_CLASS (protocol)->write_i32 (protocol, value, + error); +} + +gint32 +thrift_protocol_write_i64 (ThriftProtocol *protocol, const gint64 value, + GError **error) +{ + return THRIFT_PROTOCOL_GET_CLASS (protocol)->write_i64 (protocol, value, + error); +} + +gint32 +thrift_protocol_write_double (ThriftProtocol *protocol, + const gdouble value, GError **error) +{ + return THRIFT_PROTOCOL_GET_CLASS (protocol)->write_double (protocol, + value, error); +} + +gint32 +thrift_protocol_write_string (ThriftProtocol *protocol, + const gchar *str, GError **error) +{ + return THRIFT_PROTOCOL_GET_CLASS (protocol)->write_string (protocol, str, + error); +} + +gint32 +thrift_protocol_write_binary (ThriftProtocol *protocol, const gpointer buf, + const guint32 len, GError **error) +{ + return THRIFT_PROTOCOL_GET_CLASS (protocol)->write_binary (protocol, buf, + len, error); +} + +gint32 +thrift_protocol_read_message_begin (ThriftProtocol *protocol, + gchar **name, + ThriftMessageType *message_type, + gint32 *seqid, GError **error) +{ + return THRIFT_PROTOCOL_GET_CLASS (protocol)->read_message_begin (protocol, + name, message_type, + seqid, error); +} + +gint32 +thrift_protocol_read_message_end (ThriftProtocol *protocol, + GError **error) +{ + return THRIFT_PROTOCOL_GET_CLASS (protocol)->read_message_end (protocol, + error); +} + +gint32 +thrift_protocol_read_struct_begin (ThriftProtocol *protocol, + gchar **name, + GError **error) +{ + return THRIFT_PROTOCOL_GET_CLASS (protocol)->read_struct_begin (protocol, + name, + error); +} + +gint32 +thrift_protocol_read_struct_end (ThriftProtocol *protocol, GError **error) +{ + return THRIFT_PROTOCOL_GET_CLASS (protocol)->read_struct_end (protocol, + error); +} + +gint32 +thrift_protocol_read_field_begin (ThriftProtocol *protocol, + gchar **name, + ThriftType *field_type, + gint16 *field_id, + GError **error) +{ + return THRIFT_PROTOCOL_GET_CLASS (protocol)->read_field_begin (protocol, + name, + field_type, + field_id, + error); +} + +gint32 +thrift_protocol_read_field_end (ThriftProtocol *protocol, + GError **error) +{ + return THRIFT_PROTOCOL_GET_CLASS (protocol)->read_field_end (protocol, + error); +} + +gint32 +thrift_protocol_read_map_begin (ThriftProtocol *protocol, + ThriftType *key_type, + ThriftType *value_type, guint32 *size, + GError **error) +{ + return THRIFT_PROTOCOL_GET_CLASS (protocol)->read_map_begin (protocol, + key_type, + value_type, + size, + error); +} + +gint32 +thrift_protocol_read_map_end (ThriftProtocol *protocol, GError **error) +{ + return THRIFT_PROTOCOL_GET_CLASS (protocol)->read_map_end (protocol, + error); +} + +gint32 +thrift_protocol_read_list_begin (ThriftProtocol *protocol, + ThriftType *element_type, + guint32 *size, GError **error) +{ + return THRIFT_PROTOCOL_GET_CLASS (protocol)->read_list_begin (protocol, + element_type, + size, error); +} + +gint32 +thrift_protocol_read_list_end (ThriftProtocol *protocol, GError **error) +{ + return THRIFT_PROTOCOL_GET_CLASS (protocol)->read_list_end (protocol, + error); +} + +gint32 +thrift_protocol_read_set_begin (ThriftProtocol *protocol, + ThriftType *element_type, + guint32 *size, GError **error) +{ + return THRIFT_PROTOCOL_GET_CLASS (protocol)->read_set_begin (protocol, + element_type, + size, error); +} + +gint32 +thrift_protocol_read_set_end (ThriftProtocol *protocol, GError **error) +{ + return THRIFT_PROTOCOL_GET_CLASS (protocol)->read_set_end (protocol, + error); +} + +gint32 +thrift_protocol_read_bool (ThriftProtocol *protocol, gboolean *value, + GError **error) +{ + return THRIFT_PROTOCOL_GET_CLASS (protocol)->read_bool (protocol, value, + error); +} + +gint32 +thrift_protocol_read_byte (ThriftProtocol *protocol, gint8 *value, + GError **error) +{ + return THRIFT_PROTOCOL_GET_CLASS (protocol)->read_byte (protocol, value, + error); +} + +gint32 +thrift_protocol_read_i16 (ThriftProtocol *protocol, gint16 *value, + GError **error) +{ + return THRIFT_PROTOCOL_GET_CLASS (protocol)->read_i16 (protocol, value, + error); +} + +gint32 +thrift_protocol_read_i32 (ThriftProtocol *protocol, gint32 *value, + GError **error) +{ + return THRIFT_PROTOCOL_GET_CLASS (protocol)->read_i32 (protocol, value, + error); +} + +gint32 +thrift_protocol_read_i64 (ThriftProtocol *protocol, gint64 *value, + GError **error) +{ + return THRIFT_PROTOCOL_GET_CLASS (protocol)->read_i64 (protocol, value, + error); +} + +gint32 +thrift_protocol_read_double (ThriftProtocol *protocol, + gdouble *value, GError **error) +{ + return THRIFT_PROTOCOL_GET_CLASS (protocol)->read_double (protocol, value, + error); +} + +gint32 +thrift_protocol_read_string (ThriftProtocol *protocol, + gchar **str, GError **error) +{ + return THRIFT_PROTOCOL_GET_CLASS (protocol)->read_string (protocol, str, + error); +} + +gint32 +thrift_protocol_read_binary (ThriftProtocol *protocol, gpointer *buf, + guint32 *len, GError **error) +{ + return THRIFT_PROTOCOL_GET_CLASS (protocol)->read_binary (protocol, buf, + len, error); +} + +gint32 +thrift_protocol_skip (ThriftProtocol *protocol, ThriftType type, GError **error) +{ + switch (type) + { + case T_BOOL: + { + gboolean boolv; + return thrift_protocol_read_bool (protocol, &boolv, error); + } + case T_BYTE: + { + gint8 bytev; + return thrift_protocol_read_byte (protocol, &bytev, error); + } + + case T_I16: + { + gint16 i16; + return thrift_protocol_read_i16 (protocol, &i16, error); + } + case T_I32: + { + gint32 i32; + return thrift_protocol_read_i32 (protocol, &i32, error); + } + case T_I64: + { + gint64 i64; + return thrift_protocol_read_i64 (protocol, &i64, error); + } + case T_DOUBLE: + { + gdouble dub; + return thrift_protocol_read_double (protocol, &dub, error); + } + case T_STRING: + { + gpointer data; + guint32 len; + gint32 ret = thrift_protocol_read_binary (protocol, &data, &len, error); + g_free (data); + return ret; + } + case T_STRUCT: + { + guint32 result = 0; + gchar *name; + gint16 fid; + ThriftType ftype; + result += thrift_protocol_read_struct_begin (protocol, &name, error); + + while (1) + { + result += thrift_protocol_read_field_begin (protocol, &name, &ftype, + &fid, error); + if (ftype == T_STOP) + { + break; + } + result += thrift_protocol_skip (protocol, ftype, error); + result += thrift_protocol_read_field_end (protocol, error); + } + result += thrift_protocol_read_struct_end (protocol, error); + return result; + } + case T_SET: + { + guint32 result = 0; + ThriftType elem_type; + guint32 i, size; + result += thrift_protocol_read_set_begin (protocol, &elem_type, &size, + error); + for (i = 0; i < size; i++) + { + result += thrift_protocol_skip (protocol, elem_type, error); + } + result += thrift_protocol_read_set_end (protocol, error); + return result; + } + case T_MAP: + { + guint32 result = 0; + ThriftType elem_type; + ThriftType key_type; + guint32 i, size; + result += thrift_protocol_read_map_begin (protocol, &key_type, &elem_type, &size, + error); + for (i = 0; i < size; i++) + { + result += thrift_protocol_skip (protocol, key_type, error); + result += thrift_protocol_skip (protocol, elem_type, error); + } + result += thrift_protocol_read_map_end (protocol, error); + return result; + } + case T_LIST: + { + guint32 result = 0; + ThriftType elem_type; + guint32 i, size; + result += thrift_protocol_read_list_begin (protocol, &elem_type, &size, + error); + for (i = 0; i < size; i++) + { + result += thrift_protocol_skip (protocol, elem_type, error); + } + result += thrift_protocol_read_list_end (protocol, error); + return result; + } + default: + return 0; + } +} + +/* define the GError domain for Thrift protocols */ +GQuark +thrift_protocol_error_quark (void) +{ + return g_quark_from_static_string (THRIFT_PROTOCOL_ERROR_DOMAIN); +} + + +static void +thrift_protocol_init (ThriftProtocol *protocol) +{ + protocol->transport = NULL; +} + +static void +thrift_protocol_class_init (ThriftProtocolClass *cls) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (cls); + + gobject_class->get_property = thrift_protocol_get_property; + gobject_class->set_property = thrift_protocol_set_property; + + g_object_class_install_property (gobject_class, + PROP_THRIFT_PROTOCOL_TRANSPORT, + g_param_spec_object ("transport", "Transport", "Thrift Transport", + THRIFT_TYPE_TRANSPORT, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + + cls->write_message_begin = thrift_protocol_write_message_begin; + cls->write_message_end = thrift_protocol_write_message_end; + cls->write_struct_begin = thrift_protocol_write_struct_begin; + cls->write_struct_end = thrift_protocol_write_struct_end; + cls->write_field_begin = thrift_protocol_write_field_begin; + cls->write_field_end = thrift_protocol_write_field_end; + cls->write_field_stop = thrift_protocol_write_field_stop; + cls->write_map_begin = thrift_protocol_write_map_begin; + cls->write_map_end = thrift_protocol_write_map_end; + cls->write_list_begin = thrift_protocol_write_list_begin; + cls->write_list_end = thrift_protocol_write_list_end; + cls->write_set_begin = thrift_protocol_write_set_begin; + cls->write_set_end = thrift_protocol_write_set_end; + cls->write_bool = thrift_protocol_write_bool; + cls->write_byte = thrift_protocol_write_byte; + cls->write_i16 = thrift_protocol_write_i16; + cls->write_i32 = thrift_protocol_write_i32; + cls->write_i64 = thrift_protocol_write_i64; + cls->write_double = thrift_protocol_write_double; + cls->write_string = thrift_protocol_write_string; + cls->write_binary = thrift_protocol_write_binary; + cls->read_message_begin = thrift_protocol_read_message_begin; + cls->read_message_end = thrift_protocol_read_message_end; + cls->read_struct_begin = thrift_protocol_read_struct_begin; + cls->read_struct_end = thrift_protocol_read_struct_end; + cls->read_field_begin = thrift_protocol_read_field_begin; + cls->read_field_end = thrift_protocol_read_field_end; + cls->read_map_begin = thrift_protocol_read_map_begin; + cls->read_map_end = thrift_protocol_read_map_end; + cls->read_list_begin = thrift_protocol_read_list_begin; + cls->read_set_begin = thrift_protocol_read_set_begin; + cls->read_set_end = thrift_protocol_read_set_end; + cls->read_bool = thrift_protocol_read_bool; + cls->read_byte = thrift_protocol_read_byte; + cls->read_i16 = thrift_protocol_read_i16; + cls->read_i32 = thrift_protocol_read_i32; + cls->read_i64 = thrift_protocol_read_i64; + cls->read_double = thrift_protocol_read_double; + cls->read_string = thrift_protocol_read_string; + cls->read_binary = thrift_protocol_read_binary; +} diff --git a/vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/protocol/thrift_protocol.h b/vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/protocol/thrift_protocol.h new file mode 100644 index 000000000..58fe5e0af --- /dev/null +++ b/vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/protocol/thrift_protocol.h @@ -0,0 +1,341 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT 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_H +#define _THRIFT_PROTOCOL_H + +#include + +#include + +G_BEGIN_DECLS + +/*! \file thrift_protocol.h + * \brief Abstract class for Thrift protocol implementations. + */ + +/** + * 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. + */ +typedef enum { + 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 +} ThriftType; + +/** + * Enumerated definition of the message types that the Thrift protocol + * supports. + */ +typedef enum { + T_CALL = 1, + T_REPLY = 2, + T_EXCEPTION = 3, + T_ONEWAY = 4 +} ThriftMessageType; + +/* type macros */ +#define THRIFT_TYPE_PROTOCOL (thrift_protocol_get_type ()) +#define THRIFT_PROTOCOL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), THRIFT_TYPE_PROTOCOL, ThriftProtocol)) +#define THRIFT_IS_PROTOCOL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), THRIFT_TYPE_PROTOCOL)) +#define THRIFT_PROTOCOL_CLASS(c) (G_TYPE_CHECK_CLASS_CAST ((c), THRIFT_TYPE_PROTOCOL, ThriftProtocolClass)) +#define THRIFT_IS_PROTOCOL_CLASS(c) (G_TYPE_CHECK_CLASS_TYPE ((c), THRIFT_TYPE_PROTOCOL)) +#define THRIFT_PROTOCOL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), THRIFT_TYPE_PROTOCOL, ThriftProtocolClass)) + +typedef struct _ThriftProtocol ThriftProtocol; + +/*! + * Thrift Protocol object + */ +struct _ThriftProtocol +{ + GObject parent; + + /* protected */ + ThriftTransport *transport; +}; + +typedef struct _ThriftProtocolClass ThriftProtocolClass; + +/*! + * Thrift Protocol class + */ +struct _ThriftProtocolClass +{ + GObjectClass parent; + + gint32 (*write_message_begin) (ThriftProtocol *protocol, const gchar *name, + const ThriftMessageType message_type, + const gint32 seqid, GError **error); + gint32 (*write_message_end) (ThriftProtocol *protocol, GError **error); + gint32 (*write_struct_begin) (ThriftProtocol *protocol, const gchar *name, + GError **error); + gint32 (*write_struct_end) (ThriftProtocol *protocol, GError **error); + gint32 (*write_field_begin) (ThriftProtocol *protocol, const gchar *name, + const ThriftType field_type, + const gint16 field_id, GError **error); + gint32 (*write_field_end) (ThriftProtocol *protocol, GError **error); + gint32 (*write_field_stop) (ThriftProtocol *protocol, GError **error); + gint32 (*write_map_begin) (ThriftProtocol *protocol, + const ThriftType key_type, + const ThriftType value_type, + const guint32 size, GError **error); + gint32 (*write_map_end) (ThriftProtocol *protocol, GError **error); + gint32 (*write_list_begin) (ThriftProtocol *protocol, + const ThriftType element_type, + const guint32 size, GError **error); + gint32 (*write_list_end) (ThriftProtocol *protocol, GError **error); + gint32 (*write_set_begin) (ThriftProtocol *protocol, + const ThriftType element_type, + const guint32 size, GError **error); + gint32 (*write_set_end) (ThriftProtocol *protocol, GError **error); + gint32 (*write_bool) (ThriftProtocol *protocol, const gboolean value, + GError **error); + gint32 (*write_byte) (ThriftProtocol *protocol, const gint8 value, + GError **error); + gint32 (*write_i16) (ThriftProtocol *protocol, const gint16 value, + GError **error); + gint32 (*write_i32) (ThriftProtocol *protocol, const gint32 value, + GError **error); + gint32 (*write_i64) (ThriftProtocol *protocol, const gint64 value, + GError **error); + gint32 (*write_double) (ThriftProtocol *protocol, const gdouble value, + GError **error); + gint32 (*write_string) (ThriftProtocol *protocol, const gchar *str, + GError **error); + gint32 (*write_binary) (ThriftProtocol *protocol, const gpointer buf, + const guint32 len, GError **error); + + gint32 (*read_message_begin) (ThriftProtocol *thrift_protocol, gchar **name, + ThriftMessageType *message_type, + gint32 *seqid, GError **error); + gint32 (*read_message_end) (ThriftProtocol *protocol, GError **error); + gint32 (*read_struct_begin) (ThriftProtocol *protocol, gchar **name, + GError **error); + gint32 (*read_struct_end) (ThriftProtocol *protocol, GError **error); + gint32 (*read_field_begin) (ThriftProtocol *protocol, gchar **name, + ThriftType *field_type, gint16 *field_id, + GError **error); + gint32 (*read_field_end) (ThriftProtocol *protocol, GError **error); + gint32 (*read_map_begin) (ThriftProtocol *protocol, ThriftType *key_type, + ThriftType *value_type, guint32 *size, + GError **error); + gint32 (*read_map_end) (ThriftProtocol *protocol, GError **error); + gint32 (*read_list_begin) (ThriftProtocol *protocol, ThriftType *element_type, + guint32 *size, GError **error); + gint32 (*read_list_end) (ThriftProtocol *protocol, GError **error); + gint32 (*read_set_begin) (ThriftProtocol *protocol, ThriftType *element_type, + guint32 *size, GError **error); + gint32 (*read_set_end) (ThriftProtocol *protocol, GError **error); + gint32 (*read_bool) (ThriftProtocol *protocol, gboolean *value, + GError **error); + gint32 (*read_byte) (ThriftProtocol *protocol, gint8 *value, GError **error); + gint32 (*read_i16) (ThriftProtocol *protocol, gint16 *value, GError **error); + gint32 (*read_i32) (ThriftProtocol *protocol, gint32 *value, GError **error); + gint32 (*read_i64) (ThriftProtocol *protocol, gint64 *value, GError **error); + gint32 (*read_double) (ThriftProtocol *protocol, gdouble *value, + GError **error); + gint32 (*read_string) (ThriftProtocol *protocol, gchar **str, GError **error); + gint32 (*read_binary) (ThriftProtocol *protocol, gpointer *buf, + guint32 *len, GError **error); +}; + +/* used by THRIFT_TYPE_PROTOCOL */ +GType thrift_protocol_get_type (void); + +/* virtual public methods */ +gint32 thrift_protocol_write_message_begin (ThriftProtocol *protocol, + const gchar *name, const ThriftMessageType message_type, + const gint32 seqid, GError **error); + +gint32 thrift_protocol_write_message_end (ThriftProtocol *protocol, + GError **error); + +gint32 thrift_protocol_write_struct_begin (ThriftProtocol *protocol, + const gchar *name, + GError **error); + +gint32 thrift_protocol_write_struct_end (ThriftProtocol *protocol, + GError **error); + +gint32 thrift_protocol_write_field_begin (ThriftProtocol *protocol, + const gchar *name, + const ThriftType field_type, + const gint16 field_id, + GError **error); + +gint32 thrift_protocol_write_field_end (ThriftProtocol *protocol, + GError **error); + +gint32 thrift_protocol_write_field_stop (ThriftProtocol *protocol, + GError **error); + +gint32 thrift_protocol_write_map_begin (ThriftProtocol *protocol, + const ThriftType key_type, + const ThriftType value_type, + const guint32 size, GError **error); + +gint32 thrift_protocol_write_map_end (ThriftProtocol *protocol, GError **error); + +gint32 thrift_protocol_write_list_begin (ThriftProtocol *protocol, + const ThriftType element_type, + const guint32 size, GError **error); + +gint32 thrift_protocol_write_list_end (ThriftProtocol *protocol, + GError **error); + +gint32 thrift_protocol_write_set_begin (ThriftProtocol *protocol, + const ThriftType element_type, + const guint32 size, GError **error); + +gint32 thrift_protocol_write_set_end (ThriftProtocol *protocol, + GError **error); + +gint32 thrift_protocol_write_bool (ThriftProtocol *protocol, + const gboolean value, GError **error); + +gint32 thrift_protocol_write_byte (ThriftProtocol *protocol, const gint8 value, + GError **error); + +gint32 thrift_protocol_write_i16 (ThriftProtocol *protocol, const gint16 value, + GError **error); + +gint32 thrift_protocol_write_i32 (ThriftProtocol *protocol, const gint32 value, + GError **error); + +gint32 thrift_protocol_write_i64 (ThriftProtocol *protocol, const gint64 value, + GError **error); + +gint32 thrift_protocol_write_double (ThriftProtocol *protocol, + const gdouble value, GError **error); + +gint32 thrift_protocol_write_string (ThriftProtocol *protocol, + const gchar *str, GError **error); + +gint32 thrift_protocol_write_binary (ThriftProtocol *protocol, + const gpointer buf, + const guint32 len, GError **error); + +gint32 thrift_protocol_read_message_begin (ThriftProtocol *thrift_protocol, + gchar **name, + ThriftMessageType *message_type, + gint32 *seqid, GError **error); + +gint32 thrift_protocol_read_message_end (ThriftProtocol *protocol, + GError **error); + +gint32 thrift_protocol_read_struct_begin (ThriftProtocol *protocol, + gchar **name, + GError **error); + +gint32 thrift_protocol_read_struct_end (ThriftProtocol *protocol, + GError **error); + +gint32 thrift_protocol_read_field_begin (ThriftProtocol *protocol, + gchar **name, + ThriftType *field_type, + gint16 *field_id, + GError **error); + +gint32 thrift_protocol_read_field_end (ThriftProtocol *protocol, + GError **error); + +gint32 thrift_protocol_read_map_begin (ThriftProtocol *protocol, + ThriftType *key_type, + ThriftType *value_type, guint32 *size, + GError **error); + +gint32 thrift_protocol_read_map_end (ThriftProtocol *protocol, GError **error); + +gint32 thrift_protocol_read_list_begin (ThriftProtocol *protocol, + ThriftType *element_type, + guint32 *size, GError **error); + +gint32 thrift_protocol_read_list_end (ThriftProtocol *protocol, GError **error); + +gint32 thrift_protocol_read_set_begin (ThriftProtocol *protocol, + ThriftType *element_type, + guint32 *size, GError **error); + +gint32 thrift_protocol_read_set_end (ThriftProtocol *protocol, GError **error); + +gint32 thrift_protocol_read_bool (ThriftProtocol *protocol, gboolean *value, + GError **error); + +gint32 thrift_protocol_read_byte (ThriftProtocol *protocol, gint8 *value, + GError **error); + +gint32 thrift_protocol_read_i16 (ThriftProtocol *protocol, gint16 *value, + GError **error); + +gint32 thrift_protocol_read_i32 (ThriftProtocol *protocol, gint32 *value, + GError **error); + +gint32 thrift_protocol_read_i64 (ThriftProtocol *protocol, gint64 *value, + GError **error); + +gint32 thrift_protocol_read_double (ThriftProtocol *protocol, + gdouble *value, GError **error); + +gint32 thrift_protocol_read_string (ThriftProtocol *protocol, + gchar **str, GError **error); + +gint32 thrift_protocol_read_binary (ThriftProtocol *protocol, + gpointer *buf, guint32 *len, + GError **error); + +gint32 thrift_protocol_skip (ThriftProtocol *protocol, ThriftType type, + GError **error); + +/* define error types */ +typedef enum +{ + THRIFT_PROTOCOL_ERROR_UNKNOWN, + THRIFT_PROTOCOL_ERROR_INVALID_DATA, + THRIFT_PROTOCOL_ERROR_NEGATIVE_SIZE, + THRIFT_PROTOCOL_ERROR_SIZE_LIMIT, + THRIFT_PROTOCOL_ERROR_BAD_VERSION, + THRIFT_PROTOCOL_ERROR_NOT_IMPLEMENTED, + THRIFT_PROTOCOL_ERROR_DEPTH_LIMIT +} ThriftProtocolError; + +/* define an error domain for GError to use */ +GQuark thrift_protocol_error_quark (void); +#define THRIFT_PROTOCOL_ERROR (thrift_protocol_error_quark ()) + +G_END_DECLS + +#endif /* _THRIFT_PROTOCOL_H */ diff --git a/vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/protocol/thrift_protocol_factory.c b/vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/protocol/thrift_protocol_factory.c new file mode 100644 index 000000000..bef40876f --- /dev/null +++ b/vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/protocol/thrift_protocol_factory.c @@ -0,0 +1,43 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT 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 +#include + +G_DEFINE_ABSTRACT_TYPE(ThriftProtocolFactory, thrift_protocol_factory, G_TYPE_OBJECT) + +ThriftProtocol * +thrift_protocol_factory_get_protocol(ThriftProtocolFactory *factory, + ThriftTransport *transport) +{ + return THRIFT_PROTOCOL_FACTORY_GET_CLASS (factory)->get_protocol (factory, + transport); +} + +static void +thrift_protocol_factory_init (ThriftProtocolFactory *factory) +{ + THRIFT_UNUSED_VAR (factory); +} + +static void +thrift_protocol_factory_class_init (ThriftProtocolFactoryClass *cls) +{ + cls->get_protocol = thrift_protocol_factory_get_protocol; +} diff --git a/vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/protocol/thrift_protocol_factory.h b/vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/protocol/thrift_protocol_factory.h new file mode 100644 index 000000000..5f146dde3 --- /dev/null +++ b/vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/protocol/thrift_protocol_factory.h @@ -0,0 +1,73 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef _THRIFT_PROTOCOL_FACTORY_H +#define _THRIFT_PROTOCOL_FACTORY_H + +#include + +#include +#include + +G_BEGIN_DECLS + +/*! \file thrift_protocol_factory.h + * \brief Abstract class for Thrift protocol factory implementations. + */ + +/* type macros */ +#define THRIFT_TYPE_PROTOCOL_FACTORY (thrift_protocol_factory_get_type ()) +#define THRIFT_PROTOCOL_FACTORY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), THRIFT_TYPE_PROTOCOL_FACTORY, ThriftProtocolFactory)) +#define THRIFT_IS_PROTOCOL_FACTORY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), THRIFT_TYPE_PROTOCOL_FACTORY)) +#define THRIFT_PROTOCOL_FACTORY_CLASS(c) (G_TYPE_CHECK_CLASS_CAST ((c), THRIFT_TYPE_PROTOCOL_FACTORY, ThriftProtocolFactoryClass)) +#define THRIFT_IS_PROTOCOL_FACTORY_CLASS(c) (G_TYPE_CHECK_CLASS_TYPE ((c), THRIFT_TYPE_PROTOCOL_FACTORY)) +#define THRIFT_PROTOCOL_FACTORY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), THRIFT_TYPE_PROTOCOL_FACTORY, ThriftProtocolFactoryClass)) + +typedef struct _ThriftProtocolFactory ThriftProtocolFactory; + +/*! + * Thrift Protocol Factory object + */ +struct _ThriftProtocolFactory +{ + GObject parent; +}; + +typedef struct _ThriftProtocolFactoryClass ThriftProtocolFactoryClass; + +/*! + * Thrift Protocol Factory class + */ +struct _ThriftProtocolFactoryClass +{ + GObjectClass parent; + + ThriftProtocol *(*get_protocol) (ThriftProtocolFactory *factory, + ThriftTransport *transport); +}; + +/* used by THRIFT_TYPE_PROTOCOL_FACTORY */ +GType thrift_protocol_factory_get_type (void); + +/* virtual public methods */ +ThriftProtocol *thrift_protocol_factory_get_protocol(ThriftProtocolFactory *factory, ThriftTransport *transport); + +G_END_DECLS + +#endif /* _THRIFT_PROTOCOL_FACTORY_H */ diff --git a/vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/server/thrift_server.c b/vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/server/thrift_server.c new file mode 100644 index 000000000..e8aff4525 --- /dev/null +++ b/vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/server/thrift_server.c @@ -0,0 +1,174 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT 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 +#include "thrift_server.h" + +/* object properties */ +enum _ThriftServerProperties +{ + PROP_0, + PROP_THRIFT_SERVER_PROCESSOR, + PROP_THRIFT_SERVER_SERVER_TRANSPORT, + PROP_THRIFT_SERVER_INPUT_TRANSPORT_FACTORY, + PROP_THRIFT_SERVER_OUTPUT_TRANSPORT_FACTORY, + PROP_THRIFT_SERVER_INPUT_PROTOCOL_FACTORY, + PROP_THRIFT_SERVER_OUTPUT_PROTOCOL_FACTORY +}; + +G_DEFINE_ABSTRACT_TYPE(ThriftServer, thrift_server, G_TYPE_OBJECT) + +void +thrift_server_get_property (GObject *object, guint property_id, + GValue *value, GParamSpec *pspec) +{ + ThriftServer *server = THRIFT_SERVER (object); + + THRIFT_UNUSED_VAR (pspec); + + switch (property_id) + { + case PROP_THRIFT_SERVER_PROCESSOR: + g_value_set_object (value, server->processor); + break; + case PROP_THRIFT_SERVER_SERVER_TRANSPORT: + g_value_set_object (value, server->server_transport); + break; + case PROP_THRIFT_SERVER_INPUT_TRANSPORT_FACTORY: + g_value_set_object (value, server->input_transport_factory); + break; + case PROP_THRIFT_SERVER_OUTPUT_TRANSPORT_FACTORY: + g_value_set_object (value, server->output_transport_factory); + break; + case PROP_THRIFT_SERVER_INPUT_PROTOCOL_FACTORY: + g_value_set_object (value, server->input_protocol_factory); + break; + case PROP_THRIFT_SERVER_OUTPUT_PROTOCOL_FACTORY: + g_value_set_object (value, server->output_protocol_factory); + break; + } +} + +void +thrift_server_set_property (GObject *object, guint property_id, + const GValue *value, GParamSpec *pspec) +{ + ThriftServer *server = THRIFT_SERVER (object); + + THRIFT_UNUSED_VAR (pspec); + + switch (property_id) + { + case PROP_THRIFT_SERVER_PROCESSOR: + server->processor = g_value_get_object (value); + break; + case PROP_THRIFT_SERVER_SERVER_TRANSPORT: + server->server_transport = g_value_get_object (value); + break; + case PROP_THRIFT_SERVER_INPUT_TRANSPORT_FACTORY: + server->input_transport_factory = g_value_get_object (value); + break; + case PROP_THRIFT_SERVER_OUTPUT_TRANSPORT_FACTORY: + server->output_transport_factory = g_value_get_object (value); + break; + case PROP_THRIFT_SERVER_INPUT_PROTOCOL_FACTORY: + server->input_protocol_factory = g_value_get_object (value); + break; + case PROP_THRIFT_SERVER_OUTPUT_PROTOCOL_FACTORY: + server->output_protocol_factory = g_value_get_object (value); + break; + } +} + +gboolean +thrift_server_serve (ThriftServer *server, GError **error) +{ + return THRIFT_SERVER_GET_CLASS (server)->serve (server, error); +} + +void +thrift_server_stop (ThriftServer *server) +{ + THRIFT_SERVER_GET_CLASS (server)->stop (server); +} + +/* instance initializer for Thrift Server */ +static void +thrift_server_init (ThriftServer *server) +{ + server->processor = NULL; + server->server_transport = NULL; + server->input_transport_factory = NULL; + server->output_transport_factory = NULL; + server->input_protocol_factory = NULL; + server->output_protocol_factory = NULL; +} + +/* class initializer for ThriftServer + * TODO: implement ServerEventHandler as a GClosure + */ +static void +thrift_server_class_init (ThriftServerClass *cls) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (cls); + + gobject_class->get_property = thrift_server_get_property; + gobject_class->set_property = thrift_server_set_property; + + g_object_class_install_property (gobject_class, + PROP_THRIFT_SERVER_PROCESSOR, + g_param_spec_object ("processor", "Processor", "Thrift Processor", + THRIFT_TYPE_PROCESSOR, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + g_object_class_install_property (gobject_class, + PROP_THRIFT_SERVER_SERVER_TRANSPORT, + g_param_spec_object ("server_transport", "Server Transport", + "Thrift Server Transport", + THRIFT_TYPE_SERVER_TRANSPORT, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + g_object_class_install_property (gobject_class, + PROP_THRIFT_SERVER_INPUT_TRANSPORT_FACTORY, + g_param_spec_object ("input_transport_factory", "Input Transport Factory", + "Thrift Server Input Transport Factory", + THRIFT_TYPE_TRANSPORT_FACTORY, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + g_object_class_install_property (gobject_class, + PROP_THRIFT_SERVER_OUTPUT_TRANSPORT_FACTORY, + g_param_spec_object ("output_transport_factory", + "Output Transport Factory", + "Thrift Server Output Transport Factory", + THRIFT_TYPE_TRANSPORT_FACTORY, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + g_object_class_install_property (gobject_class, + PROP_THRIFT_SERVER_INPUT_PROTOCOL_FACTORY, + g_param_spec_object ("input_protocol_factory", "Input Protocol Factory", + "Thrift Server Input Protocol Factory", + THRIFT_TYPE_PROTOCOL_FACTORY, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + g_object_class_install_property (gobject_class, + PROP_THRIFT_SERVER_OUTPUT_PROTOCOL_FACTORY, + g_param_spec_object ("output_protocol_factory", "Output Protocol Factory", + "Thrift Server Output Protocol Factory", + THRIFT_TYPE_PROTOCOL_FACTORY, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + + /* set these as virtual methods to be implemented by a subclass */ + cls->serve = thrift_server_serve; + cls->stop = thrift_server_stop; +} diff --git a/vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/server/thrift_server.h b/vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/server/thrift_server.h new file mode 100644 index 000000000..49beddcbe --- /dev/null +++ b/vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/server/thrift_server.h @@ -0,0 +1,93 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef _THRIFT_SERVER_H +#define _THRIFT_SERVER_H + +#include + +#include +#include +#include +#include + +G_BEGIN_DECLS + +/*! \file thrift_server.h + * \brief Abstract class for Thrift servers. + */ + +/* type macros */ +#define THRIFT_TYPE_SERVER (thrift_server_get_type ()) +#define THRIFT_SERVER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), THRIFT_TYPE_SERVER, ThriftServer)) +#define THRIFT_IS_SERVER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), THRIFT_TYPE_SERVER)) +#define THRIFT_SERVER_CLASS(c) (G_TYPE_CHECK_CLASS_CAST ((c), THRIFT_TYPE_SERVER, ThriftServerClass)) +#define THRIFT_IS_SERVER_CLASS(c) (G_TYPE_CHECK_CLASS_TYPE ((c), THRIFT_TYPE_SERVER)) +#define THRIFT_SERVER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), THRIFT_TYPE_SERVER, ThriftServerClass)) + +typedef struct _ThriftServer ThriftServer; + +/*! + * Thrift Server object + */ +struct _ThriftServer +{ + GObject parent; + + /* protected */ + ThriftProcessor *processor; + ThriftServerTransport *server_transport; + ThriftTransportFactory *input_transport_factory; + ThriftTransportFactory *output_transport_factory; + ThriftProtocolFactory *input_protocol_factory; + ThriftProtocolFactory *output_protocol_factory; +}; + +typedef struct _ThriftServerClass ThriftServerClass; + +/*! + * Thrift Server class + */ +struct _ThriftServerClass +{ + GObjectClass parent; + + /* vtable */ + gboolean (*serve) (ThriftServer *server, GError **error); + void (*stop) (ThriftServer *server); +}; + +/* used by THRIFT_TYPE_SERVER */ +GType thrift_server_get_type (void); + +/*! + * Processes the request. + * \public \memberof ThriftServerClass + */ +gboolean thrift_server_serve (ThriftServer *server, GError **error); + +/*! + * Stop handling requests. + */ +void thrift_server_stop (ThriftServer *server); + +G_END_DECLS + +#endif /* _THRIFT_SERVER_H */ + diff --git a/vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/server/thrift_simple_server.c b/vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/server/thrift_simple_server.c new file mode 100644 index 000000000..22a96c7a4 --- /dev/null +++ b/vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/server/thrift_simple_server.c @@ -0,0 +1,138 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT 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 +#include +#include +#include + +G_DEFINE_TYPE(ThriftSimpleServer, thrift_simple_server, THRIFT_TYPE_SERVER) + +gboolean +thrift_simple_server_serve (ThriftServer *server, GError **error) +{ + ThriftTransport *t = NULL; + ThriftTransport *input_transport = NULL, *output_transport = NULL; + ThriftProtocol *input_protocol = NULL, *output_protocol = NULL; + ThriftSimpleServer *tss = THRIFT_SIMPLE_SERVER(server); + GError *process_error = NULL; + + g_return_val_if_fail (THRIFT_IS_SIMPLE_SERVER (server), FALSE); + + if (thrift_server_transport_listen (server->server_transport, error)) { + tss->running = TRUE; + while (tss->running == TRUE) + { + t = thrift_server_transport_accept (server->server_transport, + error); + if (t != NULL && tss->running) { + input_transport = + THRIFT_TRANSPORT_FACTORY_GET_CLASS (server->input_transport_factory) + ->get_transport (server->input_transport_factory, t); + output_transport = + THRIFT_TRANSPORT_FACTORY_GET_CLASS (server->output_transport_factory) + ->get_transport (server->output_transport_factory, t); + input_protocol = + THRIFT_PROTOCOL_FACTORY_GET_CLASS (server->input_protocol_factory) + ->get_protocol (server->input_protocol_factory, input_transport); + output_protocol = + THRIFT_PROTOCOL_FACTORY_GET_CLASS (server->output_protocol_factory) + ->get_protocol (server->output_protocol_factory, output_transport); + + while (THRIFT_PROCESSOR_GET_CLASS (server->processor) + ->process (server->processor, + input_protocol, + output_protocol, + &process_error) && + thrift_transport_peek (input_transport, &process_error)) + { + } + + if (process_error != NULL) + { + g_message ("thrift_simple_server_serve: %s", process_error->message); + g_clear_error (&process_error); + + /* Note we do not propagate processing errors to the caller as they + * normally are transient and not fatal to the server */ + } + + /* TODO: handle exceptions */ + THRIFT_TRANSPORT_GET_CLASS (input_transport)->close (input_transport, + NULL); + THRIFT_TRANSPORT_GET_CLASS (output_transport)->close (output_transport, + NULL); + } + } + + /* attempt to shutdown */ + THRIFT_SERVER_TRANSPORT_GET_CLASS (server->server_transport) + ->close (server->server_transport, NULL); + } + + /* Since this method is designed to run forever, it can only ever return on + * error */ + return FALSE; +} + +void +thrift_simple_server_stop (ThriftServer *server) +{ + g_return_if_fail (THRIFT_IS_SIMPLE_SERVER (server)); + (THRIFT_SIMPLE_SERVER (server))->running = FALSE; +} + +static void +thrift_simple_server_init (ThriftSimpleServer *tss) +{ + ThriftServer *server = THRIFT_SERVER(tss); + + tss->running = FALSE; + + if (server->input_transport_factory == NULL) + { + server->input_transport_factory = + g_object_new (THRIFT_TYPE_TRANSPORT_FACTORY, NULL); + } + if (server->output_transport_factory == NULL) + { + server->output_transport_factory = + g_object_new (THRIFT_TYPE_TRANSPORT_FACTORY, NULL); + } + if (server->input_protocol_factory == NULL) + { + server->input_protocol_factory = + g_object_new (THRIFT_TYPE_BINARY_PROTOCOL_FACTORY, NULL); + } + if (server->output_protocol_factory == NULL) + { + server->output_protocol_factory = + g_object_new (THRIFT_TYPE_BINARY_PROTOCOL_FACTORY, NULL); + } +} + +/* initialize the class */ +static void +thrift_simple_server_class_init (ThriftSimpleServerClass *class) +{ + ThriftServerClass *cls = THRIFT_SERVER_CLASS(class); + + cls->serve = thrift_simple_server_serve; + cls->stop = thrift_simple_server_stop; +} diff --git a/vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/server/thrift_simple_server.h b/vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/server/thrift_simple_server.h new file mode 100644 index 000000000..86b538b48 --- /dev/null +++ b/vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/server/thrift_simple_server.h @@ -0,0 +1,70 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT 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_SIMPLE_SERVER_H +#define _THRIFT_SIMPLE_SERVER_H + +#include + +#include + +G_BEGIN_DECLS + +/*! \file thrift_simple_server.h + * \brief A simple Thrift server, single-threaded. + */ + +/* type macros */ +#define THRIFT_TYPE_SIMPLE_SERVER (thrift_simple_server_get_type ()) +#define THRIFT_SIMPLE_SERVER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), THRIFT_TYPE_SIMPLE_SERVER, ThriftSimpleServer)) +#define THRIFT_IS_SIMPLE_SERVER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), THRIFT_TYPE_SIMPLE_SERVER)) +#define THRIFT_SIMPLE_SERVER_CLASS(c) (G_TYPE_CHECK_CLASS_CAST ((c) THRIFT_TYPE_SIMPLE_SERVER, ThriftSimpleServerClass)) +#define THRIFT_IS_SIMPLE_SERVER_CLASS(c) (G_TYPE_CHECK_CLASS_TYPE ((c), THRIFT_TYPE_SIMPLE_SERVER)) +#define THRIFT_SIMPLE_SERVER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), THRIFT_TYPE_SIMPLE_SERVER, ThriftSimpleServerClass)) + +typedef struct _ThriftSimpleServer ThriftSimpleServer; + +/** + * Thrift Simple Server instance. + */ +struct _ThriftSimpleServer +{ + ThriftServer parent; + + /* private */ + volatile gboolean running; +}; + +typedef struct _ThriftSimpleServerClass ThriftSimpleServerClass; + +/** + * Thrift Simple Server class. + */ +struct _ThriftSimpleServerClass +{ + ThriftServerClass parent; +}; + +/* used by THRIFT_TYPE_SIMPLE_SERVER */ +GType thrift_simple_server_get_type (void); + +G_END_DECLS + +#endif /* _THRIFT_SIMPLE_SERVER_H */ + diff --git a/vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/thrift.c b/vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/thrift.c new file mode 100644 index 000000000..8de869f79 --- /dev/null +++ b/vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/thrift.c @@ -0,0 +1,101 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include + +/** + * GHashTable callback to add keys to a GList. + */ +void +thrift_hash_table_get_keys (gpointer key, gpointer value, gpointer user_data) +{ + GList **list = (GList **) user_data; + + THRIFT_UNUSED_VAR (value); + + *list = g_list_append (*list, key); +} +void thrift_safe_hash_table_destroy(GHashTable* hash_table) +{ + if (hash_table) + { + g_hash_table_destroy(hash_table); + } +} + +guint thrift_boolean_hash(gconstpointer v) +{ + const gboolean* p = v; + return p && *p ? 1 : 0; +} +gboolean thrift_boolean_equal(gconstpointer a, gconstpointer b) +{ + if (a == b) { + return TRUE; + } + if (!a || !b) { + return FALSE; + } + const gboolean* pa = a; + const gboolean* pb = b; + return *pa == *pb; +} + +guint thrift_int8_hash(gconstpointer v) +{ + const gint8* p = v; + return p ? *p : 0; +} +gboolean thrift_int8_equal(gconstpointer a, gconstpointer b) +{ + if (a == b) { + return TRUE; + } + if (!a || !b) { + return FALSE; + } + const gint8* pa = a; + const gint8* pb = b; + return *pa == *pb; +} + +guint thrift_int16_hash(gconstpointer v) +{ + const gint16* p = v; + return p ? *p : 0; +} +gboolean thrift_int16_equal(gconstpointer a, gconstpointer b) +{ + if (a == b) { + return TRUE; + } + if (!a || !b) { + return FALSE; + } + const gint16* pa = a; + const gint16* pb = b; + return *pa == *pb; +} + +void +thrift_string_free (gpointer str) +{ + GByteArray* ptr = str; + g_byte_array_unref(ptr); +} diff --git a/vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/thrift.h b/vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/thrift.h new file mode 100644 index 000000000..94a647831 --- /dev/null +++ b/vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/thrift.h @@ -0,0 +1,49 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT 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_H +#define _THRIFT_H + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +/* this macro is called to satisfy -Wall hardcore compilation */ +#ifndef THRIFT_UNUSED_VAR +# define THRIFT_UNUSED_VAR(x) ((void) x) +#endif + +void thrift_hash_table_get_keys (gpointer key, gpointer value, + gpointer user_data); +void thrift_safe_hash_table_destroy(GHashTable* hash_table); + +guint thrift_boolean_hash(gconstpointer v); +gboolean thrift_boolean_equal(gconstpointer a, gconstpointer b); + +guint thrift_int8_hash(gconstpointer v); +gboolean thrift_int8_equal(gconstpointer a, gconstpointer b); + +guint thrift_int16_hash(gconstpointer v); +gboolean thrift_int16_equal(gconstpointer a, gconstpointer b); + +void thrift_string_free (gpointer str); + +#endif /* #ifndef _THRIFT_THRIFT_H */ diff --git a/vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/thrift_application_exception.c b/vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/thrift_application_exception.c new file mode 100644 index 000000000..1234caef9 --- /dev/null +++ b/vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/thrift_application_exception.c @@ -0,0 +1,277 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT 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_application_exception.h" +#include + +/* object properties */ +enum _ThriftApplicationExceptionProperties +{ + PROP_0, + PROP_THRIFT_APPLICATION_EXCEPTION_TYPE, + PROP_THRIFT_APPLICATION_EXCEPTION_MESSAGE +}; + +G_DEFINE_TYPE(ThriftApplicationException, thrift_application_exception, THRIFT_TYPE_STRUCT) + +gint32 +thrift_application_exception_read (ThriftStruct *object, + ThriftProtocol *protocol, GError **error) +{ + gint32 ret; + gint32 xfer = 0; + gchar *name; + ThriftType ftype; + gint16 fid; + ThriftApplicationException *this = THRIFT_APPLICATION_EXCEPTION (object); + + /* read the struct begin marker */ + if ((ret = thrift_protocol_read_struct_begin (protocol, &name, error)) < 0) + { + if (name) g_free (name); + return -1; + } + xfer += ret; + if (name) g_free (name); + + while (1) + { + if ((ret = thrift_protocol_read_field_begin (protocol, &name, &ftype, + &fid, error)) < 0) + { + if (name) g_free (name); + return -1; + } + xfer += ret; + if (name) g_free (name); + + /* break if we get a STOP field */ + if (ftype == T_STOP) + { + break; + } + + switch (fid) + { + case 1: + if (ftype == T_STRING) + { + if ((ret = thrift_protocol_read_string (protocol, &this->message, + error)) < 0) + return -1; + xfer += ret; + this->__isset_message = TRUE; + } else { + if ((ret = thrift_protocol_skip (protocol, ftype, error)) < 0) + return -1; + xfer += ret; + } + break; + case 2: + if (ftype == T_I32) + { + if ((ret = thrift_protocol_read_i32 (protocol, &this->type, + error)) < 0) + return -1; + xfer += ret; + this->__isset_type = TRUE; + } else { + if ((ret = thrift_protocol_skip (protocol, ftype, error)) < 0) + return -1; + xfer += ret; + } + break; + default: + if ((ret = thrift_protocol_skip (protocol, ftype, error)) < 0) + return -1; + xfer += ret; + break; + } + if ((ret = thrift_protocol_read_field_end (protocol, error)) < 0) + return -1; + xfer += ret; + } + + if ((ret = thrift_protocol_read_struct_end (protocol, error)) < 0) + return -1; + xfer += ret; + + return xfer; +} + +gint32 +thrift_application_exception_write (ThriftStruct *object, + ThriftProtocol *protocol, GError **error) +{ + gint32 ret; + gint32 xfer = 0; + + ThriftApplicationException *this = THRIFT_APPLICATION_EXCEPTION (object); + + if ((ret = thrift_protocol_write_struct_begin (protocol, + "TApplicationException", + error)) < 0) + return -1; + xfer += ret; + if ((ret = thrift_protocol_write_field_begin (protocol, "message", + T_STRING, 1, error)) < 0) + return -1; + xfer += ret; + if ((ret = thrift_protocol_write_string (protocol, this->message, error)) < 0) + return -1; + xfer += ret; + if ((ret = thrift_protocol_write_field_end (protocol, error)) < 0) + return -1; + xfer += ret; + if ((ret = thrift_protocol_write_field_begin (protocol, "type", + T_I32, 2, error)) < 0) + return -1; + xfer += ret; + if ((ret = thrift_protocol_write_i32 (protocol, this->type, error)) < 0) + return -1; + xfer += ret; + if ((ret = thrift_protocol_write_field_end (protocol, error)) < 0) + return -1; + xfer += ret; + if ((ret = thrift_protocol_write_field_stop (protocol, error)) < 0) + return -1; + xfer += ret; + if ((ret = thrift_protocol_write_struct_end (protocol, error)) < 0) + return -1; + xfer += ret; + + return xfer; +} + + +/* GError domain */ +#define THRIFT_APPLICATION_EXCEPTION_ERROR_DOMAIN "thrift-application-exception-error-quark" + +GQuark +thrift_application_exception_error_quark (void) +{ + return g_quark_from_static_string (THRIFT_APPLICATION_EXCEPTION_ERROR_DOMAIN); +} + +static void +thrift_application_exception_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + ThriftApplicationException *tae = THRIFT_APPLICATION_EXCEPTION (object); + + switch (property_id) + { + case PROP_THRIFT_APPLICATION_EXCEPTION_TYPE: + g_value_set_int (value, tae->type); + break; + case PROP_THRIFT_APPLICATION_EXCEPTION_MESSAGE: + g_value_set_string (value, tae->message); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static void +thrift_application_exception_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + ThriftApplicationException *tae = THRIFT_APPLICATION_EXCEPTION (object); + + switch (property_id) + { + case PROP_THRIFT_APPLICATION_EXCEPTION_TYPE: + tae->type = g_value_get_int (value); + tae->__isset_type = TRUE; + break; + case PROP_THRIFT_APPLICATION_EXCEPTION_MESSAGE: + if (tae->message != NULL) + g_free (tae->message); + + tae->message = g_value_dup_string (value); + tae->__isset_message = TRUE; + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +void +thrift_application_exception_init (ThriftApplicationException *object) +{ + object->type = 0; + object->__isset_type = FALSE; + object->message = NULL; + object->__isset_message = FALSE; +} + +void +thrift_application_exception_finalize (GObject *object) +{ + ThriftApplicationException *tae = THRIFT_APPLICATION_EXCEPTION (object); + + if (tae->__isset_message) { + g_free(tae->message); + } +} + +void +thrift_application_exception_class_init (ThriftApplicationExceptionClass *class) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS(class); + ThriftStructClass *cls = THRIFT_STRUCT_CLASS(class); + GParamSpec *param_spec; + + cls->read = thrift_application_exception_read; + cls->write = thrift_application_exception_write; + + gobject_class->finalize = thrift_application_exception_finalize; + gobject_class->get_property = thrift_application_exception_get_property; + gobject_class->set_property = thrift_application_exception_set_property; + + param_spec = g_param_spec_int ("type", + "Exception type", + "The type of the exception, one of the " + "values defined by the " + "ThriftApplicationExceptionError " + "enumeration.", + 0, + THRIFT_APPLICATION_EXCEPTION_ERROR_N - 1, + 0, + G_PARAM_READWRITE); + g_object_class_install_property (gobject_class, + PROP_THRIFT_APPLICATION_EXCEPTION_TYPE, + param_spec); + + param_spec = g_param_spec_string ("message", + "Exception message", + "A string describing the exception that " + "occurred.", + NULL, + G_PARAM_READWRITE); + g_object_class_install_property (gobject_class, + PROP_THRIFT_APPLICATION_EXCEPTION_MESSAGE, + param_spec); +} diff --git a/vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/thrift_application_exception.h b/vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/thrift_application_exception.h new file mode 100644 index 000000000..733f793cb --- /dev/null +++ b/vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/thrift_application_exception.h @@ -0,0 +1,86 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef _THRIFT_APPLICATION_EXCEPTION_H +#define _THRIFT_APPLICATION_EXCEPTION_H + +#include +#include "thrift_struct.h" + +G_BEGIN_DECLS + +/*! \file thrift_application_exception.h + * \brief C Implementation of a TApplicationException. + */ + +/* type macros */ +#define THRIFT_TYPE_APPLICATION_EXCEPTION (thrift_application_exception_get_type ()) +#define THRIFT_APPLICATION_EXCEPTION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), THRIFT_TYPE_APPLICATION_EXCEPTION, ThriftApplicationException)) +#define THRIFT_IS_APPLICATION_EXCEPTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), THRIFT_TYPE_APPLICATION_EXCEPTION)) +#define THRIFT_APPLICATION_EXCEPTION_CLASS(c) (G_TYPE_CHECK_CLASS_CAST ((c), THRIFT_TYPE_APPLICATION_EXCEPTION, ThriftApplicationExceptionClass)) +#define THRIFT_IS_APPLICATION_EXCEPTION_CLASS(c) (G_TYPE_CHECK_CLASS_TYPE ((c), THRIFT_TYPE_APPLICATION_EXCEPTION)) +#define THRIFT_APPLICATION_EXCEPTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), THRIFT_TYPE_APPLICATION_EXCEPTION, ThriftApplicationExceptionClass)) + +typedef struct _ThriftApplicationException ThriftApplicationException; + +struct _ThriftApplicationException +{ + ThriftStruct parent; + + /* private */ + gint32 type; + gboolean __isset_type; + gchar *message; + gboolean __isset_message; +}; + +typedef struct _ThriftApplicationExceptionClass ThriftApplicationExceptionClass; + +struct _ThriftApplicationExceptionClass +{ + ThriftStructClass parent; +}; + +GType thrift_application_exception_get_type (void); + +/* gerror codes */ +typedef enum +{ + THRIFT_APPLICATION_EXCEPTION_ERROR_UNKNOWN, + THRIFT_APPLICATION_EXCEPTION_ERROR_UNKNOWN_METHOD, + THRIFT_APPLICATION_EXCEPTION_ERROR_INVALID_MESSAGE_TYPE, + THRIFT_APPLICATION_EXCEPTION_ERROR_WRONG_METHOD_NAME, + THRIFT_APPLICATION_EXCEPTION_ERROR_BAD_SEQUENCE_ID, + THRIFT_APPLICATION_EXCEPTION_ERROR_MISSING_RESULT, + THRIFT_APPLICATION_EXCEPTION_ERROR_INTERNAL_ERROR, + THRIFT_APPLICATION_EXCEPTION_ERROR_PROTOCOL_ERROR, + THRIFT_APPLICATION_EXCEPTION_ERROR_INVALID_TRANSFORM, + THRIFT_APPLICATION_EXCEPTION_ERROR_INVALID_PROTOCOL, + THRIFT_APPLICATION_EXCEPTION_ERROR_UNSUPPORTED_CLIENT_TYPE, + + THRIFT_APPLICATION_EXCEPTION_ERROR_N +} ThriftApplicationExceptionError; + +/* define error domain for GError */ +GQuark thrift_application_exception_error_quark (void); +#define THRIFT_APPLICATION_EXCEPTION_ERROR (thrift_application_exception_error_quark ()) + +G_END_DECLS + +#endif /* _THRIFT_APPLICATION_EXCEPTION_H */ diff --git a/vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/thrift_struct.c b/vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/thrift_struct.c new file mode 100644 index 000000000..f24f2a1c8 --- /dev/null +++ b/vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/thrift_struct.c @@ -0,0 +1,52 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include +#include "thrift_struct.h" + +G_DEFINE_ABSTRACT_TYPE(ThriftStruct, thrift_struct, G_TYPE_OBJECT) + +gint32 +thrift_struct_read (ThriftStruct *object, ThriftProtocol *protocol, + GError **error) +{ + g_return_val_if_fail (THRIFT_IS_STRUCT (object), -1); + return THRIFT_STRUCT_GET_CLASS (object)->read (object, protocol, error); +} + +gint32 +thrift_struct_write (ThriftStruct *object, ThriftProtocol *protocol, + GError **error) +{ + g_return_val_if_fail (THRIFT_IS_STRUCT (object), -1); + return THRIFT_STRUCT_GET_CLASS (object)->write (object, protocol, error); +} + +static void +thrift_struct_class_init (ThriftStructClass *cls) +{ + cls->read = thrift_struct_read; + cls->write = thrift_struct_write; +} + +static void +thrift_struct_init (ThriftStruct *structure) +{ + THRIFT_UNUSED_VAR (structure); +} diff --git a/vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/thrift_struct.h b/vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/thrift_struct.h new file mode 100644 index 000000000..f4cfcb2c4 --- /dev/null +++ b/vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/thrift_struct.h @@ -0,0 +1,68 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef THRIFT_STRUCT_H +#define THRIFT_STRUCT_H + +#include + +#include + +G_BEGIN_DECLS + +#define THRIFT_TYPE_STRUCT (thrift_struct_get_type ()) +#define THRIFT_STRUCT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), THRIFT_TYPE_STRUCT, ThriftStruct)) +#define THRIFT_STRUCT_CLASS(c) (G_TYPE_CHECK_CLASS_CAST ((c), THRIFT_TYPE_STRUCT, ThriftStructClass)) +#define THRIFT_IS_STRUCT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), THRIFT_TYPE_STRUCT)) +#define THRIFT_IS_STRUCT_CLASS(c) (G_TYPE_CHECK_CLASS_TYPE ((c), THRIFT_TYPE_STRUCT)) +#define THRIFT_STRUCT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), THRIFT_TYPE_STRUCT, ThriftStructClass)) + +typedef struct _ThriftStruct ThriftStruct; + +/* struct */ +struct _ThriftStruct +{ + GObject parent; + + /* private */ +}; + +typedef struct _ThriftStructClass ThriftStructClass; + +struct _ThriftStructClass +{ + GObjectClass parent; + + /* public */ + gint32 (*read) (ThriftStruct *object, ThriftProtocol *protocol, + GError **error); + gint32 (*write) (ThriftStruct *object, ThriftProtocol *protocol, + GError **error); +}; + +GType thrift_struct_get_type (void); + +gint32 thrift_struct_read (ThriftStruct *object, ThriftProtocol *protocol, + GError **error); + +gint32 thrift_struct_write (ThriftStruct *object, ThriftProtocol *protocol, + GError **error); +G_END_DECLS + +#endif diff --git a/vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/transport/thrift_buffered_transport.c b/vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/transport/thrift_buffered_transport.c new file mode 100644 index 000000000..ede28cffb --- /dev/null +++ b/vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/transport/thrift_buffered_transport.c @@ -0,0 +1,391 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT 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 +#include +#include +#include +#include +#include + +#include +#include +#include + +/* object properties */ +enum _ThriftBufferedTransportProperties +{ + PROP_0, + PROP_THRIFT_BUFFERED_TRANSPORT_TRANSPORT, + PROP_THRIFT_BUFFERED_TRANSPORT_READ_BUFFER_SIZE, + PROP_THRIFT_BUFFERED_TRANSPORT_WRITE_BUFFER_SIZE +}; + +G_DEFINE_TYPE(ThriftBufferedTransport, thrift_buffered_transport, THRIFT_TYPE_TRANSPORT) + +/* implements thrift_transport_is_open */ +gboolean +thrift_buffered_transport_is_open (ThriftTransport *transport) +{ + ThriftBufferedTransport *t = THRIFT_BUFFERED_TRANSPORT (transport); + return THRIFT_TRANSPORT_GET_CLASS (t->transport)->is_open (t->transport); +} + +/* overrides thrift_transport_peek */ +gboolean +thrift_buffered_transport_peek (ThriftTransport *transport, GError **error) +{ + ThriftBufferedTransport *t = THRIFT_BUFFERED_TRANSPORT (transport); + return (t->r_buf->len > 0) || thrift_transport_peek (t->transport, error); +} + +/* implements thrift_transport_open */ +gboolean +thrift_buffered_transport_open (ThriftTransport *transport, GError **error) +{ + ThriftBufferedTransport *t = THRIFT_BUFFERED_TRANSPORT (transport); + return THRIFT_TRANSPORT_GET_CLASS (t->transport)->open (t->transport, error); +} + +/* implements thrift_transport_close */ +gboolean +thrift_buffered_transport_close (ThriftTransport *transport, GError **error) +{ + ThriftBufferedTransport *t = THRIFT_BUFFERED_TRANSPORT (transport); + return THRIFT_TRANSPORT_GET_CLASS (t->transport)->close (t->transport, error); +} + +/* the actual read is "slow" because it calls the underlying transport */ +gint32 +thrift_buffered_transport_read_slow (ThriftTransport *transport, gpointer buf, + guint32 len, GError **error) +{ + ThriftBufferedTransport *t = THRIFT_BUFFERED_TRANSPORT (transport); + gint ret = 0; + guint32 want = len; + guint32 got = 0; + guchar *tmpdata = g_alloca (len); + guint32 have = t->r_buf->len; + + /* we shouldn't hit this unless the buffer doesn't have enough to read */ + assert (t->r_buf->len < want); + + /* first copy what we have in our buffer. */ + if (have > 0) + { + memcpy (buf, t->r_buf, t->r_buf->len); + want -= t->r_buf->len; + t->r_buf = g_byte_array_remove_range (t->r_buf, 0, t->r_buf->len); + } + + /* if the buffer is still smaller than what we want to read, then just + * read it directly. otherwise, fill the buffer and then give out + * enough to satisfy the read. */ + if (t->r_buf_size < want) + { + if ((ret = THRIFT_TRANSPORT_GET_CLASS (t->transport)->read (t->transport, + tmpdata, + want, + error)) < 0) { + return ret; + } + got += ret; + + /* copy the data starting from where we left off */ + memcpy ((guint8 *)buf + have, tmpdata, got); + return got + have; + } else { + guint32 give; + + if ((ret = THRIFT_TRANSPORT_GET_CLASS (t->transport)->read (t->transport, + tmpdata, + want, + error)) < 0) { + return ret; + } + got += ret; + t->r_buf = g_byte_array_append (t->r_buf, tmpdata, got); + + /* hand over what we have up to what the caller wants */ + give = want < t->r_buf->len ? want : t->r_buf->len; + + + memcpy ((guint8 *)buf + len - want, t->r_buf->data, give); + t->r_buf = g_byte_array_remove_range (t->r_buf, 0, give); + want -= give; + + return (len - want); + } +} + +/* implements thrift_transport_read */ +gint32 +thrift_buffered_transport_read (ThriftTransport *transport, gpointer buf, + guint32 len, GError **error) +{ + ThriftBufferedTransport *t = THRIFT_BUFFERED_TRANSPORT (transport); + + /* if we have enough buffer data to fulfill the read, just use + * a memcpy */ + if (len <= t->r_buf->len) + { + memcpy (buf, t->r_buf->data, len); + g_byte_array_remove_range (t->r_buf, 0, len); + return len; + } + + return thrift_buffered_transport_read_slow (transport, buf, len, error); +} + +/* implements thrift_transport_read_end + * called when write is complete. nothing to do on our end. */ +gboolean +thrift_buffered_transport_read_end (ThriftTransport *transport, GError **error) +{ + /* satisfy -Wall */ + THRIFT_UNUSED_VAR (transport); + THRIFT_UNUSED_VAR (error); + return TRUE; +} + +gboolean +thrift_buffered_transport_write_slow (ThriftTransport *transport, gpointer buf, + guint32 len, GError **error) +{ + ThriftBufferedTransport *t = THRIFT_BUFFERED_TRANSPORT (transport); + guint32 have_bytes = t->w_buf->len; + guint32 space = t->w_buf_size - t->w_buf->len; + + /* we need two syscalls because the buffered data plus the buffer itself + * is too big. */ + if ((have_bytes + len >= 2*t->w_buf_size) || (have_bytes == 0)) + { + if (have_bytes > 0) + { + if (!THRIFT_TRANSPORT_GET_CLASS (t->transport)->write (t->transport, + t->w_buf->data, + have_bytes, + error)) { + return FALSE; + } + t->w_buf = g_byte_array_remove_range (t->w_buf, 0, have_bytes); + } + if (!THRIFT_TRANSPORT_GET_CLASS (t->transport)->write (t->transport, + buf, len, error)) { + return FALSE; + } + return TRUE; + } + + t->w_buf = g_byte_array_append (t->w_buf, buf, space); + if (!THRIFT_TRANSPORT_GET_CLASS (t->transport)->write (t->transport, + t->w_buf->data, + t->w_buf->len, + error)) { + return FALSE; + } + + t->w_buf = g_byte_array_remove_range (t->w_buf, 0, t->w_buf->len); + t->w_buf = g_byte_array_append (t->w_buf, (guint8 *)buf + space, len-space); + + return TRUE; +} + +/* implements thrift_transport_write */ +gboolean +thrift_buffered_transport_write (ThriftTransport *transport, + const gpointer buf, + const guint32 len, GError **error) +{ + ThriftBufferedTransport *t = THRIFT_BUFFERED_TRANSPORT (transport); + + /* the length of the current buffer plus the length of the data being read */ + if (t->w_buf->len + len <= t->w_buf_size) + { + t->w_buf = g_byte_array_append (t->w_buf, buf, len); + return len; + } + + return thrift_buffered_transport_write_slow (transport, buf, len, error); +} + +/* implements thrift_transport_write_end + * called when write is complete. nothing to do on our end. */ +gboolean +thrift_buffered_transport_write_end (ThriftTransport *transport, GError **error) +{ + /* satisfy -Wall */ + THRIFT_UNUSED_VAR (transport); + THRIFT_UNUSED_VAR (error); + return TRUE; +} + +/* implements thrift_transport_flush */ +gboolean +thrift_buffered_transport_flush (ThriftTransport *transport, GError **error) +{ + ThriftBufferedTransport *t = THRIFT_BUFFERED_TRANSPORT (transport); + + if (t->w_buf != NULL && t->w_buf->len > 0) + { + /* write the buffer and then empty it */ + if (!THRIFT_TRANSPORT_GET_CLASS (t->transport)->write (t->transport, + t->w_buf->data, + t->w_buf->len, + error)) { + return FALSE; + } + t->w_buf = g_byte_array_remove_range (t->w_buf, 0, t->w_buf->len); + } + THRIFT_TRANSPORT_GET_CLASS (t->transport)->flush (t->transport, + error); + + return TRUE; +} + +/* initializes the instance */ +static void +thrift_buffered_transport_init (ThriftBufferedTransport *transport) +{ + transport->transport = NULL; + transport->r_buf = g_byte_array_new (); + transport->w_buf = g_byte_array_new (); +} + +/* destructor */ +static void +thrift_buffered_transport_finalize (GObject *object) +{ + ThriftBufferedTransport *transport = THRIFT_BUFFERED_TRANSPORT (object); + + if (transport->r_buf != NULL) + { + g_byte_array_free (transport->r_buf, TRUE); + } + transport->r_buf = NULL; + + if (transport->w_buf != NULL) + { + g_byte_array_free (transport->w_buf, TRUE); + } + transport->w_buf = NULL; +} + +/* property accessor */ +void +thrift_buffered_transport_get_property (GObject *object, guint property_id, + GValue *value, GParamSpec *pspec) +{ + ThriftBufferedTransport *transport = THRIFT_BUFFERED_TRANSPORT (object); + + THRIFT_UNUSED_VAR (pspec); + + switch (property_id) + { + case PROP_THRIFT_BUFFERED_TRANSPORT_TRANSPORT: + g_value_set_object (value, transport->transport); + break; + case PROP_THRIFT_BUFFERED_TRANSPORT_READ_BUFFER_SIZE: + g_value_set_uint (value, transport->r_buf_size); + break; + case PROP_THRIFT_BUFFERED_TRANSPORT_WRITE_BUFFER_SIZE: + g_value_set_uint (value, transport->w_buf_size); + break; + } +} + +/* property mutator */ +void +thrift_buffered_transport_set_property (GObject *object, guint property_id, + const GValue *value, GParamSpec *pspec) +{ + ThriftBufferedTransport *transport = THRIFT_BUFFERED_TRANSPORT (object); + + THRIFT_UNUSED_VAR (pspec); + + switch (property_id) + { + case PROP_THRIFT_BUFFERED_TRANSPORT_TRANSPORT: + transport->transport = g_value_get_object (value); + break; + case PROP_THRIFT_BUFFERED_TRANSPORT_READ_BUFFER_SIZE: + transport->r_buf_size = g_value_get_uint (value); + break; + case PROP_THRIFT_BUFFERED_TRANSPORT_WRITE_BUFFER_SIZE: + transport->w_buf_size = g_value_get_uint (value); + break; + } +} + +/* initializes the class */ +static void +thrift_buffered_transport_class_init (ThriftBufferedTransportClass *cls) +{ + ThriftTransportClass *ttc = THRIFT_TRANSPORT_CLASS (cls); + GObjectClass *gobject_class = G_OBJECT_CLASS (cls); + GParamSpec *param_spec = NULL; + + /* setup accessors and mutators */ + gobject_class->get_property = thrift_buffered_transport_get_property; + gobject_class->set_property = thrift_buffered_transport_set_property; + + param_spec = g_param_spec_object ("transport", "transport (construct)", + "Thrift transport", + THRIFT_TYPE_TRANSPORT, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY); + g_object_class_install_property (gobject_class, + PROP_THRIFT_BUFFERED_TRANSPORT_TRANSPORT, + param_spec); + + param_spec = g_param_spec_uint ("r_buf_size", + "read buffer size (construct)", + "Set the read buffer size", + 0, /* min */ + 1048576, /* max, 1024*1024 */ + 512, /* default value */ + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_READWRITE); + g_object_class_install_property (gobject_class, + PROP_THRIFT_BUFFERED_TRANSPORT_READ_BUFFER_SIZE, + param_spec); + + param_spec = g_param_spec_uint ("w_buf_size", + "write buffer size (construct)", + "Set the write buffer size", + 0, /* min */ + 1048576, /* max, 1024*1024 */ + 512, /* default value */ + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_READWRITE); + g_object_class_install_property (gobject_class, + PROP_THRIFT_BUFFERED_TRANSPORT_WRITE_BUFFER_SIZE, + param_spec); + + + gobject_class->finalize = thrift_buffered_transport_finalize; + ttc->is_open = thrift_buffered_transport_is_open; + ttc->peek = thrift_buffered_transport_peek; + ttc->open = thrift_buffered_transport_open; + ttc->close = thrift_buffered_transport_close; + ttc->read = thrift_buffered_transport_read; + ttc->read_end = thrift_buffered_transport_read_end; + ttc->write = thrift_buffered_transport_write; + ttc->write_end = thrift_buffered_transport_write_end; + ttc->flush = thrift_buffered_transport_flush; +} diff --git a/vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/transport/thrift_buffered_transport.h b/vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/transport/thrift_buffered_transport.h new file mode 100644 index 000000000..837f46770 --- /dev/null +++ b/vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/transport/thrift_buffered_transport.h @@ -0,0 +1,77 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef _THRIFT_BUFFERED_TRANSPORT_H +#define _THRIFT_BUFFERED_TRANSPORT_H + +#include +#include + +#include + +G_BEGIN_DECLS + +/*! \file thrift_buffered_transport.h + * \brief Implementation of a Thrift buffered transport. Subclasses + * the ThriftTransport class. + */ + +/* type macros */ +#define THRIFT_TYPE_BUFFERED_TRANSPORT (thrift_buffered_transport_get_type ()) +#define THRIFT_BUFFERED_TRANSPORT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), THRIFT_TYPE_BUFFERED_TRANSPORT, ThriftBufferedTransport)) +#define THRIFT_IS_BUFFERED_TRANSPORT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), THRIFT_TYPE_BUFFERED_TRANSPORT)) +#define THRIFT_BUFFERED_TRANSPORT_CLASS(c) (G_TYPE_CHECK_CLASS_CAST ((c), THRIFT_TYPE_BUFFERED_TRANSPORT, ThriftBufferedTransportClass)) +#define THRIFT_IS_BUFFERED_TRANSPORT_CLASS(c) (G_TYPE_CHECK_CLASS_TYPE ((c), THRIFT_TYPE_BUFFERED_TRANSPORT) +#define THRIFT_BUFFERED_TRANSPORT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), THRIFT_TYPE_BUFFERED_TRANSPORT, ThriftBufferedTransportClass)) + +typedef struct _ThriftBufferedTransport ThriftBufferedTransport; + +/*! + * ThriftBufferedTransport instance. + */ +struct _ThriftBufferedTransport +{ + ThriftTransport parent; + + /* protected */ + ThriftTransport *transport; + + /* private */ + GByteArray *r_buf; + GByteArray *w_buf; + guint32 r_buf_size; + guint32 w_buf_size; +}; + +typedef struct _ThriftBufferedTransportClass ThriftBufferedTransportClass; + +/*! + * ThriftBufferedTransport class. + */ +struct _ThriftBufferedTransportClass +{ + ThriftTransportClass parent; +}; + +/* used by THRIFT_TYPE_BUFFERED_TRANSPORT */ +GType thrift_buffered_transport_get_type (void); + +G_END_DECLS + +#endif diff --git a/vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/transport/thrift_buffered_transport_factory.c b/vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/transport/thrift_buffered_transport_factory.c new file mode 100644 index 000000000..86050b691 --- /dev/null +++ b/vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/transport/thrift_buffered_transport_factory.c @@ -0,0 +1,55 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include +#include +#include + +G_DEFINE_TYPE (ThriftBufferedTransportFactory, + thrift_buffered_transport_factory, + THRIFT_TYPE_TRANSPORT_FACTORY) + +/* Wraps a transport with a ThriftBufferedTransport. */ +ThriftTransport * +thrift_buffered_transport_factory_get_transport (ThriftTransportFactory *factory, + ThriftTransport *transport) +{ + THRIFT_UNUSED_VAR (factory); + + return THRIFT_TRANSPORT (g_object_new (THRIFT_TYPE_BUFFERED_TRANSPORT, + "transport", transport, + NULL)); +} + +static void +thrift_buffered_transport_factory_init (ThriftBufferedTransportFactory *self) +{ + THRIFT_UNUSED_VAR (self); +} + +static void +thrift_buffered_transport_factory_class_init (ThriftBufferedTransportFactoryClass *klass) +{ + ThriftTransportFactoryClass *base_class = + THRIFT_TRANSPORT_FACTORY_CLASS (klass); + + base_class->get_transport = + klass->get_transport = + thrift_buffered_transport_factory_get_transport; +} diff --git a/vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/transport/thrift_buffered_transport_factory.h b/vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/transport/thrift_buffered_transport_factory.h new file mode 100644 index 000000000..d43f4e4ad --- /dev/null +++ b/vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/transport/thrift_buffered_transport_factory.h @@ -0,0 +1,86 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef _THRIFT_BUFFERED_TRANSPORT_FACTORY_H +#define _THRIFT_BUFFERED_TRANSPORT_FACTORY_H + +#include + +#include +#include + +G_BEGIN_DECLS + +/*! \file thrift_buffered_transport_factory.h + * \brief Wraps a transport with a ThriftBufferedTransport. + */ + +/* type macros */ +#define THRIFT_TYPE_BUFFERED_TRANSPORT_FACTORY \ + (thrift_buffered_transport_factory_get_type ()) +#define THRIFT_BUFFERED_TRANSPORT_FACTORY(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), \ + THRIFT_TYPE_BUFFERED_TRANSPORT_FACTORY, \ + ThriftBufferedTransportFactory)) +#define THRIFT_IS_BUFFERED_TRANSPORT_FACTORY(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \ + THRIFT_TYPE_BUFFERED_TRANSPORT_FACTORY)) +#define THRIFT_BUFFERED_TRANSPORT_FACTORY_CLASS(c) \ + (G_TYPE_CHECK_CLASS_CAST ((c), \ + THRIFT_TYPE_BUFFERED_TRANSPORT_FACTORY, \ + ThriftBufferedTransportFactoryClass)) +#define THRIFT_IS_BUFFERED_TRANSPORT_FACTORY_CLASS(c) \ + (G_TYPE_CHECK_CLASS_TYPE ((c), \ + THRIFT_TYPE_BUFFERED_TRANSPORT_FACTORY)) +#define THRIFT_BUFFERED_TRANSPORT_FACTORY_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), \ + THRIFT_TYPE_BUFFERED_TRANSPORT_FACTORY, \ + ThriftBufferedTransportFactoryClass)) + +typedef struct _ThriftBufferedTransportFactory ThriftBufferedTransportFactory; + +/* Thrift Buffered-Transport Factory instance */ +struct _ThriftBufferedTransportFactory +{ + ThriftTransportFactory parent; +}; + +typedef struct _ThriftBufferedTransportFactoryClass ThriftBufferedTransportFactoryClass; + +/* Thrift Buffered-Transport Factory class */ +struct _ThriftBufferedTransportFactoryClass +{ + ThriftTransportFactoryClass parent; + + /* vtable */ + ThriftTransport *(*get_transport) (ThriftTransportFactory *factory, + ThriftTransport *transport); +}; + +/* used by THRIFT_TYPE_BUFFERED_TRANSPORT_FACTORY */ +GType thrift_buffered_transport_factory_get_type (void); + +/* virtual public methods */ +ThriftTransport * +thrift_buffered_transport_factory_get_transport (ThriftTransportFactory *factory, + ThriftTransport *transport); + +G_END_DECLS + +#endif /* _THRIFT_BUFFERED_TRANSPORT_FACTORY_H */ diff --git a/vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/transport/thrift_fd_transport.c b/vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/transport/thrift_fd_transport.c new file mode 100644 index 000000000..14abff7a4 --- /dev/null +++ b/vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/transport/thrift_fd_transport.c @@ -0,0 +1,265 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT 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 +#include +#include +#include + +#include +#include + +#include +#include +#include + +/* object properties */ +enum _ThriftFDTransportProperties +{ + PROP_0, + PROP_THRIFT_FD_TRANSPORT_FD +}; + +G_DEFINE_TYPE (ThriftFDTransport, thrift_fd_transport, THRIFT_TYPE_TRANSPORT) + +/* implements thrift_transport_is_open */ +gboolean +thrift_fd_transport_is_open (ThriftTransport *transport) +{ + ThriftFDTransport *t; + t = THRIFT_FD_TRANSPORT (transport); + return t->fd >= 0 && ! (fcntl (t->fd, F_GETFL) == -1 && errno == EBADF); +} + +/* implements thrift_transport_open */ +gboolean +thrift_fd_transport_open (ThriftTransport *transport, GError **error) +{ + THRIFT_UNUSED_VAR (error); + return thrift_fd_transport_is_open (transport); +} + +/* implements thrift_transport_close */ +gboolean +thrift_fd_transport_close (ThriftTransport *transport, GError **error) +{ + ThriftFDTransport *t; + t = THRIFT_FD_TRANSPORT (transport); + +#if GLIB_CHECK_VERSION (2, 36, 0) + return g_close (t->fd, error); +#else + if (close (t->fd) == 0) { + g_clear_error (error); + return TRUE; + } else { + g_set_error (error, + THRIFT_TRANSPORT_ERROR, + THRIFT_TRANSPORT_ERROR_CLOSE, + strerror (errno)); + return FALSE; + } +#endif +} + +/* implements thrift_transport_read */ +gint32 +thrift_fd_transport_read (ThriftTransport *transport, gpointer buf, + guint32 len, GError **error) +{ + ThriftFDTransport *t; + ssize_t n; + + t = THRIFT_FD_TRANSPORT (transport); + n = read (t->fd, (guint8 *) buf, len); + if (n == -1) { + g_set_error (error, + THRIFT_TRANSPORT_ERROR, + THRIFT_TRANSPORT_ERROR_RECEIVE, + "Failed to read from fd: %s", + strerror (errno)); + return -1; + } + return n; +} + +/* implements thrift_transport_read_end + * called when write is complete. nothing to do on our end. */ +gboolean +thrift_fd_transport_read_end (ThriftTransport *transport, GError **error) +{ + /* satisfy -Wall */ + THRIFT_UNUSED_VAR (transport); + THRIFT_UNUSED_VAR (error); + return TRUE; +} + +/* implements thrift_transport_write */ +gboolean +thrift_fd_transport_write (ThriftTransport *transport, + const gpointer buf, + const guint32 len, GError **error) +{ + ThriftFDTransport *t; + guint8 *_buf; + guint32 _len; + ssize_t n; + + t = THRIFT_FD_TRANSPORT (transport); + _buf = (guint8 *) buf; + _len = len; + while (_len > 0) { + n = write (t->fd, _buf, _len); + if (n == -1) { + g_set_error (error, + THRIFT_TRANSPORT_ERROR, + THRIFT_TRANSPORT_ERROR_SEND, + "Failed to write from fd: %s", + strerror (errno)); + return FALSE; + } else { + _buf += n; + _len -= n; + } + } + return TRUE; +} + +/* implements thrift_transport_write_end + * called when write is complete. nothing to do on our end. */ +gboolean +thrift_fd_transport_write_end (ThriftTransport *transport, GError **error) +{ + THRIFT_UNUSED_VAR (transport); + THRIFT_UNUSED_VAR (error); + return TRUE; +} + +/* implements thrift_transport_flush */ +gboolean +thrift_fd_transport_flush (ThriftTransport *transport, GError **error) +{ + ThriftFDTransport *t; + t = THRIFT_FD_TRANSPORT (transport); + if (fsync (t->fd) == -1) { + g_set_error (error, + THRIFT_TRANSPORT_ERROR, + THRIFT_TRANSPORT_ERROR_UNKNOWN, + "Failed to flush fd: %s", + strerror (errno)); + return FALSE; + } else { + return TRUE; + } +} + +/* initializes the instance */ +static void +thrift_fd_transport_init (ThriftFDTransport *transport) +{ + transport->fd = -1; +} + +/* destructor */ +static void +thrift_fd_transport_finalize (GObject *object) +{ + THRIFT_UNUSED_VAR (object); +} + +/* property accessor */ +void +thrift_fd_transport_get_property (GObject *object, guint property_id, + GValue *value, GParamSpec *pspec) +{ + ThriftFDTransport *t; + + THRIFT_UNUSED_VAR (pspec); + + t = THRIFT_FD_TRANSPORT (object); + + switch (property_id) { + case PROP_THRIFT_FD_TRANSPORT_FD: + g_value_set_int (value, t->fd); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +/* property mutator */ +void +thrift_fd_transport_set_property (GObject *object, guint property_id, + const GValue *value, GParamSpec *pspec) +{ + ThriftFDTransport *t; + + THRIFT_UNUSED_VAR (pspec); + + t = THRIFT_FD_TRANSPORT (object); + + switch (property_id) { + case PROP_THRIFT_FD_TRANSPORT_FD: + t->fd = g_value_get_int (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +/* initializes the class */ +static void +thrift_fd_transport_class_init (ThriftFDTransportClass *cls) +{ + ThriftTransportClass *ttc; + GObjectClass *gobject_class; + GParamSpec *param_spec; + + ttc = THRIFT_TRANSPORT_CLASS (cls); + gobject_class = G_OBJECT_CLASS (cls); + param_spec = NULL; + + /* setup accessors and mutators */ + gobject_class->get_property = thrift_fd_transport_get_property; + gobject_class->set_property = thrift_fd_transport_set_property; + + param_spec = g_param_spec_int ("fd", + "file descriptor (construct)", + "Set the file descriptor", + INT_MIN, /* min */ + INT_MAX, /* max, 1024*1024 */ + -1, /* default value */ + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_READWRITE); + g_object_class_install_property (gobject_class, + PROP_THRIFT_FD_TRANSPORT_FD, + param_spec); + + gobject_class->finalize = thrift_fd_transport_finalize; + ttc->is_open = thrift_fd_transport_is_open; + ttc->open = thrift_fd_transport_open; + ttc->close = thrift_fd_transport_close; + ttc->read = thrift_fd_transport_read; + ttc->read_end = thrift_fd_transport_read_end; + ttc->write = thrift_fd_transport_write; + ttc->write_end = thrift_fd_transport_write_end; + ttc->flush = thrift_fd_transport_flush; +} diff --git a/vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/transport/thrift_fd_transport.h b/vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/transport/thrift_fd_transport.h new file mode 100644 index 000000000..0e6d5c4b3 --- /dev/null +++ b/vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/transport/thrift_fd_transport.h @@ -0,0 +1,74 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef _THRIFT_FD_TRANSPORT_H +#define _THRIFT_FD_TRANSPORT_H + +#include + +#include "thrift_transport.h" + +G_BEGIN_DECLS + +/*! \file thrift_fd_transport.h + * \brief Class for Thrift file descriptor transports. + */ + +/* type macros */ +#define THRIFT_TYPE_FD_TRANSPORT (thrift_fd_transport_get_type ()) +#define THRIFT_FD_TRANSPORT(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), THRIFT_TYPE_FD_TRANSPORT, \ + ThriftFDTransport)) +#define THRIFT_IS_FD_TRANSPORT(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), THRIFT_TYPE_FD_TRANSPORT)) +#define THRIFT_FD_TRANSPORT_CLASS(c) \ + (G_TYPE_CHECK_CLASS_CAST ((c), THRIFT_TYPE_FD_TRANSPORT, \ + ThriftFDTransportClass)) +#define THRIFT_IS_FD_TRANSPORT_CLASS(c) \ + (G_TYPE_CHECK_CLASS_TYPE ((c), THRIFT_TYPE_FD_TRANSPORT)) +#define THRIFT_FD_TRANSPORT_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), THRIFT_TYPE_FD_TRANSPORT, \ + ThriftFDTransportClass)) + +typedef struct _ThriftFDTransport ThriftFDTransport; + +struct _ThriftFDTransport +{ + ThriftTransport parent; + + /* protected */ + gint fd; +}; + +typedef struct _ThriftFDTransportClass ThriftFDTransportClass; + +/*! + * Thrift Transport class + */ +struct _ThriftFDTransportClass +{ + ThriftTransportClass parent; +}; + +/* used by THRIFT_TYPE_FD_TRANSPORT */ +GType thrift_fd_transport_get_type (void); + +G_END_DECLS + +#endif /* _THRIFT_FD_TRANSPORT_H */ diff --git a/vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/transport/thrift_framed_transport.c b/vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/transport/thrift_framed_transport.c new file mode 100644 index 000000000..4c8b71fb6 --- /dev/null +++ b/vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/transport/thrift_framed_transport.c @@ -0,0 +1,384 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT 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 +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +/* object properties */ +enum _ThriftFramedTransportProperties +{ + PROP_0, + PROP_THRIFT_FRAMED_TRANSPORT_TRANSPORT, + PROP_THRIFT_FRAMED_TRANSPORT_READ_BUFFER_SIZE, + PROP_THRIFT_FRAMED_TRANSPORT_WRITE_BUFFER_SIZE +}; + +G_DEFINE_TYPE(ThriftFramedTransport, thrift_framed_transport, THRIFT_TYPE_TRANSPORT) + +/* implements thrift_transport_is_open */ +gboolean +thrift_framed_transport_is_open (ThriftTransport *transport) +{ + ThriftFramedTransport *t = THRIFT_FRAMED_TRANSPORT (transport); + return THRIFT_TRANSPORT_GET_CLASS (t->transport)->is_open (t->transport); +} + +/* overrides thrift_transport_peek */ +gboolean +thrift_framed_transport_peek (ThriftTransport *transport, GError **error) +{ + ThriftFramedTransport *t = THRIFT_FRAMED_TRANSPORT (transport); + return (t->r_buf->len > 0) || thrift_transport_peek (t->transport, error); +} + +/* implements thrift_transport_open */ +gboolean +thrift_framed_transport_open (ThriftTransport *transport, GError **error) +{ + ThriftFramedTransport *t = THRIFT_FRAMED_TRANSPORT (transport); + return THRIFT_TRANSPORT_GET_CLASS (t->transport)->open (t->transport, error); +} + +/* implements thrift_transport_close */ +gboolean +thrift_framed_transport_close (ThriftTransport *transport, GError **error) +{ + ThriftFramedTransport *t = THRIFT_FRAMED_TRANSPORT (transport); + return THRIFT_TRANSPORT_GET_CLASS (t->transport)->close (t->transport, error); +} + +/* reads a frame and puts it into the buffer */ +gboolean +thrift_framed_transport_read_frame (ThriftTransport *transport, + GError **error) +{ + ThriftFramedTransport *t = THRIFT_FRAMED_TRANSPORT (transport); + guint32 sz; + gint32 bytes; + gboolean result = FALSE; + + /* read the size */ + if (thrift_transport_read (t->transport, + &sz, + sizeof (sz), + error) == sizeof (sz)) + { + guchar *tmpdata; + + sz = ntohl (sz); + + /* create a buffer to hold the data and read that much data */ + tmpdata = g_alloca (sz); + bytes = thrift_transport_read (t->transport, tmpdata, sz, error); + + if (bytes > 0 && (error == NULL || *error == NULL)) + { + /* add the data to the buffer */ + g_byte_array_append (t->r_buf, tmpdata, bytes); + + result = TRUE; + } + } + + return result; +} + +/* the actual read is "slow" because it calls the underlying transport */ +gint32 +thrift_framed_transport_read_slow (ThriftTransport *transport, gpointer buf, + guint32 len, GError **error) +{ + ThriftFramedTransport *t = THRIFT_FRAMED_TRANSPORT (transport); + guint32 want = len; + guint32 have = t->r_buf->len; + gint32 result = -1; + + /* we shouldn't hit this unless the buffer doesn't have enough to read */ + assert (t->r_buf->len < want); + + /* first copy what we have in our buffer, if there is anything left */ + if (have > 0) + { + memcpy (buf, t->r_buf, t->r_buf->len); + want -= t->r_buf->len; + t->r_buf = g_byte_array_remove_range (t->r_buf, 0, t->r_buf->len); + } + + /* read a frame of input and buffer it */ + if (thrift_framed_transport_read_frame (transport, error) == TRUE) + { + /* hand over what we have up to what the caller wants */ + guint32 give = want < t->r_buf->len ? want : t->r_buf->len; + + /* copy the data into the buffer */ + memcpy ((guint8 *)buf + len - want, t->r_buf->data, give); + t->r_buf = g_byte_array_remove_range (t->r_buf, 0, give); + want -= give; + + result = len - want; + } + + return result; +} + +/* implements thrift_transport_read */ +gint32 +thrift_framed_transport_read (ThriftTransport *transport, gpointer buf, + guint32 len, GError **error) +{ + ThriftFramedTransport *t = THRIFT_FRAMED_TRANSPORT (transport); + + /* if we have enough buffer data to fulfill the read, just use + * a memcpy from the buffer */ + if (len <= t->r_buf->len) + { + memcpy (buf, t->r_buf->data, len); + g_byte_array_remove_range (t->r_buf, 0, len); + return len; + } + + return thrift_framed_transport_read_slow (transport, buf, len, error); +} + +/* implements thrift_transport_read_end + * called when read is complete. nothing to do on our end. */ +gboolean +thrift_framed_transport_read_end (ThriftTransport *transport, GError **error) +{ + /* satisfy -Wall */ + THRIFT_UNUSED_VAR (transport); + THRIFT_UNUSED_VAR (error); + return TRUE; +} + +gboolean +thrift_framed_transport_write_slow (ThriftTransport *transport, gpointer buf, + guint32 len, GError **error) +{ + ThriftFramedTransport *t = THRIFT_FRAMED_TRANSPORT (transport); + + THRIFT_UNUSED_VAR (error); + + /* append the data to the buffer and we're done */ + g_byte_array_append (t->w_buf, buf, len); + + return TRUE; +} + +/* implements thrift_transport_write */ +gboolean +thrift_framed_transport_write (ThriftTransport *transport, + const gpointer buf, + const guint32 len, GError **error) +{ + ThriftFramedTransport *t = THRIFT_FRAMED_TRANSPORT (transport); + + /* the length of the current buffer plus the length of the data being read */ + if (t->w_buf->len + len <= t->w_buf_size) + { + t->w_buf = g_byte_array_append (t->w_buf, buf, len); + return TRUE; + } + + return thrift_framed_transport_write_slow (transport, buf, len, error); +} + +/* implements thrift_transport_write_end + * called when write is complete. nothing to do on our end. */ +gboolean +thrift_framed_transport_write_end (ThriftTransport *transport, GError **error) +{ + /* satisfy -Wall */ + THRIFT_UNUSED_VAR (transport); + THRIFT_UNUSED_VAR (error); + return TRUE; +} + +/* implements thrift_transport_flush */ +gboolean +thrift_framed_transport_flush (ThriftTransport *transport, GError **error) +{ + ThriftFramedTransport *t = THRIFT_FRAMED_TRANSPORT (transport); + gint32 sz_hbo, sz_nbo; + guchar *tmpdata; + + /* get the size of the frame in host and network byte order */ + sz_hbo = t->w_buf->len + sizeof(sz_nbo); + sz_nbo = (gint32) htonl ((guint32) t->w_buf->len); + + /* copy the size of the frame and then the frame itself */ + tmpdata = g_alloca (sz_hbo); + memcpy (tmpdata, (guint8 *) &sz_nbo, sizeof (sz_nbo)); + + if (t->w_buf->len > 0) + { + memcpy (tmpdata + sizeof (sz_nbo), t->w_buf->data, t->w_buf->len); + t->w_buf = g_byte_array_remove_range (t->w_buf, 0, t->w_buf->len); + } + + /* write the buffer and then empty it */ + THRIFT_TRANSPORT_GET_CLASS (t->transport)->write (t->transport, + tmpdata, sz_hbo, + error); + + THRIFT_TRANSPORT_GET_CLASS (t->transport)->flush (t->transport, + error); + + return TRUE; +} + +/* initializes the instance */ +static void +thrift_framed_transport_init (ThriftFramedTransport *transport) +{ + transport->transport = NULL; + transport->r_buf = g_byte_array_new (); + transport->w_buf = g_byte_array_new (); +} + +/* destructor */ +static void +thrift_framed_transport_finalize (GObject *object) +{ + ThriftFramedTransport *transport = THRIFT_FRAMED_TRANSPORT (object); + + if (transport->r_buf != NULL) + { + g_byte_array_free (transport->r_buf, TRUE); + } + transport->r_buf = NULL; + + if (transport->w_buf != NULL) + { + g_byte_array_free (transport->w_buf, TRUE); + } + transport->w_buf = NULL; +} + +/* property accessor */ +void +thrift_framed_transport_get_property (GObject *object, guint property_id, + GValue *value, GParamSpec *pspec) +{ + ThriftFramedTransport *transport = THRIFT_FRAMED_TRANSPORT (object); + + THRIFT_UNUSED_VAR (pspec); + + switch (property_id) + { + case PROP_THRIFT_FRAMED_TRANSPORT_TRANSPORT: + g_value_set_object (value, transport->transport); + break; + case PROP_THRIFT_FRAMED_TRANSPORT_READ_BUFFER_SIZE: + g_value_set_uint (value, transport->r_buf_size); + break; + case PROP_THRIFT_FRAMED_TRANSPORT_WRITE_BUFFER_SIZE: + g_value_set_uint (value, transport->w_buf_size); + break; + } +} + +/* property mutator */ +void +thrift_framed_transport_set_property (GObject *object, guint property_id, + const GValue *value, GParamSpec *pspec) +{ + ThriftFramedTransport *transport = THRIFT_FRAMED_TRANSPORT (object); + + THRIFT_UNUSED_VAR (pspec); + + switch (property_id) + { + case PROP_THRIFT_FRAMED_TRANSPORT_TRANSPORT: + transport->transport = g_value_get_object (value); + break; + case PROP_THRIFT_FRAMED_TRANSPORT_READ_BUFFER_SIZE: + transport->r_buf_size = g_value_get_uint (value); + break; + case PROP_THRIFT_FRAMED_TRANSPORT_WRITE_BUFFER_SIZE: + transport->w_buf_size = g_value_get_uint (value); + break; + } +} + +/* initializes the class */ +static void +thrift_framed_transport_class_init (ThriftFramedTransportClass *cls) +{ + ThriftTransportClass *ttc = THRIFT_TRANSPORT_CLASS (cls); + GObjectClass *gobject_class = G_OBJECT_CLASS (cls); + GParamSpec *param_spec = NULL; + + /* setup accessors and mutators */ + gobject_class->get_property = thrift_framed_transport_get_property; + gobject_class->set_property = thrift_framed_transport_set_property; + + param_spec = g_param_spec_object ("transport", "transport (construct)", + "Thrift transport", + THRIFT_TYPE_TRANSPORT, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY); + g_object_class_install_property (gobject_class, + PROP_THRIFT_FRAMED_TRANSPORT_TRANSPORT, + param_spec); + + param_spec = g_param_spec_uint ("r_buf_size", + "read buffer size (construct)", + "Set the read buffer size", + 0, /* min */ + 1048576, /* max, 1024*1024 */ + 512, /* default value */ + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_READWRITE); + g_object_class_install_property (gobject_class, + PROP_THRIFT_FRAMED_TRANSPORT_READ_BUFFER_SIZE, + param_spec); + + param_spec = g_param_spec_uint ("w_buf_size", + "write buffer size (construct)", + "Set the write buffer size", + 0, /* min */ + 1048576, /* max, 1024*1024 */ + 512, /* default value */ + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_READWRITE); + g_object_class_install_property (gobject_class, + PROP_THRIFT_FRAMED_TRANSPORT_WRITE_BUFFER_SIZE, + param_spec); + + gobject_class->finalize = thrift_framed_transport_finalize; + ttc->is_open = thrift_framed_transport_is_open; + ttc->peek = thrift_framed_transport_peek; + ttc->open = thrift_framed_transport_open; + ttc->close = thrift_framed_transport_close; + ttc->read = thrift_framed_transport_read; + ttc->read_end = thrift_framed_transport_read_end; + ttc->write = thrift_framed_transport_write; + ttc->write_end = thrift_framed_transport_write_end; + ttc->flush = thrift_framed_transport_flush; +} diff --git a/vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/transport/thrift_framed_transport.h b/vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/transport/thrift_framed_transport.h new file mode 100644 index 000000000..95c012393 --- /dev/null +++ b/vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/transport/thrift_framed_transport.h @@ -0,0 +1,77 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef _THRIFT_FRAMED_TRANSPORT_H +#define _THRIFT_FRAMED_TRANSPORT_H + +#include +#include + +#include + +G_BEGIN_DECLS + +/*! \file thrift_framed_transport.h + * \brief Implementation of a Thrift framed transport. Subclasses + * the ThriftTransport class. + */ + +/* type macros */ +#define THRIFT_TYPE_FRAMED_TRANSPORT (thrift_framed_transport_get_type ()) +#define THRIFT_FRAMED_TRANSPORT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), THRIFT_TYPE_FRAMED_TRANSPORT, ThriftFramedTransport)) +#define THRIFT_IS_FRAMED_TRANSPORT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), THRIFT_TYPE_FRAMED_TRANSPORT)) +#define THRIFT_FRAMED_TRANSPORT_CLASS(c) (G_TYPE_CHECK_CLASS_CAST ((c), THRIFT_TYPE_FRAMED_TRANSPORT, ThriftFramedTransportClass)) +#define THRIFT_IS_FRAMED_TRANSPORT_CLASS(c) (G_TYPE_CHECK_CLASS_TYPE ((c), THRIFT_TYPE_FRAMED_TRANSPORT) +#define THRIFT_FRAMED_TRANSPORT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), THRIFT_TYPE_FRAMED_TRANSPORT, ThriftFramedTransportClass)) + +typedef struct _ThriftFramedTransport ThriftFramedTransport; + +/*! + * ThriftFramedTransport instance. + */ +struct _ThriftFramedTransport +{ + ThriftTransport parent; + + /* protected */ + ThriftTransport *transport; + + /* private */ + GByteArray *r_buf; + GByteArray *w_buf; + guint32 r_buf_size; + guint32 w_buf_size; +}; + +typedef struct _ThriftFramedTransportClass ThriftFramedTransportClass; + +/*! + * ThriftFramedTransport class. + */ +struct _ThriftFramedTransportClass +{ + ThriftTransportClass parent; +}; + +/* used by THRIFT_TYPE_FRAMED_TRANSPORT */ +GType thrift_framed_transport_get_type (void); + +G_END_DECLS + +#endif diff --git a/vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/transport/thrift_framed_transport_factory.c b/vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/transport/thrift_framed_transport_factory.c new file mode 100644 index 000000000..e68fe0a24 --- /dev/null +++ b/vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/transport/thrift_framed_transport_factory.c @@ -0,0 +1,55 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include +#include +#include + +G_DEFINE_TYPE (ThriftFramedTransportFactory, + thrift_framed_transport_factory, + THRIFT_TYPE_TRANSPORT_FACTORY) + +/* Wraps a transport with a ThriftFramedTransport. */ +ThriftTransport * +thrift_framed_transport_factory_get_transport (ThriftTransportFactory *factory, + ThriftTransport *transport) +{ + THRIFT_UNUSED_VAR (factory); + + return THRIFT_TRANSPORT (g_object_new (THRIFT_TYPE_FRAMED_TRANSPORT, + "transport", transport, + NULL)); +} + +static void +thrift_framed_transport_factory_init (ThriftFramedTransportFactory *self) +{ + THRIFT_UNUSED_VAR (self); +} + +static void +thrift_framed_transport_factory_class_init (ThriftFramedTransportFactoryClass *klass) +{ + ThriftTransportFactoryClass *base_class = + THRIFT_TRANSPORT_FACTORY_CLASS (klass); + + base_class->get_transport = + klass->get_transport = + thrift_framed_transport_factory_get_transport; +} diff --git a/vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/transport/thrift_framed_transport_factory.h b/vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/transport/thrift_framed_transport_factory.h new file mode 100644 index 000000000..c3e94962f --- /dev/null +++ b/vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/transport/thrift_framed_transport_factory.h @@ -0,0 +1,86 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef _THRIFT_FRAMED_TRANSPORT_FACTORY_H +#define _THRIFT_FRAMED_TRANSPORT_FACTORY_H + +#include + +#include +#include + +G_BEGIN_DECLS + +/*! \file thrift_framed_transport_factory.h + * \brief Wraps a transport with a ThriftFramedTransport. + */ + +/* type macros */ +#define THRIFT_TYPE_FRAMED_TRANSPORT_FACTORY \ + (thrift_framed_transport_factory_get_type ()) +#define THRIFT_FRAMED_TRANSPORT_FACTORY(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), \ + THRIFT_TYPE_FRAMED_TRANSPORT_FACTORY, \ + ThriftFramedTransportFactory)) +#define THRIFT_IS_FRAMED_TRANSPORT_FACTORY(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \ + THRIFT_TYPE_FRAMED_TRANSPORT_FACTORY)) +#define THRIFT_FRAMED_TRANSPORT_FACTORY_CLASS(c) \ + (G_TYPE_CHECK_CLASS_CAST ((c), \ + THRIFT_TYPE_FRAMED_TRANSPORT_FACTORY, \ + ThriftFramedTransportFactoryClass)) +#define THRIFT_IS_FRAMED_TRANSPORT_FACTORY_CLASS(c) \ + (G_TYPE_CHECK_CLASS_TYPE ((c), \ + THRIFT_TYPE_FRAMED_TRANSPORT_FACTORY)) +#define THRIFT_FRAMED_TRANSPORT_FACTORY_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), \ + THRIFT_TYPE_FRAMED_TRANSPORT_FACTORY, \ + ThriftFramedTransportFactoryClass)) + +typedef struct _ThriftFramedTransportFactory ThriftFramedTransportFactory; + +/* Thrift Framed-Transport Factory instance */ +struct _ThriftFramedTransportFactory +{ + ThriftTransportFactory parent; +}; + +typedef struct _ThriftFramedTransportFactoryClass ThriftFramedTransportFactoryClass; + +/* Thrift Framed-Transport Factory class */ +struct _ThriftFramedTransportFactoryClass +{ + ThriftTransportFactoryClass parent; + + /* vtable */ + ThriftTransport *(*get_transport) (ThriftTransportFactory *factory, + ThriftTransport *transport); +}; + +/* used by THRIFT_TYPE_FRAMED_TRANSPORT_FACTORY */ +GType thrift_framed_transport_factory_get_type (void); + +/* virtual public methods */ +ThriftTransport * +thrift_framed_transport_factory_get_transport (ThriftTransportFactory *factory, + ThriftTransport *transport); + +G_END_DECLS + +#endif /* _THRIFT_FRAMED_TRANSPORT_FACTORY_H */ diff --git a/vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/transport/thrift_memory_buffer.c b/vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/transport/thrift_memory_buffer.c new file mode 100644 index 000000000..b96db3593 --- /dev/null +++ b/vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/transport/thrift_memory_buffer.c @@ -0,0 +1,286 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT 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 +#include +#include +#include +#include +#include + +#include +#include +#include + +/* object properties */ +enum _ThriftMemoryBufferProperties +{ + PROP_0, + PROP_THRIFT_MEMORY_BUFFER_BUFFER_SIZE, + PROP_THRIFT_MEMORY_BUFFER_BUFFER, + PROP_THRIFT_MEMORY_BUFFER_OWNER +}; + +G_DEFINE_TYPE(ThriftMemoryBuffer, thrift_memory_buffer, THRIFT_TYPE_TRANSPORT) + +/* implements thrift_transport_is_open */ +gboolean +thrift_memory_buffer_is_open (ThriftTransport *transport) +{ + THRIFT_UNUSED_VAR (transport); + return TRUE; +} + +/* implements thrift_transport_open */ +gboolean +thrift_memory_buffer_open (ThriftTransport *transport, GError **error) +{ + THRIFT_UNUSED_VAR (transport); + THRIFT_UNUSED_VAR (error); + return TRUE; +} + +/* implements thrift_transport_close */ +gboolean +thrift_memory_buffer_close (ThriftTransport *transport, GError **error) +{ + THRIFT_UNUSED_VAR (transport); + THRIFT_UNUSED_VAR (error); + return TRUE; +} + +/* implements thrift_transport_read */ +gint32 +thrift_memory_buffer_read (ThriftTransport *transport, gpointer buf, + guint32 len, GError **error) +{ + ThriftMemoryBuffer *t = THRIFT_MEMORY_BUFFER (transport); + guint32 give = len; + + THRIFT_UNUSED_VAR (error); + + /* if the requested bytes are more than what we have available, + * just give all that we have the buffer */ + if (t->buf->len < len) + { + give = t->buf->len; + } + + memcpy (buf, t->buf->data, give); + g_byte_array_remove_range (t->buf, 0, give); + + return give; +} + +/* implements thrift_transport_read_end + * called when read is complete. nothing to do on our end. */ +gboolean +thrift_memory_buffer_read_end (ThriftTransport *transport, GError **error) +{ + /* satisfy -Wall */ + THRIFT_UNUSED_VAR (transport); + THRIFT_UNUSED_VAR (error); + return TRUE; +} + +/* implements thrift_transport_write */ +gboolean +thrift_memory_buffer_write (ThriftTransport *transport, + const gpointer buf, + const guint32 len, GError **error) +{ + ThriftMemoryBuffer *t = THRIFT_MEMORY_BUFFER (transport); + + THRIFT_UNUSED_VAR (error); + + /* return an exception if the buffer doesn't have enough space. */ + if (len > t->buf_size - t->buf->len) + { + g_set_error (error, THRIFT_TRANSPORT_ERROR, THRIFT_TRANSPORT_ERROR_SEND, + "unable to write %d bytes to buffer of length %d", + len, t->buf_size); + return FALSE; + } else { + t->buf = g_byte_array_append (t->buf, buf, len); + return TRUE; + } +} + +/* implements thrift_transport_write_end + * called when write is complete. nothing to do on our end. */ +gboolean +thrift_memory_buffer_write_end (ThriftTransport *transport, GError **error) +{ + /* satisfy -Wall */ + THRIFT_UNUSED_VAR (transport); + THRIFT_UNUSED_VAR (error); + return TRUE; +} + +/* implements thrift_transport_flush */ +gboolean +thrift_memory_buffer_flush (ThriftTransport *transport, GError **error) +{ + THRIFT_UNUSED_VAR (transport); + THRIFT_UNUSED_VAR (error); + + return TRUE; +} + +/* initializes class before constructor properties are set */ +static void +thrift_memory_buffer_init (ThriftMemoryBuffer *t) +{ + THRIFT_UNUSED_VAR (t); +} + +/* destructor */ +static void +thrift_memory_buffer_finalize (GObject *object) +{ + ThriftMemoryBuffer *t = THRIFT_MEMORY_BUFFER (object); + + if (t->owner && t->buf != NULL) + { + g_byte_array_unref (t->buf); + } + t->buf = NULL; +} + +/* property accessor */ +void +thrift_memory_buffer_get_property (GObject *object, guint property_id, + GValue *value, GParamSpec *pspec) +{ + ThriftMemoryBuffer *t = THRIFT_MEMORY_BUFFER (object); + + THRIFT_UNUSED_VAR (pspec); + + switch (property_id) + { + case PROP_THRIFT_MEMORY_BUFFER_BUFFER_SIZE: + g_value_set_uint (value, t->buf_size); + break; + case PROP_THRIFT_MEMORY_BUFFER_BUFFER: + g_value_set_pointer (value, (gpointer) (t->buf)); + break; + case PROP_THRIFT_MEMORY_BUFFER_OWNER: + g_value_set_boolean (value, t->owner); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +/* property mutator */ +void +thrift_memory_buffer_set_property (GObject *object, guint property_id, + const GValue *value, GParamSpec *pspec) +{ + ThriftMemoryBuffer *t = THRIFT_MEMORY_BUFFER (object); + + THRIFT_UNUSED_VAR (pspec); + + switch (property_id) + { + case PROP_THRIFT_MEMORY_BUFFER_BUFFER_SIZE: + t->buf_size = g_value_get_uint (value); + break; + case PROP_THRIFT_MEMORY_BUFFER_BUFFER: + t->buf = (GByteArray*) g_value_get_pointer (value); + break; + case PROP_THRIFT_MEMORY_BUFFER_OWNER: + t->owner = g_value_get_boolean (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +/* initializes class after constructor properties are set */ +static void +thrift_memory_buffer_constructed (GObject *object) +{ + ThriftMemoryBuffer *t = THRIFT_MEMORY_BUFFER (object); + + if (t->buf == NULL) { + t->buf = g_byte_array_new (); + } + + G_OBJECT_CLASS (thrift_memory_buffer_parent_class)->constructed (object); +} + +/* initializes the class */ +static void +thrift_memory_buffer_class_init (ThriftMemoryBufferClass *cls) +{ + ThriftTransportClass *ttc = THRIFT_TRANSPORT_CLASS (cls); + GObjectClass *gobject_class = G_OBJECT_CLASS (cls); + GParamSpec *param_spec = NULL; + + /* setup accessors and mutators */ + gobject_class->get_property = thrift_memory_buffer_get_property; + gobject_class->set_property = thrift_memory_buffer_set_property; + + param_spec = g_param_spec_uint ("buf_size", + "buffer size (construct)", + "Set the read/write buffer size limit", + 0, /* min */ + G_MAXUINT32, /* max */ + G_MAXUINT32, /* default */ + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_READWRITE); + g_object_class_install_property (gobject_class, + PROP_THRIFT_MEMORY_BUFFER_BUFFER_SIZE, + param_spec); + + param_spec = g_param_spec_pointer ("buf", + "internal buffer (GByteArray)", + "Set the internal buffer (GByteArray)", + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_READWRITE); + g_object_class_install_property (gobject_class, + PROP_THRIFT_MEMORY_BUFFER_BUFFER, + param_spec); + + param_spec = g_param_spec_boolean ("owner", + "internal buffer memory management policy", + "Set whether internal buffer should be" + " unreferenced when thrift_memory_buffer" + " is finalized", + TRUE, + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_READWRITE); + g_object_class_install_property (gobject_class, + PROP_THRIFT_MEMORY_BUFFER_OWNER, + param_spec); + + gobject_class->constructed = thrift_memory_buffer_constructed; + gobject_class->finalize = thrift_memory_buffer_finalize; + ttc->is_open = thrift_memory_buffer_is_open; + ttc->open = thrift_memory_buffer_open; + ttc->close = thrift_memory_buffer_close; + ttc->read = thrift_memory_buffer_read; + ttc->read_end = thrift_memory_buffer_read_end; + ttc->write = thrift_memory_buffer_write; + ttc->write_end = thrift_memory_buffer_write_end; + ttc->flush = thrift_memory_buffer_flush; +} diff --git a/vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/transport/thrift_memory_buffer.h b/vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/transport/thrift_memory_buffer.h new file mode 100644 index 000000000..d5d47b390 --- /dev/null +++ b/vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/transport/thrift_memory_buffer.h @@ -0,0 +1,72 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT 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_MEMORY_BUFFER_H +#define _THRIFT_MEMORY_BUFFER_H + +#include +#include + +#include + +G_BEGIN_DECLS + +/*! \file thrift_memory_buffer.h + * \brief Implementation of a Thrift memory buffer transport. + */ + +/* type macros */ +#define THRIFT_TYPE_MEMORY_BUFFER (thrift_memory_buffer_get_type ()) +#define THRIFT_MEMORY_BUFFER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), THRIFT_TYPE_MEMORY_BUFFER, ThriftMemoryBuffer)) +#define THRIFT_IS_MEMORY_BUFFER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), THRIFT_TYPE_MEMORY_BUFFER)) +#define THRIFT_MEMORY_BUFFER_CLASS(c) (G_TYPE_CHECK_CLASS_CAST ((c), THRIFT_TYPE_MEMORY_BUFFER, ThriftMemoryBufferClass)) +#define THRIFT_IS_MEMORY_BUFFER_CLASS(c) (G_TYPE_CHECK_CLASS_TYPE ((c), THRIFT_TYPE_MEMORY_BUFFER) +#define THRIFT_MEMORY_BUFFER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), THRIFT_TYPE_MEMORY_BUFFER, ThriftMemoryBufferClass)) + +typedef struct _ThriftMemoryBuffer ThriftMemoryBuffer; + +/*! + * ThriftMemoryBuffer instance. + */ +struct _ThriftMemoryBuffer +{ + ThriftTransport parent; + + /* private */ + GByteArray *buf; + guint32 buf_size; + gboolean owner; +}; + +typedef struct _ThriftMemoryBufferClass ThriftMemoryBufferClass; + +/*! + * ThriftMemoryBuffer class. + */ +struct _ThriftMemoryBufferClass +{ + ThriftTransportClass parent; +}; + +/* used by THRIFT_TYPE_MEMORY_BUFFER */ +GType thrift_memory_buffer_get_type (void); + +G_END_DECLS + +#endif diff --git a/vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/transport/thrift_server_socket.c b/vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/transport/thrift_server_socket.c new file mode 100644 index 000000000..6fc6ab3ec --- /dev/null +++ b/vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/transport/thrift_server_socket.c @@ -0,0 +1,253 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT 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 +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +/* object properties */ +enum _ThriftServerSocketProperties +{ + PROP_0, + PROP_THRIFT_SERVER_SOCKET_PORT, + PROP_THRIFT_SERVER_SOCKET_BACKLOG +}; + +/* define the GError domain string */ +#define THRIFT_SERVER_SOCKET_ERROR_DOMAIN "thrift-server-socket-error-quark" + +G_DEFINE_TYPE(ThriftServerSocket, thrift_server_socket, THRIFT_TYPE_SERVER_TRANSPORT) + +gboolean +thrift_server_socket_listen (ThriftServerTransport *transport, GError **error) +{ + int enabled = 1; /* for setsockopt() */ + struct sockaddr_in pin; + ThriftServerSocket *tsocket = THRIFT_SERVER_SOCKET (transport); + + /* create a address structure */ + memset (&pin, 0, sizeof(pin)); + pin.sin_family = AF_INET; + pin.sin_addr.s_addr = INADDR_ANY; + pin.sin_port = htons(tsocket->port); + + /* create a socket */ + if ((tsocket->sd = socket (AF_INET, SOCK_STREAM, 0)) == -1) + { + g_set_error (error, THRIFT_SERVER_SOCKET_ERROR, + THRIFT_SERVER_SOCKET_ERROR_SOCKET, + "failed to create socket - %s", strerror (errno)); + return FALSE; + } + + if (setsockopt(tsocket->sd, SOL_SOCKET, SO_REUSEADDR, &enabled, + sizeof(enabled)) == -1) + { + g_set_error (error, THRIFT_SERVER_SOCKET_ERROR, + THRIFT_SERVER_SOCKET_ERROR_SETSOCKOPT, + "unable to set SO_REUSEADDR - %s", strerror(errno)); + return FALSE; + } + + /* bind to the socket */ + if (bind(tsocket->sd, (struct sockaddr *) &pin, sizeof(pin)) == -1) + { + g_set_error (error, THRIFT_SERVER_SOCKET_ERROR, + THRIFT_SERVER_SOCKET_ERROR_BIND, + "failed to bind to port %d - %s", + tsocket->port, strerror(errno)); + return FALSE; + } + + if (listen(tsocket->sd, tsocket->backlog) == -1) + { + g_set_error (error, THRIFT_SERVER_SOCKET_ERROR, + THRIFT_SERVER_SOCKET_ERROR_LISTEN, + "failed to listen to port %d - %s", + tsocket->port, strerror(errno)); + return FALSE; + } + + return TRUE; +} + +ThriftTransport * +thrift_server_socket_accept (ThriftServerTransport *transport, GError **error) +{ + int sd = THRIFT_INVALID_SOCKET; + guint addrlen = 0; + struct sockaddr_in address; + ThriftSocket *socket = NULL; + + ThriftServerSocket *tsocket = THRIFT_SERVER_SOCKET (transport); + + if ((sd = accept(tsocket->sd, (struct sockaddr *) &address, &addrlen)) == -1) + { + g_set_error (error, THRIFT_SERVER_SOCKET_ERROR, + THRIFT_SERVER_SOCKET_ERROR_ACCEPT, + "failed to accept connection - %s", + strerror(errno)); + return FALSE; + } + + socket = g_object_new (THRIFT_TYPE_SOCKET, NULL); + socket->sd = sd; + + return THRIFT_TRANSPORT(socket); +} + +gboolean +thrift_server_socket_close (ThriftServerTransport *transport, GError **error) +{ + ThriftServerSocket *tsocket = THRIFT_SERVER_SOCKET (transport); + + if (close (tsocket->sd) == -1) + { + g_set_error (error, THRIFT_SERVER_SOCKET_ERROR, + THRIFT_SERVER_SOCKET_ERROR_CLOSE, + "unable to close socket - %s", strerror(errno)); + return FALSE; + } + tsocket->sd = THRIFT_INVALID_SOCKET; + + return TRUE; +} + +/* define the GError domain for this implementation */ +GQuark +thrift_server_socket_error_quark (void) +{ + return g_quark_from_static_string(THRIFT_SERVER_SOCKET_ERROR_DOMAIN); +} + +/* initializes the instance */ +static void +thrift_server_socket_init (ThriftServerSocket *socket) +{ + socket->sd = THRIFT_INVALID_SOCKET; +} + +/* destructor */ +static void +thrift_server_socket_finalize (GObject *object) +{ + ThriftServerSocket *socket = THRIFT_SERVER_SOCKET (object); + + if (socket->sd != THRIFT_INVALID_SOCKET) + { + close (socket->sd); + } + socket->sd = THRIFT_INVALID_SOCKET; +} + +/* property accessor */ +void +thrift_server_socket_get_property (GObject *object, guint property_id, + GValue *value, GParamSpec *pspec) +{ + ThriftServerSocket *socket = THRIFT_SERVER_SOCKET (object); + + switch (property_id) + { + case PROP_THRIFT_SERVER_SOCKET_PORT: + g_value_set_uint (value, socket->port); + break; + case PROP_THRIFT_SERVER_SOCKET_BACKLOG: + g_value_set_uint (value, socket->backlog); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +/* property mutator */ +void +thrift_server_socket_set_property (GObject *object, guint property_id, + const GValue *value, GParamSpec *pspec) +{ + ThriftServerSocket *socket = THRIFT_SERVER_SOCKET (object); + + switch (property_id) + { + case PROP_THRIFT_SERVER_SOCKET_PORT: + socket->port = g_value_get_uint (value); + break; + case PROP_THRIFT_SERVER_SOCKET_BACKLOG: + socket->backlog = g_value_get_uint (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +/* initializes the class */ +static void +thrift_server_socket_class_init (ThriftServerSocketClass *cls) +{ + ThriftServerTransportClass *tstc = THRIFT_SERVER_TRANSPORT_CLASS (cls); + GObjectClass *gobject_class = G_OBJECT_CLASS (cls); + GParamSpec *param_spec = NULL; + + /* setup accessors and mutators */ + gobject_class->get_property = thrift_server_socket_get_property; + gobject_class->set_property = thrift_server_socket_set_property; + + param_spec = g_param_spec_uint ("port", + "port (construct)", + "Set the port to listen to", + 0, /* min */ + 65534, /* max */ + 9090, /* default by convention */ + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_READWRITE); + g_object_class_install_property (gobject_class, + PROP_THRIFT_SERVER_SOCKET_PORT, + param_spec); + + param_spec = g_param_spec_uint ("backlog", + "backlog (construct)", + "Set the accept backlog", + 0, /* max */ + 65534, /* max */ + 1024, /* default */ + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_READWRITE); + g_object_class_install_property (gobject_class, + PROP_THRIFT_SERVER_SOCKET_BACKLOG, + param_spec); + + gobject_class->finalize = thrift_server_socket_finalize; + + tstc->listen = thrift_server_socket_listen; + tstc->accept = thrift_server_socket_accept; + tstc->close = thrift_server_socket_close; +} + diff --git a/vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/transport/thrift_server_socket.h b/vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/transport/thrift_server_socket.h new file mode 100644 index 000000000..f072cb0ef --- /dev/null +++ b/vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/transport/thrift_server_socket.h @@ -0,0 +1,90 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef _THRIFT_SERVER_SOCKET_H +#define _THRIFT_SERVER_SOCKET_H + +#include + +#include "thrift_server_transport.h" + +G_BEGIN_DECLS + +/*! \file thrift_server_socket.h + * \brief Socket implementation of a Thrift server transport. Implements the + * ThriftServerTransport class. + */ + +/* type macros */ +#define THRIFT_TYPE_SERVER_SOCKET (thrift_server_socket_get_type ()) +#define THRIFT_SERVER_SOCKET(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), THRIFT_TYPE_SERVER_SOCKET, ThriftServerSocket)) +#define THRIFT_IS_SERVER_SOCKET(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), THRIFT_TYPE_SERVER_SOCKET)) +#define THRIFT_SERVER_SOCKET_CLASS(c) (G_TYPE_CHECK_CLASS_CAST ((c), THRIFT_TYPE_SERVER_SOCKET, ThriftServerSocketClass)) +#define THRIFT_IS_SERVER_SOCKET_CLASS(c) (G_TYPE_CHECK_CLASS_TYPE ((c), THRIFT_TYPE_SERVER_SOCKET)) +#define THRIFT_SERVER_SOCKET_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), THRIFT_TYPE_SERVER_SOCKET, ThriftServerSocketClass)) + +typedef struct _ThriftServerSocket ThriftServerSocket; + +/*! + * Thrift ServerSocket instance. + */ +struct _ThriftServerSocket +{ + ThriftServerTransport parent; + + /* private */ + gshort port; + gshort backlog; + int sd; + guint8 *buf; + guint32 buf_size; + guint32 buf_len; +}; + +typedef struct _ThriftServerSocketClass ThriftServerSocketClass; + +/*! + * Thrift ServerSocket class. + */ +struct _ThriftServerSocketClass +{ + ThriftServerTransportClass parent; +}; + +/* used by THRIFT_TYPE_SERVER_SOCKET */ +GType thrift_server_socket_get_type (void); + +/* define error/exception types */ +typedef enum +{ + THRIFT_SERVER_SOCKET_ERROR_SOCKET, + THRIFT_SERVER_SOCKET_ERROR_SETSOCKOPT, + THRIFT_SERVER_SOCKET_ERROR_BIND, + THRIFT_SERVER_SOCKET_ERROR_LISTEN, + THRIFT_SERVER_SOCKET_ERROR_ACCEPT, + THRIFT_SERVER_SOCKET_ERROR_CLOSE +} ThriftServerSocketError; + +/* define a error domain for GError to use */ +GQuark thrift_server_socket_error_quark (void); +#define THRIFT_SERVER_SOCKET_ERROR (thrift_server_socket_error_quark ()) + +G_END_DECLS + +#endif diff --git a/vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/transport/thrift_server_transport.c b/vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/transport/thrift_server_transport.c new file mode 100644 index 000000000..c25d1384f --- /dev/null +++ b/vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/transport/thrift_server_transport.c @@ -0,0 +1,62 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT 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 +#include +#include + +G_DEFINE_ABSTRACT_TYPE(ThriftServerTransport, thrift_server_transport, G_TYPE_OBJECT) + +/* base initializer for the server transport interface */ +static void +thrift_server_transport_class_init (ThriftServerTransportClass *c) +{ + c->listen = thrift_server_transport_listen; + c->accept = thrift_server_transport_accept; + c->close = thrift_server_transport_close; +} + +static void +thrift_server_transport_init (ThriftServerTransport *transport) +{ + THRIFT_UNUSED_VAR (transport); +} + +gboolean +thrift_server_transport_listen (ThriftServerTransport *transport, + GError **error) +{ + return THRIFT_SERVER_TRANSPORT_GET_CLASS (transport)->listen (transport, + error); +} + +ThriftTransport * +thrift_server_transport_accept (ThriftServerTransport *transport, + GError **error) +{ + return THRIFT_SERVER_TRANSPORT_GET_CLASS (transport)->accept (transport, + error); +} + +gboolean +thrift_server_transport_close (ThriftServerTransport *transport, GError **error) +{ + return THRIFT_SERVER_TRANSPORT_GET_CLASS (transport)->close (transport, + error); +} diff --git a/vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/transport/thrift_server_transport.h b/vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/transport/thrift_server_transport.h new file mode 100644 index 000000000..98a9191bd --- /dev/null +++ b/vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/transport/thrift_server_transport.h @@ -0,0 +1,89 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef _THRIFT_SERVER_TRANSPORT_H +#define _THRIFT_SERVER_TRANSPORT_H + +#include + +#include "thrift_transport.h" + +G_BEGIN_DECLS + +/*! \file thrift_server_transport.h + * \brief Abstract class for Thrift server transports. + */ + +/* type macros */ +#define THRIFT_TYPE_SERVER_TRANSPORT (thrift_server_transport_get_type ()) +#define THRIFT_SERVER_TRANSPORT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), THRIFT_TYPE_SERVER_TRANSPORT, ThriftServerTransport)) +#define THRIFT_IS_SERVER_TRANSPORT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), THRIFT_TYPE_SERVER_TRANSPORT)) +#define THRIFT_SERVER_TRANSPORT_CLASS(c) (G_TYPE_CHECK_CLASS_CAST ((c), THRIFT_TYPE_SERVER_TRANSPORT, ThriftServerTransportClass)) +#define THRIFT_IS_SERVER_TRANSPORT_CLASS(c) (G_TYPE_CHECK_CLASS_TYPE ((c), THRIFT_TYPE_SERVER_TRANSPORT)) +#define THRIFT_SERVER_TRANSPORT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), THRIFT_TYPE_SERVER_TRANSPORT, ThriftServerTransportClass)) + +typedef struct _ThriftServerTransport ThriftServerTransport; + +struct _ThriftServerTransport +{ + GObject parent; +}; + +typedef struct _ThriftServerTransportClass ThriftServerTransportClass; + +/*! + * Thrift Transport class + */ +struct _ThriftServerTransportClass +{ + GObjectClass parent; + + /* vtable */ + gboolean (*listen) (ThriftServerTransport *transport, GError **error); + ThriftTransport *(*accept) (ThriftServerTransport *transport, GError **error); + gboolean (*close) (ThriftServerTransport *transport, GError **error); +}; + +/* used by THRIFT_TYPE_SERVER_TRANSPORT */ +GType thrift_server_transport_get_type (void); + +/*! + * Listen for new connections. + * \public \memberof ThriftServerTransportClass + */ +gboolean thrift_server_transport_listen (ThriftServerTransport *transport, + GError **error); + +/*! + * Accept a connection. + * \public \memberof ThriftServerTransportClass + */ +ThriftTransport *thrift_server_transport_accept + (ThriftServerTransport *transport, GError **error); + +/*! + * Close the transport. + * \public \memberof ThriftServerTransportClass + */ +gboolean thrift_server_transport_close (ThriftServerTransport *transport, + GError **error); + +G_END_DECLS + +#endif /* _THRIFT_SERVER_TRANSPORT_H */ diff --git a/vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/transport/thrift_socket.c b/vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/transport/thrift_socket.c new file mode 100644 index 000000000..07ee2cb22 --- /dev/null +++ b/vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/transport/thrift_socket.c @@ -0,0 +1,368 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT 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 +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +/* object properties */ +enum _ThriftSocketProperties +{ + PROP_0, + PROP_THRIFT_SOCKET_HOSTNAME, + PROP_THRIFT_SOCKET_PORT +}; + +G_DEFINE_TYPE(ThriftSocket, thrift_socket, THRIFT_TYPE_TRANSPORT) + +/* implements thrift_transport_is_open */ +gboolean +thrift_socket_is_open (ThriftTransport *transport) +{ + ThriftSocket *socket = THRIFT_SOCKET (transport); + return socket->sd != THRIFT_INVALID_SOCKET; +} + +/* overrides thrift_transport_peek */ +gboolean +thrift_socket_peek (ThriftTransport *transport, GError **error) +{ + gboolean result = FALSE; + guint8 buf; + int r; + int errno_copy; + + ThriftSocket *socket = THRIFT_SOCKET (transport); + + if (thrift_socket_is_open (transport)) + { + r = recv (socket->sd, &buf, 1, MSG_PEEK); + if (r == -1) + { + errno_copy = errno; + + #if defined __FreeBSD__ || defined __MACH__ + /* FreeBSD returns -1 and ECONNRESET if the socket was closed by the other + side */ + if (errno_copy == ECONNRESET) + { + thrift_socket_close (transport, error); + } + else + { + #endif + + g_set_error (error, + THRIFT_TRANSPORT_ERROR, + THRIFT_TRANSPORT_ERROR_SOCKET, + "failed to peek at socket - %s", + strerror (errno_copy)); + + #if defined __FreeBSD__ || defined __MACH__ + } + #endif + } + else if (r > 0) + { + result = TRUE; + } + } + + return result; +} + +/* implements thrift_transport_open */ +gboolean +thrift_socket_open (ThriftTransport *transport, GError **error) +{ + struct hostent *hp = NULL; + struct sockaddr_in pin; + int err; +#if defined(HAVE_GETHOSTBYNAME_R) + struct hostent he; + char buf[1024]; +#endif + + ThriftSocket *tsocket = THRIFT_SOCKET (transport); + g_return_val_if_fail (tsocket->sd == THRIFT_INVALID_SOCKET, FALSE); + + /* lookup the destination host */ +#if defined(HAVE_GETHOSTBYNAME_R) + if (gethostbyname_r (tsocket->hostname, &he, buf, 1024, &hp, &err) != 0 || hp == NULL) +#else + if ((hp = gethostbyname (tsocket->hostname)) == NULL && (err = h_errno)) +#endif + { + /* host lookup failed, bail out with an error */ + g_set_error (error, THRIFT_TRANSPORT_ERROR, THRIFT_TRANSPORT_ERROR_HOST, + "host lookup failed for %s:%d - %s", + tsocket->hostname, tsocket->port, + hstrerror (err)); + return FALSE; + } + + /* create a socket structure */ + memset (&pin, 0, sizeof(pin)); + pin.sin_family = AF_INET; + pin.sin_addr.s_addr = ((struct in_addr *) (hp->h_addr))->s_addr; + pin.sin_port = htons (tsocket->port); + + /* create the socket */ + if ((tsocket->sd = socket (AF_INET, SOCK_STREAM, 0)) == -1) + { + g_set_error (error, THRIFT_TRANSPORT_ERROR, THRIFT_TRANSPORT_ERROR_SOCKET, + "failed to create socket for host %s:%d - %s", + tsocket->hostname, tsocket->port, + strerror(errno)); + return FALSE; + } + + /* open a connection */ + if (connect (tsocket->sd, (struct sockaddr *) &pin, sizeof(pin)) == -1) + { + g_set_error (error, THRIFT_TRANSPORT_ERROR, THRIFT_TRANSPORT_ERROR_CONNECT, + "failed to connect to host %s:%d - %s", + tsocket->hostname, tsocket->port, strerror(errno)); + return FALSE; + } + + return TRUE; +} + +/* implements thrift_transport_close */ +gboolean +thrift_socket_close (ThriftTransport *transport, GError **error) +{ + ThriftSocket *socket = THRIFT_SOCKET (transport); + + if (close (socket->sd) == -1) + { + g_set_error (error, THRIFT_TRANSPORT_ERROR, THRIFT_TRANSPORT_ERROR_CLOSE, + "unable to close socket - %s", + strerror(errno)); + return FALSE; + } + + socket->sd = THRIFT_INVALID_SOCKET; + return TRUE; +} + +/* implements thrift_transport_read */ +gint32 +thrift_socket_read (ThriftTransport *transport, gpointer buf, + guint32 len, GError **error) +{ + gint ret = 0; + guint got = 0; + + ThriftSocket *socket = THRIFT_SOCKET (transport); + + while (got < len) + { + ret = recv (socket->sd, (guint8 *)buf + got, len-got, 0); + if (ret <= 0) + { + g_set_error (error, THRIFT_TRANSPORT_ERROR, + THRIFT_TRANSPORT_ERROR_RECEIVE, + "failed to read %d bytes - %s", len, strerror(errno)); + return -1; + } + got += ret; + } + + return got; +} + +/* implements thrift_transport_read_end + * called when write is complete. nothing to do on our end. */ +gboolean +thrift_socket_read_end (ThriftTransport *transport, GError **error) +{ + /* satisfy -Wall */ + THRIFT_UNUSED_VAR (transport); + THRIFT_UNUSED_VAR (error); + return TRUE; +} + +/* implements thrift_transport_write */ +gboolean +thrift_socket_write (ThriftTransport *transport, const gpointer buf, + const guint32 len, GError **error) +{ + gint ret = 0; + guint sent = 0; + + ThriftSocket *socket = THRIFT_SOCKET (transport); + g_return_val_if_fail (socket->sd != THRIFT_INVALID_SOCKET, FALSE); + + while (sent < len) + { + ret = send (socket->sd, (guint8 *)buf + sent, len - sent, 0); + if (ret < 0) + { + g_set_error (error, THRIFT_TRANSPORT_ERROR, + THRIFT_TRANSPORT_ERROR_SEND, + "failed to send %d bytes - %s", len, strerror(errno)); + return FALSE; + } + sent += ret; + } + + return TRUE; +} + +/* implements thrift_transport_write_end + * called when write is complete. nothing to do on our end. */ +gboolean +thrift_socket_write_end (ThriftTransport *transport, GError **error) +{ + /* satisfy -Wall */ + THRIFT_UNUSED_VAR (transport); + THRIFT_UNUSED_VAR (error); + return TRUE; +} + +/* implements thrift_transport_flush + * flush pending data. since we are not buffered, this is a no-op */ +gboolean +thrift_socket_flush (ThriftTransport *transport, GError **error) +{ + /* satisfy -Wall */ + THRIFT_UNUSED_VAR (transport); + THRIFT_UNUSED_VAR (error); + return TRUE; +} + +/* initializes the instance */ +static void +thrift_socket_init (ThriftSocket *socket) +{ + socket->sd = THRIFT_INVALID_SOCKET; +} + +/* destructor */ +static void +thrift_socket_finalize (GObject *object) +{ + ThriftSocket *socket = THRIFT_SOCKET (object); + + if (socket->hostname != NULL) + { + g_free (socket->hostname); + } + socket->hostname = NULL; + + if (socket->sd != THRIFT_INVALID_SOCKET) + { + close (socket->sd); + } + socket->sd = THRIFT_INVALID_SOCKET; +} + +/* property accessor */ +void +thrift_socket_get_property (GObject *object, guint property_id, + GValue *value, GParamSpec *pspec) +{ + ThriftSocket *socket = THRIFT_SOCKET (object); + + THRIFT_UNUSED_VAR (pspec); + + switch (property_id) + { + case PROP_THRIFT_SOCKET_HOSTNAME: + g_value_set_string (value, socket->hostname); + break; + case PROP_THRIFT_SOCKET_PORT: + g_value_set_uint (value, socket->port); + break; + } +} + +/* property mutator */ +void +thrift_socket_set_property (GObject *object, guint property_id, + const GValue *value, GParamSpec *pspec) +{ + ThriftSocket *socket = THRIFT_SOCKET (object); + + THRIFT_UNUSED_VAR (pspec); + + switch (property_id) + { + case PROP_THRIFT_SOCKET_HOSTNAME: + socket->hostname = g_strdup (g_value_get_string (value)); + break; + case PROP_THRIFT_SOCKET_PORT: + socket->port = g_value_get_uint (value); + break; + } +} + +/* initializes the class */ +static void +thrift_socket_class_init (ThriftSocketClass *cls) +{ + ThriftTransportClass *ttc = THRIFT_TRANSPORT_CLASS (cls); + GObjectClass *gobject_class = G_OBJECT_CLASS (cls); + GParamSpec *param_spec = NULL; + + /* setup accessors and mutators */ + gobject_class->get_property = thrift_socket_get_property; + gobject_class->set_property = thrift_socket_set_property; + + param_spec = g_param_spec_string ("hostname", + "hostname (construct)", + "Set the hostname of the remote host", + "localhost", /* default value */ + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_READWRITE); + g_object_class_install_property (gobject_class, PROP_THRIFT_SOCKET_HOSTNAME, + param_spec); + + param_spec = g_param_spec_uint ("port", + "port (construct)", + "Set the port of the remote host", + 0, /* min */ + 65534, /* max */ + 9090, /* default by convention */ + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_READWRITE); + g_object_class_install_property (gobject_class, PROP_THRIFT_SOCKET_PORT, + param_spec); + + gobject_class->finalize = thrift_socket_finalize; + ttc->is_open = thrift_socket_is_open; + ttc->peek = thrift_socket_peek; + ttc->open = thrift_socket_open; + ttc->close = thrift_socket_close; + ttc->read = thrift_socket_read; + ttc->read_end = thrift_socket_read_end; + ttc->write = thrift_socket_write; + ttc->write_end = thrift_socket_write_end; + ttc->flush = thrift_socket_flush; +} diff --git a/vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/transport/thrift_socket.h b/vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/transport/thrift_socket.h new file mode 100644 index 000000000..981577da7 --- /dev/null +++ b/vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/transport/thrift_socket.h @@ -0,0 +1,75 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT 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_SOCKET_H +#define _THRIFT_SOCKET_H + +#include + +#include + +G_BEGIN_DECLS + +/*! \file thrift_socket.h + * \brief Socket implementation of a Thrift transport. Subclasses the + * ThriftTransport class. + */ + +/* type macros */ +#define THRIFT_TYPE_SOCKET (thrift_socket_get_type ()) +#define THRIFT_SOCKET(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), THRIFT_TYPE_SOCKET, ThriftSocket)) +#define THRIFT_IS_SOCKET(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), THRIFT_TYPE_SOCKET)) +#define THRIFT_SOCKET_CLASS(c) (G_TYPE_CHECK_CLASS_CAST ((c), THRIFT_TYPE_SOCKET, ThriftSocketClass)) +#define THRIFT_IS_SOCKET_CLASS(c) (G_TYPE_CHECK_CLASS_TYPE ((c), THRIFT_TYPE_SOCKET)) +#define THRIFT_SOCKET_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), THRIFT_TYPE_SOCKET, ThriftSocketClass)) + +typedef struct _ThriftSocket ThriftSocket; + +/*! + * Thrift Socket instance. + */ +struct _ThriftSocket +{ + ThriftTransport parent; + + /* private */ + gchar *hostname; + gshort port; + int sd; + guint8 *buf; + guint32 buf_size; + guint32 buf_len; +}; + +typedef struct _ThriftSocketClass ThriftSocketClass; + +/*! + * Thrift Socket class. + */ +struct _ThriftSocketClass +{ + ThriftTransportClass parent; +}; + +/* used by THRIFT_TYPE_SOCKET */ +GType thrift_socket_get_type (void); + +G_END_DECLS + +#endif diff --git a/vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/transport/thrift_transport.c b/vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/transport/thrift_transport.c new file mode 100644 index 000000000..9dd267143 --- /dev/null +++ b/vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/transport/thrift_transport.c @@ -0,0 +1,162 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT 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 +#include + +/* define the GError domain string */ +#define THRIFT_TRANSPORT_ERROR_DOMAIN "thrift-transport-error-quark" + +G_DEFINE_ABSTRACT_TYPE(ThriftTransport, thrift_transport, G_TYPE_OBJECT) + +gboolean +thrift_transport_is_open (ThriftTransport *transport) +{ + return THRIFT_TRANSPORT_GET_CLASS (transport)->is_open (transport); +} + +gboolean +thrift_transport_peek (ThriftTransport *transport, GError **error) +{ + return THRIFT_TRANSPORT_GET_CLASS (transport)->peek (transport, error); +} + +gboolean +thrift_transport_open (ThriftTransport *transport, GError **error) +{ + return THRIFT_TRANSPORT_GET_CLASS (transport)->open (transport, error); +} + +gboolean +thrift_transport_close (ThriftTransport *transport, GError **error) +{ + return THRIFT_TRANSPORT_GET_CLASS (transport)->close (transport, error); +} + +gint32 +thrift_transport_read (ThriftTransport *transport, gpointer buf, + guint32 len, GError **error) +{ + return THRIFT_TRANSPORT_GET_CLASS (transport)->read (transport, buf, + len, error); +} + +gboolean +thrift_transport_read_end (ThriftTransport *transport, GError **error) +{ + return THRIFT_TRANSPORT_GET_CLASS (transport)->read_end (transport, + error); +} + +gboolean +thrift_transport_write (ThriftTransport *transport, const gpointer buf, + const guint32 len, GError **error) +{ + return THRIFT_TRANSPORT_GET_CLASS (transport)->write (transport, buf, + len, error); +} + +gboolean +thrift_transport_write_end (ThriftTransport *transport, GError **error) +{ + return THRIFT_TRANSPORT_GET_CLASS (transport)->write_end (transport, + error); +} + +gboolean +thrift_transport_flush (ThriftTransport *transport, GError **error) +{ + return THRIFT_TRANSPORT_GET_CLASS (transport)->flush (transport, error); +} + +gint32 +thrift_transport_read_all (ThriftTransport *transport, gpointer buf, + guint32 len, GError **error) +{ + return THRIFT_TRANSPORT_GET_CLASS (transport)->read_all (transport, buf, + len, error); +} + +/* by default, peek returns true if and only if the transport is open */ +static gboolean +thrift_transport_real_peek (ThriftTransport *transport, GError **error) +{ + THRIFT_UNUSED_VAR (error); + + return THRIFT_TRANSPORT_GET_CLASS (transport)->is_open (transport); +} + +static gint32 +thrift_transport_real_read_all (ThriftTransport *transport, gpointer buf, + guint32 len, GError **error) +{ + ThriftTransportClass *ttc; + guint32 have; + gint32 ret; + gint8 *bytes; + + THRIFT_UNUSED_VAR (error); + + ttc = THRIFT_TRANSPORT_GET_CLASS (transport); + have = 0; + ret = 0; + bytes = (gint8*) buf; + + while (have < len) { + if ((ret = ttc->read (transport, (gpointer) (bytes + have), len - have, + error)) < 0) { + return ret; + } + have += ret; + } + + return have; +} + +/* define the GError domain for Thrift transports */ +GQuark +thrift_transport_error_quark (void) +{ + return g_quark_from_static_string (THRIFT_TRANSPORT_ERROR_DOMAIN); +} + +/* class initializer for ThriftTransport */ +static void +thrift_transport_class_init (ThriftTransportClass *cls) +{ + /* set these as virtual methods to be implemented by a subclass */ + cls->is_open = thrift_transport_is_open; + cls->open = thrift_transport_open; + cls->close = thrift_transport_close; + cls->read = thrift_transport_read; + cls->read_end = thrift_transport_read_end; + cls->write = thrift_transport_write; + cls->write_end = thrift_transport_write_end; + cls->flush = thrift_transport_flush; + + /* provide a default implementation for the peek and read_all methods */ + cls->peek = thrift_transport_real_peek; + cls->read_all = thrift_transport_real_read_all; +} + +static void +thrift_transport_init (ThriftTransport *transport) +{ + THRIFT_UNUSED_VAR (transport); +} diff --git a/vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/transport/thrift_transport.h b/vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/transport/thrift_transport.h new file mode 100644 index 000000000..94bb6f507 --- /dev/null +++ b/vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/transport/thrift_transport.h @@ -0,0 +1,176 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef _THRIFT_TRANSPORT_H +#define _THRIFT_TRANSPORT_H + +#include + +G_BEGIN_DECLS + +/*! \file thrift_transport.h + * \brief Abstract class for Thrift transports. + * + * An abstract class is used instead of an interface because: + * - interfaces can't seem to be used as properties. ThriftProtocol has + * a ThriftTransport as an object property. + * - if a method needs to be added that all subclasses can use, a class + * is necessary. + */ + +/* type macros */ +#define THRIFT_TYPE_TRANSPORT (thrift_transport_get_type ()) +#define THRIFT_TRANSPORT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), THRIFT_TYPE_TRANSPORT, ThriftTransport)) +#define THRIFT_IS_TRANSPORT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), THRIFT_TYPE_TRANSPORT)) +#define THRIFT_TRANSPORT_CLASS(c) (G_TYPE_CHECK_CLASS_CAST ((c), THRIFT_TYPE_TRANSPORT, ThriftTransportClass)) +#define THRIFT_IS_TRANSPORT_CLASS(c) (G_TYPE_CHECK_CLASS_TYPE ((c), THRIFT_TYPE_TRANSPORT)) +#define THRIFT_TRANSPORT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), THRIFT_TYPE_TRANSPORT, ThriftTransportClass)) + +typedef struct _ThriftTransport ThriftTransport; + +/*! + * Thrift Protocol object + */ +struct _ThriftTransport +{ + GObject parent; +}; + +typedef struct _ThriftTransportClass ThriftTransportClass; + +/*! + * Thrift Transport class + */ +struct _ThriftTransportClass +{ + GObjectClass parent; + + /* vtable */ + gboolean (*is_open) (ThriftTransport *transport); + gboolean (*peek) (ThriftTransport *transport, GError **error); + gboolean (*open) (ThriftTransport *transport, GError **error); + gboolean (*close) (ThriftTransport *transport, GError **error); + gint32 (*read) (ThriftTransport *transport, gpointer buf, + guint32 len, GError **error); + gboolean (*read_end) (ThriftTransport *transport, GError **error); + gboolean (*write) (ThriftTransport *transport, const gpointer buf, + const guint32 len, GError **error); + gboolean (*write_end) (ThriftTransport *transport, GError **error); + gboolean (*flush) (ThriftTransport *transport, GError **error); + gint32 (*read_all) (ThriftTransport *transport, gpointer buf, + guint32 len, GError **error); +}; + +/* used by THRIFT_TYPE_TRANSPORT */ +GType thrift_transport_get_type (void); + +/* virtual public methods */ + +/*! + * Checks if this transport is opened. + * \public \memberof ThriftTransportInterface + */ +gboolean thrift_transport_is_open (ThriftTransport *transport); + +/*! + * Open the transport for reading and writing. + * \public \memberof ThriftTransportInterface + */ +gboolean thrift_transport_open (ThriftTransport *transport, GError **error); + +/*! + * 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. + * \public \memberof ThriftTransportInterface + */ +gboolean thrift_transport_peek (ThriftTransport *transport, GError **error); + +/*! + * Close the transport. + * \public \memberof ThriftTransportInterface + */ +gboolean thrift_transport_close (ThriftTransport *transport, GError **error); + +/*! + * Read some data into the buffer buf. + * \public \memberof ThriftTransportInterface + */ +gint32 thrift_transport_read (ThriftTransport *transport, gpointer buf, + guint32 len, GError **error); + +/*! + * Called when read is completed. + * \public \memberof ThriftTransportInterface + */ +gboolean thrift_transport_read_end (ThriftTransport *transport, GError **error); + +/*! + * Writes data from a buffer to the transport. + * \public \memberof ThriftTransportInterface + */ +gboolean thrift_transport_write (ThriftTransport *transport, const gpointer buf, + const guint32 len, GError **error); + +/*! + * Called when write is completed. + * \public \memberof ThriftTransportInterface + */ +gboolean thrift_transport_write_end (ThriftTransport *transport, + GError **error); + +/*! + * Flushes any pending data to be written. Typically used with buffered + * transport mechanisms. + * \public \memberof ThriftTransportInterface + */ +gboolean thrift_transport_flush (ThriftTransport *transport, GError **error); + +/*! + * Read len bytes of data into the buffer buf. + * \public \memberof ThriftTransportInterface + */ +gint32 thrift_transport_read_all (ThriftTransport *transport, gpointer buf, + guint32 len, GError **error); + +/* define error/exception types */ +typedef enum +{ + THRIFT_TRANSPORT_ERROR_UNKNOWN, + THRIFT_TRANSPORT_ERROR_HOST, + THRIFT_TRANSPORT_ERROR_SOCKET, + THRIFT_TRANSPORT_ERROR_CONNECT, + THRIFT_TRANSPORT_ERROR_SEND, + THRIFT_TRANSPORT_ERROR_RECEIVE, + THRIFT_TRANSPORT_ERROR_CLOSE +} ThriftTransportError; + +/* define an error domain for GError to use */ +GQuark thrift_transport_error_quark (void); +#define THRIFT_TRANSPORT_ERROR (thrift_transport_error_quark ()) + +/* define macro for invalid socket */ +#define THRIFT_INVALID_SOCKET (-1) + +G_END_DECLS + +#endif /* _THRIFT_TRANSPORT_H */ diff --git a/vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/transport/thrift_transport_factory.c b/vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/transport/thrift_transport_factory.c new file mode 100644 index 000000000..a2025cf4b --- /dev/null +++ b/vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/transport/thrift_transport_factory.c @@ -0,0 +1,44 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include +#include + +G_DEFINE_TYPE(ThriftTransportFactory, thrift_transport_factory, G_TYPE_OBJECT) + +/* builds a transport from the base transport. */ +ThriftTransport * +thrift_transport_factory_get_transport (ThriftTransportFactory *factory, + ThriftTransport *transport) +{ + THRIFT_UNUSED_VAR (factory); + return transport; +} + +static void +thrift_transport_factory_class_init (ThriftTransportFactoryClass *cls) +{ + cls->get_transport = thrift_transport_factory_get_transport; +} + +static void +thrift_transport_factory_init (ThriftTransportFactory *factory) +{ + THRIFT_UNUSED_VAR (factory); +} diff --git a/vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/transport/thrift_transport_factory.h b/vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/transport/thrift_transport_factory.h new file mode 100644 index 000000000..0e3da302e --- /dev/null +++ b/vendor/github.com/apache/thrift/lib/c_glib/src/thrift/c_glib/transport/thrift_transport_factory.h @@ -0,0 +1,71 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef _THRIFT_TRANSPORT_FACTORY_H +#define _THRIFT_TRANSPORT_FACTORY_H + +#include + +#include "thrift_transport.h" + +G_BEGIN_DECLS + +/*! \file thrift_transport_factory.h + * \brief Base class for Thrift Transport Factories. Used by Thrift Servers + * to obtain a client transport from an existing transport. The default + * implementation simply clones the provided transport. + */ + +/* type macros */ +#define THRIFT_TYPE_TRANSPORT_FACTORY (thrift_transport_factory_get_type ()) +#define THRIFT_TRANSPORT_FACTORY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), THRIFT_TYPE_TRANSPORT_FACTORY, ThriftTransportFactory)) +#define THRIFT_IS_TRANSPORT_FACTORY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), THRIFT_TYPE_TRANSPORT_FACTORY)) +#define THRIFT_TRANSPORT_FACTORY_CLASS(c) (G_TYPE_CHECK_CLASS_CAST ((c), THRIFT_TYPE_TRANSPORT_FACTORY, ThriftTransportFactoryClass)) +#define THRIFT_IS_TRANSPORT_FACTORY_CLASS(c) (G_TYPE_CHECK_CLASS_TYPE ((c), THRIFT_TYPE_TRANSPORT_FACTORY)) +#define THRIFT_TRANSPORT_FACTORY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), THRIFT_TYPE_TRANSPORT_FACTORY, ThriftTransportFactoryClass)) + +typedef struct _ThriftTransportFactory ThriftTransportFactory; + +/* Thrift Transport Factory instance */ +struct _ThriftTransportFactory +{ + GObject parent; +}; + +typedef struct _ThriftTransportFactoryClass ThriftTransportFactoryClass; + +/* Thrift Transport Factory class */ +struct _ThriftTransportFactoryClass +{ + GObjectClass parent; + + /* vtable */ + ThriftTransport *(*get_transport) (ThriftTransportFactory *factory, + ThriftTransport *transport); +}; + +/* used by THRIFT_TYPE_TRANSPORT_FACTORY */ +GType thrift_transport_factory_get_type (void); + +/* virtual public methods */ +ThriftTransport *thrift_transport_factory_get_transport (ThriftTransportFactory *factory, ThriftTransport *transport); + +G_END_DECLS + +#endif /* _THRIFT_TRANSPORT_FACTORY_H */ diff --git a/vendor/github.com/apache/thrift/lib/cocoa/README.md b/vendor/github.com/apache/thrift/lib/cocoa/README.md new file mode 100644 index 000000000..bbe3c934f --- /dev/null +++ b/vendor/github.com/apache/thrift/lib/cocoa/README.md @@ -0,0 +1,21 @@ +Thrift Cocoa Software Library + +License +======= + +Licensed to the Apache Software Foundation (ASF) under one +or more contributor license agreements. See the NOTICE file +distributed with this work for additional information +regarding copyright ownership. The ASF licenses this file +to you under the Apache License, Version 2.0 (the +"License"); you may not use this file except in compliance +with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, +software distributed under the License is distributed on an +"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +KIND, either express or implied. See the License for the +specific language governing permissions and limitations +under the License. diff --git a/vendor/github.com/apache/thrift/lib/cocoa/src/TApplicationError.h b/vendor/github.com/apache/thrift/lib/cocoa/src/TApplicationError.h new file mode 100644 index 000000000..079881a60 --- /dev/null +++ b/vendor/github.com/apache/thrift/lib/cocoa/src/TApplicationError.h @@ -0,0 +1,55 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#import "TProtocol.h" + +extern NSString *TApplicationErrorDomain; + +typedef NS_ENUM (int, TApplicationError) { + TApplicationErrorUnknown = 0, + TApplicationErrorUnknownMethod = 1, + TApplicationErrorInvalidMessageType = 2, + TApplicationErrorWrongMethodName = 3, + TApplicationErrorBadSequenceId = 4, + TApplicationErrorMissingResult = 5, + TApplicationErrorInternalError = 6, + TApplicationErrorProtocolError = 7, + TApplicationErrorInvalidTransform = 8, + TApplicationErrorInvalidProtocol = 9, + TApplicationErrorUnsupportedClientType = 10, +}; + + +extern NSString *TApplicationErrorNameKey; +extern NSString *TApplicationErrorReasonKey; +extern NSString *TApplicationErrorMethodKey; + + +@interface NSError (TApplicationError) + +@property (readonly, copy) NSString *name; +@property (readonly, copy) NSString *reason; + ++(instancetype) errorWithType:(TApplicationError)type reason:(NSString *)reason; + ++(instancetype) read:(id)protocol; + +-(BOOL) write:(id)outProtocol error:(NSError *__autoreleasing *)error; + +@end diff --git a/vendor/github.com/apache/thrift/lib/cocoa/src/TBaseClient.h b/vendor/github.com/apache/thrift/lib/cocoa/src/TBaseClient.h new file mode 100644 index 000000000..0f73aa027 --- /dev/null +++ b/vendor/github.com/apache/thrift/lib/cocoa/src/TBaseClient.h @@ -0,0 +1,27 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#import "TProtocol.h" +#import "TApplicationError.h" + +@interface TBaseClient : NSObject + +-(NSError *) checkIncomingMessageException:(id)protocol; + +@end diff --git a/vendor/github.com/apache/thrift/lib/cocoa/src/TError.h b/vendor/github.com/apache/thrift/lib/cocoa/src/TError.h new file mode 100644 index 000000000..abb72c7ad --- /dev/null +++ b/vendor/github.com/apache/thrift/lib/cocoa/src/TError.h @@ -0,0 +1,23 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#import + + +extern NSString *TErrorDomain; diff --git a/vendor/github.com/apache/thrift/lib/cocoa/src/TProcessor.h b/vendor/github.com/apache/thrift/lib/cocoa/src/TProcessor.h new file mode 100644 index 000000000..20c72e2e1 --- /dev/null +++ b/vendor/github.com/apache/thrift/lib/cocoa/src/TProcessor.h @@ -0,0 +1,35 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#import +#import "TProtocol.h" + +NS_ASSUME_NONNULL_BEGIN + + +@protocol TProcessor + +-(BOOL) processOnInputProtocol:(id )inProtocol + outputProtocol:(id )outProtocol + error:(NSError **)error; + +@end + + +NS_ASSUME_NONNULL_END diff --git a/vendor/github.com/apache/thrift/lib/cocoa/src/TProcessorFactory.h b/vendor/github.com/apache/thrift/lib/cocoa/src/TProcessorFactory.h new file mode 100644 index 000000000..85020a593 --- /dev/null +++ b/vendor/github.com/apache/thrift/lib/cocoa/src/TProcessorFactory.h @@ -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. + */ + +#import +#import "TProcessor.h" + +NS_ASSUME_NONNULL_BEGIN + + +@protocol TProcessorFactory + +-(id) processorForTransport:(id)transport; + +@end + + +NS_ASSUME_NONNULL_END diff --git a/vendor/github.com/apache/thrift/lib/cocoa/src/TSharedProcessorFactory.h b/vendor/github.com/apache/thrift/lib/cocoa/src/TSharedProcessorFactory.h new file mode 100644 index 000000000..c75fad1ee --- /dev/null +++ b/vendor/github.com/apache/thrift/lib/cocoa/src/TSharedProcessorFactory.h @@ -0,0 +1,28 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#import +#import "TProcessorFactory.h" + + +@interface TSharedProcessorFactory : NSObject + +-(id) initWithSharedProcessor:(id)sharedProcessor; + +@end diff --git a/vendor/github.com/apache/thrift/lib/cocoa/src/Thrift.h b/vendor/github.com/apache/thrift/lib/cocoa/src/Thrift.h new file mode 100644 index 000000000..5c72a01c7 --- /dev/null +++ b/vendor/github.com/apache/thrift/lib/cocoa/src/Thrift.h @@ -0,0 +1,20 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#define ThriftVersion @"0.10.0" diff --git a/vendor/github.com/apache/thrift/lib/cocoa/src/protocol/TBase.h b/vendor/github.com/apache/thrift/lib/cocoa/src/protocol/TBase.h new file mode 100644 index 000000000..b31061ec0 --- /dev/null +++ b/vendor/github.com/apache/thrift/lib/cocoa/src/protocol/TBase.h @@ -0,0 +1,46 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#import + +#import "TProtocol.h" + +@protocol TBase + +/** + * De-serialize object from the given input protocol + * + * @param input protocol used for reading + */ +-(BOOL) read:(id )inProtocol error:(NSError **)error; + +/** + * Serialize object to the given protocol + * + * @param buf output protocol used for writing + */ +-(BOOL) write:(id )outProtocol error:(NSError **)error; + + +/** + * Validate required fields + */ +-(BOOL) validate:(NSError *__autoreleasing *)__thriftError; + +@end diff --git a/vendor/github.com/apache/thrift/lib/cocoa/src/protocol/TBinaryProtocol.h b/vendor/github.com/apache/thrift/lib/cocoa/src/protocol/TBinaryProtocol.h new file mode 100644 index 000000000..bb90fadcb --- /dev/null +++ b/vendor/github.com/apache/thrift/lib/cocoa/src/protocol/TBinaryProtocol.h @@ -0,0 +1,49 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#import "TProtocol.h" +#import "TTransport.h" +#import "TProtocolFactory.h" + +NS_ASSUME_NONNULL_BEGIN + + +@interface TBinaryProtocol : NSObject + +@property (assign, nonatomic) UInt32 messageSizeLimit; + +-(id) initWithTransport:(id )transport; + +-(id) initWithTransport:(id )transport + strictRead:(BOOL)strictRead + strictWrite:(BOOL)strictWrite; + +@end; + + +@interface TBinaryProtocolFactory : NSObject + ++(TBinaryProtocolFactory *) sharedFactory; + +-(TBinaryProtocol *) newProtocolOnTransport:(id )transport; + +@end + + +NS_ASSUME_NONNULL_END \ No newline at end of file diff --git a/vendor/github.com/apache/thrift/lib/cocoa/src/protocol/TCompactProtocol.h b/vendor/github.com/apache/thrift/lib/cocoa/src/protocol/TCompactProtocol.h new file mode 100644 index 000000000..3f6accc5a --- /dev/null +++ b/vendor/github.com/apache/thrift/lib/cocoa/src/protocol/TCompactProtocol.h @@ -0,0 +1,42 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#import "TProtocol.h" +#import "TTransport.h" +#import "TProtocolFactory.h" + +NS_ASSUME_NONNULL_BEGIN + + +@interface TCompactProtocol : NSObject + +-(id) initWithTransport:(id )transport; + +@end + +@interface TCompactProtocolFactory : NSObject + ++(TCompactProtocolFactory *) sharedFactory; + +-(TCompactProtocol *) newProtocolOnTransport:(id )transport; + +@end + + +NS_ASSUME_NONNULL_END \ No newline at end of file diff --git a/vendor/github.com/apache/thrift/lib/cocoa/src/protocol/TMultiplexedProtocol.h b/vendor/github.com/apache/thrift/lib/cocoa/src/protocol/TMultiplexedProtocol.h new file mode 100644 index 000000000..b8ce361f5 --- /dev/null +++ b/vendor/github.com/apache/thrift/lib/cocoa/src/protocol/TMultiplexedProtocol.h @@ -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. + */ + +#import + +#import "TProtocolDecorator.h" + +NS_ASSUME_NONNULL_BEGIN + + +extern NSString *TMultiplexedProtocolSeperator; + + +@interface TMultiplexedProtocol : TProtocolDecorator + +-(id) initWithProtocol:(id )protocol + serviceName:(NSString *)name; + +@end + + +NS_ASSUME_NONNULL_END \ No newline at end of file diff --git a/vendor/github.com/apache/thrift/lib/cocoa/src/protocol/TProtocol.h b/vendor/github.com/apache/thrift/lib/cocoa/src/protocol/TProtocol.h new file mode 100644 index 000000000..841059f51 --- /dev/null +++ b/vendor/github.com/apache/thrift/lib/cocoa/src/protocol/TProtocol.h @@ -0,0 +1,164 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#import + +#import "TTransport.h" + + +NS_ASSUME_NONNULL_BEGIN + + +typedef NS_ENUM (int, TMessageType) { + TMessageTypeCALL = 1, + TMessageTypeREPLY = 2, + TMessageTypeEXCEPTION = 3, + TMessageTypeONEWAY = 4 +}; + +typedef NS_ENUM (int, TType) { + TTypeSTOP = 0, + TTypeVOID = 1, + TTypeBOOL = 2, + TTypeBYTE = 3, + TTypeDOUBLE = 4, + TTypeI16 = 6, + TTypeI32 = 8, + TTypeI64 = 10, + TTypeSTRING = 11, + TTypeSTRUCT = 12, + TTypeMAP = 13, + TTypeSET = 14, + TTypeLIST = 15 +}; + + +@protocol TProtocol + +-(id ) transport; + +-(BOOL) readMessageBeginReturningName:(NSString *__nullable __autoreleasing *__nullable)name + type:(nullable SInt32 *)type + sequenceID:(nullable SInt32 *)sequenceID + error:(NSError *__autoreleasing *)error; +-(BOOL) readMessageEnd:(NSError *__autoreleasing *)error; + +-(BOOL) readStructBeginReturningName:(NSString *__nullable __autoreleasing *__nullable)name + error:(NSError *__autoreleasing *)error; +-(BOOL) readStructEnd:(NSError *__autoreleasing *)error; + +-(BOOL) readFieldBeginReturningName:(NSString *__nullable __autoreleasing *__nullable)name + type:(SInt32 *)fieldType + fieldID:(nullable SInt32 *)fieldID + error:(NSError *__autoreleasing *)error; +-(BOOL) readFieldEnd:(NSError *__autoreleasing *)error; + +-(BOOL) readString:(NSString *__nonnull __autoreleasing *__nonnull)value error:(NSError **)error; + +-(BOOL) readBool:(BOOL *)value error:(NSError *__autoreleasing *)error; + +-(BOOL) readByte:(UInt8 *)value error:(NSError *__autoreleasing *)error; + +-(BOOL) readI16:(SInt16 *)value error:(NSError *__autoreleasing *)error; + +-(BOOL) readI32:(SInt32 *)value error:(NSError *__autoreleasing *)error; + +-(BOOL) readI64:(SInt64 *)value error:(NSError *__autoreleasing *)error; + +-(BOOL) readDouble:(double *)value error:(NSError *__autoreleasing *)error; + +-(BOOL) readBinary:(NSData *__nonnull __autoreleasing *__nonnull)value error:(NSError **)error; + +-(BOOL) readMapBeginReturningKeyType:(nullable SInt32 *)keyType + valueType:(nullable SInt32 *)valueType + size:(SInt32 *)size + error:(NSError *__autoreleasing *)error; +-(BOOL) readMapEnd:(NSError *__autoreleasing *)error; + + +-(BOOL) readSetBeginReturningElementType:(nullable SInt32 *)elementType + size:(SInt32 *)size + error:(NSError *__autoreleasing *)error; +-(BOOL) readSetEnd:(NSError *__autoreleasing *)error; + + +-(BOOL) readListBeginReturningElementType:(nullable SInt32 *)elementType + size:(SInt32 *)size + error:(NSError *__autoreleasing *)error; +-(BOOL) readListEnd:(NSError *__autoreleasing *)error; + + +-(BOOL) writeMessageBeginWithName:(NSString *)name + type:(SInt32)messageType + sequenceID:(SInt32)sequenceID + error:(NSError *__autoreleasing *)error; +-(BOOL) writeMessageEnd:(NSError *__autoreleasing *)error; + +-(BOOL) writeStructBeginWithName:(NSString *)name error:(NSError **)error; +-(BOOL) writeStructEnd:(NSError *__autoreleasing *)error; + +-(BOOL) writeFieldBeginWithName:(NSString *)name + type:(SInt32)fieldType + fieldID:(SInt32)fieldID + error:(NSError *__autoreleasing *)error; + +-(BOOL) writeI32:(SInt32)value error:(NSError *__autoreleasing *)error; + +-(BOOL) writeI64:(SInt64)value error:(NSError *__autoreleasing *)error; + +-(BOOL) writeI16:(short)value error:(NSError *__autoreleasing *)error; + +-(BOOL) writeByte:(UInt8)value error:(NSError *__autoreleasing *)error; + +-(BOOL) writeString:(NSString *)value error:(NSError *__autoreleasing *)error; + +-(BOOL) writeDouble:(double)value error:(NSError *__autoreleasing *)error; + +-(BOOL) writeBool:(BOOL)value error:(NSError *__autoreleasing *)error; + +-(BOOL) writeBinary:(NSData *)data error:(NSError *__autoreleasing *)error; + +-(BOOL) writeFieldStop:(NSError *__autoreleasing *)error; + +-(BOOL) writeFieldEnd:(NSError *__autoreleasing *)error; + +-(BOOL) writeMapBeginWithKeyType:(SInt32)keyType + valueType:(SInt32)valueType + size:(SInt32)size + error:(NSError *__autoreleasing *)error; +-(BOOL) writeMapEnd:(NSError *__autoreleasing *)error; + + +-(BOOL) writeSetBeginWithElementType:(SInt32)elementType + size:(SInt32)size + error:(NSError *__autoreleasing *)error; +-(BOOL) writeSetEnd:(NSError *__autoreleasing *)error; + + +-(BOOL) writeListBeginWithElementType:(SInt32)elementType + size:(SInt32)size + error:(NSError *__autoreleasing *)error; + +-(BOOL) writeListEnd:(NSError *__autoreleasing *)error; + + +@end + + +NS_ASSUME_NONNULL_END diff --git a/vendor/github.com/apache/thrift/lib/cocoa/src/protocol/TProtocolDecorator.h b/vendor/github.com/apache/thrift/lib/cocoa/src/protocol/TProtocolDecorator.h new file mode 100644 index 000000000..369b6a233 --- /dev/null +++ b/vendor/github.com/apache/thrift/lib/cocoa/src/protocol/TProtocolDecorator.h @@ -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. + */ + +#import + +#import "TProtocol.h" + +NS_ASSUME_NONNULL_BEGIN + + +@interface TProtocolDecorator : NSObject + +-(id) initWithProtocol:(id )protocol; + +@end + + +NS_ASSUME_NONNULL_END \ No newline at end of file diff --git a/vendor/github.com/apache/thrift/lib/cocoa/src/protocol/TProtocolError.h b/vendor/github.com/apache/thrift/lib/cocoa/src/protocol/TProtocolError.h new file mode 100644 index 000000000..ab0bc40da --- /dev/null +++ b/vendor/github.com/apache/thrift/lib/cocoa/src/protocol/TProtocolError.h @@ -0,0 +1,76 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#import "TError.h" + + +extern NSString *TProtocolErrorDomain; + +typedef NS_ENUM (int, TProtocolError) { + TProtocolErrorUnknown = 0, + TProtocolErrorInvalidData = 1, + TProtocolErrorNegativeSize = 2, + TProtocolErrorSizeLimit = 3, + TProtocolErrorBadVersion = 4, + TProtocolErrorNotImplemented = 5, + TProtocolErrorDepthLimit = 6, +}; + + +typedef NS_ENUM(int, TProtocolExtendedError) { + TProtocolExtendedErrorMissingRequiredField = 1001, + TProtocolExtendedErrorUnexpectedType = 1002, + TProtocolExtendedErrorMismatchedProtocol = 1003, +}; + +extern NSString *TProtocolErrorExtendedErrorKey; +extern NSString *TProtocolErrorFieldNameKey; +extern NSString *TProtocolErrorExpectedIdKey; +extern NSString *TProtocolErrorExpectedVersionKey; +extern NSString *TProtocolErrorTypeKey; +extern NSString *TProtocolErrorSourceLineKey; +extern NSString *TProtocolErrorSourceFileKey; +extern NSString *TProtocolErrorSourceMethodKey; +extern NSString *TProtocolErrorMessageNameKey; + + +#define PROTOCOL_ERROR(ret, err, ...) \ + if (error) { \ + *error = [NSError errorWithDomain:TProtocolErrorDomain \ + code:TProtocolError ## err \ + userInfo:@{NSLocalizedDescriptionKey: [NSString stringWithFormat:__VA_ARGS__], \ + @"SourceFile": [NSString stringWithUTF8String:__FILE__], \ + @"SourceLine": @(__LINE__), \ + @"SourceFunction": [NSString stringWithUTF8String:__PRETTY_FUNCTION__], \ + @"Message": self.currentMessageName ? self.currentMessageName : @""}]; \ + } \ + return ret + +#define PROTOCOL_TRANSPORT_ERROR(ret, errorPtr, ...) \ + if (errorPtr) { \ + *error = [NSError errorWithDomain:TProtocolErrorDomain \ + code:TProtocolErrorUnknown \ + userInfo:@{NSLocalizedDescriptionKey: [[NSString stringWithFormat:__VA_ARGS__] stringByAppendingFormat:@": %@", [(*errorPtr) localizedDescription]], \ + TProtocolErrorSourceFileKey: [NSString stringWithUTF8String:__FILE__], \ + TProtocolErrorSourceLineKey: @(__LINE__), \ + TProtocolErrorSourceMethodKey: [NSString stringWithUTF8String:__PRETTY_FUNCTION__], \ + TProtocolErrorMessageNameKey: self.currentMessageName ? self.currentMessageName : @"", \ + NSUnderlyingErrorKey: *errorPtr}]; \ + } \ + return ret diff --git a/vendor/github.com/apache/thrift/lib/cocoa/src/protocol/TProtocolFactory.h b/vendor/github.com/apache/thrift/lib/cocoa/src/protocol/TProtocolFactory.h new file mode 100644 index 000000000..a022a7f9f --- /dev/null +++ b/vendor/github.com/apache/thrift/lib/cocoa/src/protocol/TProtocolFactory.h @@ -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. + */ + +#import +#import "TProtocol.h" +#import "TTransport.h" + +NS_ASSUME_NONNULL_BEGIN + + +@protocol TProtocolFactory + +@property (readonly, nonatomic) NSString *protocolName; + +-(id) newProtocolOnTransport:(id)transport; + +@end + + +NS_ASSUME_NONNULL_END diff --git a/vendor/github.com/apache/thrift/lib/cocoa/src/protocol/TProtocolUtil.h b/vendor/github.com/apache/thrift/lib/cocoa/src/protocol/TProtocolUtil.h new file mode 100644 index 000000000..82510cfca --- /dev/null +++ b/vendor/github.com/apache/thrift/lib/cocoa/src/protocol/TProtocolUtil.h @@ -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. + */ + +#import "TProtocol.h" +#import "TTransport.h" + +NS_ASSUME_NONNULL_BEGIN + + +@interface TProtocolUtil : NSObject + ++(BOOL) skipType:(int)type onProtocol:(id )protocol error:(NSError **)error; + +@end; + + +NS_ASSUME_NONNULL_END \ No newline at end of file diff --git a/vendor/github.com/apache/thrift/lib/cocoa/src/server/TSocketServer.h b/vendor/github.com/apache/thrift/lib/cocoa/src/server/TSocketServer.h new file mode 100644 index 000000000..fe657ea11 --- /dev/null +++ b/vendor/github.com/apache/thrift/lib/cocoa/src/server/TSocketServer.h @@ -0,0 +1,47 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#import +#import "TProtocolFactory.h" +#import "TProcessorFactory.h" + +#if !TARGET_OS_IPHONE +#import +#else +#import +#endif + +NS_ASSUME_NONNULL_BEGIN + + +extern NSString *const TSocketServerClientConnectionFinished; +extern NSString *const TSocketServerProcessorKey; +extern NSString *const TSockerServerTransportKey; + + +@interface TSocketServer : NSObject + +-(instancetype) initWithPort:(int)port + protocolFactory:(id )protocolFactory + processorFactory:(id )processorFactory; + +@end + + +NS_ASSUME_NONNULL_END diff --git a/vendor/github.com/apache/thrift/lib/cocoa/src/transport/TAsyncTransport.h b/vendor/github.com/apache/thrift/lib/cocoa/src/transport/TAsyncTransport.h new file mode 100644 index 000000000..bab4fbdcd --- /dev/null +++ b/vendor/github.com/apache/thrift/lib/cocoa/src/transport/TAsyncTransport.h @@ -0,0 +1,46 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#import "TTransport.h" + +NS_ASSUME_NONNULL_BEGIN + + +@protocol TAsyncTransport; + + +@protocol TAsyncTransportFactory + +-(id) newTransport; + +@end + + +typedef void (^TAsyncCompletionBlock)(); +typedef void (^TAsyncFailureBlock)(NSError * __nonnull); + + +@protocol TAsyncTransport + +-(void) flushWithCompletion:(TAsyncCompletionBlock)completed failure:(TAsyncFailureBlock)failure; + +@end + + +NS_ASSUME_NONNULL_END \ No newline at end of file diff --git a/vendor/github.com/apache/thrift/lib/cocoa/src/transport/TFramedTransport.h b/vendor/github.com/apache/thrift/lib/cocoa/src/transport/TFramedTransport.h new file mode 100644 index 000000000..ea68ac44d --- /dev/null +++ b/vendor/github.com/apache/thrift/lib/cocoa/src/transport/TFramedTransport.h @@ -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. + */ + +#import +#import "TTransport.h" + +NS_ASSUME_NONNULL_BEGIN + + +@interface TFramedTransport : NSObject + +-(id) initWithTransport:(id )transport; + +@end + + +NS_ASSUME_NONNULL_END diff --git a/vendor/github.com/apache/thrift/lib/cocoa/src/transport/THTTPSessionTransport.h b/vendor/github.com/apache/thrift/lib/cocoa/src/transport/THTTPSessionTransport.h new file mode 100644 index 000000000..003499b80 --- /dev/null +++ b/vendor/github.com/apache/thrift/lib/cocoa/src/transport/THTTPSessionTransport.h @@ -0,0 +1,47 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#import +#import "TAsyncTransport.h" + +NS_ASSUME_NONNULL_BEGIN + + +typedef NSError *__nullable (^THTTPSessionTransportResponseValidateBlock) (NSHTTPURLResponse *response, NSData *responseData); + + +@interface THTTPSessionTransportFactory : NSObject + +@property (strong, nonatomic) THTTPSessionTransportResponseValidateBlock responseValidate; + ++(void) setupDefaultsForSessionConfiguration:(NSURLSessionConfiguration *)config + withProtocolName:(NSString *)protocolName; + +-(id) initWithSession:(NSURLSession *)session + URL:(NSURL *)aURL; + +@end + + +@interface THTTPSessionTransport : NSObject + +@end + + +NS_ASSUME_NONNULL_END diff --git a/vendor/github.com/apache/thrift/lib/cocoa/src/transport/THTTPTransport.h b/vendor/github.com/apache/thrift/lib/cocoa/src/transport/THTTPTransport.h new file mode 100644 index 000000000..3c35daf9e --- /dev/null +++ b/vendor/github.com/apache/thrift/lib/cocoa/src/transport/THTTPTransport.h @@ -0,0 +1,39 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#import +#import "TTransport.h" + +NS_ASSUME_NONNULL_BEGIN + + +@interface THTTPTransport : NSObject + +-(id) initWithURL:(NSURL *)aURL; + +-(id) initWithURL:(NSURL *)aURL + userAgent:(nullable NSString *)userAgent + timeout:(int)timeout; + +-(void) setURL:(NSURL *)aURL; + +@end + + +NS_ASSUME_NONNULL_END diff --git a/vendor/github.com/apache/thrift/lib/cocoa/src/transport/TMemoryBuffer.h b/vendor/github.com/apache/thrift/lib/cocoa/src/transport/TMemoryBuffer.h new file mode 100644 index 000000000..6249d3209 --- /dev/null +++ b/vendor/github.com/apache/thrift/lib/cocoa/src/transport/TMemoryBuffer.h @@ -0,0 +1,37 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#import +#import "TTransport.h" + +NS_ASSUME_NONNULL_BEGIN + + +@interface TMemoryBuffer : NSObject + +-(NSData *) buffer; + +-(id) initWithData:(NSData *)data; + +-(id) initWithDataNoCopy:(NSMutableData *)data; + +@end + + +NS_ASSUME_NONNULL_END diff --git a/vendor/github.com/apache/thrift/lib/cocoa/src/transport/TNSFileHandleTransport.h b/vendor/github.com/apache/thrift/lib/cocoa/src/transport/TNSFileHandleTransport.h new file mode 100644 index 000000000..db6edf383 --- /dev/null +++ b/vendor/github.com/apache/thrift/lib/cocoa/src/transport/TNSFileHandleTransport.h @@ -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. + */ + + +#import +#import "TTransport.h" + +NS_ASSUME_NONNULL_BEGIN + + +@interface TNSFileHandleTransport : NSObject + +-(id) initWithFileHandle:(NSFileHandle *)fileHandle; + +-(id) initWithInputFileHandle:(NSFileHandle *)inputFileHandle + outputFileHandle:(NSFileHandle *)outputFileHandle; + + +@end + + +NS_ASSUME_NONNULL_END diff --git a/vendor/github.com/apache/thrift/lib/cocoa/src/transport/TNSStreamTransport.h b/vendor/github.com/apache/thrift/lib/cocoa/src/transport/TNSStreamTransport.h new file mode 100644 index 000000000..54c488444 --- /dev/null +++ b/vendor/github.com/apache/thrift/lib/cocoa/src/transport/TNSStreamTransport.h @@ -0,0 +1,43 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#import +#import "TTransport.h" + +NS_ASSUME_NONNULL_BEGIN + + +@interface TNSStreamTransport : NSObject + +@property (strong, nonatomic) NSInputStream *input; +@property (strong, nonatomic) NSOutputStream *output; + +-(id) initWithInputStream:(nullable NSInputStream *)input + outputStream:(nullable NSOutputStream *)output; + +-(id) initWithInputStream:(NSInputStream *)input; + +-(id) initWithOutputStream:(NSOutputStream *)output; + +-(void) close; + +@end + + +NS_ASSUME_NONNULL_END diff --git a/vendor/github.com/apache/thrift/lib/cocoa/src/transport/TSSLSocketTransport.h b/vendor/github.com/apache/thrift/lib/cocoa/src/transport/TSSLSocketTransport.h new file mode 100644 index 000000000..b606c4a33 --- /dev/null +++ b/vendor/github.com/apache/thrift/lib/cocoa/src/transport/TSSLSocketTransport.h @@ -0,0 +1,37 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#import +#import "TNSStreamTransport.h" + +NS_ASSUME_NONNULL_BEGIN + + +@interface TSSLSocketTransport : TNSStreamTransport + +-(id) initWithHostname:(NSString *)hostname + port:(int)port + error:(NSError **)error; + +-(BOOL) isOpen; + +@end + + +NS_ASSUME_NONNULL_END diff --git a/vendor/github.com/apache/thrift/lib/cocoa/src/transport/TSSLSocketTransportError.h b/vendor/github.com/apache/thrift/lib/cocoa/src/transport/TSSLSocketTransportError.h new file mode 100644 index 000000000..e17f39e32 --- /dev/null +++ b/vendor/github.com/apache/thrift/lib/cocoa/src/transport/TSSLSocketTransportError.h @@ -0,0 +1,30 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#import "TTransportError.h" + + +extern NSString *TSSLSocketTransportErrorDomain; + + +typedef NS_ENUM (int, TSSLSocketTransportError) { + TSSLSocketTransportErrorHostanameResolution = -10000, + TSSLSocketTransportErrorSocketCreate = -10001, + TSSLSocketTransportErrorConnect = -10002, +}; diff --git a/vendor/github.com/apache/thrift/lib/cocoa/src/transport/TSocketTransport.h b/vendor/github.com/apache/thrift/lib/cocoa/src/transport/TSocketTransport.h new file mode 100644 index 000000000..4ea03cc73 --- /dev/null +++ b/vendor/github.com/apache/thrift/lib/cocoa/src/transport/TSocketTransport.h @@ -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. + */ + +#import +#import "TNSStreamTransport.h" + +NS_ASSUME_NONNULL_BEGIN + + +@interface TSocketTransport : TNSStreamTransport + +-(id) initWithHostname:(NSString *)hostname + port:(int)port; + +@end + + +NS_ASSUME_NONNULL_END diff --git a/vendor/github.com/apache/thrift/lib/cocoa/src/transport/TTransport.h b/vendor/github.com/apache/thrift/lib/cocoa/src/transport/TTransport.h new file mode 100644 index 000000000..558cf60fb --- /dev/null +++ b/vendor/github.com/apache/thrift/lib/cocoa/src/transport/TTransport.h @@ -0,0 +1,48 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#import + + +NS_ASSUME_NONNULL_BEGIN + + +@protocol TTransport + +/** + * Guarantees that all of len bytes are read + * + * @param buf Buffer to read into + * @param off Index in buffer to start storing bytes at + * @param len Maximum number of bytes to read + * @return YES if succeeded, NO if failed + * @throws TTransportError if there was an error reading data + */ +-(BOOL) readAll:(UInt8 *)buf offset:(UInt32)off length:(UInt32)len error:(NSError *__autoreleasing *)error; + +-(UInt32) readAvail:(UInt8 *)buf offset:(UInt32)off maxLength:(UInt32)maxLen error:(NSError *__autoreleasing *)error; + +-(BOOL) write:(const UInt8 *)data offset:(UInt32)offset length:(UInt32)length error:(NSError *__autoreleasing *)error; + +-(BOOL) flush:(NSError *__autoreleasing *)error; + +@end + + +NS_ASSUME_NONNULL_END diff --git a/vendor/github.com/apache/thrift/lib/cocoa/src/transport/TTransportError.h b/vendor/github.com/apache/thrift/lib/cocoa/src/transport/TTransportError.h new file mode 100644 index 000000000..c8c9f067f --- /dev/null +++ b/vendor/github.com/apache/thrift/lib/cocoa/src/transport/TTransportError.h @@ -0,0 +1,43 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#import "TError.h" + + +extern NSString *TTransportErrorDomain; + + +typedef NS_ENUM (int, TTransportError) { + TTransportErrorUnknown = 0, + TTransportErrorNotOpen = 1, + TTransportErrorAlreadyOpen = 2, + TTransportErrorTimedOut = 3, + TTransportErrorEndOfFile = 4, +}; + + +extern NSString *TTransportErrorExtendedErrorKey; +extern NSString *TTransportErrorHttpErrorKey; + + +typedef NS_ENUM(int, THttpTransportError) { + THttpTransportErrorInvalidResponse = 1001, + THttpTransportErrorInvalidStatus = 1002, + THttpTransportErrorAuthentication = 1003, +}; diff --git a/vendor/github.com/apache/thrift/lib/go/README.md b/vendor/github.com/apache/thrift/lib/go/README.md new file mode 100644 index 000000000..7440474c3 --- /dev/null +++ b/vendor/github.com/apache/thrift/lib/go/README.md @@ -0,0 +1,81 @@ +Thrift Go Software Library + +License +======= + +Licensed to the Apache Software Foundation (ASF) under one +or more contributor license agreements. See the NOTICE file +distributed with this work for additional information +regarding copyright ownership. The ASF licenses this file +to you under the Apache License, Version 2.0 (the +"License"); you may not use this file except in compliance +with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, +software distributed under the License is distributed on an +"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +KIND, either express or implied. See the License for the +specific language governing permissions and limitations +under the License. + + +Using Thrift with Go +==================== + +In following Go conventions, we recommend you use the 'go' tool to install +Thrift for go. + + $ go get git.apache.org/thrift.git/lib/go/thrift/... + +Will retrieve and install the most recent version of the package. + + +A note about optional fields +============================ + +The thrift-to-Go compiler tries to represent thrift IDL structs as Go structs. +We must be able to distinguish between optional fields that are set to their +default value and optional values which are actually unset, so the generated +code represents optional fields via pointers. + +This is generally intuitive and works well much of the time, but Go does not +have a syntax for creating a pointer to a constant in a single expression. That +is, given a struct like + + struct SomeIDLType { + OptionalField *int32 + } + +, the following will not compile: + + x := &SomeIDLType{ + OptionalField: &(3), + } + +(Nor is there any other syntax that's built in to the language) + +As such, we provide some helpers that do just this under lib/go/thrift/. E.g., + + x := &SomeIDLType{ + OptionalField: thrift.Int32Ptr(3), + } + +And so on. The code generator also creates analogous helpers for user-defined +typedefs and enums. + +Adding custom tags to generated Thrift structs +============================================== + +You can add tags to the auto-generated thrift structs using the following format: + + struct foo { + 1: required string Bar (go.tag = "some_tag:\"some_tag_value\"") + } + +which will generate: + + type Foo struct { + Bar string `thrift:"bar,1,required" some_tag:"some_tag_value"` + } diff --git a/vendor/github.com/apache/thrift/lib/go/thrift/application_exception.go b/vendor/github.com/apache/thrift/lib/go/thrift/application_exception.go new file mode 100644 index 000000000..6655cc5a9 --- /dev/null +++ b/vendor/github.com/apache/thrift/lib/go/thrift/application_exception.go @@ -0,0 +1,142 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package thrift + +const ( + UNKNOWN_APPLICATION_EXCEPTION = 0 + UNKNOWN_METHOD = 1 + INVALID_MESSAGE_TYPE_EXCEPTION = 2 + WRONG_METHOD_NAME = 3 + BAD_SEQUENCE_ID = 4 + MISSING_RESULT = 5 + INTERNAL_ERROR = 6 + PROTOCOL_ERROR = 7 +) + +// Application level Thrift exception +type TApplicationException interface { + TException + TypeId() int32 + Read(iprot TProtocol) (TApplicationException, error) + Write(oprot TProtocol) error +} + +type tApplicationException struct { + message string + type_ int32 +} + +func (e tApplicationException) Error() string { + return e.message +} + +func NewTApplicationException(type_ int32, message string) TApplicationException { + return &tApplicationException{message, type_} +} + +func (p *tApplicationException) TypeId() int32 { + return p.type_ +} + +func (p *tApplicationException) Read(iprot TProtocol) (TApplicationException, error) { + _, err := iprot.ReadStructBegin() + if err != nil { + return nil, err + } + + message := "" + type_ := int32(UNKNOWN_APPLICATION_EXCEPTION) + + for { + _, ttype, id, err := iprot.ReadFieldBegin() + if err != nil { + return nil, err + } + if ttype == STOP { + break + } + switch id { + case 1: + if ttype == STRING { + if message, err = iprot.ReadString(); err != nil { + return nil, err + } + } else { + if err = SkipDefaultDepth(iprot, ttype); err != nil { + return nil, err + } + } + case 2: + if ttype == I32 { + if type_, err = iprot.ReadI32(); err != nil { + return nil, err + } + } else { + if err = SkipDefaultDepth(iprot, ttype); err != nil { + return nil, err + } + } + default: + if err = SkipDefaultDepth(iprot, ttype); err != nil { + return nil, err + } + } + if err = iprot.ReadFieldEnd(); err != nil { + return nil, err + } + } + return NewTApplicationException(type_, message), iprot.ReadStructEnd() +} + +func (p *tApplicationException) Write(oprot TProtocol) (err error) { + err = oprot.WriteStructBegin("TApplicationException") + if len(p.Error()) > 0 { + err = oprot.WriteFieldBegin("message", STRING, 1) + if err != nil { + return + } + err = oprot.WriteString(p.Error()) + if err != nil { + return + } + err = oprot.WriteFieldEnd() + if err != nil { + return + } + } + err = oprot.WriteFieldBegin("type", I32, 2) + if err != nil { + return + } + err = oprot.WriteI32(p.type_) + if err != nil { + return + } + err = oprot.WriteFieldEnd() + if err != nil { + return + } + err = oprot.WriteFieldStop() + if err != nil { + return + } + err = oprot.WriteStructEnd() + return +} diff --git a/vendor/github.com/apache/thrift/lib/go/thrift/binary_protocol.go b/vendor/github.com/apache/thrift/lib/go/thrift/binary_protocol.go new file mode 100644 index 000000000..690d34111 --- /dev/null +++ b/vendor/github.com/apache/thrift/lib/go/thrift/binary_protocol.go @@ -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. + */ + +package thrift + +import ( + "bytes" + "encoding/binary" + "errors" + "fmt" + "io" + "math" +) + +type TBinaryProtocol struct { + trans TRichTransport + origTransport TTransport + reader io.Reader + writer io.Writer + strictRead bool + strictWrite bool + buffer [64]byte +} + +type TBinaryProtocolFactory struct { + strictRead bool + strictWrite bool +} + +func NewTBinaryProtocolTransport(t TTransport) *TBinaryProtocol { + return NewTBinaryProtocol(t, false, true) +} + +func NewTBinaryProtocol(t TTransport, strictRead, strictWrite bool) *TBinaryProtocol { + p := &TBinaryProtocol{origTransport: t, strictRead: strictRead, strictWrite: strictWrite} + if et, ok := t.(TRichTransport); ok { + p.trans = et + } else { + p.trans = NewTRichTransport(t) + } + p.reader = p.trans + p.writer = p.trans + return p +} + +func NewTBinaryProtocolFactoryDefault() *TBinaryProtocolFactory { + return NewTBinaryProtocolFactory(false, true) +} + +func NewTBinaryProtocolFactory(strictRead, strictWrite bool) *TBinaryProtocolFactory { + return &TBinaryProtocolFactory{strictRead: strictRead, strictWrite: strictWrite} +} + +func (p *TBinaryProtocolFactory) GetProtocol(t TTransport) TProtocol { + return NewTBinaryProtocol(t, p.strictRead, p.strictWrite) +} + +/** + * Writing Methods + */ + +func (p *TBinaryProtocol) WriteMessageBegin(name string, typeId TMessageType, seqId int32) error { + if p.strictWrite { + version := uint32(VERSION_1) | uint32(typeId) + e := p.WriteI32(int32(version)) + if e != nil { + return e + } + e = p.WriteString(name) + if e != nil { + return e + } + e = p.WriteI32(seqId) + return e + } else { + e := p.WriteString(name) + if e != nil { + return e + } + e = p.WriteByte(int8(typeId)) + if e != nil { + return e + } + e = p.WriteI32(seqId) + return e + } + return nil +} + +func (p *TBinaryProtocol) WriteMessageEnd() error { + return nil +} + +func (p *TBinaryProtocol) WriteStructBegin(name string) error { + return nil +} + +func (p *TBinaryProtocol) WriteStructEnd() error { + return nil +} + +func (p *TBinaryProtocol) WriteFieldBegin(name string, typeId TType, id int16) error { + e := p.WriteByte(int8(typeId)) + if e != nil { + return e + } + e = p.WriteI16(id) + return e +} + +func (p *TBinaryProtocol) WriteFieldEnd() error { + return nil +} + +func (p *TBinaryProtocol) WriteFieldStop() error { + e := p.WriteByte(STOP) + return e +} + +func (p *TBinaryProtocol) WriteMapBegin(keyType TType, valueType TType, size int) error { + e := p.WriteByte(int8(keyType)) + if e != nil { + return e + } + e = p.WriteByte(int8(valueType)) + if e != nil { + return e + } + e = p.WriteI32(int32(size)) + return e +} + +func (p *TBinaryProtocol) WriteMapEnd() error { + return nil +} + +func (p *TBinaryProtocol) WriteListBegin(elemType TType, size int) error { + e := p.WriteByte(int8(elemType)) + if e != nil { + return e + } + e = p.WriteI32(int32(size)) + return e +} + +func (p *TBinaryProtocol) WriteListEnd() error { + return nil +} + +func (p *TBinaryProtocol) WriteSetBegin(elemType TType, size int) error { + e := p.WriteByte(int8(elemType)) + if e != nil { + return e + } + e = p.WriteI32(int32(size)) + return e +} + +func (p *TBinaryProtocol) WriteSetEnd() error { + return nil +} + +func (p *TBinaryProtocol) WriteBool(value bool) error { + if value { + return p.WriteByte(1) + } + return p.WriteByte(0) +} + +func (p *TBinaryProtocol) WriteByte(value int8) error { + e := p.trans.WriteByte(byte(value)) + return NewTProtocolException(e) +} + +func (p *TBinaryProtocol) WriteI16(value int16) error { + v := p.buffer[0:2] + binary.BigEndian.PutUint16(v, uint16(value)) + _, e := p.writer.Write(v) + return NewTProtocolException(e) +} + +func (p *TBinaryProtocol) WriteI32(value int32) error { + v := p.buffer[0:4] + binary.BigEndian.PutUint32(v, uint32(value)) + _, e := p.writer.Write(v) + return NewTProtocolException(e) +} + +func (p *TBinaryProtocol) WriteI64(value int64) error { + v := p.buffer[0:8] + binary.BigEndian.PutUint64(v, uint64(value)) + _, err := p.writer.Write(v) + return NewTProtocolException(err) +} + +func (p *TBinaryProtocol) WriteDouble(value float64) error { + return p.WriteI64(int64(math.Float64bits(value))) +} + +func (p *TBinaryProtocol) WriteString(value string) error { + e := p.WriteI32(int32(len(value))) + if e != nil { + return e + } + _, err := p.trans.WriteString(value) + return NewTProtocolException(err) +} + +func (p *TBinaryProtocol) WriteBinary(value []byte) error { + e := p.WriteI32(int32(len(value))) + if e != nil { + return e + } + _, err := p.writer.Write(value) + return NewTProtocolException(err) +} + +/** + * Reading methods + */ + +func (p *TBinaryProtocol) ReadMessageBegin() (name string, typeId TMessageType, seqId int32, err error) { + size, e := p.ReadI32() + if e != nil { + return "", typeId, 0, NewTProtocolException(e) + } + if size < 0 { + typeId = TMessageType(size & 0x0ff) + version := int64(int64(size) & VERSION_MASK) + if version != VERSION_1 { + return name, typeId, seqId, NewTProtocolExceptionWithType(BAD_VERSION, fmt.Errorf("Bad version in ReadMessageBegin")) + } + name, e = p.ReadString() + if e != nil { + return name, typeId, seqId, NewTProtocolException(e) + } + seqId, e = p.ReadI32() + if e != nil { + return name, typeId, seqId, NewTProtocolException(e) + } + return name, typeId, seqId, nil + } + if p.strictRead { + return name, typeId, seqId, NewTProtocolExceptionWithType(BAD_VERSION, fmt.Errorf("Missing version in ReadMessageBegin")) + } + name, e2 := p.readStringBody(size) + if e2 != nil { + return name, typeId, seqId, e2 + } + b, e3 := p.ReadByte() + if e3 != nil { + return name, typeId, seqId, e3 + } + typeId = TMessageType(b) + seqId, e4 := p.ReadI32() + if e4 != nil { + return name, typeId, seqId, e4 + } + return name, typeId, seqId, nil +} + +func (p *TBinaryProtocol) ReadMessageEnd() error { + return nil +} + +func (p *TBinaryProtocol) ReadStructBegin() (name string, err error) { + return +} + +func (p *TBinaryProtocol) ReadStructEnd() error { + return nil +} + +func (p *TBinaryProtocol) ReadFieldBegin() (name string, typeId TType, seqId int16, err error) { + t, err := p.ReadByte() + typeId = TType(t) + if err != nil { + return name, typeId, seqId, err + } + if t != STOP { + seqId, err = p.ReadI16() + } + return name, typeId, seqId, err +} + +func (p *TBinaryProtocol) ReadFieldEnd() error { + return nil +} + +var invalidDataLength = NewTProtocolExceptionWithType(INVALID_DATA, errors.New("Invalid data length")) + +func (p *TBinaryProtocol) ReadMapBegin() (kType, vType TType, size int, err error) { + k, e := p.ReadByte() + if e != nil { + err = NewTProtocolException(e) + return + } + kType = TType(k) + v, e := p.ReadByte() + if e != nil { + err = NewTProtocolException(e) + return + } + vType = TType(v) + size32, e := p.ReadI32() + if e != nil { + err = NewTProtocolException(e) + return + } + if size32 < 0 { + err = invalidDataLength + return + } + size = int(size32) + return kType, vType, size, nil +} + +func (p *TBinaryProtocol) ReadMapEnd() error { + return nil +} + +func (p *TBinaryProtocol) ReadListBegin() (elemType TType, size int, err error) { + b, e := p.ReadByte() + if e != nil { + err = NewTProtocolException(e) + return + } + elemType = TType(b) + size32, e := p.ReadI32() + if e != nil { + err = NewTProtocolException(e) + return + } + if size32 < 0 { + err = invalidDataLength + return + } + size = int(size32) + + return +} + +func (p *TBinaryProtocol) ReadListEnd() error { + return nil +} + +func (p *TBinaryProtocol) ReadSetBegin() (elemType TType, size int, err error) { + b, e := p.ReadByte() + if e != nil { + err = NewTProtocolException(e) + return + } + elemType = TType(b) + size32, e := p.ReadI32() + if e != nil { + err = NewTProtocolException(e) + return + } + if size32 < 0 { + err = invalidDataLength + return + } + size = int(size32) + return elemType, size, nil +} + +func (p *TBinaryProtocol) ReadSetEnd() error { + return nil +} + +func (p *TBinaryProtocol) ReadBool() (bool, error) { + b, e := p.ReadByte() + v := true + if b != 1 { + v = false + } + return v, e +} + +func (p *TBinaryProtocol) ReadByte() (int8, error) { + v, err := p.trans.ReadByte() + return int8(v), err +} + +func (p *TBinaryProtocol) ReadI16() (value int16, err error) { + buf := p.buffer[0:2] + err = p.readAll(buf) + value = int16(binary.BigEndian.Uint16(buf)) + return value, err +} + +func (p *TBinaryProtocol) ReadI32() (value int32, err error) { + buf := p.buffer[0:4] + err = p.readAll(buf) + value = int32(binary.BigEndian.Uint32(buf)) + return value, err +} + +func (p *TBinaryProtocol) ReadI64() (value int64, err error) { + buf := p.buffer[0:8] + err = p.readAll(buf) + value = int64(binary.BigEndian.Uint64(buf)) + return value, err +} + +func (p *TBinaryProtocol) ReadDouble() (value float64, err error) { + buf := p.buffer[0:8] + err = p.readAll(buf) + value = math.Float64frombits(binary.BigEndian.Uint64(buf)) + return value, err +} + +func (p *TBinaryProtocol) ReadString() (value string, err error) { + size, e := p.ReadI32() + if e != nil { + return "", e + } + if size < 0 { + err = invalidDataLength + return + } + + return p.readStringBody(size) +} + +func (p *TBinaryProtocol) ReadBinary() ([]byte, error) { + size, e := p.ReadI32() + if e != nil { + return nil, e + } + if size < 0 { + return nil, invalidDataLength + } + if uint64(size) > p.trans.RemainingBytes() { + return nil, invalidDataLength + } + + isize := int(size) + buf := make([]byte, isize) + _, err := io.ReadFull(p.trans, buf) + return buf, NewTProtocolException(err) +} + +func (p *TBinaryProtocol) Flush() (err error) { + return NewTProtocolException(p.trans.Flush()) +} + +func (p *TBinaryProtocol) Skip(fieldType TType) (err error) { + return SkipDefaultDepth(p, fieldType) +} + +func (p *TBinaryProtocol) Transport() TTransport { + return p.origTransport +} + +func (p *TBinaryProtocol) readAll(buf []byte) error { + _, err := io.ReadFull(p.reader, buf) + return NewTProtocolException(err) +} + +const readLimit = 32768 + +func (p *TBinaryProtocol) readStringBody(size int32) (value string, err error) { + if size < 0 { + return "", nil + } + if uint64(size) > p.trans.RemainingBytes() { + return "", invalidDataLength + } + + var ( + buf bytes.Buffer + e error + b []byte + ) + + switch { + case int(size) <= len(p.buffer): + b = p.buffer[:size] // avoids allocation for small reads + case int(size) < readLimit: + b = make([]byte, size) + default: + b = make([]byte, readLimit) + } + + for size > 0 { + _, e = io.ReadFull(p.trans, b) + buf.Write(b) + if e != nil { + break + } + size -= readLimit + if size < readLimit && size > 0 { + b = b[:size] + } + } + return buf.String(), NewTProtocolException(e) +} diff --git a/vendor/github.com/apache/thrift/lib/go/thrift/buffered_transport.go b/vendor/github.com/apache/thrift/lib/go/thrift/buffered_transport.go new file mode 100644 index 000000000..f73a98b6c --- /dev/null +++ b/vendor/github.com/apache/thrift/lib/go/thrift/buffered_transport.go @@ -0,0 +1,91 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package thrift + +import ( + "bufio" +) + +type TBufferedTransportFactory struct { + size int +} + +type TBufferedTransport struct { + bufio.ReadWriter + tp TTransport +} + +func (p *TBufferedTransportFactory) GetTransport(trans TTransport) TTransport { + return NewTBufferedTransport(trans, p.size) +} + +func NewTBufferedTransportFactory(bufferSize int) *TBufferedTransportFactory { + return &TBufferedTransportFactory{size: bufferSize} +} + +func NewTBufferedTransport(trans TTransport, bufferSize int) *TBufferedTransport { + return &TBufferedTransport{ + ReadWriter: bufio.ReadWriter{ + Reader: bufio.NewReaderSize(trans, bufferSize), + Writer: bufio.NewWriterSize(trans, bufferSize), + }, + tp: trans, + } +} + +func (p *TBufferedTransport) IsOpen() bool { + return p.tp.IsOpen() +} + +func (p *TBufferedTransport) Open() (err error) { + return p.tp.Open() +} + +func (p *TBufferedTransport) Close() (err error) { + return p.tp.Close() +} + +func (p *TBufferedTransport) Read(b []byte) (int, error) { + n, err := p.ReadWriter.Read(b) + if err != nil { + p.ReadWriter.Reader.Reset(p.tp) + } + return n, err +} + +func (p *TBufferedTransport) Write(b []byte) (int, error) { + n, err := p.ReadWriter.Write(b) + if err != nil { + p.ReadWriter.Writer.Reset(p.tp) + } + return n, err +} + +func (p *TBufferedTransport) Flush() error { + if err := p.ReadWriter.Flush(); err != nil { + p.ReadWriter.Writer.Reset(p.tp) + return err + } + return p.tp.Flush() +} + +func (p *TBufferedTransport) RemainingBytes() (num_bytes uint64) { + return p.tp.RemainingBytes() +} diff --git a/vendor/github.com/apache/thrift/lib/go/thrift/compact_protocol.go b/vendor/github.com/apache/thrift/lib/go/thrift/compact_protocol.go new file mode 100644 index 000000000..0bc5fddeb --- /dev/null +++ b/vendor/github.com/apache/thrift/lib/go/thrift/compact_protocol.go @@ -0,0 +1,815 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package thrift + +import ( + "encoding/binary" + "fmt" + "io" + "math" +) + +const ( + COMPACT_PROTOCOL_ID = 0x082 + COMPACT_VERSION = 1 + COMPACT_VERSION_MASK = 0x1f + COMPACT_TYPE_MASK = 0x0E0 + COMPACT_TYPE_BITS = 0x07 + COMPACT_TYPE_SHIFT_AMOUNT = 5 +) + +type tCompactType byte + +const ( + COMPACT_BOOLEAN_TRUE = 0x01 + COMPACT_BOOLEAN_FALSE = 0x02 + COMPACT_BYTE = 0x03 + COMPACT_I16 = 0x04 + COMPACT_I32 = 0x05 + COMPACT_I64 = 0x06 + COMPACT_DOUBLE = 0x07 + COMPACT_BINARY = 0x08 + COMPACT_LIST = 0x09 + COMPACT_SET = 0x0A + COMPACT_MAP = 0x0B + COMPACT_STRUCT = 0x0C +) + +var ( + ttypeToCompactType map[TType]tCompactType +) + +func init() { + ttypeToCompactType = map[TType]tCompactType{ + STOP: STOP, + BOOL: COMPACT_BOOLEAN_TRUE, + BYTE: COMPACT_BYTE, + I16: COMPACT_I16, + I32: COMPACT_I32, + I64: COMPACT_I64, + DOUBLE: COMPACT_DOUBLE, + STRING: COMPACT_BINARY, + LIST: COMPACT_LIST, + SET: COMPACT_SET, + MAP: COMPACT_MAP, + STRUCT: COMPACT_STRUCT, + } +} + +type TCompactProtocolFactory struct{} + +func NewTCompactProtocolFactory() *TCompactProtocolFactory { + return &TCompactProtocolFactory{} +} + +func (p *TCompactProtocolFactory) GetProtocol(trans TTransport) TProtocol { + return NewTCompactProtocol(trans) +} + +type TCompactProtocol struct { + trans TRichTransport + origTransport TTransport + + // Used to keep track of the last field for the current and previous structs, + // so we can do the delta stuff. + lastField []int + lastFieldId int + + // If we encounter a boolean field begin, save the TField here so it can + // have the value incorporated. + booleanFieldName string + booleanFieldId int16 + booleanFieldPending bool + + // If we read a field header, and it's a boolean field, save the boolean + // value here so that readBool can use it. + boolValue bool + boolValueIsNotNull bool + buffer [64]byte +} + +// Create a TCompactProtocol given a TTransport +func NewTCompactProtocol(trans TTransport) *TCompactProtocol { + p := &TCompactProtocol{origTransport: trans, lastField: []int{}} + if et, ok := trans.(TRichTransport); ok { + p.trans = et + } else { + p.trans = NewTRichTransport(trans) + } + + return p + +} + +// +// Public Writing methods. +// + +// Write a message header to the wire. Compact Protocol messages contain the +// protocol version so we can migrate forwards in the future if need be. +func (p *TCompactProtocol) WriteMessageBegin(name string, typeId TMessageType, seqid int32) error { + err := p.writeByteDirect(COMPACT_PROTOCOL_ID) + if err != nil { + return NewTProtocolException(err) + } + err = p.writeByteDirect((COMPACT_VERSION & COMPACT_VERSION_MASK) | ((byte(typeId) << COMPACT_TYPE_SHIFT_AMOUNT) & COMPACT_TYPE_MASK)) + if err != nil { + return NewTProtocolException(err) + } + _, err = p.writeVarint32(seqid) + if err != nil { + return NewTProtocolException(err) + } + e := p.WriteString(name) + return e + +} + +func (p *TCompactProtocol) WriteMessageEnd() error { return nil } + +// 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. +func (p *TCompactProtocol) WriteStructBegin(name string) error { + p.lastField = append(p.lastField, p.lastFieldId) + p.lastFieldId = 0 + return nil +} + +// 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. +func (p *TCompactProtocol) WriteStructEnd() error { + p.lastFieldId = p.lastField[len(p.lastField)-1] + p.lastField = p.lastField[:len(p.lastField)-1] + return nil +} + +func (p *TCompactProtocol) WriteFieldBegin(name string, typeId TType, id int16) error { + if typeId == BOOL { + // we want to possibly include the value, so we'll wait. + p.booleanFieldName, p.booleanFieldId, p.booleanFieldPending = name, id, true + return nil + } + _, err := p.writeFieldBeginInternal(name, typeId, id, 0xFF) + return NewTProtocolException(err) +} + +// 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. +func (p *TCompactProtocol) writeFieldBeginInternal(name string, typeId TType, id int16, typeOverride byte) (int, error) { + // short lastField = lastField_.pop(); + + // if there's a type override, use that. + var typeToWrite byte + if typeOverride == 0xFF { + typeToWrite = byte(p.getCompactType(typeId)) + } else { + typeToWrite = typeOverride + } + // check if we can use delta encoding for the field id + fieldId := int(id) + written := 0 + if fieldId > p.lastFieldId && fieldId-p.lastFieldId <= 15 { + // write them together + err := p.writeByteDirect(byte((fieldId-p.lastFieldId)<<4) | typeToWrite) + if err != nil { + return 0, err + } + } else { + // write them separate + err := p.writeByteDirect(typeToWrite) + if err != nil { + return 0, err + } + err = p.WriteI16(id) + written = 1 + 2 + if err != nil { + return 0, err + } + } + + p.lastFieldId = fieldId + // p.lastField.Push(field.id); + return written, nil +} + +func (p *TCompactProtocol) WriteFieldEnd() error { return nil } + +func (p *TCompactProtocol) WriteFieldStop() error { + err := p.writeByteDirect(STOP) + return NewTProtocolException(err) +} + +func (p *TCompactProtocol) WriteMapBegin(keyType TType, valueType TType, size int) error { + if size == 0 { + err := p.writeByteDirect(0) + return NewTProtocolException(err) + } + _, err := p.writeVarint32(int32(size)) + if err != nil { + return NewTProtocolException(err) + } + err = p.writeByteDirect(byte(p.getCompactType(keyType))<<4 | byte(p.getCompactType(valueType))) + return NewTProtocolException(err) +} + +func (p *TCompactProtocol) WriteMapEnd() error { return nil } + +// Write a list header. +func (p *TCompactProtocol) WriteListBegin(elemType TType, size int) error { + _, err := p.writeCollectionBegin(elemType, size) + return NewTProtocolException(err) +} + +func (p *TCompactProtocol) WriteListEnd() error { return nil } + +// Write a set header. +func (p *TCompactProtocol) WriteSetBegin(elemType TType, size int) error { + _, err := p.writeCollectionBegin(elemType, size) + return NewTProtocolException(err) +} + +func (p *TCompactProtocol) WriteSetEnd() error { return nil } + +func (p *TCompactProtocol) WriteBool(value bool) error { + v := byte(COMPACT_BOOLEAN_FALSE) + if value { + v = byte(COMPACT_BOOLEAN_TRUE) + } + if p.booleanFieldPending { + // we haven't written the field header yet + _, err := p.writeFieldBeginInternal(p.booleanFieldName, BOOL, p.booleanFieldId, v) + p.booleanFieldPending = false + return NewTProtocolException(err) + } + // we're not part of a field, so just write the value. + err := p.writeByteDirect(v) + return NewTProtocolException(err) +} + +// Write a byte. Nothing to see here! +func (p *TCompactProtocol) WriteByte(value int8) error { + err := p.writeByteDirect(byte(value)) + return NewTProtocolException(err) +} + +// Write an I16 as a zigzag varint. +func (p *TCompactProtocol) WriteI16(value int16) error { + _, err := p.writeVarint32(p.int32ToZigzag(int32(value))) + return NewTProtocolException(err) +} + +// Write an i32 as a zigzag varint. +func (p *TCompactProtocol) WriteI32(value int32) error { + _, err := p.writeVarint32(p.int32ToZigzag(value)) + return NewTProtocolException(err) +} + +// Write an i64 as a zigzag varint. +func (p *TCompactProtocol) WriteI64(value int64) error { + _, err := p.writeVarint64(p.int64ToZigzag(value)) + return NewTProtocolException(err) +} + +// Write a double to the wire as 8 bytes. +func (p *TCompactProtocol) WriteDouble(value float64) error { + buf := p.buffer[0:8] + binary.LittleEndian.PutUint64(buf, math.Float64bits(value)) + _, err := p.trans.Write(buf) + return NewTProtocolException(err) +} + +// Write a string to the wire with a varint size preceding. +func (p *TCompactProtocol) WriteString(value string) error { + _, e := p.writeVarint32(int32(len(value))) + if e != nil { + return NewTProtocolException(e) + } + if len(value) > 0 { + } + _, e = p.trans.WriteString(value) + return e +} + +// Write a byte array, using a varint for the size. +func (p *TCompactProtocol) WriteBinary(bin []byte) error { + _, e := p.writeVarint32(int32(len(bin))) + if e != nil { + return NewTProtocolException(e) + } + if len(bin) > 0 { + _, e = p.trans.Write(bin) + return NewTProtocolException(e) + } + return nil +} + +// +// Reading methods. +// + +// Read a message header. +func (p *TCompactProtocol) ReadMessageBegin() (name string, typeId TMessageType, seqId int32, err error) { + + protocolId, err := p.readByteDirect() + if err != nil { + return + } + + if protocolId != COMPACT_PROTOCOL_ID { + e := fmt.Errorf("Expected protocol id %02x but got %02x", COMPACT_PROTOCOL_ID, protocolId) + return "", typeId, seqId, NewTProtocolExceptionWithType(BAD_VERSION, e) + } + + versionAndType, err := p.readByteDirect() + if err != nil { + return + } + + version := versionAndType & COMPACT_VERSION_MASK + typeId = TMessageType((versionAndType >> COMPACT_TYPE_SHIFT_AMOUNT) & COMPACT_TYPE_BITS) + if version != COMPACT_VERSION { + e := fmt.Errorf("Expected version %02x but got %02x", COMPACT_VERSION, version) + err = NewTProtocolExceptionWithType(BAD_VERSION, e) + return + } + seqId, e := p.readVarint32() + if e != nil { + err = NewTProtocolException(e) + return + } + name, err = p.ReadString() + return +} + +func (p *TCompactProtocol) ReadMessageEnd() error { return nil } + +// Read a struct begin. There's nothing on the wire for this, but it is our +// opportunity to push a new struct begin marker onto the field stack. +func (p *TCompactProtocol) ReadStructBegin() (name string, err error) { + p.lastField = append(p.lastField, p.lastFieldId) + p.lastFieldId = 0 + return +} + +// Doesn't actually consume any wire data, just removes the last field for +// this struct from the field stack. +func (p *TCompactProtocol) ReadStructEnd() error { + // consume the last field we read off the wire. + p.lastFieldId = p.lastField[len(p.lastField)-1] + p.lastField = p.lastField[:len(p.lastField)-1] + return nil +} + +// Read a field header off the wire. +func (p *TCompactProtocol) ReadFieldBegin() (name string, typeId TType, id int16, err error) { + t, err := p.readByteDirect() + if err != nil { + return + } + + // if it's a stop, then we can return immediately, as the struct is over. + if (t & 0x0f) == STOP { + return "", STOP, 0, nil + } + + // mask off the 4 MSB of the type header. it could contain a field id delta. + modifier := int16((t & 0xf0) >> 4) + if modifier == 0 { + // not a delta. look ahead for the zigzag varint field id. + id, err = p.ReadI16() + if err != nil { + return + } + } else { + // has a delta. add the delta to the last read field id. + id = int16(p.lastFieldId) + modifier + } + typeId, e := p.getTType(tCompactType(t & 0x0f)) + if e != nil { + err = NewTProtocolException(e) + return + } + + // if this happens to be a boolean field, the value is encoded in the type + if p.isBoolType(t) { + // save the boolean value in a special instance variable. + p.boolValue = (byte(t)&0x0f == COMPACT_BOOLEAN_TRUE) + p.boolValueIsNotNull = true + } + + // push the new field onto the field stack so we can keep the deltas going. + p.lastFieldId = int(id) + return +} + +func (p *TCompactProtocol) ReadFieldEnd() error { return nil } + +// 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. +func (p *TCompactProtocol) ReadMapBegin() (keyType TType, valueType TType, size int, err error) { + size32, e := p.readVarint32() + if e != nil { + err = NewTProtocolException(e) + return + } + if size32 < 0 { + err = invalidDataLength + return + } + size = int(size32) + + keyAndValueType := byte(STOP) + if size != 0 { + keyAndValueType, err = p.readByteDirect() + if err != nil { + return + } + } + keyType, _ = p.getTType(tCompactType(keyAndValueType >> 4)) + valueType, _ = p.getTType(tCompactType(keyAndValueType & 0xf)) + return +} + +func (p *TCompactProtocol) ReadMapEnd() error { return nil } + +// Read a list header off the wire. If the list size is 0-14, the size will +// be packed into the element type header. If it's a longer list, the 4 MSB +// of the element type header will be 0xF, and a varint will follow with the +// true size. +func (p *TCompactProtocol) ReadListBegin() (elemType TType, size int, err error) { + size_and_type, err := p.readByteDirect() + if err != nil { + return + } + size = int((size_and_type >> 4) & 0x0f) + if size == 15 { + size2, e := p.readVarint32() + if e != nil { + err = NewTProtocolException(e) + return + } + if size2 < 0 { + err = invalidDataLength + return + } + size = int(size2) + } + elemType, e := p.getTType(tCompactType(size_and_type)) + if e != nil { + err = NewTProtocolException(e) + return + } + return +} + +func (p *TCompactProtocol) ReadListEnd() error { return nil } + +// Read a set header off the wire. If the set size is 0-14, the size will +// be packed into the element type header. If it's a longer set, the 4 MSB +// of the element type header will be 0xF, and a varint will follow with the +// true size. +func (p *TCompactProtocol) ReadSetBegin() (elemType TType, size int, err error) { + return p.ReadListBegin() +} + +func (p *TCompactProtocol) ReadSetEnd() error { return nil } + +// 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. +func (p *TCompactProtocol) ReadBool() (value bool, err error) { + if p.boolValueIsNotNull { + p.boolValueIsNotNull = false + return p.boolValue, nil + } + v, err := p.readByteDirect() + return v == COMPACT_BOOLEAN_TRUE, err +} + +// Read a single byte off the wire. Nothing interesting here. +func (p *TCompactProtocol) ReadByte() (int8, error) { + v, err := p.readByteDirect() + if err != nil { + return 0, NewTProtocolException(err) + } + return int8(v), err +} + +// Read an i16 from the wire as a zigzag varint. +func (p *TCompactProtocol) ReadI16() (value int16, err error) { + v, err := p.ReadI32() + return int16(v), err +} + +// Read an i32 from the wire as a zigzag varint. +func (p *TCompactProtocol) ReadI32() (value int32, err error) { + v, e := p.readVarint32() + if e != nil { + return 0, NewTProtocolException(e) + } + value = p.zigzagToInt32(v) + return value, nil +} + +// Read an i64 from the wire as a zigzag varint. +func (p *TCompactProtocol) ReadI64() (value int64, err error) { + v, e := p.readVarint64() + if e != nil { + return 0, NewTProtocolException(e) + } + value = p.zigzagToInt64(v) + return value, nil +} + +// No magic here - just read a double off the wire. +func (p *TCompactProtocol) ReadDouble() (value float64, err error) { + longBits := p.buffer[0:8] + _, e := io.ReadFull(p.trans, longBits) + if e != nil { + return 0.0, NewTProtocolException(e) + } + return math.Float64frombits(p.bytesToUint64(longBits)), nil +} + +// Reads a []byte (via readBinary), and then UTF-8 decodes it. +func (p *TCompactProtocol) ReadString() (value string, err error) { + length, e := p.readVarint32() + if e != nil { + return "", NewTProtocolException(e) + } + if length < 0 { + return "", invalidDataLength + } + if uint64(length) > p.trans.RemainingBytes() { + return "", invalidDataLength + } + + if length == 0 { + return "", nil + } + var buf []byte + if length <= int32(len(p.buffer)) { + buf = p.buffer[0:length] + } else { + buf = make([]byte, length) + } + _, e = io.ReadFull(p.trans, buf) + return string(buf), NewTProtocolException(e) +} + +// Read a []byte from the wire. +func (p *TCompactProtocol) ReadBinary() (value []byte, err error) { + length, e := p.readVarint32() + if e != nil { + return nil, NewTProtocolException(e) + } + if length == 0 { + return []byte{}, nil + } + if length < 0 { + return nil, invalidDataLength + } + if uint64(length) > p.trans.RemainingBytes() { + return nil, invalidDataLength + } + + buf := make([]byte, length) + _, e = io.ReadFull(p.trans, buf) + return buf, NewTProtocolException(e) +} + +func (p *TCompactProtocol) Flush() (err error) { + return NewTProtocolException(p.trans.Flush()) +} + +func (p *TCompactProtocol) Skip(fieldType TType) (err error) { + return SkipDefaultDepth(p, fieldType) +} + +func (p *TCompactProtocol) Transport() TTransport { + return p.origTransport +} + +// +// Internal writing methods +// + +// Abstract method for writing the start of lists and sets. List and sets on +// the wire differ only by the type indicator. +func (p *TCompactProtocol) writeCollectionBegin(elemType TType, size int) (int, error) { + if size <= 14 { + return 1, p.writeByteDirect(byte(int32(size<<4) | int32(p.getCompactType(elemType)))) + } + err := p.writeByteDirect(0xf0 | byte(p.getCompactType(elemType))) + if err != nil { + return 0, err + } + m, err := p.writeVarint32(int32(size)) + return 1 + m, err +} + +// Write an i32 as a varint. Results in 1-5 bytes on the wire. +// TODO(pomack): make a permanent buffer like writeVarint64? +func (p *TCompactProtocol) writeVarint32(n int32) (int, error) { + i32buf := p.buffer[0:5] + idx := 0 + for { + if (n & ^0x7F) == 0 { + i32buf[idx] = byte(n) + idx++ + // p.writeByteDirect(byte(n)); + break + // return; + } else { + i32buf[idx] = byte((n & 0x7F) | 0x80) + idx++ + // p.writeByteDirect(byte(((n & 0x7F) | 0x80))); + u := uint32(n) + n = int32(u >> 7) + } + } + return p.trans.Write(i32buf[0:idx]) +} + +// Write an i64 as a varint. Results in 1-10 bytes on the wire. +func (p *TCompactProtocol) writeVarint64(n int64) (int, error) { + varint64out := p.buffer[0:10] + idx := 0 + for { + if (n & ^0x7F) == 0 { + varint64out[idx] = byte(n) + idx++ + break + } else { + varint64out[idx] = byte((n & 0x7F) | 0x80) + idx++ + u := uint64(n) + n = int64(u >> 7) + } + } + return p.trans.Write(varint64out[0:idx]) +} + +// Convert l into a zigzag long. This allows negative numbers to be +// represented compactly as a varint. +func (p *TCompactProtocol) int64ToZigzag(l int64) int64 { + return (l << 1) ^ (l >> 63) +} + +// Convert l into a zigzag long. This allows negative numbers to be +// represented compactly as a varint. +func (p *TCompactProtocol) int32ToZigzag(n int32) int32 { + return (n << 1) ^ (n >> 31) +} + +func (p *TCompactProtocol) fixedUint64ToBytes(n uint64, buf []byte) { + binary.LittleEndian.PutUint64(buf, n) +} + +func (p *TCompactProtocol) fixedInt64ToBytes(n int64, buf []byte) { + binary.LittleEndian.PutUint64(buf, uint64(n)) +} + +// Writes a byte without any possibility of all that field header nonsense. +// Used internally by other writing methods that know they need to write a byte. +func (p *TCompactProtocol) writeByteDirect(b byte) error { + return p.trans.WriteByte(b) +} + +// Writes a byte without any possibility of all that field header nonsense. +func (p *TCompactProtocol) writeIntAsByteDirect(n int) (int, error) { + return 1, p.writeByteDirect(byte(n)) +} + +// +// Internal reading methods +// + +// Read an i32 from the wire as a varint. The MSB of each byte is set +// if there is another byte to follow. This can read up to 5 bytes. +func (p *TCompactProtocol) readVarint32() (int32, error) { + // if the wire contains the right stuff, this will just truncate the i64 we + // read and get us the right sign. + v, err := p.readVarint64() + return int32(v), err +} + +// Read an i64 from the wire as a proper varint. The MSB of each byte is set +// if there is another byte to follow. This can read up to 10 bytes. +func (p *TCompactProtocol) readVarint64() (int64, error) { + shift := uint(0) + result := int64(0) + for { + b, err := p.readByteDirect() + if err != nil { + return 0, err + } + result |= int64(b&0x7f) << shift + if (b & 0x80) != 0x80 { + break + } + shift += 7 + } + return result, nil +} + +// Read a byte, unlike ReadByte that reads Thrift-byte that is i8. +func (p *TCompactProtocol) readByteDirect() (byte, error) { + return p.trans.ReadByte() +} + +// +// encoding helpers +// + +// Convert from zigzag int to int. +func (p *TCompactProtocol) zigzagToInt32(n int32) int32 { + u := uint32(n) + return int32(u>>1) ^ -(n & 1) +} + +// Convert from zigzag long to long. +func (p *TCompactProtocol) zigzagToInt64(n int64) int64 { + u := uint64(n) + return int64(u>>1) ^ -(n & 1) +} + +// Note that it's important that the mask bytes are long literals, +// otherwise they'll default to ints, and when you shift an int left 56 bits, +// you just get a messed up int. +func (p *TCompactProtocol) bytesToInt64(b []byte) int64 { + return int64(binary.LittleEndian.Uint64(b)) +} + +// Note that it's important that the mask bytes are long literals, +// otherwise they'll default to ints, and when you shift an int left 56 bits, +// you just get a messed up int. +func (p *TCompactProtocol) bytesToUint64(b []byte) uint64 { + return binary.LittleEndian.Uint64(b) +} + +// +// type testing and converting +// + +func (p *TCompactProtocol) isBoolType(b byte) bool { + return (b&0x0f) == COMPACT_BOOLEAN_TRUE || (b&0x0f) == COMPACT_BOOLEAN_FALSE +} + +// Given a tCompactType constant, convert it to its corresponding +// TType value. +func (p *TCompactProtocol) getTType(t tCompactType) (TType, error) { + switch byte(t) & 0x0f { + case STOP: + return STOP, nil + case COMPACT_BOOLEAN_FALSE, COMPACT_BOOLEAN_TRUE: + return BOOL, nil + case COMPACT_BYTE: + return BYTE, nil + case COMPACT_I16: + return I16, nil + case COMPACT_I32: + return I32, nil + case COMPACT_I64: + return I64, nil + case COMPACT_DOUBLE: + return DOUBLE, nil + case COMPACT_BINARY: + return STRING, nil + case COMPACT_LIST: + return LIST, nil + case COMPACT_SET: + return SET, nil + case COMPACT_MAP: + return MAP, nil + case COMPACT_STRUCT: + return STRUCT, nil + } + return STOP, TException(fmt.Errorf("don't know what type: %s", t&0x0f)) +} + +// Given a TType value, find the appropriate TCompactProtocol.Types constant. +func (p *TCompactProtocol) getCompactType(t TType) tCompactType { + return ttypeToCompactType[t] +} diff --git a/vendor/github.com/apache/thrift/lib/go/thrift/debug_protocol.go b/vendor/github.com/apache/thrift/lib/go/thrift/debug_protocol.go new file mode 100644 index 000000000..d37252cc6 --- /dev/null +++ b/vendor/github.com/apache/thrift/lib/go/thrift/debug_protocol.go @@ -0,0 +1,269 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package thrift + +import ( + "log" +) + +type TDebugProtocol struct { + Delegate TProtocol + LogPrefix string +} + +type TDebugProtocolFactory struct { + Underlying TProtocolFactory + LogPrefix string +} + +func NewTDebugProtocolFactory(underlying TProtocolFactory, logPrefix string) *TDebugProtocolFactory { + return &TDebugProtocolFactory{ + Underlying: underlying, + LogPrefix: logPrefix, + } +} + +func (t *TDebugProtocolFactory) GetProtocol(trans TTransport) TProtocol { + return &TDebugProtocol{ + Delegate: t.Underlying.GetProtocol(trans), + LogPrefix: t.LogPrefix, + } +} + +func (tdp *TDebugProtocol) WriteMessageBegin(name string, typeId TMessageType, seqid int32) error { + err := tdp.Delegate.WriteMessageBegin(name, typeId, seqid) + log.Printf("%sWriteMessageBegin(name=%#v, typeId=%#v, seqid=%#v) => %#v", tdp.LogPrefix, name, typeId, seqid, err) + return err +} +func (tdp *TDebugProtocol) WriteMessageEnd() error { + err := tdp.Delegate.WriteMessageEnd() + log.Printf("%sWriteMessageEnd() => %#v", tdp.LogPrefix, err) + return err +} +func (tdp *TDebugProtocol) WriteStructBegin(name string) error { + err := tdp.Delegate.WriteStructBegin(name) + log.Printf("%sWriteStructBegin(name=%#v) => %#v", tdp.LogPrefix, name, err) + return err +} +func (tdp *TDebugProtocol) WriteStructEnd() error { + err := tdp.Delegate.WriteStructEnd() + log.Printf("%sWriteStructEnd() => %#v", tdp.LogPrefix, err) + return err +} +func (tdp *TDebugProtocol) WriteFieldBegin(name string, typeId TType, id int16) error { + err := tdp.Delegate.WriteFieldBegin(name, typeId, id) + log.Printf("%sWriteFieldBegin(name=%#v, typeId=%#v, id%#v) => %#v", tdp.LogPrefix, name, typeId, id, err) + return err +} +func (tdp *TDebugProtocol) WriteFieldEnd() error { + err := tdp.Delegate.WriteFieldEnd() + log.Printf("%sWriteFieldEnd() => %#v", tdp.LogPrefix, err) + return err +} +func (tdp *TDebugProtocol) WriteFieldStop() error { + err := tdp.Delegate.WriteFieldStop() + log.Printf("%sWriteFieldStop() => %#v", tdp.LogPrefix, err) + return err +} +func (tdp *TDebugProtocol) WriteMapBegin(keyType TType, valueType TType, size int) error { + err := tdp.Delegate.WriteMapBegin(keyType, valueType, size) + log.Printf("%sWriteMapBegin(keyType=%#v, valueType=%#v, size=%#v) => %#v", tdp.LogPrefix, keyType, valueType, size, err) + return err +} +func (tdp *TDebugProtocol) WriteMapEnd() error { + err := tdp.Delegate.WriteMapEnd() + log.Printf("%sWriteMapEnd() => %#v", tdp.LogPrefix, err) + return err +} +func (tdp *TDebugProtocol) WriteListBegin(elemType TType, size int) error { + err := tdp.Delegate.WriteListBegin(elemType, size) + log.Printf("%sWriteListBegin(elemType=%#v, size=%#v) => %#v", tdp.LogPrefix, elemType, size, err) + return err +} +func (tdp *TDebugProtocol) WriteListEnd() error { + err := tdp.Delegate.WriteListEnd() + log.Printf("%sWriteListEnd() => %#v", tdp.LogPrefix, err) + return err +} +func (tdp *TDebugProtocol) WriteSetBegin(elemType TType, size int) error { + err := tdp.Delegate.WriteSetBegin(elemType, size) + log.Printf("%sWriteSetBegin(elemType=%#v, size=%#v) => %#v", tdp.LogPrefix, elemType, size, err) + return err +} +func (tdp *TDebugProtocol) WriteSetEnd() error { + err := tdp.Delegate.WriteSetEnd() + log.Printf("%sWriteSetEnd() => %#v", tdp.LogPrefix, err) + return err +} +func (tdp *TDebugProtocol) WriteBool(value bool) error { + err := tdp.Delegate.WriteBool(value) + log.Printf("%sWriteBool(value=%#v) => %#v", tdp.LogPrefix, value, err) + return err +} +func (tdp *TDebugProtocol) WriteByte(value int8) error { + err := tdp.Delegate.WriteByte(value) + log.Printf("%sWriteByte(value=%#v) => %#v", tdp.LogPrefix, value, err) + return err +} +func (tdp *TDebugProtocol) WriteI16(value int16) error { + err := tdp.Delegate.WriteI16(value) + log.Printf("%sWriteI16(value=%#v) => %#v", tdp.LogPrefix, value, err) + return err +} +func (tdp *TDebugProtocol) WriteI32(value int32) error { + err := tdp.Delegate.WriteI32(value) + log.Printf("%sWriteI32(value=%#v) => %#v", tdp.LogPrefix, value, err) + return err +} +func (tdp *TDebugProtocol) WriteI64(value int64) error { + err := tdp.Delegate.WriteI64(value) + log.Printf("%sWriteI64(value=%#v) => %#v", tdp.LogPrefix, value, err) + return err +} +func (tdp *TDebugProtocol) WriteDouble(value float64) error { + err := tdp.Delegate.WriteDouble(value) + log.Printf("%sWriteDouble(value=%#v) => %#v", tdp.LogPrefix, value, err) + return err +} +func (tdp *TDebugProtocol) WriteString(value string) error { + err := tdp.Delegate.WriteString(value) + log.Printf("%sWriteString(value=%#v) => %#v", tdp.LogPrefix, value, err) + return err +} +func (tdp *TDebugProtocol) WriteBinary(value []byte) error { + err := tdp.Delegate.WriteBinary(value) + log.Printf("%sWriteBinary(value=%#v) => %#v", tdp.LogPrefix, value, err) + return err +} + +func (tdp *TDebugProtocol) ReadMessageBegin() (name string, typeId TMessageType, seqid int32, err error) { + name, typeId, seqid, err = tdp.Delegate.ReadMessageBegin() + log.Printf("%sReadMessageBegin() (name=%#v, typeId=%#v, seqid=%#v, err=%#v)", tdp.LogPrefix, name, typeId, seqid, err) + return +} +func (tdp *TDebugProtocol) ReadMessageEnd() (err error) { + err = tdp.Delegate.ReadMessageEnd() + log.Printf("%sReadMessageEnd() err=%#v", tdp.LogPrefix, err) + return +} +func (tdp *TDebugProtocol) ReadStructBegin() (name string, err error) { + name, err = tdp.Delegate.ReadStructBegin() + log.Printf("%sReadStructBegin() (name%#v, err=%#v)", tdp.LogPrefix, name, err) + return +} +func (tdp *TDebugProtocol) ReadStructEnd() (err error) { + err = tdp.Delegate.ReadStructEnd() + log.Printf("%sReadStructEnd() err=%#v", tdp.LogPrefix, err) + return +} +func (tdp *TDebugProtocol) ReadFieldBegin() (name string, typeId TType, id int16, err error) { + name, typeId, id, err = tdp.Delegate.ReadFieldBegin() + log.Printf("%sReadFieldBegin() (name=%#v, typeId=%#v, id=%#v, err=%#v)", tdp.LogPrefix, name, typeId, id, err) + return +} +func (tdp *TDebugProtocol) ReadFieldEnd() (err error) { + err = tdp.Delegate.ReadFieldEnd() + log.Printf("%sReadFieldEnd() err=%#v", tdp.LogPrefix, err) + return +} +func (tdp *TDebugProtocol) ReadMapBegin() (keyType TType, valueType TType, size int, err error) { + keyType, valueType, size, err = tdp.Delegate.ReadMapBegin() + log.Printf("%sReadMapBegin() (keyType=%#v, valueType=%#v, size=%#v, err=%#v)", tdp.LogPrefix, keyType, valueType, size, err) + return +} +func (tdp *TDebugProtocol) ReadMapEnd() (err error) { + err = tdp.Delegate.ReadMapEnd() + log.Printf("%sReadMapEnd() err=%#v", tdp.LogPrefix, err) + return +} +func (tdp *TDebugProtocol) ReadListBegin() (elemType TType, size int, err error) { + elemType, size, err = tdp.Delegate.ReadListBegin() + log.Printf("%sReadListBegin() (elemType=%#v, size=%#v, err=%#v)", tdp.LogPrefix, elemType, size, err) + return +} +func (tdp *TDebugProtocol) ReadListEnd() (err error) { + err = tdp.Delegate.ReadListEnd() + log.Printf("%sReadListEnd() err=%#v", tdp.LogPrefix, err) + return +} +func (tdp *TDebugProtocol) ReadSetBegin() (elemType TType, size int, err error) { + elemType, size, err = tdp.Delegate.ReadSetBegin() + log.Printf("%sReadSetBegin() (elemType=%#v, size=%#v, err=%#v)", tdp.LogPrefix, elemType, size, err) + return +} +func (tdp *TDebugProtocol) ReadSetEnd() (err error) { + err = tdp.Delegate.ReadSetEnd() + log.Printf("%sReadSetEnd() err=%#v", tdp.LogPrefix, err) + return +} +func (tdp *TDebugProtocol) ReadBool() (value bool, err error) { + value, err = tdp.Delegate.ReadBool() + log.Printf("%sReadBool() (value=%#v, err=%#v)", tdp.LogPrefix, value, err) + return +} +func (tdp *TDebugProtocol) ReadByte() (value int8, err error) { + value, err = tdp.Delegate.ReadByte() + log.Printf("%sReadByte() (value=%#v, err=%#v)", tdp.LogPrefix, value, err) + return +} +func (tdp *TDebugProtocol) ReadI16() (value int16, err error) { + value, err = tdp.Delegate.ReadI16() + log.Printf("%sReadI16() (value=%#v, err=%#v)", tdp.LogPrefix, value, err) + return +} +func (tdp *TDebugProtocol) ReadI32() (value int32, err error) { + value, err = tdp.Delegate.ReadI32() + log.Printf("%sReadI32() (value=%#v, err=%#v)", tdp.LogPrefix, value, err) + return +} +func (tdp *TDebugProtocol) ReadI64() (value int64, err error) { + value, err = tdp.Delegate.ReadI64() + log.Printf("%sReadI64() (value=%#v, err=%#v)", tdp.LogPrefix, value, err) + return +} +func (tdp *TDebugProtocol) ReadDouble() (value float64, err error) { + value, err = tdp.Delegate.ReadDouble() + log.Printf("%sReadDouble() (value=%#v, err=%#v)", tdp.LogPrefix, value, err) + return +} +func (tdp *TDebugProtocol) ReadString() (value string, err error) { + value, err = tdp.Delegate.ReadString() + log.Printf("%sReadString() (value=%#v, err=%#v)", tdp.LogPrefix, value, err) + return +} +func (tdp *TDebugProtocol) ReadBinary() (value []byte, err error) { + value, err = tdp.Delegate.ReadBinary() + log.Printf("%sReadBinary() (value=%#v, err=%#v)", tdp.LogPrefix, value, err) + return +} +func (tdp *TDebugProtocol) Skip(fieldType TType) (err error) { + err = tdp.Delegate.Skip(fieldType) + log.Printf("%sSkip(fieldType=%#v) (err=%#v)", tdp.LogPrefix, fieldType, err) + return +} +func (tdp *TDebugProtocol) Flush() (err error) { + err = tdp.Delegate.Flush() + log.Printf("%sFlush() (err=%#v)", tdp.LogPrefix, err) + return +} + +func (tdp *TDebugProtocol) Transport() TTransport { + return tdp.Delegate.Transport() +} diff --git a/vendor/github.com/apache/thrift/lib/go/thrift/deserializer.go b/vendor/github.com/apache/thrift/lib/go/thrift/deserializer.go new file mode 100644 index 000000000..91a0983a4 --- /dev/null +++ b/vendor/github.com/apache/thrift/lib/go/thrift/deserializer.go @@ -0,0 +1,58 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package thrift + +type TDeserializer struct { + Transport TTransport + Protocol TProtocol +} + +func NewTDeserializer() *TDeserializer { + var transport TTransport + transport = NewTMemoryBufferLen(1024) + + protocol := NewTBinaryProtocolFactoryDefault().GetProtocol(transport) + + return &TDeserializer{ + transport, + protocol} +} + +func (t *TDeserializer) ReadString(msg TStruct, s string) (err error) { + err = nil + if _, err = t.Transport.Write([]byte(s)); err != nil { + return + } + if err = msg.Read(t.Protocol); err != nil { + return + } + return +} + +func (t *TDeserializer) Read(msg TStruct, b []byte) (err error) { + err = nil + if _, err = t.Transport.Write(b); err != nil { + return + } + if err = msg.Read(t.Protocol); err != nil { + return + } + return +} diff --git a/vendor/github.com/apache/thrift/lib/go/thrift/exception.go b/vendor/github.com/apache/thrift/lib/go/thrift/exception.go new file mode 100644 index 000000000..ea8d6f661 --- /dev/null +++ b/vendor/github.com/apache/thrift/lib/go/thrift/exception.go @@ -0,0 +1,44 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package thrift + +import ( + "errors" +) + +// Generic Thrift exception +type TException interface { + error +} + +// Prepends additional information to an error without losing the Thrift exception interface +func PrependError(prepend string, err error) error { + if t, ok := err.(TTransportException); ok { + return NewTTransportException(t.TypeId(), prepend+t.Error()) + } + if t, ok := err.(TProtocolException); ok { + return NewTProtocolExceptionWithType(t.TypeId(), errors.New(prepend+err.Error())) + } + if t, ok := err.(TApplicationException); ok { + return NewTApplicationException(t.TypeId(), prepend+t.Error()) + } + + return errors.New(prepend + err.Error()) +} diff --git a/vendor/github.com/apache/thrift/lib/go/thrift/field.go b/vendor/github.com/apache/thrift/lib/go/thrift/field.go new file mode 100644 index 000000000..9d6652550 --- /dev/null +++ b/vendor/github.com/apache/thrift/lib/go/thrift/field.go @@ -0,0 +1,79 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package thrift + +// Helper class that encapsulates field metadata. +type field struct { + name string + typeId TType + id int +} + +func newField(n string, t TType, i int) *field { + return &field{name: n, typeId: t, id: i} +} + +func (p *field) Name() string { + if p == nil { + return "" + } + return p.name +} + +func (p *field) TypeId() TType { + if p == nil { + return TType(VOID) + } + return p.typeId +} + +func (p *field) Id() int { + if p == nil { + return -1 + } + return p.id +} + +func (p *field) String() string { + if p == nil { + return "" + } + return "" +} + +var ANONYMOUS_FIELD *field + +type fieldSlice []field + +func (p fieldSlice) Len() int { + return len(p) +} + +func (p fieldSlice) Less(i, j int) bool { + return p[i].Id() < p[j].Id() +} + +func (p fieldSlice) Swap(i, j int) { + p[i], p[j] = p[j], p[i] +} + +func init() { + ANONYMOUS_FIELD = newField("", STOP, 0) +} diff --git a/vendor/github.com/apache/thrift/lib/go/thrift/framed_transport.go b/vendor/github.com/apache/thrift/lib/go/thrift/framed_transport.go new file mode 100644 index 000000000..d0bae21bc --- /dev/null +++ b/vendor/github.com/apache/thrift/lib/go/thrift/framed_transport.go @@ -0,0 +1,167 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package thrift + +import ( + "bufio" + "bytes" + "encoding/binary" + "fmt" + "io" +) + +const DEFAULT_MAX_LENGTH = 16384000 + +type TFramedTransport struct { + transport TTransport + buf bytes.Buffer + reader *bufio.Reader + frameSize uint32 //Current remaining size of the frame. if ==0 read next frame header + buffer [4]byte + maxLength uint32 +} + +type tFramedTransportFactory struct { + factory TTransportFactory + maxLength uint32 +} + +func NewTFramedTransportFactory(factory TTransportFactory) TTransportFactory { + return &tFramedTransportFactory{factory: factory, maxLength: DEFAULT_MAX_LENGTH} +} + +func NewTFramedTransportFactoryMaxLength(factory TTransportFactory, maxLength uint32) TTransportFactory { + return &tFramedTransportFactory{factory: factory, maxLength: maxLength} +} + +func (p *tFramedTransportFactory) GetTransport(base TTransport) TTransport { + return NewTFramedTransportMaxLength(p.factory.GetTransport(base), p.maxLength) +} + +func NewTFramedTransport(transport TTransport) *TFramedTransport { + return &TFramedTransport{transport: transport, reader: bufio.NewReader(transport), maxLength: DEFAULT_MAX_LENGTH} +} + +func NewTFramedTransportMaxLength(transport TTransport, maxLength uint32) *TFramedTransport { + return &TFramedTransport{transport: transport, reader: bufio.NewReader(transport), maxLength: maxLength} +} + +func (p *TFramedTransport) Open() error { + return p.transport.Open() +} + +func (p *TFramedTransport) IsOpen() bool { + return p.transport.IsOpen() +} + +func (p *TFramedTransport) Close() error { + return p.transport.Close() +} + +func (p *TFramedTransport) Read(buf []byte) (l int, err error) { + if p.frameSize == 0 { + p.frameSize, err = p.readFrameHeader() + if err != nil { + return + } + } + if p.frameSize < uint32(len(buf)) { + frameSize := p.frameSize + tmp := make([]byte, p.frameSize) + l, err = p.Read(tmp) + copy(buf, tmp) + if err == nil { + err = NewTTransportExceptionFromError(fmt.Errorf("Not enough frame size %d to read %d bytes", frameSize, len(buf))) + return + } + } + got, err := p.reader.Read(buf) + p.frameSize = p.frameSize - uint32(got) + //sanity check + if p.frameSize < 0 { + return 0, NewTTransportException(UNKNOWN_TRANSPORT_EXCEPTION, "Negative frame size") + } + return got, NewTTransportExceptionFromError(err) +} + +func (p *TFramedTransport) ReadByte() (c byte, err error) { + if p.frameSize == 0 { + p.frameSize, err = p.readFrameHeader() + if err != nil { + return + } + } + if p.frameSize < 1 { + return 0, NewTTransportExceptionFromError(fmt.Errorf("Not enough frame size %d to read %d bytes", p.frameSize, 1)) + } + c, err = p.reader.ReadByte() + if err == nil { + p.frameSize-- + } + return +} + +func (p *TFramedTransport) Write(buf []byte) (int, error) { + n, err := p.buf.Write(buf) + return n, NewTTransportExceptionFromError(err) +} + +func (p *TFramedTransport) WriteByte(c byte) error { + return p.buf.WriteByte(c) +} + +func (p *TFramedTransport) WriteString(s string) (n int, err error) { + return p.buf.WriteString(s) +} + +func (p *TFramedTransport) Flush() error { + size := p.buf.Len() + buf := p.buffer[:4] + binary.BigEndian.PutUint32(buf, uint32(size)) + _, err := p.transport.Write(buf) + if err != nil { + return NewTTransportExceptionFromError(err) + } + if size > 0 { + if n, err := p.buf.WriteTo(p.transport); err != nil { + print("Error while flushing write buffer of size ", size, " to transport, only wrote ", n, " bytes: ", err.Error(), "\n") + return NewTTransportExceptionFromError(err) + } + } + err = p.transport.Flush() + return NewTTransportExceptionFromError(err) +} + +func (p *TFramedTransport) readFrameHeader() (uint32, error) { + buf := p.buffer[:4] + if _, err := io.ReadFull(p.reader, buf); err != nil { + return 0, err + } + size := binary.BigEndian.Uint32(buf) + if size < 0 || size > p.maxLength { + return 0, NewTTransportException(UNKNOWN_TRANSPORT_EXCEPTION, fmt.Sprintf("Incorrect frame size (%d)", size)) + } + return size, nil +} + +func (p *TFramedTransport) RemainingBytes() (num_bytes uint64) { + return uint64(p.frameSize) +} + diff --git a/vendor/github.com/apache/thrift/lib/go/thrift/http_client.go b/vendor/github.com/apache/thrift/lib/go/thrift/http_client.go new file mode 100644 index 000000000..88eb2c128 --- /dev/null +++ b/vendor/github.com/apache/thrift/lib/go/thrift/http_client.go @@ -0,0 +1,258 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package thrift + +import ( + "bytes" + "io" + "io/ioutil" + "net/http" + "net/url" + "strconv" +) + +// Default to using the shared http client. Library users are +// free to change this global client or specify one through +// THttpClientOptions. +var DefaultHttpClient *http.Client = http.DefaultClient + +type THttpClient struct { + client *http.Client + response *http.Response + url *url.URL + requestBuffer *bytes.Buffer + header http.Header + nsecConnectTimeout int64 + nsecReadTimeout int64 +} + +type THttpClientTransportFactory struct { + options THttpClientOptions + url string + isPost bool +} + +func (p *THttpClientTransportFactory) GetTransport(trans TTransport) TTransport { + if trans != nil { + t, ok := trans.(*THttpClient) + if ok && t.url != nil { + if t.requestBuffer != nil { + t2, _ := NewTHttpPostClientWithOptions(t.url.String(), p.options) + return t2 + } + t2, _ := NewTHttpClientWithOptions(t.url.String(), p.options) + return t2 + } + } + if p.isPost { + s, _ := NewTHttpPostClientWithOptions(p.url, p.options) + return s + } + s, _ := NewTHttpClientWithOptions(p.url, p.options) + return s +} + +type THttpClientOptions struct { + // If nil, DefaultHttpClient is used + Client *http.Client +} + +func NewTHttpClientTransportFactory(url string) *THttpClientTransportFactory { + return NewTHttpClientTransportFactoryWithOptions(url, THttpClientOptions{}) +} + +func NewTHttpClientTransportFactoryWithOptions(url string, options THttpClientOptions) *THttpClientTransportFactory { + return &THttpClientTransportFactory{url: url, isPost: false, options: options} +} + +func NewTHttpPostClientTransportFactory(url string) *THttpClientTransportFactory { + return NewTHttpPostClientTransportFactoryWithOptions(url, THttpClientOptions{}) +} + +func NewTHttpPostClientTransportFactoryWithOptions(url string, options THttpClientOptions) *THttpClientTransportFactory { + return &THttpClientTransportFactory{url: url, isPost: true, options: options} +} + +func NewTHttpClientWithOptions(urlstr string, options THttpClientOptions) (TTransport, error) { + parsedURL, err := url.Parse(urlstr) + if err != nil { + return nil, err + } + response, err := http.Get(urlstr) + if err != nil { + return nil, err + } + client := options.Client + if client == nil { + client = DefaultHttpClient + } + httpHeader := map[string][]string{"Content-Type": []string{"application/x-thrift"}} + return &THttpClient{client: client, response: response, url: parsedURL, header: httpHeader}, nil +} + +func NewTHttpClient(urlstr string) (TTransport, error) { + return NewTHttpClientWithOptions(urlstr, THttpClientOptions{}) +} + +func NewTHttpPostClientWithOptions(urlstr string, options THttpClientOptions) (TTransport, error) { + parsedURL, err := url.Parse(urlstr) + if err != nil { + return nil, err + } + buf := make([]byte, 0, 1024) + client := options.Client + if client == nil { + client = DefaultHttpClient + } + httpHeader := map[string][]string{"Content-Type": []string{"application/x-thrift"}} + return &THttpClient{client: client, url: parsedURL, requestBuffer: bytes.NewBuffer(buf), header: httpHeader}, nil +} + +func NewTHttpPostClient(urlstr string) (TTransport, error) { + return NewTHttpPostClientWithOptions(urlstr, THttpClientOptions{}) +} + +// Set the HTTP Header for this specific Thrift Transport +// It is important that you first assert the TTransport as a THttpClient type +// like so: +// +// httpTrans := trans.(THttpClient) +// httpTrans.SetHeader("User-Agent","Thrift Client 1.0") +func (p *THttpClient) SetHeader(key string, value string) { + p.header.Add(key, value) +} + +// Get the HTTP Header represented by the supplied Header Key for this specific Thrift Transport +// It is important that you first assert the TTransport as a THttpClient type +// like so: +// +// httpTrans := trans.(THttpClient) +// hdrValue := httpTrans.GetHeader("User-Agent") +func (p *THttpClient) GetHeader(key string) string { + return p.header.Get(key) +} + +// Deletes the HTTP Header given a Header Key for this specific Thrift Transport +// It is important that you first assert the TTransport as a THttpClient type +// like so: +// +// httpTrans := trans.(THttpClient) +// httpTrans.DelHeader("User-Agent") +func (p *THttpClient) DelHeader(key string) { + p.header.Del(key) +} + +func (p *THttpClient) Open() error { + // do nothing + return nil +} + +func (p *THttpClient) IsOpen() bool { + return p.response != nil || p.requestBuffer != nil +} + +func (p *THttpClient) closeResponse() error { + var err error + if p.response != nil && p.response.Body != nil { + // The docs specify that if keepalive is enabled and the response body is not + // read to completion the connection will never be returned to the pool and + // reused. Errors are being ignored here because if the connection is invalid + // and this fails for some reason, the Close() method will do any remaining + // cleanup. + io.Copy(ioutil.Discard, p.response.Body) + + err = p.response.Body.Close() + } + + p.response = nil + return err +} + +func (p *THttpClient) Close() error { + if p.requestBuffer != nil { + p.requestBuffer.Reset() + p.requestBuffer = nil + } + return p.closeResponse() +} + +func (p *THttpClient) Read(buf []byte) (int, error) { + if p.response == nil { + return 0, NewTTransportException(NOT_OPEN, "Response buffer is empty, no request.") + } + n, err := p.response.Body.Read(buf) + if n > 0 && (err == nil || err == io.EOF) { + return n, nil + } + return n, NewTTransportExceptionFromError(err) +} + +func (p *THttpClient) ReadByte() (c byte, err error) { + return readByte(p.response.Body) +} + +func (p *THttpClient) Write(buf []byte) (int, error) { + n, err := p.requestBuffer.Write(buf) + return n, err +} + +func (p *THttpClient) WriteByte(c byte) error { + return p.requestBuffer.WriteByte(c) +} + +func (p *THttpClient) WriteString(s string) (n int, err error) { + return p.requestBuffer.WriteString(s) +} + +func (p *THttpClient) Flush() error { + // Close any previous response body to avoid leaking connections. + p.closeResponse() + + req, err := http.NewRequest("POST", p.url.String(), p.requestBuffer) + if err != nil { + return NewTTransportExceptionFromError(err) + } + req.Header = p.header + response, err := p.client.Do(req) + if err != nil { + return NewTTransportExceptionFromError(err) + } + if response.StatusCode != http.StatusOK { + // Close the response to avoid leaking file descriptors. closeResponse does + // more than just call Close(), so temporarily assign it and reuse the logic. + p.response = response + p.closeResponse() + + // TODO(pomack) log bad response + return NewTTransportException(UNKNOWN_TRANSPORT_EXCEPTION, "HTTP Response code: "+strconv.Itoa(response.StatusCode)) + } + p.response = response + return nil +} + +func (p *THttpClient) RemainingBytes() (num_bytes uint64) { + len := p.response.ContentLength + if len >= 0 { + return uint64(len) + } + + const maxSize = ^uint64(0) + return maxSize // the thruth is, we just don't know unless framed is used +} diff --git a/vendor/github.com/apache/thrift/lib/go/thrift/http_transport.go b/vendor/github.com/apache/thrift/lib/go/thrift/http_transport.go new file mode 100644 index 000000000..f6d7458db --- /dev/null +++ b/vendor/github.com/apache/thrift/lib/go/thrift/http_transport.go @@ -0,0 +1,34 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package thrift + +import "net/http" + +// NewThriftHandlerFunc is a function that create a ready to use Apache Thrift Handler function +func NewThriftHandlerFunc(processor TProcessor, + inPfactory, outPfactory TProtocolFactory) func(w http.ResponseWriter, r *http.Request) { + + return func(w http.ResponseWriter, r *http.Request) { + w.Header().Add("Content-Type", "application/x-thrift") + + transport := NewStreamTransport(r.Body, w) + processor.Process(inPfactory.GetProtocol(transport), outPfactory.GetProtocol(transport)) + } +} diff --git a/vendor/github.com/apache/thrift/lib/go/thrift/iostream_transport.go b/vendor/github.com/apache/thrift/lib/go/thrift/iostream_transport.go new file mode 100644 index 000000000..794872ff1 --- /dev/null +++ b/vendor/github.com/apache/thrift/lib/go/thrift/iostream_transport.go @@ -0,0 +1,214 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package thrift + +import ( + "bufio" + "io" +) + +// StreamTransport is a Transport made of an io.Reader and/or an io.Writer +type StreamTransport struct { + io.Reader + io.Writer + isReadWriter bool + closed bool +} + +type StreamTransportFactory struct { + Reader io.Reader + Writer io.Writer + isReadWriter bool +} + +func (p *StreamTransportFactory) GetTransport(trans TTransport) TTransport { + if trans != nil { + t, ok := trans.(*StreamTransport) + if ok { + if t.isReadWriter { + return NewStreamTransportRW(t.Reader.(io.ReadWriter)) + } + if t.Reader != nil && t.Writer != nil { + return NewStreamTransport(t.Reader, t.Writer) + } + if t.Reader != nil && t.Writer == nil { + return NewStreamTransportR(t.Reader) + } + if t.Reader == nil && t.Writer != nil { + return NewStreamTransportW(t.Writer) + } + return &StreamTransport{} + } + } + if p.isReadWriter { + return NewStreamTransportRW(p.Reader.(io.ReadWriter)) + } + if p.Reader != nil && p.Writer != nil { + return NewStreamTransport(p.Reader, p.Writer) + } + if p.Reader != nil && p.Writer == nil { + return NewStreamTransportR(p.Reader) + } + if p.Reader == nil && p.Writer != nil { + return NewStreamTransportW(p.Writer) + } + return &StreamTransport{} +} + +func NewStreamTransportFactory(reader io.Reader, writer io.Writer, isReadWriter bool) *StreamTransportFactory { + return &StreamTransportFactory{Reader: reader, Writer: writer, isReadWriter: isReadWriter} +} + +func NewStreamTransport(r io.Reader, w io.Writer) *StreamTransport { + return &StreamTransport{Reader: bufio.NewReader(r), Writer: bufio.NewWriter(w)} +} + +func NewStreamTransportR(r io.Reader) *StreamTransport { + return &StreamTransport{Reader: bufio.NewReader(r)} +} + +func NewStreamTransportW(w io.Writer) *StreamTransport { + return &StreamTransport{Writer: bufio.NewWriter(w)} +} + +func NewStreamTransportRW(rw io.ReadWriter) *StreamTransport { + bufrw := bufio.NewReadWriter(bufio.NewReader(rw), bufio.NewWriter(rw)) + return &StreamTransport{Reader: bufrw, Writer: bufrw, isReadWriter: true} +} + +func (p *StreamTransport) IsOpen() bool { + return !p.closed +} + +// implicitly opened on creation, can't be reopened once closed +func (p *StreamTransport) Open() error { + if !p.closed { + return NewTTransportException(ALREADY_OPEN, "StreamTransport already open.") + } else { + return NewTTransportException(NOT_OPEN, "cannot reopen StreamTransport.") + } +} + +// Closes both the input and output streams. +func (p *StreamTransport) Close() error { + if p.closed { + return NewTTransportException(NOT_OPEN, "StreamTransport already closed.") + } + p.closed = true + closedReader := false + if p.Reader != nil { + c, ok := p.Reader.(io.Closer) + if ok { + e := c.Close() + closedReader = true + if e != nil { + return e + } + } + p.Reader = nil + } + if p.Writer != nil && (!closedReader || !p.isReadWriter) { + c, ok := p.Writer.(io.Closer) + if ok { + e := c.Close() + if e != nil { + return e + } + } + p.Writer = nil + } + return nil +} + +// Flushes the underlying output stream if not null. +func (p *StreamTransport) Flush() error { + if p.Writer == nil { + return NewTTransportException(NOT_OPEN, "Cannot flush null outputStream") + } + f, ok := p.Writer.(Flusher) + if ok { + err := f.Flush() + if err != nil { + return NewTTransportExceptionFromError(err) + } + } + return nil +} + +func (p *StreamTransport) Read(c []byte) (n int, err error) { + n, err = p.Reader.Read(c) + if err != nil { + err = NewTTransportExceptionFromError(err) + } + return +} + +func (p *StreamTransport) ReadByte() (c byte, err error) { + f, ok := p.Reader.(io.ByteReader) + if ok { + c, err = f.ReadByte() + } else { + c, err = readByte(p.Reader) + } + if err != nil { + err = NewTTransportExceptionFromError(err) + } + return +} + +func (p *StreamTransport) Write(c []byte) (n int, err error) { + n, err = p.Writer.Write(c) + if err != nil { + err = NewTTransportExceptionFromError(err) + } + return +} + +func (p *StreamTransport) WriteByte(c byte) (err error) { + f, ok := p.Writer.(io.ByteWriter) + if ok { + err = f.WriteByte(c) + } else { + err = writeByte(p.Writer, c) + } + if err != nil { + err = NewTTransportExceptionFromError(err) + } + return +} + +func (p *StreamTransport) WriteString(s string) (n int, err error) { + f, ok := p.Writer.(stringWriter) + if ok { + n, err = f.WriteString(s) + } else { + n, err = p.Writer.Write([]byte(s)) + } + if err != nil { + err = NewTTransportExceptionFromError(err) + } + return +} + +func (p *StreamTransport) RemainingBytes() (num_bytes uint64) { + const maxSize = ^uint64(0) + return maxSize // the thruth is, we just don't know unless framed is used +} + diff --git a/vendor/github.com/apache/thrift/lib/go/thrift/json_protocol.go b/vendor/github.com/apache/thrift/lib/go/thrift/json_protocol.go new file mode 100644 index 000000000..442fa9144 --- /dev/null +++ b/vendor/github.com/apache/thrift/lib/go/thrift/json_protocol.go @@ -0,0 +1,583 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package thrift + +import ( + "encoding/base64" + "fmt" +) + +const ( + THRIFT_JSON_PROTOCOL_VERSION = 1 +) + +// for references to _ParseContext see tsimplejson_protocol.go + +// JSON protocol implementation for thrift. +// +// This protocol produces/consumes a simple output format +// suitable for parsing by scripting languages. It should not be +// confused with the full-featured TJSONProtocol. +// +type TJSONProtocol struct { + *TSimpleJSONProtocol +} + +// Constructor +func NewTJSONProtocol(t TTransport) *TJSONProtocol { + v := &TJSONProtocol{TSimpleJSONProtocol: NewTSimpleJSONProtocol(t)} + v.parseContextStack = append(v.parseContextStack, int(_CONTEXT_IN_TOPLEVEL)) + v.dumpContext = append(v.dumpContext, int(_CONTEXT_IN_TOPLEVEL)) + return v +} + +// Factory +type TJSONProtocolFactory struct{} + +func (p *TJSONProtocolFactory) GetProtocol(trans TTransport) TProtocol { + return NewTJSONProtocol(trans) +} + +func NewTJSONProtocolFactory() *TJSONProtocolFactory { + return &TJSONProtocolFactory{} +} + +func (p *TJSONProtocol) WriteMessageBegin(name string, typeId TMessageType, seqId int32) error { + p.resetContextStack() // THRIFT-3735 + if e := p.OutputListBegin(); e != nil { + return e + } + if e := p.WriteI32(THRIFT_JSON_PROTOCOL_VERSION); e != nil { + return e + } + if e := p.WriteString(name); e != nil { + return e + } + if e := p.WriteByte(int8(typeId)); e != nil { + return e + } + if e := p.WriteI32(seqId); e != nil { + return e + } + return nil +} + +func (p *TJSONProtocol) WriteMessageEnd() error { + return p.OutputListEnd() +} + +func (p *TJSONProtocol) WriteStructBegin(name string) error { + if e := p.OutputObjectBegin(); e != nil { + return e + } + return nil +} + +func (p *TJSONProtocol) WriteStructEnd() error { + return p.OutputObjectEnd() +} + +func (p *TJSONProtocol) WriteFieldBegin(name string, typeId TType, id int16) error { + if e := p.WriteI16(id); e != nil { + return e + } + if e := p.OutputObjectBegin(); e != nil { + return e + } + s, e1 := p.TypeIdToString(typeId) + if e1 != nil { + return e1 + } + if e := p.WriteString(s); e != nil { + return e + } + return nil +} + +func (p *TJSONProtocol) WriteFieldEnd() error { + return p.OutputObjectEnd() +} + +func (p *TJSONProtocol) WriteFieldStop() error { return nil } + +func (p *TJSONProtocol) WriteMapBegin(keyType TType, valueType TType, size int) error { + if e := p.OutputListBegin(); e != nil { + return e + } + s, e1 := p.TypeIdToString(keyType) + if e1 != nil { + return e1 + } + if e := p.WriteString(s); e != nil { + return e + } + s, e1 = p.TypeIdToString(valueType) + if e1 != nil { + return e1 + } + if e := p.WriteString(s); e != nil { + return e + } + if e := p.WriteI64(int64(size)); e != nil { + return e + } + return p.OutputObjectBegin() +} + +func (p *TJSONProtocol) WriteMapEnd() error { + if e := p.OutputObjectEnd(); e != nil { + return e + } + return p.OutputListEnd() +} + +func (p *TJSONProtocol) WriteListBegin(elemType TType, size int) error { + return p.OutputElemListBegin(elemType, size) +} + +func (p *TJSONProtocol) WriteListEnd() error { + return p.OutputListEnd() +} + +func (p *TJSONProtocol) WriteSetBegin(elemType TType, size int) error { + return p.OutputElemListBegin(elemType, size) +} + +func (p *TJSONProtocol) WriteSetEnd() error { + return p.OutputListEnd() +} + +func (p *TJSONProtocol) WriteBool(b bool) error { + if b { + return p.WriteI32(1) + } + return p.WriteI32(0) +} + +func (p *TJSONProtocol) WriteByte(b int8) error { + return p.WriteI32(int32(b)) +} + +func (p *TJSONProtocol) WriteI16(v int16) error { + return p.WriteI32(int32(v)) +} + +func (p *TJSONProtocol) WriteI32(v int32) error { + return p.OutputI64(int64(v)) +} + +func (p *TJSONProtocol) WriteI64(v int64) error { + return p.OutputI64(int64(v)) +} + +func (p *TJSONProtocol) WriteDouble(v float64) error { + return p.OutputF64(v) +} + +func (p *TJSONProtocol) WriteString(v string) error { + return p.OutputString(v) +} + +func (p *TJSONProtocol) WriteBinary(v []byte) error { + // JSON library only takes in a string, + // not an arbitrary byte array, to ensure bytes are transmitted + // efficiently we must convert this into a valid JSON string + // therefore we use base64 encoding to avoid excessive escaping/quoting + if e := p.OutputPreValue(); e != nil { + return e + } + if _, e := p.write(JSON_QUOTE_BYTES); e != nil { + return NewTProtocolException(e) + } + writer := base64.NewEncoder(base64.StdEncoding, p.writer) + if _, e := writer.Write(v); e != nil { + p.writer.Reset(p.trans) // THRIFT-3735 + return NewTProtocolException(e) + } + if e := writer.Close(); e != nil { + return NewTProtocolException(e) + } + if _, e := p.write(JSON_QUOTE_BYTES); e != nil { + return NewTProtocolException(e) + } + return p.OutputPostValue() +} + +// Reading methods. +func (p *TJSONProtocol) ReadMessageBegin() (name string, typeId TMessageType, seqId int32, err error) { + p.resetContextStack() // THRIFT-3735 + if isNull, err := p.ParseListBegin(); isNull || err != nil { + return name, typeId, seqId, err + } + version, err := p.ReadI32() + if err != nil { + return name, typeId, seqId, err + } + if version != THRIFT_JSON_PROTOCOL_VERSION { + e := fmt.Errorf("Unknown Protocol version %d, expected version %d", version, THRIFT_JSON_PROTOCOL_VERSION) + return name, typeId, seqId, NewTProtocolExceptionWithType(INVALID_DATA, e) + + } + if name, err = p.ReadString(); err != nil { + return name, typeId, seqId, err + } + bTypeId, err := p.ReadByte() + typeId = TMessageType(bTypeId) + if err != nil { + return name, typeId, seqId, err + } + if seqId, err = p.ReadI32(); err != nil { + return name, typeId, seqId, err + } + return name, typeId, seqId, nil +} + +func (p *TJSONProtocol) ReadMessageEnd() error { + err := p.ParseListEnd() + return err +} + +func (p *TJSONProtocol) ReadStructBegin() (name string, err error) { + _, err = p.ParseObjectStart() + return "", err +} + +func (p *TJSONProtocol) ReadStructEnd() error { + return p.ParseObjectEnd() +} + +func (p *TJSONProtocol) ReadFieldBegin() (string, TType, int16, error) { + b, _ := p.reader.Peek(1) + if len(b) < 1 || b[0] == JSON_RBRACE[0] || b[0] == JSON_RBRACKET[0] { + return "", STOP, -1, nil + } + fieldId, err := p.ReadI16() + if err != nil { + return "", STOP, fieldId, err + } + if _, err = p.ParseObjectStart(); err != nil { + return "", STOP, fieldId, err + } + sType, err := p.ReadString() + if err != nil { + return "", STOP, fieldId, err + } + fType, err := p.StringToTypeId(sType) + return "", fType, fieldId, err +} + +func (p *TJSONProtocol) ReadFieldEnd() error { + return p.ParseObjectEnd() +} + +func (p *TJSONProtocol) ReadMapBegin() (keyType TType, valueType TType, size int, e error) { + if isNull, e := p.ParseListBegin(); isNull || e != nil { + return VOID, VOID, 0, e + } + + // read keyType + sKeyType, e := p.ReadString() + if e != nil { + return keyType, valueType, size, e + } + keyType, e = p.StringToTypeId(sKeyType) + if e != nil { + return keyType, valueType, size, e + } + + // read valueType + sValueType, e := p.ReadString() + if e != nil { + return keyType, valueType, size, e + } + valueType, e = p.StringToTypeId(sValueType) + if e != nil { + return keyType, valueType, size, e + } + + // read size + iSize, e := p.ReadI64() + if e != nil { + return keyType, valueType, size, e + } + size = int(iSize) + + _, e = p.ParseObjectStart() + return keyType, valueType, size, e +} + +func (p *TJSONProtocol) ReadMapEnd() error { + e := p.ParseObjectEnd() + if e != nil { + return e + } + return p.ParseListEnd() +} + +func (p *TJSONProtocol) ReadListBegin() (elemType TType, size int, e error) { + return p.ParseElemListBegin() +} + +func (p *TJSONProtocol) ReadListEnd() error { + return p.ParseListEnd() +} + +func (p *TJSONProtocol) ReadSetBegin() (elemType TType, size int, e error) { + return p.ParseElemListBegin() +} + +func (p *TJSONProtocol) ReadSetEnd() error { + return p.ParseListEnd() +} + +func (p *TJSONProtocol) ReadBool() (bool, error) { + value, err := p.ReadI32() + return (value != 0), err +} + +func (p *TJSONProtocol) ReadByte() (int8, error) { + v, err := p.ReadI64() + return int8(v), err +} + +func (p *TJSONProtocol) ReadI16() (int16, error) { + v, err := p.ReadI64() + return int16(v), err +} + +func (p *TJSONProtocol) ReadI32() (int32, error) { + v, err := p.ReadI64() + return int32(v), err +} + +func (p *TJSONProtocol) ReadI64() (int64, error) { + v, _, err := p.ParseI64() + return v, err +} + +func (p *TJSONProtocol) ReadDouble() (float64, error) { + v, _, err := p.ParseF64() + return v, err +} + +func (p *TJSONProtocol) ReadString() (string, error) { + var v string + if err := p.ParsePreValue(); err != nil { + return v, err + } + f, _ := p.reader.Peek(1) + if len(f) > 0 && f[0] == JSON_QUOTE { + p.reader.ReadByte() + value, err := p.ParseStringBody() + v = value + if err != nil { + return v, err + } + } else if len(f) > 0 && f[0] == JSON_NULL[0] { + b := make([]byte, len(JSON_NULL)) + _, err := p.reader.Read(b) + if err != nil { + return v, NewTProtocolException(err) + } + if string(b) != string(JSON_NULL) { + e := fmt.Errorf("Expected a JSON string, found unquoted data started with %s", string(b)) + return v, NewTProtocolExceptionWithType(INVALID_DATA, e) + } + } else { + e := fmt.Errorf("Expected a JSON string, found unquoted data started with %s", string(f)) + return v, NewTProtocolExceptionWithType(INVALID_DATA, e) + } + return v, p.ParsePostValue() +} + +func (p *TJSONProtocol) ReadBinary() ([]byte, error) { + var v []byte + if err := p.ParsePreValue(); err != nil { + return nil, err + } + f, _ := p.reader.Peek(1) + if len(f) > 0 && f[0] == JSON_QUOTE { + p.reader.ReadByte() + value, err := p.ParseBase64EncodedBody() + v = value + if err != nil { + return v, err + } + } else if len(f) > 0 && f[0] == JSON_NULL[0] { + b := make([]byte, len(JSON_NULL)) + _, err := p.reader.Read(b) + if err != nil { + return v, NewTProtocolException(err) + } + if string(b) != string(JSON_NULL) { + e := fmt.Errorf("Expected a JSON string, found unquoted data started with %s", string(b)) + return v, NewTProtocolExceptionWithType(INVALID_DATA, e) + } + } else { + e := fmt.Errorf("Expected a JSON string, found unquoted data started with %s", string(f)) + return v, NewTProtocolExceptionWithType(INVALID_DATA, e) + } + + return v, p.ParsePostValue() +} + +func (p *TJSONProtocol) Flush() (err error) { + err = p.writer.Flush() + if err == nil { + err = p.trans.Flush() + } + return NewTProtocolException(err) +} + +func (p *TJSONProtocol) Skip(fieldType TType) (err error) { + return SkipDefaultDepth(p, fieldType) +} + +func (p *TJSONProtocol) Transport() TTransport { + return p.trans +} + +func (p *TJSONProtocol) OutputElemListBegin(elemType TType, size int) error { + if e := p.OutputListBegin(); e != nil { + return e + } + s, e1 := p.TypeIdToString(elemType) + if e1 != nil { + return e1 + } + if e := p.WriteString(s); e != nil { + return e + } + if e := p.WriteI64(int64(size)); e != nil { + return e + } + return nil +} + +func (p *TJSONProtocol) ParseElemListBegin() (elemType TType, size int, e error) { + if isNull, e := p.ParseListBegin(); isNull || e != nil { + return VOID, 0, e + } + sElemType, err := p.ReadString() + if err != nil { + return VOID, size, err + } + elemType, err = p.StringToTypeId(sElemType) + if err != nil { + return elemType, size, err + } + nSize, err2 := p.ReadI64() + size = int(nSize) + return elemType, size, err2 +} + +func (p *TJSONProtocol) readElemListBegin() (elemType TType, size int, e error) { + if isNull, e := p.ParseListBegin(); isNull || e != nil { + return VOID, 0, e + } + sElemType, err := p.ReadString() + if err != nil { + return VOID, size, err + } + elemType, err = p.StringToTypeId(sElemType) + if err != nil { + return elemType, size, err + } + nSize, err2 := p.ReadI64() + size = int(nSize) + return elemType, size, err2 +} + +func (p *TJSONProtocol) writeElemListBegin(elemType TType, size int) error { + if e := p.OutputListBegin(); e != nil { + return e + } + s, e1 := p.TypeIdToString(elemType) + if e1 != nil { + return e1 + } + if e := p.OutputString(s); e != nil { + return e + } + if e := p.OutputI64(int64(size)); e != nil { + return e + } + return nil +} + +func (p *TJSONProtocol) TypeIdToString(fieldType TType) (string, error) { + switch byte(fieldType) { + case BOOL: + return "tf", nil + case BYTE: + return "i8", nil + case I16: + return "i16", nil + case I32: + return "i32", nil + case I64: + return "i64", nil + case DOUBLE: + return "dbl", nil + case STRING: + return "str", nil + case STRUCT: + return "rec", nil + case MAP: + return "map", nil + case SET: + return "set", nil + case LIST: + return "lst", nil + } + + e := fmt.Errorf("Unknown fieldType: %d", int(fieldType)) + return "", NewTProtocolExceptionWithType(INVALID_DATA, e) +} + +func (p *TJSONProtocol) StringToTypeId(fieldType string) (TType, error) { + switch fieldType { + case "tf": + return TType(BOOL), nil + case "i8": + return TType(BYTE), nil + case "i16": + return TType(I16), nil + case "i32": + return TType(I32), nil + case "i64": + return TType(I64), nil + case "dbl": + return TType(DOUBLE), nil + case "str": + return TType(STRING), nil + case "rec": + return TType(STRUCT), nil + case "map": + return TType(MAP), nil + case "set": + return TType(SET), nil + case "lst": + return TType(LIST), nil + } + + e := fmt.Errorf("Unknown type identifier: %s", fieldType) + return TType(STOP), NewTProtocolExceptionWithType(INVALID_DATA, e) +} diff --git a/vendor/github.com/apache/thrift/lib/go/thrift/memory_buffer.go b/vendor/github.com/apache/thrift/lib/go/thrift/memory_buffer.go new file mode 100644 index 000000000..b62fd56f0 --- /dev/null +++ b/vendor/github.com/apache/thrift/lib/go/thrift/memory_buffer.go @@ -0,0 +1,79 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package thrift + +import ( + "bytes" +) + +// Memory buffer-based implementation of the TTransport interface. +type TMemoryBuffer struct { + *bytes.Buffer + size int +} + +type TMemoryBufferTransportFactory struct { + size int +} + +func (p *TMemoryBufferTransportFactory) GetTransport(trans TTransport) TTransport { + if trans != nil { + t, ok := trans.(*TMemoryBuffer) + if ok && t.size > 0 { + return NewTMemoryBufferLen(t.size) + } + } + return NewTMemoryBufferLen(p.size) +} + +func NewTMemoryBufferTransportFactory(size int) *TMemoryBufferTransportFactory { + return &TMemoryBufferTransportFactory{size: size} +} + +func NewTMemoryBuffer() *TMemoryBuffer { + return &TMemoryBuffer{Buffer: &bytes.Buffer{}, size: 0} +} + +func NewTMemoryBufferLen(size int) *TMemoryBuffer { + buf := make([]byte, 0, size) + return &TMemoryBuffer{Buffer: bytes.NewBuffer(buf), size: size} +} + +func (p *TMemoryBuffer) IsOpen() bool { + return true +} + +func (p *TMemoryBuffer) Open() error { + return nil +} + +func (p *TMemoryBuffer) Close() error { + p.Buffer.Reset() + return nil +} + +// Flushing a memory buffer is a no-op +func (p *TMemoryBuffer) Flush() error { + return nil +} + +func (p *TMemoryBuffer) RemainingBytes() (num_bytes uint64) { + return uint64(p.Buffer.Len()) +} diff --git a/vendor/github.com/apache/thrift/lib/go/thrift/messagetype.go b/vendor/github.com/apache/thrift/lib/go/thrift/messagetype.go new file mode 100644 index 000000000..25ab2e98a --- /dev/null +++ b/vendor/github.com/apache/thrift/lib/go/thrift/messagetype.go @@ -0,0 +1,31 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package thrift + +// Message type constants in the Thrift protocol. +type TMessageType int32 + +const ( + INVALID_TMESSAGE_TYPE TMessageType = 0 + CALL TMessageType = 1 + REPLY TMessageType = 2 + EXCEPTION TMessageType = 3 + ONEWAY TMessageType = 4 +) diff --git a/vendor/github.com/apache/thrift/lib/go/thrift/multiplexed_protocol.go b/vendor/github.com/apache/thrift/lib/go/thrift/multiplexed_protocol.go new file mode 100644 index 000000000..3157e0d5d --- /dev/null +++ b/vendor/github.com/apache/thrift/lib/go/thrift/multiplexed_protocol.go @@ -0,0 +1,169 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package thrift + +import ( + "fmt" + "strings" +) + +/* +TMultiplexedProtocol is a protocol-independent concrete decorator +that allows a Thrift client to communicate with a multiplexing Thrift server, +by prepending the service name to the function name during function calls. + +NOTE: THIS IS NOT USED BY SERVERS. On the server, use TMultiplexedProcessor to handle request +from a multiplexing client. + +This example uses a single socket transport to invoke two services: + +socket := thrift.NewTSocketFromAddrTimeout(addr, TIMEOUT) +transport := thrift.NewTFramedTransport(socket) +protocol := thrift.NewTBinaryProtocolTransport(transport) + +mp := thrift.NewTMultiplexedProtocol(protocol, "Calculator") +service := Calculator.NewCalculatorClient(mp) + +mp2 := thrift.NewTMultiplexedProtocol(protocol, "WeatherReport") +service2 := WeatherReport.NewWeatherReportClient(mp2) + +err := transport.Open() +if err != nil { + t.Fatal("Unable to open client socket", err) +} + +fmt.Println(service.Add(2,2)) +fmt.Println(service2.GetTemperature()) +*/ + +type TMultiplexedProtocol struct { + TProtocol + serviceName string +} + +const MULTIPLEXED_SEPARATOR = ":" + +func NewTMultiplexedProtocol(protocol TProtocol, serviceName string) *TMultiplexedProtocol { + return &TMultiplexedProtocol{ + TProtocol: protocol, + serviceName: serviceName, + } +} + +func (t *TMultiplexedProtocol) WriteMessageBegin(name string, typeId TMessageType, seqid int32) error { + if typeId == CALL || typeId == ONEWAY { + return t.TProtocol.WriteMessageBegin(t.serviceName+MULTIPLEXED_SEPARATOR+name, typeId, seqid) + } else { + return t.TProtocol.WriteMessageBegin(name, typeId, seqid) + } +} + +/* +TMultiplexedProcessor is a TProcessor allowing +a single TServer to provide multiple services. + +To do so, you instantiate the processor and then register additional +processors with it, as shown in the following example: + +var processor = thrift.NewTMultiplexedProcessor() + +firstProcessor := +processor.RegisterProcessor("FirstService", firstProcessor) + +processor.registerProcessor( + "Calculator", + Calculator.NewCalculatorProcessor(&CalculatorHandler{}), +) + +processor.registerProcessor( + "WeatherReport", + WeatherReport.NewWeatherReportProcessor(&WeatherReportHandler{}), +) + +serverTransport, err := thrift.NewTServerSocketTimeout(addr, TIMEOUT) +if err != nil { + t.Fatal("Unable to create server socket", err) +} +server := thrift.NewTSimpleServer2(processor, serverTransport) +server.Serve(); +*/ + +type TMultiplexedProcessor struct { + serviceProcessorMap map[string]TProcessor + DefaultProcessor TProcessor +} + +func NewTMultiplexedProcessor() *TMultiplexedProcessor { + return &TMultiplexedProcessor{ + serviceProcessorMap: make(map[string]TProcessor), + } +} + +func (t *TMultiplexedProcessor) RegisterDefault(processor TProcessor) { + t.DefaultProcessor = processor +} + +func (t *TMultiplexedProcessor) RegisterProcessor(name string, processor TProcessor) { + if t.serviceProcessorMap == nil { + t.serviceProcessorMap = make(map[string]TProcessor) + } + t.serviceProcessorMap[name] = processor +} + +func (t *TMultiplexedProcessor) Process(in, out TProtocol) (bool, TException) { + name, typeId, seqid, err := in.ReadMessageBegin() + if err != nil { + return false, err + } + if typeId != CALL && typeId != ONEWAY { + return false, fmt.Errorf("Unexpected message type %v", typeId) + } + //extract the service name + v := strings.SplitN(name, MULTIPLEXED_SEPARATOR, 2) + if len(v) != 2 { + if t.DefaultProcessor != nil { + smb := NewStoredMessageProtocol(in, name, typeId, seqid) + return t.DefaultProcessor.Process(smb, out) + } + return false, fmt.Errorf("Service name not found in message name: %s. Did you forget to use a TMultiplexProtocol in your client?", name) + } + actualProcessor, ok := t.serviceProcessorMap[v[0]] + if !ok { + return false, fmt.Errorf("Service name not found: %s. Did you forget to call registerProcessor()?", v[0]) + } + smb := NewStoredMessageProtocol(in, v[1], typeId, seqid) + return actualProcessor.Process(smb, out) +} + +//Protocol that use stored message for ReadMessageBegin +type storedMessageProtocol struct { + TProtocol + name string + typeId TMessageType + seqid int32 +} + +func NewStoredMessageProtocol(protocol TProtocol, name string, typeId TMessageType, seqid int32) *storedMessageProtocol { + return &storedMessageProtocol{protocol, name, typeId, seqid} +} + +func (s *storedMessageProtocol) ReadMessageBegin() (name string, typeId TMessageType, seqid int32, err error) { + return s.name, s.typeId, s.seqid, nil +} diff --git a/vendor/github.com/apache/thrift/lib/go/thrift/numeric.go b/vendor/github.com/apache/thrift/lib/go/thrift/numeric.go new file mode 100644 index 000000000..aa8daa9b5 --- /dev/null +++ b/vendor/github.com/apache/thrift/lib/go/thrift/numeric.go @@ -0,0 +1,164 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package thrift + +import ( + "math" + "strconv" +) + +type Numeric interface { + Int64() int64 + Int32() int32 + Int16() int16 + Byte() byte + Int() int + Float64() float64 + Float32() float32 + String() string + isNull() bool +} + +type numeric struct { + iValue int64 + dValue float64 + sValue string + isNil bool +} + +var ( + INFINITY Numeric + NEGATIVE_INFINITY Numeric + NAN Numeric + ZERO Numeric + NUMERIC_NULL Numeric +) + +func NewNumericFromDouble(dValue float64) Numeric { + if math.IsInf(dValue, 1) { + return INFINITY + } + if math.IsInf(dValue, -1) { + return NEGATIVE_INFINITY + } + if math.IsNaN(dValue) { + return NAN + } + iValue := int64(dValue) + sValue := strconv.FormatFloat(dValue, 'g', 10, 64) + isNil := false + return &numeric{iValue: iValue, dValue: dValue, sValue: sValue, isNil: isNil} +} + +func NewNumericFromI64(iValue int64) Numeric { + dValue := float64(iValue) + sValue := string(iValue) + isNil := false + return &numeric{iValue: iValue, dValue: dValue, sValue: sValue, isNil: isNil} +} + +func NewNumericFromI32(iValue int32) Numeric { + dValue := float64(iValue) + sValue := string(iValue) + isNil := false + return &numeric{iValue: int64(iValue), dValue: dValue, sValue: sValue, isNil: isNil} +} + +func NewNumericFromString(sValue string) Numeric { + if sValue == INFINITY.String() { + return INFINITY + } + if sValue == NEGATIVE_INFINITY.String() { + return NEGATIVE_INFINITY + } + if sValue == NAN.String() { + return NAN + } + iValue, _ := strconv.ParseInt(sValue, 10, 64) + dValue, _ := strconv.ParseFloat(sValue, 64) + isNil := len(sValue) == 0 + return &numeric{iValue: iValue, dValue: dValue, sValue: sValue, isNil: isNil} +} + +func NewNumericFromJSONString(sValue string, isNull bool) Numeric { + if isNull { + return NewNullNumeric() + } + if sValue == JSON_INFINITY { + return INFINITY + } + if sValue == JSON_NEGATIVE_INFINITY { + return NEGATIVE_INFINITY + } + if sValue == JSON_NAN { + return NAN + } + iValue, _ := strconv.ParseInt(sValue, 10, 64) + dValue, _ := strconv.ParseFloat(sValue, 64) + return &numeric{iValue: iValue, dValue: dValue, sValue: sValue, isNil: isNull} +} + +func NewNullNumeric() Numeric { + return &numeric{iValue: 0, dValue: 0.0, sValue: "", isNil: true} +} + +func (p *numeric) Int64() int64 { + return p.iValue +} + +func (p *numeric) Int32() int32 { + return int32(p.iValue) +} + +func (p *numeric) Int16() int16 { + return int16(p.iValue) +} + +func (p *numeric) Byte() byte { + return byte(p.iValue) +} + +func (p *numeric) Int() int { + return int(p.iValue) +} + +func (p *numeric) Float64() float64 { + return p.dValue +} + +func (p *numeric) Float32() float32 { + return float32(p.dValue) +} + +func (p *numeric) String() string { + return p.sValue +} + +func (p *numeric) isNull() bool { + return p.isNil +} + +func init() { + INFINITY = &numeric{iValue: 0, dValue: math.Inf(1), sValue: "Infinity", isNil: false} + NEGATIVE_INFINITY = &numeric{iValue: 0, dValue: math.Inf(-1), sValue: "-Infinity", isNil: false} + NAN = &numeric{iValue: 0, dValue: math.NaN(), sValue: "NaN", isNil: false} + ZERO = &numeric{iValue: 0, dValue: 0, sValue: "0", isNil: false} + NUMERIC_NULL = &numeric{iValue: 0, dValue: 0, sValue: "0", isNil: true} +} diff --git a/vendor/github.com/apache/thrift/lib/go/thrift/pointerize.go b/vendor/github.com/apache/thrift/lib/go/thrift/pointerize.go new file mode 100644 index 000000000..8d6b2c215 --- /dev/null +++ b/vendor/github.com/apache/thrift/lib/go/thrift/pointerize.go @@ -0,0 +1,50 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package thrift + +/////////////////////////////////////////////////////////////////////////////// +// This file is home to helpers that convert from various base types to +// respective pointer types. This is necessary because Go does not permit +// references to constants, nor can a pointer type to base type be allocated +// and initialized in a single expression. +// +// E.g., this is not allowed: +// +// var ip *int = &5 +// +// But this *is* allowed: +// +// func IntPtr(i int) *int { return &i } +// var ip *int = IntPtr(5) +// +// Since pointers to base types are commonplace as [optional] fields in +// exported thrift structs, we factor such helpers here. +/////////////////////////////////////////////////////////////////////////////// + +func Float32Ptr(v float32) *float32 { return &v } +func Float64Ptr(v float64) *float64 { return &v } +func IntPtr(v int) *int { return &v } +func Int32Ptr(v int32) *int32 { return &v } +func Int64Ptr(v int64) *int64 { return &v } +func StringPtr(v string) *string { return &v } +func Uint32Ptr(v uint32) *uint32 { return &v } +func Uint64Ptr(v uint64) *uint64 { return &v } +func BoolPtr(v bool) *bool { return &v } +func ByteSlicePtr(v []byte) *[]byte { return &v } diff --git a/vendor/github.com/apache/thrift/lib/go/thrift/processor.go b/vendor/github.com/apache/thrift/lib/go/thrift/processor.go new file mode 100644 index 000000000..ca0d3faf2 --- /dev/null +++ b/vendor/github.com/apache/thrift/lib/go/thrift/processor.go @@ -0,0 +1,30 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package thrift + +// A processor is a generic object which operates upon an input stream and +// writes to some output stream. +type TProcessor interface { + Process(in, out TProtocol) (bool, TException) +} + +type TProcessorFunction interface { + Process(seqId int32, in, out TProtocol) (bool, TException) +} diff --git a/vendor/github.com/apache/thrift/lib/go/thrift/processor_factory.go b/vendor/github.com/apache/thrift/lib/go/thrift/processor_factory.go new file mode 100644 index 000000000..9d645df24 --- /dev/null +++ b/vendor/github.com/apache/thrift/lib/go/thrift/processor_factory.go @@ -0,0 +1,58 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package thrift + +// The default processor factory just returns a singleton +// instance. +type TProcessorFactory interface { + GetProcessor(trans TTransport) TProcessor +} + +type tProcessorFactory struct { + processor TProcessor +} + +func NewTProcessorFactory(p TProcessor) TProcessorFactory { + return &tProcessorFactory{processor: p} +} + +func (p *tProcessorFactory) GetProcessor(trans TTransport) TProcessor { + return p.processor +} + +/** + * The default processor factory just returns a singleton + * instance. + */ +type TProcessorFunctionFactory interface { + GetProcessorFunction(trans TTransport) TProcessorFunction +} + +type tProcessorFunctionFactory struct { + processor TProcessorFunction +} + +func NewTProcessorFunctionFactory(p TProcessorFunction) TProcessorFunctionFactory { + return &tProcessorFunctionFactory{processor: p} +} + +func (p *tProcessorFunctionFactory) GetProcessorFunction(trans TTransport) TProcessorFunction { + return p.processor +} diff --git a/vendor/github.com/apache/thrift/lib/go/thrift/protocol.go b/vendor/github.com/apache/thrift/lib/go/thrift/protocol.go new file mode 100644 index 000000000..45fa202e7 --- /dev/null +++ b/vendor/github.com/apache/thrift/lib/go/thrift/protocol.go @@ -0,0 +1,175 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package thrift + +import ( + "errors" +) + +const ( + VERSION_MASK = 0xffff0000 + VERSION_1 = 0x80010000 +) + +type TProtocol interface { + WriteMessageBegin(name string, typeId TMessageType, seqid int32) error + WriteMessageEnd() error + WriteStructBegin(name string) error + WriteStructEnd() error + WriteFieldBegin(name string, typeId TType, id int16) error + WriteFieldEnd() error + WriteFieldStop() error + WriteMapBegin(keyType TType, valueType TType, size int) error + WriteMapEnd() error + WriteListBegin(elemType TType, size int) error + WriteListEnd() error + WriteSetBegin(elemType TType, size int) error + WriteSetEnd() error + WriteBool(value bool) error + WriteByte(value int8) error + WriteI16(value int16) error + WriteI32(value int32) error + WriteI64(value int64) error + WriteDouble(value float64) error + WriteString(value string) error + WriteBinary(value []byte) error + + ReadMessageBegin() (name string, typeId TMessageType, seqid int32, err error) + ReadMessageEnd() error + ReadStructBegin() (name string, err error) + ReadStructEnd() error + ReadFieldBegin() (name string, typeId TType, id int16, err error) + ReadFieldEnd() error + ReadMapBegin() (keyType TType, valueType TType, size int, err error) + ReadMapEnd() error + ReadListBegin() (elemType TType, size int, err error) + ReadListEnd() error + ReadSetBegin() (elemType TType, size int, err error) + ReadSetEnd() error + ReadBool() (value bool, err error) + ReadByte() (value int8, err error) + ReadI16() (value int16, err error) + ReadI32() (value int32, err error) + ReadI64() (value int64, err error) + ReadDouble() (value float64, err error) + ReadString() (value string, err error) + ReadBinary() (value []byte, err error) + + Skip(fieldType TType) (err error) + Flush() (err error) + + Transport() TTransport +} + +// The maximum recursive depth the skip() function will traverse +const DEFAULT_RECURSION_DEPTH = 64 + +// Skips over the next data element from the provided input TProtocol object. +func SkipDefaultDepth(prot TProtocol, typeId TType) (err error) { + return Skip(prot, typeId, DEFAULT_RECURSION_DEPTH) +} + +// Skips over the next data element from the provided input TProtocol object. +func Skip(self TProtocol, fieldType TType, maxDepth int) (err error) { + + if maxDepth <= 0 { + return NewTProtocolExceptionWithType( DEPTH_LIMIT, errors.New("Depth limit exceeded")) + } + + switch fieldType { + case STOP: + return + case BOOL: + _, err = self.ReadBool() + return + case BYTE: + _, err = self.ReadByte() + return + case I16: + _, err = self.ReadI16() + return + case I32: + _, err = self.ReadI32() + return + case I64: + _, err = self.ReadI64() + return + case DOUBLE: + _, err = self.ReadDouble() + return + case STRING: + _, err = self.ReadString() + return + case STRUCT: + if _, err = self.ReadStructBegin(); err != nil { + return err + } + for { + _, typeId, _, _ := self.ReadFieldBegin() + if typeId == STOP { + break + } + err := Skip(self, typeId, maxDepth-1) + if err != nil { + return err + } + self.ReadFieldEnd() + } + return self.ReadStructEnd() + case MAP: + keyType, valueType, size, err := self.ReadMapBegin() + if err != nil { + return err + } + for i := 0; i < size; i++ { + err := Skip(self, keyType, maxDepth-1) + if err != nil { + return err + } + self.Skip(valueType) + } + return self.ReadMapEnd() + case SET: + elemType, size, err := self.ReadSetBegin() + if err != nil { + return err + } + for i := 0; i < size; i++ { + err := Skip(self, elemType, maxDepth-1) + if err != nil { + return err + } + } + return self.ReadSetEnd() + case LIST: + elemType, size, err := self.ReadListBegin() + if err != nil { + return err + } + for i := 0; i < size; i++ { + err := Skip(self, elemType, maxDepth-1) + if err != nil { + return err + } + } + return self.ReadListEnd() + } + return nil +} diff --git a/vendor/github.com/apache/thrift/lib/go/thrift/protocol_exception.go b/vendor/github.com/apache/thrift/lib/go/thrift/protocol_exception.go new file mode 100644 index 000000000..6e357ee89 --- /dev/null +++ b/vendor/github.com/apache/thrift/lib/go/thrift/protocol_exception.go @@ -0,0 +1,78 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package thrift + +import ( + "encoding/base64" +) + +// Thrift Protocol exception +type TProtocolException interface { + TException + TypeId() int +} + +const ( + UNKNOWN_PROTOCOL_EXCEPTION = 0 + INVALID_DATA = 1 + NEGATIVE_SIZE = 2 + SIZE_LIMIT = 3 + BAD_VERSION = 4 + NOT_IMPLEMENTED = 5 + DEPTH_LIMIT = 6 +) + +type tProtocolException struct { + typeId int + message string +} + +func (p *tProtocolException) TypeId() int { + return p.typeId +} + +func (p *tProtocolException) String() string { + return p.message +} + +func (p *tProtocolException) Error() string { + return p.message +} + +func NewTProtocolException(err error) TProtocolException { + if err == nil { + return nil + } + if e,ok := err.(TProtocolException); ok { + return e + } + if _, ok := err.(base64.CorruptInputError); ok { + return &tProtocolException{INVALID_DATA, err.Error()} + } + return &tProtocolException{UNKNOWN_PROTOCOL_EXCEPTION, err.Error()} +} + +func NewTProtocolExceptionWithType(errType int, err error) TProtocolException { + if err == nil { + return nil + } + return &tProtocolException{errType, err.Error()} +} + diff --git a/vendor/github.com/apache/thrift/lib/go/thrift/protocol_factory.go b/vendor/github.com/apache/thrift/lib/go/thrift/protocol_factory.go new file mode 100644 index 000000000..c40f796d8 --- /dev/null +++ b/vendor/github.com/apache/thrift/lib/go/thrift/protocol_factory.go @@ -0,0 +1,25 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package thrift + +// Factory interface for constructing protocol instances. +type TProtocolFactory interface { + GetProtocol(trans TTransport) TProtocol +} diff --git a/vendor/github.com/apache/thrift/lib/go/thrift/rich_transport.go b/vendor/github.com/apache/thrift/lib/go/thrift/rich_transport.go new file mode 100644 index 000000000..8e296a99b --- /dev/null +++ b/vendor/github.com/apache/thrift/lib/go/thrift/rich_transport.go @@ -0,0 +1,69 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package thrift + +import "io" + +type RichTransport struct { + TTransport +} + +// Wraps Transport to provide TRichTransport interface +func NewTRichTransport(trans TTransport) *RichTransport { + return &RichTransport{trans} +} + +func (r *RichTransport) ReadByte() (c byte, err error) { + return readByte(r.TTransport) +} + +func (r *RichTransport) WriteByte(c byte) error { + return writeByte(r.TTransport, c) +} + +func (r *RichTransport) WriteString(s string) (n int, err error) { + return r.Write([]byte(s)) +} + +func (r *RichTransport) RemainingBytes() (num_bytes uint64) { + return r.TTransport.RemainingBytes() +} + +func readByte(r io.Reader) (c byte, err error) { + v := [1]byte{0} + n, err := r.Read(v[0:1]) + if n > 0 && (err == nil || err == io.EOF) { + return v[0], nil + } + if n > 0 && err != nil { + return v[0], err + } + if err != nil { + return 0, err + } + return v[0], nil +} + +func writeByte(w io.Writer, c byte) error { + v := [1]byte{c} + _, err := w.Write(v[0:1]) + return err +} + diff --git a/vendor/github.com/apache/thrift/lib/go/thrift/serializer.go b/vendor/github.com/apache/thrift/lib/go/thrift/serializer.go new file mode 100644 index 000000000..771222999 --- /dev/null +++ b/vendor/github.com/apache/thrift/lib/go/thrift/serializer.go @@ -0,0 +1,75 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package thrift + +type TSerializer struct { + Transport *TMemoryBuffer + Protocol TProtocol +} + +type TStruct interface { + Write(p TProtocol) error + Read(p TProtocol) error +} + +func NewTSerializer() *TSerializer { + transport := NewTMemoryBufferLen(1024) + protocol := NewTBinaryProtocolFactoryDefault().GetProtocol(transport) + + return &TSerializer{ + transport, + protocol} +} + +func (t *TSerializer) WriteString(msg TStruct) (s string, err error) { + t.Transport.Reset() + + if err = msg.Write(t.Protocol); err != nil { + return + } + + if err = t.Protocol.Flush(); err != nil { + return + } + if err = t.Transport.Flush(); err != nil { + return + } + + return t.Transport.String(), nil +} + +func (t *TSerializer) Write(msg TStruct) (b []byte, err error) { + t.Transport.Reset() + + if err = msg.Write(t.Protocol); err != nil { + return + } + + if err = t.Protocol.Flush(); err != nil { + return + } + + if err = t.Transport.Flush(); err != nil { + return + } + + b = append(b, t.Transport.Bytes()...) + return +} diff --git a/vendor/github.com/apache/thrift/lib/go/thrift/server.go b/vendor/github.com/apache/thrift/lib/go/thrift/server.go new file mode 100644 index 000000000..f813fa353 --- /dev/null +++ b/vendor/github.com/apache/thrift/lib/go/thrift/server.go @@ -0,0 +1,35 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package thrift + +type TServer interface { + ProcessorFactory() TProcessorFactory + ServerTransport() TServerTransport + InputTransportFactory() TTransportFactory + OutputTransportFactory() TTransportFactory + InputProtocolFactory() TProtocolFactory + OutputProtocolFactory() TProtocolFactory + + // Starts the server + Serve() error + // Stops the server. This is optional on a per-implementation basis. Not + // all servers are required to be cleanly stoppable. + Stop() error +} diff --git a/vendor/github.com/apache/thrift/lib/go/thrift/server_socket.go b/vendor/github.com/apache/thrift/lib/go/thrift/server_socket.go new file mode 100644 index 000000000..d6e9495d2 --- /dev/null +++ b/vendor/github.com/apache/thrift/lib/go/thrift/server_socket.go @@ -0,0 +1,122 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package thrift + +import ( + "net" + "sync" + "time" +) + +type TServerSocket struct { + listener net.Listener + addr net.Addr + clientTimeout time.Duration + + // Protects the interrupted value to make it thread safe. + mu sync.RWMutex + interrupted bool +} + +func NewTServerSocket(listenAddr string) (*TServerSocket, error) { + return NewTServerSocketTimeout(listenAddr, 0) +} + +func NewTServerSocketTimeout(listenAddr string, clientTimeout time.Duration) (*TServerSocket, error) { + addr, err := net.ResolveTCPAddr("tcp", listenAddr) + if err != nil { + return nil, err + } + return &TServerSocket{addr: addr, clientTimeout: clientTimeout}, nil +} + +func (p *TServerSocket) Listen() error { + if p.IsListening() { + return nil + } + l, err := net.Listen(p.addr.Network(), p.addr.String()) + if err != nil { + return err + } + p.listener = l + return nil +} + +func (p *TServerSocket) Accept() (TTransport, error) { + p.mu.RLock() + interrupted := p.interrupted + p.mu.RUnlock() + + if interrupted { + return nil, errTransportInterrupted + } + if p.listener == nil { + return nil, NewTTransportException(NOT_OPEN, "No underlying server socket") + } + conn, err := p.listener.Accept() + if err != nil { + return nil, NewTTransportExceptionFromError(err) + } + return NewTSocketFromConnTimeout(conn, p.clientTimeout), nil +} + +// Checks whether the socket is listening. +func (p *TServerSocket) IsListening() bool { + return p.listener != nil +} + +// Connects the socket, creating a new socket object if necessary. +func (p *TServerSocket) Open() error { + if p.IsListening() { + return NewTTransportException(ALREADY_OPEN, "Server socket already open") + } + if l, err := net.Listen(p.addr.Network(), p.addr.String()); err != nil { + return err + } else { + p.listener = l + } + return nil +} + +func (p *TServerSocket) Addr() net.Addr { + if p.listener != nil { + return p.listener.Addr() + } + return p.addr +} + +func (p *TServerSocket) Close() error { + defer func() { + p.listener = nil + }() + if p.IsListening() { + return p.listener.Close() + } + return nil +} + +func (p *TServerSocket) Interrupt() error { + p.mu.Lock() + p.interrupted = true + p.Close() + p.mu.Unlock() + + return nil +} diff --git a/vendor/github.com/apache/thrift/lib/go/thrift/server_transport.go b/vendor/github.com/apache/thrift/lib/go/thrift/server_transport.go new file mode 100644 index 000000000..51c40b64a --- /dev/null +++ b/vendor/github.com/apache/thrift/lib/go/thrift/server_transport.go @@ -0,0 +1,34 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package thrift + +// Server transport. Object which provides client transports. +type TServerTransport interface { + Listen() error + Accept() (TTransport, error) + Close() error + + // Optional method implementation. This signals to the server transport + // that it should break out of any accept() or listen() that it is currently + // blocked on. This method, if implemented, MUST be thread safe, as it may + // be called from a different thread context than the other TServerTransport + // methods. + Interrupt() error +} diff --git a/vendor/github.com/apache/thrift/lib/go/thrift/simple_json_protocol.go b/vendor/github.com/apache/thrift/lib/go/thrift/simple_json_protocol.go new file mode 100644 index 000000000..735332231 --- /dev/null +++ b/vendor/github.com/apache/thrift/lib/go/thrift/simple_json_protocol.go @@ -0,0 +1,1337 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package thrift + +import ( + "bufio" + "bytes" + "encoding/base64" + "encoding/json" + "fmt" + "io" + "math" + "strconv" +) + +type _ParseContext int + +const ( + _CONTEXT_IN_TOPLEVEL _ParseContext = 1 + _CONTEXT_IN_LIST_FIRST _ParseContext = 2 + _CONTEXT_IN_LIST _ParseContext = 3 + _CONTEXT_IN_OBJECT_FIRST _ParseContext = 4 + _CONTEXT_IN_OBJECT_NEXT_KEY _ParseContext = 5 + _CONTEXT_IN_OBJECT_NEXT_VALUE _ParseContext = 6 +) + +func (p _ParseContext) String() string { + switch p { + case _CONTEXT_IN_TOPLEVEL: + return "TOPLEVEL" + case _CONTEXT_IN_LIST_FIRST: + return "LIST-FIRST" + case _CONTEXT_IN_LIST: + return "LIST" + case _CONTEXT_IN_OBJECT_FIRST: + return "OBJECT-FIRST" + case _CONTEXT_IN_OBJECT_NEXT_KEY: + return "OBJECT-NEXT-KEY" + case _CONTEXT_IN_OBJECT_NEXT_VALUE: + return "OBJECT-NEXT-VALUE" + } + return "UNKNOWN-PARSE-CONTEXT" +} + +// JSON protocol implementation for thrift. +// +// This protocol produces/consumes a simple output format +// suitable for parsing by scripting languages. It should not be +// confused with the full-featured TJSONProtocol. +// +type TSimpleJSONProtocol struct { + trans TTransport + + parseContextStack []int + dumpContext []int + + writer *bufio.Writer + reader *bufio.Reader +} + +// Constructor +func NewTSimpleJSONProtocol(t TTransport) *TSimpleJSONProtocol { + v := &TSimpleJSONProtocol{trans: t, + writer: bufio.NewWriter(t), + reader: bufio.NewReader(t), + } + v.parseContextStack = append(v.parseContextStack, int(_CONTEXT_IN_TOPLEVEL)) + v.dumpContext = append(v.dumpContext, int(_CONTEXT_IN_TOPLEVEL)) + return v +} + +// Factory +type TSimpleJSONProtocolFactory struct{} + +func (p *TSimpleJSONProtocolFactory) GetProtocol(trans TTransport) TProtocol { + return NewTSimpleJSONProtocol(trans) +} + +func NewTSimpleJSONProtocolFactory() *TSimpleJSONProtocolFactory { + return &TSimpleJSONProtocolFactory{} +} + +var ( + JSON_COMMA []byte + JSON_COLON []byte + JSON_LBRACE []byte + JSON_RBRACE []byte + JSON_LBRACKET []byte + JSON_RBRACKET []byte + JSON_QUOTE byte + JSON_QUOTE_BYTES []byte + JSON_NULL []byte + JSON_TRUE []byte + JSON_FALSE []byte + JSON_INFINITY string + JSON_NEGATIVE_INFINITY string + JSON_NAN string + JSON_INFINITY_BYTES []byte + JSON_NEGATIVE_INFINITY_BYTES []byte + JSON_NAN_BYTES []byte + json_nonbase_map_elem_bytes []byte +) + +func init() { + JSON_COMMA = []byte{','} + JSON_COLON = []byte{':'} + JSON_LBRACE = []byte{'{'} + JSON_RBRACE = []byte{'}'} + JSON_LBRACKET = []byte{'['} + JSON_RBRACKET = []byte{']'} + JSON_QUOTE = '"' + JSON_QUOTE_BYTES = []byte{'"'} + JSON_NULL = []byte{'n', 'u', 'l', 'l'} + JSON_TRUE = []byte{'t', 'r', 'u', 'e'} + JSON_FALSE = []byte{'f', 'a', 'l', 's', 'e'} + JSON_INFINITY = "Infinity" + JSON_NEGATIVE_INFINITY = "-Infinity" + JSON_NAN = "NaN" + JSON_INFINITY_BYTES = []byte{'I', 'n', 'f', 'i', 'n', 'i', 't', 'y'} + JSON_NEGATIVE_INFINITY_BYTES = []byte{'-', 'I', 'n', 'f', 'i', 'n', 'i', 't', 'y'} + JSON_NAN_BYTES = []byte{'N', 'a', 'N'} + json_nonbase_map_elem_bytes = []byte{']', ',', '['} +} + +func jsonQuote(s string) string { + b, _ := json.Marshal(s) + s1 := string(b) + return s1 +} + +func jsonUnquote(s string) (string, bool) { + s1 := new(string) + err := json.Unmarshal([]byte(s), s1) + return *s1, err == nil +} + +func mismatch(expected, actual string) error { + return fmt.Errorf("Expected '%s' but found '%s' while parsing JSON.", expected, actual) +} + +func (p *TSimpleJSONProtocol) WriteMessageBegin(name string, typeId TMessageType, seqId int32) error { + p.resetContextStack() // THRIFT-3735 + if e := p.OutputListBegin(); e != nil { + return e + } + if e := p.WriteString(name); e != nil { + return e + } + if e := p.WriteByte(int8(typeId)); e != nil { + return e + } + if e := p.WriteI32(seqId); e != nil { + return e + } + return nil +} + +func (p *TSimpleJSONProtocol) WriteMessageEnd() error { + return p.OutputListEnd() +} + +func (p *TSimpleJSONProtocol) WriteStructBegin(name string) error { + if e := p.OutputObjectBegin(); e != nil { + return e + } + return nil +} + +func (p *TSimpleJSONProtocol) WriteStructEnd() error { + return p.OutputObjectEnd() +} + +func (p *TSimpleJSONProtocol) WriteFieldBegin(name string, typeId TType, id int16) error { + if e := p.WriteString(name); e != nil { + return e + } + return nil +} + +func (p *TSimpleJSONProtocol) WriteFieldEnd() error { + //return p.OutputListEnd() + return nil +} + +func (p *TSimpleJSONProtocol) WriteFieldStop() error { return nil } + +func (p *TSimpleJSONProtocol) WriteMapBegin(keyType TType, valueType TType, size int) error { + if e := p.OutputListBegin(); e != nil { + return e + } + if e := p.WriteByte(int8(keyType)); e != nil { + return e + } + if e := p.WriteByte(int8(valueType)); e != nil { + return e + } + return p.WriteI32(int32(size)) +} + +func (p *TSimpleJSONProtocol) WriteMapEnd() error { + return p.OutputListEnd() +} + +func (p *TSimpleJSONProtocol) WriteListBegin(elemType TType, size int) error { + return p.OutputElemListBegin(elemType, size) +} + +func (p *TSimpleJSONProtocol) WriteListEnd() error { + return p.OutputListEnd() +} + +func (p *TSimpleJSONProtocol) WriteSetBegin(elemType TType, size int) error { + return p.OutputElemListBegin(elemType, size) +} + +func (p *TSimpleJSONProtocol) WriteSetEnd() error { + return p.OutputListEnd() +} + +func (p *TSimpleJSONProtocol) WriteBool(b bool) error { + return p.OutputBool(b) +} + +func (p *TSimpleJSONProtocol) WriteByte(b int8) error { + return p.WriteI32(int32(b)) +} + +func (p *TSimpleJSONProtocol) WriteI16(v int16) error { + return p.WriteI32(int32(v)) +} + +func (p *TSimpleJSONProtocol) WriteI32(v int32) error { + return p.OutputI64(int64(v)) +} + +func (p *TSimpleJSONProtocol) WriteI64(v int64) error { + return p.OutputI64(int64(v)) +} + +func (p *TSimpleJSONProtocol) WriteDouble(v float64) error { + return p.OutputF64(v) +} + +func (p *TSimpleJSONProtocol) WriteString(v string) error { + return p.OutputString(v) +} + +func (p *TSimpleJSONProtocol) WriteBinary(v []byte) error { + // JSON library only takes in a string, + // not an arbitrary byte array, to ensure bytes are transmitted + // efficiently we must convert this into a valid JSON string + // therefore we use base64 encoding to avoid excessive escaping/quoting + if e := p.OutputPreValue(); e != nil { + return e + } + if _, e := p.write(JSON_QUOTE_BYTES); e != nil { + return NewTProtocolException(e) + } + writer := base64.NewEncoder(base64.StdEncoding, p.writer) + if _, e := writer.Write(v); e != nil { + p.writer.Reset(p.trans) // THRIFT-3735 + return NewTProtocolException(e) + } + if e := writer.Close(); e != nil { + return NewTProtocolException(e) + } + if _, e := p.write(JSON_QUOTE_BYTES); e != nil { + return NewTProtocolException(e) + } + return p.OutputPostValue() +} + +// Reading methods. +func (p *TSimpleJSONProtocol) ReadMessageBegin() (name string, typeId TMessageType, seqId int32, err error) { + p.resetContextStack() // THRIFT-3735 + if isNull, err := p.ParseListBegin(); isNull || err != nil { + return name, typeId, seqId, err + } + if name, err = p.ReadString(); err != nil { + return name, typeId, seqId, err + } + bTypeId, err := p.ReadByte() + typeId = TMessageType(bTypeId) + if err != nil { + return name, typeId, seqId, err + } + if seqId, err = p.ReadI32(); err != nil { + return name, typeId, seqId, err + } + return name, typeId, seqId, nil +} + +func (p *TSimpleJSONProtocol) ReadMessageEnd() error { + return p.ParseListEnd() +} + +func (p *TSimpleJSONProtocol) ReadStructBegin() (name string, err error) { + _, err = p.ParseObjectStart() + return "", err +} + +func (p *TSimpleJSONProtocol) ReadStructEnd() error { + return p.ParseObjectEnd() +} + +func (p *TSimpleJSONProtocol) ReadFieldBegin() (string, TType, int16, error) { + if err := p.ParsePreValue(); err != nil { + return "", STOP, 0, err + } + b, _ := p.reader.Peek(1) + if len(b) > 0 { + switch b[0] { + case JSON_RBRACE[0]: + return "", STOP, 0, nil + case JSON_QUOTE: + p.reader.ReadByte() + name, err := p.ParseStringBody() + // simplejson is not meant to be read back into thrift + // - see http://wiki.apache.org/thrift/ThriftUsageJava + // - use JSON instead + if err != nil { + return name, STOP, 0, err + } + return name, STOP, -1, p.ParsePostValue() + /* + if err = p.ParsePostValue(); err != nil { + return name, STOP, 0, err + } + if isNull, err := p.ParseListBegin(); isNull || err != nil { + return name, STOP, 0, err + } + bType, err := p.ReadByte() + thetype := TType(bType) + if err != nil { + return name, thetype, 0, err + } + id, err := p.ReadI16() + return name, thetype, id, err + */ + } + e := fmt.Errorf("Expected \"}\" or '\"', but found: '%s'", string(b)) + return "", STOP, 0, NewTProtocolExceptionWithType(INVALID_DATA, e) + } + return "", STOP, 0, NewTProtocolException(io.EOF) +} + +func (p *TSimpleJSONProtocol) ReadFieldEnd() error { + return nil + //return p.ParseListEnd() +} + +func (p *TSimpleJSONProtocol) ReadMapBegin() (keyType TType, valueType TType, size int, e error) { + if isNull, e := p.ParseListBegin(); isNull || e != nil { + return VOID, VOID, 0, e + } + + // read keyType + bKeyType, e := p.ReadByte() + keyType = TType(bKeyType) + if e != nil { + return keyType, valueType, size, e + } + + // read valueType + bValueType, e := p.ReadByte() + valueType = TType(bValueType) + if e != nil { + return keyType, valueType, size, e + } + + // read size + iSize, err := p.ReadI64() + size = int(iSize) + return keyType, valueType, size, err +} + +func (p *TSimpleJSONProtocol) ReadMapEnd() error { + return p.ParseListEnd() +} + +func (p *TSimpleJSONProtocol) ReadListBegin() (elemType TType, size int, e error) { + return p.ParseElemListBegin() +} + +func (p *TSimpleJSONProtocol) ReadListEnd() error { + return p.ParseListEnd() +} + +func (p *TSimpleJSONProtocol) ReadSetBegin() (elemType TType, size int, e error) { + return p.ParseElemListBegin() +} + +func (p *TSimpleJSONProtocol) ReadSetEnd() error { + return p.ParseListEnd() +} + +func (p *TSimpleJSONProtocol) ReadBool() (bool, error) { + var value bool + + if err := p.ParsePreValue(); err != nil { + return value, err + } + f, _ := p.reader.Peek(1) + if len(f) > 0 { + switch f[0] { + case JSON_TRUE[0]: + b := make([]byte, len(JSON_TRUE)) + _, err := p.reader.Read(b) + if err != nil { + return false, NewTProtocolException(err) + } + if string(b) == string(JSON_TRUE) { + value = true + } else { + e := fmt.Errorf("Expected \"true\" but found: %s", string(b)) + return value, NewTProtocolExceptionWithType(INVALID_DATA, e) + } + break + case JSON_FALSE[0]: + b := make([]byte, len(JSON_FALSE)) + _, err := p.reader.Read(b) + if err != nil { + return false, NewTProtocolException(err) + } + if string(b) == string(JSON_FALSE) { + value = false + } else { + e := fmt.Errorf("Expected \"false\" but found: %s", string(b)) + return value, NewTProtocolExceptionWithType(INVALID_DATA, e) + } + break + case JSON_NULL[0]: + b := make([]byte, len(JSON_NULL)) + _, err := p.reader.Read(b) + if err != nil { + return false, NewTProtocolException(err) + } + if string(b) == string(JSON_NULL) { + value = false + } else { + e := fmt.Errorf("Expected \"null\" but found: %s", string(b)) + return value, NewTProtocolExceptionWithType(INVALID_DATA, e) + } + default: + e := fmt.Errorf("Expected \"true\", \"false\", or \"null\" but found: %s", string(f)) + return value, NewTProtocolExceptionWithType(INVALID_DATA, e) + } + } + return value, p.ParsePostValue() +} + +func (p *TSimpleJSONProtocol) ReadByte() (int8, error) { + v, err := p.ReadI64() + return int8(v), err +} + +func (p *TSimpleJSONProtocol) ReadI16() (int16, error) { + v, err := p.ReadI64() + return int16(v), err +} + +func (p *TSimpleJSONProtocol) ReadI32() (int32, error) { + v, err := p.ReadI64() + return int32(v), err +} + +func (p *TSimpleJSONProtocol) ReadI64() (int64, error) { + v, _, err := p.ParseI64() + return v, err +} + +func (p *TSimpleJSONProtocol) ReadDouble() (float64, error) { + v, _, err := p.ParseF64() + return v, err +} + +func (p *TSimpleJSONProtocol) ReadString() (string, error) { + var v string + if err := p.ParsePreValue(); err != nil { + return v, err + } + f, _ := p.reader.Peek(1) + if len(f) > 0 && f[0] == JSON_QUOTE { + p.reader.ReadByte() + value, err := p.ParseStringBody() + v = value + if err != nil { + return v, err + } + } else if len(f) > 0 && f[0] == JSON_NULL[0] { + b := make([]byte, len(JSON_NULL)) + _, err := p.reader.Read(b) + if err != nil { + return v, NewTProtocolException(err) + } + if string(b) != string(JSON_NULL) { + e := fmt.Errorf("Expected a JSON string, found unquoted data started with %s", string(b)) + return v, NewTProtocolExceptionWithType(INVALID_DATA, e) + } + } else { + e := fmt.Errorf("Expected a JSON string, found unquoted data started with %s", string(f)) + return v, NewTProtocolExceptionWithType(INVALID_DATA, e) + } + return v, p.ParsePostValue() +} + +func (p *TSimpleJSONProtocol) ReadBinary() ([]byte, error) { + var v []byte + if err := p.ParsePreValue(); err != nil { + return nil, err + } + f, _ := p.reader.Peek(1) + if len(f) > 0 && f[0] == JSON_QUOTE { + p.reader.ReadByte() + value, err := p.ParseBase64EncodedBody() + v = value + if err != nil { + return v, err + } + } else if len(f) > 0 && f[0] == JSON_NULL[0] { + b := make([]byte, len(JSON_NULL)) + _, err := p.reader.Read(b) + if err != nil { + return v, NewTProtocolException(err) + } + if string(b) != string(JSON_NULL) { + e := fmt.Errorf("Expected a JSON string, found unquoted data started with %s", string(b)) + return v, NewTProtocolExceptionWithType(INVALID_DATA, e) + } + } else { + e := fmt.Errorf("Expected a JSON string, found unquoted data started with %s", string(f)) + return v, NewTProtocolExceptionWithType(INVALID_DATA, e) + } + + return v, p.ParsePostValue() +} + +func (p *TSimpleJSONProtocol) Flush() (err error) { + return NewTProtocolException(p.writer.Flush()) +} + +func (p *TSimpleJSONProtocol) Skip(fieldType TType) (err error) { + return SkipDefaultDepth(p, fieldType) +} + +func (p *TSimpleJSONProtocol) Transport() TTransport { + return p.trans +} + +func (p *TSimpleJSONProtocol) OutputPreValue() error { + cxt := _ParseContext(p.dumpContext[len(p.dumpContext)-1]) + switch cxt { + case _CONTEXT_IN_LIST, _CONTEXT_IN_OBJECT_NEXT_KEY: + if _, e := p.write(JSON_COMMA); e != nil { + return NewTProtocolException(e) + } + break + case _CONTEXT_IN_OBJECT_NEXT_VALUE: + if _, e := p.write(JSON_COLON); e != nil { + return NewTProtocolException(e) + } + break + } + return nil +} + +func (p *TSimpleJSONProtocol) OutputPostValue() error { + cxt := _ParseContext(p.dumpContext[len(p.dumpContext)-1]) + switch cxt { + case _CONTEXT_IN_LIST_FIRST: + p.dumpContext = p.dumpContext[:len(p.dumpContext)-1] + p.dumpContext = append(p.dumpContext, int(_CONTEXT_IN_LIST)) + break + case _CONTEXT_IN_OBJECT_FIRST: + p.dumpContext = p.dumpContext[:len(p.dumpContext)-1] + p.dumpContext = append(p.dumpContext, int(_CONTEXT_IN_OBJECT_NEXT_VALUE)) + break + case _CONTEXT_IN_OBJECT_NEXT_KEY: + p.dumpContext = p.dumpContext[:len(p.dumpContext)-1] + p.dumpContext = append(p.dumpContext, int(_CONTEXT_IN_OBJECT_NEXT_VALUE)) + break + case _CONTEXT_IN_OBJECT_NEXT_VALUE: + p.dumpContext = p.dumpContext[:len(p.dumpContext)-1] + p.dumpContext = append(p.dumpContext, int(_CONTEXT_IN_OBJECT_NEXT_KEY)) + break + } + return nil +} + +func (p *TSimpleJSONProtocol) OutputBool(value bool) error { + if e := p.OutputPreValue(); e != nil { + return e + } + var v string + if value { + v = string(JSON_TRUE) + } else { + v = string(JSON_FALSE) + } + switch _ParseContext(p.dumpContext[len(p.dumpContext)-1]) { + case _CONTEXT_IN_OBJECT_FIRST, _CONTEXT_IN_OBJECT_NEXT_KEY: + v = jsonQuote(v) + default: + } + if e := p.OutputStringData(v); e != nil { + return e + } + return p.OutputPostValue() +} + +func (p *TSimpleJSONProtocol) OutputNull() error { + if e := p.OutputPreValue(); e != nil { + return e + } + if _, e := p.write(JSON_NULL); e != nil { + return NewTProtocolException(e) + } + return p.OutputPostValue() +} + +func (p *TSimpleJSONProtocol) OutputF64(value float64) error { + if e := p.OutputPreValue(); e != nil { + return e + } + var v string + if math.IsNaN(value) { + v = string(JSON_QUOTE) + JSON_NAN + string(JSON_QUOTE) + } else if math.IsInf(value, 1) { + v = string(JSON_QUOTE) + JSON_INFINITY + string(JSON_QUOTE) + } else if math.IsInf(value, -1) { + v = string(JSON_QUOTE) + JSON_NEGATIVE_INFINITY + string(JSON_QUOTE) + } else { + v = strconv.FormatFloat(value, 'g', -1, 64) + switch _ParseContext(p.dumpContext[len(p.dumpContext)-1]) { + case _CONTEXT_IN_OBJECT_FIRST, _CONTEXT_IN_OBJECT_NEXT_KEY: + v = string(JSON_QUOTE) + v + string(JSON_QUOTE) + default: + } + } + if e := p.OutputStringData(v); e != nil { + return e + } + return p.OutputPostValue() +} + +func (p *TSimpleJSONProtocol) OutputI64(value int64) error { + if e := p.OutputPreValue(); e != nil { + return e + } + v := strconv.FormatInt(value, 10) + switch _ParseContext(p.dumpContext[len(p.dumpContext)-1]) { + case _CONTEXT_IN_OBJECT_FIRST, _CONTEXT_IN_OBJECT_NEXT_KEY: + v = jsonQuote(v) + default: + } + if e := p.OutputStringData(v); e != nil { + return e + } + return p.OutputPostValue() +} + +func (p *TSimpleJSONProtocol) OutputString(s string) error { + if e := p.OutputPreValue(); e != nil { + return e + } + if e := p.OutputStringData(jsonQuote(s)); e != nil { + return e + } + return p.OutputPostValue() +} + +func (p *TSimpleJSONProtocol) OutputStringData(s string) error { + _, e := p.write([]byte(s)) + return NewTProtocolException(e) +} + +func (p *TSimpleJSONProtocol) OutputObjectBegin() error { + if e := p.OutputPreValue(); e != nil { + return e + } + if _, e := p.write(JSON_LBRACE); e != nil { + return NewTProtocolException(e) + } + p.dumpContext = append(p.dumpContext, int(_CONTEXT_IN_OBJECT_FIRST)) + return nil +} + +func (p *TSimpleJSONProtocol) OutputObjectEnd() error { + if _, e := p.write(JSON_RBRACE); e != nil { + return NewTProtocolException(e) + } + p.dumpContext = p.dumpContext[:len(p.dumpContext)-1] + if e := p.OutputPostValue(); e != nil { + return e + } + return nil +} + +func (p *TSimpleJSONProtocol) OutputListBegin() error { + if e := p.OutputPreValue(); e != nil { + return e + } + if _, e := p.write(JSON_LBRACKET); e != nil { + return NewTProtocolException(e) + } + p.dumpContext = append(p.dumpContext, int(_CONTEXT_IN_LIST_FIRST)) + return nil +} + +func (p *TSimpleJSONProtocol) OutputListEnd() error { + if _, e := p.write(JSON_RBRACKET); e != nil { + return NewTProtocolException(e) + } + p.dumpContext = p.dumpContext[:len(p.dumpContext)-1] + if e := p.OutputPostValue(); e != nil { + return e + } + return nil +} + +func (p *TSimpleJSONProtocol) OutputElemListBegin(elemType TType, size int) error { + if e := p.OutputListBegin(); e != nil { + return e + } + if e := p.WriteByte(int8(elemType)); e != nil { + return e + } + if e := p.WriteI64(int64(size)); e != nil { + return e + } + return nil +} + +func (p *TSimpleJSONProtocol) ParsePreValue() error { + if e := p.readNonSignificantWhitespace(); e != nil { + return NewTProtocolException(e) + } + cxt := _ParseContext(p.parseContextStack[len(p.parseContextStack)-1]) + b, _ := p.reader.Peek(1) + switch cxt { + case _CONTEXT_IN_LIST: + if len(b) > 0 { + switch b[0] { + case JSON_RBRACKET[0]: + return nil + case JSON_COMMA[0]: + p.reader.ReadByte() + if e := p.readNonSignificantWhitespace(); e != nil { + return NewTProtocolException(e) + } + return nil + default: + e := fmt.Errorf("Expected \"]\" or \",\" in list context, but found \"%s\"", string(b)) + return NewTProtocolExceptionWithType(INVALID_DATA, e) + } + } + break + case _CONTEXT_IN_OBJECT_NEXT_KEY: + if len(b) > 0 { + switch b[0] { + case JSON_RBRACE[0]: + return nil + case JSON_COMMA[0]: + p.reader.ReadByte() + if e := p.readNonSignificantWhitespace(); e != nil { + return NewTProtocolException(e) + } + return nil + default: + e := fmt.Errorf("Expected \"}\" or \",\" in object context, but found \"%s\"", string(b)) + return NewTProtocolExceptionWithType(INVALID_DATA, e) + } + } + break + case _CONTEXT_IN_OBJECT_NEXT_VALUE: + if len(b) > 0 { + switch b[0] { + case JSON_COLON[0]: + p.reader.ReadByte() + if e := p.readNonSignificantWhitespace(); e != nil { + return NewTProtocolException(e) + } + return nil + default: + e := fmt.Errorf("Expected \":\" in object context, but found \"%s\"", string(b)) + return NewTProtocolExceptionWithType(INVALID_DATA, e) + } + } + break + } + return nil +} + +func (p *TSimpleJSONProtocol) ParsePostValue() error { + if e := p.readNonSignificantWhitespace(); e != nil { + return NewTProtocolException(e) + } + cxt := _ParseContext(p.parseContextStack[len(p.parseContextStack)-1]) + switch cxt { + case _CONTEXT_IN_LIST_FIRST: + p.parseContextStack = p.parseContextStack[:len(p.parseContextStack)-1] + p.parseContextStack = append(p.parseContextStack, int(_CONTEXT_IN_LIST)) + break + case _CONTEXT_IN_OBJECT_FIRST, _CONTEXT_IN_OBJECT_NEXT_KEY: + p.parseContextStack = p.parseContextStack[:len(p.parseContextStack)-1] + p.parseContextStack = append(p.parseContextStack, int(_CONTEXT_IN_OBJECT_NEXT_VALUE)) + break + case _CONTEXT_IN_OBJECT_NEXT_VALUE: + p.parseContextStack = p.parseContextStack[:len(p.parseContextStack)-1] + p.parseContextStack = append(p.parseContextStack, int(_CONTEXT_IN_OBJECT_NEXT_KEY)) + break + } + return nil +} + +func (p *TSimpleJSONProtocol) readNonSignificantWhitespace() error { + for { + b, _ := p.reader.Peek(1) + if len(b) < 1 { + return nil + } + switch b[0] { + case ' ', '\r', '\n', '\t': + p.reader.ReadByte() + continue + default: + break + } + break + } + return nil +} + +func (p *TSimpleJSONProtocol) ParseStringBody() (string, error) { + line, err := p.reader.ReadString(JSON_QUOTE) + if err != nil { + return "", NewTProtocolException(err) + } + l := len(line) + // count number of escapes to see if we need to keep going + i := 1 + for ; i < l; i++ { + if line[l-i-1] != '\\' { + break + } + } + if i&0x01 == 1 { + v, ok := jsonUnquote(string(JSON_QUOTE) + line) + if !ok { + return "", NewTProtocolException(err) + } + return v, nil + } + s, err := p.ParseQuotedStringBody() + if err != nil { + return "", NewTProtocolException(err) + } + str := string(JSON_QUOTE) + line + s + v, ok := jsonUnquote(str) + if !ok { + e := fmt.Errorf("Unable to parse as JSON string %s", str) + return "", NewTProtocolExceptionWithType(INVALID_DATA, e) + } + return v, nil +} + +func (p *TSimpleJSONProtocol) ParseQuotedStringBody() (string, error) { + line, err := p.reader.ReadString(JSON_QUOTE) + if err != nil { + return "", NewTProtocolException(err) + } + l := len(line) + // count number of escapes to see if we need to keep going + i := 1 + for ; i < l; i++ { + if line[l-i-1] != '\\' { + break + } + } + if i&0x01 == 1 { + return line, nil + } + s, err := p.ParseQuotedStringBody() + if err != nil { + return "", NewTProtocolException(err) + } + v := line + s + return v, nil +} + +func (p *TSimpleJSONProtocol) ParseBase64EncodedBody() ([]byte, error) { + line, err := p.reader.ReadBytes(JSON_QUOTE) + if err != nil { + return line, NewTProtocolException(err) + } + line2 := line[0 : len(line)-1] + l := len(line2) + if (l % 4) != 0 { + pad := 4 - (l % 4) + fill := [...]byte{'=', '=', '='} + line2 = append(line2, fill[:pad]...) + l = len(line2) + } + output := make([]byte, base64.StdEncoding.DecodedLen(l)) + n, err := base64.StdEncoding.Decode(output, line2) + return output[0:n], NewTProtocolException(err) +} + +func (p *TSimpleJSONProtocol) ParseI64() (int64, bool, error) { + if err := p.ParsePreValue(); err != nil { + return 0, false, err + } + var value int64 + var isnull bool + if p.safePeekContains(JSON_NULL) { + p.reader.Read(make([]byte, len(JSON_NULL))) + isnull = true + } else { + num, err := p.readNumeric() + isnull = (num == nil) + if !isnull { + value = num.Int64() + } + if err != nil { + return value, isnull, err + } + } + return value, isnull, p.ParsePostValue() +} + +func (p *TSimpleJSONProtocol) ParseF64() (float64, bool, error) { + if err := p.ParsePreValue(); err != nil { + return 0, false, err + } + var value float64 + var isnull bool + if p.safePeekContains(JSON_NULL) { + p.reader.Read(make([]byte, len(JSON_NULL))) + isnull = true + } else { + num, err := p.readNumeric() + isnull = (num == nil) + if !isnull { + value = num.Float64() + } + if err != nil { + return value, isnull, err + } + } + return value, isnull, p.ParsePostValue() +} + +func (p *TSimpleJSONProtocol) ParseObjectStart() (bool, error) { + if err := p.ParsePreValue(); err != nil { + return false, err + } + var b []byte + b, err := p.reader.Peek(1) + if err != nil { + return false, err + } + if len(b) > 0 && b[0] == JSON_LBRACE[0] { + p.reader.ReadByte() + p.parseContextStack = append(p.parseContextStack, int(_CONTEXT_IN_OBJECT_FIRST)) + return false, nil + } else if p.safePeekContains(JSON_NULL) { + return true, nil + } + e := fmt.Errorf("Expected '{' or null, but found '%s'", string(b)) + return false, NewTProtocolExceptionWithType(INVALID_DATA, e) +} + +func (p *TSimpleJSONProtocol) ParseObjectEnd() error { + if isNull, err := p.readIfNull(); isNull || err != nil { + return err + } + cxt := _ParseContext(p.parseContextStack[len(p.parseContextStack)-1]) + if (cxt != _CONTEXT_IN_OBJECT_FIRST) && (cxt != _CONTEXT_IN_OBJECT_NEXT_KEY) { + e := fmt.Errorf("Expected to be in the Object Context, but not in Object Context (%d)", cxt) + return NewTProtocolExceptionWithType(INVALID_DATA, e) + } + line, err := p.reader.ReadString(JSON_RBRACE[0]) + if err != nil { + return NewTProtocolException(err) + } + for _, char := range line { + switch char { + default: + e := fmt.Errorf("Expecting end of object \"}\", but found: \"%s\"", line) + return NewTProtocolExceptionWithType(INVALID_DATA, e) + case ' ', '\n', '\r', '\t', '}': + break + } + } + p.parseContextStack = p.parseContextStack[:len(p.parseContextStack)-1] + return p.ParsePostValue() +} + +func (p *TSimpleJSONProtocol) ParseListBegin() (isNull bool, err error) { + if e := p.ParsePreValue(); e != nil { + return false, e + } + var b []byte + b, err = p.reader.Peek(1) + if err != nil { + return false, err + } + if len(b) >= 1 && b[0] == JSON_LBRACKET[0] { + p.parseContextStack = append(p.parseContextStack, int(_CONTEXT_IN_LIST_FIRST)) + p.reader.ReadByte() + isNull = false + } else if p.safePeekContains(JSON_NULL) { + isNull = true + } else { + err = fmt.Errorf("Expected \"null\" or \"[\", received %q", b) + } + return isNull, NewTProtocolExceptionWithType(INVALID_DATA, err) +} + +func (p *TSimpleJSONProtocol) ParseElemListBegin() (elemType TType, size int, e error) { + if isNull, e := p.ParseListBegin(); isNull || e != nil { + return VOID, 0, e + } + bElemType, err := p.ReadByte() + elemType = TType(bElemType) + if err != nil { + return elemType, size, err + } + nSize, err2 := p.ReadI64() + size = int(nSize) + return elemType, size, err2 +} + +func (p *TSimpleJSONProtocol) ParseListEnd() error { + if isNull, err := p.readIfNull(); isNull || err != nil { + return err + } + cxt := _ParseContext(p.parseContextStack[len(p.parseContextStack)-1]) + if cxt != _CONTEXT_IN_LIST { + e := fmt.Errorf("Expected to be in the List Context, but not in List Context (%d)", cxt) + return NewTProtocolExceptionWithType(INVALID_DATA, e) + } + line, err := p.reader.ReadString(JSON_RBRACKET[0]) + if err != nil { + return NewTProtocolException(err) + } + for _, char := range line { + switch char { + default: + e := fmt.Errorf("Expecting end of list \"]\", but found: \"", line, "\"") + return NewTProtocolExceptionWithType(INVALID_DATA, e) + case ' ', '\n', '\r', '\t', rune(JSON_RBRACKET[0]): + break + } + } + p.parseContextStack = p.parseContextStack[:len(p.parseContextStack)-1] + if _ParseContext(p.parseContextStack[len(p.parseContextStack)-1]) == _CONTEXT_IN_TOPLEVEL { + return nil + } + return p.ParsePostValue() +} + +func (p *TSimpleJSONProtocol) readSingleValue() (interface{}, TType, error) { + e := p.readNonSignificantWhitespace() + if e != nil { + return nil, VOID, NewTProtocolException(e) + } + b, e := p.reader.Peek(1) + if len(b) > 0 { + c := b[0] + switch c { + case JSON_NULL[0]: + buf := make([]byte, len(JSON_NULL)) + _, e := p.reader.Read(buf) + if e != nil { + return nil, VOID, NewTProtocolException(e) + } + if string(JSON_NULL) != string(buf) { + e = mismatch(string(JSON_NULL), string(buf)) + return nil, VOID, NewTProtocolExceptionWithType(INVALID_DATA, e) + } + return nil, VOID, nil + case JSON_QUOTE: + p.reader.ReadByte() + v, e := p.ParseStringBody() + if e != nil { + return v, UTF8, NewTProtocolException(e) + } + if v == JSON_INFINITY { + return INFINITY, DOUBLE, nil + } else if v == JSON_NEGATIVE_INFINITY { + return NEGATIVE_INFINITY, DOUBLE, nil + } else if v == JSON_NAN { + return NAN, DOUBLE, nil + } + return v, UTF8, nil + case JSON_TRUE[0]: + buf := make([]byte, len(JSON_TRUE)) + _, e := p.reader.Read(buf) + if e != nil { + return true, BOOL, NewTProtocolException(e) + } + if string(JSON_TRUE) != string(buf) { + e := mismatch(string(JSON_TRUE), string(buf)) + return true, BOOL, NewTProtocolExceptionWithType(INVALID_DATA, e) + } + return true, BOOL, nil + case JSON_FALSE[0]: + buf := make([]byte, len(JSON_FALSE)) + _, e := p.reader.Read(buf) + if e != nil { + return false, BOOL, NewTProtocolException(e) + } + if string(JSON_FALSE) != string(buf) { + e := mismatch(string(JSON_FALSE), string(buf)) + return false, BOOL, NewTProtocolExceptionWithType(INVALID_DATA, e) + } + return false, BOOL, nil + case JSON_LBRACKET[0]: + _, e := p.reader.ReadByte() + return make([]interface{}, 0), LIST, NewTProtocolException(e) + case JSON_LBRACE[0]: + _, e := p.reader.ReadByte() + return make(map[string]interface{}), STRUCT, NewTProtocolException(e) + case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'e', 'E', '.', '+', '-', JSON_INFINITY[0], JSON_NAN[0]: + // assume numeric + v, e := p.readNumeric() + return v, DOUBLE, e + default: + e := fmt.Errorf("Expected element in list but found '%s' while parsing JSON.", string(c)) + return nil, VOID, NewTProtocolExceptionWithType(INVALID_DATA, e) + } + } + e = fmt.Errorf("Cannot read a single element while parsing JSON.") + return nil, VOID, NewTProtocolExceptionWithType(INVALID_DATA, e) + +} + +func (p *TSimpleJSONProtocol) readIfNull() (bool, error) { + cont := true + for cont { + b, _ := p.reader.Peek(1) + if len(b) < 1 { + return false, nil + } + switch b[0] { + default: + return false, nil + case JSON_NULL[0]: + cont = false + break + case ' ', '\n', '\r', '\t': + p.reader.ReadByte() + break + } + } + if p.safePeekContains(JSON_NULL) { + p.reader.Read(make([]byte, len(JSON_NULL))) + return true, nil + } + return false, nil +} + +func (p *TSimpleJSONProtocol) readQuoteIfNext() { + b, _ := p.reader.Peek(1) + if len(b) > 0 && b[0] == JSON_QUOTE { + p.reader.ReadByte() + } +} + +func (p *TSimpleJSONProtocol) readNumeric() (Numeric, error) { + isNull, err := p.readIfNull() + if isNull || err != nil { + return NUMERIC_NULL, err + } + hasDecimalPoint := false + nextCanBeSign := true + hasE := false + MAX_LEN := 40 + buf := bytes.NewBuffer(make([]byte, 0, MAX_LEN)) + continueFor := true + inQuotes := false + for continueFor { + c, err := p.reader.ReadByte() + if err != nil { + if err == io.EOF { + break + } + return NUMERIC_NULL, NewTProtocolException(err) + } + switch c { + case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9': + buf.WriteByte(c) + nextCanBeSign = false + case '.': + if hasDecimalPoint { + e := fmt.Errorf("Unable to parse number with multiple decimal points '%s.'", buf.String()) + return NUMERIC_NULL, NewTProtocolExceptionWithType(INVALID_DATA, e) + } + if hasE { + e := fmt.Errorf("Unable to parse number with decimal points in the exponent '%s.'", buf.String()) + return NUMERIC_NULL, NewTProtocolExceptionWithType(INVALID_DATA, e) + } + buf.WriteByte(c) + hasDecimalPoint, nextCanBeSign = true, false + case 'e', 'E': + if hasE { + e := fmt.Errorf("Unable to parse number with multiple exponents '%s%c'", buf.String(), c) + return NUMERIC_NULL, NewTProtocolExceptionWithType(INVALID_DATA, e) + } + buf.WriteByte(c) + hasE, nextCanBeSign = true, true + case '-', '+': + if !nextCanBeSign { + e := fmt.Errorf("Negative sign within number") + return NUMERIC_NULL, NewTProtocolExceptionWithType(INVALID_DATA, e) + } + buf.WriteByte(c) + nextCanBeSign = false + case ' ', 0, '\t', '\n', '\r', JSON_RBRACE[0], JSON_RBRACKET[0], JSON_COMMA[0], JSON_COLON[0]: + p.reader.UnreadByte() + continueFor = false + case JSON_NAN[0]: + if buf.Len() == 0 { + buffer := make([]byte, len(JSON_NAN)) + buffer[0] = c + _, e := p.reader.Read(buffer[1:]) + if e != nil { + return NUMERIC_NULL, NewTProtocolException(e) + } + if JSON_NAN != string(buffer) { + e := mismatch(JSON_NAN, string(buffer)) + return NUMERIC_NULL, NewTProtocolExceptionWithType(INVALID_DATA, e) + } + if inQuotes { + p.readQuoteIfNext() + } + return NAN, nil + } else { + e := fmt.Errorf("Unable to parse number starting with character '%c'", c) + return NUMERIC_NULL, NewTProtocolExceptionWithType(INVALID_DATA, e) + } + case JSON_INFINITY[0]: + if buf.Len() == 0 || (buf.Len() == 1 && buf.Bytes()[0] == '+') { + buffer := make([]byte, len(JSON_INFINITY)) + buffer[0] = c + _, e := p.reader.Read(buffer[1:]) + if e != nil { + return NUMERIC_NULL, NewTProtocolException(e) + } + if JSON_INFINITY != string(buffer) { + e := mismatch(JSON_INFINITY, string(buffer)) + return NUMERIC_NULL, NewTProtocolExceptionWithType(INVALID_DATA, e) + } + if inQuotes { + p.readQuoteIfNext() + } + return INFINITY, nil + } else if buf.Len() == 1 && buf.Bytes()[0] == JSON_NEGATIVE_INFINITY[0] { + buffer := make([]byte, len(JSON_NEGATIVE_INFINITY)) + buffer[0] = JSON_NEGATIVE_INFINITY[0] + buffer[1] = c + _, e := p.reader.Read(buffer[2:]) + if e != nil { + return NUMERIC_NULL, NewTProtocolException(e) + } + if JSON_NEGATIVE_INFINITY != string(buffer) { + e := mismatch(JSON_NEGATIVE_INFINITY, string(buffer)) + return NUMERIC_NULL, NewTProtocolExceptionWithType(INVALID_DATA, e) + } + if inQuotes { + p.readQuoteIfNext() + } + return NEGATIVE_INFINITY, nil + } else { + e := fmt.Errorf("Unable to parse number starting with character '%c' due to existing buffer %s", c, buf.String()) + return NUMERIC_NULL, NewTProtocolExceptionWithType(INVALID_DATA, e) + } + case JSON_QUOTE: + if !inQuotes { + inQuotes = true + } else { + break + } + default: + e := fmt.Errorf("Unable to parse number starting with character '%c'", c) + return NUMERIC_NULL, NewTProtocolExceptionWithType(INVALID_DATA, e) + } + } + if buf.Len() == 0 { + e := fmt.Errorf("Unable to parse number from empty string ''") + return NUMERIC_NULL, NewTProtocolExceptionWithType(INVALID_DATA, e) + } + return NewNumericFromJSONString(buf.String(), false), nil +} + +// Safely peeks into the buffer, reading only what is necessary +func (p *TSimpleJSONProtocol) safePeekContains(b []byte) bool { + for i := 0; i < len(b); i++ { + a, _ := p.reader.Peek(i + 1) + if len(a) == 0 || a[i] != b[i] { + return false + } + } + return true +} + +// Reset the context stack to its initial state. +func (p *TSimpleJSONProtocol) resetContextStack() { + p.parseContextStack = []int{int(_CONTEXT_IN_TOPLEVEL)} + p.dumpContext = []int{int(_CONTEXT_IN_TOPLEVEL)} +} + +func (p *TSimpleJSONProtocol) write(b []byte) (int, error) { + n, err := p.writer.Write(b) + if err != nil { + p.writer.Reset(p.trans) // THRIFT-3735 + } + return n, err +} diff --git a/vendor/github.com/apache/thrift/lib/go/thrift/simple_server.go b/vendor/github.com/apache/thrift/lib/go/thrift/simple_server.go new file mode 100644 index 000000000..4097c4aea --- /dev/null +++ b/vendor/github.com/apache/thrift/lib/go/thrift/simple_server.go @@ -0,0 +1,196 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package thrift + +import ( + "log" + "runtime/debug" + "sync" +) + +// Simple, non-concurrent server for testing. +type TSimpleServer struct { + quit chan struct{} + + processorFactory TProcessorFactory + serverTransport TServerTransport + inputTransportFactory TTransportFactory + outputTransportFactory TTransportFactory + inputProtocolFactory TProtocolFactory + outputProtocolFactory TProtocolFactory +} + +func NewTSimpleServer2(processor TProcessor, serverTransport TServerTransport) *TSimpleServer { + return NewTSimpleServerFactory2(NewTProcessorFactory(processor), serverTransport) +} + +func NewTSimpleServer4(processor TProcessor, serverTransport TServerTransport, transportFactory TTransportFactory, protocolFactory TProtocolFactory) *TSimpleServer { + return NewTSimpleServerFactory4(NewTProcessorFactory(processor), + serverTransport, + transportFactory, + protocolFactory, + ) +} + +func NewTSimpleServer6(processor TProcessor, serverTransport TServerTransport, inputTransportFactory TTransportFactory, outputTransportFactory TTransportFactory, inputProtocolFactory TProtocolFactory, outputProtocolFactory TProtocolFactory) *TSimpleServer { + return NewTSimpleServerFactory6(NewTProcessorFactory(processor), + serverTransport, + inputTransportFactory, + outputTransportFactory, + inputProtocolFactory, + outputProtocolFactory, + ) +} + +func NewTSimpleServerFactory2(processorFactory TProcessorFactory, serverTransport TServerTransport) *TSimpleServer { + return NewTSimpleServerFactory6(processorFactory, + serverTransport, + NewTTransportFactory(), + NewTTransportFactory(), + NewTBinaryProtocolFactoryDefault(), + NewTBinaryProtocolFactoryDefault(), + ) +} + +func NewTSimpleServerFactory4(processorFactory TProcessorFactory, serverTransport TServerTransport, transportFactory TTransportFactory, protocolFactory TProtocolFactory) *TSimpleServer { + return NewTSimpleServerFactory6(processorFactory, + serverTransport, + transportFactory, + transportFactory, + protocolFactory, + protocolFactory, + ) +} + +func NewTSimpleServerFactory6(processorFactory TProcessorFactory, serverTransport TServerTransport, inputTransportFactory TTransportFactory, outputTransportFactory TTransportFactory, inputProtocolFactory TProtocolFactory, outputProtocolFactory TProtocolFactory) *TSimpleServer { + return &TSimpleServer{ + processorFactory: processorFactory, + serverTransport: serverTransport, + inputTransportFactory: inputTransportFactory, + outputTransportFactory: outputTransportFactory, + inputProtocolFactory: inputProtocolFactory, + outputProtocolFactory: outputProtocolFactory, + quit: make(chan struct{}, 1), + } +} + +func (p *TSimpleServer) ProcessorFactory() TProcessorFactory { + return p.processorFactory +} + +func (p *TSimpleServer) ServerTransport() TServerTransport { + return p.serverTransport +} + +func (p *TSimpleServer) InputTransportFactory() TTransportFactory { + return p.inputTransportFactory +} + +func (p *TSimpleServer) OutputTransportFactory() TTransportFactory { + return p.outputTransportFactory +} + +func (p *TSimpleServer) InputProtocolFactory() TProtocolFactory { + return p.inputProtocolFactory +} + +func (p *TSimpleServer) OutputProtocolFactory() TProtocolFactory { + return p.outputProtocolFactory +} + +func (p *TSimpleServer) Listen() error { + return p.serverTransport.Listen() +} + +func (p *TSimpleServer) AcceptLoop() error { + for { + client, err := p.serverTransport.Accept() + if err != nil { + select { + case <-p.quit: + return nil + default: + } + return err + } + if client != nil { + go func() { + if err := p.processRequests(client); err != nil { + log.Println("error processing request:", err) + } + }() + } + } +} + +func (p *TSimpleServer) Serve() error { + err := p.Listen() + if err != nil { + return err + } + p.AcceptLoop() + return nil +} + +var once sync.Once + +func (p *TSimpleServer) Stop() error { + q := func() { + p.quit <- struct{}{} + p.serverTransport.Interrupt() + } + once.Do(q) + return nil +} + +func (p *TSimpleServer) processRequests(client TTransport) error { + processor := p.processorFactory.GetProcessor(client) + inputTransport := p.inputTransportFactory.GetTransport(client) + outputTransport := p.outputTransportFactory.GetTransport(client) + inputProtocol := p.inputProtocolFactory.GetProtocol(inputTransport) + outputProtocol := p.outputProtocolFactory.GetProtocol(outputTransport) + defer func() { + if e := recover(); e != nil { + log.Printf("panic in processor: %s: %s", e, debug.Stack()) + } + }() + if inputTransport != nil { + defer inputTransport.Close() + } + if outputTransport != nil { + defer outputTransport.Close() + } + for { + ok, err := processor.Process(inputProtocol, outputProtocol) + if err, ok := err.(TTransportException); ok && err.TypeId() == END_OF_FILE { + return nil + } else if err != nil { + log.Printf("error processing request: %s", err) + return err + } + if err, ok := err.(TApplicationException); ok && err.TypeId() == UNKNOWN_METHOD { + continue + } + if !ok { + break + } + } + return nil +} diff --git a/vendor/github.com/apache/thrift/lib/go/thrift/socket.go b/vendor/github.com/apache/thrift/lib/go/thrift/socket.go new file mode 100644 index 000000000..82e28b4b1 --- /dev/null +++ b/vendor/github.com/apache/thrift/lib/go/thrift/socket.go @@ -0,0 +1,166 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package thrift + +import ( + "net" + "time" +) + +type TSocket struct { + conn net.Conn + addr net.Addr + timeout time.Duration +} + +// NewTSocket creates a net.Conn-backed TTransport, given a host and port +// +// Example: +// trans, err := thrift.NewTSocket("localhost:9090") +func NewTSocket(hostPort string) (*TSocket, error) { + return NewTSocketTimeout(hostPort, 0) +} + +// NewTSocketTimeout creates a net.Conn-backed TTransport, given a host and port +// it also accepts a timeout as a time.Duration +func NewTSocketTimeout(hostPort string, timeout time.Duration) (*TSocket, error) { + //conn, err := net.DialTimeout(network, address, timeout) + addr, err := net.ResolveTCPAddr("tcp", hostPort) + if err != nil { + return nil, err + } + return NewTSocketFromAddrTimeout(addr, timeout), nil +} + +// Creates a TSocket from a net.Addr +func NewTSocketFromAddrTimeout(addr net.Addr, timeout time.Duration) *TSocket { + return &TSocket{addr: addr, timeout: timeout} +} + +// Creates a TSocket from an existing net.Conn +func NewTSocketFromConnTimeout(conn net.Conn, timeout time.Duration) *TSocket { + return &TSocket{conn: conn, addr: conn.RemoteAddr(), timeout: timeout} +} + +// Sets the socket timeout +func (p *TSocket) SetTimeout(timeout time.Duration) error { + p.timeout = timeout + return nil +} + +func (p *TSocket) pushDeadline(read, write bool) { + var t time.Time + if p.timeout > 0 { + t = time.Now().Add(time.Duration(p.timeout)) + } + if read && write { + p.conn.SetDeadline(t) + } else if read { + p.conn.SetReadDeadline(t) + } else if write { + p.conn.SetWriteDeadline(t) + } +} + +// Connects the socket, creating a new socket object if necessary. +func (p *TSocket) Open() error { + if p.IsOpen() { + return NewTTransportException(ALREADY_OPEN, "Socket already connected.") + } + if p.addr == nil { + return NewTTransportException(NOT_OPEN, "Cannot open nil address.") + } + if len(p.addr.Network()) == 0 { + return NewTTransportException(NOT_OPEN, "Cannot open bad network name.") + } + if len(p.addr.String()) == 0 { + return NewTTransportException(NOT_OPEN, "Cannot open bad address.") + } + var err error + if p.conn, err = net.DialTimeout(p.addr.Network(), p.addr.String(), p.timeout); err != nil { + return NewTTransportException(NOT_OPEN, err.Error()) + } + return nil +} + +// Retrieve the underlying net.Conn +func (p *TSocket) Conn() net.Conn { + return p.conn +} + +// Returns true if the connection is open +func (p *TSocket) IsOpen() bool { + if p.conn == nil { + return false + } + return true +} + +// Closes the socket. +func (p *TSocket) Close() error { + // Close the socket + if p.conn != nil { + err := p.conn.Close() + if err != nil { + return err + } + p.conn = nil + } + return nil +} + +//Returns the remote address of the socket. +func (p *TSocket) Addr() net.Addr { + return p.addr +} + +func (p *TSocket) Read(buf []byte) (int, error) { + if !p.IsOpen() { + return 0, NewTTransportException(NOT_OPEN, "Connection not open") + } + p.pushDeadline(true, false) + n, err := p.conn.Read(buf) + return n, NewTTransportExceptionFromError(err) +} + +func (p *TSocket) Write(buf []byte) (int, error) { + if !p.IsOpen() { + return 0, NewTTransportException(NOT_OPEN, "Connection not open") + } + p.pushDeadline(false, true) + return p.conn.Write(buf) +} + +func (p *TSocket) Flush() error { + return nil +} + +func (p *TSocket) Interrupt() error { + if !p.IsOpen() { + return nil + } + return p.conn.Close() +} + +func (p *TSocket) RemainingBytes() (num_bytes uint64) { + const maxSize = ^uint64(0) + return maxSize // the thruth is, we just don't know unless framed is used +} + diff --git a/vendor/github.com/apache/thrift/lib/go/thrift/ssl_server_socket.go b/vendor/github.com/apache/thrift/lib/go/thrift/ssl_server_socket.go new file mode 100644 index 000000000..58f859b0e --- /dev/null +++ b/vendor/github.com/apache/thrift/lib/go/thrift/ssl_server_socket.go @@ -0,0 +1,109 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package thrift + +import ( + "net" + "time" + "crypto/tls" +) + +type TSSLServerSocket struct { + listener net.Listener + addr net.Addr + clientTimeout time.Duration + interrupted bool + cfg *tls.Config +} + +func NewTSSLServerSocket(listenAddr string, cfg *tls.Config) (*TSSLServerSocket, error) { + return NewTSSLServerSocketTimeout(listenAddr, cfg, 0) +} + +func NewTSSLServerSocketTimeout(listenAddr string, cfg *tls.Config, clientTimeout time.Duration) (*TSSLServerSocket, error) { + addr, err := net.ResolveTCPAddr("tcp", listenAddr) + if err != nil { + return nil, err + } + return &TSSLServerSocket{addr: addr, clientTimeout: clientTimeout, cfg: cfg}, nil +} + +func (p *TSSLServerSocket) Listen() error { + if p.IsListening() { + return nil + } + l, err := tls.Listen(p.addr.Network(), p.addr.String(), p.cfg) + if err != nil { + return err + } + p.listener = l + return nil +} + +func (p *TSSLServerSocket) Accept() (TTransport, error) { + if p.interrupted { + return nil, errTransportInterrupted + } + if p.listener == nil { + return nil, NewTTransportException(NOT_OPEN, "No underlying server socket") + } + conn, err := p.listener.Accept() + if err != nil { + return nil, NewTTransportExceptionFromError(err) + } + return NewTSSLSocketFromConnTimeout(conn, p.cfg, p.clientTimeout), nil +} + +// Checks whether the socket is listening. +func (p *TSSLServerSocket) IsListening() bool { + return p.listener != nil +} + +// Connects the socket, creating a new socket object if necessary. +func (p *TSSLServerSocket) Open() error { + if p.IsListening() { + return NewTTransportException(ALREADY_OPEN, "Server socket already open") + } + if l, err := tls.Listen(p.addr.Network(), p.addr.String(), p.cfg); err != nil { + return err + } else { + p.listener = l + } + return nil +} + +func (p *TSSLServerSocket) Addr() net.Addr { + return p.addr +} + +func (p *TSSLServerSocket) Close() error { + defer func() { + p.listener = nil + }() + if p.IsListening() { + return p.listener.Close() + } + return nil +} + +func (p *TSSLServerSocket) Interrupt() error { + p.interrupted = true + return nil +} diff --git a/vendor/github.com/apache/thrift/lib/go/thrift/ssl_socket.go b/vendor/github.com/apache/thrift/lib/go/thrift/ssl_socket.go new file mode 100644 index 000000000..04d385085 --- /dev/null +++ b/vendor/github.com/apache/thrift/lib/go/thrift/ssl_socket.go @@ -0,0 +1,171 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package thrift + +import ( + "crypto/tls" + "net" + "time" +) + +type TSSLSocket struct { + conn net.Conn + // hostPort contains host:port (e.g. "asdf.com:12345"). The field is + // only valid if addr is nil. + hostPort string + // addr is nil when hostPort is not "", and is only used when the + // TSSLSocket is constructed from a net.Addr. + addr net.Addr + timeout time.Duration + cfg *tls.Config +} + +// NewTSSLSocket creates a net.Conn-backed TTransport, given a host and port and tls Configuration +// +// Example: +// trans, err := thrift.NewTSSLSocket("localhost:9090", nil) +func NewTSSLSocket(hostPort string, cfg *tls.Config) (*TSSLSocket, error) { + return NewTSSLSocketTimeout(hostPort, cfg, 0) +} + +// NewTSSLSocketTimeout creates a net.Conn-backed TTransport, given a host and port +// it also accepts a tls Configuration and a timeout as a time.Duration +func NewTSSLSocketTimeout(hostPort string, cfg *tls.Config, timeout time.Duration) (*TSSLSocket, error) { + return &TSSLSocket{hostPort: hostPort, timeout: timeout, cfg: cfg}, nil +} + +// Creates a TSSLSocket from a net.Addr +func NewTSSLSocketFromAddrTimeout(addr net.Addr, cfg *tls.Config, timeout time.Duration) *TSSLSocket { + return &TSSLSocket{addr: addr, timeout: timeout, cfg: cfg} +} + +// Creates a TSSLSocket from an existing net.Conn +func NewTSSLSocketFromConnTimeout(conn net.Conn, cfg *tls.Config, timeout time.Duration) *TSSLSocket { + return &TSSLSocket{conn: conn, addr: conn.RemoteAddr(), timeout: timeout, cfg: cfg} +} + +// Sets the socket timeout +func (p *TSSLSocket) SetTimeout(timeout time.Duration) error { + p.timeout = timeout + return nil +} + +func (p *TSSLSocket) pushDeadline(read, write bool) { + var t time.Time + if p.timeout > 0 { + t = time.Now().Add(time.Duration(p.timeout)) + } + if read && write { + p.conn.SetDeadline(t) + } else if read { + p.conn.SetReadDeadline(t) + } else if write { + p.conn.SetWriteDeadline(t) + } +} + +// Connects the socket, creating a new socket object if necessary. +func (p *TSSLSocket) Open() error { + var err error + // If we have a hostname, we need to pass the hostname to tls.Dial for + // certificate hostname checks. + if p.hostPort != "" { + if p.conn, err = tls.Dial("tcp", p.hostPort, p.cfg); err != nil { + return NewTTransportException(NOT_OPEN, err.Error()) + } + } else { + if p.IsOpen() { + return NewTTransportException(ALREADY_OPEN, "Socket already connected.") + } + if p.addr == nil { + return NewTTransportException(NOT_OPEN, "Cannot open nil address.") + } + if len(p.addr.Network()) == 0 { + return NewTTransportException(NOT_OPEN, "Cannot open bad network name.") + } + if len(p.addr.String()) == 0 { + return NewTTransportException(NOT_OPEN, "Cannot open bad address.") + } + if p.conn, err = tls.Dial(p.addr.Network(), p.addr.String(), p.cfg); err != nil { + return NewTTransportException(NOT_OPEN, err.Error()) + } + } + return nil +} + +// Retrieve the underlying net.Conn +func (p *TSSLSocket) Conn() net.Conn { + return p.conn +} + +// Returns true if the connection is open +func (p *TSSLSocket) IsOpen() bool { + if p.conn == nil { + return false + } + return true +} + +// Closes the socket. +func (p *TSSLSocket) Close() error { + // Close the socket + if p.conn != nil { + err := p.conn.Close() + if err != nil { + return err + } + p.conn = nil + } + return nil +} + +func (p *TSSLSocket) Read(buf []byte) (int, error) { + if !p.IsOpen() { + return 0, NewTTransportException(NOT_OPEN, "Connection not open") + } + p.pushDeadline(true, false) + n, err := p.conn.Read(buf) + return n, NewTTransportExceptionFromError(err) +} + +func (p *TSSLSocket) Write(buf []byte) (int, error) { + if !p.IsOpen() { + return 0, NewTTransportException(NOT_OPEN, "Connection not open") + } + p.pushDeadline(false, true) + return p.conn.Write(buf) +} + +func (p *TSSLSocket) Flush() error { + return nil +} + +func (p *TSSLSocket) Interrupt() error { + if !p.IsOpen() { + return nil + } + return p.conn.Close() +} + +func (p *TSSLSocket) RemainingBytes() (num_bytes uint64) { + const maxSize = ^uint64(0) + return maxSize // the thruth is, we just don't know unless framed is used +} + diff --git a/vendor/github.com/apache/thrift/lib/go/thrift/transport.go b/vendor/github.com/apache/thrift/lib/go/thrift/transport.go new file mode 100644 index 000000000..453899651 --- /dev/null +++ b/vendor/github.com/apache/thrift/lib/go/thrift/transport.go @@ -0,0 +1,68 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package thrift + +import ( + "errors" + "io" +) + +var errTransportInterrupted = errors.New("Transport Interrupted") + +type Flusher interface { + Flush() (err error) +} + +type ReadSizeProvider interface { + RemainingBytes() (num_bytes uint64) +} + + +// Encapsulates the I/O layer +type TTransport interface { + io.ReadWriteCloser + Flusher + ReadSizeProvider + + // Opens the transport for communication + Open() error + + // Returns true if the transport is open + IsOpen() bool +} + +type stringWriter interface { + WriteString(s string) (n int, err error) +} + + +// This is "enchanced" transport with extra capabilities. You need to use one of these +// to construct protocol. +// Notably, TSocket does not implement this interface, and it is always a mistake to use +// TSocket directly in protocol. +type TRichTransport interface { + io.ReadWriter + io.ByteReader + io.ByteWriter + stringWriter + Flusher + ReadSizeProvider +} + diff --git a/vendor/github.com/apache/thrift/lib/go/thrift/transport_exception.go b/vendor/github.com/apache/thrift/lib/go/thrift/transport_exception.go new file mode 100644 index 000000000..9505b4461 --- /dev/null +++ b/vendor/github.com/apache/thrift/lib/go/thrift/transport_exception.go @@ -0,0 +1,90 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package thrift + +import ( + "errors" + "io" +) + +type timeoutable interface { + Timeout() bool +} + +// Thrift Transport exception +type TTransportException interface { + TException + TypeId() int + Err() error +} + +const ( + UNKNOWN_TRANSPORT_EXCEPTION = 0 + NOT_OPEN = 1 + ALREADY_OPEN = 2 + TIMED_OUT = 3 + END_OF_FILE = 4 +) + +type tTransportException struct { + typeId int + err error +} + +func (p *tTransportException) TypeId() int { + return p.typeId +} + +func (p *tTransportException) Error() string { + return p.err.Error() +} + +func (p *tTransportException) Err() error { + return p.err +} + +func NewTTransportException(t int, e string) TTransportException { + return &tTransportException{typeId: t, err: errors.New(e)} +} + +func NewTTransportExceptionFromError(e error) TTransportException { + if e == nil { + return nil + } + + if t, ok := e.(TTransportException); ok { + return t + } + + switch v := e.(type) { + case TTransportException: + return v + case timeoutable: + if v.Timeout() { + return &tTransportException{typeId: TIMED_OUT, err: e} + } + } + + if e == io.EOF { + return &tTransportException{typeId: END_OF_FILE, err: e} + } + + return &tTransportException{typeId: UNKNOWN_TRANSPORT_EXCEPTION, err: e} +} diff --git a/vendor/github.com/apache/thrift/lib/go/thrift/transport_factory.go b/vendor/github.com/apache/thrift/lib/go/thrift/transport_factory.go new file mode 100644 index 000000000..533d1b437 --- /dev/null +++ b/vendor/github.com/apache/thrift/lib/go/thrift/transport_factory.go @@ -0,0 +1,39 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package thrift + +// Factory class used to create wrapped instance of Transports. +// This is used primarily in servers, which get Transports from +// a ServerTransport and then may want to mutate them (i.e. create +// a BufferedTransport from the underlying base transport) +type TTransportFactory interface { + GetTransport(trans TTransport) TTransport +} + +type tTransportFactory struct{} + +// Return a wrapped instance of the base Transport. +func (p *tTransportFactory) GetTransport(trans TTransport) TTransport { + return trans +} + +func NewTTransportFactory() TTransportFactory { + return &tTransportFactory{} +} diff --git a/vendor/github.com/apache/thrift/lib/go/thrift/type.go b/vendor/github.com/apache/thrift/lib/go/thrift/type.go new file mode 100644 index 000000000..4292ffcad --- /dev/null +++ b/vendor/github.com/apache/thrift/lib/go/thrift/type.go @@ -0,0 +1,69 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package thrift + +// Type constants in the Thrift protocol +type TType byte + +const ( + STOP = 0 + VOID = 1 + BOOL = 2 + BYTE = 3 + I08 = 3 + DOUBLE = 4 + I16 = 6 + I32 = 8 + I64 = 10 + STRING = 11 + UTF7 = 11 + STRUCT = 12 + MAP = 13 + SET = 14 + LIST = 15 + UTF8 = 16 + UTF16 = 17 + //BINARY = 18 wrong and unusued +) + +var typeNames = map[int]string{ + STOP: "STOP", + VOID: "VOID", + BOOL: "BOOL", + BYTE: "BYTE", + DOUBLE: "DOUBLE", + I16: "I16", + I32: "I32", + I64: "I64", + STRING: "STRING", + STRUCT: "STRUCT", + MAP: "MAP", + SET: "SET", + LIST: "LIST", + UTF8: "UTF8", + UTF16: "UTF16", +} + +func (p TType) String() string { + if s, ok := typeNames[int(p)]; ok { + return s + } + return "Unknown" +} diff --git a/vendor/github.com/apache/thrift/lib/go/thrift/zlib_transport.go b/vendor/github.com/apache/thrift/lib/go/thrift/zlib_transport.go new file mode 100644 index 000000000..e47455fe1 --- /dev/null +++ b/vendor/github.com/apache/thrift/lib/go/thrift/zlib_transport.go @@ -0,0 +1,117 @@ +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. + */ + +package thrift + +import ( + "compress/zlib" + "io" + "log" +) + +// TZlibTransportFactory is a factory for TZlibTransport instances +type TZlibTransportFactory struct { + level int +} + +// TZlibTransport is a TTransport implementation that makes use of zlib compression. +type TZlibTransport struct { + reader io.ReadCloser + transport TTransport + writer *zlib.Writer +} + +// GetTransport constructs a new instance of NewTZlibTransport +func (p *TZlibTransportFactory) GetTransport(trans TTransport) TTransport { + t, _ := NewTZlibTransport(trans, p.level) + return t +} + +// NewTZlibTransportFactory constructs a new instance of NewTZlibTransportFactory +func NewTZlibTransportFactory(level int) *TZlibTransportFactory { + return &TZlibTransportFactory{level: level} +} + +// NewTZlibTransport constructs a new instance of TZlibTransport +func NewTZlibTransport(trans TTransport, level int) (*TZlibTransport, error) { + w, err := zlib.NewWriterLevel(trans, level) + if err != nil { + log.Println(err) + return nil, err + } + + return &TZlibTransport{ + writer: w, + transport: trans, + }, nil +} + +// Close closes the reader and writer (flushing any unwritten data) and closes +// the underlying transport. +func (z *TZlibTransport) Close() error { + if z.reader != nil { + if err := z.reader.Close(); err != nil { + return err + } + } + if err := z.writer.Close(); err != nil { + return err + } + return z.transport.Close() +} + +// Flush flushes the writer and its underlying transport. +func (z *TZlibTransport) Flush() error { + if err := z.writer.Flush(); err != nil { + return err + } + return z.transport.Flush() +} + +// IsOpen returns true if the transport is open +func (z *TZlibTransport) IsOpen() bool { + return z.transport.IsOpen() +} + +// Open opens the transport for communication +func (z *TZlibTransport) Open() error { + return z.transport.Open() +} + +func (z *TZlibTransport) Read(p []byte) (int, error) { + if z.reader == nil { + r, err := zlib.NewReader(z.transport) + if err != nil { + return 0, NewTTransportExceptionFromError(err) + } + z.reader = r + } + + return z.reader.Read(p) +} + +// RemainingBytes returns the size in bytes of the data that is still to be +// read. +func (z *TZlibTransport) RemainingBytes() uint64 { + return z.transport.RemainingBytes() +} + +func (z *TZlibTransport) Write(p []byte) (int, error) { + return z.writer.Write(p) +} diff --git a/vendor/github.com/apache/thrift/lib/lua/src/longnumberutils.c b/vendor/github.com/apache/thrift/lib/lua/src/longnumberutils.c new file mode 100644 index 000000000..fbc678900 --- /dev/null +++ b/vendor/github.com/apache/thrift/lib/lua/src/longnumberutils.c @@ -0,0 +1,47 @@ +// +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT 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 +#include +#include +#include + +const char * LONG_NUM_TYPE = "__thrift_longnumber"; +int64_t lualongnumber_checklong(lua_State *L, int index) { + switch (lua_type(L, index)) { + case LUA_TNUMBER: + return (int64_t)lua_tonumber(L, index); + case LUA_TSTRING: + return atoll(lua_tostring(L, index)); + default: + return *((int64_t *)luaL_checkudata(L, index, LONG_NUM_TYPE)); + } +} + +// Creates a new longnumber and pushes it onto the statck +int64_t * lualongnumber_pushlong(lua_State *L, int64_t *val) { + int64_t *data = (int64_t *)lua_newuserdata(L, sizeof(int64_t)); // longnum + luaL_getmetatable(L, LONG_NUM_TYPE); // longnum, mt + lua_setmetatable(L, -2); // longnum + if (val) { + *data = *val; + } + return data; +} + diff --git a/vendor/github.com/apache/thrift/lib/lua/src/luabitwise.c b/vendor/github.com/apache/thrift/lib/lua/src/luabitwise.c new file mode 100644 index 000000000..2e07e1724 --- /dev/null +++ b/vendor/github.com/apache/thrift/lib/lua/src/luabitwise.c @@ -0,0 +1,83 @@ +// +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +// + +#include +#include + +static int l_not(lua_State *L) { + int a = luaL_checkinteger(L, 1); + a = ~a; + lua_pushnumber(L, a); + return 1; +} + +static int l_xor(lua_State *L) { + int a = luaL_checkinteger(L, 1); + int b = luaL_checkinteger(L, 2); + a ^= b; + lua_pushnumber(L, a); + return 1; +} + +static int l_and(lua_State *L) { + int a = luaL_checkinteger(L, 1); + int b = luaL_checkinteger(L, 2); + a &= b; + lua_pushnumber(L, a); + return 1; +} + +static int l_or(lua_State *L) { + int a = luaL_checkinteger(L, 1); + int b = luaL_checkinteger(L, 2); + a |= b; + lua_pushnumber(L, a); + return 1; +} + +static int l_shiftr(lua_State *L) { + int a = luaL_checkinteger(L, 1); + int b = luaL_checkinteger(L, 2); + a = a >> b; + lua_pushnumber(L, a); + return 1; +} + +static int l_shiftl(lua_State *L) { + int a = luaL_checkinteger(L, 1); + int b = luaL_checkinteger(L, 2); + a = a << b; + lua_pushnumber(L, a); + return 1; +} + +static const struct luaL_Reg funcs[] = { + {"band", l_and}, + {"bor", l_or}, + {"bxor", l_xor}, + {"bnot", l_not}, + {"shiftl", l_shiftl}, + {"shiftr", l_shiftr}, + {NULL, NULL} +}; + +int luaopen_libluabitwise(lua_State *L) { + luaL_register(L, "libluabitwise", funcs); + return 1; +} diff --git a/vendor/github.com/apache/thrift/lib/lua/src/luabpack.c b/vendor/github.com/apache/thrift/lib/lua/src/luabpack.c new file mode 100644 index 000000000..a86fc3ed1 --- /dev/null +++ b/vendor/github.com/apache/thrift/lib/lua/src/luabpack.c @@ -0,0 +1,308 @@ +// +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT 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 +#include +#include +#include +#include + +extern int64_t lualongnumber_checklong(lua_State *L, int index); +extern int64_t lualongnumber_pushlong(lua_State *L, int64_t *val); + +// host order to network order (64-bit) +static int64_t T_htonll(uint64_t data) { + uint32_t d1 = htonl((uint32_t)data); + uint32_t d2 = htonl((uint32_t)(data >> 32)); + return ((uint64_t)d1 << 32) + (uint64_t)d2; +} + +// network order to host order (64-bit) +static int64_t T_ntohll(uint64_t data) { + uint32_t d1 = ntohl((uint32_t)data); + uint32_t d2 = ntohl((uint32_t)(data >> 32)); + return ((uint64_t)d1 << 32) + (uint64_t)d2; +} + +/** + * bpack(type, data) + * c - Signed Byte + * s - Signed Short + * i - Signed Int + * l - Signed Long + * d - Double + */ +static int l_bpack(lua_State *L) { + const char *code = luaL_checkstring(L, 1); + luaL_argcheck(L, code[1] == '\0', 0, "Format code must be one character."); + luaL_Buffer buf; + luaL_buffinit(L, &buf); + + switch (code[0]) { + case 'c': { + int8_t data = luaL_checknumber(L, 2); + luaL_addlstring(&buf, (void*)&data, sizeof(data)); + break; + } + case 's': { + int16_t data = luaL_checknumber(L, 2); + data = (int16_t)htons(data); + luaL_addlstring(&buf, (void*)&data, sizeof(data)); + break; + } + case 'i': { + int32_t data = luaL_checkinteger(L, 2); + data = (int32_t)htonl(data); + luaL_addlstring(&buf, (void*)&data, sizeof(data)); + break; + } + case 'l': { + int64_t data = lualongnumber_checklong(L, 2); + data = (int64_t)T_htonll(data); + luaL_addlstring(&buf, (void*)&data, sizeof(data)); + break; + } + case 'd': { + double data = luaL_checknumber(L, 2); + luaL_addlstring(&buf, (void*)&data, sizeof(data)); + break; + } + default: + luaL_argcheck(L, 0, 0, "Invalid format code."); + } + + luaL_pushresult(&buf); + return 1; +} + +/** + * bunpack(type, data) + * c - Signed Byte + * C - Unsigned Byte + * s - Signed Short + * i - Signed Int + * l - Signed Long + * d - Double + */ +static int l_bunpack(lua_State *L) { + const char *code = luaL_checkstring(L, 1); + luaL_argcheck(L, code[1] == '\0', 0, "Format code must be one character."); + const char *data = luaL_checkstring(L, 2); +#ifdef _LUA51_ + size_t len = lua_objlen(L, 2); +#else + size_t len = lua_rawlen(L, 2); +#endif + + switch (code[0]) { + case 'c': { + int8_t val; + luaL_argcheck(L, len == sizeof(val), 1, "Invalid input string size."); + memcpy(&val, data, sizeof(val)); + lua_pushnumber(L, val); + break; + } + /** + * unpack unsigned Byte. + */ + case 'C': { + uint8_t val; + luaL_argcheck(L, len == sizeof(val), 1, "Invalid input string size."); + memcpy(&val, data, sizeof(val)); + lua_pushnumber(L, val); + break; + } + case 's': { + int16_t val; + luaL_argcheck(L, len == sizeof(val), 1, "Invalid input string size."); + memcpy(&val, data, sizeof(val)); + val = (int16_t)ntohs(val); + lua_pushnumber(L, val); + break; + } + case 'i': { + int32_t val; + luaL_argcheck(L, len == sizeof(val), 1, "Invalid input string size."); + memcpy(&val, data, sizeof(val)); + val = (int32_t)ntohl(val); + lua_pushnumber(L, val); + break; + } + case 'l': { + int64_t val; + luaL_argcheck(L, len == sizeof(val), 1, "Invalid input string size."); + memcpy(&val, data, sizeof(val)); + val = (int64_t)T_ntohll(val); + lualongnumber_pushlong(L, &val); + break; + } + case 'd': { + double val; + luaL_argcheck(L, len == sizeof(val), 1, "Invalid input string size."); + memcpy(&val, data, sizeof(val)); + lua_pushnumber(L, val); + break; + } + default: + luaL_argcheck(L, 0, 0, "Invalid format code."); + } + return 1; +} + +/** + * Convert l into a zigzag long. This allows negative numbers to be + * represented compactly as a varint. + */ +static int l_i64ToZigzag(lua_State *L) { + int64_t n = lualongnumber_checklong(L, 1); + int64_t result = (n << 1) ^ (n >> 63); + lualongnumber_pushlong(L, &result); + return 1; +} +/** + * Convert n into a zigzag int. This allows negative numbers to be + * represented compactly as a varint. + */ +static int l_i32ToZigzag(lua_State *L) { + int32_t n = luaL_checkinteger(L, 1); + uint32_t result = (uint32_t)(n << 1) ^ (n >> 31); + lua_pushnumber(L, result); + return 1; +} + +/** + * Convert from zigzag int to int. + */ +static int l_zigzagToI32(lua_State *L) { + uint32_t n = luaL_checkinteger(L, 1); + int32_t result = (int32_t)(n >> 1) ^ (uint32_t)(-(int32_t)(n & 1)); + lua_pushnumber(L, result); + return 1; +} + +/** + * Convert from zigzag long to long. + */ +static int l_zigzagToI64(lua_State *L) { + int64_t n = lualongnumber_checklong(L, 1); + int64_t result = (int64_t)(n >> 1) ^ (uint64_t)(-(int64_t)(n & 1)); + lualongnumber_pushlong(L, &result); + return 1; +} + +/** + * Convert an i32 to a varint. Results in 1-5 bytes on the buffer. + */ +static int l_toVarint32(lua_State *L) { + uint8_t buf[5]; + uint32_t n = luaL_checkinteger(L, 1); + uint32_t wsize = 0; + + while (1) { + if ((n & ~0x7F) == 0) { + buf[wsize++] = (int8_t)n; + break; + } else { + buf[wsize++] = (int8_t)((n & 0x7F) | 0x80); + n >>= 7; + } + } + lua_pushlstring(L, buf, wsize); + return 1; +} + +/** + * Convert an i64 to a varint. Results in 1-10 bytes on the buffer. + */ +static int l_toVarint64(lua_State *L) { + uint8_t data[10]; + uint64_t n = lualongnumber_checklong(L, 1); + uint32_t wsize = 0; + luaL_Buffer buf; + luaL_buffinit(L, &buf); + + while (1) { + if ((n & ~0x7FL) == 0) { + data[wsize++] = (int8_t)n; + break; + } else { + data[wsize++] = (int8_t)((n & 0x7F) | 0x80); + n >>= 7; + } + } + + luaL_addlstring(&buf, (void*)&data, wsize); + luaL_pushresult(&buf); + return 1; +} + +/** + * Convert a varint to i64. + */ +static int l_fromVarint64(lua_State *L) { + int64_t result; + uint8_t byte = luaL_checknumber(L, 1); + int32_t shift = luaL_checknumber(L, 2); + uint64_t n = (uint64_t)lualongnumber_checklong(L, 3); + n |= (uint64_t)(byte & 0x7f) << shift; + + if (!(byte & 0x80)) { + result = (int64_t)(n >> 1) ^ (uint64_t)(-(int64_t)(n & 1)); + lua_pushnumber(L, 0); + } else { + result = n; + lua_pushnumber(L, 1); + } + lualongnumber_pushlong(L, &result); + return 2; +} + +/** + * To pack message type of compact protocol. + */ +static int l_packMesgType(lua_State *L) { + int32_t version_n = luaL_checkinteger(L, 1); + int32_t version_mask = luaL_checkinteger(L, 2); + int32_t messagetype = luaL_checkinteger(L, 3); + int32_t type_shift_amount = luaL_checkinteger(L, 4); + int32_t type_mask = luaL_checkinteger(L, 5); + int32_t to_mesg_type = (version_n & version_mask) | + (((int32_t)messagetype << type_shift_amount) & type_mask); + lua_pushnumber(L, to_mesg_type); + return 1; +} + +static const struct luaL_Reg lua_bpack[] = { + {"bpack", l_bpack}, + {"bunpack", l_bunpack}, + {"i32ToZigzag", l_i32ToZigzag}, + {"i64ToZigzag", l_i64ToZigzag}, + {"zigzagToI32", l_zigzagToI32}, + {"zigzagToI64", l_zigzagToI64}, + {"toVarint32", l_toVarint32}, + {"toVarint64", l_toVarint64}, + {"fromVarint64", l_fromVarint64}, + {"packMesgType", l_packMesgType}, + {NULL, NULL} +}; + +int luaopen_libluabpack(lua_State *L) { + luaL_register(L, "libluabpack", lua_bpack); + return 1; +} diff --git a/vendor/github.com/apache/thrift/lib/lua/src/lualongnumber.c b/vendor/github.com/apache/thrift/lib/lua/src/lualongnumber.c new file mode 100644 index 000000000..9001e4a90 --- /dev/null +++ b/vendor/github.com/apache/thrift/lib/lua/src/lualongnumber.c @@ -0,0 +1,228 @@ +// +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT 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 +#include +#include +#include +#include +#include + +extern const char * LONG_NUM_TYPE; +extern int64_t lualongnumber_checklong(lua_State *L, int index); +extern int64_t lualongnumber_pushlong(lua_State *L, int64_t *val); + +//////////////////////////////////////////////////////////////////////////////// + +static void l_serialize(char *buf, int len, int64_t val) { + snprintf(buf, len, "%"PRId64, val); +} + +static int64_t l_deserialize(const char *buf) { + int64_t data; + int rv; + // Support hex prefixed with '0x' + if (strstr(buf, "0x") == buf) { + rv = sscanf(buf, "%"PRIx64, &data); + } else { + rv = sscanf(buf, "%"PRId64, &data); + } + if (rv == 1) { + return data; + } + return 0; // Failed +} + +//////////////////////////////////////////////////////////////////////////////// + +static int l_new(lua_State *L) { + int64_t val; + const char *str = NULL; + if (lua_type(L, 1) == LUA_TSTRING) { + str = lua_tostring(L, 1); + val = l_deserialize(str); + } else if (lua_type(L, 1) == LUA_TNUMBER) { + val = (int64_t)lua_tonumber(L, 1); + str = (const char *)1; + } + lualongnumber_pushlong(L, (str ? &val : NULL)); + return 1; +} + +//////////////////////////////////////////////////////////////////////////////// + +// a + b +static int l_add(lua_State *L) { + int64_t a, b, c; + a = lualongnumber_checklong(L, 1); + b = lualongnumber_checklong(L, 2); + c = a + b; + lualongnumber_pushlong(L, &c); + return 1; +} + +// a / b +static int l_div(lua_State *L) { + int64_t a, b, c; + a = lualongnumber_checklong(L, 1); + b = lualongnumber_checklong(L, 2); + c = a / b; + lualongnumber_pushlong(L, &c); + return 1; +} + +// a == b (both a and b are lualongnumber's) +static int l_eq(lua_State *L) { + int64_t a, b; + a = lualongnumber_checklong(L, 1); + b = lualongnumber_checklong(L, 2); + lua_pushboolean(L, (a == b ? 1 : 0)); + return 1; +} + +// garbage collection +static int l_gc(lua_State *L) { + lua_pushnil(L); + lua_setmetatable(L, 1); + return 0; +} + +// a < b +static int l_lt(lua_State *L) { + int64_t a, b; + a = lualongnumber_checklong(L, 1); + b = lualongnumber_checklong(L, 2); + lua_pushboolean(L, (a < b ? 1 : 0)); + return 1; +} + +// a <= b +static int l_le(lua_State *L) { + int64_t a, b; + a = lualongnumber_checklong(L, 1); + b = lualongnumber_checklong(L, 2); + lua_pushboolean(L, (a <= b ? 1 : 0)); + return 1; +} + +// a % b +static int l_mod(lua_State *L) { + int64_t a, b, c; + a = lualongnumber_checklong(L, 1); + b = lualongnumber_checklong(L, 2); + c = a % b; + lualongnumber_pushlong(L, &c); + return 1; +} + +// a * b +static int l_mul(lua_State *L) { + int64_t a, b, c; + a = lualongnumber_checklong(L, 1); + b = lualongnumber_checklong(L, 2); + c = a * b; + lualongnumber_pushlong(L, &c); + return 1; +} + +// a ^ b +static int l_pow(lua_State *L) { + long double a, b; + int64_t c; + a = (long double)lualongnumber_checklong(L, 1); + b = (long double)lualongnumber_checklong(L, 2); + c = (int64_t)pow(a, b); + lualongnumber_pushlong(L, &c); + return 1; +} + +// a - b +static int l_sub(lua_State *L) { + int64_t a, b, c; + a = lualongnumber_checklong(L, 1); + b = lualongnumber_checklong(L, 2); + c = a - b; + lualongnumber_pushlong(L, &c); + return 1; +} + +// tostring() +static int l_tostring(lua_State *L) { + int64_t a; + char str[256]; + l_serialize(str, 256, lualongnumber_checklong(L, 1)); + lua_pushstring(L, str); + return 1; +} + +// -a +static int l_unm(lua_State *L) { + int64_t a, c; + a = lualongnumber_checklong(L, 1); + c = -a; + lualongnumber_pushlong(L, &c); + return 1; +} + +//////////////////////////////////////////////////////////////////////////////// + +static const luaL_Reg methods[] = { + {"__add", l_add}, + {"__div", l_div}, + {"__eq", l_eq}, + {"__gc", l_gc}, + {"__lt", l_lt}, + {"__le", l_le}, + {"__mod", l_mod}, + {"__mul", l_mul}, + {"__pow", l_pow}, + {"__sub", l_sub}, + {"__tostring", l_tostring}, + {"__unm", l_unm}, + {NULL, NULL}, +}; + +static const luaL_Reg funcs[] = { + {"new", l_new}, + {NULL, NULL} +}; + +//////////////////////////////////////////////////////////////////////////////// + +static void set_methods(lua_State *L, + const char *metatablename, + const struct luaL_Reg *methods) { + luaL_getmetatable(L, metatablename); // mt + // No need for a __index table since everything is __* + for (; methods->name; methods++) { + lua_pushstring(L, methods->name); // mt, "name" + lua_pushcfunction(L, methods->func); // mt, "name", func + lua_rawset(L, -3); // mt + } + lua_pop(L, 1); +} + +LUALIB_API int luaopen_liblualongnumber(lua_State *L) { + luaL_newmetatable(L, LONG_NUM_TYPE); + lua_pop(L, 1); + set_methods(L, LONG_NUM_TYPE, methods); + + luaL_register(L, "liblualongnumber", funcs); + return 1; +} diff --git a/vendor/github.com/apache/thrift/lib/lua/src/luasocket.c b/vendor/github.com/apache/thrift/lib/lua/src/luasocket.c new file mode 100644 index 000000000..d48351077 --- /dev/null +++ b/vendor/github.com/apache/thrift/lib/lua/src/luasocket.c @@ -0,0 +1,380 @@ +// +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT 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 +#include + +#include +#include "string.h" +#include "socket.h" + +//////////////////////////////////////////////////////////////////////////////// + +static const char *SOCKET_ANY = "__thrift_socket_any"; +static const char *SOCKET_CONN = "__thrift_socket_connected"; + +static const char *SOCKET_GENERIC = "__thrift_socket_generic"; +static const char *SOCKET_CLIENT = "__thrift_socket_client"; +static const char *SOCKET_SERVER = "__thrift_socket_server"; + +static const char *DEFAULT_HOST = "localhost"; + +typedef struct __t_tcp { + t_socket sock; + int timeout; // Milliseconds +} t_tcp; +typedef t_tcp *p_tcp; + +//////////////////////////////////////////////////////////////////////////////// +// Util + +static void throw_argerror(lua_State *L, int index, const char *expected) { + char msg[256]; + sprintf(msg, "%s expected, got %s", expected, luaL_typename(L, index)); + luaL_argerror(L, index, msg); +} + +static void *checkgroup(lua_State *L, int index, const char *groupname) { + if (!lua_getmetatable(L, index)) { + throw_argerror(L, index, groupname); + } + + lua_pushstring(L, groupname); + lua_rawget(L, -2); + if (lua_isnil(L, -1)) { + lua_pop(L, 2); + throw_argerror(L, index, groupname); + } else { + lua_pop(L, 2); + return lua_touserdata(L, index); + } + return NULL; // Not reachable +} + +static void *checktype(lua_State *L, int index, const char *typename) { + if (strcmp(typename, SOCKET_ANY) == 0 || + strcmp(typename, SOCKET_CONN) == 0) { + return checkgroup(L, index, typename); + } else { + return luaL_checkudata(L, index, typename); + } +} + +static void settype(lua_State *L, int index, const char *typename) { + luaL_getmetatable(L, typename); + lua_setmetatable(L, index); +} + +#define LUA_SUCCESS_RETURN(L) \ + lua_pushnumber(L, 1); \ + return 1 + +#define LUA_CHECK_RETURN(L, err) \ + if (err) { \ + lua_pushnil(L); \ + lua_pushstring(L, err); \ + return 2; \ + } \ + LUA_SUCCESS_RETURN(L) + +//////////////////////////////////////////////////////////////////////////////// + +static int l_socket_create(lua_State *L); +static int l_socket_destroy(lua_State *L); +static int l_socket_settimeout(lua_State *L); +static int l_socket_getsockinfo(lua_State *L); + +static int l_socket_accept(lua_State *L); +static int l_socket_listen(lua_State *L); + +static int l_socket_create_and_connect(lua_State *L); +static int l_socket_connect(lua_State *L); +static int l_socket_send(lua_State *L); +static int l_socket_receive(lua_State *L); + +//////////////////////////////////////////////////////////////////////////////// + +static const struct luaL_Reg methods_generic[] = { + {"destroy", l_socket_destroy}, + {"settimeout", l_socket_settimeout}, + {"getsockinfo", l_socket_getsockinfo}, + {"listen", l_socket_listen}, + {"connect", l_socket_connect}, + {NULL, NULL} +}; + +static const struct luaL_Reg methods_server[] = { + {"destroy", l_socket_destroy}, + {"getsockinfo", l_socket_getsockinfo}, + {"accept", l_socket_accept}, + {"send", l_socket_send}, + {"receive", l_socket_receive}, + {NULL, NULL} +}; + +static const struct luaL_Reg methods_client[] = { + {"destroy", l_socket_destroy}, + {"settimeout", l_socket_settimeout}, + {"getsockinfo", l_socket_getsockinfo}, + {"send", l_socket_send}, + {"receive", l_socket_receive}, + {NULL, NULL} +}; + +static const struct luaL_Reg funcs_luasocket[] = { + {"create", l_socket_create}, + {"create_and_connect", l_socket_create_and_connect}, + {NULL, NULL} +}; + +//////////////////////////////////////////////////////////////////////////////// + +// Check/enforce inheritance +static void add_to_group(lua_State *L, + const char *metatablename, + const char *groupname) { + luaL_getmetatable(L, metatablename); // mt + lua_pushstring(L, groupname); // mt, "name" + lua_pushboolean(L, 1); // mt, "name", true + lua_rawset(L, -3); // mt + lua_pop(L, 1); +} + +static void set_methods(lua_State *L, + const char *metatablename, + const struct luaL_Reg *methods) { + luaL_getmetatable(L, metatablename); // mt + // Create the __index table + lua_pushstring(L, "__index"); // mt, "__index" + lua_newtable(L); // mt, "__index", t + for (; methods->name; methods++) { + lua_pushstring(L, methods->name); // mt, "__index", t, "name" + lua_pushcfunction(L, methods->func); // mt, "__index", t, "name", func + lua_rawset(L, -3); // mt, "__index", t + } + lua_rawset(L, -3); // mt + lua_pop(L, 1); +} + +int luaopen_libluasocket(lua_State *L) { + luaL_newmetatable(L, SOCKET_GENERIC); + luaL_newmetatable(L, SOCKET_CLIENT); + luaL_newmetatable(L, SOCKET_SERVER); + lua_pop(L, 3); + add_to_group(L, SOCKET_GENERIC, SOCKET_ANY); + add_to_group(L, SOCKET_CLIENT, SOCKET_ANY); + add_to_group(L, SOCKET_SERVER, SOCKET_ANY); + add_to_group(L, SOCKET_CLIENT, SOCKET_CONN); + add_to_group(L, SOCKET_SERVER, SOCKET_CONN); + set_methods(L, SOCKET_GENERIC, methods_generic); + set_methods(L, SOCKET_CLIENT, methods_client); + set_methods(L, SOCKET_SERVER, methods_server); + + luaL_register(L, "luasocket", funcs_luasocket); + return 1; +} + +//////////////////////////////////////////////////////////////////////////////// +// General + +// sock,err create(bind_host, bind_port) +// sock,err create(bind_host) -> any port +// sock,err create() -> any port on localhost +static int l_socket_create(lua_State *L) { + const char *err; + t_socket sock; + const char *addr = lua_tostring(L, 1); + if (!addr) { + addr = DEFAULT_HOST; + } + unsigned short port = lua_tonumber(L, 2); + err = tcp_create(&sock); + if (!err) { + err = tcp_bind(&sock, addr, port); // bind on create + if (err) { + tcp_destroy(&sock); + } else { + p_tcp tcp = (p_tcp) lua_newuserdata(L, sizeof(t_tcp)); + settype(L, -2, SOCKET_GENERIC); + socket_setnonblocking(&sock); + tcp->sock = sock; + tcp->timeout = 0; + return 1; // Return userdata + } + } + LUA_CHECK_RETURN(L, err); +} + +// destroy() +static int l_socket_destroy(lua_State *L) { + p_tcp tcp = (p_tcp) checktype(L, 1, SOCKET_ANY); + const char *err = tcp_destroy(&tcp->sock); + LUA_CHECK_RETURN(L, err); +} + +// send(socket, data) +static int l_socket_send(lua_State *L) { + p_tcp self = (p_tcp) checktype(L, 1, SOCKET_CONN); + p_tcp tcp = (p_tcp) checktype(L, 2, SOCKET_CONN); + size_t len; + const char *data = luaL_checklstring(L, 3, &len); + const char *err = + tcp_send(&tcp->sock, data, len, tcp->timeout); + LUA_CHECK_RETURN(L, err); +} + +#define LUA_READ_STEP 8192 +static int l_socket_receive(lua_State *L) { + p_tcp self = (p_tcp) checktype(L, 1, SOCKET_CONN); + p_tcp handle = (p_tcp) checktype(L, 2, SOCKET_CONN); + size_t len = luaL_checknumber(L, 3); + char buf[LUA_READ_STEP]; + const char *err = NULL; + int received; + size_t got = 0, step = 0; + luaL_Buffer b; + + luaL_buffinit(L, &b); + do { + step = (LUA_READ_STEP < len - got ? LUA_READ_STEP : len - got); + err = tcp_raw_receive(&handle->sock, buf, step, self->timeout, &received); + if (err == NULL) { + luaL_addlstring(&b, buf, received); + got += received; + } + } while (err == NULL && got < len); + + if (err) { + lua_pushnil(L); + lua_pushstring(L, err); + return 2; + } + luaL_pushresult(&b); + return 1; +} + +// settimeout(timeout) +static int l_socket_settimeout(lua_State *L) { + p_tcp self = (p_tcp) checktype(L, 1, SOCKET_ANY); + int timeout = luaL_checknumber(L, 2); + self->timeout = timeout; + LUA_SUCCESS_RETURN(L); +} + +// table getsockinfo() +static int l_socket_getsockinfo(lua_State *L) { + char buf[256]; + short port = 0; + p_tcp tcp = (p_tcp) checktype(L, 1, SOCKET_ANY); + if (socket_get_info(&tcp->sock, &port, buf, 256) == SUCCESS) { + lua_newtable(L); // t + lua_pushstring(L, "host"); // t, "host" + lua_pushstring(L, buf); // t, "host", buf + lua_rawset(L, -3); // t + lua_pushstring(L, "port"); // t, "port" + lua_pushnumber(L, port); // t, "port", port + lua_rawset(L, -3); // t + return 1; + } + return 0; +} + +//////////////////////////////////////////////////////////////////////////////// +// Server + +// accept() +static int l_socket_accept(lua_State *L) { + const char *err; + p_tcp self = (p_tcp) checktype(L, 1, SOCKET_SERVER); + t_socket sock; + err = tcp_accept(&self->sock, &sock, self->timeout); + if (!err) { // Success + // Create a reference to the client + p_tcp client = (p_tcp) lua_newuserdata(L, sizeof(t_tcp)); + settype(L, 2, SOCKET_CLIENT); + socket_setnonblocking(&sock); + client->sock = sock; + client->timeout = self->timeout; + return 1; + } + LUA_CHECK_RETURN(L, err); +} + +static int l_socket_listen(lua_State *L) { + const char* err; + p_tcp tcp = (p_tcp) checktype(L, 1, SOCKET_GENERIC); + int backlog = 10; + err = tcp_listen(&tcp->sock, backlog); + if (!err) { + // Set the current as a server + settype(L, 1, SOCKET_SERVER); // Now a server + } + LUA_CHECK_RETURN(L, err); +} + +//////////////////////////////////////////////////////////////////////////////// +// Client + +// create_and_connect(host, port, timeout) +extern double __gettime(); +static int l_socket_create_and_connect(lua_State *L) { + const char* err = NULL; + double end; + t_socket sock; + const char *host = luaL_checkstring(L, 1); + unsigned short port = luaL_checknumber(L, 2); + int timeout = luaL_checknumber(L, 3); + + // Create and connect loop for timeout milliseconds + end = __gettime() + timeout/1000; + do { + // Create the socket + err = tcp_create(&sock); + if (!err) { + // Connect + err = tcp_connect(&sock, host, port, timeout); + if (err) { + tcp_destroy(&sock); + usleep(100000); // sleep for 100ms + } else { + p_tcp tcp = (p_tcp) lua_newuserdata(L, sizeof(t_tcp)); + settype(L, -2, SOCKET_CLIENT); + socket_setnonblocking(&sock); + tcp->sock = sock; + tcp->timeout = timeout; + return 1; // Return userdata + } + } + } while (err && __gettime() < end); + + LUA_CHECK_RETURN(L, err); +} + +// connect(host, port) +static int l_socket_connect(lua_State *L) { + const char *err; + p_tcp tcp = (p_tcp) checktype(L, 1, SOCKET_GENERIC); + const char *host = luaL_checkstring(L, 2); + unsigned short port = luaL_checknumber(L, 3); + err = tcp_connect(&tcp->sock, host, port, tcp->timeout); + if (!err) { + settype(L, 1, SOCKET_CLIENT); // Now a client + } + LUA_CHECK_RETURN(L, err); +} diff --git a/vendor/github.com/apache/thrift/lib/lua/src/socket.h b/vendor/github.com/apache/thrift/lib/lua/src/socket.h new file mode 100644 index 000000000..8019ffed8 --- /dev/null +++ b/vendor/github.com/apache/thrift/lib/lua/src/socket.h @@ -0,0 +1,78 @@ +// +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT 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 LUA_THRIFT_SOCKET_H +#define LUA_THRIFT_SOCKET_H + +#include + +#ifdef _WIN32 +// SOL +#else +typedef int t_socket; +typedef t_socket* p_socket; +#endif + +// Error Codes +enum { + SUCCESS = 0, + TIMEOUT = -1, + CLOSED = -2, +}; +typedef int T_ERRCODE; + +static const char * TIMEOUT_MSG = "Timeout"; +static const char * CLOSED_MSG = "Connection Closed"; + +typedef struct sockaddr t_sa; +typedef t_sa * p_sa; + +T_ERRCODE socket_create(p_socket sock, int domain, int type, int protocol); +T_ERRCODE socket_destroy(p_socket sock); +T_ERRCODE socket_bind(p_socket sock, p_sa addr, int addr_len); +T_ERRCODE socket_get_info(p_socket sock, short *port, char *buf, size_t len); +T_ERRCODE socket_send(p_socket sock, const char *data, size_t len, int timeout); +T_ERRCODE socket_recv(p_socket sock, char *data, size_t len, int timeout, + int *received); + +void socket_setblocking(p_socket sock); +void socket_setnonblocking(p_socket sock); + +T_ERRCODE socket_accept(p_socket sock, p_socket sibling, + p_sa addr, socklen_t *addr_len, int timeout); +T_ERRCODE socket_listen(p_socket sock, int backlog); + +T_ERRCODE socket_connect(p_socket sock, p_sa addr, int addr_len, int timeout); + +const char * tcp_create(p_socket sock); +const char * tcp_destroy(p_socket sock); +const char * tcp_bind(p_socket sock, const char *host, unsigned short port); +const char * tcp_send(p_socket sock, const char *data, size_t w_len, + int timeout); +const char * tcp_receive(p_socket sock, char *data, size_t r_len, int timeout); +const char * tcp_raw_receive(p_socket sock, char * data, size_t r_len, + int timeout, int *received); + +const char * tcp_listen(p_socket sock, int backlog); +const char * tcp_accept(p_socket sock, p_socket client, int timeout); + +const char * tcp_connect(p_socket sock, const char *host, unsigned short port, + int timeout); + +#endif diff --git a/vendor/github.com/apache/thrift/lib/lua/src/usocket.c b/vendor/github.com/apache/thrift/lib/lua/src/usocket.c new file mode 100644 index 000000000..864fa3654 --- /dev/null +++ b/vendor/github.com/apache/thrift/lib/lua/src/usocket.c @@ -0,0 +1,370 @@ +// +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT 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 +#include +#include +#include +#include +#include +#include +#include + +#include // TODO REMOVE + +#include "socket.h" + +//////////////////////////////////////////////////////////////////////////////// +// Private + +// Num seconds since Jan 1 1970 (UTC) +#ifdef _WIN32 +// SOL +#else + double __gettime() { + struct timeval v; + gettimeofday(&v, (struct timezone*) NULL); + return v.tv_sec + v.tv_usec/1.0e6; + } +#endif + +#define WAIT_MODE_R 1 +#define WAIT_MODE_W 2 +#define WAIT_MODE_C (WAIT_MODE_R|WAIT_MODE_W) +T_ERRCODE socket_wait(p_socket sock, int mode, int timeout) { + int ret = 0; + fd_set rfds, wfds; + struct timeval tv; + double end, t; + if (!timeout) { + return TIMEOUT; + } + + end = __gettime() + timeout/1000; + do { + FD_ZERO(&rfds); + FD_ZERO(&wfds); + + // Specify what I/O operations we care about + if (mode & WAIT_MODE_R) { + FD_SET(*sock, &rfds); + } + if (mode & WAIT_MODE_W) { + FD_SET(*sock, &wfds); + } + + // Check for timeout + t = end - __gettime(); + if (t < 0.0) { + break; + } + + // Wait + tv.tv_sec = (int)t; + tv.tv_usec = (int)((t - tv.tv_sec) * 1.0e6); + ret = select(*sock+1, &rfds, &wfds, NULL, &tv); + } while (ret == -1 && errno == EINTR); + if (ret == -1) { + return errno; + } + + // Check for timeout + if (ret == 0) { + return TIMEOUT; + } + + // Verify that we can actually read from the remote host + if (mode & WAIT_MODE_C && FD_ISSET(*sock, &rfds) && + recv(*sock, (char*) &rfds, 0, 0) != 0) { + return errno; + } + + return SUCCESS; +} + +//////////////////////////////////////////////////////////////////////////////// +// General + +T_ERRCODE socket_create(p_socket sock, int domain, int type, int protocol) { + *sock = socket(domain, type, protocol); + if (*sock > 0) { + return SUCCESS; + } else { + return errno; + } +} + +T_ERRCODE socket_destroy(p_socket sock) { + // TODO Figure out if I should be free-ing this + if (*sock > 0) { + socket_setblocking(sock); + close(*sock); + *sock = -1; + } + return SUCCESS; +} + +T_ERRCODE socket_bind(p_socket sock, p_sa addr, int addr_len) { + int ret = SUCCESS; + socket_setblocking(sock); + if (bind(*sock, addr, addr_len)) { + ret = errno; + } + socket_setnonblocking(sock); + return ret; +} + +T_ERRCODE socket_get_info(p_socket sock, short *port, char *buf, size_t len) { + struct sockaddr_storage sa; + memset(&sa, 0, sizeof(sa)); + socklen_t addrlen = sizeof(sa); + int rc = getsockname(*sock, (struct sockaddr*)&sa, &addrlen); + if (!rc) { + if (sa.ss_family == AF_INET6) { + struct sockaddr_in6* sin = (struct sockaddr_in6*)(&sa); + if (!inet_ntop(AF_INET6, &sin->sin6_addr, buf, len)) { + return errno; + } + *port = ntohs(sin->sin6_port); + } else { + struct sockaddr_in* sin = (struct sockaddr_in*)(&sa); + if (!inet_ntop(AF_INET, &sin->sin_addr, buf, len)) { + return errno; + } + *port = ntohs(sin->sin_port); + } + return SUCCESS; + } + return errno; +} + +//////////////////////////////////////////////////////////////////////////////// +// Server + +T_ERRCODE socket_accept(p_socket sock, p_socket client, + p_sa addr, socklen_t *addrlen, int timeout) { + int err; + if (*sock < 0) { + return CLOSED; + } + do { + *client = accept(*sock, addr, addrlen); + if (*client > 0) { + return SUCCESS; + } + err = errno; + } while (err != EINTR); + if (err == EAGAIN || err == ECONNABORTED) { + return socket_wait(sock, WAIT_MODE_R, timeout); + } + return err; +} + +T_ERRCODE socket_listen(p_socket sock, int backlog) { + int ret = SUCCESS; + socket_setblocking(sock); + if (listen(*sock, backlog)) { + ret = errno; + } + socket_setnonblocking(sock); + return ret; +} + +//////////////////////////////////////////////////////////////////////////////// +// Client + +T_ERRCODE socket_connect(p_socket sock, p_sa addr, int addr_len, int timeout) { + int err; + if (*sock < 0) { + return CLOSED; + } + + do { + if (connect(*sock, addr, addr_len) == 0) { + return SUCCESS; + } + } while ((err = errno) == EINTR); + if (err != EINPROGRESS && err != EAGAIN) { + return err; + } + return socket_wait(sock, WAIT_MODE_C, timeout); +} + +T_ERRCODE socket_send( + p_socket sock, const char *data, size_t len, int timeout) { + int err, put = 0; + if (*sock < 0) { + return CLOSED; + } + do { + put = send(*sock, data, len, 0); + if (put > 0) { + return SUCCESS; + } + err = errno; + } while (err != EINTR); + + if (err == EAGAIN) { + return socket_wait(sock, WAIT_MODE_W, timeout); + } + return err; +} + +T_ERRCODE socket_recv( + p_socket sock, char *data, size_t len, int timeout, int *received) { + int err, got = 0; + if (*sock < 0) { + return CLOSED; + } + + int flags = fcntl(*sock, F_GETFL, 0); + do { + got = recv(*sock, data, len, 0); + if (got > 0) { + *received = got; + return SUCCESS; + } + err = errno; + + // Connection has been closed by peer + if (got == 0) { + return CLOSED; + } + } while (err != EINTR); + + if (err == EAGAIN) { + return socket_wait(sock, WAIT_MODE_R, timeout); + } + return err; +} + +//////////////////////////////////////////////////////////////////////////////// +// Util + +void socket_setnonblocking(p_socket sock) { + int flags = fcntl(*sock, F_GETFL, 0); + flags |= O_NONBLOCK; + fcntl(*sock, F_SETFL, flags); +} + +void socket_setblocking(p_socket sock) { + int flags = fcntl(*sock, F_GETFL, 0); + flags &= (~(O_NONBLOCK)); + fcntl(*sock, F_SETFL, flags); +} + +//////////////////////////////////////////////////////////////////////////////// +// TCP + +#define ERRORSTR_RETURN(err) \ + if (err == SUCCESS) { \ + return NULL; \ + } else if (err == TIMEOUT) { \ + return TIMEOUT_MSG; \ + } else if (err == CLOSED) { \ + return CLOSED_MSG; \ + } \ + return strerror(err) + +const char * tcp_create(p_socket sock) { + int err = socket_create(sock, AF_INET, SOCK_STREAM, 0); + ERRORSTR_RETURN(err); +} + +const char * tcp_destroy(p_socket sock) { + int err = socket_destroy(sock); + ERRORSTR_RETURN(err); +} + +const char * tcp_bind(p_socket sock, const char *host, unsigned short port) { + int err; + struct hostent *h; + struct sockaddr_in local; + memset(&local, 0, sizeof(local)); + local.sin_family = AF_INET; + local.sin_addr.s_addr = htonl(INADDR_ANY); + local.sin_port = htons(port); + if (strcmp(host, "*") && !inet_aton(host, &local.sin_addr)) { + h = gethostbyname(host); + if (!h) { + return hstrerror(h_errno); + } + memcpy(&local.sin_addr, + (struct in_addr *)h->h_addr_list[0], + sizeof(struct in_addr)); + } + err = socket_bind(sock, (p_sa) &local, sizeof(local)); + ERRORSTR_RETURN(err); +} + +const char * tcp_listen(p_socket sock, int backlog) { + int err = socket_listen(sock, backlog); + ERRORSTR_RETURN(err); +} + +const char * tcp_accept(p_socket sock, p_socket client, int timeout) { + int err = socket_accept(sock, client, NULL, NULL, timeout); + ERRORSTR_RETURN(err); +} + +const char * tcp_connect(p_socket sock, + const char *host, + unsigned short port, + int timeout) { + int err; + struct hostent *h; + struct sockaddr_in remote; + memset(&remote, 0, sizeof(remote)); + remote.sin_family = AF_INET; + remote.sin_port = htons(port); + if (strcmp(host, "*") && !inet_aton(host, &remote.sin_addr)) { + h = gethostbyname(host); + if (!h) { + return hstrerror(h_errno); + } + memcpy(&remote.sin_addr, + (struct in_addr *)h->h_addr_list[0], + sizeof(struct in_addr)); + } + err = socket_connect(sock, (p_sa) &remote, sizeof(remote), timeout); + ERRORSTR_RETURN(err); +} + +#define WRITE_STEP 8192 +const char * tcp_send( + p_socket sock, const char * data, size_t w_len, int timeout) { + int err; + size_t put = 0, step; + if (!w_len) { + return NULL; + } + + do { + step = (WRITE_STEP < w_len - put ? WRITE_STEP : w_len - put); + err = socket_send(sock, data + put, step, timeout); + put += step; + } while (err == SUCCESS && put < w_len); + ERRORSTR_RETURN(err); +} + +const char * tcp_raw_receive( + p_socket sock, char * data, size_t r_len, int timeout, int *received) { + int err = socket_recv(sock, data, r_len, timeout, received); + ERRORSTR_RETURN(err); +} diff --git a/vendor/github.com/apache/thrift/lib/py/README.md b/vendor/github.com/apache/thrift/lib/py/README.md new file mode 100644 index 000000000..29b8c73c4 --- /dev/null +++ b/vendor/github.com/apache/thrift/lib/py/README.md @@ -0,0 +1,35 @@ +Thrift Python Software Library + +License +======= + +Licensed to the Apache Software Foundation (ASF) under one +or more contributor license agreements. See the NOTICE file +distributed with this work for additional information +regarding copyright ownership. The ASF licenses this file +to you under the Apache License, Version 2.0 (the +"License"); you may not use this file except in compliance +with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, +software distributed under the License is distributed on an +"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +KIND, either express or implied. See the License for the +specific language governing permissions and limitations +under the License. + +Using Thrift with Python +======================== + +Thrift is provided as a set of Python packages. The top level package is +thrift, and there are subpackages for the protocol, transport, and server +code. Each package contains modules using standard Thrift naming conventions +(i.e. TProtocol, TTransport) and implementations in corresponding modules +(i.e. TSocket). There is also a subpackage reflection, which contains +the generated code for the reflection structures. + +The Python libraries can be installed manually using the provided setup.py +file, or automatically using the install hook provided via autoconf/automake. +To use the latter, become superuser and do make install. diff --git a/vendor/github.com/apache/thrift/lib/py/compat/win32/stdint.h b/vendor/github.com/apache/thrift/lib/py/compat/win32/stdint.h new file mode 100644 index 000000000..d02608a59 --- /dev/null +++ b/vendor/github.com/apache/thrift/lib/py/compat/win32/stdint.h @@ -0,0 +1,247 @@ +// ISO C9x compliant stdint.h for Microsoft Visual Studio +// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124 +// +// Copyright (c) 2006-2008 Alexander Chemeris +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// 3. The name of the author may be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED +// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO +// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef _MSC_VER // [ +#error "Use this header only with Microsoft Visual C++ compilers!" +#endif // _MSC_VER ] + +#ifndef _MSC_STDINT_H_ // [ +#define _MSC_STDINT_H_ + +#if _MSC_VER > 1000 +#pragma once +#endif + +#include + +// For Visual Studio 6 in C++ mode and for many Visual Studio versions when +// compiling for ARM we should wrap include with 'extern "C++" {}' +// or compiler give many errors like this: +// error C2733: second C linkage of overloaded function 'wmemchr' not allowed +#ifdef __cplusplus +extern "C" { +#endif +# include +#ifdef __cplusplus +} +#endif + +// Define _W64 macros to mark types changing their size, like intptr_t. +#ifndef _W64 +# if !defined(__midl) && (defined(_X86_) || defined(_M_IX86)) && _MSC_VER >= 1300 +# define _W64 __w64 +# else +# define _W64 +# endif +#endif + + +// 7.18.1 Integer types + +// 7.18.1.1 Exact-width integer types + +// Visual Studio 6 and Embedded Visual C++ 4 doesn't +// realize that, e.g. char has the same size as __int8 +// so we give up on __intX for them. +#if (_MSC_VER < 1300) + typedef signed char int8_t; + typedef signed short int16_t; + typedef signed int int32_t; + typedef unsigned char uint8_t; + typedef unsigned short uint16_t; + typedef unsigned int uint32_t; +#else + typedef signed __int8 int8_t; + typedef signed __int16 int16_t; + typedef signed __int32 int32_t; + typedef unsigned __int8 uint8_t; + typedef unsigned __int16 uint16_t; + typedef unsigned __int32 uint32_t; +#endif +typedef signed __int64 int64_t; +typedef unsigned __int64 uint64_t; + + +// 7.18.1.2 Minimum-width integer types +typedef int8_t int_least8_t; +typedef int16_t int_least16_t; +typedef int32_t int_least32_t; +typedef int64_t int_least64_t; +typedef uint8_t uint_least8_t; +typedef uint16_t uint_least16_t; +typedef uint32_t uint_least32_t; +typedef uint64_t uint_least64_t; + +// 7.18.1.3 Fastest minimum-width integer types +typedef int8_t int_fast8_t; +typedef int16_t int_fast16_t; +typedef int32_t int_fast32_t; +typedef int64_t int_fast64_t; +typedef uint8_t uint_fast8_t; +typedef uint16_t uint_fast16_t; +typedef uint32_t uint_fast32_t; +typedef uint64_t uint_fast64_t; + +// 7.18.1.4 Integer types capable of holding object pointers +#ifdef _WIN64 // [ + typedef signed __int64 intptr_t; + typedef unsigned __int64 uintptr_t; +#else // _WIN64 ][ + typedef _W64 signed int intptr_t; + typedef _W64 unsigned int uintptr_t; +#endif // _WIN64 ] + +// 7.18.1.5 Greatest-width integer types +typedef int64_t intmax_t; +typedef uint64_t uintmax_t; + + +// 7.18.2 Limits of specified-width integer types + +#if !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS) // [ See footnote 220 at page 257 and footnote 221 at page 259 + +// 7.18.2.1 Limits of exact-width integer types +#define INT8_MIN ((int8_t)_I8_MIN) +#define INT8_MAX _I8_MAX +#define INT16_MIN ((int16_t)_I16_MIN) +#define INT16_MAX _I16_MAX +#define INT32_MIN ((int32_t)_I32_MIN) +#define INT32_MAX _I32_MAX +#define INT64_MIN ((int64_t)_I64_MIN) +#define INT64_MAX _I64_MAX +#define UINT8_MAX _UI8_MAX +#define UINT16_MAX _UI16_MAX +#define UINT32_MAX _UI32_MAX +#define UINT64_MAX _UI64_MAX + +// 7.18.2.2 Limits of minimum-width integer types +#define INT_LEAST8_MIN INT8_MIN +#define INT_LEAST8_MAX INT8_MAX +#define INT_LEAST16_MIN INT16_MIN +#define INT_LEAST16_MAX INT16_MAX +#define INT_LEAST32_MIN INT32_MIN +#define INT_LEAST32_MAX INT32_MAX +#define INT_LEAST64_MIN INT64_MIN +#define INT_LEAST64_MAX INT64_MAX +#define UINT_LEAST8_MAX UINT8_MAX +#define UINT_LEAST16_MAX UINT16_MAX +#define UINT_LEAST32_MAX UINT32_MAX +#define UINT_LEAST64_MAX UINT64_MAX + +// 7.18.2.3 Limits of fastest minimum-width integer types +#define INT_FAST8_MIN INT8_MIN +#define INT_FAST8_MAX INT8_MAX +#define INT_FAST16_MIN INT16_MIN +#define INT_FAST16_MAX INT16_MAX +#define INT_FAST32_MIN INT32_MIN +#define INT_FAST32_MAX INT32_MAX +#define INT_FAST64_MIN INT64_MIN +#define INT_FAST64_MAX INT64_MAX +#define UINT_FAST8_MAX UINT8_MAX +#define UINT_FAST16_MAX UINT16_MAX +#define UINT_FAST32_MAX UINT32_MAX +#define UINT_FAST64_MAX UINT64_MAX + +// 7.18.2.4 Limits of integer types capable of holding object pointers +#ifdef _WIN64 // [ +# define INTPTR_MIN INT64_MIN +# define INTPTR_MAX INT64_MAX +# define UINTPTR_MAX UINT64_MAX +#else // _WIN64 ][ +# define INTPTR_MIN INT32_MIN +# define INTPTR_MAX INT32_MAX +# define UINTPTR_MAX UINT32_MAX +#endif // _WIN64 ] + +// 7.18.2.5 Limits of greatest-width integer types +#define INTMAX_MIN INT64_MIN +#define INTMAX_MAX INT64_MAX +#define UINTMAX_MAX UINT64_MAX + +// 7.18.3 Limits of other integer types + +#ifdef _WIN64 // [ +# define PTRDIFF_MIN _I64_MIN +# define PTRDIFF_MAX _I64_MAX +#else // _WIN64 ][ +# define PTRDIFF_MIN _I32_MIN +# define PTRDIFF_MAX _I32_MAX +#endif // _WIN64 ] + +#define SIG_ATOMIC_MIN INT_MIN +#define SIG_ATOMIC_MAX INT_MAX + +#ifndef SIZE_MAX // [ +# ifdef _WIN64 // [ +# define SIZE_MAX _UI64_MAX +# else // _WIN64 ][ +# define SIZE_MAX _UI32_MAX +# endif // _WIN64 ] +#endif // SIZE_MAX ] + +// WCHAR_MIN and WCHAR_MAX are also defined in +#ifndef WCHAR_MIN // [ +# define WCHAR_MIN 0 +#endif // WCHAR_MIN ] +#ifndef WCHAR_MAX // [ +# define WCHAR_MAX _UI16_MAX +#endif // WCHAR_MAX ] + +#define WINT_MIN 0 +#define WINT_MAX _UI16_MAX + +#endif // __STDC_LIMIT_MACROS ] + + +// 7.18.4 Limits of other integer types + +#if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) // [ See footnote 224 at page 260 + +// 7.18.4.1 Macros for minimum-width integer constants + +#define INT8_C(val) val##i8 +#define INT16_C(val) val##i16 +#define INT32_C(val) val##i32 +#define INT64_C(val) val##i64 + +#define UINT8_C(val) val##ui8 +#define UINT16_C(val) val##ui16 +#define UINT32_C(val) val##ui32 +#define UINT64_C(val) val##ui64 + +// 7.18.4.2 Macros for greatest-width integer constants +#define INTMAX_C INT64_C +#define UINTMAX_C UINT64_C + +#endif // __STDC_CONSTANT_MACROS ] + + +#endif // _MSC_STDINT_H_ ] diff --git a/vendor/github.com/apache/thrift/lib/rb/README.md b/vendor/github.com/apache/thrift/lib/rb/README.md new file mode 100644 index 000000000..b6e9a0792 --- /dev/null +++ b/vendor/github.com/apache/thrift/lib/rb/README.md @@ -0,0 +1,43 @@ +Thrift Ruby Software Library + http://thrift.apache.org + +== LICENSE: + +Licensed to the Apache Software Foundation (ASF) under one +or more contributor license agreements. See the NOTICE file +distributed with this work for additional information +regarding copyright ownership. The ASF licenses this file +to you under the Apache License, Version 2.0 (the +"License"); you may not use this file except in compliance +with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, +software distributed under the License is distributed on an +"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +KIND, either express or implied. See the License for the +specific language governing permissions and limitations +under the License. + +== DESCRIPTION: + +Thrift is a strongly-typed language-agnostic RPC system. +This library is the ruby implementation for both clients and servers. + +== INSTALL: + + $ gem install thrift + +== CAVEATS: + +This library provides the client and server implementations of thrift. +It does not provide the compiler for the .thrift files. To compile +.thrift files into language-specific implementations, please download the full +thrift software package. + +== USAGE: + +This section should get written by someone with the time and inclination. +In the meantime, look at existing code, such as the benchmark or the tutorial +in the full thrift distribution. diff --git a/vendor/github.com/apache/thrift/lib/rb/ext/binary_protocol_accelerated.c b/vendor/github.com/apache/thrift/lib/rb/ext/binary_protocol_accelerated.c new file mode 100644 index 000000000..65cbe5ffe --- /dev/null +++ b/vendor/github.com/apache/thrift/lib/rb/ext/binary_protocol_accelerated.c @@ -0,0 +1,460 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT 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 +#include +#include +#include +#include +#include +#include + +VALUE rb_thrift_binary_proto_native_qmark(VALUE self) { + return Qtrue; +} + + + +static int VERSION_1; +static int VERSION_MASK; +static int TYPE_MASK; +static int BAD_VERSION; +static ID rbuf_ivar_id; + +static void write_byte_direct(VALUE trans, int8_t b) { + WRITE(trans, (char*)&b, 1); +} + +static void write_i16_direct(VALUE trans, int16_t value) { + char data[2]; + + data[1] = value; + data[0] = (value >> 8); + + WRITE(trans, data, 2); +} + +static void write_i32_direct(VALUE trans, int32_t value) { + char data[4]; + + data[3] = value; + data[2] = (value >> 8); + data[1] = (value >> 16); + data[0] = (value >> 24); + + WRITE(trans, data, 4); +} + + +static void write_i64_direct(VALUE trans, int64_t value) { + char data[8]; + + data[7] = value; + data[6] = (value >> 8); + data[5] = (value >> 16); + data[4] = (value >> 24); + data[3] = (value >> 32); + data[2] = (value >> 40); + data[1] = (value >> 48); + data[0] = (value >> 56); + + WRITE(trans, data, 8); +} + +static void write_string_direct(VALUE trans, VALUE str) { + if (TYPE(str) != T_STRING) { + rb_raise(rb_eStandardError, "Value should be a string"); + } + str = convert_to_utf8_byte_buffer(str); + write_i32_direct(trans, RSTRING_LEN(str)); + rb_funcall(trans, write_method_id, 1, str); +} + +//-------------------------------- +// interface writing methods +//-------------------------------- + +VALUE rb_thrift_binary_proto_write_message_end(VALUE self) { + return Qnil; +} + +VALUE rb_thrift_binary_proto_write_struct_begin(VALUE self, VALUE name) { + return Qnil; +} + +VALUE rb_thrift_binary_proto_write_struct_end(VALUE self) { + return Qnil; +} + +VALUE rb_thrift_binary_proto_write_field_end(VALUE self) { + return Qnil; +} + +VALUE rb_thrift_binary_proto_write_map_end(VALUE self) { + return Qnil; +} + +VALUE rb_thrift_binary_proto_write_list_end(VALUE self) { + return Qnil; +} + +VALUE rb_thrift_binary_proto_write_set_end(VALUE self) { + return Qnil; +} + +VALUE rb_thrift_binary_proto_write_message_begin(VALUE self, VALUE name, VALUE type, VALUE seqid) { + VALUE trans = GET_TRANSPORT(self); + VALUE strict_write = GET_STRICT_WRITE(self); + + if (strict_write == Qtrue) { + write_i32_direct(trans, VERSION_1 | FIX2INT(type)); + write_string_direct(trans, name); + write_i32_direct(trans, FIX2INT(seqid)); + } else { + write_string_direct(trans, name); + write_byte_direct(trans, FIX2INT(type)); + write_i32_direct(trans, FIX2INT(seqid)); + } + + return Qnil; +} + +VALUE rb_thrift_binary_proto_write_field_begin(VALUE self, VALUE name, VALUE type, VALUE id) { + VALUE trans = GET_TRANSPORT(self); + write_byte_direct(trans, FIX2INT(type)); + write_i16_direct(trans, FIX2INT(id)); + + return Qnil; +} + +VALUE rb_thrift_binary_proto_write_field_stop(VALUE self) { + write_byte_direct(GET_TRANSPORT(self), TTYPE_STOP); + return Qnil; +} + +VALUE rb_thrift_binary_proto_write_map_begin(VALUE self, VALUE ktype, VALUE vtype, VALUE size) { + VALUE trans = GET_TRANSPORT(self); + write_byte_direct(trans, FIX2INT(ktype)); + write_byte_direct(trans, FIX2INT(vtype)); + write_i32_direct(trans, FIX2INT(size)); + + return Qnil; +} + +VALUE rb_thrift_binary_proto_write_list_begin(VALUE self, VALUE etype, VALUE size) { + VALUE trans = GET_TRANSPORT(self); + write_byte_direct(trans, FIX2INT(etype)); + write_i32_direct(trans, FIX2INT(size)); + + return Qnil; +} + +VALUE rb_thrift_binary_proto_write_set_begin(VALUE self, VALUE etype, VALUE size) { + rb_thrift_binary_proto_write_list_begin(self, etype, size); + return Qnil; +} + +VALUE rb_thrift_binary_proto_write_bool(VALUE self, VALUE b) { + write_byte_direct(GET_TRANSPORT(self), RTEST(b) ? 1 : 0); + return Qnil; +} + +VALUE rb_thrift_binary_proto_write_byte(VALUE self, VALUE byte) { + CHECK_NIL(byte); + write_byte_direct(GET_TRANSPORT(self), NUM2INT(byte)); + return Qnil; +} + +VALUE rb_thrift_binary_proto_write_i16(VALUE self, VALUE i16) { + CHECK_NIL(i16); + write_i16_direct(GET_TRANSPORT(self), FIX2INT(i16)); + return Qnil; +} + +VALUE rb_thrift_binary_proto_write_i32(VALUE self, VALUE i32) { + CHECK_NIL(i32); + write_i32_direct(GET_TRANSPORT(self), NUM2INT(i32)); + return Qnil; +} + +VALUE rb_thrift_binary_proto_write_i64(VALUE self, VALUE i64) { + CHECK_NIL(i64); + write_i64_direct(GET_TRANSPORT(self), NUM2LL(i64)); + return Qnil; +} + +VALUE rb_thrift_binary_proto_write_double(VALUE self, VALUE dub) { + CHECK_NIL(dub); + // Unfortunately, bitwise_cast doesn't work in C. Bad C! + union { + double f; + int64_t t; + } transfer; + transfer.f = RFLOAT_VALUE(rb_Float(dub)); + write_i64_direct(GET_TRANSPORT(self), transfer.t); + + return Qnil; +} + +VALUE rb_thrift_binary_proto_write_string(VALUE self, VALUE str) { + CHECK_NIL(str); + VALUE trans = GET_TRANSPORT(self); + write_string_direct(trans, str); + return Qnil; +} + +VALUE rb_thrift_binary_proto_write_binary(VALUE self, VALUE buf) { + CHECK_NIL(buf); + VALUE trans = GET_TRANSPORT(self); + buf = force_binary_encoding(buf); + write_i32_direct(trans, RSTRING_LEN(buf)); + rb_funcall(trans, write_method_id, 1, buf); + return Qnil; +} + +//--------------------------------------- +// interface reading methods +//--------------------------------------- + +VALUE rb_thrift_binary_proto_read_string(VALUE self); +VALUE rb_thrift_binary_proto_read_binary(VALUE self); +VALUE rb_thrift_binary_proto_read_byte(VALUE self); +VALUE rb_thrift_binary_proto_read_i32(VALUE self); +VALUE rb_thrift_binary_proto_read_i16(VALUE self); + +static char read_byte_direct(VALUE self) { + VALUE byte = rb_funcall(GET_TRANSPORT(self), read_byte_method_id, 0); + return (char)(FIX2INT(byte)); +} + +static int16_t read_i16_direct(VALUE self) { + VALUE rbuf = rb_ivar_get(self, rbuf_ivar_id); + rb_funcall(GET_TRANSPORT(self), read_into_buffer_method_id, 2, rbuf, INT2FIX(2)); + return (int16_t)(((uint8_t)(RSTRING_PTR(rbuf)[1])) | ((uint16_t)((RSTRING_PTR(rbuf)[0]) << 8))); +} + +static int32_t read_i32_direct(VALUE self) { + VALUE rbuf = rb_ivar_get(self, rbuf_ivar_id); + rb_funcall(GET_TRANSPORT(self), read_into_buffer_method_id, 2, rbuf, INT2FIX(4)); + return ((uint8_t)(RSTRING_PTR(rbuf)[3])) | + (((uint8_t)(RSTRING_PTR(rbuf)[2])) << 8) | + (((uint8_t)(RSTRING_PTR(rbuf)[1])) << 16) | + (((uint8_t)(RSTRING_PTR(rbuf)[0])) << 24); +} + +static int64_t read_i64_direct(VALUE self) { + VALUE rbuf = rb_ivar_get(self, rbuf_ivar_id); + rb_funcall(GET_TRANSPORT(self), read_into_buffer_method_id, 2, rbuf, INT2FIX(8)); + uint64_t hi = ((uint8_t)(RSTRING_PTR(rbuf)[3])) | + (((uint8_t)(RSTRING_PTR(rbuf)[2])) << 8) | + (((uint8_t)(RSTRING_PTR(rbuf)[1])) << 16) | + (((uint8_t)(RSTRING_PTR(rbuf)[0])) << 24); + uint32_t lo = ((uint8_t)(RSTRING_PTR(rbuf)[7])) | + (((uint8_t)(RSTRING_PTR(rbuf)[6])) << 8) | + (((uint8_t)(RSTRING_PTR(rbuf)[5])) << 16) | + (((uint8_t)(RSTRING_PTR(rbuf)[4])) << 24); + return (hi << 32) | lo; +} + +static VALUE get_protocol_exception(VALUE code, VALUE message) { + VALUE args[2]; + args[0] = code; + args[1] = message; + return rb_class_new_instance(2, (VALUE*)&args, protocol_exception_class); +} + +VALUE rb_thrift_binary_proto_read_message_end(VALUE self) { + return Qnil; +} + +VALUE rb_thrift_binary_proto_read_struct_begin(VALUE self) { + return Qnil; +} + +VALUE rb_thrift_binary_proto_read_struct_end(VALUE self) { + return Qnil; +} + +VALUE rb_thrift_binary_proto_read_field_end(VALUE self) { + return Qnil; +} + +VALUE rb_thrift_binary_proto_read_map_end(VALUE self) { + return Qnil; +} + +VALUE rb_thrift_binary_proto_read_list_end(VALUE self) { + return Qnil; +} + +VALUE rb_thrift_binary_proto_read_set_end(VALUE self) { + return Qnil; +} + +VALUE rb_thrift_binary_proto_read_message_begin(VALUE self) { + VALUE strict_read = GET_STRICT_READ(self); + VALUE name, seqid; + int type; + + int version = read_i32_direct(self); + + if (version < 0) { + if ((version & VERSION_MASK) != VERSION_1) { + rb_exc_raise(get_protocol_exception(INT2FIX(BAD_VERSION), rb_str_new2("Missing version identifier"))); + } + type = version & TYPE_MASK; + name = rb_thrift_binary_proto_read_string(self); + seqid = rb_thrift_binary_proto_read_i32(self); + } else { + if (strict_read == Qtrue) { + rb_exc_raise(get_protocol_exception(INT2FIX(BAD_VERSION), rb_str_new2("No version identifier, old protocol client?"))); + } + name = READ(self, version); + type = read_byte_direct(self); + seqid = rb_thrift_binary_proto_read_i32(self); + } + + return rb_ary_new3(3, name, INT2FIX(type), seqid); +} + +VALUE rb_thrift_binary_proto_read_field_begin(VALUE self) { + int type = read_byte_direct(self); + if (type == TTYPE_STOP) { + return rb_ary_new3(3, Qnil, INT2FIX(type), INT2FIX(0)); + } else { + VALUE id = rb_thrift_binary_proto_read_i16(self); + return rb_ary_new3(3, Qnil, INT2FIX(type), id); + } +} + +VALUE rb_thrift_binary_proto_read_map_begin(VALUE self) { + VALUE ktype = rb_thrift_binary_proto_read_byte(self); + VALUE vtype = rb_thrift_binary_proto_read_byte(self); + VALUE size = rb_thrift_binary_proto_read_i32(self); + return rb_ary_new3(3, ktype, vtype, size); +} + +VALUE rb_thrift_binary_proto_read_list_begin(VALUE self) { + VALUE etype = rb_thrift_binary_proto_read_byte(self); + VALUE size = rb_thrift_binary_proto_read_i32(self); + return rb_ary_new3(2, etype, size); +} + +VALUE rb_thrift_binary_proto_read_set_begin(VALUE self) { + return rb_thrift_binary_proto_read_list_begin(self); +} + +VALUE rb_thrift_binary_proto_read_bool(VALUE self) { + char byte = read_byte_direct(self); + return byte != 0 ? Qtrue : Qfalse; +} + +VALUE rb_thrift_binary_proto_read_byte(VALUE self) { + return INT2FIX(read_byte_direct(self)); +} + +VALUE rb_thrift_binary_proto_read_i16(VALUE self) { + return INT2FIX(read_i16_direct(self)); +} + +VALUE rb_thrift_binary_proto_read_i32(VALUE self) { + return INT2NUM(read_i32_direct(self)); +} + +VALUE rb_thrift_binary_proto_read_i64(VALUE self) { + return LL2NUM(read_i64_direct(self)); +} + +VALUE rb_thrift_binary_proto_read_double(VALUE self) { + union { + double f; + int64_t t; + } transfer; + transfer.t = read_i64_direct(self); + return rb_float_new(transfer.f); +} + +VALUE rb_thrift_binary_proto_read_string(VALUE self) { + VALUE buffer = rb_thrift_binary_proto_read_binary(self); + return convert_to_string(buffer); +} + +VALUE rb_thrift_binary_proto_read_binary(VALUE self) { + int size = read_i32_direct(self); + return READ(self, size); +} + +void Init_binary_protocol_accelerated() { + VALUE thrift_binary_protocol_class = rb_const_get(thrift_module, rb_intern("BinaryProtocol")); + + VERSION_1 = rb_num2ll(rb_const_get(thrift_binary_protocol_class, rb_intern("VERSION_1"))); + VERSION_MASK = rb_num2ll(rb_const_get(thrift_binary_protocol_class, rb_intern("VERSION_MASK"))); + TYPE_MASK = rb_num2ll(rb_const_get(thrift_binary_protocol_class, rb_intern("TYPE_MASK"))); + + VALUE bpa_class = rb_define_class_under(thrift_module, "BinaryProtocolAccelerated", thrift_binary_protocol_class); + + rb_define_method(bpa_class, "native?", rb_thrift_binary_proto_native_qmark, 0); + + rb_define_method(bpa_class, "write_message_begin", rb_thrift_binary_proto_write_message_begin, 3); + rb_define_method(bpa_class, "write_field_begin", rb_thrift_binary_proto_write_field_begin, 3); + rb_define_method(bpa_class, "write_field_stop", rb_thrift_binary_proto_write_field_stop, 0); + rb_define_method(bpa_class, "write_map_begin", rb_thrift_binary_proto_write_map_begin, 3); + rb_define_method(bpa_class, "write_list_begin", rb_thrift_binary_proto_write_list_begin, 2); + rb_define_method(bpa_class, "write_set_begin", rb_thrift_binary_proto_write_set_begin, 2); + rb_define_method(bpa_class, "write_byte", rb_thrift_binary_proto_write_byte, 1); + rb_define_method(bpa_class, "write_bool", rb_thrift_binary_proto_write_bool, 1); + rb_define_method(bpa_class, "write_i16", rb_thrift_binary_proto_write_i16, 1); + rb_define_method(bpa_class, "write_i32", rb_thrift_binary_proto_write_i32, 1); + rb_define_method(bpa_class, "write_i64", rb_thrift_binary_proto_write_i64, 1); + rb_define_method(bpa_class, "write_double", rb_thrift_binary_proto_write_double, 1); + rb_define_method(bpa_class, "write_string", rb_thrift_binary_proto_write_string, 1); + rb_define_method(bpa_class, "write_binary", rb_thrift_binary_proto_write_binary, 1); + // unused methods + rb_define_method(bpa_class, "write_message_end", rb_thrift_binary_proto_write_message_end, 0); + rb_define_method(bpa_class, "write_struct_begin", rb_thrift_binary_proto_write_struct_begin, 1); + rb_define_method(bpa_class, "write_struct_end", rb_thrift_binary_proto_write_struct_end, 0); + rb_define_method(bpa_class, "write_field_end", rb_thrift_binary_proto_write_field_end, 0); + rb_define_method(bpa_class, "write_map_end", rb_thrift_binary_proto_write_map_end, 0); + rb_define_method(bpa_class, "write_list_end", rb_thrift_binary_proto_write_list_end, 0); + rb_define_method(bpa_class, "write_set_end", rb_thrift_binary_proto_write_set_end, 0); + + rb_define_method(bpa_class, "read_message_begin", rb_thrift_binary_proto_read_message_begin, 0); + rb_define_method(bpa_class, "read_field_begin", rb_thrift_binary_proto_read_field_begin, 0); + rb_define_method(bpa_class, "read_map_begin", rb_thrift_binary_proto_read_map_begin, 0); + rb_define_method(bpa_class, "read_list_begin", rb_thrift_binary_proto_read_list_begin, 0); + rb_define_method(bpa_class, "read_set_begin", rb_thrift_binary_proto_read_set_begin, 0); + rb_define_method(bpa_class, "read_byte", rb_thrift_binary_proto_read_byte, 0); + rb_define_method(bpa_class, "read_bool", rb_thrift_binary_proto_read_bool, 0); + rb_define_method(bpa_class, "read_i16", rb_thrift_binary_proto_read_i16, 0); + rb_define_method(bpa_class, "read_i32", rb_thrift_binary_proto_read_i32, 0); + rb_define_method(bpa_class, "read_i64", rb_thrift_binary_proto_read_i64, 0); + rb_define_method(bpa_class, "read_double", rb_thrift_binary_proto_read_double, 0); + rb_define_method(bpa_class, "read_string", rb_thrift_binary_proto_read_string, 0); + rb_define_method(bpa_class, "read_binary", rb_thrift_binary_proto_read_binary, 0); + // unused methods + rb_define_method(bpa_class, "read_message_end", rb_thrift_binary_proto_read_message_end, 0); + rb_define_method(bpa_class, "read_struct_begin", rb_thrift_binary_proto_read_struct_begin, 0); + rb_define_method(bpa_class, "read_struct_end", rb_thrift_binary_proto_read_struct_end, 0); + rb_define_method(bpa_class, "read_field_end", rb_thrift_binary_proto_read_field_end, 0); + rb_define_method(bpa_class, "read_map_end", rb_thrift_binary_proto_read_map_end, 0); + rb_define_method(bpa_class, "read_list_end", rb_thrift_binary_proto_read_list_end, 0); + rb_define_method(bpa_class, "read_set_end", rb_thrift_binary_proto_read_set_end, 0); + + rbuf_ivar_id = rb_intern("@rbuf"); +} diff --git a/vendor/github.com/apache/thrift/lib/rb/ext/binary_protocol_accelerated.h b/vendor/github.com/apache/thrift/lib/rb/ext/binary_protocol_accelerated.h new file mode 100644 index 000000000..37baf4142 --- /dev/null +++ b/vendor/github.com/apache/thrift/lib/rb/ext/binary_protocol_accelerated.h @@ -0,0 +1,20 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +void Init_binary_protocol_accelerated(); diff --git a/vendor/github.com/apache/thrift/lib/rb/ext/bytes.c b/vendor/github.com/apache/thrift/lib/rb/ext/bytes.c new file mode 100644 index 000000000..8a6fac4ac --- /dev/null +++ b/vendor/github.com/apache/thrift/lib/rb/ext/bytes.c @@ -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. + */ + +#include +#ifdef HAVE_RUBY_ENCODING_H +#include +#endif +#include + +VALUE force_binary_encoding(VALUE buffer) { + return rb_funcall(thrift_bytes_module, force_binary_encoding_id, 1, buffer); +} + +VALUE convert_to_utf8_byte_buffer(VALUE string) { + return rb_funcall(thrift_bytes_module, convert_to_utf8_byte_buffer_id, 1, string); +} + +VALUE convert_to_string(VALUE utf8_buffer) { + return rb_funcall(thrift_bytes_module, convert_to_string_id, 1, utf8_buffer); +} diff --git a/vendor/github.com/apache/thrift/lib/rb/ext/bytes.h b/vendor/github.com/apache/thrift/lib/rb/ext/bytes.h new file mode 100644 index 000000000..7108d83ff --- /dev/null +++ b/vendor/github.com/apache/thrift/lib/rb/ext/bytes.h @@ -0,0 +1,31 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT 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 + +/* + * A collection of utilities for working with bytes and byte buffers. + * + * These methods are the native analogies to some of the methods in + * Thrift::Bytes (thrift/bytes.rb). + */ + +VALUE force_binary_encoding(VALUE buffer); +VALUE convert_to_utf8_byte_buffer(VALUE string); +VALUE convert_to_string(VALUE utf8_buffer); diff --git a/vendor/github.com/apache/thrift/lib/rb/ext/compact_protocol.c b/vendor/github.com/apache/thrift/lib/rb/ext/compact_protocol.c new file mode 100644 index 000000000..c0f46b958 --- /dev/null +++ b/vendor/github.com/apache/thrift/lib/rb/ext/compact_protocol.c @@ -0,0 +1,637 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT 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 +#include +#include +#include +#include +#include +#include + +#define LAST_ID(obj) FIX2INT(rb_ary_pop(rb_ivar_get(obj, last_field_id))) +#define SET_LAST_ID(obj, val) rb_ary_push(rb_ivar_get(obj, last_field_id), val) + +VALUE rb_thrift_compact_proto_native_qmark(VALUE self) { + return Qtrue; +} + +static ID last_field_id; +static ID boolean_field_id; +static ID bool_value_id; +static ID rbuf_ivar_id; + +static int VERSION; +static int VERSION_MASK; +static int TYPE_MASK; +static int TYPE_BITS; +static int TYPE_SHIFT_AMOUNT; +static int PROTOCOL_ID; + +static VALUE thrift_compact_protocol_class; + +static int CTYPE_BOOLEAN_TRUE = 0x01; +static int CTYPE_BOOLEAN_FALSE = 0x02; +static int CTYPE_BYTE = 0x03; +static int CTYPE_I16 = 0x04; +static int CTYPE_I32 = 0x05; +static int CTYPE_I64 = 0x06; +static int CTYPE_DOUBLE = 0x07; +static int CTYPE_BINARY = 0x08; +static int CTYPE_LIST = 0x09; +static int CTYPE_SET = 0x0A; +static int CTYPE_MAP = 0x0B; +static int CTYPE_STRUCT = 0x0C; + +VALUE rb_thrift_compact_proto_write_i16(VALUE self, VALUE i16); + +// TODO: implement this +static int get_compact_type(VALUE type_value) { + int type = FIX2INT(type_value); + if (type == TTYPE_BOOL) { + return CTYPE_BOOLEAN_TRUE; + } else if (type == TTYPE_BYTE) { + return CTYPE_BYTE; + } else if (type == TTYPE_I16) { + return CTYPE_I16; + } else if (type == TTYPE_I32) { + return CTYPE_I32; + } else if (type == TTYPE_I64) { + return CTYPE_I64; + } else if (type == TTYPE_DOUBLE) { + return CTYPE_DOUBLE; + } else if (type == TTYPE_STRING) { + return CTYPE_BINARY; + } else if (type == TTYPE_LIST) { + return CTYPE_LIST; + } else if (type == TTYPE_SET) { + return CTYPE_SET; + } else if (type == TTYPE_MAP) { + return CTYPE_MAP; + } else if (type == TTYPE_STRUCT) { + return CTYPE_STRUCT; + } else { + char str[50]; + sprintf(str, "don't know what type: %d", type); + rb_raise(rb_eStandardError, "%s", str); + return 0; + } +} + +static void write_byte_direct(VALUE transport, int8_t b) { + WRITE(transport, (char*)&b, 1); +} + +static void write_field_begin_internal(VALUE self, VALUE type, VALUE id_value, VALUE type_override) { + int id = FIX2INT(id_value); + int last_id = LAST_ID(self); + VALUE transport = GET_TRANSPORT(self); + + // if there's a type override, use that. + int8_t type_to_write = RTEST(type_override) ? FIX2INT(type_override) : get_compact_type(type); + // check if we can use delta encoding for the field id + int diff = id - last_id; + if (diff > 0 && diff <= 15) { + // write them together + write_byte_direct(transport, diff << 4 | (type_to_write & 0x0f)); + } else { + // write them separate + write_byte_direct(transport, type_to_write & 0x0f); + rb_thrift_compact_proto_write_i16(self, id_value); + } + + SET_LAST_ID(self, id_value); +} + +static int32_t int_to_zig_zag(int32_t n) { + return (n << 1) ^ (n >> 31); +} + +static uint64_t ll_to_zig_zag(int64_t n) { + return (n << 1) ^ (n >> 63); +} + +static void write_varint32(VALUE transport, uint32_t n) { + while (true) { + if ((n & ~0x7F) == 0) { + write_byte_direct(transport, n & 0x7f); + break; + } else { + write_byte_direct(transport, (n & 0x7F) | 0x80); + n = n >> 7; + } + } +} + +static void write_varint64(VALUE transport, uint64_t n) { + while (true) { + if ((n & ~0x7F) == 0) { + write_byte_direct(transport, n & 0x7f); + break; + } else { + write_byte_direct(transport, (n & 0x7F) | 0x80); + n = n >> 7; + } + } +} + +static void write_collection_begin(VALUE transport, VALUE elem_type, VALUE size_value) { + int size = FIX2INT(size_value); + if (size <= 14) { + write_byte_direct(transport, size << 4 | get_compact_type(elem_type)); + } else { + write_byte_direct(transport, 0xf0 | get_compact_type(elem_type)); + write_varint32(transport, size); + } +} + + +//-------------------------------- +// interface writing methods +//-------------------------------- + +VALUE rb_thrift_compact_proto_write_i32(VALUE self, VALUE i32); +VALUE rb_thrift_compact_proto_write_string(VALUE self, VALUE str); +VALUE rb_thrift_compact_proto_write_binary(VALUE self, VALUE buf); + +VALUE rb_thrift_compact_proto_write_message_end(VALUE self) { + return Qnil; +} + +VALUE rb_thrift_compact_proto_write_struct_begin(VALUE self, VALUE name) { + rb_ary_push(rb_ivar_get(self, last_field_id), INT2FIX(0)); + return Qnil; +} + +VALUE rb_thrift_compact_proto_write_struct_end(VALUE self) { + rb_ary_pop(rb_ivar_get(self, last_field_id)); + return Qnil; +} + +VALUE rb_thrift_compact_proto_write_field_end(VALUE self) { + return Qnil; +} + +VALUE rb_thrift_compact_proto_write_map_end(VALUE self) { + return Qnil; +} + +VALUE rb_thrift_compact_proto_write_list_end(VALUE self) { + return Qnil; +} + +VALUE rb_thrift_compact_proto_write_set_end(VALUE self) { + return Qnil; +} + +VALUE rb_thrift_compact_proto_write_message_begin(VALUE self, VALUE name, VALUE type, VALUE seqid) { + VALUE transport = GET_TRANSPORT(self); + write_byte_direct(transport, PROTOCOL_ID); + write_byte_direct(transport, (VERSION & VERSION_MASK) | ((FIX2INT(type) << TYPE_SHIFT_AMOUNT) & TYPE_MASK)); + write_varint32(transport, FIX2INT(seqid)); + rb_thrift_compact_proto_write_string(self, name); + + return Qnil; +} + +VALUE rb_thrift_compact_proto_write_field_begin(VALUE self, VALUE name, VALUE type, VALUE id) { + if (FIX2INT(type) == TTYPE_BOOL) { + // we want to possibly include the value, so we'll wait. + rb_ivar_set(self, boolean_field_id, rb_ary_new3(2, type, id)); + } else { + write_field_begin_internal(self, type, id, Qnil); + } + + return Qnil; +} + +VALUE rb_thrift_compact_proto_write_field_stop(VALUE self) { + write_byte_direct(GET_TRANSPORT(self), TTYPE_STOP); + return Qnil; +} + +VALUE rb_thrift_compact_proto_write_map_begin(VALUE self, VALUE ktype, VALUE vtype, VALUE size_value) { + int size = FIX2INT(size_value); + VALUE transport = GET_TRANSPORT(self); + if (size == 0) { + write_byte_direct(transport, 0); + } else { + write_varint32(transport, size); + write_byte_direct(transport, get_compact_type(ktype) << 4 | get_compact_type(vtype)); + } + return Qnil; +} + +VALUE rb_thrift_compact_proto_write_list_begin(VALUE self, VALUE etype, VALUE size) { + write_collection_begin(GET_TRANSPORT(self), etype, size); + return Qnil; +} + +VALUE rb_thrift_compact_proto_write_set_begin(VALUE self, VALUE etype, VALUE size) { + write_collection_begin(GET_TRANSPORT(self), etype, size); + return Qnil; +} + +VALUE rb_thrift_compact_proto_write_bool(VALUE self, VALUE b) { + int8_t type = b == Qtrue ? CTYPE_BOOLEAN_TRUE : CTYPE_BOOLEAN_FALSE; + VALUE boolean_field = rb_ivar_get(self, boolean_field_id); + if (NIL_P(boolean_field)) { + // we're not part of a field, so just write the value. + write_byte_direct(GET_TRANSPORT(self), type); + } else { + // we haven't written the field header yet + write_field_begin_internal(self, rb_ary_entry(boolean_field, 0), rb_ary_entry(boolean_field, 1), INT2FIX(type)); + rb_ivar_set(self, boolean_field_id, Qnil); + } + return Qnil; +} + +VALUE rb_thrift_compact_proto_write_byte(VALUE self, VALUE byte) { + CHECK_NIL(byte); + write_byte_direct(GET_TRANSPORT(self), FIX2INT(byte)); + return Qnil; +} + +VALUE rb_thrift_compact_proto_write_i16(VALUE self, VALUE i16) { + rb_thrift_compact_proto_write_i32(self, i16); + return Qnil; +} + +VALUE rb_thrift_compact_proto_write_i32(VALUE self, VALUE i32) { + CHECK_NIL(i32); + write_varint32(GET_TRANSPORT(self), int_to_zig_zag(NUM2INT(i32))); + return Qnil; +} + +VALUE rb_thrift_compact_proto_write_i64(VALUE self, VALUE i64) { + CHECK_NIL(i64); + write_varint64(GET_TRANSPORT(self), ll_to_zig_zag(NUM2LL(i64))); + return Qnil; +} + +VALUE rb_thrift_compact_proto_write_double(VALUE self, VALUE dub) { + CHECK_NIL(dub); + // Unfortunately, bitwise_cast doesn't work in C. Bad C! + union { + double f; + int64_t l; + } transfer; + transfer.f = RFLOAT_VALUE(rb_Float(dub)); + char buf[8]; + buf[0] = transfer.l & 0xff; + buf[1] = (transfer.l >> 8) & 0xff; + buf[2] = (transfer.l >> 16) & 0xff; + buf[3] = (transfer.l >> 24) & 0xff; + buf[4] = (transfer.l >> 32) & 0xff; + buf[5] = (transfer.l >> 40) & 0xff; + buf[6] = (transfer.l >> 48) & 0xff; + buf[7] = (transfer.l >> 56) & 0xff; + WRITE(GET_TRANSPORT(self), buf, 8); + return Qnil; +} + +VALUE rb_thrift_compact_proto_write_string(VALUE self, VALUE str) { + str = convert_to_utf8_byte_buffer(str); + rb_thrift_compact_proto_write_binary(self, str); + return Qnil; +} + +VALUE rb_thrift_compact_proto_write_binary(VALUE self, VALUE buf) { + buf = force_binary_encoding(buf); + VALUE transport = GET_TRANSPORT(self); + write_varint32(transport, RSTRING_LEN(buf)); + WRITE(transport, StringValuePtr(buf), RSTRING_LEN(buf)); + return Qnil; +} + +//--------------------------------------- +// interface reading methods +//--------------------------------------- + +#define is_bool_type(ctype) (((ctype) & 0x0F) == CTYPE_BOOLEAN_TRUE || ((ctype) & 0x0F) == CTYPE_BOOLEAN_FALSE) + +VALUE rb_thrift_compact_proto_read_string(VALUE self); +VALUE rb_thrift_compact_proto_read_binary(VALUE self); +VALUE rb_thrift_compact_proto_read_byte(VALUE self); +VALUE rb_thrift_compact_proto_read_i32(VALUE self); +VALUE rb_thrift_compact_proto_read_i16(VALUE self); + +static int8_t get_ttype(int8_t ctype) { + if (ctype == TTYPE_STOP) { + return TTYPE_STOP; + } else if (ctype == CTYPE_BOOLEAN_TRUE || ctype == CTYPE_BOOLEAN_FALSE) { + return TTYPE_BOOL; + } else if (ctype == CTYPE_BYTE) { + return TTYPE_BYTE; + } else if (ctype == CTYPE_I16) { + return TTYPE_I16; + } else if (ctype == CTYPE_I32) { + return TTYPE_I32; + } else if (ctype == CTYPE_I64) { + return TTYPE_I64; + } else if (ctype == CTYPE_DOUBLE) { + return TTYPE_DOUBLE; + } else if (ctype == CTYPE_BINARY) { + return TTYPE_STRING; + } else if (ctype == CTYPE_LIST) { + return TTYPE_LIST; + } else if (ctype == CTYPE_SET) { + return TTYPE_SET; + } else if (ctype == CTYPE_MAP) { + return TTYPE_MAP; + } else if (ctype == CTYPE_STRUCT) { + return TTYPE_STRUCT; + } else { + char str[50]; + sprintf(str, "don't know what type: %d", ctype); + rb_raise(rb_eStandardError, "%s", str); + return 0; + } +} + +static char read_byte_direct(VALUE self) { + VALUE byte = rb_funcall(GET_TRANSPORT(self), read_byte_method_id, 0); + return (char)(FIX2INT(byte)); +} + +static int64_t zig_zag_to_ll(int64_t n) { + return (((uint64_t)n) >> 1) ^ -(n & 1); +} + +static int32_t zig_zag_to_int(int32_t n) { + return (((uint32_t)n) >> 1) ^ -(n & 1); +} + +static int64_t read_varint64(VALUE self) { + int shift = 0; + int64_t result = 0; + while (true) { + int8_t b = read_byte_direct(self); + result = result | ((uint64_t)(b & 0x7f) << shift); + if ((b & 0x80) != 0x80) { + break; + } + shift += 7; + } + return result; +} + +static int16_t read_i16(VALUE self) { + return zig_zag_to_int((int32_t)read_varint64(self)); +} + +static VALUE get_protocol_exception(VALUE code, VALUE message) { + VALUE args[2]; + args[0] = code; + args[1] = message; + return rb_class_new_instance(2, (VALUE*)&args, protocol_exception_class); +} + +VALUE rb_thrift_compact_proto_read_message_end(VALUE self) { + return Qnil; +} + +VALUE rb_thrift_compact_proto_read_struct_begin(VALUE self) { + rb_ary_push(rb_ivar_get(self, last_field_id), INT2FIX(0)); + return Qnil; +} + +VALUE rb_thrift_compact_proto_read_struct_end(VALUE self) { + rb_ary_pop(rb_ivar_get(self, last_field_id)); + return Qnil; +} + +VALUE rb_thrift_compact_proto_read_field_end(VALUE self) { + return Qnil; +} + +VALUE rb_thrift_compact_proto_read_map_end(VALUE self) { + return Qnil; +} + +VALUE rb_thrift_compact_proto_read_list_end(VALUE self) { + return Qnil; +} + +VALUE rb_thrift_compact_proto_read_set_end(VALUE self) { + return Qnil; +} + +VALUE rb_thrift_compact_proto_read_message_begin(VALUE self) { + int8_t protocol_id = read_byte_direct(self); + if (protocol_id != PROTOCOL_ID) { + char buf[100]; + int len = sprintf(buf, "Expected protocol id %d but got %d", PROTOCOL_ID, protocol_id); + buf[len] = 0; + rb_exc_raise(get_protocol_exception(INT2FIX(-1), rb_str_new2(buf))); + } + + int8_t version_and_type = read_byte_direct(self); + int8_t version = version_and_type & VERSION_MASK; + if (version != VERSION) { + char buf[100]; + int len = sprintf(buf, "Expected version id %d but got %d", version, VERSION); + buf[len] = 0; + rb_exc_raise(get_protocol_exception(INT2FIX(-1), rb_str_new2(buf))); + } + + int8_t type = (version_and_type >> TYPE_SHIFT_AMOUNT) & TYPE_BITS; + int32_t seqid = read_varint64(self); + VALUE messageName = rb_thrift_compact_proto_read_string(self); + return rb_ary_new3(3, messageName, INT2FIX(type), INT2NUM(seqid)); +} + +VALUE rb_thrift_compact_proto_read_field_begin(VALUE self) { + int8_t type = read_byte_direct(self); + // if it's a stop, then we can return immediately, as the struct is over. + if ((type & 0x0f) == TTYPE_STOP) { + return rb_ary_new3(3, Qnil, INT2FIX(0), INT2FIX(0)); + } else { + int field_id = 0; + + // mask off the 4 MSB of the type header. it could contain a field id delta. + uint8_t modifier = ((type & 0xf0) >> 4); + + if (modifier == 0) { + // not a delta. look ahead for the zigzag varint field id. + (void) LAST_ID(self); + field_id = read_i16(self); + } else { + // has a delta. add the delta to the last read field id. + field_id = LAST_ID(self) + modifier; + } + + // if this happens to be a boolean field, the value is encoded in the type + if (is_bool_type(type)) { + // save the boolean value in a special instance variable. + rb_ivar_set(self, bool_value_id, (type & 0x0f) == CTYPE_BOOLEAN_TRUE ? Qtrue : Qfalse); + } + + // push the new field onto the field stack so we can keep the deltas going. + SET_LAST_ID(self, INT2FIX(field_id)); + return rb_ary_new3(3, Qnil, INT2FIX(get_ttype(type & 0x0f)), INT2FIX(field_id)); + } +} + +VALUE rb_thrift_compact_proto_read_map_begin(VALUE self) { + int32_t size = read_varint64(self); + uint8_t key_and_value_type = size == 0 ? 0 : read_byte_direct(self); + return rb_ary_new3(3, INT2FIX(get_ttype(key_and_value_type >> 4)), INT2FIX(get_ttype(key_and_value_type & 0xf)), INT2FIX(size)); +} + +VALUE rb_thrift_compact_proto_read_list_begin(VALUE self) { + uint8_t size_and_type = read_byte_direct(self); + int32_t size = (size_and_type >> 4) & 0x0f; + if (size == 15) { + size = read_varint64(self); + } + uint8_t type = get_ttype(size_and_type & 0x0f); + return rb_ary_new3(2, INT2FIX(type), INT2FIX(size)); +} + +VALUE rb_thrift_compact_proto_read_set_begin(VALUE self) { + return rb_thrift_compact_proto_read_list_begin(self); +} + +VALUE rb_thrift_compact_proto_read_bool(VALUE self) { + VALUE bool_value = rb_ivar_get(self, bool_value_id); + if (NIL_P(bool_value)) { + return read_byte_direct(self) == CTYPE_BOOLEAN_TRUE ? Qtrue : Qfalse; + } else { + rb_ivar_set(self, bool_value_id, Qnil); + return bool_value; + } +} + +VALUE rb_thrift_compact_proto_read_byte(VALUE self) { + return INT2FIX(read_byte_direct(self)); +} + +VALUE rb_thrift_compact_proto_read_i16(VALUE self) { + return INT2FIX(read_i16(self)); +} + +VALUE rb_thrift_compact_proto_read_i32(VALUE self) { + return INT2NUM(zig_zag_to_int(read_varint64(self))); +} + +VALUE rb_thrift_compact_proto_read_i64(VALUE self) { + return LL2NUM(zig_zag_to_ll(read_varint64(self))); +} + +VALUE rb_thrift_compact_proto_read_double(VALUE self) { + union { + double f; + int64_t l; + } transfer; + VALUE rbuf = rb_ivar_get(self, rbuf_ivar_id); + rb_funcall(GET_TRANSPORT(self), read_into_buffer_method_id, 2, rbuf, INT2FIX(8)); + uint32_t lo = ((uint8_t)(RSTRING_PTR(rbuf)[0])) + | (((uint8_t)(RSTRING_PTR(rbuf)[1])) << 8) + | (((uint8_t)(RSTRING_PTR(rbuf)[2])) << 16) + | (((uint8_t)(RSTRING_PTR(rbuf)[3])) << 24); + uint64_t hi = (((uint8_t)(RSTRING_PTR(rbuf)[4]))) + | (((uint8_t)(RSTRING_PTR(rbuf)[5])) << 8) + | (((uint8_t)(RSTRING_PTR(rbuf)[6])) << 16) + | (((uint8_t)(RSTRING_PTR(rbuf)[7])) << 24); + transfer.l = (hi << 32) | lo; + + return rb_float_new(transfer.f); +} + +VALUE rb_thrift_compact_proto_read_string(VALUE self) { + VALUE buffer = rb_thrift_compact_proto_read_binary(self); + return convert_to_string(buffer); +} + +VALUE rb_thrift_compact_proto_read_binary(VALUE self) { + int64_t size = read_varint64(self); + return READ(self, size); +} + +static void Init_constants() { + thrift_compact_protocol_class = rb_const_get(thrift_module, rb_intern("CompactProtocol")); + + VERSION = rb_num2ll(rb_const_get(thrift_compact_protocol_class, rb_intern("VERSION"))); + VERSION_MASK = rb_num2ll(rb_const_get(thrift_compact_protocol_class, rb_intern("VERSION_MASK"))); + TYPE_MASK = rb_num2ll(rb_const_get(thrift_compact_protocol_class, rb_intern("TYPE_MASK"))); + TYPE_BITS = rb_num2ll(rb_const_get(thrift_compact_protocol_class, rb_intern("TYPE_BITS"))); + TYPE_SHIFT_AMOUNT = FIX2INT(rb_const_get(thrift_compact_protocol_class, rb_intern("TYPE_SHIFT_AMOUNT"))); + PROTOCOL_ID = FIX2INT(rb_const_get(thrift_compact_protocol_class, rb_intern("PROTOCOL_ID"))); + + last_field_id = rb_intern("@last_field"); + boolean_field_id = rb_intern("@boolean_field"); + bool_value_id = rb_intern("@bool_value"); + rbuf_ivar_id = rb_intern("@rbuf"); +} + +static void Init_rb_methods() { + rb_define_method(thrift_compact_protocol_class, "native?", rb_thrift_compact_proto_native_qmark, 0); + + rb_define_method(thrift_compact_protocol_class, "write_message_begin", rb_thrift_compact_proto_write_message_begin, 3); + rb_define_method(thrift_compact_protocol_class, "write_field_begin", rb_thrift_compact_proto_write_field_begin, 3); + rb_define_method(thrift_compact_protocol_class, "write_field_stop", rb_thrift_compact_proto_write_field_stop, 0); + rb_define_method(thrift_compact_protocol_class, "write_map_begin", rb_thrift_compact_proto_write_map_begin, 3); + rb_define_method(thrift_compact_protocol_class, "write_list_begin", rb_thrift_compact_proto_write_list_begin, 2); + rb_define_method(thrift_compact_protocol_class, "write_set_begin", rb_thrift_compact_proto_write_set_begin, 2); + rb_define_method(thrift_compact_protocol_class, "write_byte", rb_thrift_compact_proto_write_byte, 1); + rb_define_method(thrift_compact_protocol_class, "write_bool", rb_thrift_compact_proto_write_bool, 1); + rb_define_method(thrift_compact_protocol_class, "write_i16", rb_thrift_compact_proto_write_i16, 1); + rb_define_method(thrift_compact_protocol_class, "write_i32", rb_thrift_compact_proto_write_i32, 1); + rb_define_method(thrift_compact_protocol_class, "write_i64", rb_thrift_compact_proto_write_i64, 1); + rb_define_method(thrift_compact_protocol_class, "write_double", rb_thrift_compact_proto_write_double, 1); + rb_define_method(thrift_compact_protocol_class, "write_string", rb_thrift_compact_proto_write_string, 1); + rb_define_method(thrift_compact_protocol_class, "write_binary", rb_thrift_compact_proto_write_binary, 1); + + rb_define_method(thrift_compact_protocol_class, "write_message_end", rb_thrift_compact_proto_write_message_end, 0); + rb_define_method(thrift_compact_protocol_class, "write_struct_begin", rb_thrift_compact_proto_write_struct_begin, 1); + rb_define_method(thrift_compact_protocol_class, "write_struct_end", rb_thrift_compact_proto_write_struct_end, 0); + rb_define_method(thrift_compact_protocol_class, "write_field_end", rb_thrift_compact_proto_write_field_end, 0); + rb_define_method(thrift_compact_protocol_class, "write_map_end", rb_thrift_compact_proto_write_map_end, 0); + rb_define_method(thrift_compact_protocol_class, "write_list_end", rb_thrift_compact_proto_write_list_end, 0); + rb_define_method(thrift_compact_protocol_class, "write_set_end", rb_thrift_compact_proto_write_set_end, 0); + + + rb_define_method(thrift_compact_protocol_class, "read_message_begin", rb_thrift_compact_proto_read_message_begin, 0); + rb_define_method(thrift_compact_protocol_class, "read_field_begin", rb_thrift_compact_proto_read_field_begin, 0); + rb_define_method(thrift_compact_protocol_class, "read_map_begin", rb_thrift_compact_proto_read_map_begin, 0); + rb_define_method(thrift_compact_protocol_class, "read_list_begin", rb_thrift_compact_proto_read_list_begin, 0); + rb_define_method(thrift_compact_protocol_class, "read_set_begin", rb_thrift_compact_proto_read_set_begin, 0); + rb_define_method(thrift_compact_protocol_class, "read_byte", rb_thrift_compact_proto_read_byte, 0); + rb_define_method(thrift_compact_protocol_class, "read_bool", rb_thrift_compact_proto_read_bool, 0); + rb_define_method(thrift_compact_protocol_class, "read_i16", rb_thrift_compact_proto_read_i16, 0); + rb_define_method(thrift_compact_protocol_class, "read_i32", rb_thrift_compact_proto_read_i32, 0); + rb_define_method(thrift_compact_protocol_class, "read_i64", rb_thrift_compact_proto_read_i64, 0); + rb_define_method(thrift_compact_protocol_class, "read_double", rb_thrift_compact_proto_read_double, 0); + rb_define_method(thrift_compact_protocol_class, "read_string", rb_thrift_compact_proto_read_string, 0); + rb_define_method(thrift_compact_protocol_class, "read_binary", rb_thrift_compact_proto_read_binary, 0); + + rb_define_method(thrift_compact_protocol_class, "read_message_end", rb_thrift_compact_proto_read_message_end, 0); + rb_define_method(thrift_compact_protocol_class, "read_struct_begin", rb_thrift_compact_proto_read_struct_begin, 0); + rb_define_method(thrift_compact_protocol_class, "read_struct_end", rb_thrift_compact_proto_read_struct_end, 0); + rb_define_method(thrift_compact_protocol_class, "read_field_end", rb_thrift_compact_proto_read_field_end, 0); + rb_define_method(thrift_compact_protocol_class, "read_map_end", rb_thrift_compact_proto_read_map_end, 0); + rb_define_method(thrift_compact_protocol_class, "read_list_end", rb_thrift_compact_proto_read_list_end, 0); + rb_define_method(thrift_compact_protocol_class, "read_set_end", rb_thrift_compact_proto_read_set_end, 0); +} + +void Init_compact_protocol() { + Init_constants(); + Init_rb_methods(); +} diff --git a/vendor/github.com/apache/thrift/lib/rb/ext/compact_protocol.h b/vendor/github.com/apache/thrift/lib/rb/ext/compact_protocol.h new file mode 100644 index 000000000..163915e94 --- /dev/null +++ b/vendor/github.com/apache/thrift/lib/rb/ext/compact_protocol.h @@ -0,0 +1,20 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +void Init_compact_protocol(); diff --git a/vendor/github.com/apache/thrift/lib/rb/ext/constants.h b/vendor/github.com/apache/thrift/lib/rb/ext/constants.h new file mode 100644 index 000000000..e7aec4478 --- /dev/null +++ b/vendor/github.com/apache/thrift/lib/rb/ext/constants.h @@ -0,0 +1,99 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +extern int TTYPE_STOP; +extern int TTYPE_BOOL; +extern int TTYPE_BYTE; +extern int TTYPE_I16; +extern int TTYPE_I32; +extern int TTYPE_I64; +extern int TTYPE_DOUBLE; +extern int TTYPE_STRING; +extern int TTYPE_MAP; +extern int TTYPE_SET; +extern int TTYPE_LIST; +extern int TTYPE_STRUCT; + +extern ID validate_method_id; +extern ID write_struct_begin_method_id; +extern ID write_struct_end_method_id; +extern ID write_field_begin_method_id; +extern ID write_field_end_method_id; +extern ID write_boolean_method_id; +extern ID write_byte_method_id; +extern ID write_i16_method_id; +extern ID write_i32_method_id; +extern ID write_i64_method_id; +extern ID write_double_method_id; +extern ID write_string_method_id; +extern ID write_binary_method_id; +extern ID write_map_begin_method_id; +extern ID write_map_end_method_id; +extern ID write_list_begin_method_id; +extern ID write_list_end_method_id; +extern ID write_set_begin_method_id; +extern ID write_set_end_method_id; +extern ID read_bool_method_id; +extern ID read_byte_method_id; +extern ID read_i16_method_id; +extern ID read_i32_method_id; +extern ID read_i64_method_id; +extern ID read_string_method_id; +extern ID read_binary_method_id; +extern ID read_double_method_id; +extern ID read_map_begin_method_id; +extern ID read_map_end_method_id; +extern ID read_list_begin_method_id; +extern ID read_list_end_method_id; +extern ID read_set_begin_method_id; +extern ID read_set_end_method_id; +extern ID read_struct_begin_method_id; +extern ID read_struct_end_method_id; +extern ID read_field_begin_method_id; +extern ID read_field_end_method_id; +extern ID keys_method_id; +extern ID entries_method_id; +extern ID write_field_stop_method_id; +extern ID skip_method_id; +extern ID write_method_id; +extern ID read_all_method_id; +extern ID read_into_buffer_method_id; +extern ID force_binary_encoding_id; +extern ID convert_to_utf8_byte_buffer_id; +extern ID convert_to_string_id; + +extern ID fields_const_id; +extern ID transport_ivar_id; +extern ID strict_read_ivar_id; +extern ID strict_write_ivar_id; + +extern VALUE type_sym; +extern VALUE name_sym; +extern VALUE key_sym; +extern VALUE value_sym; +extern VALUE element_sym; +extern VALUE class_sym; +extern VALUE binary_sym; + +extern VALUE rb_cSet; +extern VALUE thrift_module; +extern VALUE thrift_types_module; +extern VALUE thrift_bytes_module; +extern VALUE class_thrift_protocol; +extern VALUE protocol_exception_class; diff --git a/vendor/github.com/apache/thrift/lib/rb/ext/macros.h b/vendor/github.com/apache/thrift/lib/rb/ext/macros.h new file mode 100644 index 000000000..265f6930d --- /dev/null +++ b/vendor/github.com/apache/thrift/lib/rb/ext/macros.h @@ -0,0 +1,41 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#define GET_TRANSPORT(obj) rb_ivar_get(obj, transport_ivar_id) +#define GET_STRICT_READ(obj) rb_ivar_get(obj, strict_read_ivar_id) +#define GET_STRICT_WRITE(obj) rb_ivar_get(obj, strict_write_ivar_id) +#define WRITE(obj, data, length) rb_funcall(obj, write_method_id, 1, rb_str_new(data, length)) +#define CHECK_NIL(obj) if (NIL_P(obj)) { rb_raise(rb_eStandardError, "nil argument not allowed!");} +#define READ(obj, length) rb_funcall(GET_TRANSPORT(obj), read_all_method_id, 1, INT2FIX(length)) + +#ifndef RFLOAT_VALUE +# define RFLOAT_VALUE(v) RFLOAT(rb_Float(v))->value +#endif + +#ifndef RSTRING_LEN +# define RSTRING_LEN(v) RSTRING(rb_String(v))->len +#endif + +#ifndef RSTRING_PTR +# define RSTRING_PTR(v) RSTRING(rb_String(v))->ptr +#endif + +#ifndef RARRAY_LEN +# define RARRAY_LEN(v) RARRAY(rb_Array(v))->len +#endif diff --git a/vendor/github.com/apache/thrift/lib/rb/ext/memory_buffer.c b/vendor/github.com/apache/thrift/lib/rb/ext/memory_buffer.c new file mode 100644 index 000000000..8b52c4a3e --- /dev/null +++ b/vendor/github.com/apache/thrift/lib/rb/ext/memory_buffer.c @@ -0,0 +1,134 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT 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 +#include +#include +#include + +ID buf_ivar_id; +ID index_ivar_id; + +ID slice_method_id; + +int GARBAGE_BUFFER_SIZE; + +#define GET_BUF(self) rb_ivar_get(self, buf_ivar_id) + +VALUE rb_thrift_memory_buffer_write(VALUE self, VALUE str); +VALUE rb_thrift_memory_buffer_read(VALUE self, VALUE length_value); +VALUE rb_thrift_memory_buffer_read_byte(VALUE self); +VALUE rb_thrift_memory_buffer_read_into_buffer(VALUE self, VALUE buffer_value, VALUE size_value); + +VALUE rb_thrift_memory_buffer_write(VALUE self, VALUE str) { + VALUE buf = GET_BUF(self); + str = force_binary_encoding(str); + rb_str_buf_cat(buf, StringValuePtr(str), RSTRING_LEN(str)); + return Qnil; +} + +VALUE rb_thrift_memory_buffer_read(VALUE self, VALUE length_value) { + int length = FIX2INT(length_value); + + VALUE index_value = rb_ivar_get(self, index_ivar_id); + int index = FIX2INT(index_value); + + VALUE buf = GET_BUF(self); + VALUE data = rb_funcall(buf, slice_method_id, 2, index_value, length_value); + + index += length; + if (index > RSTRING_LEN(buf)) { + index = RSTRING_LEN(buf); + } + if (index >= GARBAGE_BUFFER_SIZE) { + rb_ivar_set(self, buf_ivar_id, rb_funcall(buf, slice_method_id, 2, INT2FIX(index), INT2FIX(RSTRING_LEN(buf) - 1))); + index = 0; + } + rb_ivar_set(self, index_ivar_id, INT2FIX(index)); + + if (RSTRING_LEN(data) < length) { + rb_raise(rb_eEOFError, "Not enough bytes remain in memory buffer"); + } + + return data; +} + +VALUE rb_thrift_memory_buffer_read_byte(VALUE self) { + VALUE index_value = rb_ivar_get(self, index_ivar_id); + int index = FIX2INT(index_value); + + VALUE buf = GET_BUF(self); + if (index >= RSTRING_LEN(buf)) { + rb_raise(rb_eEOFError, "Not enough bytes remain in memory buffer"); + } + char byte = RSTRING_PTR(buf)[index++]; + + if (index >= GARBAGE_BUFFER_SIZE) { + rb_ivar_set(self, buf_ivar_id, rb_funcall(buf, slice_method_id, 2, INT2FIX(index), INT2FIX(RSTRING_LEN(buf) - 1))); + index = 0; + } + rb_ivar_set(self, index_ivar_id, INT2FIX(index)); + + int result = (int) byte; + return INT2FIX(result); +} + +VALUE rb_thrift_memory_buffer_read_into_buffer(VALUE self, VALUE buffer_value, VALUE size_value) { + int i = 0; + int size = FIX2INT(size_value); + int index; + VALUE buf = GET_BUF(self); + + index = FIX2INT(rb_ivar_get(self, index_ivar_id)); + while (i < size) { + if (index >= RSTRING_LEN(buf)) { + rb_raise(rb_eEOFError, "Not enough bytes remain in memory buffer"); + } + char byte = RSTRING_PTR(buf)[index++]; + + if (i >= RSTRING_LEN(buffer_value)) { + rb_raise(rb_eIndexError, "index %d out of string", i); + } + ((char*)RSTRING_PTR(buffer_value))[i] = byte; + i++; + } + + if (index >= GARBAGE_BUFFER_SIZE) { + rb_ivar_set(self, buf_ivar_id, rb_funcall(buf, slice_method_id, 2, INT2FIX(index), INT2FIX(RSTRING_LEN(buf) - 1))); + index = 0; + } + rb_ivar_set(self, index_ivar_id, INT2FIX(index)); + + return INT2FIX(i); +} + +void Init_memory_buffer() { + VALUE thrift_memory_buffer_class = rb_const_get(thrift_module, rb_intern("MemoryBufferTransport")); + rb_define_method(thrift_memory_buffer_class, "write", rb_thrift_memory_buffer_write, 1); + rb_define_method(thrift_memory_buffer_class, "read", rb_thrift_memory_buffer_read, 1); + rb_define_method(thrift_memory_buffer_class, "read_byte", rb_thrift_memory_buffer_read_byte, 0); + rb_define_method(thrift_memory_buffer_class, "read_into_buffer", rb_thrift_memory_buffer_read_into_buffer, 2); + + buf_ivar_id = rb_intern("@buf"); + index_ivar_id = rb_intern("@index"); + + slice_method_id = rb_intern("slice"); + + GARBAGE_BUFFER_SIZE = FIX2INT(rb_const_get(thrift_memory_buffer_class, rb_intern("GARBAGE_BUFFER_SIZE"))); +} diff --git a/vendor/github.com/apache/thrift/lib/rb/ext/memory_buffer.h b/vendor/github.com/apache/thrift/lib/rb/ext/memory_buffer.h new file mode 100644 index 000000000..b277fa6f6 --- /dev/null +++ b/vendor/github.com/apache/thrift/lib/rb/ext/memory_buffer.h @@ -0,0 +1,20 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +void Init_memory_buffer(); diff --git a/vendor/github.com/apache/thrift/lib/rb/ext/protocol.c b/vendor/github.com/apache/thrift/lib/rb/ext/protocol.c new file mode 100644 index 000000000..e69de29bb diff --git a/vendor/github.com/apache/thrift/lib/rb/ext/protocol.h b/vendor/github.com/apache/thrift/lib/rb/ext/protocol.h new file mode 100644 index 000000000..e69de29bb diff --git a/vendor/github.com/apache/thrift/lib/rb/ext/strlcpy.c b/vendor/github.com/apache/thrift/lib/rb/ext/strlcpy.c new file mode 100644 index 000000000..6700ff2d4 --- /dev/null +++ b/vendor/github.com/apache/thrift/lib/rb/ext/strlcpy.c @@ -0,0 +1,41 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT 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 "strlcpy.h" + +#ifndef HAVE_STRLCPY +#define HAVE_STRLCPY +size_t +strlcpy (char *dst, const char *src, size_t dst_sz) +{ + size_t n; + + for (n = 0; n < dst_sz; n++) { + if ((*dst++ = *src++) == '\0') + break; + } + + if (n < dst_sz) + return n; + if (n > 0) + *(dst - 1) = '\0'; + return n + strlen (src); +} +#endif + diff --git a/vendor/github.com/apache/thrift/lib/rb/ext/strlcpy.h b/vendor/github.com/apache/thrift/lib/rb/ext/strlcpy.h new file mode 100644 index 000000000..f6fe0fe6b --- /dev/null +++ b/vendor/github.com/apache/thrift/lib/rb/ext/strlcpy.h @@ -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. + */ + +#include +#include + +#ifndef __has_builtin +#define __has_builtin(x) 0 +#endif + +#ifndef HAVE_STRLCPY +size_t strlcpy (char *dst, const char *src, size_t dst_sz); +#else +#if !__has_builtin(strlcpy) +extern size_t strlcpy(char *, const char *, size_t); +#endif +#endif + diff --git a/vendor/github.com/apache/thrift/lib/rb/ext/struct.c b/vendor/github.com/apache/thrift/lib/rb/ext/struct.c new file mode 100644 index 000000000..e3aa855ed --- /dev/null +++ b/vendor/github.com/apache/thrift/lib/rb/ext/struct.c @@ -0,0 +1,711 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT 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 "struct.h" +#include "constants.h" +#include "macros.h" +#include "strlcpy.h" + +VALUE thrift_union_class; + +ID setfield_id; +ID setvalue_id; + +ID to_s_method_id; +ID name_to_id_method_id; +static ID sorted_field_ids_method_id; + +#define IS_CONTAINER(ttype) ((ttype) == TTYPE_MAP || (ttype) == TTYPE_LIST || (ttype) == TTYPE_SET) +#define STRUCT_FIELDS(obj) rb_const_get(CLASS_OF(obj), fields_const_id) + +//------------------------------------------- +// Writing section +//------------------------------------------- + +// default fn pointers for protocol stuff here + +VALUE default_write_bool(VALUE protocol, VALUE value) { + rb_funcall(protocol, write_boolean_method_id, 1, value); + return Qnil; +} + +VALUE default_write_byte(VALUE protocol, VALUE value) { + rb_funcall(protocol, write_byte_method_id, 1, value); + return Qnil; +} + +VALUE default_write_i16(VALUE protocol, VALUE value) { + rb_funcall(protocol, write_i16_method_id, 1, value); + return Qnil; +} + +VALUE default_write_i32(VALUE protocol, VALUE value) { + rb_funcall(protocol, write_i32_method_id, 1, value); + return Qnil; +} + +VALUE default_write_i64(VALUE protocol, VALUE value) { + rb_funcall(protocol, write_i64_method_id, 1, value); + return Qnil; +} + +VALUE default_write_double(VALUE protocol, VALUE value) { + rb_funcall(protocol, write_double_method_id, 1, value); + return Qnil; +} + +VALUE default_write_string(VALUE protocol, VALUE value) { + rb_funcall(protocol, write_string_method_id, 1, value); + return Qnil; +} + +VALUE default_write_binary(VALUE protocol, VALUE value) { + rb_funcall(protocol, write_binary_method_id, 1, value); + return Qnil; +} + +VALUE default_write_list_begin(VALUE protocol, VALUE etype, VALUE length) { + rb_funcall(protocol, write_list_begin_method_id, 2, etype, length); + return Qnil; +} + +VALUE default_write_list_end(VALUE protocol) { + rb_funcall(protocol, write_list_end_method_id, 0); + return Qnil; +} + +VALUE default_write_set_begin(VALUE protocol, VALUE etype, VALUE length) { + rb_funcall(protocol, write_set_begin_method_id, 2, etype, length); + return Qnil; +} + +VALUE default_write_set_end(VALUE protocol) { + rb_funcall(protocol, write_set_end_method_id, 0); + return Qnil; +} + +VALUE default_write_map_begin(VALUE protocol, VALUE ktype, VALUE vtype, VALUE length) { + rb_funcall(protocol, write_map_begin_method_id, 3, ktype, vtype, length); + return Qnil; +} + +VALUE default_write_map_end(VALUE protocol) { + rb_funcall(protocol, write_map_end_method_id, 0); + return Qnil; +} + +VALUE default_write_struct_begin(VALUE protocol, VALUE struct_name) { + rb_funcall(protocol, write_struct_begin_method_id, 1, struct_name); + return Qnil; +} + +VALUE default_write_struct_end(VALUE protocol) { + rb_funcall(protocol, write_struct_end_method_id, 0); + return Qnil; +} + +VALUE default_write_field_begin(VALUE protocol, VALUE name, VALUE type, VALUE id) { + rb_funcall(protocol, write_field_begin_method_id, 3, name, type, id); + return Qnil; +} + +VALUE default_write_field_end(VALUE protocol) { + rb_funcall(protocol, write_field_end_method_id, 0); + return Qnil; +} + +VALUE default_write_field_stop(VALUE protocol) { + rb_funcall(protocol, write_field_stop_method_id, 0); + return Qnil; +} + +VALUE default_read_field_begin(VALUE protocol) { + return rb_funcall(protocol, read_field_begin_method_id, 0); +} + +VALUE default_read_field_end(VALUE protocol) { + return rb_funcall(protocol, read_field_end_method_id, 0); +} + +VALUE default_read_map_begin(VALUE protocol) { + return rb_funcall(protocol, read_map_begin_method_id, 0); +} + +VALUE default_read_map_end(VALUE protocol) { + return rb_funcall(protocol, read_map_end_method_id, 0); +} + +VALUE default_read_list_begin(VALUE protocol) { + return rb_funcall(protocol, read_list_begin_method_id, 0); +} + +VALUE default_read_list_end(VALUE protocol) { + return rb_funcall(protocol, read_list_end_method_id, 0); +} + +VALUE default_read_set_begin(VALUE protocol) { + return rb_funcall(protocol, read_set_begin_method_id, 0); +} + +VALUE default_read_set_end(VALUE protocol) { + return rb_funcall(protocol, read_set_end_method_id, 0); +} + +VALUE default_read_byte(VALUE protocol) { + return rb_funcall(protocol, read_byte_method_id, 0); +} + +VALUE default_read_bool(VALUE protocol) { + return rb_funcall(protocol, read_bool_method_id, 0); +} + +VALUE default_read_i16(VALUE protocol) { + return rb_funcall(protocol, read_i16_method_id, 0); +} + +VALUE default_read_i32(VALUE protocol) { + return rb_funcall(protocol, read_i32_method_id, 0); +} + +VALUE default_read_i64(VALUE protocol) { + return rb_funcall(protocol, read_i64_method_id, 0); +} + +VALUE default_read_double(VALUE protocol) { + return rb_funcall(protocol, read_double_method_id, 0); +} + +VALUE default_read_string(VALUE protocol) { + return rb_funcall(protocol, read_string_method_id, 0); +} + +VALUE default_read_binary(VALUE protocol) { + return rb_funcall(protocol, read_binary_method_id, 0); +} + +VALUE default_read_struct_begin(VALUE protocol) { + return rb_funcall(protocol, read_struct_begin_method_id, 0); +} + +VALUE default_read_struct_end(VALUE protocol) { + return rb_funcall(protocol, read_struct_end_method_id, 0); +} + +// end default protocol methods + +static VALUE rb_thrift_union_write (VALUE self, VALUE protocol); +static VALUE rb_thrift_struct_write(VALUE self, VALUE protocol); +static void write_anything(int ttype, VALUE value, VALUE protocol, VALUE field_info); + +VALUE get_field_value(VALUE obj, VALUE field_name) { + char name_buf[RSTRING_LEN(field_name) + 2]; + + name_buf[0] = '@'; + strlcpy(&name_buf[1], RSTRING_PTR(field_name), RSTRING_LEN(field_name) + 1); + + VALUE value = rb_ivar_get(obj, rb_intern(name_buf)); + + return value; +} + +static void write_container(int ttype, VALUE field_info, VALUE value, VALUE protocol) { + int sz, i; + + if (ttype == TTYPE_MAP) { + VALUE keys; + VALUE key; + VALUE val; + + Check_Type(value, T_HASH); + + VALUE key_info = rb_hash_aref(field_info, key_sym); + VALUE keytype_value = rb_hash_aref(key_info, type_sym); + int keytype = FIX2INT(keytype_value); + + VALUE value_info = rb_hash_aref(field_info, value_sym); + VALUE valuetype_value = rb_hash_aref(value_info, type_sym); + int valuetype = FIX2INT(valuetype_value); + + keys = rb_funcall(value, keys_method_id, 0); + + sz = RARRAY_LEN(keys); + + default_write_map_begin(protocol, keytype_value, valuetype_value, INT2FIX(sz)); + + for (i = 0; i < sz; i++) { + key = rb_ary_entry(keys, i); + val = rb_hash_aref(value, key); + + if (IS_CONTAINER(keytype)) { + write_container(keytype, key_info, key, protocol); + } else { + write_anything(keytype, key, protocol, key_info); + } + + if (IS_CONTAINER(valuetype)) { + write_container(valuetype, value_info, val, protocol); + } else { + write_anything(valuetype, val, protocol, value_info); + } + } + + default_write_map_end(protocol); + } else if (ttype == TTYPE_LIST) { + Check_Type(value, T_ARRAY); + + sz = RARRAY_LEN(value); + + VALUE element_type_info = rb_hash_aref(field_info, element_sym); + VALUE element_type_value = rb_hash_aref(element_type_info, type_sym); + int element_type = FIX2INT(element_type_value); + + default_write_list_begin(protocol, element_type_value, INT2FIX(sz)); + for (i = 0; i < sz; ++i) { + VALUE val = rb_ary_entry(value, i); + if (IS_CONTAINER(element_type)) { + write_container(element_type, element_type_info, val, protocol); + } else { + write_anything(element_type, val, protocol, element_type_info); + } + } + default_write_list_end(protocol); + } else if (ttype == TTYPE_SET) { + VALUE items; + + if (TYPE(value) == T_ARRAY) { + items = value; + } else { + if (rb_cSet == CLASS_OF(value)) { + items = rb_funcall(value, entries_method_id, 0); + } else { + Check_Type(value, T_HASH); + items = rb_funcall(value, keys_method_id, 0); + } + } + + sz = RARRAY_LEN(items); + + VALUE element_type_info = rb_hash_aref(field_info, element_sym); + VALUE element_type_value = rb_hash_aref(element_type_info, type_sym); + int element_type = FIX2INT(element_type_value); + + default_write_set_begin(protocol, element_type_value, INT2FIX(sz)); + + for (i = 0; i < sz; i++) { + VALUE val = rb_ary_entry(items, i); + if (IS_CONTAINER(element_type)) { + write_container(element_type, element_type_info, val, protocol); + } else { + write_anything(element_type, val, protocol, element_type_info); + } + } + + default_write_set_end(protocol); + } else { + rb_raise(rb_eNotImpError, "can't write container of type: %d", ttype); + } +} + +static void write_anything(int ttype, VALUE value, VALUE protocol, VALUE field_info) { + if (ttype == TTYPE_BOOL) { + default_write_bool(protocol, value); + } else if (ttype == TTYPE_BYTE) { + default_write_byte(protocol, value); + } else if (ttype == TTYPE_I16) { + default_write_i16(protocol, value); + } else if (ttype == TTYPE_I32) { + default_write_i32(protocol, value); + } else if (ttype == TTYPE_I64) { + default_write_i64(protocol, value); + } else if (ttype == TTYPE_DOUBLE) { + default_write_double(protocol, value); + } else if (ttype == TTYPE_STRING) { + VALUE is_binary = rb_hash_aref(field_info, binary_sym); + if (is_binary != Qtrue) { + default_write_string(protocol, value); + } else { + default_write_binary(protocol, value); + } + } else if (IS_CONTAINER(ttype)) { + write_container(ttype, field_info, value, protocol); + } else if (ttype == TTYPE_STRUCT) { + if (rb_obj_is_kind_of(value, thrift_union_class)) { + rb_thrift_union_write(value, protocol); + } else { + rb_thrift_struct_write(value, protocol); + } + } else { + rb_raise(rb_eNotImpError, "Unknown type for binary_encoding: %d", ttype); + } +} + +static VALUE rb_thrift_struct_write(VALUE self, VALUE protocol) { + // call validate + rb_funcall(self, validate_method_id, 0); + + // write struct begin + default_write_struct_begin(protocol, rb_class_name(CLASS_OF(self))); + + // iterate through all the fields here + VALUE struct_fields = STRUCT_FIELDS(self); + VALUE sorted_field_ids = rb_funcall(self, sorted_field_ids_method_id, 0); + + int i = 0; + for (i=0; i < RARRAY_LEN(sorted_field_ids); i++) { + VALUE field_id = rb_ary_entry(sorted_field_ids, i); + + VALUE field_info = rb_hash_aref(struct_fields, field_id); + + VALUE ttype_value = rb_hash_aref(field_info, type_sym); + int ttype = FIX2INT(ttype_value); + VALUE field_name = rb_hash_aref(field_info, name_sym); + + VALUE field_value = get_field_value(self, field_name); + + if (!NIL_P(field_value)) { + default_write_field_begin(protocol, field_name, ttype_value, field_id); + + write_anything(ttype, field_value, protocol, field_info); + + default_write_field_end(protocol); + } + } + + default_write_field_stop(protocol); + + // write struct end + default_write_struct_end(protocol); + + return Qnil; +} + +//------------------------------------------- +// Reading section +//------------------------------------------- + +static VALUE rb_thrift_union_read(VALUE self, VALUE protocol); +static VALUE rb_thrift_struct_read(VALUE self, VALUE protocol); +static void skip_map_contents(VALUE protocol, VALUE key_type_value, VALUE value_type_value, int size); +static void skip_list_or_set_contents(VALUE protocol, VALUE element_type_value, int size); + +static void set_field_value(VALUE obj, VALUE field_name, VALUE value) { + char name_buf[RSTRING_LEN(field_name) + 2]; + + name_buf[0] = '@'; + strlcpy(&name_buf[1], RSTRING_PTR(field_name), RSTRING_LEN(field_name)+1); + + rb_ivar_set(obj, rb_intern(name_buf), value); +} + +// Helper method to skip the contents of a map (assumes the map header has been read). +static void skip_map_contents(VALUE protocol, VALUE key_type_value, VALUE value_type_value, int size) { + int i; + for (i = 0; i < size; i++) { + rb_funcall(protocol, skip_method_id, 1, key_type_value); + rb_funcall(protocol, skip_method_id, 1, value_type_value); + } +} + +// Helper method to skip the contents of a list or set (assumes the list/set header has been read). +static void skip_list_or_set_contents(VALUE protocol, VALUE element_type_value, int size) { + int i; + for (i = 0; i < size; i++) { + rb_funcall(protocol, skip_method_id, 1, element_type_value); + } +} + +static VALUE read_anything(VALUE protocol, int ttype, VALUE field_info) { + VALUE result = Qnil; + + if (ttype == TTYPE_BOOL) { + result = default_read_bool(protocol); + } else if (ttype == TTYPE_BYTE) { + result = default_read_byte(protocol); + } else if (ttype == TTYPE_I16) { + result = default_read_i16(protocol); + } else if (ttype == TTYPE_I32) { + result = default_read_i32(protocol); + } else if (ttype == TTYPE_I64) { + result = default_read_i64(protocol); + } else if (ttype == TTYPE_STRING) { + VALUE is_binary = rb_hash_aref(field_info, binary_sym); + if (is_binary != Qtrue) { + result = default_read_string(protocol); + } else { + result = default_read_binary(protocol); + } + } else if (ttype == TTYPE_DOUBLE) { + result = default_read_double(protocol); + } else if (ttype == TTYPE_STRUCT) { + VALUE klass = rb_hash_aref(field_info, class_sym); + result = rb_class_new_instance(0, NULL, klass); + + if (rb_obj_is_kind_of(result, thrift_union_class)) { + rb_thrift_union_read(result, protocol); + } else { + rb_thrift_struct_read(result, protocol); + } + } else if (ttype == TTYPE_MAP) { + int i; + + VALUE map_header = default_read_map_begin(protocol); + int key_ttype = FIX2INT(rb_ary_entry(map_header, 0)); + int value_ttype = FIX2INT(rb_ary_entry(map_header, 1)); + int num_entries = FIX2INT(rb_ary_entry(map_header, 2)); + + // Check the declared key and value types against the expected ones and skip the map contents + // if the types don't match. + VALUE key_info = rb_hash_aref(field_info, key_sym); + VALUE value_info = rb_hash_aref(field_info, value_sym); + + if (!NIL_P(key_info) && !NIL_P(value_info)) { + int specified_key_type = FIX2INT(rb_hash_aref(key_info, type_sym)); + int specified_value_type = FIX2INT(rb_hash_aref(value_info, type_sym)); + if (num_entries == 0 || (specified_key_type == key_ttype && specified_value_type == value_ttype)) { + result = rb_hash_new(); + + for (i = 0; i < num_entries; ++i) { + VALUE key, val; + + key = read_anything(protocol, key_ttype, key_info); + val = read_anything(protocol, value_ttype, value_info); + + rb_hash_aset(result, key, val); + } + } else { + skip_map_contents(protocol, INT2FIX(key_ttype), INT2FIX(value_ttype), num_entries); + } + } else { + skip_map_contents(protocol, INT2FIX(key_ttype), INT2FIX(value_ttype), num_entries); + } + + default_read_map_end(protocol); + } else if (ttype == TTYPE_LIST) { + int i; + + VALUE list_header = default_read_list_begin(protocol); + int element_ttype = FIX2INT(rb_ary_entry(list_header, 0)); + int num_elements = FIX2INT(rb_ary_entry(list_header, 1)); + + // Check the declared element type against the expected one and skip the list contents + // if the types don't match. + VALUE element_info = rb_hash_aref(field_info, element_sym); + if (!NIL_P(element_info)) { + int specified_element_type = FIX2INT(rb_hash_aref(element_info, type_sym)); + if (specified_element_type == element_ttype) { + result = rb_ary_new2(num_elements); + + for (i = 0; i < num_elements; ++i) { + rb_ary_push(result, read_anything(protocol, element_ttype, rb_hash_aref(field_info, element_sym))); + } + } else { + skip_list_or_set_contents(protocol, INT2FIX(element_ttype), num_elements); + } + } else { + skip_list_or_set_contents(protocol, INT2FIX(element_ttype), num_elements); + } + + default_read_list_end(protocol); + } else if (ttype == TTYPE_SET) { + VALUE items; + int i; + + VALUE set_header = default_read_set_begin(protocol); + int element_ttype = FIX2INT(rb_ary_entry(set_header, 0)); + int num_elements = FIX2INT(rb_ary_entry(set_header, 1)); + + // Check the declared element type against the expected one and skip the set contents + // if the types don't match. + VALUE element_info = rb_hash_aref(field_info, element_sym); + if (!NIL_P(element_info)) { + int specified_element_type = FIX2INT(rb_hash_aref(element_info, type_sym)); + if (specified_element_type == element_ttype) { + items = rb_ary_new2(num_elements); + + for (i = 0; i < num_elements; ++i) { + rb_ary_push(items, read_anything(protocol, element_ttype, rb_hash_aref(field_info, element_sym))); + } + + result = rb_class_new_instance(1, &items, rb_cSet); + } else { + skip_list_or_set_contents(protocol, INT2FIX(element_ttype), num_elements); + } + } else { + skip_list_or_set_contents(protocol, INT2FIX(element_ttype), num_elements); + } + + default_read_set_end(protocol); + } else { + rb_raise(rb_eNotImpError, "read_anything not implemented for type %d!", ttype); + } + + return result; +} + +static VALUE rb_thrift_struct_read(VALUE self, VALUE protocol) { + // read struct begin + default_read_struct_begin(protocol); + + VALUE struct_fields = STRUCT_FIELDS(self); + + // read each field + while (true) { + VALUE field_header = default_read_field_begin(protocol); + VALUE field_type_value = rb_ary_entry(field_header, 1); + int field_type = FIX2INT(field_type_value); + + if (field_type == TTYPE_STOP) { + break; + } + + // make sure we got a type we expected + VALUE field_info = rb_hash_aref(struct_fields, rb_ary_entry(field_header, 2)); + + if (!NIL_P(field_info)) { + int specified_type = FIX2INT(rb_hash_aref(field_info, type_sym)); + if (field_type == specified_type) { + // read the value + VALUE name = rb_hash_aref(field_info, name_sym); + set_field_value(self, name, read_anything(protocol, field_type, field_info)); + } else { + rb_funcall(protocol, skip_method_id, 1, field_type_value); + } + } else { + rb_funcall(protocol, skip_method_id, 1, field_type_value); + } + + // read field end + default_read_field_end(protocol); + } + + // read struct end + default_read_struct_end(protocol); + + // call validate + rb_funcall(self, validate_method_id, 0); + + return Qnil; +} + + +// -------------------------------- +// Union section +// -------------------------------- + +static VALUE rb_thrift_union_read(VALUE self, VALUE protocol) { + // read struct begin + default_read_struct_begin(protocol); + + VALUE struct_fields = STRUCT_FIELDS(self); + + VALUE field_header = default_read_field_begin(protocol); + VALUE field_type_value = rb_ary_entry(field_header, 1); + int field_type = FIX2INT(field_type_value); + + // make sure we got a type we expected + VALUE field_info = rb_hash_aref(struct_fields, rb_ary_entry(field_header, 2)); + + if (!NIL_P(field_info)) { + int specified_type = FIX2INT(rb_hash_aref(field_info, type_sym)); + if (field_type == specified_type) { + // read the value + VALUE name = rb_hash_aref(field_info, name_sym); + rb_iv_set(self, "@setfield", rb_str_intern(name)); + rb_iv_set(self, "@value", read_anything(protocol, field_type, field_info)); + } else { + rb_funcall(protocol, skip_method_id, 1, field_type_value); + } + } else { + rb_funcall(protocol, skip_method_id, 1, field_type_value); + } + + // read field end + default_read_field_end(protocol); + + field_header = default_read_field_begin(protocol); + field_type_value = rb_ary_entry(field_header, 1); + field_type = FIX2INT(field_type_value); + + if (field_type != TTYPE_STOP) { + rb_raise(rb_eRuntimeError, "too many fields in union!"); + } + + // read struct end + default_read_struct_end(protocol); + + // call validate + rb_funcall(self, validate_method_id, 0); + + return Qnil; +} + +static VALUE rb_thrift_union_write(VALUE self, VALUE protocol) { + // call validate + rb_funcall(self, validate_method_id, 0); + + // write struct begin + default_write_struct_begin(protocol, rb_class_name(CLASS_OF(self))); + + VALUE struct_fields = STRUCT_FIELDS(self); + + VALUE setfield = rb_ivar_get(self, setfield_id); + VALUE setvalue = rb_ivar_get(self, setvalue_id); + VALUE field_id = rb_funcall(self, name_to_id_method_id, 1, rb_funcall(setfield, to_s_method_id, 0)); + + VALUE field_info = rb_hash_aref(struct_fields, field_id); + + if(NIL_P(field_info)) { + rb_raise(rb_eRuntimeError, "set_field is not valid for this union!"); + } + + VALUE ttype_value = rb_hash_aref(field_info, type_sym); + int ttype = FIX2INT(ttype_value); + + default_write_field_begin(protocol, setfield, ttype_value, field_id); + + write_anything(ttype, setvalue, protocol, field_info); + + default_write_field_end(protocol); + + default_write_field_stop(protocol); + + // write struct end + default_write_struct_end(protocol); + + return Qnil; +} + +void Init_struct() { + VALUE struct_module = rb_const_get(thrift_module, rb_intern("Struct")); + + rb_define_method(struct_module, "write", rb_thrift_struct_write, 1); + rb_define_method(struct_module, "read", rb_thrift_struct_read, 1); + + thrift_union_class = rb_const_get(thrift_module, rb_intern("Union")); + + rb_define_method(thrift_union_class, "write", rb_thrift_union_write, 1); + rb_define_method(thrift_union_class, "read", rb_thrift_union_read, 1); + + setfield_id = rb_intern("@setfield"); + setvalue_id = rb_intern("@value"); + + to_s_method_id = rb_intern("to_s"); + name_to_id_method_id = rb_intern("name_to_id"); + sorted_field_ids_method_id = rb_intern("sorted_field_ids"); +} diff --git a/vendor/github.com/apache/thrift/lib/rb/ext/struct.h b/vendor/github.com/apache/thrift/lib/rb/ext/struct.h new file mode 100644 index 000000000..4748be5cb --- /dev/null +++ b/vendor/github.com/apache/thrift/lib/rb/ext/struct.h @@ -0,0 +1,25 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT 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 +#include + +void Init_struct(); +void Init_union(); diff --git a/vendor/github.com/apache/thrift/lib/rb/ext/thrift_native.c b/vendor/github.com/apache/thrift/lib/rb/ext/thrift_native.c new file mode 100644 index 000000000..3430b7c25 --- /dev/null +++ b/vendor/github.com/apache/thrift/lib/rb/ext/thrift_native.c @@ -0,0 +1,201 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include +#include +#include +#include +#include +#include + +// cached classes/modules +VALUE rb_cSet; +VALUE thrift_module; +VALUE thrift_bytes_module; +VALUE thrift_types_module; + +// TType constants +int TTYPE_STOP; +int TTYPE_BOOL; +int TTYPE_BYTE; +int TTYPE_I16; +int TTYPE_I32; +int TTYPE_I64; +int TTYPE_DOUBLE; +int TTYPE_STRING; +int TTYPE_MAP; +int TTYPE_SET; +int TTYPE_LIST; +int TTYPE_STRUCT; + +// method ids +ID validate_method_id; +ID write_struct_begin_method_id; +ID write_struct_end_method_id; +ID write_field_begin_method_id; +ID write_field_end_method_id; +ID write_boolean_method_id; +ID write_byte_method_id; +ID write_i16_method_id; +ID write_i32_method_id; +ID write_i64_method_id; +ID write_double_method_id; +ID write_string_method_id; +ID write_binary_method_id; +ID write_map_begin_method_id; +ID write_map_end_method_id; +ID write_list_begin_method_id; +ID write_list_end_method_id; +ID write_set_begin_method_id; +ID write_set_end_method_id; +ID read_bool_method_id; +ID read_byte_method_id; +ID read_i16_method_id; +ID read_i32_method_id; +ID read_i64_method_id; +ID read_string_method_id; +ID read_binary_method_id; +ID read_double_method_id; +ID read_map_begin_method_id; +ID read_map_end_method_id; +ID read_list_begin_method_id; +ID read_list_end_method_id; +ID read_set_begin_method_id; +ID read_set_end_method_id; +ID read_struct_begin_method_id; +ID read_struct_end_method_id; +ID read_field_begin_method_id; +ID read_field_end_method_id; +ID keys_method_id; +ID entries_method_id; +ID write_field_stop_method_id; +ID skip_method_id; +ID write_method_id; +ID read_all_method_id; +ID read_into_buffer_method_id; +ID force_binary_encoding_id; +ID convert_to_utf8_byte_buffer_id; +ID convert_to_string_id; + +// constant ids +ID fields_const_id; +ID transport_ivar_id; +ID strict_read_ivar_id; +ID strict_write_ivar_id; + +// cached symbols +VALUE type_sym; +VALUE name_sym; +VALUE key_sym; +VALUE value_sym; +VALUE element_sym; +VALUE class_sym; +VALUE binary_sym; +VALUE protocol_exception_class; + +void Init_thrift_native() { + // cached classes + thrift_module = rb_const_get(rb_cObject, rb_intern("Thrift")); + thrift_bytes_module = rb_const_get(thrift_module, rb_intern("Bytes")); + thrift_types_module = rb_const_get(thrift_module, rb_intern("Types")); + rb_cSet = rb_const_get(rb_cObject, rb_intern("Set")); + protocol_exception_class = rb_const_get(thrift_module, rb_intern("ProtocolException")); + + // Init ttype constants + TTYPE_BOOL = FIX2INT(rb_const_get(thrift_types_module, rb_intern("BOOL"))); + TTYPE_BYTE = FIX2INT(rb_const_get(thrift_types_module, rb_intern("BYTE"))); + TTYPE_I16 = FIX2INT(rb_const_get(thrift_types_module, rb_intern("I16"))); + TTYPE_I32 = FIX2INT(rb_const_get(thrift_types_module, rb_intern("I32"))); + TTYPE_I64 = FIX2INT(rb_const_get(thrift_types_module, rb_intern("I64"))); + TTYPE_DOUBLE = FIX2INT(rb_const_get(thrift_types_module, rb_intern("DOUBLE"))); + TTYPE_STRING = FIX2INT(rb_const_get(thrift_types_module, rb_intern("STRING"))); + TTYPE_MAP = FIX2INT(rb_const_get(thrift_types_module, rb_intern("MAP"))); + TTYPE_SET = FIX2INT(rb_const_get(thrift_types_module, rb_intern("SET"))); + TTYPE_LIST = FIX2INT(rb_const_get(thrift_types_module, rb_intern("LIST"))); + TTYPE_STRUCT = FIX2INT(rb_const_get(thrift_types_module, rb_intern("STRUCT"))); + + // method ids + validate_method_id = rb_intern("validate"); + write_struct_begin_method_id = rb_intern("write_struct_begin"); + write_struct_end_method_id = rb_intern("write_struct_end"); + write_field_begin_method_id = rb_intern("write_field_begin"); + write_field_end_method_id = rb_intern("write_field_end"); + write_boolean_method_id = rb_intern("write_bool"); + write_byte_method_id = rb_intern("write_byte"); + write_i16_method_id = rb_intern("write_i16"); + write_i32_method_id = rb_intern("write_i32"); + write_i64_method_id = rb_intern("write_i64"); + write_double_method_id = rb_intern("write_double"); + write_string_method_id = rb_intern("write_string"); + write_binary_method_id = rb_intern("write_binary"); + write_map_begin_method_id = rb_intern("write_map_begin"); + write_map_end_method_id = rb_intern("write_map_end"); + write_list_begin_method_id = rb_intern("write_list_begin"); + write_list_end_method_id = rb_intern("write_list_end"); + write_set_begin_method_id = rb_intern("write_set_begin"); + write_set_end_method_id = rb_intern("write_set_end"); + read_bool_method_id = rb_intern("read_bool"); + read_byte_method_id = rb_intern("read_byte"); + read_i16_method_id = rb_intern("read_i16"); + read_i32_method_id = rb_intern("read_i32"); + read_i64_method_id = rb_intern("read_i64"); + read_string_method_id = rb_intern("read_string"); + read_binary_method_id = rb_intern("read_binary"); + read_double_method_id = rb_intern("read_double"); + read_map_begin_method_id = rb_intern("read_map_begin"); + read_map_end_method_id = rb_intern("read_map_end"); + read_list_begin_method_id = rb_intern("read_list_begin"); + read_list_end_method_id = rb_intern("read_list_end"); + read_set_begin_method_id = rb_intern("read_set_begin"); + read_set_end_method_id = rb_intern("read_set_end"); + read_struct_begin_method_id = rb_intern("read_struct_begin"); + read_struct_end_method_id = rb_intern("read_struct_end"); + read_field_begin_method_id = rb_intern("read_field_begin"); + read_field_end_method_id = rb_intern("read_field_end"); + keys_method_id = rb_intern("keys"); + entries_method_id = rb_intern("entries"); + write_field_stop_method_id = rb_intern("write_field_stop"); + skip_method_id = rb_intern("skip"); + write_method_id = rb_intern("write"); + read_all_method_id = rb_intern("read_all"); + read_into_buffer_method_id = rb_intern("read_into_buffer"); + force_binary_encoding_id = rb_intern("force_binary_encoding"); + convert_to_utf8_byte_buffer_id = rb_intern("convert_to_utf8_byte_buffer"); + convert_to_string_id = rb_intern("convert_to_string"); + + // constant ids + fields_const_id = rb_intern("FIELDS"); + transport_ivar_id = rb_intern("@trans"); + strict_read_ivar_id = rb_intern("@strict_read"); + strict_write_ivar_id = rb_intern("@strict_write"); + + // cached symbols + type_sym = ID2SYM(rb_intern("type")); + name_sym = ID2SYM(rb_intern("name")); + key_sym = ID2SYM(rb_intern("key")); + value_sym = ID2SYM(rb_intern("value")); + element_sym = ID2SYM(rb_intern("element")); + class_sym = ID2SYM(rb_intern("class")); + binary_sym = ID2SYM(rb_intern("binary")); + + Init_struct(); + Init_binary_protocol_accelerated(); + Init_compact_protocol(); + Init_memory_buffer(); +} diff --git a/vendor/github.com/apache/thrift/test/README.md b/vendor/github.com/apache/thrift/test/README.md new file mode 100755 index 000000000..0682f5d98 --- /dev/null +++ b/vendor/github.com/apache/thrift/test/README.md @@ -0,0 +1,185 @@ +# Apache Thrift - integration test suite + +This is the cross everything integration test suite for Apache Thrift. + +## Run + +### A. Using Make + +The test can be executed by: + + make cross + +This starts the [test.py](test.py) script which does the real cross test with +different transports, protocols and languages. + +Note that this skips any language that is not built locally. It also skips +tests that are known to be failing. If you need more control over which tests +to run, read following section. + +### B. Using test script directly + +Alternatively, you can invoke [test.py](test.py) directly. You need to run`make +precross` once before executing it for the first time. + +For example, if you changed something in `nodejs` library and need to verify +the patch, you can skip everything except `nodejs` itself and some reference +implementation (currently `cpp` and `java` are recommended) like this: + + ./configure --without-c_glib -without-csharp --without-erlang --without-lua ... + make precross -j8 + test/test.py --server cpp,java --client nodejs + test/test.py --server nodejs --client cpp,java + +Another useful flag is --regex. For example, to run all tests that involve +Java TBinaryProtocol: + + test/test.py --regex "java.*binary" + +## Test case definition file + +The cross test cases are defined in [tests.json](tests.json). +The root element is collection of test target definitions. +Each test target definition looks like this: + + { + "name": "somelib", + + "client": { + "command": ["somelib_client_executable"], + "workdir": "somelib/bin", + "protocols": ["binary"], + "transports": ["buffered"], + "sockets": ["ip"], + }, + "server": { + "command": ["somelib_server_executable"], + "workdir": "somelib/bin", + "protocols": ["binary"], + "transports": ["buffered"], + "sockets": ["ip", "ip-ssl"], + } + } + +Either client or server definition or both should be present. + +Parameters that are common to both `client` and `server` can be put to target +definition root: + + { + "name": "somelib", + + "workdir": "somelib/bin", + "protocols": ["binary"], + "transports": ["buffered"], + "sockets": ["ip"], + + "client": { "command": ["somelib_client_executable"] }, + "server": { + "command": ["somelib_server_executable"], + "sockets": ["ip-ssl"] + } + } + +For the complete list of supported keys and their effect, see source code +comment at the opt of [crossrunner/collect.py](crossrunner/collect.py). + + +## List of known failures + +Since many cross tests currently fail (mainly due to partial incompatibility +around exception handling), the test script specifically report for "not known +before" failures. + +For this purpose, test cases known to (occasionally) fail are listed in +`known_failures_.json` where `` matches with python +`platform.system()` string. + +Currently, only Linux version is included. + +FYI, the file is initially generated by + + test/test.py --update-expected-failures=overwrite + +after a full test run, then repeatedly + + test/test.py --skip-known-failures + test/test.py --update-expected-failures=merge + +to update the known failures, run + + make fail + +## Test executable specification + +### Command line parameters + +Unit tests for languages are usually located under lib//test/ +cross language tests according to [ThriftTest.thrift](ThriftTest.thrift) shall be +provided for every language including executables with the following command +line interface: + +**Server command line interface:** + + $ ./cpp/TestServer -h + Allowed options: + -h [ --help ] produce help message + --port arg (=9090) Port number to listen + --domain-socket arg Unix Domain Socket (e.g. /tmp/ThriftTest.thrift) + --named-pipe arg Windows Named Pipe (e.g. MyThriftPipe) + --server-type arg (=simple) type of server, "simple", "thread-pool", + "threaded", or "nonblocking" + --transport arg (=buffered) transport: buffered, framed, http, anonpipe + --protocol arg (=binary) protocol: binary, compact, json + --ssl Encrypted Transport using SSL + --processor-events processor-events + -n [ --workers ] arg (=4) Number of thread pools workers. Only valid for + thread-pool server type + +**Client command line interface:** + + $ ./cpp/TestClient -h + Allowed options: + -h [ --help ] produce help message + --host arg (=localhost) Host to connect + --port arg (=9090) Port number to connect + --domain-socket arg Domain Socket (e.g. /tmp/ThriftTest.thrift), + instead of host and port + --named-pipe arg Windows Named Pipe (e.g. MyThriftPipe) + --anon-pipes hRead hWrite Windows Anonymous Pipes pair (handles) + --transport arg (=buffered) Transport: buffered, framed, http, evhttp + --protocol arg (=binary) Protocol: binary, compact, json + --ssl Encrypted Transport using SSL + -n [ --testloops ] arg (=1) Number of Tests + -t [ --threads ] arg (=1) Number of Test threads + +If you have executed the **make check** or **make cross** then you will be able to browse +[gen-html/ThriftTest.html](gen-html/ThriftTest.html) with the test documentation. + +### Return code + +The return code (exit code) shall be 0 on success, or an integer in the range 1 - 255 on errors. +In order to signal failed tests, the return code shall be composed from these bits to indicate +failing tests: + + #define TEST_BASETYPES 1 // 0000 0001 + #define TEST_STRUCTS 2 // 0000 0010 + #define TEST_CONTAINERS 4 // 0000 0100 + #define TEST_EXCEPTIONS 8 // 0000 1000 + #define TEST_UNKNOWN 64 // 0100 0000 (Failed to prepare environemt etc.) + #define TEST_TIMEOUT 128 // 1000 0000 + #define TEST_NOTUSED 48 // 0011 0000 (reserved bits) + +Tests that have not been executed at all count as errors. + +**Example:** + +During tests, the test client notices that some of the Struct tests fail. +Furthermore, due to some other problem none of the Exception tests is executed. +Therefore, the test client returns the code `10 = 2 | 8`, indicating the failure +of both test 2 (TEST_STRUCTS) and test 8 (TEST_EXCEPTIONS). + + +## SSL +Test Keys and Certificates are provided in multiple formats under the following +directory [test/keys](keys) diff --git a/vendor/github.com/apache/thrift/test/c_glib/src/test_client.c b/vendor/github.com/apache/thrift/test/c_glib/src/test_client.c new file mode 100644 index 000000000..3ae9325d4 --- /dev/null +++ b/vendor/github.com/apache/thrift/test/c_glib/src/test_client.c @@ -0,0 +1,1600 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT 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 +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "../gen-c_glib/t_test_thrift_test.h" + +/* Handle SIGPIPE signals (indicating the server has closed the + connection prematurely) by outputting an error message before + exiting. */ +static void +sigpipe_handler (int signal_number) +{ + THRIFT_UNUSED_VAR (signal_number); + + /* Flush standard output to make sure the test results so far are + logged */ + fflush (stdout); + + fputs ("Broken pipe (server closed connection prematurely)\n", stderr); + fflush (stderr); + + /* Re-raise the signal, this time invoking the default signal + handler, to terminate the program */ + raise (SIGPIPE); +} + +/* Compare two gint32 values. Used for sorting and finding integer + values within a GList. */ +static gint +gint32_compare (gconstpointer a, gconstpointer b) +{ + gint32 int32_a = *(gint32 *)a; + gint32 int32_b = *(gint32 *)b; + int result = 0; + + if (int32_a < int32_b) + result = -1; + else if (int32_a > int32_b) + result = 1; + + return result; +} + +int +main (int argc, char **argv) +{ + static gchar *host = NULL; + static gint port = 9090; + static gchar *transport_option = NULL; + static gchar *protocol_option = NULL; + static gint num_tests = 1; + + static + GOptionEntry option_entries[] ={ + { "host", 0, 0, G_OPTION_ARG_STRING, &host, + "Host to connect (=localhost)", NULL }, + { "port", 0, 0, G_OPTION_ARG_INT, &port, + "Port number to connect (=9090)", NULL }, + { "transport", 0, 0, G_OPTION_ARG_STRING, &transport_option, + "Transport: buffered, framed (=buffered)", NULL }, + { "protocol", 0, 0, G_OPTION_ARG_STRING, &protocol_option, + "Protocol: binary, compact (=binary)", NULL }, + { "testloops", 'n', 0, G_OPTION_ARG_INT, &num_tests, + "Number of tests (=1)", NULL }, + { NULL } + }; + + struct sigaction sigpipe_action; + + GType transport_type = THRIFT_TYPE_BUFFERED_TRANSPORT; + gchar *transport_name = "buffered"; + GType protocol_type = THRIFT_TYPE_BINARY_PROTOCOL; + gchar *protocol_name = "binary"; + + ThriftSocket *socket; + ThriftTransport *transport; + ThriftProtocol *protocol; + + TTestThriftTestIf *test_client; + + struct timeval time_start, time_stop, time_elapsed; + guint64 time_elapsed_usec, time_total_usec = 0; + guint64 time_min_usec = G_MAXUINT64, time_max_usec = 0, time_avg_usec; + + GOptionContext *option_context; + gboolean options_valid = TRUE; + int test_num = 0; + int fail_count = 0; + GError *error = NULL; + +#if (!GLIB_CHECK_VERSION (2, 36, 0)) + g_type_init (); +#endif + + /* Configure and parse our command-line options */ + option_context = g_option_context_new (NULL); + g_option_context_add_main_entries (option_context, + option_entries, + NULL); + if (!g_option_context_parse (option_context, + &argc, + &argv, + &error)) { + fprintf (stderr, "%s\n", error->message); + return 255; + } + g_option_context_free (option_context); + + /* Set remaining default values for unspecified options */ + if (host == NULL) + host = g_strdup ("localhost"); + + /* Validate the parsed options */ + if (protocol_option != NULL) { + if (strncmp (protocol_option, "compact", 8) == 0) { + protocol_type = THRIFT_TYPE_COMPACT_PROTOCOL; + protocol_name = "compact"; + } + else if (strncmp (protocol_option, "binary", 7) != 0) { + fprintf (stderr, "Unknown protocol type %s\n", protocol_option); + options_valid = FALSE; + } + } + + if (transport_option != NULL) { + if (strncmp (transport_option, "framed", 7) == 0) { + transport_type = THRIFT_TYPE_FRAMED_TRANSPORT; + transport_name = "framed"; + } + else if (strncmp (transport_option, "buffered", 9) != 0) { + fprintf (stderr, "Unknown transport type %s\n", transport_option); + options_valid = FALSE; + } + } + + if (!options_valid) + return 254; + + printf ("Connecting (%s/%s) to: %s:%d\n", + transport_name, + protocol_name, + host, + port); + + /* Install our SIGPIPE handler, which outputs an error message to + standard error before exiting so testers can know what + happened */ + memset (&sigpipe_action, 0, sizeof (sigpipe_action)); + sigpipe_action.sa_handler = sigpipe_handler; + sigpipe_action.sa_flags = SA_RESETHAND; + sigaction (SIGPIPE, &sigpipe_action, NULL); + + /* Establish all our connection objects */ + socket = g_object_new (THRIFT_TYPE_SOCKET, + "hostname", host, + "port", port, + NULL); + transport = g_object_new (transport_type, + "transport", socket, + NULL); + protocol = g_object_new (protocol_type, + "transport", transport, + NULL); + test_client = g_object_new (T_TEST_TYPE_THRIFT_TEST_CLIENT, + "input_protocol", protocol, + "output_protocol", protocol, + NULL); + + /* Execute the actual tests */ + for (test_num = 0; test_num < num_tests; ++test_num) { + if (thrift_transport_open (transport, &error)) { + gchar *string = NULL; + gboolean boolean = 0; + gint8 byte = 0; + gint32 int32 = 0; + gint64 int64 = 0; + gdouble dub = 0; + + gint byte_thing, i32_thing, inner_byte_thing, inner_i32_thing; + gint64 i64_thing, inner_i64_thing; + + TTestXtruct *xtruct_out, *xtruct_out2, *xtruct_in, *inner_xtruct_in; + TTestXtruct2 *xtruct2_out, *xtruct2_in; + + GHashTable *map_out, *map_in, *inner_map_in; + GHashTable *set_out, *set_in; + gpointer key, value; + gint32 *i32_key_ptr, *i32_value_ptr; + GHashTableIter hash_table_iter, inner_hash_table_iter; + GList *keys_out, *keys_in, *keys_elem; + + GArray *list_out, *list_in; + + TTestNumberz numberz; + TTestNumberz numberz2; + + TTestUserId user_id, *user_id_ptr, *user_id_ptr2; + + TTestInsanity *insanity_out, *insanity_in; + GHashTable *user_map; + GHashTableIter user_map_iter; + GPtrArray *xtructs; + + TTestXception *xception = NULL; + TTestXception2 *xception2 = NULL; + + gboolean oneway_result; + struct timeval oneway_start, oneway_end, oneway_elapsed; + gint oneway_elapsed_usec; + + gboolean first; + gint32 i, j; + + printf ("Test #%d, connect %s:%d\n", test_num + 1, host, port); + gettimeofday (&time_start, NULL); + + /* These test routines have been ported from the C++ test + client, care being taken to ensure their output remains as + close as possible to the original to facilitate diffs. + + For simplicity comments have been omitted, but every routine + has the same basic structure: + + - Create and populate data structures as necessary. + + - Format and output (to the console) a representation of the + outgoing data. + + - Issue the remote method call to the server. + + - Format and output a representation of the returned data. + + - Verify the returned data matches what was expected. + + - Deallocate any created data structures. + + Note the recognized values and expected behaviour of each + remote method are described in ThriftTest.thrift, which + you'll find in the top-level "test" folder. */ + + /** + * VOID TEST + */ + printf ("testVoid()"); + if (t_test_thrift_test_if_test_void (test_client, &error)) { + printf (" = void\n"); + } + else { + printf ("%s\n", error->message); + g_error_free (error); + error = NULL; + + fail_count++; + } + + /** + * STRING TEST + */ + printf ("testString(\"Test\")"); + if (t_test_thrift_test_if_test_string (test_client, + &string, + "Test", + &error)) { + printf (" = \"%s\"\n", string); + if (strncmp (string, "Test", 5) != 0) + fail_count++; + + g_free (string); + string = NULL; + } + else { + printf ("%s\n", error->message); + g_error_free (error); + error = NULL; + + fail_count++; + } + + /** + * BOOL TEST + */ + printf ("testByte(true)"); + if (t_test_thrift_test_if_test_bool (test_client, + &boolean, + 1, + &error)) { + printf (" = %s\n", boolean ? "true" : "false"); + if (boolean != 1) + fail_count++; + } + else { + printf ("%s\n", error->message); + g_error_free (error); + error = NULL; + + fail_count++; + } + printf ("testByte(false)"); + if (t_test_thrift_test_if_test_bool (test_client, + &boolean, + 0, + &error)) { + printf (" = %s\n", boolean ? "true" : "false"); + if (boolean != 0) + fail_count++; + } + else { + printf ("%s\n", error->message); + g_error_free (error); + error = NULL; + + fail_count++; + } + + /** + * BYTE TEST + */ + printf ("testByte(1)"); + if (t_test_thrift_test_if_test_byte (test_client, + &byte, + 1, + &error)) { + printf (" = %d\n", byte); + if (byte != 1) + fail_count++; + } + else { + printf ("%s\n", error->message); + g_error_free (error); + error = NULL; + + fail_count++; + } + printf ("testByte(-1)"); + if (t_test_thrift_test_if_test_byte (test_client, + &byte, + -1, + &error)) { + printf (" = %d\n", byte); + if (byte != -1) + fail_count++; + } + else { + printf ("%s\n", error->message); + g_error_free (error); + error = NULL; + + fail_count++; + } + + /** + * I32 TEST + */ + printf ("testI32(-1)"); + if (t_test_thrift_test_if_test_i32 (test_client, + &int32, + -1, + &error)) { + printf (" = %d\n", int32); + if (int32 != -1) + fail_count++; + } + else { + printf ("%s\n", error->message); + g_error_free (error); + error = NULL; + + fail_count++; + } + + /** + * I64 TEST + */ + printf ("testI64(-34359738368)"); + if (t_test_thrift_test_if_test_i64 (test_client, + &int64, + (gint64)-34359738368, + &error)) { + printf (" = %" PRId64 "\n", int64); + if (int64 != (gint64)-34359738368) + fail_count++; + } + else { + printf ("%s\n", error->message); + g_error_free (error); + error = NULL; + + fail_count++; + } + + /** + * DOUBLE TEST + */ + printf("testDouble(-5.2098523)"); + if (t_test_thrift_test_if_test_double (test_client, + &dub, + -5.2098523, + &error)) { + printf (" = %f\n", dub); + if ((dub - (-5.2098523)) > 0.001) + fail_count++; + } + else { + printf ("%s\n", error->message); + g_error_free (error); + error = NULL; + + fail_count++; + } + + // TODO: add testBinary() + + /** + * STRUCT TEST + */ + printf ("testStruct({\"Zero\", 1, -3, -5})"); + xtruct_out = g_object_new (T_TEST_TYPE_XTRUCT, + "string_thing", "Zero", + "byte_thing", 1, + "i32_thing", -3, + "i64_thing", -5LL, + NULL); + xtruct_in = g_object_new (T_TEST_TYPE_XTRUCT, NULL); + + if (t_test_thrift_test_if_test_struct (test_client, + &xtruct_in, + xtruct_out, + &error)) { + g_object_get (xtruct_in, + "string_thing", &string, + "byte_thing", &byte_thing, + "i32_thing", &i32_thing, + "i64_thing", &i64_thing, + NULL); + + printf (" = {\"%s\", %d, %d, %" PRId64 "}\n", + string, + byte_thing, + i32_thing, + i64_thing); + if ((string == NULL || strncmp (string, "Zero", 5) != 0) || + byte_thing != 1 || + i32_thing != -3 || + i64_thing != (gint64)-5) + fail_count++; + } + else { + printf ("%s\n", error->message); + g_error_free (error); + error = NULL; + + fail_count++; + } + g_object_unref (xtruct_in); + + /** + * NESTED STRUCT TEST + */ + printf ("testNest({1, {\"Zero\", 1, -3, -5}), 5}"); + xtruct2_out = g_object_new (T_TEST_TYPE_XTRUCT2, + "byte_thing", 1, + "struct_thing", xtruct_out, + "i32_thing", 5, + NULL); + xtruct2_in = g_object_new (T_TEST_TYPE_XTRUCT2, NULL); + + if (t_test_thrift_test_if_test_nest (test_client, + &xtruct2_in, + xtruct2_out, + &error)) { + g_object_get (xtruct2_in, + "byte_thing", &byte_thing, + "struct_thing", &xtruct_in, + "i32_thing", &i32_thing, + NULL); + g_object_get (xtruct_in, + "string_thing", &string, + "byte_thing", &inner_byte_thing, + "i32_thing", &inner_i32_thing, + "i64_thing", &inner_i64_thing, + NULL); + + printf (" = {%d, {\"%s\", %d, %d, %" PRId64 "}, %d}\n", + byte_thing, + string, + inner_byte_thing, + inner_i32_thing, + inner_i64_thing, + i32_thing); + if (byte_thing != 1 || + (string == NULL || strncmp (string, "Zero", 5) != 0) || + inner_byte_thing != 1 || + inner_i32_thing != -3 || + inner_i64_thing != (gint64)-5 || + i32_thing != 5) + fail_count++; + } + else { + printf ("%s\n", error->message); + g_error_free (error); + error = NULL; + + fail_count++; + } + + g_object_unref (xtruct_in); + g_object_unref (xtruct2_in); + g_object_unref (xtruct2_out); + g_object_unref (xtruct_out); + + /** + * MAP TEST + */ + map_out = g_hash_table_new_full (g_int_hash, + g_int_equal, + g_free, + g_free); + for (i = 0; i < 5; ++i) { + i32_key_ptr = g_malloc (sizeof *i32_key_ptr); + i32_value_ptr = g_malloc (sizeof *i32_value_ptr); + + *i32_key_ptr = i; + *i32_value_ptr = i - 10; + + g_hash_table_insert (map_out, i32_key_ptr, i32_value_ptr); + } + printf ("testMap({"); + first = TRUE; + g_hash_table_iter_init (&hash_table_iter, map_out); + while (g_hash_table_iter_next (&hash_table_iter, + &key, + &value)) { + if (first) + first = FALSE; + else + printf (", "); + + printf ("%d => %d", *(gint32 *)key, *(gint32 *)value); + } + printf ("})"); + + map_in = g_hash_table_new_full (g_int_hash, + g_int_equal, + g_free, + g_free); + + if (t_test_thrift_test_if_test_map (test_client, + &map_in, + map_out, + &error)) { + printf (" = {"); + first = TRUE; + g_hash_table_iter_init (&hash_table_iter, map_in); + while (g_hash_table_iter_next (&hash_table_iter, + &key, + &value)) { + if (first) + first = FALSE; + else + printf (", "); + + printf ("%d => %d", *(gint32 *)key, *(gint32 *)value); + } + printf ("}\n"); + + if (g_hash_table_size (map_in) != g_hash_table_size (map_out)) + fail_count++; + else { + g_hash_table_iter_init (&hash_table_iter, map_out); + while (g_hash_table_iter_next (&hash_table_iter, + &key, + &value)) { + gpointer in_value = g_hash_table_lookup (map_in, key); + if (in_value == NULL || + *(gint32 *)in_value != *(gint32 *)value) { + fail_count++; + break; + } + } + } + } + else { + printf ("%s\n", error->message); + g_error_free (error); + error = NULL; + + fail_count++; + } + + g_hash_table_unref (map_in); + g_hash_table_unref (map_out); + + /** + * STRING MAP TEST + */ + map_out = g_hash_table_new_full (g_str_hash, + g_str_equal, + NULL, + NULL); + g_hash_table_insert (map_out, "a", "2"); + g_hash_table_insert (map_out, "b", "blah"); + g_hash_table_insert (map_out, "some", "thing"); + printf ("testStringMap({"); + first = TRUE; + g_hash_table_iter_init (&hash_table_iter, map_out); + while (g_hash_table_iter_next (&hash_table_iter, + &key, + &value)) { + if (first) + first = FALSE; + else + printf (", "); + + printf ("\"%s\" => \"%s\"", (gchar *)key, (gchar *)value); + } + printf (")}"); + + map_in = g_hash_table_new_full (g_str_hash, + g_str_equal, + g_free, + g_free); + + if (t_test_thrift_test_if_test_string_map (test_client, + &map_in, + map_out, + &error)) { + printf (" = {"); + first = TRUE; + g_hash_table_iter_init (&hash_table_iter, map_in); + while (g_hash_table_iter_next (&hash_table_iter, + &key, + &value)) { + if (first) + first = FALSE; + else + printf (", "); + + printf ("\"%s\" => \"%s\"", (gchar *)key, (gchar *)value); + } + printf ("}\n"); + + if (g_hash_table_size (map_in) != g_hash_table_size (map_out)) + fail_count++; + else { + g_hash_table_iter_init (&hash_table_iter, map_out); + while (g_hash_table_iter_next (&hash_table_iter, + &key, + &value)) { + gpointer in_value = g_hash_table_lookup (map_in, key); + if (in_value == NULL || + strcmp ((gchar *)in_value, (gchar *)value) != 0) { + fail_count++; + break; + } + } + } + } + else { + printf ("%s\n", error->message); + g_error_free (error); + error = NULL; + + fail_count++; + } + + g_hash_table_unref (map_in); + g_hash_table_unref (map_out); + + /** + * SET TEST + */ + set_out = g_hash_table_new_full (g_int_hash, g_int_equal, g_free, NULL); + for (i = -2; i < 3; ++i) { + i32_key_ptr = g_malloc (sizeof *i32_key_ptr); + *i32_key_ptr = i; + + g_hash_table_insert (set_out, i32_key_ptr, NULL); + } + printf ("testSet({"); + first = TRUE; + keys_out = g_hash_table_get_keys (set_out); + keys_elem = keys_out; + while (keys_elem != NULL) { + if (first) + first = FALSE; + else + printf (", "); + + printf ("%d", *(gint32 *)keys_elem->data); + + keys_elem = keys_elem->next; + } + printf ("})"); + + set_in = g_hash_table_new_full (g_int_hash, g_int_equal, g_free, NULL); + + if (t_test_thrift_test_if_test_set (test_client, + &set_in, + set_out, + &error)) { + printf(" = {"); + first = TRUE; + keys_in = g_hash_table_get_keys (set_in); + keys_elem = keys_in; + while (keys_elem != NULL) { + if (first) + first = FALSE; + else + printf (", "); + + printf ("%d", *(gint32 *)keys_elem->data); + + keys_elem = keys_elem->next; + } + printf ("}\n"); + + if (g_list_length (keys_in) != g_list_length (keys_out)) + fail_count++; + else { + keys_elem = keys_out; + while (keys_elem != NULL) { + if (g_list_find_custom (keys_in, + keys_elem->data, + gint32_compare) == NULL) { + fail_count++; + break; + } + + keys_elem = keys_elem->next; + } + } + + g_list_free (keys_in); + } + else { + printf ("%s\n", error->message); + g_error_free (error); + error = NULL; + + fail_count++; + } + + g_hash_table_unref (set_in); + g_list_free (keys_out); + g_hash_table_unref (set_out); + + /** + * LIST TEST + */ + list_out = g_array_new (FALSE, TRUE, sizeof (gint32)); + for (i = -2; i < 3; ++i) { + g_array_append_val (list_out, i); + } + printf ("testList({"); + first = TRUE; + for (i = 0; i < (gint32)list_out->len; ++i) { + if (first) + first = FALSE; + else + printf (", "); + + printf ("%d", g_array_index (list_out, gint32, i)); + } + printf ("})"); + + list_in = g_array_new (FALSE, TRUE, sizeof (gint32)); + + if (t_test_thrift_test_if_test_list (test_client, + &list_in, + list_out, + &error)) { + printf (" = {"); + first = TRUE; + for (i = 0; i < (gint32)list_in->len; ++i) { + if (first) + first = FALSE; + else + printf (", "); + + printf ("%d", g_array_index (list_in, gint32, i)); + } + printf ("}\n"); + + if (list_in->len != list_out->len || + memcmp (list_in->data, + list_out->data, + list_in->len * sizeof (gint32)) != 0) + fail_count++; + } + else { + printf ("%s\n", error->message); + g_error_free (error); + error = NULL; + + fail_count++; + } + + g_array_unref (list_in); + g_array_unref (list_out); + + /** + * ENUM TEST + */ + printf("testEnum(ONE)"); + if (t_test_thrift_test_if_test_enum (test_client, + &numberz, + T_TEST_NUMBERZ_ONE, + &error)) { + printf(" = %d\n", numberz); + if (numberz != T_TEST_NUMBERZ_ONE) + fail_count++; + } + else { + printf ("%s\n", error->message); + g_error_free (error); + error = NULL; + + fail_count++; + } + + printf("testEnum(TWO)"); + if (t_test_thrift_test_if_test_enum (test_client, + &numberz, + T_TEST_NUMBERZ_TWO, + &error)) { + printf(" = %d\n", numberz); + if (numberz != T_TEST_NUMBERZ_TWO) + fail_count++; + } + else { + printf ("%s\n", error->message); + g_error_free (error); + error = NULL; + + fail_count++; + } + + printf("testEnum(THREE)"); + if (t_test_thrift_test_if_test_enum (test_client, + &numberz, + T_TEST_NUMBERZ_THREE, + &error)) { + printf(" = %d\n", numberz); + if (numberz != T_TEST_NUMBERZ_THREE) + fail_count++; + } + else { + printf ("%s\n", error->message); + g_error_free (error); + error = NULL; + + fail_count++; + } + + printf("testEnum(FIVE)"); + if (t_test_thrift_test_if_test_enum (test_client, + &numberz, + T_TEST_NUMBERZ_FIVE, + &error)) { + printf(" = %d\n", numberz); + if (numberz != T_TEST_NUMBERZ_FIVE) + fail_count++; + } + else { + printf ("%s\n", error->message); + g_error_free (error); + error = NULL; + + fail_count++; + } + + printf("testEnum(EIGHT)"); + if (t_test_thrift_test_if_test_enum (test_client, + &numberz, + T_TEST_NUMBERZ_EIGHT, + &error)) { + printf(" = %d\n", numberz); + if (numberz != T_TEST_NUMBERZ_EIGHT) + fail_count++; + } + else { + printf ("%s\n", error->message); + g_error_free (error); + error = NULL; + + fail_count++; + } + + /** + * TYPEDEF TEST + */ + printf ("testTypedef(309858235082523)"); + if (t_test_thrift_test_if_test_typedef (test_client, + &user_id, + 309858235082523LL, + &error)) { + printf(" = %" PRId64 "\n", user_id); + if (user_id != 309858235082523LL) + fail_count++; + } + else { + printf ("%s\n", error->message); + g_error_free (error); + error = NULL; + + fail_count++; + } + + /** + * NESTED MAP TEST + */ + printf ("testMapMap(1)"); + map_in = g_hash_table_new_full (g_int_hash, + g_int_equal, + g_free, + (GDestroyNotify)g_hash_table_unref); + if (t_test_thrift_test_if_test_map_map (test_client, + &map_in, + 1, + &error)) { + g_hash_table_iter_init (&hash_table_iter, map_in); + + printf (" = {"); + while (g_hash_table_iter_next (&hash_table_iter, + &key, + &value)) { + printf ("%d => {", *(gint32 *)key); + + g_hash_table_iter_init (&inner_hash_table_iter, + (GHashTable *)value); + while (g_hash_table_iter_next (&inner_hash_table_iter, + &key, + &value)) { + printf ("%d => %d, ", *(gint32 *)key, *(gint32 *)value); + } + + printf ("}, "); + } + printf ("}\n"); + + if (g_hash_table_size (map_in) != 2) + fail_count++; + else { + gint32 inner_keys[] = {1, 2, 3, 4}; + gint32 i32_key; + + i32_key = -4; + inner_map_in = g_hash_table_lookup (map_in, &i32_key); + if (inner_map_in == NULL || + g_hash_table_size (inner_map_in) != 4) + fail_count++; + else { + keys_in = g_hash_table_get_keys (inner_map_in); + keys_in = g_list_sort (keys_in, gint32_compare); + + for (i = 0; i < 4; i++) { + keys_elem = g_list_nth (keys_in, 3 - i); + + if (*(gint32 *)keys_elem->data != (-1 * inner_keys[i]) || + *(gint32 *)g_hash_table_lookup (inner_map_in, + keys_elem->data) != + (-1 * inner_keys[i])) { + fail_count++; + break; + } + } + + g_list_free (keys_in); + } + + i32_key = 4; + inner_map_in = g_hash_table_lookup (map_in, &i32_key); + if (inner_map_in == NULL || + g_hash_table_size (inner_map_in) != 4) + fail_count++; + else { + keys_in = g_hash_table_get_keys (inner_map_in); + keys_in = g_list_sort (keys_in, gint32_compare); + + for (i = 0; i < 4; i++) { + keys_elem = g_list_nth (keys_in, i); + + if (*(gint32 *)keys_elem->data != inner_keys[i] || + *(gint32 *)g_hash_table_lookup (inner_map_in, + keys_elem->data) != + inner_keys[i]) { + fail_count++; + break; + } + } + + g_list_free (keys_in); + } + } + } + else { + printf ("%s\n", error->message); + g_error_free (error); + error = NULL; + + fail_count++; + } + + g_hash_table_unref (map_in); + + /** + * INSANITY TEST + */ + insanity_out = g_object_new (T_TEST_TYPE_INSANITY, NULL); + g_object_get (insanity_out, + "userMap", &user_map, + "xtructs", &xtructs, + NULL); + + numberz = T_TEST_NUMBERZ_FIVE; + numberz2 = T_TEST_NUMBERZ_EIGHT; + user_id_ptr = g_malloc (sizeof *user_id_ptr); + *user_id_ptr = 5; + user_id_ptr2 = g_malloc (sizeof *user_id_ptr); + *user_id_ptr2 = 8; + g_hash_table_insert (user_map, (gpointer)numberz, user_id_ptr); + g_hash_table_insert (user_map, (gpointer)numberz2, user_id_ptr2); + g_hash_table_unref (user_map); + + xtruct_out = g_object_new (T_TEST_TYPE_XTRUCT, + "string_thing", "Hello2", + "byte_thing", 2, + "i32_thing", 2, + "i64_thing", 2LL, + NULL); + xtruct_out2 = g_object_new (T_TEST_TYPE_XTRUCT, + "string_thing", "Goodbye4", + "byte_thing", 4, + "i32_thing", 4, + "i64_thing", 4LL, + NULL); + g_ptr_array_add (xtructs, xtruct_out2); + g_ptr_array_add (xtructs, xtruct_out); + g_ptr_array_unref (xtructs); + + map_in = g_hash_table_new_full (g_int64_hash, + g_int64_equal, + g_free, + (GDestroyNotify)g_hash_table_unref); + + printf("testInsanity()"); + if (t_test_thrift_test_if_test_insanity (test_client, + &map_in, + insanity_out, + &error)) { + printf (" = {"); + g_hash_table_iter_init (&hash_table_iter, map_in); + while (g_hash_table_iter_next (&hash_table_iter, + &key, + &value)) { + printf ("%" PRId64 " => {", *(TTestUserId *)key); + + g_hash_table_iter_init (&inner_hash_table_iter, + (GHashTable *)value); + while (g_hash_table_iter_next (&inner_hash_table_iter, + &key, + &value)) { + printf ("%d => {", (TTestNumberz)key); + + g_object_get ((TTestInsanity *)value, + "userMap", &user_map, + "xtructs", &xtructs, + NULL); + + printf ("{"); + g_hash_table_iter_init (&user_map_iter, user_map); + while (g_hash_table_iter_next (&user_map_iter, + &key, + &value)) { + printf ("%d => %" PRId64 ", ", + (TTestNumberz)key, + *(TTestUserId *)value); + } + printf ("}, "); + g_hash_table_unref (user_map); + + printf("{"); + for (i = 0; i < (gint32)xtructs->len; ++i) { + xtruct_in = g_ptr_array_index (xtructs, i); + g_object_get (xtruct_in, + "string_thing", &string, + "byte_thing", &byte_thing, + "i32_thing", &i32_thing, + "i64_thing", &i64_thing, + NULL); + + printf ("{\"%s\", %d, %d, %" PRId64 "}, ", + string, + byte_thing, + i32_thing, + i64_thing); + } + printf ("}"); + g_ptr_array_unref (xtructs); + + printf ("}, "); + } + printf("}, "); + } + printf("}\n"); + + if (g_hash_table_size (map_in) != 2) + fail_count++; + else { + TTestNumberz numberz_key_values[] = { + T_TEST_NUMBERZ_TWO, T_TEST_NUMBERZ_THREE + }; + gint user_map_values[] = { 5, 8 }; + TTestUserId user_id_key; + + user_id_key = 1; + inner_map_in = g_hash_table_lookup (map_in, &user_id_key); + if (inner_map_in == NULL || + g_hash_table_size (inner_map_in) != 2) + fail_count++; + else { + TTestNumberz numberz_key; + + for (i = 0; i < 2; ++i) { + numberz_key = numberz_key_values[i]; + insanity_in = + g_hash_table_lookup (inner_map_in, + (gconstpointer)numberz_key); + if (insanity_in == NULL) + fail_count++; + else { + g_object_get (insanity_in, + "userMap", &user_map, + "xtructs", &xtructs, + NULL); + + if (user_map == NULL) + fail_count++; + else { + if (g_hash_table_size (user_map) != 2) + fail_count++; + else { + for (j = 0; j < 2; ++j) { + numberz_key = (TTestNumberz)user_map_values[j]; + + value = + g_hash_table_lookup (user_map, + (gconstpointer)numberz_key); + if (value == NULL || + *(TTestUserId *)value != (TTestUserId)user_map_values[j]) + fail_count++; + } + } + + g_hash_table_unref (user_map); + } + + if (xtructs == NULL) + fail_count++; + else { + if (xtructs->len != 2) + fail_count++; + else { + xtruct_in = g_ptr_array_index (xtructs, 0); + g_object_get (xtruct_in, + "string_thing", &string, + "byte_thing", &byte_thing, + "i32_thing", &i32_thing, + "i64_thing", &i64_thing, + NULL); + if ((string == NULL || + strncmp (string, "Goodbye4", 9) != 0) || + byte_thing != 4 || + i32_thing != 4 || + i64_thing != 4) + fail_count++; + + if (string != NULL) + g_free (string); + + xtruct_in = g_ptr_array_index (xtructs, 1); + g_object_get (xtruct_in, + "string_thing", &string, + "byte_thing", &byte_thing, + "i32_thing", &i32_thing, + "i64_thing", &i64_thing, + NULL); + if ((string == NULL || + strncmp (string, "Hello2", 7) != 0) || + byte_thing != 2 || + i32_thing != 2 || + i64_thing != 2) + fail_count++; + + if (string != NULL) + g_free (string); + } + + g_ptr_array_unref (xtructs); + } + } + } + } + + user_id_key = 2; + inner_map_in = g_hash_table_lookup (map_in, &user_id_key); + if (inner_map_in == NULL || + g_hash_table_size (inner_map_in) != 1) + fail_count++; + else { + insanity_in = + g_hash_table_lookup (inner_map_in, + (gconstpointer)T_TEST_NUMBERZ_SIX); + if (insanity_in == NULL) + fail_count++; + else { + g_object_get (insanity_in, + "userMap", &user_map, + "xtructs", &xtructs, + NULL); + + if (user_map == NULL) + fail_count++; + else { + if (g_hash_table_size (user_map) != 0) + fail_count++; + + g_hash_table_unref (user_map); + } + + if (xtructs == NULL) + fail_count++; + else { + if (xtructs->len != 0) + fail_count++; + + g_ptr_array_unref (xtructs); + } + } + } + } + } + else { + printf ("%s\n", error->message); + g_error_free (error); + error = NULL; + + fail_count++; + } + + g_hash_table_unref (map_in); + g_object_unref (insanity_out); + + /* test exception */ + printf ("testClient.testException(\"Xception\") =>"); + if (!t_test_thrift_test_if_test_exception (test_client, + "Xception", + &xception, + &error) && + xception != NULL) { + g_object_get (xception, + "errorCode", &int32, + "message", &string, + NULL); + printf (" {%u, \"%s\"}\n", int32, string); + g_free (string); + + g_object_unref (xception); + xception = NULL; + + g_error_free (error); + error = NULL; + } + else { + printf (" void\nFAILURE\n"); + fail_count++; + + if (xception != NULL) { + g_object_unref (xception); + xception = NULL; + } + + if (error != NULL) { + g_error_free (error); + error = NULL; + } + } + + printf ("testClient.testException(\"TException\") =>"); + if (!t_test_thrift_test_if_test_exception (test_client, + "TException", + &xception, + &error) && + xception == NULL && + error != NULL) { + printf (" Caught TException\n"); + + g_error_free (error); + error = NULL; + } + else { + printf (" void\nFAILURE\n"); + fail_count++; + + if (xception != NULL) { + g_object_unref (xception); + xception = NULL; + } + + if (error != NULL) { + g_error_free (error); + error = NULL; + } + } + + printf ("testClient.testException(\"success\") =>"); + if (t_test_thrift_test_if_test_exception (test_client, + "success", + &xception, + &error)) + printf (" void\n"); + else { + printf (" void\nFAILURE\n"); + fail_count++; + + if (xception != NULL) { + g_object_unref (xception); + xception = NULL; + } + + g_error_free (error); + error = NULL; + } + + g_assert (error == NULL); + + /* test multi exception */ + printf ("testClient.testMultiException(\"Xception\", \"test 1\") =>"); + xtruct_in = g_object_new (T_TEST_TYPE_XTRUCT, NULL); + if (!t_test_thrift_test_if_test_multi_exception (test_client, + &xtruct_in, + "Xception", + "test 1", + &xception, + &xception2, + &error) && + xception != NULL && + xception2 == NULL) { + g_object_get (xception, + "errorCode", &int32, + "message", &string, + NULL); + printf (" {%u, \"%s\"}\n", int32, string); + g_free (string); + + g_object_unref (xception); + xception = NULL; + + g_error_free (error); + error = NULL; + } + else { + printf (" result\nFAILURE\n"); + fail_count++; + + if (xception != NULL) { + g_object_unref (xception); + xception = NULL; + } + + if (xception2 != NULL) { + g_object_unref (xception2); + xception = NULL; + } + + if (error != NULL) { + g_error_free (error); + error = NULL; + } + } + g_object_unref (xtruct_in); + + printf ("testClient.testMultiException(\"Xception2\", \"test 2\") =>"); + xtruct_in = g_object_new (T_TEST_TYPE_XTRUCT, NULL); + if (!t_test_thrift_test_if_test_multi_exception (test_client, + &xtruct_in, + "Xception2", + "test 2", + &xception, + &xception2, + &error) && + xception == NULL && + xception2 != NULL) { + g_object_get (xception2, + "errorCode", &int32, + "struct_thing", &inner_xtruct_in, + NULL); + g_object_get (inner_xtruct_in, + "string_thing", &string, + NULL); + printf (" {%u, {\"%s\"}}\n", int32, string); + g_free (string); + + g_object_unref (inner_xtruct_in); + inner_xtruct_in = NULL; + + g_object_unref (xception2); + xception2 = NULL; + + g_error_free (error); + error = NULL; + } + else { + printf (" result\nFAILURE\n"); + fail_count++; + + if (xception != NULL) { + g_object_unref (xception); + xception = NULL; + } + + if (xception2 != NULL) { + g_object_unref (xception2); + xception = NULL; + } + + if (error != NULL) { + g_error_free (error); + error = NULL; + } + } + g_object_unref (xtruct_in); + + printf ("testClient.testMultiException(\"success\", \"test 3\") =>"); + xtruct_in = g_object_new (T_TEST_TYPE_XTRUCT, NULL); + if (t_test_thrift_test_if_test_multi_exception (test_client, + &xtruct_in, + "success", + "test 3", + &xception, + &xception2, + &error) && + xception == NULL && + xception2 == NULL) { + g_object_get (xtruct_in, + "string_thing", &string, + NULL); + printf (" {{\"%s\"}}\n", string); + g_free (string); + } + else { + printf (" result\nFAILURE\n"); + fail_count++; + + if (xception != NULL) { + g_object_unref (xception); + xception = NULL; + } + + if (xception2 != NULL) { + g_object_unref (xception2); + xception = NULL; + } + + if (error != NULL) { + g_error_free (error); + error = NULL; + } + } + g_object_unref (xtruct_in); + + /* test oneway void */ + printf ("testClient.testOneway(1) =>"); + gettimeofday (&oneway_start, NULL); + oneway_result = t_test_thrift_test_if_test_oneway (test_client, + 1, + &error); + gettimeofday (&oneway_end, NULL); + timersub (&oneway_end, &oneway_start, &oneway_elapsed); + oneway_elapsed_usec = + oneway_elapsed.tv_sec * 1000 * 1000 + oneway_elapsed.tv_usec; + + if (oneway_result) { + if (oneway_elapsed_usec > 200 * 1000) { + printf (" FAILURE - took %.2f ms\n", + (double)oneway_elapsed_usec / 1000.0); + fail_count++; + } + else + printf (" success - took %.2f ms\n", + (double)oneway_elapsed_usec / 1000.0); + } + else { + printf ("%s\n", error->message); + g_error_free (error); + error = NULL; + + fail_count++; + } + + /** + * redo a simple test after the oneway to make sure we aren't "off by + * one" -- if the server treated oneway void like normal void, this next + * test will fail since it will get the void confirmation rather than + * the correct result. In this circumstance, the client will receive the + * error: + * + * application error: Wrong method name + */ + /** + * I32 TEST + */ + printf ("re-test testI32(-1)"); + if (t_test_thrift_test_if_test_i32 (test_client, + &int32, + -1, + &error)) { + printf (" = %d\n", int32); + if (int32 != -1) + fail_count++; + } + else { + printf ("%s\n", error->message); + g_error_free (error); + error = NULL; + + fail_count++; + } + + gettimeofday (&time_stop, NULL); + timersub (&time_stop, &time_start, &time_elapsed); + time_elapsed_usec = + time_elapsed.tv_sec * 1000 * 1000 + time_elapsed.tv_usec; + + printf("Total time: %" PRIu64 " us\n", time_elapsed_usec); + + time_total_usec += time_elapsed_usec; + if (time_elapsed_usec < time_min_usec) + time_min_usec = time_elapsed_usec; + if (time_elapsed_usec > time_max_usec) + time_max_usec = time_elapsed_usec; + + thrift_transport_close (transport, &error); + } + else { + printf ("Connect failed: %s\n", error->message); + g_error_free (error); + error = NULL; + + return 1; + } + } + + /* All done---output statistics */ + puts ("\nAll tests done."); + + time_avg_usec = time_total_usec / num_tests; + + printf ("Min time: %" PRIu64 " us\n", time_min_usec); + printf ("Max time: %" PRIu64 " us\n", time_max_usec); + printf ("Avg time: %" PRIu64 " us\n", time_avg_usec); + + g_object_unref (test_client); + g_object_unref (protocol); + g_object_unref (transport); + g_free (host); + + return fail_count; +} diff --git a/vendor/github.com/apache/thrift/test/c_glib/src/test_server.c b/vendor/github.com/apache/thrift/test/c_glib/src/test_server.c new file mode 100644 index 000000000..7f41d3f89 --- /dev/null +++ b/vendor/github.com/apache/thrift/test/c_glib/src/test_server.c @@ -0,0 +1,227 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT 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 +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../gen-c_glib/t_test_thrift_test.h" + +#include "thrift_test_handler.h" + +/* Our server object, declared globally so it is accessible within the SIGINT + signal handler */ +ThriftServer *server = NULL; + +/* A flag that indicates whether the server was interrupted with SIGINT + (i.e. Ctrl-C) so we can tell whether its termination was abnormal */ +gboolean sigint_received = FALSE; + +/* Handle SIGINT ("Ctrl-C") signals by gracefully stopping the server */ +static void +sigint_handler (int signal_number) +{ + THRIFT_UNUSED_VAR (signal_number); + + /* Take note we were called */ + sigint_received = TRUE; + + /* Shut down the server gracefully */ + if (server != NULL) + thrift_server_stop (server); +} + +int +main (int argc, char **argv) +{ + static gint port = 9090; + static gchar *server_type_option = NULL; + static gchar *transport_option = NULL; + static gchar *protocol_option = NULL; + static gint string_limit = 0; + static gint container_limit = 0; + + static + GOptionEntry option_entries[] = { + { "port", 0, 0, G_OPTION_ARG_INT, &port, + "Port number to connect (=9090)", NULL }, + { "server-type", 0, 0, G_OPTION_ARG_STRING, &server_type_option, + "Type of server: simple (=simple)", NULL }, + { "transport", 0, 0, G_OPTION_ARG_STRING, &transport_option, + "Transport: buffered, framed (=buffered)", NULL }, + { "protocol", 0, 0, G_OPTION_ARG_STRING, &protocol_option, + "Protocol: binary, compact (=binary)", NULL }, + { "string-limit", 0, 0, G_OPTION_ARG_INT, &string_limit, + "Max string length (=none)", NULL }, + { "container-limit", 0, 0, G_OPTION_ARG_INT, &container_limit, + "Max container length (=none)", NULL }, + { NULL } + }; + + gchar *server_name = "simple"; + gchar *transport_name = "buffered"; + GType transport_factory_type = THRIFT_TYPE_BUFFERED_TRANSPORT_FACTORY; + gchar *protocol_name = "binary"; + GType protocol_factory_type = THRIFT_TYPE_BINARY_PROTOCOL_FACTORY; + + TTestThriftTestHandler *handler; + ThriftProcessor *processor; + ThriftServerTransport *server_transport; + ThriftTransportFactory *transport_factory; + ThriftProtocolFactory *protocol_factory; + + struct sigaction sigint_action; + + GOptionContext *option_context; + gboolean options_valid = TRUE; + + GError *error = NULL; + +#if (!GLIB_CHECK_VERSION (2, 36, 0)) + g_type_init (); +#endif + + /* Configure and parse our command-line options */ + option_context = g_option_context_new (NULL); + g_option_context_add_main_entries (option_context, + option_entries, + NULL); + if (g_option_context_parse (option_context, + &argc, + &argv, + &error) == FALSE) { + fprintf (stderr, "%s\n", error->message); + return 255; + } + g_option_context_free (option_context); + + /* Validate the parsed options */ + if (server_type_option != NULL && + strncmp (server_type_option, "simple", 7) != 0) { + fprintf (stderr, "Unknown server type %s\n", protocol_option); + options_valid = FALSE; + } + + if (protocol_option != NULL) { + if (strncmp (protocol_option, "compact", 8) == 0) { + protocol_factory_type = THRIFT_TYPE_COMPACT_PROTOCOL_FACTORY; + protocol_name = "compact"; + } + else if (strncmp (protocol_option, "binary", 7) != 0) { + fprintf (stderr, "Unknown protocol type %s\n", protocol_option); + options_valid = FALSE; + } + } + + if (transport_option != NULL) { + if (strncmp (transport_option, "framed", 7) == 0) { + transport_factory_type = THRIFT_TYPE_FRAMED_TRANSPORT_FACTORY; + transport_name = "framed"; + } + else if (strncmp (transport_option, "buffered", 9) != 0) { + fprintf (stderr, "Unknown transport type %s\n", transport_option); + options_valid = FALSE; + } + } + + if (!options_valid) + return 254; + + /* Establish all our connection objects */ + handler = g_object_new (TYPE_THRIFT_TEST_HANDLER, + NULL); + processor = g_object_new (T_TEST_TYPE_THRIFT_TEST_PROCESSOR, + "handler", handler, + NULL); + server_transport = g_object_new (THRIFT_TYPE_SERVER_SOCKET, + "port", port, + NULL); + transport_factory = g_object_new (transport_factory_type, + NULL); + + if (strncmp (protocol_name, "compact", 8) == 0) { + protocol_factory = g_object_new (protocol_factory_type, + "string_limit", string_limit, + "container_limit", container_limit, + NULL); + } else { + protocol_factory = g_object_new (protocol_factory_type, + NULL); + } + + server = g_object_new (THRIFT_TYPE_SIMPLE_SERVER, + "processor", processor, + "server_transport", server_transport, + "input_transport_factory", transport_factory, + "output_transport_factory", transport_factory, + "input_protocol_factory", protocol_factory, + "output_protocol_factory", protocol_factory, + NULL); + + /* Install our SIGINT handler, which handles Ctrl-C being pressed by stopping + the server gracefully */ + memset (&sigint_action, 0, sizeof (sigint_action)); + sigint_action.sa_handler = sigint_handler; + sigint_action.sa_flags = SA_RESETHAND; + sigaction (SIGINT, &sigint_action, NULL); + + printf ("Starting \"%s\" server (%s/%s) listen on: %d\n", + server_name, + transport_name, + protocol_name, + port); + fflush (stdout); + + /* Serve clients until SIGINT is received (Ctrl-C is pressed) */ + thrift_server_serve (server, &error); + + /* If the server stopped for any reason other than being interrupted by the + user, report the error */ + if (!sigint_received) { + g_message ("thrift_server_serve: %s", + error != NULL ? error->message : "(null)"); + g_clear_error (&error); + } + + puts ("done."); + + g_object_unref (server); + g_object_unref (protocol_factory); + g_object_unref (transport_factory); + g_object_unref (server_transport); + g_object_unref (processor); + g_object_unref (handler); + + return 0; +} diff --git a/vendor/github.com/apache/thrift/test/c_glib/src/thrift_test_handler.c b/vendor/github.com/apache/thrift/test/c_glib/src/thrift_test_handler.c new file mode 100644 index 000000000..1d8bcb25a --- /dev/null +++ b/vendor/github.com/apache/thrift/test/c_glib/src/thrift_test_handler.c @@ -0,0 +1,837 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT 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 +#include +#include + +#include +#include + +#include "thrift_test_handler.h" + +/* A handler that implements the TTestThriftTestIf interface */ + +G_DEFINE_TYPE (ThriftTestHandler, + thrift_test_handler, + T_TEST_TYPE_THRIFT_TEST_HANDLER); + +gboolean +thrift_test_handler_test_void (TTestThriftTestIf *iface, + GError **error) +{ + THRIFT_UNUSED_VAR (iface); + THRIFT_UNUSED_VAR (error); + + printf ("testVoid()\n"); + + return TRUE; +} + +gboolean +thrift_test_handler_test_string (TTestThriftTestIf *iface, + gchar **_return, + const gchar *thing, + GError **error) +{ + THRIFT_UNUSED_VAR (iface); + THRIFT_UNUSED_VAR (error); + + printf ("testString(\"%s\")\n", thing); + *_return = g_strdup (thing); + + return TRUE; +} + +gboolean +thrift_test_handler_test_bool (TTestThriftTestIf *iface, + gboolean *_return, + const gboolean thing, + GError **error) +{ + THRIFT_UNUSED_VAR (iface); + THRIFT_UNUSED_VAR (error); + + printf ("testBool(%s)\n", thing ? "true" : "false"); + *_return = thing; + + return TRUE; +} + +gboolean +thrift_test_handler_test_byte (TTestThriftTestIf *iface, + gint8 *_return, + const gint8 thing, + GError **error) +{ + THRIFT_UNUSED_VAR (iface); + THRIFT_UNUSED_VAR (error); + + printf ("testByte(%d)\n", (gint)thing); + *_return = thing; + + return TRUE; +} + +gboolean +thrift_test_handler_test_i32 (TTestThriftTestIf *iface, + gint32 *_return, + const gint32 thing, + GError **error) +{ + THRIFT_UNUSED_VAR (iface); + THRIFT_UNUSED_VAR (error); + + printf ("testI32(%d)\n", thing); + *_return = thing; + + return TRUE; +} + +gboolean +thrift_test_handler_test_i64 (TTestThriftTestIf *iface, + gint64 *_return, + const gint64 thing, + GError **error) +{ + THRIFT_UNUSED_VAR (iface); + THRIFT_UNUSED_VAR (error); + + printf ("testI64(%" PRId64 ")\n", thing); + *_return = thing; + + return TRUE; +} + +gboolean +thrift_test_handler_test_double (TTestThriftTestIf *iface, + gdouble *_return, + const gdouble thing, + GError **error) +{ + THRIFT_UNUSED_VAR (iface); + THRIFT_UNUSED_VAR (error); + + printf ("testDouble(%f)\n", thing); + *_return = thing; + + return TRUE; +} + +gboolean +thrift_test_handler_test_binary (TTestThriftTestIf *iface, + GByteArray ** _return, + const GByteArray * thing, + GError **error) +{ + THRIFT_UNUSED_VAR (iface); + THRIFT_UNUSED_VAR (error); + + printf ("testBinary()\n"); // TODO: hex output + g_byte_array_ref((GByteArray *)thing); + *_return = (GByteArray *)thing; + + return TRUE; +} + +gboolean +thrift_test_handler_test_struct (TTestThriftTestIf *iface, + TTestXtruct **_return, + const TTestXtruct *thing, + GError **error) +{ + gchar *string_thing = NULL; + gint byte_thing; + gint i32_thing; + gint64 i64_thing; + + THRIFT_UNUSED_VAR (iface); + THRIFT_UNUSED_VAR (error); + + g_object_get ((TTestXtruct *)thing, + "string_thing", &string_thing, + "byte_thing", &byte_thing, + "i32_thing", &i32_thing, + "i64_thing", &i64_thing, + NULL); + + printf ("testStruct({\"%s\", %d, %d, %" PRId64 "})\n", + string_thing, + (gint)byte_thing, + i32_thing, + i64_thing); + + g_object_set (*_return, + "string_thing", string_thing, + "byte_thing", byte_thing, + "i32_thing", i32_thing, + "i64_thing", i64_thing, + NULL); + + if (string_thing != NULL) + g_free (string_thing); + + return TRUE; +} + +gboolean +thrift_test_handler_test_nest (TTestThriftTestIf *iface, + TTestXtruct2 **_return, + const TTestXtruct2 *thing, + GError **error) +{ + gchar *inner_string_thing = NULL; + gint byte_thing, inner_byte_thing; + gint i32_thing, inner_i32_thing; + gint64 inner_i64_thing; + TTestXtruct *struct_thing; + + THRIFT_UNUSED_VAR (iface); + THRIFT_UNUSED_VAR (error); + + g_object_get ((TTestXtruct2 *)thing, + "byte_thing", &byte_thing, + "struct_thing", &struct_thing, + "i32_thing", &i32_thing, + NULL); + g_object_get (struct_thing, + "string_thing", &inner_string_thing, + "byte_thing", &inner_byte_thing, + "i32_thing", &inner_i32_thing, + "i64_thing", &inner_i64_thing, + NULL); + + printf ("testNest({%d, {\"%s\", %d, %d, %" PRId64 "}, %d})\n", + byte_thing, + inner_string_thing, + inner_byte_thing, + inner_i32_thing, + inner_i64_thing, + i32_thing); + + g_object_set (*_return, + "byte_thing", byte_thing, + "struct_thing", struct_thing, + "i32_thing", i32_thing, + NULL); + + if (inner_string_thing != NULL) + g_free (inner_string_thing); + g_object_unref (struct_thing); + + return TRUE; +} + +gboolean +thrift_test_handler_test_map (TTestThriftTestIf *iface, + GHashTable **_return, + const GHashTable *thing, + GError **error) +{ + GHashTableIter hash_table_iter; + gpointer key; + gpointer value; + gboolean first = TRUE; + + THRIFT_UNUSED_VAR (iface); + THRIFT_UNUSED_VAR (error); + + printf ("testMap({"); + g_hash_table_iter_init (&hash_table_iter, (GHashTable *)thing); + while (g_hash_table_iter_next (&hash_table_iter, + &key, + &value)) { + gint32 *new_key; + gint32 *new_value; + + if (first) + first = FALSE; + else + printf (", "); + + printf ("%d => %d", *(gint32 *)key, *(gint32 *)value); + + new_key = g_malloc (sizeof *new_key); + *new_key = *(gint32 *)key; + new_value = g_malloc (sizeof *new_value); + *new_value = *(gint32 *)value; + g_hash_table_insert (*_return, new_key, new_value); + } + printf ("})\n"); + + return TRUE; +} + +gboolean +thrift_test_handler_test_string_map (TTestThriftTestIf *iface, + GHashTable **_return, + const GHashTable *thing, + GError **error) +{ + GHashTableIter hash_table_iter; + gpointer key; + gpointer value; + gboolean first = TRUE; + + THRIFT_UNUSED_VAR (iface); + THRIFT_UNUSED_VAR (error); + + printf ("testStringMap({"); + g_hash_table_iter_init (&hash_table_iter, (GHashTable *)thing); + while (g_hash_table_iter_next (&hash_table_iter, + &key, + &value)) { + gchar *new_key; + gchar *new_value; + + if (first) + first = FALSE; + else + printf (", "); + + printf ("%s => %s", (gchar *)key, (gchar *)value); + + new_key = g_strdup ((gchar *)key); + new_value = g_strdup ((gchar *)value); + g_hash_table_insert (*_return, new_key, new_value); + } + printf ("})\n"); + + return TRUE; +} + +gboolean +thrift_test_handler_test_set (TTestThriftTestIf *iface, + GHashTable **_return, + const GHashTable *thing, + GError **error) +{ + GHashTableIter hash_table_iter; + gpointer key; + gboolean first = TRUE; + + THRIFT_UNUSED_VAR (iface); + THRIFT_UNUSED_VAR (error); + + printf ("testSet({"); + g_hash_table_iter_init (&hash_table_iter, (GHashTable *)thing); + while (g_hash_table_iter_next (&hash_table_iter, + &key, + NULL)) { + gint32 *new_key; + + if (first) + first = FALSE; + else + printf (", "); + + printf ("%d", *(gint32 *)key); + + new_key = g_malloc (sizeof *new_key); + *new_key = *(gint32 *)key; + g_hash_table_insert (*_return, new_key, NULL); + } + printf ("})\n"); + + return TRUE; +} + +gboolean +thrift_test_handler_test_list (TTestThriftTestIf *iface, + GArray **_return, + const GArray *thing, + GError **error) +{ + guint i; + gboolean first = TRUE; + + THRIFT_UNUSED_VAR (iface); + THRIFT_UNUSED_VAR (error); + + printf ("testList({"); + for (i = 0; i < thing->len; i += 1) { + gint32 value; + gint32 *new_value; + + if (first) + first = FALSE; + else + printf (", "); + + value = g_array_index (thing, gint32, i); + printf ("%d", value); + + new_value = g_malloc (sizeof *new_value); + *new_value = value; + g_array_append_val (*_return, *new_value); + } + printf ("})\n"); + + return TRUE; +} + +gboolean +thrift_test_handler_test_enum (TTestThriftTestIf *iface, + TTestNumberz *_return, + const TTestNumberz thing, + GError **error) +{ + THRIFT_UNUSED_VAR (iface); + THRIFT_UNUSED_VAR (error); + + printf ("testEnum(%d)\n", thing); + *_return = thing; + + return TRUE; +} + +gboolean +thrift_test_handler_test_typedef (TTestThriftTestIf *iface, + TTestUserId *_return, + const TTestUserId thing, + GError **error) +{ + THRIFT_UNUSED_VAR (iface); + THRIFT_UNUSED_VAR (error); + + printf ("testTypedef(%" PRId64 ")\n", thing); + *_return = thing; + + return TRUE; +} + +gboolean +thrift_test_handler_test_map_map (TTestThriftTestIf *iface, + GHashTable **_return, + const gint32 hello, + GError **error) +{ + GHashTable *positive; + GHashTable *negative; + gint32 *key; + gint32 *value; + guint i; + + THRIFT_UNUSED_VAR (iface); + THRIFT_UNUSED_VAR (error); + + printf ("testMapMap(%d)\n", hello); + + positive = g_hash_table_new_full (g_int_hash, + g_int_equal, + g_free, + g_free); + negative = g_hash_table_new_full (g_int_hash, + g_int_equal, + g_free, + g_free); + + for (i = 1; i < 5; i += 1) { + key = g_malloc (sizeof *key); + value = g_malloc (sizeof *value); + *key = i; + *value = i; + g_hash_table_insert (positive, key, value); + + key = g_malloc (sizeof *key); + value = g_malloc (sizeof *value); + *key = -i; + *value = -i; + g_hash_table_insert (negative, key, value); + } + + key = g_malloc (sizeof *key); + *key = 4; + g_hash_table_insert (*_return, key, positive); + + key = g_malloc (sizeof *key); + *key = -4; + g_hash_table_insert (*_return, key, negative); + + return TRUE; +} + +gboolean +thrift_test_handler_test_insanity (TTestThriftTestIf *iface, + GHashTable **_return, + const TTestInsanity *argument, + GError **error) +{ + TTestXtruct *xtruct_in; + + gchar *string_thing = NULL; + gint byte_thing; + gint i32_thing; + gint64 i64_thing; + + GPtrArray *xtructs; + + TTestInsanity *looney; + + GHashTable *user_map; + GHashTable *first_map; + GHashTable *second_map; + + GHashTableIter hash_table_iter; + GHashTableIter inner_hash_table_iter; + GHashTableIter user_map_iter; + + gpointer key; + gpointer value; + + TTestUserId *user_id; + + guint i; + + THRIFT_UNUSED_VAR (iface); + THRIFT_UNUSED_VAR (error); + + printf ("testInsanity()\n"); + + first_map = g_hash_table_new_full (g_direct_hash, + g_direct_equal, + NULL, + g_object_unref); + second_map = g_hash_table_new_full (g_direct_hash, + g_direct_equal, + NULL, + g_object_unref); + + g_hash_table_insert (first_map, + GINT_TO_POINTER (T_TEST_NUMBERZ_TWO), + (gpointer)argument); + g_hash_table_insert (first_map, + GINT_TO_POINTER (T_TEST_NUMBERZ_THREE), + (gpointer)argument); + + /* Increment argument's ref count by two because first_map now holds + two references to it and the caller is not aware we have made any + additional references to argument. (That is, caller owns argument + and will unref it explicitly in addition to unref-ing *_return.) + + We do this instead of creating a copy of argument in order to mimic + the C++ implementation (and since, frankly, the world needs less + argument, not more). */ + g_object_ref ((gpointer)argument); + g_object_ref ((gpointer)argument); + + looney = g_object_new (T_TEST_TYPE_INSANITY, NULL); + g_hash_table_insert (second_map, + GINT_TO_POINTER (T_TEST_NUMBERZ_SIX), + looney); + + user_id = g_malloc (sizeof *user_id); + *user_id = 1; + g_hash_table_insert (*_return, user_id, first_map); + + user_id = g_malloc (sizeof *user_id); + *user_id = 2; + g_hash_table_insert (*_return, user_id, second_map); + + printf ("return"); + printf (" = {"); + g_hash_table_iter_init (&hash_table_iter, *_return); + while (g_hash_table_iter_next (&hash_table_iter, + &key, + &value)) { + printf ("%" PRId64 " => {", *(TTestUserId *)key); + + g_hash_table_iter_init (&inner_hash_table_iter, + (GHashTable *)value); + while (g_hash_table_iter_next (&inner_hash_table_iter, + &key, + &value)) { + printf ("%d => {", (TTestNumberz)key); + + g_object_get ((TTestInsanity *)value, + "userMap", &user_map, + "xtructs", &xtructs, + NULL); + + printf ("{"); + g_hash_table_iter_init (&user_map_iter, user_map); + while (g_hash_table_iter_next (&user_map_iter, + &key, + &value)) { + printf ("%d => %" PRId64 ", ", + (TTestNumberz)key, + *(TTestUserId *)value); + } + printf ("}, "); + g_hash_table_unref (user_map); + + printf ("{"); + for (i = 0; i < xtructs->len; ++i) { + xtruct_in = g_ptr_array_index (xtructs, i); + g_object_get (xtruct_in, + "string_thing", &string_thing, + "byte_thing", &byte_thing, + "i32_thing", &i32_thing, + "i64_thing", &i64_thing, + NULL); + + printf ("{\"%s\", %d, %d, %" PRId64 "}, ", + string_thing, + byte_thing, + i32_thing, + i64_thing); + } + printf ("}"); + g_ptr_array_unref (xtructs); + + printf ("}, "); + } + printf ("}, "); + } + printf ("}\n"); + + return TRUE; +} + +gboolean +thrift_test_handler_test_multi (TTestThriftTestIf *iface, + TTestXtruct **_return, + const gint8 arg0, + const gint32 arg1, + const gint64 arg2, + const GHashTable *arg3, + const TTestNumberz arg4, + const TTestUserId arg5, + GError **error) +{ + THRIFT_UNUSED_VAR (iface); + THRIFT_UNUSED_VAR (error); + THRIFT_UNUSED_VAR (arg3); + THRIFT_UNUSED_VAR (arg4); + THRIFT_UNUSED_VAR (arg5); + + printf ("testMulti()\n"); + + g_object_set (*_return, + "string_thing", g_strdup ("Hello2"), + "byte_thing", arg0, + "i32_thing", arg1, + "i64_thing", arg2, + NULL); + + return TRUE; +} + +gboolean +thrift_test_handler_test_exception (TTestThriftTestIf *iface, + const gchar *arg, + TTestXception **err1, + GError **error) +{ + THRIFT_UNUSED_VAR (iface); + + TTestXtruct *xtruct; + gboolean result; + + printf ("testException(%s)\n", arg); + + /* Unlike argument objects, exception objects are not pre-created */ + g_assert (*err1 == NULL); + + if (strncmp (arg, "Xception", 9) == 0) { + /* "Throw" a custom exception: Set the corresponding exception + argument, set *error to NULL and return FALSE */ + *err1 = g_object_new (T_TEST_TYPE_XCEPTION, + "errorCode", 1001, + "message", g_strdup (arg), + NULL); + *error = NULL; + result = FALSE; + } + else if (strncmp (arg, "TException", 11) == 0) { + /* "Throw" a generic TException (ThriftApplicationException): Set + all exception arguments to NULL, set *error and return FALSE */ + *err1 = NULL; + g_set_error (error, + thrift_application_exception_error_quark (), + THRIFT_APPLICATION_EXCEPTION_ERROR_UNKNOWN, + "Default TException."); + result = FALSE; + } + else { + *err1 = NULL; + *error = NULL; + + /* This code is duplicated from the C++ test suite, though it + appears to serve no purpose */ + xtruct = g_object_new (T_TEST_TYPE_XTRUCT, + "string_thing", g_strdup (arg), + NULL); + g_object_unref (xtruct); + + result = TRUE; + } + + return result; +} + +gboolean +thrift_test_handler_test_multi_exception (TTestThriftTestIf *iface, + TTestXtruct **_return, + const gchar *arg0, + const gchar *arg1, + TTestXception **err1, + TTestXception2 **err2, + GError **error) +{ + THRIFT_UNUSED_VAR (iface); + THRIFT_UNUSED_VAR (error); + + TTestXtruct *struct_thing; + gboolean result; + + printf ("testMultiException(%s, %s)\n", arg0, arg1); + + g_assert (*err1 == NULL); + g_assert (*err2 == NULL); + + if (strncmp (arg0, "Xception", 8) == 0 && strlen(arg0) == 8) { + *err1 = g_object_new (T_TEST_TYPE_XCEPTION, + "errorCode", 1001, + "message", g_strdup ("This is an Xception"), + NULL); + result = FALSE; + } + else if (strncmp (arg0, "Xception2", 9) == 0) { + *err2 = g_object_new (T_TEST_TYPE_XCEPTION2, + "errorCode", 2002, + NULL); + + g_object_get (*err2, + "struct_thing", &struct_thing, + NULL); + g_object_set (struct_thing, + "string_thing", g_strdup ("This is an Xception2"), + NULL); + g_object_set (*err2, + "struct_thing", struct_thing, + NULL); + g_object_unref (struct_thing); + + result = FALSE; + } + else { + g_object_set (*_return, + "string_thing", g_strdup (arg1), + NULL); + result = TRUE; + } + + return result; +} + +gboolean +thrift_test_handler_test_oneway (TTestThriftTestIf *iface, + const gint32 secondsToSleep, + GError **error) +{ + THRIFT_UNUSED_VAR (iface); + THRIFT_UNUSED_VAR (error); + + printf ("testOneway(%d): Sleeping...\n", secondsToSleep); + sleep (secondsToSleep); + printf ("testOneway(%d): done sleeping!\n", secondsToSleep); + + return TRUE; +} + +static void +thrift_test_handler_init (ThriftTestHandler *self) +{ + THRIFT_UNUSED_VAR (self); +} + +static void +thrift_test_handler_class_init (ThriftTestHandlerClass *klass) +{ + TTestThriftTestHandlerClass *base_class = + T_TEST_THRIFT_TEST_HANDLER_CLASS (klass); + + base_class->test_void = + klass->test_void = + thrift_test_handler_test_void; + base_class->test_string = + klass->test_string = + thrift_test_handler_test_string; + base_class->test_bool = + klass->test_bool = + thrift_test_handler_test_bool; + base_class->test_byte = + klass->test_byte = + thrift_test_handler_test_byte; + base_class->test_i32 = + klass->test_i32 = + thrift_test_handler_test_i32; + base_class->test_i64 = + klass->test_i64 = + thrift_test_handler_test_i64; + base_class->test_double = + klass->test_double = + thrift_test_handler_test_double; + base_class->test_binary = + klass->test_binary = + thrift_test_handler_test_binary; + base_class->test_struct = + klass->test_struct = + thrift_test_handler_test_struct; + base_class->test_nest = + klass->test_nest = + thrift_test_handler_test_nest; + base_class->test_map = + klass->test_map = + thrift_test_handler_test_map; + base_class->test_string_map = + klass->test_string_map = + thrift_test_handler_test_string_map; + base_class->test_set = + klass->test_set = + thrift_test_handler_test_set; + base_class->test_list = + klass->test_list = + thrift_test_handler_test_list; + base_class->test_enum = + klass->test_enum = + thrift_test_handler_test_enum; + base_class->test_typedef = + klass->test_typedef = + thrift_test_handler_test_typedef; + base_class->test_map_map = + klass->test_map_map = + thrift_test_handler_test_map_map; + base_class->test_insanity = + klass->test_insanity = + thrift_test_handler_test_insanity; + base_class->test_multi = + klass->test_multi = + thrift_test_handler_test_multi; + base_class->test_exception = + klass->test_exception = + thrift_test_handler_test_exception; + base_class->test_multi_exception = + klass->test_multi_exception = + thrift_test_handler_test_multi_exception; + base_class->test_oneway = + klass->test_oneway = + thrift_test_handler_test_oneway; +} diff --git a/vendor/github.com/apache/thrift/test/c_glib/src/thrift_test_handler.h b/vendor/github.com/apache/thrift/test/c_glib/src/thrift_test_handler.h new file mode 100644 index 000000000..b64cb16f2 --- /dev/null +++ b/vendor/github.com/apache/thrift/test/c_glib/src/thrift_test_handler.h @@ -0,0 +1,245 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT 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_TEST_HANDLER_H +#define _THRIFT_TEST_HANDLER_H + +#include +#include + +#include "../gen-c_glib/t_test_thrift_test.h" + +G_BEGIN_DECLS + +/* A handler that implements the TTestThriftTestIf interface */ + +#define TYPE_THRIFT_TEST_HANDLER (thrift_test_handler_get_type ()) + +#define THRIFT_TEST_HANDLER(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), \ + TYPE_THRIFT_TEST_HANDLER, \ + ThriftTestHandler)) +#define IS_THRIFT_TEST_HANDLER(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \ + TYPE_THRIFT_TEST_HANDLER)) +#define THRIFT_TEST_HANDLER_CLASS(c) \ + (G_TYPE_CHECK_CLASS_CAST ((c), \ + TYPE_THRIFT_TEST_HANDLER, \ + ThriftTestHandlerClass)) +#define IS_THRIFT_TEST_HANDLER_CLASS(c) \ + (G_TYPE_CHECK_CLASS_TYPE ((c), \ + TYPE_THRIFT_TEST_HANDLER)) +#define THRIFT_TEST_HANDLER_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), \ + TYPE_THRIFT_TEST_HANDLER, \ + ThriftTestHandlerClass)) + +typedef struct _ThriftTestHandler ThriftTestHandler; +typedef struct _ThriftTestHandlerClass ThriftTestHandlerClass; + +struct _ThriftTestHandler { + TTestThriftTestHandler parent; +}; + +struct _ThriftTestHandlerClass { + TTestThriftTestHandlerClass parent; + + gboolean (*test_void) (TTestThriftTestIf *iface, + GError **error); + gboolean (*test_string) (TTestThriftTestIf *iface, + gchar **_return, + const gchar *thing, + GError **error); + gboolean (*test_bool) (TTestThriftTestIf *iface, + gboolean*_return, + const gboolean thing, + GError **error); + gboolean (*test_byte) (TTestThriftTestIf *iface, + gint8*_return, + const gint8 thing, + GError **error); + gboolean (*test_i32) (TTestThriftTestIf *iface, + gint32*_return, + const gint32 thing, + GError **error); + gboolean (*test_i64) (TTestThriftTestIf *iface, + gint64*_return, + const gint64 thing, + GError **error); + gboolean (*test_double) (TTestThriftTestIf *iface, + gdouble*_return, + const gdouble thing, + GError **error); + gboolean (*test_binary) (TTestThriftTestIf *iface, + GByteArray **_return, + const GByteArray *thing, + GError **error); + gboolean (*test_struct) (TTestThriftTestIf *iface, + TTestXtruct **_return, + const TTestXtruct *thing, + GError **error); + gboolean (*test_nest) (TTestThriftTestIf *iface, + TTestXtruct2 **_return, + const TTestXtruct2 *thing, + GError **error); + gboolean (*test_map) (TTestThriftTestIf *iface, + GHashTable **_return, + const GHashTable *thing, + GError **error); + gboolean (*test_string_map) (TTestThriftTestIf *iface, + GHashTable **_return, + const GHashTable *thing, + GError **error); + gboolean (*test_set) (TTestThriftTestIf *iface, + GHashTable **_return, + const GHashTable *thing, + GError **error); + gboolean (*test_list) (TTestThriftTestIf *iface, + GArray **_return, + const GArray *thing, + GError **error); + gboolean (*test_enum) (TTestThriftTestIf *iface, + TTestNumberz*_return, + const TTestNumberz thing, + GError **error); + gboolean (*test_typedef) (TTestThriftTestIf *iface, + TTestUserId*_return, + const TTestUserId thing, + GError **error); + gboolean (*test_map_map) (TTestThriftTestIf *iface, + GHashTable **_return, + const gint32 hello, + GError **error); + gboolean (*test_insanity) (TTestThriftTestIf *iface, + GHashTable **_return, + const TTestInsanity *argument, + GError **error); + gboolean (*test_multi) (TTestThriftTestIf *iface, + TTestXtruct **_return, + const gint8 arg0, + const gint32 arg1, + const gint64 arg2, + const GHashTable *arg3, + const TTestNumberz arg4, + const TTestUserId arg5, + GError **error); + gboolean (*test_exception) (TTestThriftTestIf *iface, + const gchar *arg, + TTestXception **err1, + GError **error); + gboolean (*test_multi_exception) (TTestThriftTestIf *iface, + TTestXtruct **_return, + const gchar *arg0, + const gchar *arg1, + TTestXception **err1, + TTestXception2 **err2, + GError **error); + gboolean (*test_oneway) (TTestThriftTestIf *iface, + const gint32 secondsToSleep, + GError **error); +}; + +/* Used by THRIFT_TEST_HANDLER_GET_TYPE */ +GType thrift_test_handler_get_type (void); + +gboolean thrift_test_handler_test_void (TTestThriftTestIf *iface, + GError **error); +gboolean thrift_test_handler_test_string (TTestThriftTestIf *iface, + gchar **_return, + const gchar *thing, + GError **error); +gboolean thrift_test_handler_test_byte (TTestThriftTestIf *iface, + gint8*_return, + const gint8 thing, + GError **error); +gboolean t_test_thrift_test_if_test_i32 (TTestThriftTestIf *iface, + gint32*_return, + const gint32 thing, + GError **error); +gboolean thrift_test_handler_test_i64 (TTestThriftTestIf *iface, + gint64*_return, + const gint64 thing, + GError **error); +gboolean thrift_test_handler_test_double (TTestThriftTestIf *iface, + gdouble*_return, + const gdouble thing, + GError **error); +gboolean thrift_test_handler_test_struct (TTestThriftTestIf *iface, + TTestXtruct **_return, + const TTestXtruct *thing, + GError **error); +gboolean thrift_test_handler_test_nest (TTestThriftTestIf *iface, + TTestXtruct2 **_return, + const TTestXtruct2 *thing, + GError **error); +gboolean thrift_test_handler_test_map (TTestThriftTestIf *iface, + GHashTable **_return, + const GHashTable *thing, + GError **error); +gboolean thrift_test_handler_test_string_map (TTestThriftTestIf *iface, + GHashTable **_return, + const GHashTable *thing, + GError **error); +gboolean thrift_test_handler_test_set (TTestThriftTestIf *iface, + GHashTable **_return, + const GHashTable *thing, + GError **error); +gboolean thrift_test_handler_test_list (TTestThriftTestIf *iface, + GArray **_return, + const GArray *thing, + GError **error); +gboolean thrift_test_handler_test_typedef (TTestThriftTestIf *iface, + TTestUserId*_return, + const TTestUserId thing, + GError **error); +gboolean thrift_test_handler_test_map_map (TTestThriftTestIf *iface, + GHashTable **_return, + const gint32 hello, + GError **error); +gboolean thrift_test_handler_test_insanity (TTestThriftTestIf *iface, + GHashTable **_return, + const TTestInsanity *argument, + GError **error); +gboolean thrift_test_handler_test_multi (TTestThriftTestIf *iface, + TTestXtruct **_return, + const gint8 arg0, + const gint32 arg1, + const gint64 arg2, + const GHashTable *arg3, + const TTestNumberz arg4, + const TTestUserId arg5, + GError **error); +gboolean thrift_test_handler_test_exception (TTestThriftTestIf *iface, + const gchar *arg, + TTestXception **err1, + GError **error); +gboolean thrift_test_handler_test_multi_exception (TTestThriftTestIf *iface, + TTestXtruct **_return, + const gchar *arg0, + const gchar *arg1, + TTestXception **err1, + TTestXception2 **err2, + GError **error); +gboolean thrift_test_handler_test_oneway (TTestThriftTestIf *iface, + const gint32 secondsToSleep, + GError **error); + +G_END_DECLS + +#endif /* _THRIFT_TEST_HANDLER_H */ diff --git a/vendor/github.com/codahale/hdrhistogram/LICENSE b/vendor/github.com/codahale/hdrhistogram/LICENSE new file mode 100644 index 000000000..f9835c241 --- /dev/null +++ b/vendor/github.com/codahale/hdrhistogram/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2014 Coda Hale + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/vendor/github.com/codahale/hdrhistogram/README.md b/vendor/github.com/codahale/hdrhistogram/README.md new file mode 100644 index 000000000..614b197c3 --- /dev/null +++ b/vendor/github.com/codahale/hdrhistogram/README.md @@ -0,0 +1,15 @@ +hdrhistogram +============ + +[![Build Status](https://travis-ci.org/codahale/hdrhistogram.png?branch=master)](https://travis-ci.org/codahale/hdrhistogram) + +A pure Go implementation of the [HDR Histogram](https://github.com/HdrHistogram/HdrHistogram). + +> A Histogram that supports recording and analyzing sampled data value counts +> across a configurable integer value range with configurable value precision +> within the range. Value precision is expressed as the number of significant +> digits in the value recording, and provides control over value quantization +> behavior across the value range and the subsequent value resolution at any +> given level. + +For documentation, check [godoc](http://godoc.org/github.com/codahale/hdrhistogram). diff --git a/vendor/github.com/codahale/hdrhistogram/hdr.go b/vendor/github.com/codahale/hdrhistogram/hdr.go new file mode 100644 index 000000000..02540ddce --- /dev/null +++ b/vendor/github.com/codahale/hdrhistogram/hdr.go @@ -0,0 +1,563 @@ +// Package hdrhistogram provides an implementation of Gil Tene's HDR Histogram +// data structure. The HDR Histogram allows for fast and accurate analysis of +// the extreme ranges of data with non-normal distributions, like latency. +package hdrhistogram + +import ( + "fmt" + "math" +) + +// A Bracket is a part of a cumulative distribution. +type Bracket struct { + Quantile float64 + Count, ValueAt int64 +} + +// A Snapshot is an exported view of a Histogram, useful for serializing them. +// A Histogram can be constructed from it by passing it to Import. +type Snapshot struct { + LowestTrackableValue int64 + HighestTrackableValue int64 + SignificantFigures int64 + Counts []int64 +} + +// A Histogram is a lossy data structure used to record the distribution of +// non-normally distributed data (like latency) with a high degree of accuracy +// and a bounded degree of precision. +type Histogram struct { + lowestTrackableValue int64 + highestTrackableValue int64 + unitMagnitude int64 + significantFigures int64 + subBucketHalfCountMagnitude int32 + subBucketHalfCount int32 + subBucketMask int64 + subBucketCount int32 + bucketCount int32 + countsLen int32 + totalCount int64 + counts []int64 +} + +// New returns a new Histogram instance capable of tracking values in the given +// range and with the given amount of precision. +func New(minValue, maxValue int64, sigfigs int) *Histogram { + if sigfigs < 1 || 5 < sigfigs { + panic(fmt.Errorf("sigfigs must be [1,5] (was %d)", sigfigs)) + } + + largestValueWithSingleUnitResolution := 2 * math.Pow10(sigfigs) + subBucketCountMagnitude := int32(math.Ceil(math.Log2(float64(largestValueWithSingleUnitResolution)))) + + subBucketHalfCountMagnitude := subBucketCountMagnitude + if subBucketHalfCountMagnitude < 1 { + subBucketHalfCountMagnitude = 1 + } + subBucketHalfCountMagnitude-- + + unitMagnitude := int32(math.Floor(math.Log2(float64(minValue)))) + if unitMagnitude < 0 { + unitMagnitude = 0 + } + + subBucketCount := int32(math.Pow(2, float64(subBucketHalfCountMagnitude)+1)) + + subBucketHalfCount := subBucketCount / 2 + subBucketMask := int64(subBucketCount-1) << uint(unitMagnitude) + + // determine exponent range needed to support the trackable value with no + // overflow: + smallestUntrackableValue := int64(subBucketCount) << uint(unitMagnitude) + bucketsNeeded := int32(1) + for smallestUntrackableValue < maxValue { + smallestUntrackableValue <<= 1 + bucketsNeeded++ + } + + bucketCount := bucketsNeeded + countsLen := (bucketCount + 1) * (subBucketCount / 2) + + return &Histogram{ + lowestTrackableValue: minValue, + highestTrackableValue: maxValue, + unitMagnitude: int64(unitMagnitude), + significantFigures: int64(sigfigs), + subBucketHalfCountMagnitude: subBucketHalfCountMagnitude, + subBucketHalfCount: subBucketHalfCount, + subBucketMask: subBucketMask, + subBucketCount: subBucketCount, + bucketCount: bucketCount, + countsLen: countsLen, + totalCount: 0, + counts: make([]int64, countsLen), + } +} + +// ByteSize returns an estimate of the amount of memory allocated to the +// histogram in bytes. +// +// N.B.: This does not take into account the overhead for slices, which are +// small, constant, and specific to the compiler version. +func (h *Histogram) ByteSize() int { + return 6*8 + 5*4 + len(h.counts)*8 +} + +// Merge merges the data stored in the given histogram with the receiver, +// returning the number of recorded values which had to be dropped. +func (h *Histogram) Merge(from *Histogram) (dropped int64) { + i := from.rIterator() + for i.next() { + v := i.valueFromIdx + c := i.countAtIdx + + if h.RecordValues(v, c) != nil { + dropped += c + } + } + + return +} + +// TotalCount returns total number of values recorded. +func (h *Histogram) TotalCount() int64 { + return h.totalCount +} + +// Max returns the approximate maximum recorded value. +func (h *Histogram) Max() int64 { + var max int64 + i := h.iterator() + for i.next() { + if i.countAtIdx != 0 { + max = i.highestEquivalentValue + } + } + return h.highestEquivalentValue(max) +} + +// Min returns the approximate minimum recorded value. +func (h *Histogram) Min() int64 { + var min int64 + i := h.iterator() + for i.next() { + if i.countAtIdx != 0 && min == 0 { + min = i.highestEquivalentValue + break + } + } + return h.lowestEquivalentValue(min) +} + +// Mean returns the approximate arithmetic mean of the recorded values. +func (h *Histogram) Mean() float64 { + if h.totalCount == 0 { + return 0 + } + var total int64 + i := h.iterator() + for i.next() { + if i.countAtIdx != 0 { + total += i.countAtIdx * h.medianEquivalentValue(i.valueFromIdx) + } + } + return float64(total) / float64(h.totalCount) +} + +// StdDev returns the approximate standard deviation of the recorded values. +func (h *Histogram) StdDev() float64 { + if h.totalCount == 0 { + return 0 + } + + mean := h.Mean() + geometricDevTotal := 0.0 + + i := h.iterator() + for i.next() { + if i.countAtIdx != 0 { + dev := float64(h.medianEquivalentValue(i.valueFromIdx)) - mean + geometricDevTotal += (dev * dev) * float64(i.countAtIdx) + } + } + + return math.Sqrt(geometricDevTotal / float64(h.totalCount)) +} + +// Reset deletes all recorded values and restores the histogram to its original +// state. +func (h *Histogram) Reset() { + h.totalCount = 0 + for i := range h.counts { + h.counts[i] = 0 + } +} + +// RecordValue records the given value, returning an error if the value is out +// of range. +func (h *Histogram) RecordValue(v int64) error { + return h.RecordValues(v, 1) +} + +// RecordCorrectedValue records the given value, correcting for stalls in the +// recording process. This only works for processes which are recording values +// at an expected interval (e.g., doing jitter analysis). Processes which are +// recording ad-hoc values (e.g., latency for incoming requests) can't take +// advantage of this. +func (h *Histogram) RecordCorrectedValue(v, expectedInterval int64) error { + if err := h.RecordValue(v); err != nil { + return err + } + + if expectedInterval <= 0 || v <= expectedInterval { + return nil + } + + missingValue := v - expectedInterval + for missingValue >= expectedInterval { + if err := h.RecordValue(missingValue); err != nil { + return err + } + missingValue -= expectedInterval + } + + return nil +} + +// RecordValues records n occurrences of the given value, returning an error if +// the value is out of range. +func (h *Histogram) RecordValues(v, n int64) error { + idx := h.countsIndexFor(v) + if idx < 0 || int(h.countsLen) <= idx { + return fmt.Errorf("value %d is too large to be recorded", v) + } + h.counts[idx] += n + h.totalCount += n + + return nil +} + +// ValueAtQuantile returns the recorded value at the given quantile (0..100). +func (h *Histogram) ValueAtQuantile(q float64) int64 { + if q > 100 { + q = 100 + } + + total := int64(0) + countAtPercentile := int64(((q / 100) * float64(h.totalCount)) + 0.5) + + i := h.iterator() + for i.next() { + total += i.countAtIdx + if total >= countAtPercentile { + return h.highestEquivalentValue(i.valueFromIdx) + } + } + + return 0 +} + +// CumulativeDistribution returns an ordered list of brackets of the +// distribution of recorded values. +func (h *Histogram) CumulativeDistribution() []Bracket { + var result []Bracket + + i := h.pIterator(1) + for i.next() { + result = append(result, Bracket{ + Quantile: i.percentile, + Count: i.countToIdx, + ValueAt: i.highestEquivalentValue, + }) + } + + return result +} + +// SignificantFigures returns the significant figures used to create the +// histogram +func (h *Histogram) SignificantFigures() int64 { + return h.significantFigures +} + +// LowestTrackableValue returns the lower bound on values that will be added +// to the histogram +func (h *Histogram) LowestTrackableValue() int64 { + return h.lowestTrackableValue +} + +// HighestTrackableValue returns the upper bound on values that will be added +// to the histogram +func (h *Histogram) HighestTrackableValue() int64 { + return h.highestTrackableValue +} + +// Histogram bar for plotting +type Bar struct { + From, To, Count int64 +} + +// Pretty print as csv for easy plotting +func (b Bar) String() string { + return fmt.Sprintf("%v, %v, %v\n", b.From, b.To, b.Count) +} + +// Distribution returns an ordered list of bars of the +// distribution of recorded values, counts can be normalized to a probability +func (h *Histogram) Distribution() (result []Bar) { + i := h.iterator() + for i.next() { + result = append(result, Bar{ + Count: i.countAtIdx, + From: h.lowestEquivalentValue(i.valueFromIdx), + To: i.highestEquivalentValue, + }) + } + + return result +} + +// Equals returns true if the two Histograms are equivalent, false if not. +func (h *Histogram) Equals(other *Histogram) bool { + switch { + case + h.lowestTrackableValue != other.lowestTrackableValue, + h.highestTrackableValue != other.highestTrackableValue, + h.unitMagnitude != other.unitMagnitude, + h.significantFigures != other.significantFigures, + h.subBucketHalfCountMagnitude != other.subBucketHalfCountMagnitude, + h.subBucketHalfCount != other.subBucketHalfCount, + h.subBucketMask != other.subBucketMask, + h.subBucketCount != other.subBucketCount, + h.bucketCount != other.bucketCount, + h.countsLen != other.countsLen, + h.totalCount != other.totalCount: + return false + default: + for i, c := range h.counts { + if c != other.counts[i] { + return false + } + } + } + return true +} + +// Export returns a snapshot view of the Histogram. This can be later passed to +// Import to construct a new Histogram with the same state. +func (h *Histogram) Export() *Snapshot { + return &Snapshot{ + LowestTrackableValue: h.lowestTrackableValue, + HighestTrackableValue: h.highestTrackableValue, + SignificantFigures: h.significantFigures, + Counts: h.counts, + } +} + +// Import returns a new Histogram populated from the Snapshot data. +func Import(s *Snapshot) *Histogram { + h := New(s.LowestTrackableValue, s.HighestTrackableValue, int(s.SignificantFigures)) + h.counts = s.Counts + totalCount := int64(0) + for i := int32(0); i < h.countsLen; i++ { + countAtIndex := h.counts[i] + if countAtIndex > 0 { + totalCount += countAtIndex + } + } + h.totalCount = totalCount + return h +} + +func (h *Histogram) iterator() *iterator { + return &iterator{ + h: h, + subBucketIdx: -1, + } +} + +func (h *Histogram) rIterator() *rIterator { + return &rIterator{ + iterator: iterator{ + h: h, + subBucketIdx: -1, + }, + } +} + +func (h *Histogram) pIterator(ticksPerHalfDistance int32) *pIterator { + return &pIterator{ + iterator: iterator{ + h: h, + subBucketIdx: -1, + }, + ticksPerHalfDistance: ticksPerHalfDistance, + } +} + +func (h *Histogram) sizeOfEquivalentValueRange(v int64) int64 { + bucketIdx := h.getBucketIndex(v) + subBucketIdx := h.getSubBucketIdx(v, bucketIdx) + adjustedBucket := bucketIdx + if subBucketIdx >= h.subBucketCount { + adjustedBucket++ + } + return int64(1) << uint(h.unitMagnitude+int64(adjustedBucket)) +} + +func (h *Histogram) valueFromIndex(bucketIdx, subBucketIdx int32) int64 { + return int64(subBucketIdx) << uint(int64(bucketIdx)+h.unitMagnitude) +} + +func (h *Histogram) lowestEquivalentValue(v int64) int64 { + bucketIdx := h.getBucketIndex(v) + subBucketIdx := h.getSubBucketIdx(v, bucketIdx) + return h.valueFromIndex(bucketIdx, subBucketIdx) +} + +func (h *Histogram) nextNonEquivalentValue(v int64) int64 { + return h.lowestEquivalentValue(v) + h.sizeOfEquivalentValueRange(v) +} + +func (h *Histogram) highestEquivalentValue(v int64) int64 { + return h.nextNonEquivalentValue(v) - 1 +} + +func (h *Histogram) medianEquivalentValue(v int64) int64 { + return h.lowestEquivalentValue(v) + (h.sizeOfEquivalentValueRange(v) >> 1) +} + +func (h *Histogram) getCountAtIndex(bucketIdx, subBucketIdx int32) int64 { + return h.counts[h.countsIndex(bucketIdx, subBucketIdx)] +} + +func (h *Histogram) countsIndex(bucketIdx, subBucketIdx int32) int32 { + bucketBaseIdx := (bucketIdx + 1) << uint(h.subBucketHalfCountMagnitude) + offsetInBucket := subBucketIdx - h.subBucketHalfCount + return bucketBaseIdx + offsetInBucket +} + +func (h *Histogram) getBucketIndex(v int64) int32 { + pow2Ceiling := bitLen(v | h.subBucketMask) + return int32(pow2Ceiling - int64(h.unitMagnitude) - + int64(h.subBucketHalfCountMagnitude+1)) +} + +func (h *Histogram) getSubBucketIdx(v int64, idx int32) int32 { + return int32(v >> uint(int64(idx)+int64(h.unitMagnitude))) +} + +func (h *Histogram) countsIndexFor(v int64) int { + bucketIdx := h.getBucketIndex(v) + subBucketIdx := h.getSubBucketIdx(v, bucketIdx) + return int(h.countsIndex(bucketIdx, subBucketIdx)) +} + +type iterator struct { + h *Histogram + bucketIdx, subBucketIdx int32 + countAtIdx, countToIdx, valueFromIdx int64 + highestEquivalentValue int64 +} + +func (i *iterator) next() bool { + if i.countToIdx >= i.h.totalCount { + return false + } + + // increment bucket + i.subBucketIdx++ + if i.subBucketIdx >= i.h.subBucketCount { + i.subBucketIdx = i.h.subBucketHalfCount + i.bucketIdx++ + } + + if i.bucketIdx >= i.h.bucketCount { + return false + } + + i.countAtIdx = i.h.getCountAtIndex(i.bucketIdx, i.subBucketIdx) + i.countToIdx += i.countAtIdx + i.valueFromIdx = i.h.valueFromIndex(i.bucketIdx, i.subBucketIdx) + i.highestEquivalentValue = i.h.highestEquivalentValue(i.valueFromIdx) + + return true +} + +type rIterator struct { + iterator + countAddedThisStep int64 +} + +func (r *rIterator) next() bool { + for r.iterator.next() { + if r.countAtIdx != 0 { + r.countAddedThisStep = r.countAtIdx + return true + } + } + return false +} + +type pIterator struct { + iterator + seenLastValue bool + ticksPerHalfDistance int32 + percentileToIteratorTo float64 + percentile float64 +} + +func (p *pIterator) next() bool { + if !(p.countToIdx < p.h.totalCount) { + if p.seenLastValue { + return false + } + + p.seenLastValue = true + p.percentile = 100 + + return true + } + + if p.subBucketIdx == -1 && !p.iterator.next() { + return false + } + + var done = false + for !done { + currentPercentile := (100.0 * float64(p.countToIdx)) / float64(p.h.totalCount) + if p.countAtIdx != 0 && p.percentileToIteratorTo <= currentPercentile { + p.percentile = p.percentileToIteratorTo + halfDistance := math.Trunc(math.Pow(2, math.Trunc(math.Log2(100.0/(100.0-p.percentileToIteratorTo)))+1)) + percentileReportingTicks := float64(p.ticksPerHalfDistance) * halfDistance + p.percentileToIteratorTo += 100.0 / percentileReportingTicks + return true + } + done = !p.iterator.next() + } + + return true +} + +func bitLen(x int64) (n int64) { + for ; x >= 0x8000; x >>= 16 { + n += 16 + } + if x >= 0x80 { + x >>= 8 + n += 8 + } + if x >= 0x8 { + x >>= 4 + n += 4 + } + if x >= 0x2 { + x >>= 2 + n += 2 + } + if x >= 0x1 { + n++ + } + return +} diff --git a/vendor/github.com/codahale/hdrhistogram/window.go b/vendor/github.com/codahale/hdrhistogram/window.go new file mode 100644 index 000000000..dc43612a4 --- /dev/null +++ b/vendor/github.com/codahale/hdrhistogram/window.go @@ -0,0 +1,45 @@ +package hdrhistogram + +// A WindowedHistogram combines histograms to provide windowed statistics. +type WindowedHistogram struct { + idx int + h []Histogram + m *Histogram + + Current *Histogram +} + +// NewWindowed creates a new WindowedHistogram with N underlying histograms with +// the given parameters. +func NewWindowed(n int, minValue, maxValue int64, sigfigs int) *WindowedHistogram { + w := WindowedHistogram{ + idx: -1, + h: make([]Histogram, n), + m: New(minValue, maxValue, sigfigs), + } + + for i := range w.h { + w.h[i] = *New(minValue, maxValue, sigfigs) + } + w.Rotate() + + return &w +} + +// Merge returns a histogram which includes the recorded values from all the +// sections of the window. +func (w *WindowedHistogram) Merge() *Histogram { + w.m.Reset() + for _, h := range w.h { + w.m.Merge(&h) + } + return w.m +} + +// Rotate resets the oldest histogram and rotates it to be used as the current +// histogram. +func (w *WindowedHistogram) Rotate() { + w.idx++ + w.Current = &w.h[w.idx%len(w.h)] + w.Current.Reset() +} diff --git a/vendor/github.com/grpc-ecosystem/grpc-opentracing/LICENSE b/vendor/github.com/grpc-ecosystem/grpc-opentracing/LICENSE new file mode 100644 index 000000000..abe5fe170 --- /dev/null +++ b/vendor/github.com/grpc-ecosystem/grpc-opentracing/LICENSE @@ -0,0 +1,27 @@ +Copyright (c) 2016, gRPC Ecosystem +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* Neither the name of grpc-opentracing nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/github.com/grpc-ecosystem/grpc-opentracing/PATENTS b/vendor/github.com/grpc-ecosystem/grpc-opentracing/PATENTS new file mode 100644 index 000000000..5cfe0175e --- /dev/null +++ b/vendor/github.com/grpc-ecosystem/grpc-opentracing/PATENTS @@ -0,0 +1,23 @@ +Additional IP Rights Grant (Patents) + +"This implementation" means the copyrightable works distributed by +Google as part of the GRPC project. + +Google 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, +transfer and otherwise run, modify and propagate the contents of this +implementation of GRPC, where such license applies only to those patent +claims, both currently owned or controlled by Google and acquired in +the future, licensable by Google that are necessarily infringed by this +implementation of GRPC. This grant does not include claims that would be +infringed only as a consequence of further modification of this +implementation. If you or your agent or exclusive licensee institute or +order or agree to the institution of patent litigation against any +entity (including a cross-claim or counterclaim in a lawsuit) alleging +that this implementation of GRPC or any code incorporated within this +implementation of GRPC constitutes direct or contributory patent +infringement, or inducement of patent infringement, then any patent +rights granted to you under this License for this implementation of GRPC +shall terminate as of the date such litigation is filed. +Status API Training Shop Blog About diff --git a/vendor/github.com/grpc-ecosystem/grpc-opentracing/README.rst b/vendor/github.com/grpc-ecosystem/grpc-opentracing/README.rst new file mode 100644 index 000000000..1d44e691a --- /dev/null +++ b/vendor/github.com/grpc-ecosystem/grpc-opentracing/README.rst @@ -0,0 +1,25 @@ +################ +GRPC-OpenTracing +################ + +This package enables distributed tracing in GRPC clients and servers via `The OpenTracing Project`_: a set of consistent, expressive, vendor-neutral APIs for distributed tracing and context propagation. + +Once a production system contends with real concurrency or splits into many services, crucial (and formerly easy) tasks become difficult: user-facing latency optimization, root-cause analysis of backend errors, communication about distinct pieces of a now-distributed system, etc. Distributed tracing follows a request on its journey from inception to completion from mobile/browser all the way to the microservices. + +As core services and libraries adopt OpenTracing, the application builder is no longer burdened with the task of adding basic tracing instrumentation to their own code. In this way, developers can build their applications with the tools they prefer and benefit from built-in tracing instrumentation. OpenTracing implementations exist for major distributed tracing systems and can be bound or swapped with a one-line configuration change. + +******************* +Further Information +******************* + +If you’re interested in learning more about the OpenTracing standard, join the conversation on our `mailing list`_ or `Gitter`_. + +If you want to learn more about the underlying API for your platform, visit the `source code`_. + +If you would like to implement OpenTracing in your project and need help, feel free to send us a note at `community@opentracing.io`_. + +.. _The OpenTracing Project: http://opentracing.io/ +.. _source code: https://github.com/opentracing/ +.. _mailing list: http://opentracing.us13.list-manage.com/subscribe?u=180afe03860541dae59e84153&id=19117aa6cd +.. _Gitter: https://gitter.im/opentracing/public +.. _community@opentracing.io: community@opentracing.io diff --git a/vendor/github.com/grpc-ecosystem/grpc-opentracing/go/otgrpc/README.md b/vendor/github.com/grpc-ecosystem/grpc-opentracing/go/otgrpc/README.md new file mode 100644 index 000000000..78c49dbbe --- /dev/null +++ b/vendor/github.com/grpc-ecosystem/grpc-opentracing/go/otgrpc/README.md @@ -0,0 +1,57 @@ +# OpenTracing support for gRPC in Go + +The `otgrpc` package makes it easy to add OpenTracing support to gRPC-based +systems in Go. + +## Installation + +``` +go get github.com/grpc-ecosystem/grpc-opentracing/go/otgrpc +``` + +## Documentation + +See the basic usage examples below and the [package documentation on +godoc.org](https://godoc.org/github.com/grpc-ecosystem/grpc-opentracing/go/otgrpc). + +## Client-side usage example + +Wherever you call `grpc.Dial`: + +```go +// You must have some sort of OpenTracing Tracer instance on hand. +var tracer opentracing.Tracer = ... +... + +// Set up a connection to the server peer. +conn, err := grpc.Dial( + address, + ... // other options + grpc.WithUnaryInterceptor( + otgrpc.OpenTracingClientInterceptor(tracer)), + grpc.WithStreamInterceptor( + otgrpc.OpenTracingStreamClientInterceptor(tracer))) + +// All future RPC activity involving `conn` will be automatically traced. +``` + +## Server-side usage example + +Wherever you call `grpc.NewServer`: + +```go +// You must have some sort of OpenTracing Tracer instance on hand. +var tracer opentracing.Tracer = ... +... + +// Initialize the gRPC server. +s := grpc.NewServer( + ... // other options + grpc.UnaryInterceptor( + otgrpc.OpenTracingServerInterceptor(tracer)), + grpc.StreamInterceptor( + otgrpc.OpenTracingStreamServerInterceptor(tracer))) + +// All future RPC activity involving `s` will be automatically traced. +``` + diff --git a/vendor/github.com/grpc-ecosystem/grpc-opentracing/go/otgrpc/client.go b/vendor/github.com/grpc-ecosystem/grpc-opentracing/go/otgrpc/client.go new file mode 100644 index 000000000..3414e55cb --- /dev/null +++ b/vendor/github.com/grpc-ecosystem/grpc-opentracing/go/otgrpc/client.go @@ -0,0 +1,239 @@ +package otgrpc + +import ( + "github.com/opentracing/opentracing-go" + "github.com/opentracing/opentracing-go/ext" + "github.com/opentracing/opentracing-go/log" + "golang.org/x/net/context" + "google.golang.org/grpc" + "google.golang.org/grpc/metadata" + "io" + "runtime" + "sync/atomic" +) + +// OpenTracingClientInterceptor returns a grpc.UnaryClientInterceptor suitable +// for use in a grpc.Dial call. +// +// For example: +// +// conn, err := grpc.Dial( +// address, +// ..., // (existing DialOptions) +// grpc.WithUnaryInterceptor(otgrpc.OpenTracingClientInterceptor(tracer))) +// +// All gRPC client spans will inject the OpenTracing SpanContext into the gRPC +// metadata; they will also look in the context.Context for an active +// in-process parent Span and establish a ChildOf reference if such a parent +// Span could be found. +func OpenTracingClientInterceptor(tracer opentracing.Tracer, optFuncs ...Option) grpc.UnaryClientInterceptor { + otgrpcOpts := newOptions() + otgrpcOpts.apply(optFuncs...) + return func( + ctx context.Context, + method string, + req, resp interface{}, + cc *grpc.ClientConn, + invoker grpc.UnaryInvoker, + opts ...grpc.CallOption, + ) error { + var err error + var parentCtx opentracing.SpanContext + if parent := opentracing.SpanFromContext(ctx); parent != nil { + parentCtx = parent.Context() + } + if otgrpcOpts.inclusionFunc != nil && + !otgrpcOpts.inclusionFunc(parentCtx, method, req, resp) { + return invoker(ctx, method, req, resp, cc, opts...) + } + clientSpan := tracer.StartSpan( + method, + opentracing.ChildOf(parentCtx), + ext.SpanKindRPCClient, + gRPCComponentTag, + ) + defer clientSpan.Finish() + ctx = injectSpanContext(ctx, tracer, clientSpan) + if otgrpcOpts.logPayloads { + clientSpan.LogFields(log.Object("gRPC request", req)) + } + err = invoker(ctx, method, req, resp, cc, opts...) + if err == nil { + if otgrpcOpts.logPayloads { + clientSpan.LogFields(log.Object("gRPC response", resp)) + } + } else { + SetSpanTags(clientSpan, err, true) + clientSpan.LogFields(log.String("event", "error"), log.String("message", err.Error())) + } + if otgrpcOpts.decorator != nil { + otgrpcOpts.decorator(clientSpan, method, req, resp, err) + } + return err + } +} + +// OpenTracingStreamClientInterceptor returns a grpc.StreamClientInterceptor suitable +// for use in a grpc.Dial call. The interceptor instruments streaming RPCs by creating +// a single span to correspond to the lifetime of the RPC's stream. +// +// For example: +// +// conn, err := grpc.Dial( +// address, +// ..., // (existing DialOptions) +// grpc.WithStreamInterceptor(otgrpc.OpenTracingStreamClientInterceptor(tracer))) +// +// All gRPC client spans will inject the OpenTracing SpanContext into the gRPC +// metadata; they will also look in the context.Context for an active +// in-process parent Span and establish a ChildOf reference if such a parent +// Span could be found. +func OpenTracingStreamClientInterceptor(tracer opentracing.Tracer, optFuncs ...Option) grpc.StreamClientInterceptor { + otgrpcOpts := newOptions() + otgrpcOpts.apply(optFuncs...) + return func( + ctx context.Context, + desc *grpc.StreamDesc, + cc *grpc.ClientConn, + method string, + streamer grpc.Streamer, + opts ...grpc.CallOption, + ) (grpc.ClientStream, error) { + var err error + var parentCtx opentracing.SpanContext + if parent := opentracing.SpanFromContext(ctx); parent != nil { + parentCtx = parent.Context() + } + if otgrpcOpts.inclusionFunc != nil && + !otgrpcOpts.inclusionFunc(parentCtx, method, nil, nil) { + return streamer(ctx, desc, cc, method, opts...) + } + + clientSpan := tracer.StartSpan( + method, + opentracing.ChildOf(parentCtx), + ext.SpanKindRPCClient, + gRPCComponentTag, + ) + ctx = injectSpanContext(ctx, tracer, clientSpan) + cs, err := streamer(ctx, desc, cc, method, opts...) + if err != nil { + clientSpan.LogFields(log.String("event", "error"), log.String("message", err.Error())) + SetSpanTags(clientSpan, err, true) + clientSpan.Finish() + return cs, err + } + return newOpenTracingClientStream(cs, method, desc, clientSpan, otgrpcOpts), nil + } +} + +func newOpenTracingClientStream(cs grpc.ClientStream, method string, desc *grpc.StreamDesc, clientSpan opentracing.Span, otgrpcOpts *options) grpc.ClientStream { + finishChan := make(chan struct{}) + + isFinished := new(int32) + *isFinished = 0 + finishFunc := func(err error) { + // The current OpenTracing specification forbids finishing a span more than + // once. Since we have multiple code paths that could concurrently call + // `finishFunc`, we need to add some sort of synchronization to guard against + // multiple finishing. + if !atomic.CompareAndSwapInt32(isFinished, 0, 1) { + return + } + close(finishChan) + defer clientSpan.Finish() + if err != nil { + clientSpan.LogFields(log.String("event", "error"), log.String("message", err.Error())) + SetSpanTags(clientSpan, err, true) + } + if otgrpcOpts.decorator != nil { + otgrpcOpts.decorator(clientSpan, method, nil, nil, err) + } + } + go func() { + select { + case <-finishChan: + // The client span is being finished by another code path; hence, no + // action is necessary. + case <-cs.Context().Done(): + finishFunc(cs.Context().Err()) + } + }() + otcs := &openTracingClientStream{ + ClientStream: cs, + desc: desc, + finishFunc: finishFunc, + } + + // The `ClientStream` interface allows one to omit calling `Recv` if it's + // known that the result will be `io.EOF`. See + // http://stackoverflow.com/q/42915337 + // In such cases, there's nothing that triggers the span to finish. We, + // therefore, set a finalizer so that the span and the context goroutine will + // at least be cleaned up when the garbage collector is run. + runtime.SetFinalizer(otcs, func(otcs *openTracingClientStream) { + otcs.finishFunc(nil) + }) + return otcs +} + +type openTracingClientStream struct { + grpc.ClientStream + desc *grpc.StreamDesc + finishFunc func(error) +} + +func (cs *openTracingClientStream) Header() (metadata.MD, error) { + md, err := cs.ClientStream.Header() + if err != nil { + cs.finishFunc(err) + } + return md, err +} + +func (cs *openTracingClientStream) SendMsg(m interface{}) error { + err := cs.ClientStream.SendMsg(m) + if err != nil { + cs.finishFunc(err) + } + return err +} + +func (cs *openTracingClientStream) RecvMsg(m interface{}) error { + err := cs.ClientStream.RecvMsg(m) + if err == io.EOF { + cs.finishFunc(nil) + return err + } else if err != nil { + cs.finishFunc(err) + return err + } + if !cs.desc.ServerStreams { + cs.finishFunc(nil) + } + return err +} + +func (cs *openTracingClientStream) CloseSend() error { + err := cs.ClientStream.CloseSend() + if err != nil { + cs.finishFunc(err) + } + return err +} + +func injectSpanContext(ctx context.Context, tracer opentracing.Tracer, clientSpan opentracing.Span) context.Context { + md, ok := metadata.FromOutgoingContext(ctx) + if !ok { + md = metadata.New(nil) + } else { + md = md.Copy() + } + mdWriter := metadataReaderWriter{md} + err := tracer.Inject(clientSpan.Context(), opentracing.HTTPHeaders, mdWriter) + // We have no better place to record an error than the Span itself :-/ + if err != nil { + clientSpan.LogFields(log.String("event", "Tracer.Inject() failed"), log.Error(err)) + } + return metadata.NewOutgoingContext(ctx, md) +} diff --git a/vendor/github.com/grpc-ecosystem/grpc-opentracing/go/otgrpc/errors.go b/vendor/github.com/grpc-ecosystem/grpc-opentracing/go/otgrpc/errors.go new file mode 100644 index 000000000..41a6346f2 --- /dev/null +++ b/vendor/github.com/grpc-ecosystem/grpc-opentracing/go/otgrpc/errors.go @@ -0,0 +1,69 @@ +package otgrpc + +import ( + "github.com/opentracing/opentracing-go" + "github.com/opentracing/opentracing-go/ext" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" +) + +// A Class is a set of types of outcomes (including errors) that will often +// be handled in the same way. +type Class string + +const ( + Unknown Class = "0xx" + // Success represents outcomes that achieved the desired results. + Success Class = "2xx" + // ClientError represents errors that were the client's fault. + ClientError Class = "4xx" + // ServerError represents errors that were the server's fault. + ServerError Class = "5xx" +) + +// ErrorClass returns the class of the given error +func ErrorClass(err error) Class { + if s, ok := status.FromError(err); ok { + switch s.Code() { + // Success or "success" + case codes.OK, codes.Canceled: + return Success + + // Client errors + case codes.InvalidArgument, codes.NotFound, codes.AlreadyExists, + codes.PermissionDenied, codes.Unauthenticated, codes.FailedPrecondition, + codes.OutOfRange: + return ClientError + + // Server errors + case codes.DeadlineExceeded, codes.ResourceExhausted, codes.Aborted, + codes.Unimplemented, codes.Internal, codes.Unavailable, codes.DataLoss: + return ServerError + + // Not sure + case codes.Unknown: + fallthrough + default: + return Unknown + } + } + return Unknown +} + +// SetSpanTags sets one or more tags on the given span according to the +// error. +func SetSpanTags(span opentracing.Span, err error, client bool) { + c := ErrorClass(err) + code := codes.Unknown + if s, ok := status.FromError(err); ok { + code = s.Code() + } + span.SetTag("response_code", code) + span.SetTag("response_class", c) + if err == nil { + return + } + if client || c == ServerError { + ext.Error.Set(span, true) + } +} diff --git a/vendor/github.com/grpc-ecosystem/grpc-opentracing/go/otgrpc/options.go b/vendor/github.com/grpc-ecosystem/grpc-opentracing/go/otgrpc/options.go new file mode 100644 index 000000000..903e8382e --- /dev/null +++ b/vendor/github.com/grpc-ecosystem/grpc-opentracing/go/otgrpc/options.go @@ -0,0 +1,76 @@ +package otgrpc + +import "github.com/opentracing/opentracing-go" + +// Option instances may be used in OpenTracing(Server|Client)Interceptor +// initialization. +// +// See this post about the "functional options" pattern: +// http://dave.cheney.net/2014/10/17/functional-options-for-friendly-apis +type Option func(o *options) + +// LogPayloads returns an Option that tells the OpenTracing instrumentation to +// try to log application payloads in both directions. +func LogPayloads() Option { + return func(o *options) { + o.logPayloads = true + } +} + +// SpanInclusionFunc provides an optional mechanism to decide whether or not +// to trace a given gRPC call. Return true to create a Span and initiate +// tracing, false to not create a Span and not trace. +// +// parentSpanCtx may be nil if no parent could be extraction from either the Go +// context.Context (on the client) or the RPC (on the server). +type SpanInclusionFunc func( + parentSpanCtx opentracing.SpanContext, + method string, + req, resp interface{}) bool + +// IncludingSpans binds a IncludeSpanFunc to the options +func IncludingSpans(inclusionFunc SpanInclusionFunc) Option { + return func(o *options) { + o.inclusionFunc = inclusionFunc + } +} + +// SpanDecoratorFunc provides an (optional) mechanism for otgrpc users to add +// arbitrary tags/logs/etc to the opentracing.Span associated with client +// and/or server RPCs. +type SpanDecoratorFunc func( + span opentracing.Span, + method string, + req, resp interface{}, + grpcError error) + +// SpanDecorator binds a function that decorates gRPC Spans. +func SpanDecorator(decorator SpanDecoratorFunc) Option { + return func(o *options) { + o.decorator = decorator + } +} + +// The internal-only options struct. Obviously overkill at the moment; but will +// scale well as production use dictates other configuration and tuning +// parameters. +type options struct { + logPayloads bool + decorator SpanDecoratorFunc + // May be nil. + inclusionFunc SpanInclusionFunc +} + +// newOptions returns the default options. +func newOptions() *options { + return &options{ + logPayloads: false, + inclusionFunc: nil, + } +} + +func (o *options) apply(opts ...Option) { + for _, opt := range opts { + opt(o) + } +} diff --git a/vendor/github.com/grpc-ecosystem/grpc-opentracing/go/otgrpc/package.go b/vendor/github.com/grpc-ecosystem/grpc-opentracing/go/otgrpc/package.go new file mode 100644 index 000000000..4ff3d1997 --- /dev/null +++ b/vendor/github.com/grpc-ecosystem/grpc-opentracing/go/otgrpc/package.go @@ -0,0 +1,5 @@ +// Package otgrpc provides OpenTracing support for any gRPC client or server. +// +// See the README for simple usage examples: +// https://github.com/grpc-ecosystem/grpc-opentracing/blob/master/go/otgrpc/README.md +package otgrpc diff --git a/vendor/github.com/grpc-ecosystem/grpc-opentracing/go/otgrpc/server.go b/vendor/github.com/grpc-ecosystem/grpc-opentracing/go/otgrpc/server.go new file mode 100644 index 000000000..62cf54d22 --- /dev/null +++ b/vendor/github.com/grpc-ecosystem/grpc-opentracing/go/otgrpc/server.go @@ -0,0 +1,141 @@ +package otgrpc + +import ( + "github.com/opentracing/opentracing-go" + "github.com/opentracing/opentracing-go/ext" + "github.com/opentracing/opentracing-go/log" + "golang.org/x/net/context" + "google.golang.org/grpc" + "google.golang.org/grpc/metadata" +) + +// OpenTracingServerInterceptor returns a grpc.UnaryServerInterceptor suitable +// for use in a grpc.NewServer call. +// +// For example: +// +// s := grpc.NewServer( +// ..., // (existing ServerOptions) +// grpc.UnaryInterceptor(otgrpc.OpenTracingServerInterceptor(tracer))) +// +// All gRPC server spans will look for an OpenTracing SpanContext in the gRPC +// metadata; if found, the server span will act as the ChildOf that RPC +// SpanContext. +// +// Root or not, the server Span will be embedded in the context.Context for the +// application-specific gRPC handler(s) to access. +func OpenTracingServerInterceptor(tracer opentracing.Tracer, optFuncs ...Option) grpc.UnaryServerInterceptor { + otgrpcOpts := newOptions() + otgrpcOpts.apply(optFuncs...) + return func( + ctx context.Context, + req interface{}, + info *grpc.UnaryServerInfo, + handler grpc.UnaryHandler, + ) (resp interface{}, err error) { + spanContext, err := extractSpanContext(ctx, tracer) + if err != nil && err != opentracing.ErrSpanContextNotFound { + // TODO: establish some sort of error reporting mechanism here. We + // don't know where to put such an error and must rely on Tracer + // implementations to do something appropriate for the time being. + } + if otgrpcOpts.inclusionFunc != nil && + !otgrpcOpts.inclusionFunc(spanContext, info.FullMethod, req, nil) { + return handler(ctx, req) + } + serverSpan := tracer.StartSpan( + info.FullMethod, + ext.RPCServerOption(spanContext), + gRPCComponentTag, + ) + defer serverSpan.Finish() + + ctx = opentracing.ContextWithSpan(ctx, serverSpan) + if otgrpcOpts.logPayloads { + serverSpan.LogFields(log.Object("gRPC request", req)) + } + resp, err = handler(ctx, req) + if err == nil { + if otgrpcOpts.logPayloads { + serverSpan.LogFields(log.Object("gRPC response", resp)) + } + } else { + SetSpanTags(serverSpan, err, false) + serverSpan.LogFields(log.String("event", "error"), log.String("message", err.Error())) + } + if otgrpcOpts.decorator != nil { + otgrpcOpts.decorator(serverSpan, info.FullMethod, req, resp, err) + } + return resp, err + } +} + +// OpenTracingStreamServerInterceptor returns a grpc.StreamServerInterceptor suitable +// for use in a grpc.NewServer call. The interceptor instruments streaming RPCs by +// creating a single span to correspond to the lifetime of the RPC's stream. +// +// For example: +// +// s := grpc.NewServer( +// ..., // (existing ServerOptions) +// grpc.StreamInterceptor(otgrpc.OpenTracingStreamServerInterceptor(tracer))) +// +// All gRPC server spans will look for an OpenTracing SpanContext in the gRPC +// metadata; if found, the server span will act as the ChildOf that RPC +// SpanContext. +// +// Root or not, the server Span will be embedded in the context.Context for the +// application-specific gRPC handler(s) to access. +func OpenTracingStreamServerInterceptor(tracer opentracing.Tracer, optFuncs ...Option) grpc.StreamServerInterceptor { + otgrpcOpts := newOptions() + otgrpcOpts.apply(optFuncs...) + return func(srv interface{}, ss grpc.ServerStream, info *grpc.StreamServerInfo, handler grpc.StreamHandler) error { + spanContext, err := extractSpanContext(ss.Context(), tracer) + if err != nil && err != opentracing.ErrSpanContextNotFound { + // TODO: establish some sort of error reporting mechanism here. We + // don't know where to put such an error and must rely on Tracer + // implementations to do something appropriate for the time being. + } + if otgrpcOpts.inclusionFunc != nil && + !otgrpcOpts.inclusionFunc(spanContext, info.FullMethod, nil, nil) { + return handler(srv, ss) + } + + serverSpan := tracer.StartSpan( + info.FullMethod, + ext.RPCServerOption(spanContext), + gRPCComponentTag, + ) + defer serverSpan.Finish() + ss = &openTracingServerStream{ + ServerStream: ss, + ctx: opentracing.ContextWithSpan(ss.Context(), serverSpan), + } + err = handler(srv, ss) + if err != nil { + SetSpanTags(serverSpan, err, false) + serverSpan.LogFields(log.String("event", "error"), log.String("message", err.Error())) + } + if otgrpcOpts.decorator != nil { + otgrpcOpts.decorator(serverSpan, info.FullMethod, nil, nil, err) + } + return err + } +} + +type openTracingServerStream struct { + grpc.ServerStream + ctx context.Context +} + +func (ss *openTracingServerStream) Context() context.Context { + return ss.ctx +} + +func extractSpanContext(ctx context.Context, tracer opentracing.Tracer) (opentracing.SpanContext, error) { + md, ok := metadata.FromIncomingContext(ctx) + if !ok { + md = metadata.New(nil) + } + return tracer.Extract(opentracing.HTTPHeaders, metadataReaderWriter{md}) +} diff --git a/vendor/github.com/grpc-ecosystem/grpc-opentracing/go/otgrpc/shared.go b/vendor/github.com/grpc-ecosystem/grpc-opentracing/go/otgrpc/shared.go new file mode 100644 index 000000000..9abd5eaa6 --- /dev/null +++ b/vendor/github.com/grpc-ecosystem/grpc-opentracing/go/otgrpc/shared.go @@ -0,0 +1,42 @@ +package otgrpc + +import ( + "strings" + + opentracing "github.com/opentracing/opentracing-go" + "github.com/opentracing/opentracing-go/ext" + "google.golang.org/grpc/metadata" +) + +var ( + // Morally a const: + gRPCComponentTag = opentracing.Tag{string(ext.Component), "gRPC"} +) + +// metadataReaderWriter satisfies both the opentracing.TextMapReader and +// opentracing.TextMapWriter interfaces. +type metadataReaderWriter struct { + metadata.MD +} + +func (w metadataReaderWriter) Set(key, val string) { + // The GRPC HPACK implementation rejects any uppercase keys here. + // + // As such, since the HTTP_HEADERS format is case-insensitive anyway, we + // blindly lowercase the key (which is guaranteed to work in the + // Inject/Extract sense per the OpenTracing spec). + key = strings.ToLower(key) + w.MD[key] = append(w.MD[key], val) +} + +func (w metadataReaderWriter) ForeachKey(handler func(key, val string) error) error { + for k, vals := range w.MD { + for _, v := range vals { + if err := handler(k, v); err != nil { + return err + } + } + } + + return nil +} diff --git a/vendor/github.com/grpc-ecosystem/grpc-opentracing/python/README.md b/vendor/github.com/grpc-ecosystem/grpc-opentracing/python/README.md new file mode 100644 index 000000000..c8648c62f --- /dev/null +++ b/vendor/github.com/grpc-ecosystem/grpc-opentracing/python/README.md @@ -0,0 +1,73 @@ +# OpenTracing support for gRPC in Python + +The `grpcio-opentracing` package makes it easy to add OpenTracing support to +gRPC-based systems in Python. + +## Installation + +``` +pip install grpcio-opentracing +``` + +## Getting started + +See the below code for basic usage or [examples/trivial](examples/trivial) for a +complete example. + +### Client-side usage example + +```python +from grpc_opentracing import open_tracing_client_interceptor +from grpc_opentracing.grpcext import intercept_channel + +tracer = # some OpenTracing Tracer instance +interceptor = open_tracing_client_interceptor(tracer) +channel = # the grpc.Channel you created to invoke RPCs +channel = intercept_channel(channel, interceptor) + +# All future RPC activity involving `channel` will be automatically traced. +``` + +### Server-side usage example + +```python +from grpc_opentracing import open_tracing_server_interceptor +from grpc_opentracing.grpcext import intercept_server + +tracer = # some OpenTracing Tracer instance +interceptor = open_tracing_server_interceptor(tracer) +server = # the grpc.Server you created to receive RPCs +server = intercept_server(server, interceptor) + +# All future RPC activity involving `server` will be automatically traced. +``` + +### Integrating with other spans. + +`grpcio-opentracing` provides features that let you connect its span with other +tracing spans. On the client-side, you can write a class that derives from +`ActiveSpanSource` and provide it when creating the interceptor. + +```python +class CustomActiveSpanSource(ActiveSpanSource): + def get_active_span(self): + # your custom method of getting the active span +tracer = # some OpenTracing Tracer instance +interceptor = open_tracing_client_interceptor( + tracer, + active_span_source=CustomActiveSpanSource) +... +``` + +On the server-side, the `context` argument passed into your service methods +packages the gRPC span created on the server-side. + +```python +class CustomRpcService(...): + ... + def Method1(self, request, context): + span = context.get_active_span() + ... +``` + +See [examples/integration](examples/integration) for a complete example. diff --git a/vendor/github.com/grpc-ecosystem/grpc-opentracing/python/examples/protos/command_line.proto b/vendor/github.com/grpc-ecosystem/grpc-opentracing/python/examples/protos/command_line.proto new file mode 100644 index 000000000..b2367a72e --- /dev/null +++ b/vendor/github.com/grpc-ecosystem/grpc-opentracing/python/examples/protos/command_line.proto @@ -0,0 +1,15 @@ +syntax = "proto3"; + +package command_line; + +service CommandLine { + rpc Echo(CommandRequest) returns (CommandResponse) {} +} + +message CommandRequest { + string text = 1; +} + +message CommandResponse { + string text = 1; +} diff --git a/vendor/github.com/grpc-ecosystem/grpc-opentracing/python/examples/protos/store.proto b/vendor/github.com/grpc-ecosystem/grpc-opentracing/python/examples/protos/store.proto new file mode 100644 index 000000000..6822d985d --- /dev/null +++ b/vendor/github.com/grpc-ecosystem/grpc-opentracing/python/examples/protos/store.proto @@ -0,0 +1,37 @@ +syntax = "proto3"; + +package store; + +service Store { + rpc AddItem(AddItemRequest) returns (Empty) {} + rpc AddItems(stream AddItemRequest) returns (Empty) {} + rpc RemoveItem(RemoveItemRequest) returns (RemoveItemResponse) {} + rpc RemoveItems(stream RemoveItemRequest) returns (RemoveItemResponse) {} + rpc ListInventory(Empty) returns (stream QuantityResponse) {} + rpc QueryQuantity(QueryItemRequest) returns (QuantityResponse) {} + rpc QueryQuantities(stream QueryItemRequest) + returns (stream QuantityResponse) {} +} + +message Empty {} + +message AddItemRequest { + string name = 1; +} + +message RemoveItemRequest { + string name = 1; +} + +message RemoveItemResponse { + bool was_successful = 1; +} + +message QueryItemRequest { + string name = 1; +} + +message QuantityResponse { + string name = 1; + int32 count = 2; +} diff --git a/vendor/github.com/opentracing/opentracing-go/LICENSE b/vendor/github.com/opentracing/opentracing-go/LICENSE new file mode 100644 index 000000000..148509a40 --- /dev/null +++ b/vendor/github.com/opentracing/opentracing-go/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2016 The OpenTracing Authors + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vendor/github.com/opentracing/opentracing-go/README.md b/vendor/github.com/opentracing/opentracing-go/README.md new file mode 100644 index 000000000..19a541c2c --- /dev/null +++ b/vendor/github.com/opentracing/opentracing-go/README.md @@ -0,0 +1,163 @@ +[![Gitter chat](http://img.shields.io/badge/gitter-join%20chat%20%E2%86%92-brightgreen.svg)](https://gitter.im/opentracing/public) [![Build Status](https://travis-ci.org/opentracing/opentracing-go.svg?branch=master)](https://travis-ci.org/opentracing/opentracing-go) [![GoDoc](https://godoc.org/github.com/opentracing/opentracing-go?status.svg)](http://godoc.org/github.com/opentracing/opentracing-go) +[![Sourcegraph Badge](https://sourcegraph.com/github.com/opentracing/opentracing-go/-/badge.svg)](https://sourcegraph.com/github.com/opentracing/opentracing-go?badge) + +# OpenTracing API for Go + +This package is a Go platform API for OpenTracing. + +## Required Reading + +In order to understand the Go platform API, one must first be familiar with the +[OpenTracing project](http://opentracing.io) and +[terminology](http://opentracing.io/documentation/pages/spec.html) more specifically. + +## API overview for those adding instrumentation + +Everyday consumers of this `opentracing` package really only need to worry +about a couple of key abstractions: the `StartSpan` function, the `Span` +interface, and binding a `Tracer` at `main()`-time. Here are code snippets +demonstrating some important use cases. + +#### Singleton initialization + +The simplest starting point is `./default_tracer.go`. As early as possible, call + +```go + import "github.com/opentracing/opentracing-go" + import ".../some_tracing_impl" + + func main() { + opentracing.InitGlobalTracer( + // tracing impl specific: + some_tracing_impl.New(...), + ) + ... + } +``` + +##### Non-Singleton initialization + +If you prefer direct control to singletons, manage ownership of the +`opentracing.Tracer` implementation explicitly. + +#### Creating a Span given an existing Go `context.Context` + +If you use `context.Context` in your application, OpenTracing's Go library will +happily rely on it for `Span` propagation. To start a new (blocking child) +`Span`, you can use `StartSpanFromContext`. + +```go + func xyz(ctx context.Context, ...) { + ... + span, ctx := opentracing.StartSpanFromContext(ctx, "operation_name") + defer span.Finish() + span.LogFields( + log.String("event", "soft error"), + log.String("type", "cache timeout"), + log.Int("waited.millis", 1500)) + ... + } +``` + +#### Starting an empty trace by creating a "root span" + +It's always possible to create a "root" `Span` with no parent or other causal +reference. + +```go + func xyz() { + ... + sp := opentracing.StartSpan("operation_name") + defer sp.Finish() + ... + } +``` + +#### Creating a (child) Span given an existing (parent) Span + +```go + func xyz(parentSpan opentracing.Span, ...) { + ... + sp := opentracing.StartSpan( + "operation_name", + opentracing.ChildOf(parentSpan.Context())) + defer sp.Finish() + ... + } +``` + +#### Serializing to the wire + +```go + func makeSomeRequest(ctx context.Context) ... { + if span := opentracing.SpanFromContext(ctx); span != nil { + httpClient := &http.Client{} + httpReq, _ := http.NewRequest("GET", "http://myservice/", nil) + + // Transmit the span's TraceContext as HTTP headers on our + // outbound request. + opentracing.GlobalTracer().Inject( + span.Context(), + opentracing.HTTPHeaders, + opentracing.HTTPHeadersCarrier(httpReq.Header)) + + resp, err := httpClient.Do(httpReq) + ... + } + ... + } +``` + +#### Deserializing from the wire + +```go + http.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) { + var serverSpan opentracing.Span + appSpecificOperationName := ... + wireContext, err := opentracing.GlobalTracer().Extract( + opentracing.HTTPHeaders, + opentracing.HTTPHeadersCarrier(req.Header)) + if err != nil { + // Optionally record something about err here + } + + // Create the span referring to the RPC client if available. + // If wireContext == nil, a root span will be created. + serverSpan = opentracing.StartSpan( + appSpecificOperationName, + ext.RPCServerOption(wireContext)) + + defer serverSpan.Finish() + + ctx := opentracing.ContextWithSpan(context.Background(), serverSpan) + ... + } +``` + +#### Conditionally capture a field using `log.Noop` + +In some situations, you may want to dynamically decide whether or not +to log a field. For example, you may want to capture additional data, +such as a customer ID, in non-production environments: + +```go + func Customer(order *Order) log.Field { + if os.Getenv("ENVIRONMENT") == "dev" { + return log.String("customer", order.Customer.ID) + } + return log.Noop() + } +``` + +#### Goroutine-safety + +The entire public API is goroutine-safe and does not require external +synchronization. + +## API pointers for those implementing a tracing system + +Tracing system implementors may be able to reuse or copy-paste-modify the `basictracer` package, found [here](https://github.com/opentracing/basictracer-go). In particular, see `basictracer.New(...)`. + +## API compatibility + +For the time being, "mild" backwards-incompatible changes may be made without changing the major version number. As OpenTracing and `opentracing-go` mature, backwards compatibility will become more of a priority. diff --git a/vendor/github.com/opentracing/opentracing-go/ext/tags.go b/vendor/github.com/opentracing/opentracing-go/ext/tags.go new file mode 100644 index 000000000..8800129a2 --- /dev/null +++ b/vendor/github.com/opentracing/opentracing-go/ext/tags.go @@ -0,0 +1,210 @@ +package ext + +import opentracing "github.com/opentracing/opentracing-go" + +// These constants define common tag names recommended for better portability across +// tracing systems and languages/platforms. +// +// The tag names are defined as typed strings, so that in addition to the usual use +// +// span.setTag(TagName, value) +// +// they also support value type validation via this additional syntax: +// +// TagName.Set(span, value) +// +var ( + ////////////////////////////////////////////////////////////////////// + // SpanKind (client/server or producer/consumer) + ////////////////////////////////////////////////////////////////////// + + // SpanKind hints at relationship between spans, e.g. client/server + SpanKind = spanKindTagName("span.kind") + + // SpanKindRPCClient marks a span representing the client-side of an RPC + // or other remote call + SpanKindRPCClientEnum = SpanKindEnum("client") + SpanKindRPCClient = opentracing.Tag{Key: string(SpanKind), Value: SpanKindRPCClientEnum} + + // SpanKindRPCServer marks a span representing the server-side of an RPC + // or other remote call + SpanKindRPCServerEnum = SpanKindEnum("server") + SpanKindRPCServer = opentracing.Tag{Key: string(SpanKind), Value: SpanKindRPCServerEnum} + + // SpanKindProducer marks a span representing the producer-side of a + // message bus + SpanKindProducerEnum = SpanKindEnum("producer") + SpanKindProducer = opentracing.Tag{Key: string(SpanKind), Value: SpanKindProducerEnum} + + // SpanKindConsumer marks a span representing the consumer-side of a + // message bus + SpanKindConsumerEnum = SpanKindEnum("consumer") + SpanKindConsumer = opentracing.Tag{Key: string(SpanKind), Value: SpanKindConsumerEnum} + + ////////////////////////////////////////////////////////////////////// + // Component name + ////////////////////////////////////////////////////////////////////// + + // Component is a low-cardinality identifier of the module, library, + // or package that is generating a span. + Component = stringTagName("component") + + ////////////////////////////////////////////////////////////////////// + // Sampling hint + ////////////////////////////////////////////////////////////////////// + + // SamplingPriority determines the priority of sampling this Span. + SamplingPriority = uint16TagName("sampling.priority") + + ////////////////////////////////////////////////////////////////////// + // Peer tags. These tags can be emitted by either client-side of + // server-side to describe the other side/service in a peer-to-peer + // communications, like an RPC call. + ////////////////////////////////////////////////////////////////////// + + // PeerService records the service name of the peer. + PeerService = stringTagName("peer.service") + + // PeerAddress records the address name of the peer. This may be a "ip:port", + // a bare "hostname", a FQDN or even a database DSN substring + // like "mysql://username@127.0.0.1:3306/dbname" + PeerAddress = stringTagName("peer.address") + + // PeerHostname records the host name of the peer + PeerHostname = stringTagName("peer.hostname") + + // PeerHostIPv4 records IP v4 host address of the peer + PeerHostIPv4 = ipv4Tag("peer.ipv4") + + // PeerHostIPv6 records IP v6 host address of the peer + PeerHostIPv6 = stringTagName("peer.ipv6") + + // PeerPort records port number of the peer + PeerPort = uint16TagName("peer.port") + + ////////////////////////////////////////////////////////////////////// + // HTTP Tags + ////////////////////////////////////////////////////////////////////// + + // HTTPUrl should be the URL of the request being handled in this segment + // of the trace, in standard URI format. The protocol is optional. + HTTPUrl = stringTagName("http.url") + + // HTTPMethod is the HTTP method of the request, and is case-insensitive. + HTTPMethod = stringTagName("http.method") + + // HTTPStatusCode is the numeric HTTP status code (200, 404, etc) of the + // HTTP response. + HTTPStatusCode = uint16TagName("http.status_code") + + ////////////////////////////////////////////////////////////////////// + // DB Tags + ////////////////////////////////////////////////////////////////////// + + // DBInstance is database instance name. + DBInstance = stringTagName("db.instance") + + // DBStatement is a database statement for the given database type. + // It can be a query or a prepared statement (i.e., before substitution). + DBStatement = stringTagName("db.statement") + + // DBType is a database type. For any SQL database, "sql". + // For others, the lower-case database category, e.g. "redis" + DBType = stringTagName("db.type") + + // DBUser is a username for accessing database. + DBUser = stringTagName("db.user") + + ////////////////////////////////////////////////////////////////////// + // Message Bus Tag + ////////////////////////////////////////////////////////////////////// + + // MessageBusDestination is an address at which messages can be exchanged + MessageBusDestination = stringTagName("message_bus.destination") + + ////////////////////////////////////////////////////////////////////// + // Error Tag + ////////////////////////////////////////////////////////////////////// + + // Error indicates that operation represented by the span resulted in an error. + Error = boolTagName("error") +) + +// --- + +// SpanKindEnum represents common span types +type SpanKindEnum string + +type spanKindTagName string + +// Set adds a string tag to the `span` +func (tag spanKindTagName) Set(span opentracing.Span, value SpanKindEnum) { + span.SetTag(string(tag), value) +} + +type rpcServerOption struct { + clientContext opentracing.SpanContext +} + +func (r rpcServerOption) Apply(o *opentracing.StartSpanOptions) { + if r.clientContext != nil { + opentracing.ChildOf(r.clientContext).Apply(o) + } + SpanKindRPCServer.Apply(o) +} + +// RPCServerOption returns a StartSpanOption appropriate for an RPC server span +// with `client` representing the metadata for the remote peer Span if available. +// In case client == nil, due to the client not being instrumented, this RPC +// server span will be a root span. +func RPCServerOption(client opentracing.SpanContext) opentracing.StartSpanOption { + return rpcServerOption{client} +} + +// --- + +type stringTagName string + +// Set adds a string tag to the `span` +func (tag stringTagName) Set(span opentracing.Span, value string) { + span.SetTag(string(tag), value) +} + +// --- + +type uint32TagName string + +// Set adds a uint32 tag to the `span` +func (tag uint32TagName) Set(span opentracing.Span, value uint32) { + span.SetTag(string(tag), value) +} + +// --- + +type uint16TagName string + +// Set adds a uint16 tag to the `span` +func (tag uint16TagName) Set(span opentracing.Span, value uint16) { + span.SetTag(string(tag), value) +} + +// --- + +type boolTagName string + +// Add adds a bool tag to the `span` +func (tag boolTagName) Set(span opentracing.Span, value bool) { + span.SetTag(string(tag), value) +} + +type ipv4Tag string + +// Set adds IP v4 host address of the peer as an uint32 value to the `span`, keep this for backward and zipkin compatibility +func (tag ipv4Tag) Set(span opentracing.Span, value uint32) { + span.SetTag(string(tag), value) +} + +// SetString records IP v4 host address of the peer as a .-separated tuple to the `span`. E.g., "127.0.0.1" +func (tag ipv4Tag) SetString(span opentracing.Span, value string) { + span.SetTag(string(tag), value) +} diff --git a/vendor/github.com/opentracing/opentracing-go/globaltracer.go b/vendor/github.com/opentracing/opentracing-go/globaltracer.go new file mode 100644 index 000000000..8c8e793ff --- /dev/null +++ b/vendor/github.com/opentracing/opentracing-go/globaltracer.go @@ -0,0 +1,32 @@ +package opentracing + +var ( + globalTracer Tracer = NoopTracer{} +) + +// SetGlobalTracer sets the [singleton] opentracing.Tracer returned by +// GlobalTracer(). Those who use GlobalTracer (rather than directly manage an +// opentracing.Tracer instance) should call SetGlobalTracer as early as +// possible in main(), prior to calling the `StartSpan` global func below. +// Prior to calling `SetGlobalTracer`, any Spans started via the `StartSpan` +// (etc) globals are noops. +func SetGlobalTracer(tracer Tracer) { + globalTracer = tracer +} + +// GlobalTracer returns the global singleton `Tracer` implementation. +// Before `SetGlobalTracer()` is called, the `GlobalTracer()` is a noop +// implementation that drops all data handed to it. +func GlobalTracer() Tracer { + return globalTracer +} + +// StartSpan defers to `Tracer.StartSpan`. See `GlobalTracer()`. +func StartSpan(operationName string, opts ...StartSpanOption) Span { + return globalTracer.StartSpan(operationName, opts...) +} + +// InitGlobalTracer is deprecated. Please use SetGlobalTracer. +func InitGlobalTracer(tracer Tracer) { + SetGlobalTracer(tracer) +} diff --git a/vendor/github.com/opentracing/opentracing-go/gocontext.go b/vendor/github.com/opentracing/opentracing-go/gocontext.go new file mode 100644 index 000000000..222a65202 --- /dev/null +++ b/vendor/github.com/opentracing/opentracing-go/gocontext.go @@ -0,0 +1,57 @@ +package opentracing + +import "golang.org/x/net/context" + +type contextKey struct{} + +var activeSpanKey = contextKey{} + +// ContextWithSpan returns a new `context.Context` that holds a reference to +// `span`'s SpanContext. +func ContextWithSpan(ctx context.Context, span Span) context.Context { + return context.WithValue(ctx, activeSpanKey, span) +} + +// SpanFromContext returns the `Span` previously associated with `ctx`, or +// `nil` if no such `Span` could be found. +// +// NOTE: context.Context != SpanContext: the former is Go's intra-process +// context propagation mechanism, and the latter houses OpenTracing's per-Span +// identity and baggage information. +func SpanFromContext(ctx context.Context) Span { + val := ctx.Value(activeSpanKey) + if sp, ok := val.(Span); ok { + return sp + } + return nil +} + +// StartSpanFromContext starts and returns a Span with `operationName`, using +// any Span found within `ctx` as a ChildOfRef. If no such parent could be +// found, StartSpanFromContext creates a root (parentless) Span. +// +// The second return value is a context.Context object built around the +// returned Span. +// +// Example usage: +// +// SomeFunction(ctx context.Context, ...) { +// sp, ctx := opentracing.StartSpanFromContext(ctx, "SomeFunction") +// defer sp.Finish() +// ... +// } +func StartSpanFromContext(ctx context.Context, operationName string, opts ...StartSpanOption) (Span, context.Context) { + return startSpanFromContextWithTracer(ctx, GlobalTracer(), operationName, opts...) +} + +// startSpanFromContextWithTracer is factored out for testing purposes. +func startSpanFromContextWithTracer(ctx context.Context, tracer Tracer, operationName string, opts ...StartSpanOption) (Span, context.Context) { + var span Span + if parentSpan := SpanFromContext(ctx); parentSpan != nil { + opts = append(opts, ChildOf(parentSpan.Context())) + span = tracer.StartSpan(operationName, opts...) + } else { + span = tracer.StartSpan(operationName, opts...) + } + return span, ContextWithSpan(ctx, span) +} diff --git a/vendor/github.com/opentracing/opentracing-go/log/field.go b/vendor/github.com/opentracing/opentracing-go/log/field.go new file mode 100644 index 000000000..50feea341 --- /dev/null +++ b/vendor/github.com/opentracing/opentracing-go/log/field.go @@ -0,0 +1,269 @@ +package log + +import ( + "fmt" + "math" +) + +type fieldType int + +const ( + stringType fieldType = iota + boolType + intType + int32Type + uint32Type + int64Type + uint64Type + float32Type + float64Type + errorType + objectType + lazyLoggerType + noopType +) + +// Field instances are constructed via LogBool, LogString, and so on. +// Tracing implementations may then handle them via the Field.Marshal +// method. +// +// "heavily influenced by" (i.e., partially stolen from) +// https://github.com/uber-go/zap +type Field struct { + key string + fieldType fieldType + numericVal int64 + stringVal string + interfaceVal interface{} +} + +// String adds a string-valued key:value pair to a Span.LogFields() record +func String(key, val string) Field { + return Field{ + key: key, + fieldType: stringType, + stringVal: val, + } +} + +// Bool adds a bool-valued key:value pair to a Span.LogFields() record +func Bool(key string, val bool) Field { + var numericVal int64 + if val { + numericVal = 1 + } + return Field{ + key: key, + fieldType: boolType, + numericVal: numericVal, + } +} + +// Int adds an int-valued key:value pair to a Span.LogFields() record +func Int(key string, val int) Field { + return Field{ + key: key, + fieldType: intType, + numericVal: int64(val), + } +} + +// Int32 adds an int32-valued key:value pair to a Span.LogFields() record +func Int32(key string, val int32) Field { + return Field{ + key: key, + fieldType: int32Type, + numericVal: int64(val), + } +} + +// Int64 adds an int64-valued key:value pair to a Span.LogFields() record +func Int64(key string, val int64) Field { + return Field{ + key: key, + fieldType: int64Type, + numericVal: val, + } +} + +// Uint32 adds a uint32-valued key:value pair to a Span.LogFields() record +func Uint32(key string, val uint32) Field { + return Field{ + key: key, + fieldType: uint32Type, + numericVal: int64(val), + } +} + +// Uint64 adds a uint64-valued key:value pair to a Span.LogFields() record +func Uint64(key string, val uint64) Field { + return Field{ + key: key, + fieldType: uint64Type, + numericVal: int64(val), + } +} + +// Float32 adds a float32-valued key:value pair to a Span.LogFields() record +func Float32(key string, val float32) Field { + return Field{ + key: key, + fieldType: float32Type, + numericVal: int64(math.Float32bits(val)), + } +} + +// Float64 adds a float64-valued key:value pair to a Span.LogFields() record +func Float64(key string, val float64) Field { + return Field{ + key: key, + fieldType: float64Type, + numericVal: int64(math.Float64bits(val)), + } +} + +// Error adds an error with the key "error" to a Span.LogFields() record +func Error(err error) Field { + return Field{ + key: "error", + fieldType: errorType, + interfaceVal: err, + } +} + +// Object adds an object-valued key:value pair to a Span.LogFields() record +func Object(key string, obj interface{}) Field { + return Field{ + key: key, + fieldType: objectType, + interfaceVal: obj, + } +} + +// LazyLogger allows for user-defined, late-bound logging of arbitrary data +type LazyLogger func(fv Encoder) + +// Lazy adds a LazyLogger to a Span.LogFields() record; the tracing +// implementation will call the LazyLogger function at an indefinite time in +// the future (after Lazy() returns). +func Lazy(ll LazyLogger) Field { + return Field{ + fieldType: lazyLoggerType, + interfaceVal: ll, + } +} + +// Noop creates a no-op log field that should be ignored by the tracer. +// It can be used to capture optional fields, for example those that should +// only be logged in non-production environment: +// +// func customerField(order *Order) log.Field { +// if os.Getenv("ENVIRONMENT") == "dev" { +// return log.String("customer", order.Customer.ID) +// } +// return log.Noop() +// } +// +// span.LogFields(log.String("event", "purchase"), customerField(order)) +// +func Noop() Field { + return Field{ + fieldType: noopType, + } +} + +// Encoder allows access to the contents of a Field (via a call to +// Field.Marshal). +// +// Tracer implementations typically provide an implementation of Encoder; +// OpenTracing callers typically do not need to concern themselves with it. +type Encoder interface { + EmitString(key, value string) + EmitBool(key string, value bool) + EmitInt(key string, value int) + EmitInt32(key string, value int32) + EmitInt64(key string, value int64) + EmitUint32(key string, value uint32) + EmitUint64(key string, value uint64) + EmitFloat32(key string, value float32) + EmitFloat64(key string, value float64) + EmitObject(key string, value interface{}) + EmitLazyLogger(value LazyLogger) +} + +// Marshal passes a Field instance through to the appropriate +// field-type-specific method of an Encoder. +func (lf Field) Marshal(visitor Encoder) { + switch lf.fieldType { + case stringType: + visitor.EmitString(lf.key, lf.stringVal) + case boolType: + visitor.EmitBool(lf.key, lf.numericVal != 0) + case intType: + visitor.EmitInt(lf.key, int(lf.numericVal)) + case int32Type: + visitor.EmitInt32(lf.key, int32(lf.numericVal)) + case int64Type: + visitor.EmitInt64(lf.key, int64(lf.numericVal)) + case uint32Type: + visitor.EmitUint32(lf.key, uint32(lf.numericVal)) + case uint64Type: + visitor.EmitUint64(lf.key, uint64(lf.numericVal)) + case float32Type: + visitor.EmitFloat32(lf.key, math.Float32frombits(uint32(lf.numericVal))) + case float64Type: + visitor.EmitFloat64(lf.key, math.Float64frombits(uint64(lf.numericVal))) + case errorType: + if err, ok := lf.interfaceVal.(error); ok { + visitor.EmitString(lf.key, err.Error()) + } else { + visitor.EmitString(lf.key, "") + } + case objectType: + visitor.EmitObject(lf.key, lf.interfaceVal) + case lazyLoggerType: + visitor.EmitLazyLogger(lf.interfaceVal.(LazyLogger)) + case noopType: + // intentionally left blank + } +} + +// Key returns the field's key. +func (lf Field) Key() string { + return lf.key +} + +// Value returns the field's value as interface{}. +func (lf Field) Value() interface{} { + switch lf.fieldType { + case stringType: + return lf.stringVal + case boolType: + return lf.numericVal != 0 + case intType: + return int(lf.numericVal) + case int32Type: + return int32(lf.numericVal) + case int64Type: + return int64(lf.numericVal) + case uint32Type: + return uint32(lf.numericVal) + case uint64Type: + return uint64(lf.numericVal) + case float32Type: + return math.Float32frombits(uint32(lf.numericVal)) + case float64Type: + return math.Float64frombits(uint64(lf.numericVal)) + case errorType, objectType, lazyLoggerType: + return lf.interfaceVal + case noopType: + return nil + default: + return nil + } +} + +// String returns a string representation of the key and value. +func (lf Field) String() string { + return fmt.Sprint(lf.key, ":", lf.Value()) +} diff --git a/vendor/github.com/opentracing/opentracing-go/log/util.go b/vendor/github.com/opentracing/opentracing-go/log/util.go new file mode 100644 index 000000000..3832feb5c --- /dev/null +++ b/vendor/github.com/opentracing/opentracing-go/log/util.go @@ -0,0 +1,54 @@ +package log + +import "fmt" + +// InterleavedKVToFields converts keyValues a la Span.LogKV() to a Field slice +// a la Span.LogFields(). +func InterleavedKVToFields(keyValues ...interface{}) ([]Field, error) { + if len(keyValues)%2 != 0 { + return nil, fmt.Errorf("non-even keyValues len: %d", len(keyValues)) + } + fields := make([]Field, len(keyValues)/2) + for i := 0; i*2 < len(keyValues); i++ { + key, ok := keyValues[i*2].(string) + if !ok { + return nil, fmt.Errorf( + "non-string key (pair #%d): %T", + i, keyValues[i*2]) + } + switch typedVal := keyValues[i*2+1].(type) { + case bool: + fields[i] = Bool(key, typedVal) + case string: + fields[i] = String(key, typedVal) + case int: + fields[i] = Int(key, typedVal) + case int8: + fields[i] = Int32(key, int32(typedVal)) + case int16: + fields[i] = Int32(key, int32(typedVal)) + case int32: + fields[i] = Int32(key, typedVal) + case int64: + fields[i] = Int64(key, typedVal) + case uint: + fields[i] = Uint64(key, uint64(typedVal)) + case uint64: + fields[i] = Uint64(key, typedVal) + case uint8: + fields[i] = Uint32(key, uint32(typedVal)) + case uint16: + fields[i] = Uint32(key, uint32(typedVal)) + case uint32: + fields[i] = Uint32(key, typedVal) + case float32: + fields[i] = Float32(key, typedVal) + case float64: + fields[i] = Float64(key, typedVal) + default: + // When in doubt, coerce to a string + fields[i] = String(key, fmt.Sprint(typedVal)) + } + } + return fields, nil +} diff --git a/vendor/github.com/opentracing/opentracing-go/noop.go b/vendor/github.com/opentracing/opentracing-go/noop.go new file mode 100644 index 000000000..0d32f692c --- /dev/null +++ b/vendor/github.com/opentracing/opentracing-go/noop.go @@ -0,0 +1,64 @@ +package opentracing + +import "github.com/opentracing/opentracing-go/log" + +// A NoopTracer is a trivial, minimum overhead implementation of Tracer +// for which all operations are no-ops. +// +// The primary use of this implementation is in libraries, such as RPC +// frameworks, that make tracing an optional feature controlled by the +// end user. A no-op implementation allows said libraries to use it +// as the default Tracer and to write instrumentation that does +// not need to keep checking if the tracer instance is nil. +// +// For the same reason, the NoopTracer is the default "global" tracer +// (see GlobalTracer and SetGlobalTracer functions). +// +// WARNING: NoopTracer does not support baggage propagation. +type NoopTracer struct{} + +type noopSpan struct{} +type noopSpanContext struct{} + +var ( + defaultNoopSpanContext = noopSpanContext{} + defaultNoopSpan = noopSpan{} + defaultNoopTracer = NoopTracer{} +) + +const ( + emptyString = "" +) + +// noopSpanContext: +func (n noopSpanContext) ForeachBaggageItem(handler func(k, v string) bool) {} + +// noopSpan: +func (n noopSpan) Context() SpanContext { return defaultNoopSpanContext } +func (n noopSpan) SetBaggageItem(key, val string) Span { return defaultNoopSpan } +func (n noopSpan) BaggageItem(key string) string { return emptyString } +func (n noopSpan) SetTag(key string, value interface{}) Span { return n } +func (n noopSpan) LogFields(fields ...log.Field) {} +func (n noopSpan) LogKV(keyVals ...interface{}) {} +func (n noopSpan) Finish() {} +func (n noopSpan) FinishWithOptions(opts FinishOptions) {} +func (n noopSpan) SetOperationName(operationName string) Span { return n } +func (n noopSpan) Tracer() Tracer { return defaultNoopTracer } +func (n noopSpan) LogEvent(event string) {} +func (n noopSpan) LogEventWithPayload(event string, payload interface{}) {} +func (n noopSpan) Log(data LogData) {} + +// StartSpan belongs to the Tracer interface. +func (n NoopTracer) StartSpan(operationName string, opts ...StartSpanOption) Span { + return defaultNoopSpan +} + +// Inject belongs to the Tracer interface. +func (n NoopTracer) Inject(sp SpanContext, format interface{}, carrier interface{}) error { + return nil +} + +// Extract belongs to the Tracer interface. +func (n NoopTracer) Extract(format interface{}, carrier interface{}) (SpanContext, error) { + return nil, ErrSpanContextNotFound +} diff --git a/vendor/github.com/opentracing/opentracing-go/propagation.go b/vendor/github.com/opentracing/opentracing-go/propagation.go new file mode 100644 index 000000000..0dd466a37 --- /dev/null +++ b/vendor/github.com/opentracing/opentracing-go/propagation.go @@ -0,0 +1,176 @@ +package opentracing + +import ( + "errors" + "net/http" +) + +/////////////////////////////////////////////////////////////////////////////// +// CORE PROPAGATION INTERFACES: +/////////////////////////////////////////////////////////////////////////////// + +var ( + // ErrUnsupportedFormat occurs when the `format` passed to Tracer.Inject() or + // Tracer.Extract() is not recognized by the Tracer implementation. + ErrUnsupportedFormat = errors.New("opentracing: Unknown or unsupported Inject/Extract format") + + // ErrSpanContextNotFound occurs when the `carrier` passed to + // Tracer.Extract() is valid and uncorrupted but has insufficient + // information to extract a SpanContext. + ErrSpanContextNotFound = errors.New("opentracing: SpanContext not found in Extract carrier") + + // ErrInvalidSpanContext errors occur when Tracer.Inject() is asked to + // operate on a SpanContext which it is not prepared to handle (for + // example, since it was created by a different tracer implementation). + ErrInvalidSpanContext = errors.New("opentracing: SpanContext type incompatible with tracer") + + // ErrInvalidCarrier errors occur when Tracer.Inject() or Tracer.Extract() + // implementations expect a different type of `carrier` than they are + // given. + ErrInvalidCarrier = errors.New("opentracing: Invalid Inject/Extract carrier") + + // ErrSpanContextCorrupted occurs when the `carrier` passed to + // Tracer.Extract() is of the expected type but is corrupted. + ErrSpanContextCorrupted = errors.New("opentracing: SpanContext data corrupted in Extract carrier") +) + +/////////////////////////////////////////////////////////////////////////////// +// BUILTIN PROPAGATION FORMATS: +/////////////////////////////////////////////////////////////////////////////// + +// BuiltinFormat is used to demarcate the values within package `opentracing` +// that are intended for use with the Tracer.Inject() and Tracer.Extract() +// methods. +type BuiltinFormat byte + +const ( + // Binary represents SpanContexts as opaque binary data. + // + // For Tracer.Inject(): the carrier must be an `io.Writer`. + // + // For Tracer.Extract(): the carrier must be an `io.Reader`. + Binary BuiltinFormat = iota + + // TextMap represents SpanContexts as key:value string pairs. + // + // Unlike HTTPHeaders, the TextMap format does not restrict the key or + // value character sets in any way. + // + // For Tracer.Inject(): the carrier must be a `TextMapWriter`. + // + // For Tracer.Extract(): the carrier must be a `TextMapReader`. + TextMap + + // HTTPHeaders represents SpanContexts as HTTP header string pairs. + // + // Unlike TextMap, the HTTPHeaders format requires that the keys and values + // be valid as HTTP headers as-is (i.e., character casing may be unstable + // and special characters are disallowed in keys, values should be + // URL-escaped, etc). + // + // For Tracer.Inject(): the carrier must be a `TextMapWriter`. + // + // For Tracer.Extract(): the carrier must be a `TextMapReader`. + // + // See HTTPHeadersCarrier for an implementation of both TextMapWriter + // and TextMapReader that defers to an http.Header instance for storage. + // For example, Inject(): + // + // carrier := opentracing.HTTPHeadersCarrier(httpReq.Header) + // err := span.Tracer().Inject( + // span.Context(), opentracing.HTTPHeaders, carrier) + // + // Or Extract(): + // + // carrier := opentracing.HTTPHeadersCarrier(httpReq.Header) + // clientContext, err := tracer.Extract( + // opentracing.HTTPHeaders, carrier) + // + HTTPHeaders +) + +// TextMapWriter is the Inject() carrier for the TextMap builtin format. With +// it, the caller can encode a SpanContext for propagation as entries in a map +// of unicode strings. +type TextMapWriter interface { + // Set a key:value pair to the carrier. Multiple calls to Set() for the + // same key leads to undefined behavior. + // + // NOTE: The backing store for the TextMapWriter may contain data unrelated + // to SpanContext. As such, Inject() and Extract() implementations that + // call the TextMapWriter and TextMapReader interfaces must agree on a + // prefix or other convention to distinguish their own key:value pairs. + Set(key, val string) +} + +// TextMapReader is the Extract() carrier for the TextMap builtin format. With it, +// the caller can decode a propagated SpanContext as entries in a map of +// unicode strings. +type TextMapReader interface { + // ForeachKey returns TextMap contents via repeated calls to the `handler` + // function. If any call to `handler` returns a non-nil error, ForeachKey + // terminates and returns that error. + // + // NOTE: The backing store for the TextMapReader may contain data unrelated + // to SpanContext. As such, Inject() and Extract() implementations that + // call the TextMapWriter and TextMapReader interfaces must agree on a + // prefix or other convention to distinguish their own key:value pairs. + // + // The "foreach" callback pattern reduces unnecessary copying in some cases + // and also allows implementations to hold locks while the map is read. + ForeachKey(handler func(key, val string) error) error +} + +// TextMapCarrier allows the use of regular map[string]string +// as both TextMapWriter and TextMapReader. +type TextMapCarrier map[string]string + +// ForeachKey conforms to the TextMapReader interface. +func (c TextMapCarrier) ForeachKey(handler func(key, val string) error) error { + for k, v := range c { + if err := handler(k, v); err != nil { + return err + } + } + return nil +} + +// Set implements Set() of opentracing.TextMapWriter +func (c TextMapCarrier) Set(key, val string) { + c[key] = val +} + +// HTTPHeadersCarrier satisfies both TextMapWriter and TextMapReader. +// +// Example usage for server side: +// +// carrier := opentracing.HTTPHeadersCarrier(httpReq.Header) +// clientContext, err := tracer.Extract(opentracing.HTTPHeaders, carrier) +// +// Example usage for client side: +// +// carrier := opentracing.HTTPHeadersCarrier(httpReq.Header) +// err := tracer.Inject( +// span.Context(), +// opentracing.HTTPHeaders, +// carrier) +// +type HTTPHeadersCarrier http.Header + +// Set conforms to the TextMapWriter interface. +func (c HTTPHeadersCarrier) Set(key, val string) { + h := http.Header(c) + h.Add(key, val) +} + +// ForeachKey conforms to the TextMapReader interface. +func (c HTTPHeadersCarrier) ForeachKey(handler func(key, val string) error) error { + for k, vals := range c { + for _, v := range vals { + if err := handler(k, v); err != nil { + return err + } + } + } + return nil +} diff --git a/vendor/github.com/opentracing/opentracing-go/span.go b/vendor/github.com/opentracing/opentracing-go/span.go new file mode 100644 index 000000000..f6c3234ac --- /dev/null +++ b/vendor/github.com/opentracing/opentracing-go/span.go @@ -0,0 +1,185 @@ +package opentracing + +import ( + "time" + + "github.com/opentracing/opentracing-go/log" +) + +// SpanContext represents Span state that must propagate to descendant Spans and across process +// boundaries (e.g., a tuple). +type SpanContext interface { + // ForeachBaggageItem grants access to all baggage items stored in the + // SpanContext. + // The handler function will be called for each baggage key/value pair. + // The ordering of items is not guaranteed. + // + // The bool return value indicates if the handler wants to continue iterating + // through the rest of the baggage items; for example if the handler is trying to + // find some baggage item by pattern matching the name, it can return false + // as soon as the item is found to stop further iterations. + ForeachBaggageItem(handler func(k, v string) bool) +} + +// Span represents an active, un-finished span in the OpenTracing system. +// +// Spans are created by the Tracer interface. +type Span interface { + // Sets the end timestamp and finalizes Span state. + // + // With the exception of calls to Context() (which are always allowed), + // Finish() must be the last call made to any span instance, and to do + // otherwise leads to undefined behavior. + Finish() + // FinishWithOptions is like Finish() but with explicit control over + // timestamps and log data. + FinishWithOptions(opts FinishOptions) + + // Context() yields the SpanContext for this Span. Note that the return + // value of Context() is still valid after a call to Span.Finish(), as is + // a call to Span.Context() after a call to Span.Finish(). + Context() SpanContext + + // Sets or changes the operation name. + SetOperationName(operationName string) Span + + // Adds a tag to the span. + // + // If there is a pre-existing tag set for `key`, it is overwritten. + // + // Tag values can be numeric types, strings, or bools. The behavior of + // other tag value types is undefined at the OpenTracing level. If a + // tracing system does not know how to handle a particular value type, it + // may ignore the tag, but shall not panic. + SetTag(key string, value interface{}) Span + + // LogFields is an efficient and type-checked way to record key:value + // logging data about a Span, though the programming interface is a little + // more verbose than LogKV(). Here's an example: + // + // span.LogFields( + // log.String("event", "soft error"), + // log.String("type", "cache timeout"), + // log.Int("waited.millis", 1500)) + // + // Also see Span.FinishWithOptions() and FinishOptions.BulkLogData. + LogFields(fields ...log.Field) + + // LogKV is a concise, readable way to record key:value logging data about + // a Span, though unfortunately this also makes it less efficient and less + // type-safe than LogFields(). Here's an example: + // + // span.LogKV( + // "event", "soft error", + // "type", "cache timeout", + // "waited.millis", 1500) + // + // For LogKV (as opposed to LogFields()), the parameters must appear as + // key-value pairs, like + // + // span.LogKV(key1, val1, key2, val2, key3, val3, ...) + // + // The keys must all be strings. The values may be strings, numeric types, + // bools, Go error instances, or arbitrary structs. + // + // (Note to implementors: consider the log.InterleavedKVToFields() helper) + LogKV(alternatingKeyValues ...interface{}) + + // SetBaggageItem sets a key:value pair on this Span and its SpanContext + // that also propagates to descendants of this Span. + // + // SetBaggageItem() enables powerful functionality given a full-stack + // opentracing integration (e.g., arbitrary application data from a mobile + // app can make it, transparently, all the way into the depths of a storage + // system), and with it some powerful costs: use this feature with care. + // + // IMPORTANT NOTE #1: SetBaggageItem() will only propagate baggage items to + // *future* causal descendants of the associated Span. + // + // IMPORTANT NOTE #2: Use this thoughtfully and with care. Every key and + // value is copied into every local *and remote* child of the associated + // Span, and that can add up to a lot of network and cpu overhead. + // + // Returns a reference to this Span for chaining. + SetBaggageItem(restrictedKey, value string) Span + + // Gets the value for a baggage item given its key. Returns the empty string + // if the value isn't found in this Span. + BaggageItem(restrictedKey string) string + + // Provides access to the Tracer that created this Span. + Tracer() Tracer + + // Deprecated: use LogFields or LogKV + LogEvent(event string) + // Deprecated: use LogFields or LogKV + LogEventWithPayload(event string, payload interface{}) + // Deprecated: use LogFields or LogKV + Log(data LogData) +} + +// LogRecord is data associated with a single Span log. Every LogRecord +// instance must specify at least one Field. +type LogRecord struct { + Timestamp time.Time + Fields []log.Field +} + +// FinishOptions allows Span.FinishWithOptions callers to override the finish +// timestamp and provide log data via a bulk interface. +type FinishOptions struct { + // FinishTime overrides the Span's finish time, or implicitly becomes + // time.Now() if FinishTime.IsZero(). + // + // FinishTime must resolve to a timestamp that's >= the Span's StartTime + // (per StartSpanOptions). + FinishTime time.Time + + // LogRecords allows the caller to specify the contents of many LogFields() + // calls with a single slice. May be nil. + // + // None of the LogRecord.Timestamp values may be .IsZero() (i.e., they must + // be set explicitly). Also, they must be >= the Span's start timestamp and + // <= the FinishTime (or time.Now() if FinishTime.IsZero()). Otherwise the + // behavior of FinishWithOptions() is undefined. + // + // If specified, the caller hands off ownership of LogRecords at + // FinishWithOptions() invocation time. + // + // If specified, the (deprecated) BulkLogData must be nil or empty. + LogRecords []LogRecord + + // BulkLogData is DEPRECATED. + BulkLogData []LogData +} + +// LogData is DEPRECATED +type LogData struct { + Timestamp time.Time + Event string + Payload interface{} +} + +// ToLogRecord converts a deprecated LogData to a non-deprecated LogRecord +func (ld *LogData) ToLogRecord() LogRecord { + var literalTimestamp time.Time + if ld.Timestamp.IsZero() { + literalTimestamp = time.Now() + } else { + literalTimestamp = ld.Timestamp + } + rval := LogRecord{ + Timestamp: literalTimestamp, + } + if ld.Payload == nil { + rval.Fields = []log.Field{ + log.String("event", ld.Event), + } + } else { + rval.Fields = []log.Field{ + log.String("event", ld.Event), + log.Object("payload", ld.Payload), + } + } + return rval +} diff --git a/vendor/github.com/opentracing/opentracing-go/tracer.go b/vendor/github.com/opentracing/opentracing-go/tracer.go new file mode 100644 index 000000000..7bca1f736 --- /dev/null +++ b/vendor/github.com/opentracing/opentracing-go/tracer.go @@ -0,0 +1,305 @@ +package opentracing + +import "time" + +// Tracer is a simple, thin interface for Span creation and SpanContext +// propagation. +type Tracer interface { + + // Create, start, and return a new Span with the given `operationName` and + // incorporate the given StartSpanOption `opts`. (Note that `opts` borrows + // from the "functional options" pattern, per + // http://dave.cheney.net/2014/10/17/functional-options-for-friendly-apis) + // + // A Span with no SpanReference options (e.g., opentracing.ChildOf() or + // opentracing.FollowsFrom()) becomes the root of its own trace. + // + // Examples: + // + // var tracer opentracing.Tracer = ... + // + // // The root-span case: + // sp := tracer.StartSpan("GetFeed") + // + // // The vanilla child span case: + // sp := tracer.StartSpan( + // "GetFeed", + // opentracing.ChildOf(parentSpan.Context())) + // + // // All the bells and whistles: + // sp := tracer.StartSpan( + // "GetFeed", + // opentracing.ChildOf(parentSpan.Context()), + // opentracing.Tag{"user_agent", loggedReq.UserAgent}, + // opentracing.StartTime(loggedReq.Timestamp), + // ) + // + StartSpan(operationName string, opts ...StartSpanOption) Span + + // Inject() takes the `sm` SpanContext instance and injects it for + // propagation within `carrier`. The actual type of `carrier` depends on + // the value of `format`. + // + // OpenTracing defines a common set of `format` values (see BuiltinFormat), + // and each has an expected carrier type. + // + // Other packages may declare their own `format` values, much like the keys + // used by `context.Context` (see + // https://godoc.org/golang.org/x/net/context#WithValue). + // + // Example usage (sans error handling): + // + // carrier := opentracing.HTTPHeadersCarrier(httpReq.Header) + // err := tracer.Inject( + // span.Context(), + // opentracing.HTTPHeaders, + // carrier) + // + // NOTE: All opentracing.Tracer implementations MUST support all + // BuiltinFormats. + // + // Implementations may return opentracing.ErrUnsupportedFormat if `format` + // is not supported by (or not known by) the implementation. + // + // Implementations may return opentracing.ErrInvalidCarrier or any other + // implementation-specific error if the format is supported but injection + // fails anyway. + // + // See Tracer.Extract(). + Inject(sm SpanContext, format interface{}, carrier interface{}) error + + // Extract() returns a SpanContext instance given `format` and `carrier`. + // + // OpenTracing defines a common set of `format` values (see BuiltinFormat), + // and each has an expected carrier type. + // + // Other packages may declare their own `format` values, much like the keys + // used by `context.Context` (see + // https://godoc.org/golang.org/x/net/context#WithValue). + // + // Example usage (with StartSpan): + // + // + // carrier := opentracing.HTTPHeadersCarrier(httpReq.Header) + // clientContext, err := tracer.Extract(opentracing.HTTPHeaders, carrier) + // + // // ... assuming the ultimate goal here is to resume the trace with a + // // server-side Span: + // var serverSpan opentracing.Span + // if err == nil { + // span = tracer.StartSpan( + // rpcMethodName, ext.RPCServerOption(clientContext)) + // } else { + // span = tracer.StartSpan(rpcMethodName) + // } + // + // + // NOTE: All opentracing.Tracer implementations MUST support all + // BuiltinFormats. + // + // Return values: + // - A successful Extract returns a SpanContext instance and a nil error + // - If there was simply no SpanContext to extract in `carrier`, Extract() + // returns (nil, opentracing.ErrSpanContextNotFound) + // - If `format` is unsupported or unrecognized, Extract() returns (nil, + // opentracing.ErrUnsupportedFormat) + // - If there are more fundamental problems with the `carrier` object, + // Extract() may return opentracing.ErrInvalidCarrier, + // opentracing.ErrSpanContextCorrupted, or implementation-specific + // errors. + // + // See Tracer.Inject(). + Extract(format interface{}, carrier interface{}) (SpanContext, error) +} + +// StartSpanOptions allows Tracer.StartSpan() callers and implementors a +// mechanism to override the start timestamp, specify Span References, and make +// a single Tag or multiple Tags available at Span start time. +// +// StartSpan() callers should look at the StartSpanOption interface and +// implementations available in this package. +// +// Tracer implementations can convert a slice of `StartSpanOption` instances +// into a `StartSpanOptions` struct like so: +// +// func StartSpan(opName string, opts ...opentracing.StartSpanOption) { +// sso := opentracing.StartSpanOptions{} +// for _, o := range opts { +// o.Apply(&sso) +// } +// ... +// } +// +type StartSpanOptions struct { + // Zero or more causal references to other Spans (via their SpanContext). + // If empty, start a "root" Span (i.e., start a new trace). + References []SpanReference + + // StartTime overrides the Span's start time, or implicitly becomes + // time.Now() if StartTime.IsZero(). + StartTime time.Time + + // Tags may have zero or more entries; the restrictions on map values are + // identical to those for Span.SetTag(). May be nil. + // + // If specified, the caller hands off ownership of Tags at + // StartSpan() invocation time. + Tags map[string]interface{} +} + +// StartSpanOption instances (zero or more) may be passed to Tracer.StartSpan. +// +// StartSpanOption borrows from the "functional options" pattern, per +// http://dave.cheney.net/2014/10/17/functional-options-for-friendly-apis +type StartSpanOption interface { + Apply(*StartSpanOptions) +} + +// SpanReferenceType is an enum type describing different categories of +// relationships between two Spans. If Span-2 refers to Span-1, the +// SpanReferenceType describes Span-1 from Span-2's perspective. For example, +// ChildOfRef means that Span-1 created Span-2. +// +// NOTE: Span-1 and Span-2 do *not* necessarily depend on each other for +// completion; e.g., Span-2 may be part of a background job enqueued by Span-1, +// or Span-2 may be sitting in a distributed queue behind Span-1. +type SpanReferenceType int + +const ( + // ChildOfRef refers to a parent Span that caused *and* somehow depends + // upon the new child Span. Often (but not always), the parent Span cannot + // finish until the child Span does. + // + // An timing diagram for a ChildOfRef that's blocked on the new Span: + // + // [-Parent Span---------] + // [-Child Span----] + // + // See http://opentracing.io/spec/ + // + // See opentracing.ChildOf() + ChildOfRef SpanReferenceType = iota + + // FollowsFromRef refers to a parent Span that does not depend in any way + // on the result of the new child Span. For instance, one might use + // FollowsFromRefs to describe pipeline stages separated by queues, + // or a fire-and-forget cache insert at the tail end of a web request. + // + // A FollowsFromRef Span is part of the same logical trace as the new Span: + // i.e., the new Span is somehow caused by the work of its FollowsFromRef. + // + // All of the following could be valid timing diagrams for children that + // "FollowFrom" a parent. + // + // [-Parent Span-] [-Child Span-] + // + // + // [-Parent Span--] + // [-Child Span-] + // + // + // [-Parent Span-] + // [-Child Span-] + // + // See http://opentracing.io/spec/ + // + // See opentracing.FollowsFrom() + FollowsFromRef +) + +// SpanReference is a StartSpanOption that pairs a SpanReferenceType and a +// referenced SpanContext. See the SpanReferenceType documentation for +// supported relationships. If SpanReference is created with +// ReferencedContext==nil, it has no effect. Thus it allows for a more concise +// syntax for starting spans: +// +// sc, _ := tracer.Extract(someFormat, someCarrier) +// span := tracer.StartSpan("operation", opentracing.ChildOf(sc)) +// +// The `ChildOf(sc)` option above will not panic if sc == nil, it will just +// not add the parent span reference to the options. +type SpanReference struct { + Type SpanReferenceType + ReferencedContext SpanContext +} + +// Apply satisfies the StartSpanOption interface. +func (r SpanReference) Apply(o *StartSpanOptions) { + if r.ReferencedContext != nil { + o.References = append(o.References, r) + } +} + +// ChildOf returns a StartSpanOption pointing to a dependent parent span. +// If sc == nil, the option has no effect. +// +// See ChildOfRef, SpanReference +func ChildOf(sc SpanContext) SpanReference { + return SpanReference{ + Type: ChildOfRef, + ReferencedContext: sc, + } +} + +// FollowsFrom returns a StartSpanOption pointing to a parent Span that caused +// the child Span but does not directly depend on its result in any way. +// If sc == nil, the option has no effect. +// +// See FollowsFromRef, SpanReference +func FollowsFrom(sc SpanContext) SpanReference { + return SpanReference{ + Type: FollowsFromRef, + ReferencedContext: sc, + } +} + +// StartTime is a StartSpanOption that sets an explicit start timestamp for the +// new Span. +type StartTime time.Time + +// Apply satisfies the StartSpanOption interface. +func (t StartTime) Apply(o *StartSpanOptions) { + o.StartTime = time.Time(t) +} + +// Tags are a generic map from an arbitrary string key to an opaque value type. +// The underlying tracing system is responsible for interpreting and +// serializing the values. +type Tags map[string]interface{} + +// Apply satisfies the StartSpanOption interface. +func (t Tags) Apply(o *StartSpanOptions) { + if o.Tags == nil { + o.Tags = make(map[string]interface{}) + } + for k, v := range t { + o.Tags[k] = v + } +} + +// Tag may be passed as a StartSpanOption to add a tag to new spans, +// or its Set method may be used to apply the tag to an existing Span, +// for example: +// +// tracer.StartSpan("opName", Tag{"Key", value}) +// +// or +// +// Tag{"key", value}.Set(span) +type Tag struct { + Key string + Value interface{} +} + +// Apply satisfies the StartSpanOption interface. +func (t Tag) Apply(o *StartSpanOptions) { + if o.Tags == nil { + o.Tags = make(map[string]interface{}) + } + o.Tags[t.Key] = t.Value +} + +// Set applies the tag to an existing Span. +func (t Tag) Set(s Span) { + s.SetTag(t.Key, t.Value) +} diff --git a/vendor/github.com/uber/jaeger-client-go/LICENSE b/vendor/github.com/uber/jaeger-client-go/LICENSE new file mode 100644 index 000000000..261eeb9e9 --- /dev/null +++ b/vendor/github.com/uber/jaeger-client-go/LICENSE @@ -0,0 +1,201 @@ + 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. diff --git a/vendor/github.com/uber/jaeger-client-go/README.md b/vendor/github.com/uber/jaeger-client-go/README.md new file mode 100644 index 000000000..058ce15c9 --- /dev/null +++ b/vendor/github.com/uber/jaeger-client-go/README.md @@ -0,0 +1,237 @@ +[![GoDoc][doc-img]][doc] [![Build Status][ci-img]][ci] [![Coverage Status][cov-img]][cov] [![OpenTracing 1.0 Enabled][ot-img]][ot-url] + +# Jaeger Bindings for Go OpenTracing API + +Instrumentation library that implements an +[OpenTracing](http://opentracing.io) Tracer for Jaeger (http://jaegertracing.io). + +**IMPORTANT**: The library's import path is based on its original location under `github.com/uber`. Do not try to import it as `github.com/jaegertracing`, it will not compile. We might revisit this in the next major release. + * :white_check_mark: `import "github.com/uber/jaeger-client-go"` + * :x: `import "github.com/jaegertracing/jaeger-client-go"` + +## How to Contribute + +Please see [CONTRIBUTING.md](CONTRIBUTING.md). + +## Installation + +We recommended using a dependency manager like [glide](https://github.com/Masterminds/glide) +and [semantic versioning](http://semver.org/) when including this library into an application. +For example, Jaeger backend imports this library like this: + +```yaml +- package: github.com/uber/jaeger-client-go + version: ^2.7.0 +``` + +If you instead want to use the latest version in `master`, you can pull it via `go get`. +Note that during `go get` you may see build errors due to incompatible dependencies, which is why +we recommend using semantic versions for dependencioes. The error may be fixed by running +`make install` (it will install `glide` if you don't have it): + +```shell +go get -u github.com/uber/jaeger-client-go/ +cd $GOPATH/src/github.com/uber/jaeger-client-go/ +git submodule update --init --recursive +make install +``` + +## Initialization + +See tracer initialization examples in [godoc](https://godoc.org/github.com/uber/jaeger-client-go/config#pkg-examples) +and [config/example_test.go](./config/example_test.go). + +### Closing the tracer via `io.Closer` + +The constructor functions for Jaeger Tracer return the tracer itself and an `io.Closer` instance. +It is recommended to structure your `main()` so that it calls the `Close()` function on the closer +before exiting, e.g. + +```go +tracer, closer, err := cfg.New(...) +defer closer.Close() +``` + +This is especially useful for command-line tools that enable tracing, as well as +for the long-running apps that support graceful shutdown. For example, if your deployment +system sends SIGTERM instead of killing the process and you trap that signal to do a graceful +exit, then having `defer closer.Closer()` ensures that all buffered spans are flushed. + +### Metrics & Monitoring + +The tracer emits a number of different metrics, defined in +[metrics.go](metrics.go). The monitoring backend is expected to support +tag-based metric names, e.g. instead of `statsd`-style string names +like `counters.my-service.jaeger.spans.started.sampled`, the metrics +are defined by a short name and a collection of key/value tags, for +example: `name:jaeger.traces, state:started, sampled:y`. See [metrics.go](./metrics.go) +file for the full list and descriptions of emitted metrics. + +The monitoring backend is represented by the `metrics.Factory` interface from package +[`"github.com/uber/jaeger-lib/metrics"`](github.com/uber/jaeger-lib/metrics). An implementation +of that interface can be passed as an option to either the Configuration object or the Tracer +constructor, for example: + +```go +import ( + "github.com/uber/jaeger-client-go/config" + "github.com/uber/jaeger-lib/metrics/prometheus" +) + + metricsFactory := prometheus.New() + tracer, closer, err := new(config.Configuration).New( + "your-service-name", + config.Metrics(metricsFactory), + ) +``` + +By default, a no-op `metrics.NullFactory` is used. + +### Logging + +The tracer can be configured with an optional logger, which will be +used to log communication errors, or log spans if a logging reporter +option is specified in the configuration. The logging API is abstracted +by the [Logger](logger.go) interface. A logger instance implementing +this interface can be set on the `Config` object before calling the +`New` method. + +Besides the [zap](https://github.com/uber-go/zap) implementation +bundled with this package there is also a [go-kit](https://github.com/go-kit/kit) +one in the [jaeger-lib](https://github.com/uber/jaeger-lib) repository. + +## Instrumentation for Tracing + +Since this tracer is fully compliant with OpenTracing API 1.0, +all code instrumentation should only use the API itself, as described +in the [opentracing-go](https://github.com/opentracing/opentracing-go) documentation. + +## Features + +### Reporters + +A "reporter" is a component receives the finished spans and reports +them to somewhere. Under normal circumstances, the Tracer +should use the default `RemoteReporter`, which sends the spans out of +process via configurable "transport". For testing purposes, one can +use an `InMemoryReporter` that accumulates spans in a buffer and +allows to retrieve them for later verification. Also available are +`NullReporter`, a no-op reporter that does nothing, a `LoggingReporter` +which logs all finished spans using their `String()` method, and a +`CompositeReporter` that can be used to combine more than one reporter +into one, e.g. to attach a logging reporter to the main remote reporter. + +### Span Reporting Transports + +The remote reporter uses "transports" to actually send the spans out +of process. Currently the supported transports include: + * [Jaeger Thrift](https://github.com/jaegertracing/jaeger-idl/blob/master/thrift/agent.thrift) over UDP or HTTP, + * [Zipkin Thrift](https://github.com/jaegertracing/jaeger-idl/blob/master/thrift/zipkincore.thrift) over HTTP. + +### Sampling + +The tracer does not record all spans, but only those that have the +sampling bit set in the `flags`. When a new trace is started and a new +unique ID is generated, a sampling decision is made whether this trace +should be sampled. The sampling decision is propagated to all downstream +calls via the `flags` field of the trace context. The following samplers +are available: + 1. `RemotelyControlledSampler` uses one of the other simpler samplers + and periodically updates it by polling an external server. This + allows dynamic control of the sampling strategies. + 1. `ConstSampler` always makes the same sampling decision for all + trace IDs. it can be configured to either sample all traces, or + to sample none. + 1. `ProbabilisticSampler` uses a fixed sampling rate as a probability + for a given trace to be sampled. The actual decision is made by + comparing the trace ID with a random number multiplied by the + sampling rate. + 1. `RateLimitingSampler` can be used to allow only a certain fixed + number of traces to be sampled per second. + +### Baggage Injection + +The OpenTracing spec allows for [baggage][baggage], which are key value pairs that are added +to the span context and propagated throughout the trace. An external process can inject baggage +by setting the special HTTP Header `jaeger-baggage` on a request: + +```sh +curl -H "jaeger-baggage: key1=value1, key2=value2" http://myhost.com +``` + +Baggage can also be programatically set inside your service: + +```go +if span := opentracing.SpanFromContext(ctx); span != nil { + span.SetBaggageItem("key", "value") +} +``` + +Another service downstream of that can retrieve the baggage in a similar way: + +```go +if span := opentracing.SpanFromContext(ctx); span != nil { + val := span.BaggageItem("key") + println(val) +} +``` + +### Debug Traces (Forced Sampling) + +#### Programmatically + +The OpenTracing API defines a `sampling.priority` standard tag that +can be used to affect the sampling of a span and its children: + +```go +import ( + "github.com/opentracing/opentracing-go" + "github.com/opentracing/opentracing-go/ext" +) + +span := opentracing.SpanFromContext(ctx) +ext.SamplingPriority.Set(span, 1) +``` + +#### Via HTTP Headers + +Jaeger Tracer also understands a special HTTP Header `jaeger-debug-id`, +which can be set in the incoming request, e.g. + +```sh +curl -H "jaeger-debug-id: some-correlation-id" http://myhost.com +``` + +When Jaeger sees this header in the request that otherwise has no +tracing context, it ensures that the new trace started for this +request will be sampled in the "debug" mode (meaning it should survive +all downsampling that might happen in the collection pipeline), and the +root span will have a tag as if this statement was executed: + +```go +span.SetTag("jaeger-debug-id", "some-correlation-id") +``` + +This allows using Jaeger UI to find the trace by this tag. + +### Zipkin HTTP B3 compatible header propagation + +Jaeger Tracer supports Zipkin B3 Propagation HTTP headers, which are used +by a lot of Zipkin tracers. This means that you can use Jaeger in conjunction with e.g. [these OpenZipkin tracers](https://github.com/openzipkin). + +However it is not the default propagation format, see [here](zipkin/README.md#NewZipkinB3HTTPHeaderPropagator) how to set it up. + +## License + +[Apache 2.0 License](LICENSE). + + +[doc-img]: https://godoc.org/github.com/uber/jaeger-client-go?status.svg +[doc]: https://godoc.org/github.com/uber/jaeger-client-go +[ci-img]: https://travis-ci.org/jaegertracing/jaeger-client-go.svg?branch=master +[ci]: https://travis-ci.org/jaegertracing/jaeger-client-go +[cov-img]: https://codecov.io/gh/jaegertracing/jaeger-client-go/branch/master/graph/badge.svg +[cov]: https://codecov.io/gh/jaegertracing/jaeger-client-go +[ot-img]: https://img.shields.io/badge/OpenTracing--1.0-enabled-blue.svg +[ot-url]: http://opentracing.io +[baggage]: https://github.com/opentracing/specification/blob/master/specification.md#set-a-baggage-item diff --git a/vendor/github.com/uber/jaeger-client-go/baggage_setter.go b/vendor/github.com/uber/jaeger-client-go/baggage_setter.go new file mode 100644 index 000000000..1037ca0e8 --- /dev/null +++ b/vendor/github.com/uber/jaeger-client-go/baggage_setter.go @@ -0,0 +1,77 @@ +// Copyright (c) 2017 Uber Technologies, Inc. +// +// 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. + +package jaeger + +import ( + "github.com/opentracing/opentracing-go/log" + + "github.com/uber/jaeger-client-go/internal/baggage" +) + +// baggageSetter is an actor that can set a baggage value on a Span given certain +// restrictions (eg. maxValueLength). +type baggageSetter struct { + restrictionManager baggage.RestrictionManager + metrics *Metrics +} + +func newBaggageSetter(restrictionManager baggage.RestrictionManager, metrics *Metrics) *baggageSetter { + return &baggageSetter{ + restrictionManager: restrictionManager, + metrics: metrics, + } +} + +// (NB) span should hold the lock before making this call +func (s *baggageSetter) setBaggage(span *Span, key, value string) { + var truncated bool + var prevItem string + restriction := s.restrictionManager.GetRestriction(span.serviceName(), key) + if !restriction.KeyAllowed() { + s.logFields(span, key, value, prevItem, truncated, restriction.KeyAllowed()) + s.metrics.BaggageUpdateFailure.Inc(1) + return + } + if len(value) > restriction.MaxValueLength() { + truncated = true + value = value[:restriction.MaxValueLength()] + s.metrics.BaggageTruncate.Inc(1) + } + prevItem = span.context.baggage[key] + s.logFields(span, key, value, prevItem, truncated, restriction.KeyAllowed()) + span.context = span.context.WithBaggageItem(key, value) + s.metrics.BaggageUpdateSuccess.Inc(1) +} + +func (s *baggageSetter) logFields(span *Span, key, value, prevItem string, truncated, valid bool) { + if !span.context.IsSampled() { + return + } + fields := []log.Field{ + log.String("event", "baggage"), + log.String("key", key), + log.String("value", value), + } + if prevItem != "" { + fields = append(fields, log.String("override", "true")) + } + if truncated { + fields = append(fields, log.String("truncated", "true")) + } + if !valid { + fields = append(fields, log.String("invalid", "true")) + } + span.logFieldsNoLocking(fields...) +} diff --git a/vendor/github.com/uber/jaeger-client-go/constants.go b/vendor/github.com/uber/jaeger-client-go/constants.go new file mode 100644 index 000000000..e53ca5bf2 --- /dev/null +++ b/vendor/github.com/uber/jaeger-client-go/constants.go @@ -0,0 +1,76 @@ +// Copyright (c) 2017 Uber Technologies, Inc. +// +// 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. + +package jaeger + +const ( + // JaegerClientVersion is the version of the client library reported as Span tag. + JaegerClientVersion = "Go-2.11.2-dev" + + // JaegerClientVersionTagKey is the name of the tag used to report client version. + JaegerClientVersionTagKey = "jaeger.version" + + // JaegerDebugHeader is the name of HTTP header or a TextMap carrier key which, + // if found in the carrier, forces the trace to be sampled as "debug" trace. + // The value of the header is recorded as the tag on the root span, so that the + // trace can be found in the UI using this value as a correlation ID. + JaegerDebugHeader = "jaeger-debug-id" + + // JaegerBaggageHeader is the name of the HTTP header that is used to submit baggage. + // It differs from TraceBaggageHeaderPrefix in that it can be used only in cases where + // a root span does not exist. + JaegerBaggageHeader = "jaeger-baggage" + + // TracerHostnameTagKey used to report host name of the process. + TracerHostnameTagKey = "hostname" + + // TracerIPTagKey used to report ip of the process. + TracerIPTagKey = "ip" + + // SamplerTypeTagKey reports which sampler was used on the root span. + SamplerTypeTagKey = "sampler.type" + + // SamplerParamTagKey reports the parameter of the sampler, like sampling probability. + SamplerParamTagKey = "sampler.param" + + // TraceContextHeaderName is the http header name used to propagate tracing context. + // This must be in lower-case to avoid mismatches when decoding incoming headers. + TraceContextHeaderName = "uber-trace-id" + + // TracerStateHeaderName is deprecated. + // Deprecated: use TraceContextHeaderName + TracerStateHeaderName = TraceContextHeaderName + + // TraceBaggageHeaderPrefix is the prefix for http headers used to propagate baggage. + // This must be in lower-case to avoid mismatches when decoding incoming headers. + TraceBaggageHeaderPrefix = "uberctx-" + + // SamplerTypeConst is the type of sampler that always makes the same decision. + SamplerTypeConst = "const" + + // SamplerTypeRemote is the type of sampler that polls Jaeger agent for sampling strategy. + SamplerTypeRemote = "remote" + + // SamplerTypeProbabilistic is the type of sampler that samples traces + // with a certain fixed probability. + SamplerTypeProbabilistic = "probabilistic" + + // SamplerTypeRateLimiting is the type of sampler that samples + // only up to a fixed number of traces per second. + SamplerTypeRateLimiting = "ratelimiting" + + // SamplerTypeLowerBound is the type of sampler that samples + // at least a fixed number of traces per second. + SamplerTypeLowerBound = "lowerbound" +) diff --git a/vendor/github.com/uber/jaeger-client-go/context.go b/vendor/github.com/uber/jaeger-client-go/context.go new file mode 100644 index 000000000..8b06173d9 --- /dev/null +++ b/vendor/github.com/uber/jaeger-client-go/context.go @@ -0,0 +1,258 @@ +// Copyright (c) 2017 Uber Technologies, Inc. +// +// 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. + +package jaeger + +import ( + "errors" + "fmt" + "strconv" + "strings" +) + +const ( + flagSampled = byte(1) + flagDebug = byte(2) +) + +var ( + errEmptyTracerStateString = errors.New("Cannot convert empty string to tracer state") + errMalformedTracerStateString = errors.New("String does not match tracer state format") + + emptyContext = SpanContext{} +) + +// TraceID represents unique 128bit identifier of a trace +type TraceID struct { + High, Low uint64 +} + +// SpanID represents unique 64bit identifier of a span +type SpanID uint64 + +// SpanContext represents propagated span identity and state +type SpanContext struct { + // traceID represents globally unique ID of the trace. + // Usually generated as a random number. + traceID TraceID + + // spanID represents span ID that must be unique within its trace, + // but does not have to be globally unique. + spanID SpanID + + // parentID refers to the ID of the parent span. + // Should be 0 if the current span is a root span. + parentID SpanID + + // flags is a bitmap containing such bits as 'sampled' and 'debug'. + flags byte + + // Distributed Context baggage. The is a snapshot in time. + baggage map[string]string + + // debugID can be set to some correlation ID when the context is being + // extracted from a TextMap carrier. + // + // See JaegerDebugHeader in constants.go + debugID string +} + +// ForeachBaggageItem implements ForeachBaggageItem() of opentracing.SpanContext +func (c SpanContext) ForeachBaggageItem(handler func(k, v string) bool) { + for k, v := range c.baggage { + if !handler(k, v) { + break + } + } +} + +// IsSampled returns whether this trace was chosen for permanent storage +// by the sampling mechanism of the tracer. +func (c SpanContext) IsSampled() bool { + return (c.flags & flagSampled) == flagSampled +} + +// IsDebug indicates whether sampling was explicitly requested by the service. +func (c SpanContext) IsDebug() bool { + return (c.flags & flagDebug) == flagDebug +} + +// IsValid indicates whether this context actually represents a valid trace. +func (c SpanContext) IsValid() bool { + return c.traceID.IsValid() && c.spanID != 0 +} + +func (c SpanContext) String() string { + if c.traceID.High == 0 { + return fmt.Sprintf("%x:%x:%x:%x", c.traceID.Low, uint64(c.spanID), uint64(c.parentID), c.flags) + } + return fmt.Sprintf("%x%016x:%x:%x:%x", c.traceID.High, c.traceID.Low, uint64(c.spanID), uint64(c.parentID), c.flags) +} + +// ContextFromString reconstructs the Context encoded in a string +func ContextFromString(value string) (SpanContext, error) { + var context SpanContext + if value == "" { + return emptyContext, errEmptyTracerStateString + } + parts := strings.Split(value, ":") + if len(parts) != 4 { + return emptyContext, errMalformedTracerStateString + } + var err error + if context.traceID, err = TraceIDFromString(parts[0]); err != nil { + return emptyContext, err + } + if context.spanID, err = SpanIDFromString(parts[1]); err != nil { + return emptyContext, err + } + if context.parentID, err = SpanIDFromString(parts[2]); err != nil { + return emptyContext, err + } + flags, err := strconv.ParseUint(parts[3], 10, 8) + if err != nil { + return emptyContext, err + } + context.flags = byte(flags) + return context, nil +} + +// TraceID returns the trace ID of this span context +func (c SpanContext) TraceID() TraceID { + return c.traceID +} + +// SpanID returns the span ID of this span context +func (c SpanContext) SpanID() SpanID { + return c.spanID +} + +// ParentID returns the parent span ID of this span context +func (c SpanContext) ParentID() SpanID { + return c.parentID +} + +// NewSpanContext creates a new instance of SpanContext +func NewSpanContext(traceID TraceID, spanID, parentID SpanID, sampled bool, baggage map[string]string) SpanContext { + flags := byte(0) + if sampled { + flags = flagSampled + } + return SpanContext{ + traceID: traceID, + spanID: spanID, + parentID: parentID, + flags: flags, + baggage: baggage} +} + +// CopyFrom copies data from ctx into this context, including span identity and baggage. +// TODO This is only used by interop.go. Remove once TChannel Go supports OpenTracing. +func (c *SpanContext) CopyFrom(ctx *SpanContext) { + c.traceID = ctx.traceID + c.spanID = ctx.spanID + c.parentID = ctx.parentID + c.flags = ctx.flags + if l := len(ctx.baggage); l > 0 { + c.baggage = make(map[string]string, l) + for k, v := range ctx.baggage { + c.baggage[k] = v + } + } else { + c.baggage = nil + } +} + +// WithBaggageItem creates a new context with an extra baggage item. +func (c SpanContext) WithBaggageItem(key, value string) SpanContext { + var newBaggage map[string]string + if c.baggage == nil { + newBaggage = map[string]string{key: value} + } else { + newBaggage = make(map[string]string, len(c.baggage)+1) + for k, v := range c.baggage { + newBaggage[k] = v + } + newBaggage[key] = value + } + // Use positional parameters so the compiler will help catch new fields. + return SpanContext{c.traceID, c.spanID, c.parentID, c.flags, newBaggage, ""} +} + +// isDebugIDContainerOnly returns true when the instance of the context is only +// used to return the debug/correlation ID from extract() method. This happens +// in the situation when "jaeger-debug-id" header is passed in the carrier to +// the extract() method, but the request otherwise has no span context in it. +// Previously this would've returned opentracing.ErrSpanContextNotFound from the +// extract method, but now it returns a dummy context with only debugID filled in. +// +// See JaegerDebugHeader in constants.go +// See textMapPropagator#Extract +func (c *SpanContext) isDebugIDContainerOnly() bool { + return !c.traceID.IsValid() && c.debugID != "" +} + +// ------- TraceID ------- + +func (t TraceID) String() string { + if t.High == 0 { + return fmt.Sprintf("%x", t.Low) + } + return fmt.Sprintf("%x%016x", t.High, t.Low) +} + +// TraceIDFromString creates a TraceID from a hexadecimal string +func TraceIDFromString(s string) (TraceID, error) { + var hi, lo uint64 + var err error + if len(s) > 32 { + return TraceID{}, fmt.Errorf("TraceID cannot be longer than 32 hex characters: %s", s) + } else if len(s) > 16 { + hiLen := len(s) - 16 + if hi, err = strconv.ParseUint(s[0:hiLen], 16, 64); err != nil { + return TraceID{}, err + } + if lo, err = strconv.ParseUint(s[hiLen:], 16, 64); err != nil { + return TraceID{}, err + } + } else { + if lo, err = strconv.ParseUint(s, 16, 64); err != nil { + return TraceID{}, err + } + } + return TraceID{High: hi, Low: lo}, nil +} + +// IsValid checks if the trace ID is valid, i.e. not zero. +func (t TraceID) IsValid() bool { + return t.High != 0 || t.Low != 0 +} + +// ------- SpanID ------- + +func (s SpanID) String() string { + return fmt.Sprintf("%x", uint64(s)) +} + +// SpanIDFromString creates a SpanID from a hexadecimal string +func SpanIDFromString(s string) (SpanID, error) { + if len(s) > 16 { + return SpanID(0), fmt.Errorf("SpanID cannot be longer than 16 hex characters: %s", s) + } + id, err := strconv.ParseUint(s, 16, 64) + if err != nil { + return SpanID(0), err + } + return SpanID(id), nil +} diff --git a/vendor/github.com/uber/jaeger-client-go/contrib_observer.go b/vendor/github.com/uber/jaeger-client-go/contrib_observer.go new file mode 100644 index 000000000..4ce1881f3 --- /dev/null +++ b/vendor/github.com/uber/jaeger-client-go/contrib_observer.go @@ -0,0 +1,56 @@ +// Copyright (c) 2017 Uber Technologies, Inc. +// +// 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. + +package jaeger + +import ( + opentracing "github.com/opentracing/opentracing-go" +) + +// ContribObserver can be registered with the Tracer to receive notifications +// about new Spans. Modelled after github.com/opentracing-contrib/go-observer. +type ContribObserver interface { + // Create and return a span observer. Called when a span starts. + // If the Observer is not interested in the given span, it must return (nil, false). + // E.g : + // func StartSpan(opName string, opts ...opentracing.StartSpanOption) { + // var sp opentracing.Span + // sso := opentracing.StartSpanOptions{} + // if spanObserver, ok := Observer.OnStartSpan(span, opName, sso); ok { + // // we have a valid SpanObserver + // } + // ... + // } + OnStartSpan(sp opentracing.Span, operationName string, options opentracing.StartSpanOptions) (ContribSpanObserver, bool) +} + +// ContribSpanObserver is created by the Observer and receives notifications +// about other Span events. This interface is meant to match +// github.com/opentracing-contrib/go-observer, via duck typing, without +// directly importing the go-observer package. +type ContribSpanObserver interface { + OnSetOperationName(operationName string) + OnSetTag(key string, value interface{}) + OnFinish(options opentracing.FinishOptions) +} + +// wrapper observer for the old observers (see observer.go) +type oldObserver struct { + obs Observer +} + +func (o *oldObserver) OnStartSpan(sp opentracing.Span, operationName string, options opentracing.StartSpanOptions) (ContribSpanObserver, bool) { + spanObserver := o.obs.OnStartSpan(operationName, options) + return spanObserver, spanObserver != nil +} diff --git a/vendor/github.com/uber/jaeger-client-go/doc.go b/vendor/github.com/uber/jaeger-client-go/doc.go new file mode 100644 index 000000000..4f5549033 --- /dev/null +++ b/vendor/github.com/uber/jaeger-client-go/doc.go @@ -0,0 +1,24 @@ +// Copyright (c) 2017 Uber Technologies, Inc. +// +// 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. + +/* +Package jaeger implements an OpenTracing (http://opentracing.io) Tracer. +It is currently using Zipkin-compatible data model and can be directly +itegrated with Zipkin backend (http://zipkin.io). + +For integration instructions please refer to the README: + +https://github.com/uber/jaeger-client-go/blob/master/README.md +*/ +package jaeger diff --git a/vendor/github.com/uber/jaeger-client-go/header.go b/vendor/github.com/uber/jaeger-client-go/header.go new file mode 100644 index 000000000..19c2c055b --- /dev/null +++ b/vendor/github.com/uber/jaeger-client-go/header.go @@ -0,0 +1,64 @@ +// Copyright (c) 2017 Uber Technologies, Inc. +// +// 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. + +package jaeger + +// HeadersConfig contains the values for the header keys that Jaeger will use. +// These values may be either custom or default depending on whether custom +// values were provided via a configuration. +type HeadersConfig struct { + // JaegerDebugHeader is the name of HTTP header or a TextMap carrier key which, + // if found in the carrier, forces the trace to be sampled as "debug" trace. + // The value of the header is recorded as the tag on the root span, so that the + // trace can be found in the UI using this value as a correlation ID. + JaegerDebugHeader string `yaml:"jaegerDebugHeader"` + + // JaegerBaggageHeader is the name of the HTTP header that is used to submit baggage. + // It differs from TraceBaggageHeaderPrefix in that it can be used only in cases where + // a root span does not exist. + JaegerBaggageHeader string `yaml:"jaegerBaggageHeader"` + + // TraceContextHeaderName is the http header name used to propagate tracing context. + // This must be in lower-case to avoid mismatches when decoding incoming headers. + TraceContextHeaderName string `yaml:"TraceContextHeaderName"` + + // TraceBaggageHeaderPrefix is the prefix for http headers used to propagate baggage. + // This must be in lower-case to avoid mismatches when decoding incoming headers. + TraceBaggageHeaderPrefix string `yaml:"traceBaggageHeaderPrefix"` +} + +func (c *HeadersConfig) applyDefaults() *HeadersConfig { + if c.JaegerBaggageHeader == "" { + c.JaegerBaggageHeader = JaegerBaggageHeader + } + if c.JaegerDebugHeader == "" { + c.JaegerDebugHeader = JaegerDebugHeader + } + if c.TraceBaggageHeaderPrefix == "" { + c.TraceBaggageHeaderPrefix = TraceBaggageHeaderPrefix + } + if c.TraceContextHeaderName == "" { + c.TraceContextHeaderName = TraceContextHeaderName + } + return c +} + +func getDefaultHeadersConfig() *HeadersConfig { + return &HeadersConfig{ + JaegerDebugHeader: JaegerDebugHeader, + JaegerBaggageHeader: JaegerBaggageHeader, + TraceContextHeaderName: TraceContextHeaderName, + TraceBaggageHeaderPrefix: TraceBaggageHeaderPrefix, + } +} diff --git a/vendor/github.com/uber/jaeger-client-go/internal/baggage/restriction_manager.go b/vendor/github.com/uber/jaeger-client-go/internal/baggage/restriction_manager.go new file mode 100644 index 000000000..c16a5c566 --- /dev/null +++ b/vendor/github.com/uber/jaeger-client-go/internal/baggage/restriction_manager.go @@ -0,0 +1,71 @@ +// Copyright (c) 2017 Uber Technologies, Inc. +// +// 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. + +package baggage + +const ( + defaultMaxValueLength = 2048 +) + +// Restriction determines whether a baggage key is allowed and contains any restrictions on the baggage value. +type Restriction struct { + keyAllowed bool + maxValueLength int +} + +// NewRestriction returns a new Restriction. +func NewRestriction(keyAllowed bool, maxValueLength int) *Restriction { + return &Restriction{ + keyAllowed: keyAllowed, + maxValueLength: maxValueLength, + } +} + +// KeyAllowed returns whether the baggage key for this restriction is allowed. +func (r *Restriction) KeyAllowed() bool { + return r.keyAllowed +} + +// MaxValueLength returns the max length for the baggage value. +func (r *Restriction) MaxValueLength() int { + return r.maxValueLength +} + +// RestrictionManager keeps track of valid baggage keys and their restrictions. The manager +// will return a Restriction for a specific baggage key which will determine whether the baggage +// key is allowed for the current service and any other applicable restrictions on the baggage +// value. +type RestrictionManager interface { + GetRestriction(service, key string) *Restriction +} + +// DefaultRestrictionManager allows any baggage key. +type DefaultRestrictionManager struct { + defaultRestriction *Restriction +} + +// NewDefaultRestrictionManager returns a DefaultRestrictionManager. +func NewDefaultRestrictionManager(maxValueLength int) *DefaultRestrictionManager { + if maxValueLength == 0 { + maxValueLength = defaultMaxValueLength + } + return &DefaultRestrictionManager{ + defaultRestriction: &Restriction{keyAllowed: true, maxValueLength: maxValueLength}, + } +} + +// GetRestriction implements RestrictionManager#GetRestriction. +func (m *DefaultRestrictionManager) GetRestriction(service, key string) *Restriction { + return m.defaultRestriction +} diff --git a/vendor/github.com/uber/jaeger-client-go/internal/spanlog/json.go b/vendor/github.com/uber/jaeger-client-go/internal/spanlog/json.go new file mode 100644 index 000000000..0e10b8a5a --- /dev/null +++ b/vendor/github.com/uber/jaeger-client-go/internal/spanlog/json.go @@ -0,0 +1,81 @@ +// Copyright (c) 2017 Uber Technologies, Inc. +// +// 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. + +package spanlog + +import ( + "encoding/json" + "fmt" + + "github.com/opentracing/opentracing-go/log" +) + +type fieldsAsMap map[string]string + +// MaterializeWithJSON converts log Fields into JSON string +// TODO refactor into pluggable materializer +func MaterializeWithJSON(logFields []log.Field) ([]byte, error) { + fields := fieldsAsMap(make(map[string]string, len(logFields))) + for _, field := range logFields { + field.Marshal(fields) + } + if event, ok := fields["event"]; ok && len(fields) == 1 { + return []byte(event), nil + } + return json.Marshal(fields) +} + +func (ml fieldsAsMap) EmitString(key, value string) { + ml[key] = value +} + +func (ml fieldsAsMap) EmitBool(key string, value bool) { + ml[key] = fmt.Sprintf("%t", value) +} + +func (ml fieldsAsMap) EmitInt(key string, value int) { + ml[key] = fmt.Sprintf("%d", value) +} + +func (ml fieldsAsMap) EmitInt32(key string, value int32) { + ml[key] = fmt.Sprintf("%d", value) +} + +func (ml fieldsAsMap) EmitInt64(key string, value int64) { + ml[key] = fmt.Sprintf("%d", value) +} + +func (ml fieldsAsMap) EmitUint32(key string, value uint32) { + ml[key] = fmt.Sprintf("%d", value) +} + +func (ml fieldsAsMap) EmitUint64(key string, value uint64) { + ml[key] = fmt.Sprintf("%d", value) +} + +func (ml fieldsAsMap) EmitFloat32(key string, value float32) { + ml[key] = fmt.Sprintf("%f", value) +} + +func (ml fieldsAsMap) EmitFloat64(key string, value float64) { + ml[key] = fmt.Sprintf("%f", value) +} + +func (ml fieldsAsMap) EmitObject(key string, value interface{}) { + ml[key] = fmt.Sprintf("%+v", value) +} + +func (ml fieldsAsMap) EmitLazyLogger(value log.LazyLogger) { + value(ml) +} diff --git a/vendor/github.com/uber/jaeger-client-go/interop.go b/vendor/github.com/uber/jaeger-client-go/interop.go new file mode 100644 index 000000000..8402d087c --- /dev/null +++ b/vendor/github.com/uber/jaeger-client-go/interop.go @@ -0,0 +1,55 @@ +// Copyright (c) 2017 Uber Technologies, Inc. +// +// 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. + +package jaeger + +import ( + "github.com/opentracing/opentracing-go" +) + +// TODO this file should not be needed after TChannel PR. + +type formatKey int + +// SpanContextFormat is a constant used as OpenTracing Format. +// Requires *SpanContext as carrier. +// This format is intended for interop with TChannel or other Zipkin-like tracers. +const SpanContextFormat formatKey = iota + +type jaegerTraceContextPropagator struct { + tracer *Tracer +} + +func (p *jaegerTraceContextPropagator) Inject( + ctx SpanContext, + abstractCarrier interface{}, +) error { + carrier, ok := abstractCarrier.(*SpanContext) + if !ok { + return opentracing.ErrInvalidCarrier + } + + carrier.CopyFrom(&ctx) + return nil +} + +func (p *jaegerTraceContextPropagator) Extract(abstractCarrier interface{}) (SpanContext, error) { + carrier, ok := abstractCarrier.(*SpanContext) + if !ok { + return emptyContext, opentracing.ErrInvalidCarrier + } + ctx := new(SpanContext) + ctx.CopyFrom(carrier) + return *ctx, nil +} diff --git a/vendor/github.com/uber/jaeger-client-go/jaeger_tag.go b/vendor/github.com/uber/jaeger-client-go/jaeger_tag.go new file mode 100644 index 000000000..868b2a5b5 --- /dev/null +++ b/vendor/github.com/uber/jaeger-client-go/jaeger_tag.go @@ -0,0 +1,84 @@ +// Copyright (c) 2017 Uber Technologies, Inc. +// +// 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. + +package jaeger + +import ( + "fmt" + + "github.com/opentracing/opentracing-go/log" + + j "github.com/uber/jaeger-client-go/thrift-gen/jaeger" +) + +type tags []*j.Tag + +// ConvertLogsToJaegerTags converts log Fields into jaeger tags. +func ConvertLogsToJaegerTags(logFields []log.Field) []*j.Tag { + fields := tags(make([]*j.Tag, 0, len(logFields))) + for _, field := range logFields { + field.Marshal(&fields) + } + return fields +} + +func (t *tags) EmitString(key, value string) { + *t = append(*t, &j.Tag{Key: key, VType: j.TagType_STRING, VStr: &value}) +} + +func (t *tags) EmitBool(key string, value bool) { + *t = append(*t, &j.Tag{Key: key, VType: j.TagType_BOOL, VBool: &value}) +} + +func (t *tags) EmitInt(key string, value int) { + vLong := int64(value) + *t = append(*t, &j.Tag{Key: key, VType: j.TagType_LONG, VLong: &vLong}) +} + +func (t *tags) EmitInt32(key string, value int32) { + vLong := int64(value) + *t = append(*t, &j.Tag{Key: key, VType: j.TagType_LONG, VLong: &vLong}) +} + +func (t *tags) EmitInt64(key string, value int64) { + *t = append(*t, &j.Tag{Key: key, VType: j.TagType_LONG, VLong: &value}) +} + +func (t *tags) EmitUint32(key string, value uint32) { + vLong := int64(value) + *t = append(*t, &j.Tag{Key: key, VType: j.TagType_LONG, VLong: &vLong}) +} + +func (t *tags) EmitUint64(key string, value uint64) { + vLong := int64(value) + *t = append(*t, &j.Tag{Key: key, VType: j.TagType_LONG, VLong: &vLong}) +} + +func (t *tags) EmitFloat32(key string, value float32) { + vDouble := float64(value) + *t = append(*t, &j.Tag{Key: key, VType: j.TagType_DOUBLE, VDouble: &vDouble}) +} + +func (t *tags) EmitFloat64(key string, value float64) { + *t = append(*t, &j.Tag{Key: key, VType: j.TagType_DOUBLE, VDouble: &value}) +} + +func (t *tags) EmitObject(key string, value interface{}) { + vStr := fmt.Sprintf("%+v", value) + *t = append(*t, &j.Tag{Key: key, VType: j.TagType_STRING, VStr: &vStr}) +} + +func (t *tags) EmitLazyLogger(value log.LazyLogger) { + value(t) +} diff --git a/vendor/github.com/uber/jaeger-client-go/jaeger_thrift_span.go b/vendor/github.com/uber/jaeger-client-go/jaeger_thrift_span.go new file mode 100644 index 000000000..338a34582 --- /dev/null +++ b/vendor/github.com/uber/jaeger-client-go/jaeger_thrift_span.go @@ -0,0 +1,172 @@ +// Copyright (c) 2017 Uber Technologies, Inc. +// +// 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. + +package jaeger + +import ( + "time" + + "github.com/opentracing/opentracing-go" + + j "github.com/uber/jaeger-client-go/thrift-gen/jaeger" + "github.com/uber/jaeger-client-go/utils" +) + +// BuildJaegerThrift builds jaeger span based on internal span. +func BuildJaegerThrift(span *Span) *j.Span { + startTime := utils.TimeToMicrosecondsSinceEpochInt64(span.startTime) + duration := span.duration.Nanoseconds() / int64(time.Microsecond) + jaegerSpan := &j.Span{ + TraceIdLow: int64(span.context.traceID.Low), + TraceIdHigh: int64(span.context.traceID.High), + SpanId: int64(span.context.spanID), + ParentSpanId: int64(span.context.parentID), + OperationName: span.operationName, + Flags: int32(span.context.flags), + StartTime: startTime, + Duration: duration, + Tags: buildTags(span.tags), + Logs: buildLogs(span.logs), + References: buildReferences(span.references), + } + return jaegerSpan +} + +// BuildJaegerProcessThrift creates a thrift Process type. +func BuildJaegerProcessThrift(span *Span) *j.Process { + return buildJaegerProcessThrift(span.tracer) +} + +func buildJaegerProcessThrift(tracer *Tracer) *j.Process { + process := &j.Process{ + ServiceName: tracer.serviceName, + Tags: buildTags(tracer.tags), + } + return process +} + +func buildTags(tags []Tag) []*j.Tag { + jTags := make([]*j.Tag, 0, len(tags)) + for _, tag := range tags { + jTag := buildTag(&tag) + jTags = append(jTags, jTag) + } + return jTags +} + +func buildLogs(logs []opentracing.LogRecord) []*j.Log { + jLogs := make([]*j.Log, 0, len(logs)) + for _, log := range logs { + jLog := &j.Log{ + Timestamp: utils.TimeToMicrosecondsSinceEpochInt64(log.Timestamp), + Fields: ConvertLogsToJaegerTags(log.Fields), + } + jLogs = append(jLogs, jLog) + } + return jLogs +} + +func buildTag(tag *Tag) *j.Tag { + jTag := &j.Tag{Key: tag.key} + switch value := tag.value.(type) { + case string: + vStr := truncateString(value) + jTag.VStr = &vStr + jTag.VType = j.TagType_STRING + case []byte: + if len(value) > maxAnnotationLength { + value = value[:maxAnnotationLength] + } + jTag.VBinary = value + jTag.VType = j.TagType_BINARY + case int: + vLong := int64(value) + jTag.VLong = &vLong + jTag.VType = j.TagType_LONG + case uint: + vLong := int64(value) + jTag.VLong = &vLong + jTag.VType = j.TagType_LONG + case int8: + vLong := int64(value) + jTag.VLong = &vLong + jTag.VType = j.TagType_LONG + case uint8: + vLong := int64(value) + jTag.VLong = &vLong + jTag.VType = j.TagType_LONG + case int16: + vLong := int64(value) + jTag.VLong = &vLong + jTag.VType = j.TagType_LONG + case uint16: + vLong := int64(value) + jTag.VLong = &vLong + jTag.VType = j.TagType_LONG + case int32: + vLong := int64(value) + jTag.VLong = &vLong + jTag.VType = j.TagType_LONG + case uint32: + vLong := int64(value) + jTag.VLong = &vLong + jTag.VType = j.TagType_LONG + case int64: + vLong := int64(value) + jTag.VLong = &vLong + jTag.VType = j.TagType_LONG + case uint64: + vLong := int64(value) + jTag.VLong = &vLong + jTag.VType = j.TagType_LONG + case float32: + vDouble := float64(value) + jTag.VDouble = &vDouble + jTag.VType = j.TagType_DOUBLE + case float64: + vDouble := float64(value) + jTag.VDouble = &vDouble + jTag.VType = j.TagType_DOUBLE + case bool: + vBool := value + jTag.VBool = &vBool + jTag.VType = j.TagType_BOOL + default: + vStr := truncateString(stringify(value)) + jTag.VStr = &vStr + jTag.VType = j.TagType_STRING + } + return jTag +} + +func buildReferences(references []Reference) []*j.SpanRef { + retMe := make([]*j.SpanRef, 0, len(references)) + for _, ref := range references { + if ref.Type == opentracing.ChildOfRef { + retMe = append(retMe, spanRef(ref.Context, j.SpanRefType_CHILD_OF)) + } else if ref.Type == opentracing.FollowsFromRef { + retMe = append(retMe, spanRef(ref.Context, j.SpanRefType_FOLLOWS_FROM)) + } + } + return retMe +} + +func spanRef(ctx SpanContext, refType j.SpanRefType) *j.SpanRef { + return &j.SpanRef{ + RefType: refType, + TraceIdLow: int64(ctx.traceID.Low), + TraceIdHigh: int64(ctx.traceID.High), + SpanId: int64(ctx.spanID), + } +} diff --git a/vendor/github.com/uber/jaeger-client-go/log/logger.go b/vendor/github.com/uber/jaeger-client-go/log/logger.go new file mode 100644 index 000000000..b002cda55 --- /dev/null +++ b/vendor/github.com/uber/jaeger-client-go/log/logger.go @@ -0,0 +1,83 @@ +// Copyright (c) 2017 Uber Technologies, Inc. +// +// 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. + +package log + +import ( + "bytes" + "fmt" + "log" + "sync" +) + +// Logger provides an abstract interface for logging from Reporters. +// Applications can provide their own implementation of this interface to adapt +// reporters logging to whatever logging library they prefer (stdlib log, +// logrus, go-logging, etc). +type Logger interface { + // Error logs a message at error priority + Error(msg string) + + // Infof logs a message at info priority + Infof(msg string, args ...interface{}) +} + +// StdLogger is implementation of the Logger interface that delegates to default `log` package +var StdLogger = &stdLogger{} + +type stdLogger struct{} + +func (l *stdLogger) Error(msg string) { + log.Printf("ERROR: %s", msg) +} + +// Infof logs a message at info priority +func (l *stdLogger) Infof(msg string, args ...interface{}) { + log.Printf(msg, args...) +} + +// NullLogger is implementation of the Logger interface that delegates to default `log` package +var NullLogger = &nullLogger{} + +type nullLogger struct{} + +func (l *nullLogger) Error(msg string) {} +func (l *nullLogger) Infof(msg string, args ...interface{}) {} + +// BytesBufferLogger implements Logger backed by a bytes.Buffer. +type BytesBufferLogger struct { + mux sync.Mutex + buf bytes.Buffer +} + +// Error implements Logger. +func (l *BytesBufferLogger) Error(msg string) { + l.mux.Lock() + l.buf.WriteString(fmt.Sprintf("ERROR: %s\n", msg)) + l.mux.Unlock() +} + +// Infof implements Logger. +func (l *BytesBufferLogger) Infof(msg string, args ...interface{}) { + l.mux.Lock() + l.buf.WriteString("INFO: " + fmt.Sprintf(msg, args...) + "\n") + l.mux.Unlock() +} + +// String returns string representation of the underlying buffer. +func (l *BytesBufferLogger) String() string { + l.mux.Lock() + defer l.mux.Unlock() + return l.buf.String() +} diff --git a/vendor/github.com/uber/jaeger-client-go/logger.go b/vendor/github.com/uber/jaeger-client-go/logger.go new file mode 100644 index 000000000..d4f0b5019 --- /dev/null +++ b/vendor/github.com/uber/jaeger-client-go/logger.go @@ -0,0 +1,53 @@ +// Copyright (c) 2017 Uber Technologies, Inc. +// +// 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. + +package jaeger + +import "log" + +// NB This will be deprecated in 3.0.0, please use jaeger-client-go/log/logger instead. + +// Logger provides an abstract interface for logging from Reporters. +// Applications can provide their own implementation of this interface to adapt +// reporters logging to whatever logging library they prefer (stdlib log, +// logrus, go-logging, etc). +type Logger interface { + // Error logs a message at error priority + Error(msg string) + + // Infof logs a message at info priority + Infof(msg string, args ...interface{}) +} + +// StdLogger is implementation of the Logger interface that delegates to default `log` package +var StdLogger = &stdLogger{} + +type stdLogger struct{} + +func (l *stdLogger) Error(msg string) { + log.Printf("ERROR: %s", msg) +} + +// Infof logs a message at info priority +func (l *stdLogger) Infof(msg string, args ...interface{}) { + log.Printf(msg, args...) +} + +// NullLogger is implementation of the Logger interface that delegates to default `log` package +var NullLogger = &nullLogger{} + +type nullLogger struct{} + +func (l *nullLogger) Error(msg string) {} +func (l *nullLogger) Infof(msg string, args ...interface{}) {} diff --git a/vendor/github.com/uber/jaeger-client-go/metrics.go b/vendor/github.com/uber/jaeger-client-go/metrics.go new file mode 100644 index 000000000..8c0e63213 --- /dev/null +++ b/vendor/github.com/uber/jaeger-client-go/metrics.go @@ -0,0 +1,98 @@ +// Copyright (c) 2017 Uber Technologies, Inc. +// +// 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. + +package jaeger + +import ( + "github.com/uber/jaeger-lib/metrics" +) + +// Metrics is a container of all stats emitted by Jaeger tracer. +type Metrics struct { + // Number of traces started by this tracer as sampled + TracesStartedSampled metrics.Counter `metric:"traces" tags:"state=started,sampled=y"` + + // Number of traces started by this tracer as not sampled + TracesStartedNotSampled metrics.Counter `metric:"traces" tags:"state=started,sampled=n"` + + // Number of externally started sampled traces this tracer joined + TracesJoinedSampled metrics.Counter `metric:"traces" tags:"state=joined,sampled=y"` + + // Number of externally started not-sampled traces this tracer joined + TracesJoinedNotSampled metrics.Counter `metric:"traces" tags:"state=joined,sampled=n"` + + // Number of sampled spans started by this tracer + SpansStartedSampled metrics.Counter `metric:"started_spans" tags:"sampled=y"` + + // Number of unsampled spans started by this tracer + SpansStartedNotSampled metrics.Counter `metric:"started_spans" tags:"sampled=n"` + + // Number of spans finished by this tracer + SpansFinished metrics.Counter `metric:"finished_spans"` + + // Number of errors decoding tracing context + DecodingErrors metrics.Counter `metric:"span_context_decoding_errors"` + + // Number of spans successfully reported + ReporterSuccess metrics.Counter `metric:"reporter_spans" tags:"result=ok"` + + // Number of spans not reported due to a Sender failure + ReporterFailure metrics.Counter `metric:"reporter_spans" tags:"result=err"` + + // Number of spans dropped due to internal queue overflow + ReporterDropped metrics.Counter `metric:"reporter_spans" tags:"result=dropped"` + + // Current number of spans in the reporter queue + ReporterQueueLength metrics.Gauge `metric:"reporter_queue_length"` + + // Number of times the Sampler succeeded to retrieve sampling strategy + SamplerRetrieved metrics.Counter `metric:"sampler_queries" tags:"result=ok"` + + // Number of times the Sampler failed to retrieve sampling strategy + SamplerQueryFailure metrics.Counter `metric:"sampler_queries" tags:"result=err"` + + // Number of times the Sampler succeeded to retrieve and update sampling strategy + SamplerUpdated metrics.Counter `metric:"sampler_updates" tags:"result=ok"` + + // Number of times the Sampler failed to update sampling strategy + SamplerUpdateFailure metrics.Counter `metric:"sampler_updates" tags:"result=err"` + + // Number of times baggage was successfully written or updated on spans. + BaggageUpdateSuccess metrics.Counter `metric:"baggage_updates" tags:"result=ok"` + + // Number of times baggage failed to write or update on spans. + BaggageUpdateFailure metrics.Counter `metric:"baggage_updates" tags:"result=err"` + + // Number of times baggage was truncated as per baggage restrictions. + BaggageTruncate metrics.Counter `metric:"baggage_truncations"` + + // Number of times baggage restrictions were successfully updated. + BaggageRestrictionsUpdateSuccess metrics.Counter `metric:"baggage_restrictions_updates" tags:"result=ok"` + + // Number of times baggage restrictions failed to update. + BaggageRestrictionsUpdateFailure metrics.Counter `metric:"baggage_restrictions_updates" tags:"result=err"` +} + +// NewMetrics creates a new Metrics struct and initializes it. +func NewMetrics(factory metrics.Factory, globalTags map[string]string) *Metrics { + m := &Metrics{} + // TODO the namespace "jaeger" should be configurable (e.g. in all-in-one "jaeger-client" would make more sense) + metrics.Init(m, factory.Namespace("jaeger", nil), globalTags) + return m +} + +// NewNullMetrics creates a new Metrics struct that won't report any metrics. +func NewNullMetrics() *Metrics { + return NewMetrics(metrics.NullFactory, nil) +} diff --git a/vendor/github.com/uber/jaeger-client-go/observer.go b/vendor/github.com/uber/jaeger-client-go/observer.go new file mode 100644 index 000000000..7bbd02889 --- /dev/null +++ b/vendor/github.com/uber/jaeger-client-go/observer.go @@ -0,0 +1,88 @@ +// Copyright (c) 2017 Uber Technologies, Inc. +// +// 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. + +package jaeger + +import opentracing "github.com/opentracing/opentracing-go" + +// Observer can be registered with the Tracer to receive notifications about +// new Spans. +// +// Deprecated: use jaeger.ContribObserver instead. +type Observer interface { + OnStartSpan(operationName string, options opentracing.StartSpanOptions) SpanObserver +} + +// SpanObserver is created by the Observer and receives notifications about +// other Span events. +// +// Deprecated: use jaeger.ContribSpanObserver instead. +type SpanObserver interface { + OnSetOperationName(operationName string) + OnSetTag(key string, value interface{}) + OnFinish(options opentracing.FinishOptions) +} + +// compositeObserver is a dispatcher to other observers +type compositeObserver struct { + observers []ContribObserver +} + +// compositeSpanObserver is a dispatcher to other span observers +type compositeSpanObserver struct { + observers []ContribSpanObserver +} + +// noopSpanObserver is used when there are no observers registered +// on the Tracer or none of them returns span observers from OnStartSpan. +var noopSpanObserver = &compositeSpanObserver{} + +func (o *compositeObserver) append(contribObserver ContribObserver) { + o.observers = append(o.observers, contribObserver) +} + +func (o *compositeObserver) OnStartSpan(sp opentracing.Span, operationName string, options opentracing.StartSpanOptions) ContribSpanObserver { + var spanObservers []ContribSpanObserver + for _, obs := range o.observers { + spanObs, ok := obs.OnStartSpan(sp, operationName, options) + if ok { + if spanObservers == nil { + spanObservers = make([]ContribSpanObserver, 0, len(o.observers)) + } + spanObservers = append(spanObservers, spanObs) + } + } + if len(spanObservers) == 0 { + return noopSpanObserver + } + return &compositeSpanObserver{observers: spanObservers} +} + +func (o *compositeSpanObserver) OnSetOperationName(operationName string) { + for _, obs := range o.observers { + obs.OnSetOperationName(operationName) + } +} + +func (o *compositeSpanObserver) OnSetTag(key string, value interface{}) { + for _, obs := range o.observers { + obs.OnSetTag(key, value) + } +} + +func (o *compositeSpanObserver) OnFinish(options opentracing.FinishOptions) { + for _, obs := range o.observers { + obs.OnFinish(options) + } +} diff --git a/vendor/github.com/uber/jaeger-client-go/propagation.go b/vendor/github.com/uber/jaeger-client-go/propagation.go new file mode 100644 index 000000000..abca67a3c --- /dev/null +++ b/vendor/github.com/uber/jaeger-client-go/propagation.go @@ -0,0 +1,300 @@ +// Copyright (c) 2017 Uber Technologies, Inc. +// +// 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. + +package jaeger + +import ( + "bytes" + "encoding/binary" + "fmt" + "io" + "log" + "net/url" + "strings" + "sync" + + opentracing "github.com/opentracing/opentracing-go" +) + +// Injector is responsible for injecting SpanContext instances in a manner suitable +// for propagation via a format-specific "carrier" object. Typically the +// injection will take place across an RPC boundary, but message queues and +// other IPC mechanisms are also reasonable places to use an Injector. +type Injector interface { + // Inject takes `SpanContext` and injects it into `carrier`. The actual type + // of `carrier` depends on the `format` passed to `Tracer.Inject()`. + // + // Implementations may return opentracing.ErrInvalidCarrier or any other + // implementation-specific error if injection fails. + Inject(ctx SpanContext, carrier interface{}) error +} + +// Extractor is responsible for extracting SpanContext instances from a +// format-specific "carrier" object. Typically the extraction will take place +// on the server side of an RPC boundary, but message queues and other IPC +// mechanisms are also reasonable places to use an Extractor. +type Extractor interface { + // Extract decodes a SpanContext instance from the given `carrier`, + // or (nil, opentracing.ErrSpanContextNotFound) if no context could + // be found in the `carrier`. + Extract(carrier interface{}) (SpanContext, error) +} + +type textMapPropagator struct { + headerKeys *HeadersConfig + metrics Metrics + encodeValue func(string) string + decodeValue func(string) string +} + +func newTextMapPropagator(headerKeys *HeadersConfig, metrics Metrics) *textMapPropagator { + return &textMapPropagator{ + headerKeys: headerKeys, + metrics: metrics, + encodeValue: func(val string) string { + return val + }, + decodeValue: func(val string) string { + return val + }, + } +} + +func newHTTPHeaderPropagator(headerKeys *HeadersConfig, metrics Metrics) *textMapPropagator { + return &textMapPropagator{ + headerKeys: headerKeys, + metrics: metrics, + encodeValue: func(val string) string { + return url.QueryEscape(val) + }, + decodeValue: func(val string) string { + // ignore decoding errors, cannot do anything about them + if v, err := url.QueryUnescape(val); err == nil { + return v + } + return val + }, + } +} + +type binaryPropagator struct { + tracer *Tracer + buffers sync.Pool +} + +func newBinaryPropagator(tracer *Tracer) *binaryPropagator { + return &binaryPropagator{ + tracer: tracer, + buffers: sync.Pool{New: func() interface{} { return &bytes.Buffer{} }}, + } +} + +func (p *textMapPropagator) Inject( + sc SpanContext, + abstractCarrier interface{}, +) error { + textMapWriter, ok := abstractCarrier.(opentracing.TextMapWriter) + if !ok { + return opentracing.ErrInvalidCarrier + } + + // Do not encode the string with trace context to avoid accidental double-encoding + // if people are using opentracing < 0.10.0. Our colon-separated representation + // of the trace context is already safe for HTTP headers. + textMapWriter.Set(p.headerKeys.TraceContextHeaderName, sc.String()) + for k, v := range sc.baggage { + safeKey := p.addBaggageKeyPrefix(k) + safeVal := p.encodeValue(v) + textMapWriter.Set(safeKey, safeVal) + } + return nil +} + +func (p *textMapPropagator) Extract(abstractCarrier interface{}) (SpanContext, error) { + textMapReader, ok := abstractCarrier.(opentracing.TextMapReader) + if !ok { + return emptyContext, opentracing.ErrInvalidCarrier + } + var ctx SpanContext + var baggage map[string]string + err := textMapReader.ForeachKey(func(rawKey, value string) error { + key := strings.ToLower(rawKey) // TODO not necessary for plain TextMap + if key == p.headerKeys.TraceContextHeaderName { + var err error + safeVal := p.decodeValue(value) + if ctx, err = ContextFromString(safeVal); err != nil { + return err + } + } else if key == p.headerKeys.JaegerDebugHeader { + ctx.debugID = p.decodeValue(value) + } else if key == p.headerKeys.JaegerBaggageHeader { + if baggage == nil { + baggage = make(map[string]string) + } + for k, v := range p.parseCommaSeparatedMap(value) { + baggage[k] = v + } + } else if strings.HasPrefix(key, p.headerKeys.TraceBaggageHeaderPrefix) { + if baggage == nil { + baggage = make(map[string]string) + } + safeKey := p.removeBaggageKeyPrefix(key) + safeVal := p.decodeValue(value) + baggage[safeKey] = safeVal + } + return nil + }) + if err != nil { + p.metrics.DecodingErrors.Inc(1) + return emptyContext, err + } + if !ctx.traceID.IsValid() && ctx.debugID == "" && len(baggage) == 0 { + return emptyContext, opentracing.ErrSpanContextNotFound + } + ctx.baggage = baggage + return ctx, nil +} + +func (p *binaryPropagator) Inject( + sc SpanContext, + abstractCarrier interface{}, +) error { + carrier, ok := abstractCarrier.(io.Writer) + if !ok { + return opentracing.ErrInvalidCarrier + } + + // Handle the tracer context + if err := binary.Write(carrier, binary.BigEndian, sc.traceID); err != nil { + return err + } + if err := binary.Write(carrier, binary.BigEndian, sc.spanID); err != nil { + return err + } + if err := binary.Write(carrier, binary.BigEndian, sc.parentID); err != nil { + return err + } + if err := binary.Write(carrier, binary.BigEndian, sc.flags); err != nil { + return err + } + + // Handle the baggage items + if err := binary.Write(carrier, binary.BigEndian, int32(len(sc.baggage))); err != nil { + return err + } + for k, v := range sc.baggage { + if err := binary.Write(carrier, binary.BigEndian, int32(len(k))); err != nil { + return err + } + io.WriteString(carrier, k) + if err := binary.Write(carrier, binary.BigEndian, int32(len(v))); err != nil { + return err + } + io.WriteString(carrier, v) + } + + return nil +} + +func (p *binaryPropagator) Extract(abstractCarrier interface{}) (SpanContext, error) { + carrier, ok := abstractCarrier.(io.Reader) + if !ok { + return emptyContext, opentracing.ErrInvalidCarrier + } + var ctx SpanContext + + if err := binary.Read(carrier, binary.BigEndian, &ctx.traceID); err != nil { + return emptyContext, opentracing.ErrSpanContextCorrupted + } + if err := binary.Read(carrier, binary.BigEndian, &ctx.spanID); err != nil { + return emptyContext, opentracing.ErrSpanContextCorrupted + } + if err := binary.Read(carrier, binary.BigEndian, &ctx.parentID); err != nil { + return emptyContext, opentracing.ErrSpanContextCorrupted + } + if err := binary.Read(carrier, binary.BigEndian, &ctx.flags); err != nil { + return emptyContext, opentracing.ErrSpanContextCorrupted + } + + // Handle the baggage items + var numBaggage int32 + if err := binary.Read(carrier, binary.BigEndian, &numBaggage); err != nil { + return emptyContext, opentracing.ErrSpanContextCorrupted + } + if iNumBaggage := int(numBaggage); iNumBaggage > 0 { + ctx.baggage = make(map[string]string, iNumBaggage) + buf := p.buffers.Get().(*bytes.Buffer) + defer p.buffers.Put(buf) + + var keyLen, valLen int32 + for i := 0; i < iNumBaggage; i++ { + if err := binary.Read(carrier, binary.BigEndian, &keyLen); err != nil { + return emptyContext, opentracing.ErrSpanContextCorrupted + } + buf.Reset() + buf.Grow(int(keyLen)) + if n, err := io.CopyN(buf, carrier, int64(keyLen)); err != nil || int32(n) != keyLen { + return emptyContext, opentracing.ErrSpanContextCorrupted + } + key := buf.String() + + if err := binary.Read(carrier, binary.BigEndian, &valLen); err != nil { + return emptyContext, opentracing.ErrSpanContextCorrupted + } + buf.Reset() + buf.Grow(int(valLen)) + if n, err := io.CopyN(buf, carrier, int64(valLen)); err != nil || int32(n) != valLen { + return emptyContext, opentracing.ErrSpanContextCorrupted + } + ctx.baggage[key] = buf.String() + } + } + + return ctx, nil +} + +// Converts a comma separated key value pair list into a map +// e.g. key1=value1, key2=value2, key3 = value3 +// is converted to map[string]string { "key1" : "value1", +// "key2" : "value2", +// "key3" : "value3" } +func (p *textMapPropagator) parseCommaSeparatedMap(value string) map[string]string { + baggage := make(map[string]string) + value, err := url.QueryUnescape(value) + if err != nil { + log.Printf("Unable to unescape %s, %v", value, err) + return baggage + } + for _, kvpair := range strings.Split(value, ",") { + kv := strings.Split(strings.TrimSpace(kvpair), "=") + if len(kv) == 2 { + baggage[kv[0]] = kv[1] + } else { + log.Printf("Malformed value passed in for %s", p.headerKeys.JaegerBaggageHeader) + } + } + return baggage +} + +// Converts a baggage item key into an http header format, +// by prepending TraceBaggageHeaderPrefix and encoding the key string +func (p *textMapPropagator) addBaggageKeyPrefix(key string) string { + // TODO encodeBaggageKeyAsHeader add caching and escaping + return fmt.Sprintf("%v%v", p.headerKeys.TraceBaggageHeaderPrefix, key) +} + +func (p *textMapPropagator) removeBaggageKeyPrefix(key string) string { + // TODO decodeBaggageHeaderKey add caching and escaping + return key[len(p.headerKeys.TraceBaggageHeaderPrefix):] +} diff --git a/vendor/github.com/uber/jaeger-client-go/reference.go b/vendor/github.com/uber/jaeger-client-go/reference.go new file mode 100644 index 000000000..5646e78bb --- /dev/null +++ b/vendor/github.com/uber/jaeger-client-go/reference.go @@ -0,0 +1,23 @@ +// Copyright (c) 2017 Uber Technologies, Inc. +// +// 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. + +package jaeger + +import "github.com/opentracing/opentracing-go" + +// Reference represents a causal reference to other Spans (via their SpanContext). +type Reference struct { + Type opentracing.SpanReferenceType + Context SpanContext +} diff --git a/vendor/github.com/uber/jaeger-client-go/reporter.go b/vendor/github.com/uber/jaeger-client-go/reporter.go new file mode 100644 index 000000000..fe6288c4b --- /dev/null +++ b/vendor/github.com/uber/jaeger-client-go/reporter.go @@ -0,0 +1,289 @@ +// Copyright (c) 2017 Uber Technologies, Inc. +// +// 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. + +package jaeger + +import ( + "fmt" + "sync" + "sync/atomic" + "time" + + "github.com/opentracing/opentracing-go" + + "github.com/uber/jaeger-client-go/log" +) + +// Reporter is called by the tracer when a span is completed to report the span to the tracing collector. +type Reporter interface { + // Report submits a new span to collectors, possibly asynchronously and/or with buffering. + Report(span *Span) + + // Close does a clean shutdown of the reporter, flushing any traces that may be buffered in memory. + Close() +} + +// ------------------------------ + +type nullReporter struct{} + +// NewNullReporter creates a no-op reporter that ignores all reported spans. +func NewNullReporter() Reporter { + return &nullReporter{} +} + +// Report implements Report() method of Reporter by doing nothing. +func (r *nullReporter) Report(span *Span) { + // no-op +} + +// Close implements Close() method of Reporter by doing nothing. +func (r *nullReporter) Close() { + // no-op +} + +// ------------------------------ + +type loggingReporter struct { + logger Logger +} + +// NewLoggingReporter creates a reporter that logs all reported spans to provided logger. +func NewLoggingReporter(logger Logger) Reporter { + return &loggingReporter{logger} +} + +// Report implements Report() method of Reporter by logging the span to the logger. +func (r *loggingReporter) Report(span *Span) { + r.logger.Infof("Reporting span %+v", span) +} + +// Close implements Close() method of Reporter by doing nothing. +func (r *loggingReporter) Close() { + // no-op +} + +// ------------------------------ + +// InMemoryReporter is used for testing, and simply collects spans in memory. +type InMemoryReporter struct { + spans []opentracing.Span + lock sync.Mutex +} + +// NewInMemoryReporter creates a reporter that stores spans in memory. +// NOTE: the Tracer should be created with options.PoolSpans = false. +func NewInMemoryReporter() *InMemoryReporter { + return &InMemoryReporter{ + spans: make([]opentracing.Span, 0, 10), + } +} + +// Report implements Report() method of Reporter by storing the span in the buffer. +func (r *InMemoryReporter) Report(span *Span) { + r.lock.Lock() + r.spans = append(r.spans, span) + r.lock.Unlock() +} + +// Close implements Close() method of Reporter by doing nothing. +func (r *InMemoryReporter) Close() { + // no-op +} + +// SpansSubmitted returns the number of spans accumulated in the buffer. +func (r *InMemoryReporter) SpansSubmitted() int { + r.lock.Lock() + defer r.lock.Unlock() + return len(r.spans) +} + +// GetSpans returns accumulated spans as a copy of the buffer. +func (r *InMemoryReporter) GetSpans() []opentracing.Span { + r.lock.Lock() + defer r.lock.Unlock() + copied := make([]opentracing.Span, len(r.spans)) + copy(copied, r.spans) + return copied +} + +// Reset clears all accumulated spans. +func (r *InMemoryReporter) Reset() { + r.lock.Lock() + defer r.lock.Unlock() + r.spans = nil +} + +// ------------------------------ + +type compositeReporter struct { + reporters []Reporter +} + +// NewCompositeReporter creates a reporter that ignores all reported spans. +func NewCompositeReporter(reporters ...Reporter) Reporter { + return &compositeReporter{reporters: reporters} +} + +// Report implements Report() method of Reporter by delegating to each underlying reporter. +func (r *compositeReporter) Report(span *Span) { + for _, reporter := range r.reporters { + reporter.Report(span) + } +} + +// Close implements Close() method of Reporter by closing each underlying reporter. +func (r *compositeReporter) Close() { + for _, reporter := range r.reporters { + reporter.Close() + } +} + +// ------------- REMOTE REPORTER ----------------- + +type reporterQueueItemType int + +const ( + defaultQueueSize = 100 + defaultBufferFlushInterval = 1 * time.Second + + reporterQueueItemSpan reporterQueueItemType = iota + reporterQueueItemClose +) + +type reporterQueueItem struct { + itemType reporterQueueItemType + span *Span + close *sync.WaitGroup +} + +type remoteReporter struct { + // These fields must be first in the struct because `sync/atomic` expects 64-bit alignment. + // Cf. https://github.com/uber/jaeger-client-go/issues/155, https://goo.gl/zW7dgq + queueLength int64 + closed int64 // 0 - not closed, 1 - closed + + reporterOptions + + sender Transport + queue chan reporterQueueItem +} + +// NewRemoteReporter creates a new reporter that sends spans out of process by means of Sender. +// Calls to Report(Span) return immediately (side effect: if internal buffer is full the span is dropped). +// Periodically the transport buffer is flushed even if it hasn't reached max packet size. +// Calls to Close() block until all spans reported prior to the call to Close are flushed. +func NewRemoteReporter(sender Transport, opts ...ReporterOption) Reporter { + options := reporterOptions{} + for _, option := range opts { + option(&options) + } + if options.bufferFlushInterval <= 0 { + options.bufferFlushInterval = defaultBufferFlushInterval + } + if options.logger == nil { + options.logger = log.NullLogger + } + if options.metrics == nil { + options.metrics = NewNullMetrics() + } + if options.queueSize <= 0 { + options.queueSize = defaultQueueSize + } + reporter := &remoteReporter{ + reporterOptions: options, + sender: sender, + queue: make(chan reporterQueueItem, options.queueSize), + } + go reporter.processQueue() + return reporter +} + +// Report implements Report() method of Reporter. +// It passes the span to a background go-routine for submission to Jaeger backend. +// If the internal queue is full, the span is dropped and metrics.ReporterDropped counter is incremented. +// If Report() is called after the reporter has been Close()-ed, the additional spans will not be +// sent to the backend, but the metrics.ReporterDropped counter may not reflect them correctly, +// because some of them may still be successfully added to the queue. +func (r *remoteReporter) Report(span *Span) { + select { + case r.queue <- reporterQueueItem{itemType: reporterQueueItemSpan, span: span}: + atomic.AddInt64(&r.queueLength, 1) + default: + r.metrics.ReporterDropped.Inc(1) + } +} + +// Close implements Close() method of Reporter by waiting for the queue to be drained. +func (r *remoteReporter) Close() { + if swapped := atomic.CompareAndSwapInt64(&r.closed, 0, 1); !swapped { + r.logger.Error("Repeated attempt to close the reporter is ignored") + return + } + r.sendCloseEvent() + r.sender.Close() +} + +func (r *remoteReporter) sendCloseEvent() { + wg := &sync.WaitGroup{} + wg.Add(1) + item := reporterQueueItem{itemType: reporterQueueItemClose, close: wg} + + r.queue <- item // if the queue is full we will block until there is space + atomic.AddInt64(&r.queueLength, 1) + wg.Wait() +} + +// processQueue reads spans from the queue, converts them to Thrift, and stores them in an internal buffer. +// When the buffer length reaches batchSize, it is flushed by submitting the accumulated spans to Jaeger. +// Buffer also gets flushed automatically every batchFlushInterval seconds, just in case the tracer stopped +// reporting new spans. +func (r *remoteReporter) processQueue() { + // flush causes the Sender to flush its accumulated spans and clear the buffer + flush := func() { + if flushed, err := r.sender.Flush(); err != nil { + r.metrics.ReporterFailure.Inc(int64(flushed)) + r.logger.Error(fmt.Sprintf("error when flushing the buffer: %s", err.Error())) + } else if flushed > 0 { + r.metrics.ReporterSuccess.Inc(int64(flushed)) + } + } + + timer := time.NewTicker(r.bufferFlushInterval) + for { + select { + case <-timer.C: + flush() + case item := <-r.queue: + atomic.AddInt64(&r.queueLength, -1) + switch item.itemType { + case reporterQueueItemSpan: + span := item.span + if flushed, err := r.sender.Append(span); err != nil { + r.metrics.ReporterFailure.Inc(int64(flushed)) + r.logger.Error(fmt.Sprintf("error reporting span %q: %s", span.OperationName(), err.Error())) + } else if flushed > 0 { + r.metrics.ReporterSuccess.Inc(int64(flushed)) + // to reduce the number of gauge stats, we only emit queue length on flush + r.metrics.ReporterQueueLength.Update(atomic.LoadInt64(&r.queueLength)) + } + case reporterQueueItemClose: + timer.Stop() + flush() + item.close.Done() + return + } + } + } +} diff --git a/vendor/github.com/uber/jaeger-client-go/reporter_options.go b/vendor/github.com/uber/jaeger-client-go/reporter_options.go new file mode 100644 index 000000000..65012d701 --- /dev/null +++ b/vendor/github.com/uber/jaeger-client-go/reporter_options.go @@ -0,0 +1,69 @@ +// Copyright (c) 2017 Uber Technologies, Inc. +// +// 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. + +package jaeger + +import ( + "time" +) + +// ReporterOption is a function that sets some option on the reporter. +type ReporterOption func(c *reporterOptions) + +// ReporterOptions is a factory for all available ReporterOption's +var ReporterOptions reporterOptions + +// reporterOptions control behavior of the reporter. +type reporterOptions struct { + // queueSize is the size of internal queue where reported spans are stored before they are processed in the background + queueSize int + // bufferFlushInterval is how often the buffer is force-flushed, even if it's not full + bufferFlushInterval time.Duration + // logger is used to log errors of span submissions + logger Logger + // metrics is used to record runtime stats + metrics *Metrics +} + +// QueueSize creates a ReporterOption that sets the size of the internal queue where +// spans are stored before they are processed. +func (reporterOptions) QueueSize(queueSize int) ReporterOption { + return func(r *reporterOptions) { + r.queueSize = queueSize + } +} + +// Metrics creates a ReporterOption that initializes Metrics in the reporter, +// which is used to record runtime statistics. +func (reporterOptions) Metrics(metrics *Metrics) ReporterOption { + return func(r *reporterOptions) { + r.metrics = metrics + } +} + +// BufferFlushInterval creates a ReporterOption that sets how often the queue +// is force-flushed. +func (reporterOptions) BufferFlushInterval(bufferFlushInterval time.Duration) ReporterOption { + return func(r *reporterOptions) { + r.bufferFlushInterval = bufferFlushInterval + } +} + +// Logger creates a ReporterOption that initializes the logger used to log +// errors of span submissions. +func (reporterOptions) Logger(logger Logger) ReporterOption { + return func(r *reporterOptions) { + r.logger = logger + } +} diff --git a/vendor/github.com/uber/jaeger-client-go/sampler.go b/vendor/github.com/uber/jaeger-client-go/sampler.go new file mode 100644 index 000000000..f2e8c994e --- /dev/null +++ b/vendor/github.com/uber/jaeger-client-go/sampler.go @@ -0,0 +1,531 @@ +// Copyright (c) 2017 Uber Technologies, Inc. +// +// 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. + +package jaeger + +import ( + "fmt" + "math" + "net/url" + "sync" + "time" + + "github.com/uber/jaeger-client-go/log" + "github.com/uber/jaeger-client-go/thrift-gen/sampling" + "github.com/uber/jaeger-client-go/utils" +) + +const ( + defaultSamplingServerURL = "http://localhost:5778/sampling" + defaultSamplingRefreshInterval = time.Minute + defaultMaxOperations = 2000 +) + +// Sampler decides whether a new trace should be sampled or not. +type Sampler interface { + // IsSampled decides whether a trace with given `id` and `operation` + // should be sampled. This function will also return the tags that + // can be used to identify the type of sampling that was applied to + // the root span. Most simple samplers would return two tags, + // sampler.type and sampler.param, similar to those used in the Configuration + IsSampled(id TraceID, operation string) (sampled bool, tags []Tag) + + // Close does a clean shutdown of the sampler, stopping any background + // go-routines it may have started. + Close() + + // Equal checks if the `other` sampler is functionally equivalent + // to this sampler. + // TODO remove this function. This function is used to determine if 2 samplers are equivalent + // which does not bode well with the adaptive sampler which has to create all the composite samplers + // for the comparison to occur. This is expensive to do if only one sampler has changed. + Equal(other Sampler) bool +} + +// ----------------------- + +// ConstSampler is a sampler that always makes the same decision. +type ConstSampler struct { + Decision bool + tags []Tag +} + +// NewConstSampler creates a ConstSampler. +func NewConstSampler(sample bool) Sampler { + tags := []Tag{ + {key: SamplerTypeTagKey, value: SamplerTypeConst}, + {key: SamplerParamTagKey, value: sample}, + } + return &ConstSampler{Decision: sample, tags: tags} +} + +// IsSampled implements IsSampled() of Sampler. +func (s *ConstSampler) IsSampled(id TraceID, operation string) (bool, []Tag) { + return s.Decision, s.tags +} + +// Close implements Close() of Sampler. +func (s *ConstSampler) Close() { + // nothing to do +} + +// Equal implements Equal() of Sampler. +func (s *ConstSampler) Equal(other Sampler) bool { + if o, ok := other.(*ConstSampler); ok { + return s.Decision == o.Decision + } + return false +} + +// ----------------------- + +// ProbabilisticSampler is a sampler that randomly samples a certain percentage +// of traces. +type ProbabilisticSampler struct { + samplingRate float64 + samplingBoundary uint64 + tags []Tag +} + +const maxRandomNumber = ^(uint64(1) << 63) // i.e. 0x7fffffffffffffff + +// NewProbabilisticSampler creates a sampler that randomly samples a certain percentage of traces specified by the +// samplingRate, in the range between 0.0 and 1.0. +// +// It relies on the fact that new trace IDs are 63bit random numbers themselves, thus making the sampling decision +// without generating a new random number, but simply calculating if traceID < (samplingRate * 2^63). +// TODO remove the error from this function for next major release +func NewProbabilisticSampler(samplingRate float64) (*ProbabilisticSampler, error) { + if samplingRate < 0.0 || samplingRate > 1.0 { + return nil, fmt.Errorf("Sampling Rate must be between 0.0 and 1.0, received %f", samplingRate) + } + return newProbabilisticSampler(samplingRate), nil +} + +func newProbabilisticSampler(samplingRate float64) *ProbabilisticSampler { + samplingRate = math.Max(0.0, math.Min(samplingRate, 1.0)) + tags := []Tag{ + {key: SamplerTypeTagKey, value: SamplerTypeProbabilistic}, + {key: SamplerParamTagKey, value: samplingRate}, + } + return &ProbabilisticSampler{ + samplingRate: samplingRate, + samplingBoundary: uint64(float64(maxRandomNumber) * samplingRate), + tags: tags, + } +} + +// SamplingRate returns the sampling probability this sampled was constructed with. +func (s *ProbabilisticSampler) SamplingRate() float64 { + return s.samplingRate +} + +// IsSampled implements IsSampled() of Sampler. +func (s *ProbabilisticSampler) IsSampled(id TraceID, operation string) (bool, []Tag) { + return s.samplingBoundary >= id.Low, s.tags +} + +// Close implements Close() of Sampler. +func (s *ProbabilisticSampler) Close() { + // nothing to do +} + +// Equal implements Equal() of Sampler. +func (s *ProbabilisticSampler) Equal(other Sampler) bool { + if o, ok := other.(*ProbabilisticSampler); ok { + return s.samplingBoundary == o.samplingBoundary + } + return false +} + +// ----------------------- + +type rateLimitingSampler struct { + maxTracesPerSecond float64 + rateLimiter utils.RateLimiter + tags []Tag +} + +// NewRateLimitingSampler creates a sampler that samples at most maxTracesPerSecond. The distribution of sampled +// traces follows burstiness of the service, i.e. a service with uniformly distributed requests will have those +// requests sampled uniformly as well, but if requests are bursty, especially sub-second, then a number of +// sequential requests can be sampled each second. +func NewRateLimitingSampler(maxTracesPerSecond float64) Sampler { + tags := []Tag{ + {key: SamplerTypeTagKey, value: SamplerTypeRateLimiting}, + {key: SamplerParamTagKey, value: maxTracesPerSecond}, + } + return &rateLimitingSampler{ + maxTracesPerSecond: maxTracesPerSecond, + rateLimiter: utils.NewRateLimiter(maxTracesPerSecond, math.Max(maxTracesPerSecond, 1.0)), + tags: tags, + } +} + +// IsSampled implements IsSampled() of Sampler. +func (s *rateLimitingSampler) IsSampled(id TraceID, operation string) (bool, []Tag) { + return s.rateLimiter.CheckCredit(1.0), s.tags +} + +func (s *rateLimitingSampler) Close() { + // nothing to do +} + +func (s *rateLimitingSampler) Equal(other Sampler) bool { + if o, ok := other.(*rateLimitingSampler); ok { + return s.maxTracesPerSecond == o.maxTracesPerSecond + } + return false +} + +// ----------------------- + +// GuaranteedThroughputProbabilisticSampler is a sampler that leverages both probabilisticSampler and +// rateLimitingSampler. The rateLimitingSampler is used as a guaranteed lower bound sampler such that +// every operation is sampled at least once in a time interval defined by the lowerBound. ie a lowerBound +// of 1.0 / (60 * 10) will sample an operation at least once every 10 minutes. +// +// The probabilisticSampler is given higher priority when tags are emitted, ie. if IsSampled() for both +// samplers return true, the tags for probabilisticSampler will be used. +type GuaranteedThroughputProbabilisticSampler struct { + probabilisticSampler *ProbabilisticSampler + lowerBoundSampler Sampler + tags []Tag + samplingRate float64 + lowerBound float64 +} + +// NewGuaranteedThroughputProbabilisticSampler returns a delegating sampler that applies both +// probabilisticSampler and rateLimitingSampler. +func NewGuaranteedThroughputProbabilisticSampler( + lowerBound, samplingRate float64, +) (*GuaranteedThroughputProbabilisticSampler, error) { + return newGuaranteedThroughputProbabilisticSampler(lowerBound, samplingRate), nil +} + +func newGuaranteedThroughputProbabilisticSampler(lowerBound, samplingRate float64) *GuaranteedThroughputProbabilisticSampler { + s := &GuaranteedThroughputProbabilisticSampler{ + lowerBoundSampler: NewRateLimitingSampler(lowerBound), + lowerBound: lowerBound, + } + s.setProbabilisticSampler(samplingRate) + return s +} + +func (s *GuaranteedThroughputProbabilisticSampler) setProbabilisticSampler(samplingRate float64) { + if s.probabilisticSampler == nil || s.samplingRate != samplingRate { + s.probabilisticSampler = newProbabilisticSampler(samplingRate) + s.samplingRate = s.probabilisticSampler.SamplingRate() + s.tags = []Tag{ + {key: SamplerTypeTagKey, value: SamplerTypeLowerBound}, + {key: SamplerParamTagKey, value: s.samplingRate}, + } + } +} + +// IsSampled implements IsSampled() of Sampler. +func (s *GuaranteedThroughputProbabilisticSampler) IsSampled(id TraceID, operation string) (bool, []Tag) { + if sampled, tags := s.probabilisticSampler.IsSampled(id, operation); sampled { + s.lowerBoundSampler.IsSampled(id, operation) + return true, tags + } + sampled, _ := s.lowerBoundSampler.IsSampled(id, operation) + return sampled, s.tags +} + +// Close implements Close() of Sampler. +func (s *GuaranteedThroughputProbabilisticSampler) Close() { + s.probabilisticSampler.Close() + s.lowerBoundSampler.Close() +} + +// Equal implements Equal() of Sampler. +func (s *GuaranteedThroughputProbabilisticSampler) Equal(other Sampler) bool { + // NB The Equal() function is expensive and will be removed. See adaptiveSampler.Equal() for + // more information. + return false +} + +// this function should only be called while holding a Write lock +func (s *GuaranteedThroughputProbabilisticSampler) update(lowerBound, samplingRate float64) { + s.setProbabilisticSampler(samplingRate) + if s.lowerBound != lowerBound { + s.lowerBoundSampler = NewRateLimitingSampler(lowerBound) + s.lowerBound = lowerBound + } +} + +// ----------------------- + +type adaptiveSampler struct { + sync.RWMutex + + samplers map[string]*GuaranteedThroughputProbabilisticSampler + defaultSampler *ProbabilisticSampler + lowerBound float64 + maxOperations int +} + +// NewAdaptiveSampler returns a delegating sampler that applies both probabilisticSampler and +// rateLimitingSampler via the guaranteedThroughputProbabilisticSampler. This sampler keeps track of all +// operations and delegates calls to the respective guaranteedThroughputProbabilisticSampler. +func NewAdaptiveSampler(strategies *sampling.PerOperationSamplingStrategies, maxOperations int) (Sampler, error) { + return newAdaptiveSampler(strategies, maxOperations), nil +} + +func newAdaptiveSampler(strategies *sampling.PerOperationSamplingStrategies, maxOperations int) Sampler { + samplers := make(map[string]*GuaranteedThroughputProbabilisticSampler) + for _, strategy := range strategies.PerOperationStrategies { + sampler := newGuaranteedThroughputProbabilisticSampler( + strategies.DefaultLowerBoundTracesPerSecond, + strategy.ProbabilisticSampling.SamplingRate, + ) + samplers[strategy.Operation] = sampler + } + return &adaptiveSampler{ + samplers: samplers, + defaultSampler: newProbabilisticSampler(strategies.DefaultSamplingProbability), + lowerBound: strategies.DefaultLowerBoundTracesPerSecond, + maxOperations: maxOperations, + } +} + +func (s *adaptiveSampler) IsSampled(id TraceID, operation string) (bool, []Tag) { + s.RLock() + sampler, ok := s.samplers[operation] + if ok { + defer s.RUnlock() + return sampler.IsSampled(id, operation) + } + s.RUnlock() + s.Lock() + defer s.Unlock() + + // Check if sampler has already been created + sampler, ok = s.samplers[operation] + if ok { + return sampler.IsSampled(id, operation) + } + // Store only up to maxOperations of unique ops. + if len(s.samplers) >= s.maxOperations { + return s.defaultSampler.IsSampled(id, operation) + } + newSampler := newGuaranteedThroughputProbabilisticSampler(s.lowerBound, s.defaultSampler.SamplingRate()) + s.samplers[operation] = newSampler + return newSampler.IsSampled(id, operation) +} + +func (s *adaptiveSampler) Close() { + s.Lock() + defer s.Unlock() + for _, sampler := range s.samplers { + sampler.Close() + } + s.defaultSampler.Close() +} + +func (s *adaptiveSampler) Equal(other Sampler) bool { + // NB The Equal() function is overly expensive for adaptiveSampler since it's composed of multiple + // samplers which all need to be initialized before this function can be called for a comparison. + // Therefore, adaptiveSampler uses the update() function to only alter the samplers that need + // changing. Hence this function always returns false so that the update function can be called. + // Once the Equal() function is removed from the Sampler API, this will no longer be needed. + return false +} + +func (s *adaptiveSampler) update(strategies *sampling.PerOperationSamplingStrategies) { + s.Lock() + defer s.Unlock() + for _, strategy := range strategies.PerOperationStrategies { + operation := strategy.Operation + samplingRate := strategy.ProbabilisticSampling.SamplingRate + lowerBound := strategies.DefaultLowerBoundTracesPerSecond + if sampler, ok := s.samplers[operation]; ok { + sampler.update(lowerBound, samplingRate) + } else { + sampler := newGuaranteedThroughputProbabilisticSampler( + lowerBound, + samplingRate, + ) + s.samplers[operation] = sampler + } + } + s.lowerBound = strategies.DefaultLowerBoundTracesPerSecond + if s.defaultSampler.SamplingRate() != strategies.DefaultSamplingProbability { + s.defaultSampler = newProbabilisticSampler(strategies.DefaultSamplingProbability) + } +} + +// ----------------------- + +// RemotelyControlledSampler is a delegating sampler that polls a remote server +// for the appropriate sampling strategy, constructs a corresponding sampler and +// delegates to it for sampling decisions. +type RemotelyControlledSampler struct { + sync.RWMutex + samplerOptions + + serviceName string + timer *time.Ticker + manager sampling.SamplingManager + pollStopped sync.WaitGroup +} + +type httpSamplingManager struct { + serverURL string +} + +func (s *httpSamplingManager) GetSamplingStrategy(serviceName string) (*sampling.SamplingStrategyResponse, error) { + var out sampling.SamplingStrategyResponse + v := url.Values{} + v.Set("service", serviceName) + if err := utils.GetJSON(s.serverURL+"?"+v.Encode(), &out); err != nil { + return nil, err + } + return &out, nil +} + +// NewRemotelyControlledSampler creates a sampler that periodically pulls +// the sampling strategy from an HTTP sampling server (e.g. jaeger-agent). +func NewRemotelyControlledSampler( + serviceName string, + opts ...SamplerOption, +) *RemotelyControlledSampler { + options := applySamplerOptions(opts...) + sampler := &RemotelyControlledSampler{ + samplerOptions: options, + serviceName: serviceName, + timer: time.NewTicker(options.samplingRefreshInterval), + manager: &httpSamplingManager{serverURL: options.samplingServerURL}, + } + + go sampler.pollController() + return sampler +} + +func applySamplerOptions(opts ...SamplerOption) samplerOptions { + options := samplerOptions{} + for _, option := range opts { + option(&options) + } + if options.sampler == nil { + options.sampler = newProbabilisticSampler(0.001) + } + if options.logger == nil { + options.logger = log.NullLogger + } + if options.maxOperations <= 0 { + options.maxOperations = defaultMaxOperations + } + if options.samplingServerURL == "" { + options.samplingServerURL = defaultSamplingServerURL + } + if options.metrics == nil { + options.metrics = NewNullMetrics() + } + if options.samplingRefreshInterval <= 0 { + options.samplingRefreshInterval = defaultSamplingRefreshInterval + } + return options +} + +// IsSampled implements IsSampled() of Sampler. +func (s *RemotelyControlledSampler) IsSampled(id TraceID, operation string) (bool, []Tag) { + s.RLock() + defer s.RUnlock() + return s.sampler.IsSampled(id, operation) +} + +// Close implements Close() of Sampler. +func (s *RemotelyControlledSampler) Close() { + s.RLock() + s.timer.Stop() + s.RUnlock() + + s.pollStopped.Wait() +} + +// Equal implements Equal() of Sampler. +func (s *RemotelyControlledSampler) Equal(other Sampler) bool { + // NB The Equal() function is expensive and will be removed. See adaptiveSampler.Equal() for + // more information. + if o, ok := other.(*RemotelyControlledSampler); ok { + s.RLock() + o.RLock() + defer s.RUnlock() + defer o.RUnlock() + return s.sampler.Equal(o.sampler) + } + return false +} + +func (s *RemotelyControlledSampler) pollController() { + // in unit tests we re-assign the timer Ticker, so need to lock to avoid data races + s.Lock() + timer := s.timer + s.Unlock() + + for range timer.C { + s.updateSampler() + } + s.pollStopped.Add(1) +} + +func (s *RemotelyControlledSampler) updateSampler() { + res, err := s.manager.GetSamplingStrategy(s.serviceName) + if err != nil { + s.metrics.SamplerQueryFailure.Inc(1) + return + } + s.Lock() + defer s.Unlock() + + s.metrics.SamplerRetrieved.Inc(1) + if strategies := res.GetOperationSampling(); strategies != nil { + s.updateAdaptiveSampler(strategies) + } else { + err = s.updateRateLimitingOrProbabilisticSampler(res) + } + if err != nil { + s.metrics.SamplerUpdateFailure.Inc(1) + s.logger.Infof("Unable to handle sampling strategy response %+v. Got error: %v", res, err) + return + } + s.metrics.SamplerUpdated.Inc(1) +} + +// NB: this function should only be called while holding a Write lock +func (s *RemotelyControlledSampler) updateAdaptiveSampler(strategies *sampling.PerOperationSamplingStrategies) { + if adaptiveSampler, ok := s.sampler.(*adaptiveSampler); ok { + adaptiveSampler.update(strategies) + } else { + s.sampler = newAdaptiveSampler(strategies, s.maxOperations) + } +} + +// NB: this function should only be called while holding a Write lock +func (s *RemotelyControlledSampler) updateRateLimitingOrProbabilisticSampler(res *sampling.SamplingStrategyResponse) error { + var newSampler Sampler + if probabilistic := res.GetProbabilisticSampling(); probabilistic != nil { + newSampler = newProbabilisticSampler(probabilistic.SamplingRate) + } else if rateLimiting := res.GetRateLimitingSampling(); rateLimiting != nil { + newSampler = NewRateLimitingSampler(float64(rateLimiting.MaxTracesPerSecond)) + } else { + return fmt.Errorf("Unsupported sampling strategy type %v", res.GetStrategyType()) + } + if !s.sampler.Equal(newSampler) { + s.sampler = newSampler + } + return nil +} diff --git a/vendor/github.com/uber/jaeger-client-go/sampler_options.go b/vendor/github.com/uber/jaeger-client-go/sampler_options.go new file mode 100644 index 000000000..75d28a561 --- /dev/null +++ b/vendor/github.com/uber/jaeger-client-go/sampler_options.go @@ -0,0 +1,81 @@ +// Copyright (c) 2017 Uber Technologies, Inc. +// +// 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. + +package jaeger + +import ( + "time" +) + +// SamplerOption is a function that sets some option on the sampler +type SamplerOption func(options *samplerOptions) + +// SamplerOptions is a factory for all available SamplerOption's +var SamplerOptions samplerOptions + +type samplerOptions struct { + metrics *Metrics + maxOperations int + sampler Sampler + logger Logger + samplingServerURL string + samplingRefreshInterval time.Duration +} + +// Metrics creates a SamplerOption that initializes Metrics on the sampler, +// which is used to emit statistics. +func (samplerOptions) Metrics(m *Metrics) SamplerOption { + return func(o *samplerOptions) { + o.metrics = m + } +} + +// MaxOperations creates a SamplerOption that sets the maximum number of +// operations the sampler will keep track of. +func (samplerOptions) MaxOperations(maxOperations int) SamplerOption { + return func(o *samplerOptions) { + o.maxOperations = maxOperations + } +} + +// InitialSampler creates a SamplerOption that sets the initial sampler +// to use before a remote sampler is created and used. +func (samplerOptions) InitialSampler(sampler Sampler) SamplerOption { + return func(o *samplerOptions) { + o.sampler = sampler + } +} + +// Logger creates a SamplerOption that sets the logger used by the sampler. +func (samplerOptions) Logger(logger Logger) SamplerOption { + return func(o *samplerOptions) { + o.logger = logger + } +} + +// SamplingServerURL creates a SamplerOption that sets the sampling server url +// of the local agent that contains the sampling strategies. +func (samplerOptions) SamplingServerURL(samplingServerURL string) SamplerOption { + return func(o *samplerOptions) { + o.samplingServerURL = samplingServerURL + } +} + +// SamplingRefreshInterval creates a SamplerOption that sets how often the +// sampler will poll local agent for the appropriate sampling strategy. +func (samplerOptions) SamplingRefreshInterval(samplingRefreshInterval time.Duration) SamplerOption { + return func(o *samplerOptions) { + o.samplingRefreshInterval = samplingRefreshInterval + } +} diff --git a/vendor/github.com/uber/jaeger-client-go/span.go b/vendor/github.com/uber/jaeger-client-go/span.go new file mode 100644 index 000000000..132fb7217 --- /dev/null +++ b/vendor/github.com/uber/jaeger-client-go/span.go @@ -0,0 +1,242 @@ +// Copyright (c) 2017 Uber Technologies, Inc. +// +// 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. + +package jaeger + +import ( + "sync" + "time" + + "github.com/opentracing/opentracing-go" + "github.com/opentracing/opentracing-go/ext" + "github.com/opentracing/opentracing-go/log" +) + +// Span implements opentracing.Span +type Span struct { + sync.RWMutex + + tracer *Tracer + + context SpanContext + + // The name of the "operation" this span is an instance of. + // Known as a "span name" in some implementations. + operationName string + + // firstInProcess, if true, indicates that this span is the root of the (sub)tree + // of spans in the current process. In other words it's true for the root spans, + // and the ingress spans when the process joins another trace. + firstInProcess bool + + // startTime is the timestamp indicating when the span began, with microseconds precision. + startTime time.Time + + // duration returns duration of the span with microseconds precision. + // Zero value means duration is unknown. + duration time.Duration + + // tags attached to this span + tags []Tag + + // The span's "micro-log" + logs []opentracing.LogRecord + + // references for this span + references []Reference + + observer ContribSpanObserver +} + +// Tag is a simple key value wrapper. +// TODO deprecate in the next major release, use opentracing.Tag instead. +type Tag struct { + key string + value interface{} +} + +// SetOperationName sets or changes the operation name. +func (s *Span) SetOperationName(operationName string) opentracing.Span { + s.Lock() + defer s.Unlock() + if s.context.IsSampled() { + s.operationName = operationName + } + s.observer.OnSetOperationName(operationName) + return s +} + +// SetTag implements SetTag() of opentracing.Span +func (s *Span) SetTag(key string, value interface{}) opentracing.Span { + s.observer.OnSetTag(key, value) + if key == string(ext.SamplingPriority) && setSamplingPriority(s, value) { + return s + } + s.Lock() + defer s.Unlock() + if s.context.IsSampled() { + s.setTagNoLocking(key, value) + } + return s +} + +func (s *Span) setTagNoLocking(key string, value interface{}) { + s.tags = append(s.tags, Tag{key: key, value: value}) +} + +// LogFields implements opentracing.Span API +func (s *Span) LogFields(fields ...log.Field) { + s.Lock() + defer s.Unlock() + if !s.context.IsSampled() { + return + } + s.logFieldsNoLocking(fields...) +} + +// this function should only be called while holding a Write lock +func (s *Span) logFieldsNoLocking(fields ...log.Field) { + lr := opentracing.LogRecord{ + Fields: fields, + Timestamp: time.Now(), + } + s.appendLog(lr) +} + +// LogKV implements opentracing.Span API +func (s *Span) LogKV(alternatingKeyValues ...interface{}) { + s.RLock() + sampled := s.context.IsSampled() + s.RUnlock() + if !sampled { + return + } + fields, err := log.InterleavedKVToFields(alternatingKeyValues...) + if err != nil { + s.LogFields(log.Error(err), log.String("function", "LogKV")) + return + } + s.LogFields(fields...) +} + +// LogEvent implements opentracing.Span API +func (s *Span) LogEvent(event string) { + s.Log(opentracing.LogData{Event: event}) +} + +// LogEventWithPayload implements opentracing.Span API +func (s *Span) LogEventWithPayload(event string, payload interface{}) { + s.Log(opentracing.LogData{Event: event, Payload: payload}) +} + +// Log implements opentracing.Span API +func (s *Span) Log(ld opentracing.LogData) { + s.Lock() + defer s.Unlock() + if s.context.IsSampled() { + if ld.Timestamp.IsZero() { + ld.Timestamp = s.tracer.timeNow() + } + s.appendLog(ld.ToLogRecord()) + } +} + +// this function should only be called while holding a Write lock +func (s *Span) appendLog(lr opentracing.LogRecord) { + // TODO add logic to limit number of logs per span (issue #46) + s.logs = append(s.logs, lr) +} + +// SetBaggageItem implements SetBaggageItem() of opentracing.SpanContext +func (s *Span) SetBaggageItem(key, value string) opentracing.Span { + s.Lock() + defer s.Unlock() + s.tracer.setBaggage(s, key, value) + return s +} + +// BaggageItem implements BaggageItem() of opentracing.SpanContext +func (s *Span) BaggageItem(key string) string { + s.RLock() + defer s.RUnlock() + return s.context.baggage[key] +} + +// Finish implements opentracing.Span API +func (s *Span) Finish() { + s.FinishWithOptions(opentracing.FinishOptions{}) +} + +// FinishWithOptions implements opentracing.Span API +func (s *Span) FinishWithOptions(options opentracing.FinishOptions) { + if options.FinishTime.IsZero() { + options.FinishTime = s.tracer.timeNow() + } + s.observer.OnFinish(options) + s.Lock() + if s.context.IsSampled() { + s.duration = options.FinishTime.Sub(s.startTime) + // Note: bulk logs are not subject to maxLogsPerSpan limit + if options.LogRecords != nil { + s.logs = append(s.logs, options.LogRecords...) + } + for _, ld := range options.BulkLogData { + s.logs = append(s.logs, ld.ToLogRecord()) + } + } + s.Unlock() + // call reportSpan even for non-sampled traces, to return span to the pool + s.tracer.reportSpan(s) +} + +// Context implements opentracing.Span API +func (s *Span) Context() opentracing.SpanContext { + return s.context +} + +// Tracer implements opentracing.Span API +func (s *Span) Tracer() opentracing.Tracer { + return s.tracer +} + +func (s *Span) String() string { + s.RLock() + defer s.RUnlock() + return s.context.String() +} + +// OperationName allows retrieving current operation name. +func (s *Span) OperationName() string { + s.RLock() + defer s.RUnlock() + return s.operationName +} + +func (s *Span) serviceName() string { + return s.tracer.serviceName +} + +func setSamplingPriority(s *Span, value interface{}) bool { + s.Lock() + defer s.Unlock() + if val, ok := value.(uint16); ok { + if val > 0 { + s.context.flags = s.context.flags | flagDebug | flagSampled + } else { + s.context.flags = s.context.flags & (^flagSampled) + } + return true + } + return false +} diff --git a/vendor/github.com/uber/jaeger-client-go/thrift-gen/agent/agent.go b/vendor/github.com/uber/jaeger-client-go/thrift-gen/agent/agent.go new file mode 100644 index 000000000..a192cb6f4 --- /dev/null +++ b/vendor/github.com/uber/jaeger-client-go/thrift-gen/agent/agent.go @@ -0,0 +1,410 @@ +// Autogenerated by Thrift Compiler (0.9.3) +// DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING + +package agent + +import ( + "bytes" + "fmt" + "github.com/apache/thrift/lib/go/thrift" + "github.com/uber/jaeger-client-go/thrift-gen/jaeger" + "github.com/uber/jaeger-client-go/thrift-gen/zipkincore" +) + +// (needed to ensure safety because of naive import list construction.) +var _ = thrift.ZERO +var _ = fmt.Printf +var _ = bytes.Equal + +var _ = zipkincore.GoUnusedProtection__ + +type Agent interface { + // Parameters: + // - Spans + EmitZipkinBatch(spans []*zipkincore.Span) (err error) + // Parameters: + // - Batch + EmitBatch(batch *jaeger.Batch) (err error) +} + +type AgentClient struct { + Transport thrift.TTransport + ProtocolFactory thrift.TProtocolFactory + InputProtocol thrift.TProtocol + OutputProtocol thrift.TProtocol + SeqId int32 +} + +func NewAgentClientFactory(t thrift.TTransport, f thrift.TProtocolFactory) *AgentClient { + return &AgentClient{Transport: t, + ProtocolFactory: f, + InputProtocol: f.GetProtocol(t), + OutputProtocol: f.GetProtocol(t), + SeqId: 0, + } +} + +func NewAgentClientProtocol(t thrift.TTransport, iprot thrift.TProtocol, oprot thrift.TProtocol) *AgentClient { + return &AgentClient{Transport: t, + ProtocolFactory: nil, + InputProtocol: iprot, + OutputProtocol: oprot, + SeqId: 0, + } +} + +// Parameters: +// - Spans +func (p *AgentClient) EmitZipkinBatch(spans []*zipkincore.Span) (err error) { + if err = p.sendEmitZipkinBatch(spans); err != nil { + return + } + return +} + +func (p *AgentClient) sendEmitZipkinBatch(spans []*zipkincore.Span) (err error) { + oprot := p.OutputProtocol + if oprot == nil { + oprot = p.ProtocolFactory.GetProtocol(p.Transport) + p.OutputProtocol = oprot + } + p.SeqId++ + if err = oprot.WriteMessageBegin("emitZipkinBatch", thrift.ONEWAY, p.SeqId); err != nil { + return + } + args := AgentEmitZipkinBatchArgs{ + Spans: spans, + } + if err = args.Write(oprot); err != nil { + return + } + if err = oprot.WriteMessageEnd(); err != nil { + return + } + return oprot.Flush() +} + +// Parameters: +// - Batch +func (p *AgentClient) EmitBatch(batch *jaeger.Batch) (err error) { + if err = p.sendEmitBatch(batch); err != nil { + return + } + return +} + +func (p *AgentClient) sendEmitBatch(batch *jaeger.Batch) (err error) { + oprot := p.OutputProtocol + if oprot == nil { + oprot = p.ProtocolFactory.GetProtocol(p.Transport) + p.OutputProtocol = oprot + } + p.SeqId++ + if err = oprot.WriteMessageBegin("emitBatch", thrift.ONEWAY, p.SeqId); err != nil { + return + } + args := AgentEmitBatchArgs{ + Batch: batch, + } + if err = args.Write(oprot); err != nil { + return + } + if err = oprot.WriteMessageEnd(); err != nil { + return + } + return oprot.Flush() +} + +type AgentProcessor struct { + processorMap map[string]thrift.TProcessorFunction + handler Agent +} + +func (p *AgentProcessor) AddToProcessorMap(key string, processor thrift.TProcessorFunction) { + p.processorMap[key] = processor +} + +func (p *AgentProcessor) GetProcessorFunction(key string) (processor thrift.TProcessorFunction, ok bool) { + processor, ok = p.processorMap[key] + return processor, ok +} + +func (p *AgentProcessor) ProcessorMap() map[string]thrift.TProcessorFunction { + return p.processorMap +} + +func NewAgentProcessor(handler Agent) *AgentProcessor { + + self0 := &AgentProcessor{handler: handler, processorMap: make(map[string]thrift.TProcessorFunction)} + self0.processorMap["emitZipkinBatch"] = &agentProcessorEmitZipkinBatch{handler: handler} + self0.processorMap["emitBatch"] = &agentProcessorEmitBatch{handler: handler} + return self0 +} + +func (p *AgentProcessor) Process(iprot, oprot thrift.TProtocol) (success bool, err thrift.TException) { + name, _, seqId, err := iprot.ReadMessageBegin() + if err != nil { + return false, err + } + if processor, ok := p.GetProcessorFunction(name); ok { + return processor.Process(seqId, iprot, oprot) + } + iprot.Skip(thrift.STRUCT) + iprot.ReadMessageEnd() + x1 := thrift.NewTApplicationException(thrift.UNKNOWN_METHOD, "Unknown function "+name) + oprot.WriteMessageBegin(name, thrift.EXCEPTION, seqId) + x1.Write(oprot) + oprot.WriteMessageEnd() + oprot.Flush() + return false, x1 + +} + +type agentProcessorEmitZipkinBatch struct { + handler Agent +} + +func (p *agentProcessorEmitZipkinBatch) Process(seqId int32, iprot, oprot thrift.TProtocol) (success bool, err thrift.TException) { + args := AgentEmitZipkinBatchArgs{} + if err = args.Read(iprot); err != nil { + iprot.ReadMessageEnd() + return false, err + } + + iprot.ReadMessageEnd() + var err2 error + if err2 = p.handler.EmitZipkinBatch(args.Spans); err2 != nil { + return true, err2 + } + return true, nil +} + +type agentProcessorEmitBatch struct { + handler Agent +} + +func (p *agentProcessorEmitBatch) Process(seqId int32, iprot, oprot thrift.TProtocol) (success bool, err thrift.TException) { + args := AgentEmitBatchArgs{} + if err = args.Read(iprot); err != nil { + iprot.ReadMessageEnd() + return false, err + } + + iprot.ReadMessageEnd() + var err2 error + if err2 = p.handler.EmitBatch(args.Batch); err2 != nil { + return true, err2 + } + return true, nil +} + +// HELPER FUNCTIONS AND STRUCTURES + +// Attributes: +// - Spans +type AgentEmitZipkinBatchArgs struct { + Spans []*zipkincore.Span `thrift:"spans,1" json:"spans"` +} + +func NewAgentEmitZipkinBatchArgs() *AgentEmitZipkinBatchArgs { + return &AgentEmitZipkinBatchArgs{} +} + +func (p *AgentEmitZipkinBatchArgs) GetSpans() []*zipkincore.Span { + return p.Spans +} +func (p *AgentEmitZipkinBatchArgs) Read(iprot thrift.TProtocol) error { + if _, err := iprot.ReadStructBegin(); err != nil { + return thrift.PrependError(fmt.Sprintf("%T read error: ", p), err) + } + + for { + _, fieldTypeId, fieldId, err := iprot.ReadFieldBegin() + if err != nil { + return thrift.PrependError(fmt.Sprintf("%T field %d read error: ", p, fieldId), err) + } + if fieldTypeId == thrift.STOP { + break + } + switch fieldId { + case 1: + if err := p.readField1(iprot); err != nil { + return err + } + default: + if err := iprot.Skip(fieldTypeId); err != nil { + return err + } + } + if err := iprot.ReadFieldEnd(); err != nil { + return err + } + } + if err := iprot.ReadStructEnd(); err != nil { + return thrift.PrependError(fmt.Sprintf("%T read struct end error: ", p), err) + } + return nil +} + +func (p *AgentEmitZipkinBatchArgs) readField1(iprot thrift.TProtocol) error { + _, size, err := iprot.ReadListBegin() + if err != nil { + return thrift.PrependError("error reading list begin: ", err) + } + tSlice := make([]*zipkincore.Span, 0, size) + p.Spans = tSlice + for i := 0; i < size; i++ { + _elem2 := &zipkincore.Span{} + if err := _elem2.Read(iprot); err != nil { + return thrift.PrependError(fmt.Sprintf("%T error reading struct: ", _elem2), err) + } + p.Spans = append(p.Spans, _elem2) + } + if err := iprot.ReadListEnd(); err != nil { + return thrift.PrependError("error reading list end: ", err) + } + return nil +} + +func (p *AgentEmitZipkinBatchArgs) Write(oprot thrift.TProtocol) error { + if err := oprot.WriteStructBegin("emitZipkinBatch_args"); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write struct begin error: ", p), err) + } + if err := p.writeField1(oprot); err != nil { + return err + } + if err := oprot.WriteFieldStop(); err != nil { + return thrift.PrependError("write field stop error: ", err) + } + if err := oprot.WriteStructEnd(); err != nil { + return thrift.PrependError("write struct stop error: ", err) + } + return nil +} + +func (p *AgentEmitZipkinBatchArgs) writeField1(oprot thrift.TProtocol) (err error) { + if err := oprot.WriteFieldBegin("spans", thrift.LIST, 1); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write field begin error 1:spans: ", p), err) + } + if err := oprot.WriteListBegin(thrift.STRUCT, len(p.Spans)); err != nil { + return thrift.PrependError("error writing list begin: ", err) + } + for _, v := range p.Spans { + if err := v.Write(oprot); err != nil { + return thrift.PrependError(fmt.Sprintf("%T error writing struct: ", v), err) + } + } + if err := oprot.WriteListEnd(); err != nil { + return thrift.PrependError("error writing list end: ", err) + } + if err := oprot.WriteFieldEnd(); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write field end error 1:spans: ", p), err) + } + return err +} + +func (p *AgentEmitZipkinBatchArgs) String() string { + if p == nil { + return "" + } + return fmt.Sprintf("AgentEmitZipkinBatchArgs(%+v)", *p) +} + +// Attributes: +// - Batch +type AgentEmitBatchArgs struct { + Batch *jaeger.Batch `thrift:"batch,1" json:"batch"` +} + +func NewAgentEmitBatchArgs() *AgentEmitBatchArgs { + return &AgentEmitBatchArgs{} +} + +var AgentEmitBatchArgs_Batch_DEFAULT *jaeger.Batch + +func (p *AgentEmitBatchArgs) GetBatch() *jaeger.Batch { + if !p.IsSetBatch() { + return AgentEmitBatchArgs_Batch_DEFAULT + } + return p.Batch +} +func (p *AgentEmitBatchArgs) IsSetBatch() bool { + return p.Batch != nil +} + +func (p *AgentEmitBatchArgs) Read(iprot thrift.TProtocol) error { + if _, err := iprot.ReadStructBegin(); err != nil { + return thrift.PrependError(fmt.Sprintf("%T read error: ", p), err) + } + + for { + _, fieldTypeId, fieldId, err := iprot.ReadFieldBegin() + if err != nil { + return thrift.PrependError(fmt.Sprintf("%T field %d read error: ", p, fieldId), err) + } + if fieldTypeId == thrift.STOP { + break + } + switch fieldId { + case 1: + if err := p.readField1(iprot); err != nil { + return err + } + default: + if err := iprot.Skip(fieldTypeId); err != nil { + return err + } + } + if err := iprot.ReadFieldEnd(); err != nil { + return err + } + } + if err := iprot.ReadStructEnd(); err != nil { + return thrift.PrependError(fmt.Sprintf("%T read struct end error: ", p), err) + } + return nil +} + +func (p *AgentEmitBatchArgs) readField1(iprot thrift.TProtocol) error { + p.Batch = &jaeger.Batch{} + if err := p.Batch.Read(iprot); err != nil { + return thrift.PrependError(fmt.Sprintf("%T error reading struct: ", p.Batch), err) + } + return nil +} + +func (p *AgentEmitBatchArgs) Write(oprot thrift.TProtocol) error { + if err := oprot.WriteStructBegin("emitBatch_args"); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write struct begin error: ", p), err) + } + if err := p.writeField1(oprot); err != nil { + return err + } + if err := oprot.WriteFieldStop(); err != nil { + return thrift.PrependError("write field stop error: ", err) + } + if err := oprot.WriteStructEnd(); err != nil { + return thrift.PrependError("write struct stop error: ", err) + } + return nil +} + +func (p *AgentEmitBatchArgs) writeField1(oprot thrift.TProtocol) (err error) { + if err := oprot.WriteFieldBegin("batch", thrift.STRUCT, 1); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write field begin error 1:batch: ", p), err) + } + if err := p.Batch.Write(oprot); err != nil { + return thrift.PrependError(fmt.Sprintf("%T error writing struct: ", p.Batch), err) + } + if err := oprot.WriteFieldEnd(); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write field end error 1:batch: ", p), err) + } + return err +} + +func (p *AgentEmitBatchArgs) String() string { + if p == nil { + return "" + } + return fmt.Sprintf("AgentEmitBatchArgs(%+v)", *p) +} diff --git a/vendor/github.com/uber/jaeger-client-go/thrift-gen/agent/constants.go b/vendor/github.com/uber/jaeger-client-go/thrift-gen/agent/constants.go new file mode 100644 index 000000000..369d016ea --- /dev/null +++ b/vendor/github.com/uber/jaeger-client-go/thrift-gen/agent/constants.go @@ -0,0 +1,21 @@ +// Autogenerated by Thrift Compiler (0.9.3) +// DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING + +package agent + +import ( + "bytes" + "fmt" + "github.com/apache/thrift/lib/go/thrift" + "github.com/uber/jaeger-client-go/thrift-gen/zipkincore" +) + +// (needed to ensure safety because of naive import list construction.) +var _ = thrift.ZERO +var _ = fmt.Printf +var _ = bytes.Equal + +var _ = zipkincore.GoUnusedProtection__ + +func init() { +} diff --git a/vendor/github.com/uber/jaeger-client-go/thrift-gen/agent/ttypes.go b/vendor/github.com/uber/jaeger-client-go/thrift-gen/agent/ttypes.go new file mode 100644 index 000000000..f377c2276 --- /dev/null +++ b/vendor/github.com/uber/jaeger-client-go/thrift-gen/agent/ttypes.go @@ -0,0 +1,19 @@ +// Autogenerated by Thrift Compiler (0.9.3) +// DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING + +package agent + +import ( + "bytes" + "fmt" + "github.com/apache/thrift/lib/go/thrift" + "github.com/uber/jaeger-client-go/thrift-gen/zipkincore" +) + +// (needed to ensure safety because of naive import list construction.) +var _ = thrift.ZERO +var _ = fmt.Printf +var _ = bytes.Equal + +var _ = zipkincore.GoUnusedProtection__ +var GoUnusedProtection__ int diff --git a/vendor/github.com/uber/jaeger-client-go/thrift-gen/jaeger/agent.go b/vendor/github.com/uber/jaeger-client-go/thrift-gen/jaeger/agent.go new file mode 100644 index 000000000..db6cac9fc --- /dev/null +++ b/vendor/github.com/uber/jaeger-client-go/thrift-gen/jaeger/agent.go @@ -0,0 +1,242 @@ +// Autogenerated by Thrift Compiler (0.9.3) +// DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING + +package jaeger + +import ( + "bytes" + "fmt" + "github.com/apache/thrift/lib/go/thrift" +) + +// (needed to ensure safety because of naive import list construction.) +var _ = thrift.ZERO +var _ = fmt.Printf +var _ = bytes.Equal + +type Agent interface { + // Parameters: + // - Batch + EmitBatch(batch *Batch) (err error) +} + +type AgentClient struct { + Transport thrift.TTransport + ProtocolFactory thrift.TProtocolFactory + InputProtocol thrift.TProtocol + OutputProtocol thrift.TProtocol + SeqId int32 +} + +func NewAgentClientFactory(t thrift.TTransport, f thrift.TProtocolFactory) *AgentClient { + return &AgentClient{Transport: t, + ProtocolFactory: f, + InputProtocol: f.GetProtocol(t), + OutputProtocol: f.GetProtocol(t), + SeqId: 0, + } +} + +func NewAgentClientProtocol(t thrift.TTransport, iprot thrift.TProtocol, oprot thrift.TProtocol) *AgentClient { + return &AgentClient{Transport: t, + ProtocolFactory: nil, + InputProtocol: iprot, + OutputProtocol: oprot, + SeqId: 0, + } +} + +// Parameters: +// - Batch +func (p *AgentClient) EmitBatch(batch *Batch) (err error) { + if err = p.sendEmitBatch(batch); err != nil { + return + } + return +} + +func (p *AgentClient) sendEmitBatch(batch *Batch) (err error) { + oprot := p.OutputProtocol + if oprot == nil { + oprot = p.ProtocolFactory.GetProtocol(p.Transport) + p.OutputProtocol = oprot + } + p.SeqId++ + if err = oprot.WriteMessageBegin("emitBatch", thrift.ONEWAY, p.SeqId); err != nil { + return + } + args := AgentEmitBatchArgs{ + Batch: batch, + } + if err = args.Write(oprot); err != nil { + return + } + if err = oprot.WriteMessageEnd(); err != nil { + return + } + return oprot.Flush() +} + +type AgentProcessor struct { + processorMap map[string]thrift.TProcessorFunction + handler Agent +} + +func (p *AgentProcessor) AddToProcessorMap(key string, processor thrift.TProcessorFunction) { + p.processorMap[key] = processor +} + +func (p *AgentProcessor) GetProcessorFunction(key string) (processor thrift.TProcessorFunction, ok bool) { + processor, ok = p.processorMap[key] + return processor, ok +} + +func (p *AgentProcessor) ProcessorMap() map[string]thrift.TProcessorFunction { + return p.processorMap +} + +func NewAgentProcessor(handler Agent) *AgentProcessor { + + self6 := &AgentProcessor{handler: handler, processorMap: make(map[string]thrift.TProcessorFunction)} + self6.processorMap["emitBatch"] = &agentProcessorEmitBatch{handler: handler} + return self6 +} + +func (p *AgentProcessor) Process(iprot, oprot thrift.TProtocol) (success bool, err thrift.TException) { + name, _, seqId, err := iprot.ReadMessageBegin() + if err != nil { + return false, err + } + if processor, ok := p.GetProcessorFunction(name); ok { + return processor.Process(seqId, iprot, oprot) + } + iprot.Skip(thrift.STRUCT) + iprot.ReadMessageEnd() + x7 := thrift.NewTApplicationException(thrift.UNKNOWN_METHOD, "Unknown function "+name) + oprot.WriteMessageBegin(name, thrift.EXCEPTION, seqId) + x7.Write(oprot) + oprot.WriteMessageEnd() + oprot.Flush() + return false, x7 + +} + +type agentProcessorEmitBatch struct { + handler Agent +} + +func (p *agentProcessorEmitBatch) Process(seqId int32, iprot, oprot thrift.TProtocol) (success bool, err thrift.TException) { + args := AgentEmitBatchArgs{} + if err = args.Read(iprot); err != nil { + iprot.ReadMessageEnd() + return false, err + } + + iprot.ReadMessageEnd() + var err2 error + if err2 = p.handler.EmitBatch(args.Batch); err2 != nil { + return true, err2 + } + return true, nil +} + +// HELPER FUNCTIONS AND STRUCTURES + +// Attributes: +// - Batch +type AgentEmitBatchArgs struct { + Batch *Batch `thrift:"batch,1" json:"batch"` +} + +func NewAgentEmitBatchArgs() *AgentEmitBatchArgs { + return &AgentEmitBatchArgs{} +} + +var AgentEmitBatchArgs_Batch_DEFAULT *Batch + +func (p *AgentEmitBatchArgs) GetBatch() *Batch { + if !p.IsSetBatch() { + return AgentEmitBatchArgs_Batch_DEFAULT + } + return p.Batch +} +func (p *AgentEmitBatchArgs) IsSetBatch() bool { + return p.Batch != nil +} + +func (p *AgentEmitBatchArgs) Read(iprot thrift.TProtocol) error { + if _, err := iprot.ReadStructBegin(); err != nil { + return thrift.PrependError(fmt.Sprintf("%T read error: ", p), err) + } + + for { + _, fieldTypeId, fieldId, err := iprot.ReadFieldBegin() + if err != nil { + return thrift.PrependError(fmt.Sprintf("%T field %d read error: ", p, fieldId), err) + } + if fieldTypeId == thrift.STOP { + break + } + switch fieldId { + case 1: + if err := p.readField1(iprot); err != nil { + return err + } + default: + if err := iprot.Skip(fieldTypeId); err != nil { + return err + } + } + if err := iprot.ReadFieldEnd(); err != nil { + return err + } + } + if err := iprot.ReadStructEnd(); err != nil { + return thrift.PrependError(fmt.Sprintf("%T read struct end error: ", p), err) + } + return nil +} + +func (p *AgentEmitBatchArgs) readField1(iprot thrift.TProtocol) error { + p.Batch = &Batch{} + if err := p.Batch.Read(iprot); err != nil { + return thrift.PrependError(fmt.Sprintf("%T error reading struct: ", p.Batch), err) + } + return nil +} + +func (p *AgentEmitBatchArgs) Write(oprot thrift.TProtocol) error { + if err := oprot.WriteStructBegin("emitBatch_args"); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write struct begin error: ", p), err) + } + if err := p.writeField1(oprot); err != nil { + return err + } + if err := oprot.WriteFieldStop(); err != nil { + return thrift.PrependError("write field stop error: ", err) + } + if err := oprot.WriteStructEnd(); err != nil { + return thrift.PrependError("write struct stop error: ", err) + } + return nil +} + +func (p *AgentEmitBatchArgs) writeField1(oprot thrift.TProtocol) (err error) { + if err := oprot.WriteFieldBegin("batch", thrift.STRUCT, 1); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write field begin error 1:batch: ", p), err) + } + if err := p.Batch.Write(oprot); err != nil { + return thrift.PrependError(fmt.Sprintf("%T error writing struct: ", p.Batch), err) + } + if err := oprot.WriteFieldEnd(); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write field end error 1:batch: ", p), err) + } + return err +} + +func (p *AgentEmitBatchArgs) String() string { + if p == nil { + return "" + } + return fmt.Sprintf("AgentEmitBatchArgs(%+v)", *p) +} diff --git a/vendor/github.com/uber/jaeger-client-go/thrift-gen/jaeger/constants.go b/vendor/github.com/uber/jaeger-client-go/thrift-gen/jaeger/constants.go new file mode 100644 index 000000000..250474222 --- /dev/null +++ b/vendor/github.com/uber/jaeger-client-go/thrift-gen/jaeger/constants.go @@ -0,0 +1,18 @@ +// Autogenerated by Thrift Compiler (0.9.3) +// DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING + +package jaeger + +import ( + "bytes" + "fmt" + "github.com/apache/thrift/lib/go/thrift" +) + +// (needed to ensure safety because of naive import list construction.) +var _ = thrift.ZERO +var _ = fmt.Printf +var _ = bytes.Equal + +func init() { +} diff --git a/vendor/github.com/uber/jaeger-client-go/thrift-gen/jaeger/ttypes.go b/vendor/github.com/uber/jaeger-client-go/thrift-gen/jaeger/ttypes.go new file mode 100644 index 000000000..b5ddfa645 --- /dev/null +++ b/vendor/github.com/uber/jaeger-client-go/thrift-gen/jaeger/ttypes.go @@ -0,0 +1,1838 @@ +// Autogenerated by Thrift Compiler (0.9.3) +// DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING + +package jaeger + +import ( + "bytes" + "fmt" + "github.com/apache/thrift/lib/go/thrift" +) + +// (needed to ensure safety because of naive import list construction.) +var _ = thrift.ZERO +var _ = fmt.Printf +var _ = bytes.Equal + +var GoUnusedProtection__ int + +type TagType int64 + +const ( + TagType_STRING TagType = 0 + TagType_DOUBLE TagType = 1 + TagType_BOOL TagType = 2 + TagType_LONG TagType = 3 + TagType_BINARY TagType = 4 +) + +func (p TagType) String() string { + switch p { + case TagType_STRING: + return "STRING" + case TagType_DOUBLE: + return "DOUBLE" + case TagType_BOOL: + return "BOOL" + case TagType_LONG: + return "LONG" + case TagType_BINARY: + return "BINARY" + } + return "" +} + +func TagTypeFromString(s string) (TagType, error) { + switch s { + case "STRING": + return TagType_STRING, nil + case "DOUBLE": + return TagType_DOUBLE, nil + case "BOOL": + return TagType_BOOL, nil + case "LONG": + return TagType_LONG, nil + case "BINARY": + return TagType_BINARY, nil + } + return TagType(0), fmt.Errorf("not a valid TagType string") +} + +func TagTypePtr(v TagType) *TagType { return &v } + +func (p TagType) MarshalText() ([]byte, error) { + return []byte(p.String()), nil +} + +func (p *TagType) UnmarshalText(text []byte) error { + q, err := TagTypeFromString(string(text)) + if err != nil { + return err + } + *p = q + return nil +} + +type SpanRefType int64 + +const ( + SpanRefType_CHILD_OF SpanRefType = 0 + SpanRefType_FOLLOWS_FROM SpanRefType = 1 +) + +func (p SpanRefType) String() string { + switch p { + case SpanRefType_CHILD_OF: + return "CHILD_OF" + case SpanRefType_FOLLOWS_FROM: + return "FOLLOWS_FROM" + } + return "" +} + +func SpanRefTypeFromString(s string) (SpanRefType, error) { + switch s { + case "CHILD_OF": + return SpanRefType_CHILD_OF, nil + case "FOLLOWS_FROM": + return SpanRefType_FOLLOWS_FROM, nil + } + return SpanRefType(0), fmt.Errorf("not a valid SpanRefType string") +} + +func SpanRefTypePtr(v SpanRefType) *SpanRefType { return &v } + +func (p SpanRefType) MarshalText() ([]byte, error) { + return []byte(p.String()), nil +} + +func (p *SpanRefType) UnmarshalText(text []byte) error { + q, err := SpanRefTypeFromString(string(text)) + if err != nil { + return err + } + *p = q + return nil +} + +// Attributes: +// - Key +// - VType +// - VStr +// - VDouble +// - VBool +// - VLong +// - VBinary +type Tag struct { + Key string `thrift:"key,1,required" json:"key"` + VType TagType `thrift:"vType,2,required" json:"vType"` + VStr *string `thrift:"vStr,3" json:"vStr,omitempty"` + VDouble *float64 `thrift:"vDouble,4" json:"vDouble,omitempty"` + VBool *bool `thrift:"vBool,5" json:"vBool,omitempty"` + VLong *int64 `thrift:"vLong,6" json:"vLong,omitempty"` + VBinary []byte `thrift:"vBinary,7" json:"vBinary,omitempty"` +} + +func NewTag() *Tag { + return &Tag{} +} + +func (p *Tag) GetKey() string { + return p.Key +} + +func (p *Tag) GetVType() TagType { + return p.VType +} + +var Tag_VStr_DEFAULT string + +func (p *Tag) GetVStr() string { + if !p.IsSetVStr() { + return Tag_VStr_DEFAULT + } + return *p.VStr +} + +var Tag_VDouble_DEFAULT float64 + +func (p *Tag) GetVDouble() float64 { + if !p.IsSetVDouble() { + return Tag_VDouble_DEFAULT + } + return *p.VDouble +} + +var Tag_VBool_DEFAULT bool + +func (p *Tag) GetVBool() bool { + if !p.IsSetVBool() { + return Tag_VBool_DEFAULT + } + return *p.VBool +} + +var Tag_VLong_DEFAULT int64 + +func (p *Tag) GetVLong() int64 { + if !p.IsSetVLong() { + return Tag_VLong_DEFAULT + } + return *p.VLong +} + +var Tag_VBinary_DEFAULT []byte + +func (p *Tag) GetVBinary() []byte { + return p.VBinary +} +func (p *Tag) IsSetVStr() bool { + return p.VStr != nil +} + +func (p *Tag) IsSetVDouble() bool { + return p.VDouble != nil +} + +func (p *Tag) IsSetVBool() bool { + return p.VBool != nil +} + +func (p *Tag) IsSetVLong() bool { + return p.VLong != nil +} + +func (p *Tag) IsSetVBinary() bool { + return p.VBinary != nil +} + +func (p *Tag) Read(iprot thrift.TProtocol) error { + if _, err := iprot.ReadStructBegin(); err != nil { + return thrift.PrependError(fmt.Sprintf("%T read error: ", p), err) + } + + var issetKey bool = false + var issetVType bool = false + + for { + _, fieldTypeId, fieldId, err := iprot.ReadFieldBegin() + if err != nil { + return thrift.PrependError(fmt.Sprintf("%T field %d read error: ", p, fieldId), err) + } + if fieldTypeId == thrift.STOP { + break + } + switch fieldId { + case 1: + if err := p.readField1(iprot); err != nil { + return err + } + issetKey = true + case 2: + if err := p.readField2(iprot); err != nil { + return err + } + issetVType = true + case 3: + if err := p.readField3(iprot); err != nil { + return err + } + case 4: + if err := p.readField4(iprot); err != nil { + return err + } + case 5: + if err := p.readField5(iprot); err != nil { + return err + } + case 6: + if err := p.readField6(iprot); err != nil { + return err + } + case 7: + if err := p.readField7(iprot); err != nil { + return err + } + default: + if err := iprot.Skip(fieldTypeId); err != nil { + return err + } + } + if err := iprot.ReadFieldEnd(); err != nil { + return err + } + } + if err := iprot.ReadStructEnd(); err != nil { + return thrift.PrependError(fmt.Sprintf("%T read struct end error: ", p), err) + } + if !issetKey { + return thrift.NewTProtocolExceptionWithType(thrift.INVALID_DATA, fmt.Errorf("Required field Key is not set")) + } + if !issetVType { + return thrift.NewTProtocolExceptionWithType(thrift.INVALID_DATA, fmt.Errorf("Required field VType is not set")) + } + return nil +} + +func (p *Tag) readField1(iprot thrift.TProtocol) error { + if v, err := iprot.ReadString(); err != nil { + return thrift.PrependError("error reading field 1: ", err) + } else { + p.Key = v + } + return nil +} + +func (p *Tag) readField2(iprot thrift.TProtocol) error { + if v, err := iprot.ReadI32(); err != nil { + return thrift.PrependError("error reading field 2: ", err) + } else { + temp := TagType(v) + p.VType = temp + } + return nil +} + +func (p *Tag) readField3(iprot thrift.TProtocol) error { + if v, err := iprot.ReadString(); err != nil { + return thrift.PrependError("error reading field 3: ", err) + } else { + p.VStr = &v + } + return nil +} + +func (p *Tag) readField4(iprot thrift.TProtocol) error { + if v, err := iprot.ReadDouble(); err != nil { + return thrift.PrependError("error reading field 4: ", err) + } else { + p.VDouble = &v + } + return nil +} + +func (p *Tag) readField5(iprot thrift.TProtocol) error { + if v, err := iprot.ReadBool(); err != nil { + return thrift.PrependError("error reading field 5: ", err) + } else { + p.VBool = &v + } + return nil +} + +func (p *Tag) readField6(iprot thrift.TProtocol) error { + if v, err := iprot.ReadI64(); err != nil { + return thrift.PrependError("error reading field 6: ", err) + } else { + p.VLong = &v + } + return nil +} + +func (p *Tag) readField7(iprot thrift.TProtocol) error { + if v, err := iprot.ReadBinary(); err != nil { + return thrift.PrependError("error reading field 7: ", err) + } else { + p.VBinary = v + } + return nil +} + +func (p *Tag) Write(oprot thrift.TProtocol) error { + if err := oprot.WriteStructBegin("Tag"); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write struct begin error: ", p), err) + } + if err := p.writeField1(oprot); err != nil { + return err + } + if err := p.writeField2(oprot); err != nil { + return err + } + if err := p.writeField3(oprot); err != nil { + return err + } + if err := p.writeField4(oprot); err != nil { + return err + } + if err := p.writeField5(oprot); err != nil { + return err + } + if err := p.writeField6(oprot); err != nil { + return err + } + if err := p.writeField7(oprot); err != nil { + return err + } + if err := oprot.WriteFieldStop(); err != nil { + return thrift.PrependError("write field stop error: ", err) + } + if err := oprot.WriteStructEnd(); err != nil { + return thrift.PrependError("write struct stop error: ", err) + } + return nil +} + +func (p *Tag) writeField1(oprot thrift.TProtocol) (err error) { + if err := oprot.WriteFieldBegin("key", thrift.STRING, 1); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write field begin error 1:key: ", p), err) + } + if err := oprot.WriteString(string(p.Key)); err != nil { + return thrift.PrependError(fmt.Sprintf("%T.key (1) field write error: ", p), err) + } + if err := oprot.WriteFieldEnd(); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write field end error 1:key: ", p), err) + } + return err +} + +func (p *Tag) writeField2(oprot thrift.TProtocol) (err error) { + if err := oprot.WriteFieldBegin("vType", thrift.I32, 2); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write field begin error 2:vType: ", p), err) + } + if err := oprot.WriteI32(int32(p.VType)); err != nil { + return thrift.PrependError(fmt.Sprintf("%T.vType (2) field write error: ", p), err) + } + if err := oprot.WriteFieldEnd(); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write field end error 2:vType: ", p), err) + } + return err +} + +func (p *Tag) writeField3(oprot thrift.TProtocol) (err error) { + if p.IsSetVStr() { + if err := oprot.WriteFieldBegin("vStr", thrift.STRING, 3); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write field begin error 3:vStr: ", p), err) + } + if err := oprot.WriteString(string(*p.VStr)); err != nil { + return thrift.PrependError(fmt.Sprintf("%T.vStr (3) field write error: ", p), err) + } + if err := oprot.WriteFieldEnd(); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write field end error 3:vStr: ", p), err) + } + } + return err +} + +func (p *Tag) writeField4(oprot thrift.TProtocol) (err error) { + if p.IsSetVDouble() { + if err := oprot.WriteFieldBegin("vDouble", thrift.DOUBLE, 4); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write field begin error 4:vDouble: ", p), err) + } + if err := oprot.WriteDouble(float64(*p.VDouble)); err != nil { + return thrift.PrependError(fmt.Sprintf("%T.vDouble (4) field write error: ", p), err) + } + if err := oprot.WriteFieldEnd(); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write field end error 4:vDouble: ", p), err) + } + } + return err +} + +func (p *Tag) writeField5(oprot thrift.TProtocol) (err error) { + if p.IsSetVBool() { + if err := oprot.WriteFieldBegin("vBool", thrift.BOOL, 5); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write field begin error 5:vBool: ", p), err) + } + if err := oprot.WriteBool(bool(*p.VBool)); err != nil { + return thrift.PrependError(fmt.Sprintf("%T.vBool (5) field write error: ", p), err) + } + if err := oprot.WriteFieldEnd(); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write field end error 5:vBool: ", p), err) + } + } + return err +} + +func (p *Tag) writeField6(oprot thrift.TProtocol) (err error) { + if p.IsSetVLong() { + if err := oprot.WriteFieldBegin("vLong", thrift.I64, 6); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write field begin error 6:vLong: ", p), err) + } + if err := oprot.WriteI64(int64(*p.VLong)); err != nil { + return thrift.PrependError(fmt.Sprintf("%T.vLong (6) field write error: ", p), err) + } + if err := oprot.WriteFieldEnd(); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write field end error 6:vLong: ", p), err) + } + } + return err +} + +func (p *Tag) writeField7(oprot thrift.TProtocol) (err error) { + if p.IsSetVBinary() { + if err := oprot.WriteFieldBegin("vBinary", thrift.STRING, 7); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write field begin error 7:vBinary: ", p), err) + } + if err := oprot.WriteBinary(p.VBinary); err != nil { + return thrift.PrependError(fmt.Sprintf("%T.vBinary (7) field write error: ", p), err) + } + if err := oprot.WriteFieldEnd(); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write field end error 7:vBinary: ", p), err) + } + } + return err +} + +func (p *Tag) String() string { + if p == nil { + return "" + } + return fmt.Sprintf("Tag(%+v)", *p) +} + +// Attributes: +// - Timestamp +// - Fields +type Log struct { + Timestamp int64 `thrift:"timestamp,1,required" json:"timestamp"` + Fields []*Tag `thrift:"fields,2,required" json:"fields"` +} + +func NewLog() *Log { + return &Log{} +} + +func (p *Log) GetTimestamp() int64 { + return p.Timestamp +} + +func (p *Log) GetFields() []*Tag { + return p.Fields +} +func (p *Log) Read(iprot thrift.TProtocol) error { + if _, err := iprot.ReadStructBegin(); err != nil { + return thrift.PrependError(fmt.Sprintf("%T read error: ", p), err) + } + + var issetTimestamp bool = false + var issetFields bool = false + + for { + _, fieldTypeId, fieldId, err := iprot.ReadFieldBegin() + if err != nil { + return thrift.PrependError(fmt.Sprintf("%T field %d read error: ", p, fieldId), err) + } + if fieldTypeId == thrift.STOP { + break + } + switch fieldId { + case 1: + if err := p.readField1(iprot); err != nil { + return err + } + issetTimestamp = true + case 2: + if err := p.readField2(iprot); err != nil { + return err + } + issetFields = true + default: + if err := iprot.Skip(fieldTypeId); err != nil { + return err + } + } + if err := iprot.ReadFieldEnd(); err != nil { + return err + } + } + if err := iprot.ReadStructEnd(); err != nil { + return thrift.PrependError(fmt.Sprintf("%T read struct end error: ", p), err) + } + if !issetTimestamp { + return thrift.NewTProtocolExceptionWithType(thrift.INVALID_DATA, fmt.Errorf("Required field Timestamp is not set")) + } + if !issetFields { + return thrift.NewTProtocolExceptionWithType(thrift.INVALID_DATA, fmt.Errorf("Required field Fields is not set")) + } + return nil +} + +func (p *Log) readField1(iprot thrift.TProtocol) error { + if v, err := iprot.ReadI64(); err != nil { + return thrift.PrependError("error reading field 1: ", err) + } else { + p.Timestamp = v + } + return nil +} + +func (p *Log) readField2(iprot thrift.TProtocol) error { + _, size, err := iprot.ReadListBegin() + if err != nil { + return thrift.PrependError("error reading list begin: ", err) + } + tSlice := make([]*Tag, 0, size) + p.Fields = tSlice + for i := 0; i < size; i++ { + _elem0 := &Tag{} + if err := _elem0.Read(iprot); err != nil { + return thrift.PrependError(fmt.Sprintf("%T error reading struct: ", _elem0), err) + } + p.Fields = append(p.Fields, _elem0) + } + if err := iprot.ReadListEnd(); err != nil { + return thrift.PrependError("error reading list end: ", err) + } + return nil +} + +func (p *Log) Write(oprot thrift.TProtocol) error { + if err := oprot.WriteStructBegin("Log"); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write struct begin error: ", p), err) + } + if err := p.writeField1(oprot); err != nil { + return err + } + if err := p.writeField2(oprot); err != nil { + return err + } + if err := oprot.WriteFieldStop(); err != nil { + return thrift.PrependError("write field stop error: ", err) + } + if err := oprot.WriteStructEnd(); err != nil { + return thrift.PrependError("write struct stop error: ", err) + } + return nil +} + +func (p *Log) writeField1(oprot thrift.TProtocol) (err error) { + if err := oprot.WriteFieldBegin("timestamp", thrift.I64, 1); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write field begin error 1:timestamp: ", p), err) + } + if err := oprot.WriteI64(int64(p.Timestamp)); err != nil { + return thrift.PrependError(fmt.Sprintf("%T.timestamp (1) field write error: ", p), err) + } + if err := oprot.WriteFieldEnd(); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write field end error 1:timestamp: ", p), err) + } + return err +} + +func (p *Log) writeField2(oprot thrift.TProtocol) (err error) { + if err := oprot.WriteFieldBegin("fields", thrift.LIST, 2); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write field begin error 2:fields: ", p), err) + } + if err := oprot.WriteListBegin(thrift.STRUCT, len(p.Fields)); err != nil { + return thrift.PrependError("error writing list begin: ", err) + } + for _, v := range p.Fields { + if err := v.Write(oprot); err != nil { + return thrift.PrependError(fmt.Sprintf("%T error writing struct: ", v), err) + } + } + if err := oprot.WriteListEnd(); err != nil { + return thrift.PrependError("error writing list end: ", err) + } + if err := oprot.WriteFieldEnd(); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write field end error 2:fields: ", p), err) + } + return err +} + +func (p *Log) String() string { + if p == nil { + return "" + } + return fmt.Sprintf("Log(%+v)", *p) +} + +// Attributes: +// - RefType +// - TraceIdLow +// - TraceIdHigh +// - SpanId +type SpanRef struct { + RefType SpanRefType `thrift:"refType,1,required" json:"refType"` + TraceIdLow int64 `thrift:"traceIdLow,2,required" json:"traceIdLow"` + TraceIdHigh int64 `thrift:"traceIdHigh,3,required" json:"traceIdHigh"` + SpanId int64 `thrift:"spanId,4,required" json:"spanId"` +} + +func NewSpanRef() *SpanRef { + return &SpanRef{} +} + +func (p *SpanRef) GetRefType() SpanRefType { + return p.RefType +} + +func (p *SpanRef) GetTraceIdLow() int64 { + return p.TraceIdLow +} + +func (p *SpanRef) GetTraceIdHigh() int64 { + return p.TraceIdHigh +} + +func (p *SpanRef) GetSpanId() int64 { + return p.SpanId +} +func (p *SpanRef) Read(iprot thrift.TProtocol) error { + if _, err := iprot.ReadStructBegin(); err != nil { + return thrift.PrependError(fmt.Sprintf("%T read error: ", p), err) + } + + var issetRefType bool = false + var issetTraceIdLow bool = false + var issetTraceIdHigh bool = false + var issetSpanId bool = false + + for { + _, fieldTypeId, fieldId, err := iprot.ReadFieldBegin() + if err != nil { + return thrift.PrependError(fmt.Sprintf("%T field %d read error: ", p, fieldId), err) + } + if fieldTypeId == thrift.STOP { + break + } + switch fieldId { + case 1: + if err := p.readField1(iprot); err != nil { + return err + } + issetRefType = true + case 2: + if err := p.readField2(iprot); err != nil { + return err + } + issetTraceIdLow = true + case 3: + if err := p.readField3(iprot); err != nil { + return err + } + issetTraceIdHigh = true + case 4: + if err := p.readField4(iprot); err != nil { + return err + } + issetSpanId = true + default: + if err := iprot.Skip(fieldTypeId); err != nil { + return err + } + } + if err := iprot.ReadFieldEnd(); err != nil { + return err + } + } + if err := iprot.ReadStructEnd(); err != nil { + return thrift.PrependError(fmt.Sprintf("%T read struct end error: ", p), err) + } + if !issetRefType { + return thrift.NewTProtocolExceptionWithType(thrift.INVALID_DATA, fmt.Errorf("Required field RefType is not set")) + } + if !issetTraceIdLow { + return thrift.NewTProtocolExceptionWithType(thrift.INVALID_DATA, fmt.Errorf("Required field TraceIdLow is not set")) + } + if !issetTraceIdHigh { + return thrift.NewTProtocolExceptionWithType(thrift.INVALID_DATA, fmt.Errorf("Required field TraceIdHigh is not set")) + } + if !issetSpanId { + return thrift.NewTProtocolExceptionWithType(thrift.INVALID_DATA, fmt.Errorf("Required field SpanId is not set")) + } + return nil +} + +func (p *SpanRef) readField1(iprot thrift.TProtocol) error { + if v, err := iprot.ReadI32(); err != nil { + return thrift.PrependError("error reading field 1: ", err) + } else { + temp := SpanRefType(v) + p.RefType = temp + } + return nil +} + +func (p *SpanRef) readField2(iprot thrift.TProtocol) error { + if v, err := iprot.ReadI64(); err != nil { + return thrift.PrependError("error reading field 2: ", err) + } else { + p.TraceIdLow = v + } + return nil +} + +func (p *SpanRef) readField3(iprot thrift.TProtocol) error { + if v, err := iprot.ReadI64(); err != nil { + return thrift.PrependError("error reading field 3: ", err) + } else { + p.TraceIdHigh = v + } + return nil +} + +func (p *SpanRef) readField4(iprot thrift.TProtocol) error { + if v, err := iprot.ReadI64(); err != nil { + return thrift.PrependError("error reading field 4: ", err) + } else { + p.SpanId = v + } + return nil +} + +func (p *SpanRef) Write(oprot thrift.TProtocol) error { + if err := oprot.WriteStructBegin("SpanRef"); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write struct begin error: ", p), err) + } + if err := p.writeField1(oprot); err != nil { + return err + } + if err := p.writeField2(oprot); err != nil { + return err + } + if err := p.writeField3(oprot); err != nil { + return err + } + if err := p.writeField4(oprot); err != nil { + return err + } + if err := oprot.WriteFieldStop(); err != nil { + return thrift.PrependError("write field stop error: ", err) + } + if err := oprot.WriteStructEnd(); err != nil { + return thrift.PrependError("write struct stop error: ", err) + } + return nil +} + +func (p *SpanRef) writeField1(oprot thrift.TProtocol) (err error) { + if err := oprot.WriteFieldBegin("refType", thrift.I32, 1); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write field begin error 1:refType: ", p), err) + } + if err := oprot.WriteI32(int32(p.RefType)); err != nil { + return thrift.PrependError(fmt.Sprintf("%T.refType (1) field write error: ", p), err) + } + if err := oprot.WriteFieldEnd(); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write field end error 1:refType: ", p), err) + } + return err +} + +func (p *SpanRef) writeField2(oprot thrift.TProtocol) (err error) { + if err := oprot.WriteFieldBegin("traceIdLow", thrift.I64, 2); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write field begin error 2:traceIdLow: ", p), err) + } + if err := oprot.WriteI64(int64(p.TraceIdLow)); err != nil { + return thrift.PrependError(fmt.Sprintf("%T.traceIdLow (2) field write error: ", p), err) + } + if err := oprot.WriteFieldEnd(); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write field end error 2:traceIdLow: ", p), err) + } + return err +} + +func (p *SpanRef) writeField3(oprot thrift.TProtocol) (err error) { + if err := oprot.WriteFieldBegin("traceIdHigh", thrift.I64, 3); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write field begin error 3:traceIdHigh: ", p), err) + } + if err := oprot.WriteI64(int64(p.TraceIdHigh)); err != nil { + return thrift.PrependError(fmt.Sprintf("%T.traceIdHigh (3) field write error: ", p), err) + } + if err := oprot.WriteFieldEnd(); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write field end error 3:traceIdHigh: ", p), err) + } + return err +} + +func (p *SpanRef) writeField4(oprot thrift.TProtocol) (err error) { + if err := oprot.WriteFieldBegin("spanId", thrift.I64, 4); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write field begin error 4:spanId: ", p), err) + } + if err := oprot.WriteI64(int64(p.SpanId)); err != nil { + return thrift.PrependError(fmt.Sprintf("%T.spanId (4) field write error: ", p), err) + } + if err := oprot.WriteFieldEnd(); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write field end error 4:spanId: ", p), err) + } + return err +} + +func (p *SpanRef) String() string { + if p == nil { + return "" + } + return fmt.Sprintf("SpanRef(%+v)", *p) +} + +// Attributes: +// - TraceIdLow +// - TraceIdHigh +// - SpanId +// - ParentSpanId +// - OperationName +// - References +// - Flags +// - StartTime +// - Duration +// - Tags +// - Logs +type Span struct { + TraceIdLow int64 `thrift:"traceIdLow,1,required" json:"traceIdLow"` + TraceIdHigh int64 `thrift:"traceIdHigh,2,required" json:"traceIdHigh"` + SpanId int64 `thrift:"spanId,3,required" json:"spanId"` + ParentSpanId int64 `thrift:"parentSpanId,4,required" json:"parentSpanId"` + OperationName string `thrift:"operationName,5,required" json:"operationName"` + References []*SpanRef `thrift:"references,6" json:"references,omitempty"` + Flags int32 `thrift:"flags,7,required" json:"flags"` + StartTime int64 `thrift:"startTime,8,required" json:"startTime"` + Duration int64 `thrift:"duration,9,required" json:"duration"` + Tags []*Tag `thrift:"tags,10" json:"tags,omitempty"` + Logs []*Log `thrift:"logs,11" json:"logs,omitempty"` +} + +func NewSpan() *Span { + return &Span{} +} + +func (p *Span) GetTraceIdLow() int64 { + return p.TraceIdLow +} + +func (p *Span) GetTraceIdHigh() int64 { + return p.TraceIdHigh +} + +func (p *Span) GetSpanId() int64 { + return p.SpanId +} + +func (p *Span) GetParentSpanId() int64 { + return p.ParentSpanId +} + +func (p *Span) GetOperationName() string { + return p.OperationName +} + +var Span_References_DEFAULT []*SpanRef + +func (p *Span) GetReferences() []*SpanRef { + return p.References +} + +func (p *Span) GetFlags() int32 { + return p.Flags +} + +func (p *Span) GetStartTime() int64 { + return p.StartTime +} + +func (p *Span) GetDuration() int64 { + return p.Duration +} + +var Span_Tags_DEFAULT []*Tag + +func (p *Span) GetTags() []*Tag { + return p.Tags +} + +var Span_Logs_DEFAULT []*Log + +func (p *Span) GetLogs() []*Log { + return p.Logs +} +func (p *Span) IsSetReferences() bool { + return p.References != nil +} + +func (p *Span) IsSetTags() bool { + return p.Tags != nil +} + +func (p *Span) IsSetLogs() bool { + return p.Logs != nil +} + +func (p *Span) Read(iprot thrift.TProtocol) error { + if _, err := iprot.ReadStructBegin(); err != nil { + return thrift.PrependError(fmt.Sprintf("%T read error: ", p), err) + } + + var issetTraceIdLow bool = false + var issetTraceIdHigh bool = false + var issetSpanId bool = false + var issetParentSpanId bool = false + var issetOperationName bool = false + var issetFlags bool = false + var issetStartTime bool = false + var issetDuration bool = false + + for { + _, fieldTypeId, fieldId, err := iprot.ReadFieldBegin() + if err != nil { + return thrift.PrependError(fmt.Sprintf("%T field %d read error: ", p, fieldId), err) + } + if fieldTypeId == thrift.STOP { + break + } + switch fieldId { + case 1: + if err := p.readField1(iprot); err != nil { + return err + } + issetTraceIdLow = true + case 2: + if err := p.readField2(iprot); err != nil { + return err + } + issetTraceIdHigh = true + case 3: + if err := p.readField3(iprot); err != nil { + return err + } + issetSpanId = true + case 4: + if err := p.readField4(iprot); err != nil { + return err + } + issetParentSpanId = true + case 5: + if err := p.readField5(iprot); err != nil { + return err + } + issetOperationName = true + case 6: + if err := p.readField6(iprot); err != nil { + return err + } + case 7: + if err := p.readField7(iprot); err != nil { + return err + } + issetFlags = true + case 8: + if err := p.readField8(iprot); err != nil { + return err + } + issetStartTime = true + case 9: + if err := p.readField9(iprot); err != nil { + return err + } + issetDuration = true + case 10: + if err := p.readField10(iprot); err != nil { + return err + } + case 11: + if err := p.readField11(iprot); err != nil { + return err + } + default: + if err := iprot.Skip(fieldTypeId); err != nil { + return err + } + } + if err := iprot.ReadFieldEnd(); err != nil { + return err + } + } + if err := iprot.ReadStructEnd(); err != nil { + return thrift.PrependError(fmt.Sprintf("%T read struct end error: ", p), err) + } + if !issetTraceIdLow { + return thrift.NewTProtocolExceptionWithType(thrift.INVALID_DATA, fmt.Errorf("Required field TraceIdLow is not set")) + } + if !issetTraceIdHigh { + return thrift.NewTProtocolExceptionWithType(thrift.INVALID_DATA, fmt.Errorf("Required field TraceIdHigh is not set")) + } + if !issetSpanId { + return thrift.NewTProtocolExceptionWithType(thrift.INVALID_DATA, fmt.Errorf("Required field SpanId is not set")) + } + if !issetParentSpanId { + return thrift.NewTProtocolExceptionWithType(thrift.INVALID_DATA, fmt.Errorf("Required field ParentSpanId is not set")) + } + if !issetOperationName { + return thrift.NewTProtocolExceptionWithType(thrift.INVALID_DATA, fmt.Errorf("Required field OperationName is not set")) + } + if !issetFlags { + return thrift.NewTProtocolExceptionWithType(thrift.INVALID_DATA, fmt.Errorf("Required field Flags is not set")) + } + if !issetStartTime { + return thrift.NewTProtocolExceptionWithType(thrift.INVALID_DATA, fmt.Errorf("Required field StartTime is not set")) + } + if !issetDuration { + return thrift.NewTProtocolExceptionWithType(thrift.INVALID_DATA, fmt.Errorf("Required field Duration is not set")) + } + return nil +} + +func (p *Span) readField1(iprot thrift.TProtocol) error { + if v, err := iprot.ReadI64(); err != nil { + return thrift.PrependError("error reading field 1: ", err) + } else { + p.TraceIdLow = v + } + return nil +} + +func (p *Span) readField2(iprot thrift.TProtocol) error { + if v, err := iprot.ReadI64(); err != nil { + return thrift.PrependError("error reading field 2: ", err) + } else { + p.TraceIdHigh = v + } + return nil +} + +func (p *Span) readField3(iprot thrift.TProtocol) error { + if v, err := iprot.ReadI64(); err != nil { + return thrift.PrependError("error reading field 3: ", err) + } else { + p.SpanId = v + } + return nil +} + +func (p *Span) readField4(iprot thrift.TProtocol) error { + if v, err := iprot.ReadI64(); err != nil { + return thrift.PrependError("error reading field 4: ", err) + } else { + p.ParentSpanId = v + } + return nil +} + +func (p *Span) readField5(iprot thrift.TProtocol) error { + if v, err := iprot.ReadString(); err != nil { + return thrift.PrependError("error reading field 5: ", err) + } else { + p.OperationName = v + } + return nil +} + +func (p *Span) readField6(iprot thrift.TProtocol) error { + _, size, err := iprot.ReadListBegin() + if err != nil { + return thrift.PrependError("error reading list begin: ", err) + } + tSlice := make([]*SpanRef, 0, size) + p.References = tSlice + for i := 0; i < size; i++ { + _elem1 := &SpanRef{} + if err := _elem1.Read(iprot); err != nil { + return thrift.PrependError(fmt.Sprintf("%T error reading struct: ", _elem1), err) + } + p.References = append(p.References, _elem1) + } + if err := iprot.ReadListEnd(); err != nil { + return thrift.PrependError("error reading list end: ", err) + } + return nil +} + +func (p *Span) readField7(iprot thrift.TProtocol) error { + if v, err := iprot.ReadI32(); err != nil { + return thrift.PrependError("error reading field 7: ", err) + } else { + p.Flags = v + } + return nil +} + +func (p *Span) readField8(iprot thrift.TProtocol) error { + if v, err := iprot.ReadI64(); err != nil { + return thrift.PrependError("error reading field 8: ", err) + } else { + p.StartTime = v + } + return nil +} + +func (p *Span) readField9(iprot thrift.TProtocol) error { + if v, err := iprot.ReadI64(); err != nil { + return thrift.PrependError("error reading field 9: ", err) + } else { + p.Duration = v + } + return nil +} + +func (p *Span) readField10(iprot thrift.TProtocol) error { + _, size, err := iprot.ReadListBegin() + if err != nil { + return thrift.PrependError("error reading list begin: ", err) + } + tSlice := make([]*Tag, 0, size) + p.Tags = tSlice + for i := 0; i < size; i++ { + _elem2 := &Tag{} + if err := _elem2.Read(iprot); err != nil { + return thrift.PrependError(fmt.Sprintf("%T error reading struct: ", _elem2), err) + } + p.Tags = append(p.Tags, _elem2) + } + if err := iprot.ReadListEnd(); err != nil { + return thrift.PrependError("error reading list end: ", err) + } + return nil +} + +func (p *Span) readField11(iprot thrift.TProtocol) error { + _, size, err := iprot.ReadListBegin() + if err != nil { + return thrift.PrependError("error reading list begin: ", err) + } + tSlice := make([]*Log, 0, size) + p.Logs = tSlice + for i := 0; i < size; i++ { + _elem3 := &Log{} + if err := _elem3.Read(iprot); err != nil { + return thrift.PrependError(fmt.Sprintf("%T error reading struct: ", _elem3), err) + } + p.Logs = append(p.Logs, _elem3) + } + if err := iprot.ReadListEnd(); err != nil { + return thrift.PrependError("error reading list end: ", err) + } + return nil +} + +func (p *Span) Write(oprot thrift.TProtocol) error { + if err := oprot.WriteStructBegin("Span"); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write struct begin error: ", p), err) + } + if err := p.writeField1(oprot); err != nil { + return err + } + if err := p.writeField2(oprot); err != nil { + return err + } + if err := p.writeField3(oprot); err != nil { + return err + } + if err := p.writeField4(oprot); err != nil { + return err + } + if err := p.writeField5(oprot); err != nil { + return err + } + if err := p.writeField6(oprot); err != nil { + return err + } + if err := p.writeField7(oprot); err != nil { + return err + } + if err := p.writeField8(oprot); err != nil { + return err + } + if err := p.writeField9(oprot); err != nil { + return err + } + if err := p.writeField10(oprot); err != nil { + return err + } + if err := p.writeField11(oprot); err != nil { + return err + } + if err := oprot.WriteFieldStop(); err != nil { + return thrift.PrependError("write field stop error: ", err) + } + if err := oprot.WriteStructEnd(); err != nil { + return thrift.PrependError("write struct stop error: ", err) + } + return nil +} + +func (p *Span) writeField1(oprot thrift.TProtocol) (err error) { + if err := oprot.WriteFieldBegin("traceIdLow", thrift.I64, 1); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write field begin error 1:traceIdLow: ", p), err) + } + if err := oprot.WriteI64(int64(p.TraceIdLow)); err != nil { + return thrift.PrependError(fmt.Sprintf("%T.traceIdLow (1) field write error: ", p), err) + } + if err := oprot.WriteFieldEnd(); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write field end error 1:traceIdLow: ", p), err) + } + return err +} + +func (p *Span) writeField2(oprot thrift.TProtocol) (err error) { + if err := oprot.WriteFieldBegin("traceIdHigh", thrift.I64, 2); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write field begin error 2:traceIdHigh: ", p), err) + } + if err := oprot.WriteI64(int64(p.TraceIdHigh)); err != nil { + return thrift.PrependError(fmt.Sprintf("%T.traceIdHigh (2) field write error: ", p), err) + } + if err := oprot.WriteFieldEnd(); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write field end error 2:traceIdHigh: ", p), err) + } + return err +} + +func (p *Span) writeField3(oprot thrift.TProtocol) (err error) { + if err := oprot.WriteFieldBegin("spanId", thrift.I64, 3); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write field begin error 3:spanId: ", p), err) + } + if err := oprot.WriteI64(int64(p.SpanId)); err != nil { + return thrift.PrependError(fmt.Sprintf("%T.spanId (3) field write error: ", p), err) + } + if err := oprot.WriteFieldEnd(); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write field end error 3:spanId: ", p), err) + } + return err +} + +func (p *Span) writeField4(oprot thrift.TProtocol) (err error) { + if err := oprot.WriteFieldBegin("parentSpanId", thrift.I64, 4); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write field begin error 4:parentSpanId: ", p), err) + } + if err := oprot.WriteI64(int64(p.ParentSpanId)); err != nil { + return thrift.PrependError(fmt.Sprintf("%T.parentSpanId (4) field write error: ", p), err) + } + if err := oprot.WriteFieldEnd(); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write field end error 4:parentSpanId: ", p), err) + } + return err +} + +func (p *Span) writeField5(oprot thrift.TProtocol) (err error) { + if err := oprot.WriteFieldBegin("operationName", thrift.STRING, 5); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write field begin error 5:operationName: ", p), err) + } + if err := oprot.WriteString(string(p.OperationName)); err != nil { + return thrift.PrependError(fmt.Sprintf("%T.operationName (5) field write error: ", p), err) + } + if err := oprot.WriteFieldEnd(); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write field end error 5:operationName: ", p), err) + } + return err +} + +func (p *Span) writeField6(oprot thrift.TProtocol) (err error) { + if p.IsSetReferences() { + if err := oprot.WriteFieldBegin("references", thrift.LIST, 6); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write field begin error 6:references: ", p), err) + } + if err := oprot.WriteListBegin(thrift.STRUCT, len(p.References)); err != nil { + return thrift.PrependError("error writing list begin: ", err) + } + for _, v := range p.References { + if err := v.Write(oprot); err != nil { + return thrift.PrependError(fmt.Sprintf("%T error writing struct: ", v), err) + } + } + if err := oprot.WriteListEnd(); err != nil { + return thrift.PrependError("error writing list end: ", err) + } + if err := oprot.WriteFieldEnd(); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write field end error 6:references: ", p), err) + } + } + return err +} + +func (p *Span) writeField7(oprot thrift.TProtocol) (err error) { + if err := oprot.WriteFieldBegin("flags", thrift.I32, 7); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write field begin error 7:flags: ", p), err) + } + if err := oprot.WriteI32(int32(p.Flags)); err != nil { + return thrift.PrependError(fmt.Sprintf("%T.flags (7) field write error: ", p), err) + } + if err := oprot.WriteFieldEnd(); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write field end error 7:flags: ", p), err) + } + return err +} + +func (p *Span) writeField8(oprot thrift.TProtocol) (err error) { + if err := oprot.WriteFieldBegin("startTime", thrift.I64, 8); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write field begin error 8:startTime: ", p), err) + } + if err := oprot.WriteI64(int64(p.StartTime)); err != nil { + return thrift.PrependError(fmt.Sprintf("%T.startTime (8) field write error: ", p), err) + } + if err := oprot.WriteFieldEnd(); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write field end error 8:startTime: ", p), err) + } + return err +} + +func (p *Span) writeField9(oprot thrift.TProtocol) (err error) { + if err := oprot.WriteFieldBegin("duration", thrift.I64, 9); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write field begin error 9:duration: ", p), err) + } + if err := oprot.WriteI64(int64(p.Duration)); err != nil { + return thrift.PrependError(fmt.Sprintf("%T.duration (9) field write error: ", p), err) + } + if err := oprot.WriteFieldEnd(); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write field end error 9:duration: ", p), err) + } + return err +} + +func (p *Span) writeField10(oprot thrift.TProtocol) (err error) { + if p.IsSetTags() { + if err := oprot.WriteFieldBegin("tags", thrift.LIST, 10); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write field begin error 10:tags: ", p), err) + } + if err := oprot.WriteListBegin(thrift.STRUCT, len(p.Tags)); err != nil { + return thrift.PrependError("error writing list begin: ", err) + } + for _, v := range p.Tags { + if err := v.Write(oprot); err != nil { + return thrift.PrependError(fmt.Sprintf("%T error writing struct: ", v), err) + } + } + if err := oprot.WriteListEnd(); err != nil { + return thrift.PrependError("error writing list end: ", err) + } + if err := oprot.WriteFieldEnd(); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write field end error 10:tags: ", p), err) + } + } + return err +} + +func (p *Span) writeField11(oprot thrift.TProtocol) (err error) { + if p.IsSetLogs() { + if err := oprot.WriteFieldBegin("logs", thrift.LIST, 11); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write field begin error 11:logs: ", p), err) + } + if err := oprot.WriteListBegin(thrift.STRUCT, len(p.Logs)); err != nil { + return thrift.PrependError("error writing list begin: ", err) + } + for _, v := range p.Logs { + if err := v.Write(oprot); err != nil { + return thrift.PrependError(fmt.Sprintf("%T error writing struct: ", v), err) + } + } + if err := oprot.WriteListEnd(); err != nil { + return thrift.PrependError("error writing list end: ", err) + } + if err := oprot.WriteFieldEnd(); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write field end error 11:logs: ", p), err) + } + } + return err +} + +func (p *Span) String() string { + if p == nil { + return "" + } + return fmt.Sprintf("Span(%+v)", *p) +} + +// Attributes: +// - ServiceName +// - Tags +type Process struct { + ServiceName string `thrift:"serviceName,1,required" json:"serviceName"` + Tags []*Tag `thrift:"tags,2" json:"tags,omitempty"` +} + +func NewProcess() *Process { + return &Process{} +} + +func (p *Process) GetServiceName() string { + return p.ServiceName +} + +var Process_Tags_DEFAULT []*Tag + +func (p *Process) GetTags() []*Tag { + return p.Tags +} +func (p *Process) IsSetTags() bool { + return p.Tags != nil +} + +func (p *Process) Read(iprot thrift.TProtocol) error { + if _, err := iprot.ReadStructBegin(); err != nil { + return thrift.PrependError(fmt.Sprintf("%T read error: ", p), err) + } + + var issetServiceName bool = false + + for { + _, fieldTypeId, fieldId, err := iprot.ReadFieldBegin() + if err != nil { + return thrift.PrependError(fmt.Sprintf("%T field %d read error: ", p, fieldId), err) + } + if fieldTypeId == thrift.STOP { + break + } + switch fieldId { + case 1: + if err := p.readField1(iprot); err != nil { + return err + } + issetServiceName = true + case 2: + if err := p.readField2(iprot); err != nil { + return err + } + default: + if err := iprot.Skip(fieldTypeId); err != nil { + return err + } + } + if err := iprot.ReadFieldEnd(); err != nil { + return err + } + } + if err := iprot.ReadStructEnd(); err != nil { + return thrift.PrependError(fmt.Sprintf("%T read struct end error: ", p), err) + } + if !issetServiceName { + return thrift.NewTProtocolExceptionWithType(thrift.INVALID_DATA, fmt.Errorf("Required field ServiceName is not set")) + } + return nil +} + +func (p *Process) readField1(iprot thrift.TProtocol) error { + if v, err := iprot.ReadString(); err != nil { + return thrift.PrependError("error reading field 1: ", err) + } else { + p.ServiceName = v + } + return nil +} + +func (p *Process) readField2(iprot thrift.TProtocol) error { + _, size, err := iprot.ReadListBegin() + if err != nil { + return thrift.PrependError("error reading list begin: ", err) + } + tSlice := make([]*Tag, 0, size) + p.Tags = tSlice + for i := 0; i < size; i++ { + _elem4 := &Tag{} + if err := _elem4.Read(iprot); err != nil { + return thrift.PrependError(fmt.Sprintf("%T error reading struct: ", _elem4), err) + } + p.Tags = append(p.Tags, _elem4) + } + if err := iprot.ReadListEnd(); err != nil { + return thrift.PrependError("error reading list end: ", err) + } + return nil +} + +func (p *Process) Write(oprot thrift.TProtocol) error { + if err := oprot.WriteStructBegin("Process"); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write struct begin error: ", p), err) + } + if err := p.writeField1(oprot); err != nil { + return err + } + if err := p.writeField2(oprot); err != nil { + return err + } + if err := oprot.WriteFieldStop(); err != nil { + return thrift.PrependError("write field stop error: ", err) + } + if err := oprot.WriteStructEnd(); err != nil { + return thrift.PrependError("write struct stop error: ", err) + } + return nil +} + +func (p *Process) writeField1(oprot thrift.TProtocol) (err error) { + if err := oprot.WriteFieldBegin("serviceName", thrift.STRING, 1); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write field begin error 1:serviceName: ", p), err) + } + if err := oprot.WriteString(string(p.ServiceName)); err != nil { + return thrift.PrependError(fmt.Sprintf("%T.serviceName (1) field write error: ", p), err) + } + if err := oprot.WriteFieldEnd(); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write field end error 1:serviceName: ", p), err) + } + return err +} + +func (p *Process) writeField2(oprot thrift.TProtocol) (err error) { + if p.IsSetTags() { + if err := oprot.WriteFieldBegin("tags", thrift.LIST, 2); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write field begin error 2:tags: ", p), err) + } + if err := oprot.WriteListBegin(thrift.STRUCT, len(p.Tags)); err != nil { + return thrift.PrependError("error writing list begin: ", err) + } + for _, v := range p.Tags { + if err := v.Write(oprot); err != nil { + return thrift.PrependError(fmt.Sprintf("%T error writing struct: ", v), err) + } + } + if err := oprot.WriteListEnd(); err != nil { + return thrift.PrependError("error writing list end: ", err) + } + if err := oprot.WriteFieldEnd(); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write field end error 2:tags: ", p), err) + } + } + return err +} + +func (p *Process) String() string { + if p == nil { + return "" + } + return fmt.Sprintf("Process(%+v)", *p) +} + +// Attributes: +// - Process +// - Spans +type Batch struct { + Process *Process `thrift:"process,1,required" json:"process"` + Spans []*Span `thrift:"spans,2,required" json:"spans"` +} + +func NewBatch() *Batch { + return &Batch{} +} + +var Batch_Process_DEFAULT *Process + +func (p *Batch) GetProcess() *Process { + if !p.IsSetProcess() { + return Batch_Process_DEFAULT + } + return p.Process +} + +func (p *Batch) GetSpans() []*Span { + return p.Spans +} +func (p *Batch) IsSetProcess() bool { + return p.Process != nil +} + +func (p *Batch) Read(iprot thrift.TProtocol) error { + if _, err := iprot.ReadStructBegin(); err != nil { + return thrift.PrependError(fmt.Sprintf("%T read error: ", p), err) + } + + var issetProcess bool = false + var issetSpans bool = false + + for { + _, fieldTypeId, fieldId, err := iprot.ReadFieldBegin() + if err != nil { + return thrift.PrependError(fmt.Sprintf("%T field %d read error: ", p, fieldId), err) + } + if fieldTypeId == thrift.STOP { + break + } + switch fieldId { + case 1: + if err := p.readField1(iprot); err != nil { + return err + } + issetProcess = true + case 2: + if err := p.readField2(iprot); err != nil { + return err + } + issetSpans = true + default: + if err := iprot.Skip(fieldTypeId); err != nil { + return err + } + } + if err := iprot.ReadFieldEnd(); err != nil { + return err + } + } + if err := iprot.ReadStructEnd(); err != nil { + return thrift.PrependError(fmt.Sprintf("%T read struct end error: ", p), err) + } + if !issetProcess { + return thrift.NewTProtocolExceptionWithType(thrift.INVALID_DATA, fmt.Errorf("Required field Process is not set")) + } + if !issetSpans { + return thrift.NewTProtocolExceptionWithType(thrift.INVALID_DATA, fmt.Errorf("Required field Spans is not set")) + } + return nil +} + +func (p *Batch) readField1(iprot thrift.TProtocol) error { + p.Process = &Process{} + if err := p.Process.Read(iprot); err != nil { + return thrift.PrependError(fmt.Sprintf("%T error reading struct: ", p.Process), err) + } + return nil +} + +func (p *Batch) readField2(iprot thrift.TProtocol) error { + _, size, err := iprot.ReadListBegin() + if err != nil { + return thrift.PrependError("error reading list begin: ", err) + } + tSlice := make([]*Span, 0, size) + p.Spans = tSlice + for i := 0; i < size; i++ { + _elem5 := &Span{} + if err := _elem5.Read(iprot); err != nil { + return thrift.PrependError(fmt.Sprintf("%T error reading struct: ", _elem5), err) + } + p.Spans = append(p.Spans, _elem5) + } + if err := iprot.ReadListEnd(); err != nil { + return thrift.PrependError("error reading list end: ", err) + } + return nil +} + +func (p *Batch) Write(oprot thrift.TProtocol) error { + if err := oprot.WriteStructBegin("Batch"); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write struct begin error: ", p), err) + } + if err := p.writeField1(oprot); err != nil { + return err + } + if err := p.writeField2(oprot); err != nil { + return err + } + if err := oprot.WriteFieldStop(); err != nil { + return thrift.PrependError("write field stop error: ", err) + } + if err := oprot.WriteStructEnd(); err != nil { + return thrift.PrependError("write struct stop error: ", err) + } + return nil +} + +func (p *Batch) writeField1(oprot thrift.TProtocol) (err error) { + if err := oprot.WriteFieldBegin("process", thrift.STRUCT, 1); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write field begin error 1:process: ", p), err) + } + if err := p.Process.Write(oprot); err != nil { + return thrift.PrependError(fmt.Sprintf("%T error writing struct: ", p.Process), err) + } + if err := oprot.WriteFieldEnd(); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write field end error 1:process: ", p), err) + } + return err +} + +func (p *Batch) writeField2(oprot thrift.TProtocol) (err error) { + if err := oprot.WriteFieldBegin("spans", thrift.LIST, 2); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write field begin error 2:spans: ", p), err) + } + if err := oprot.WriteListBegin(thrift.STRUCT, len(p.Spans)); err != nil { + return thrift.PrependError("error writing list begin: ", err) + } + for _, v := range p.Spans { + if err := v.Write(oprot); err != nil { + return thrift.PrependError(fmt.Sprintf("%T error writing struct: ", v), err) + } + } + if err := oprot.WriteListEnd(); err != nil { + return thrift.PrependError("error writing list end: ", err) + } + if err := oprot.WriteFieldEnd(); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write field end error 2:spans: ", p), err) + } + return err +} + +func (p *Batch) String() string { + if p == nil { + return "" + } + return fmt.Sprintf("Batch(%+v)", *p) +} + +// Attributes: +// - Ok +type BatchSubmitResponse struct { + Ok bool `thrift:"ok,1,required" json:"ok"` +} + +func NewBatchSubmitResponse() *BatchSubmitResponse { + return &BatchSubmitResponse{} +} + +func (p *BatchSubmitResponse) GetOk() bool { + return p.Ok +} +func (p *BatchSubmitResponse) Read(iprot thrift.TProtocol) error { + if _, err := iprot.ReadStructBegin(); err != nil { + return thrift.PrependError(fmt.Sprintf("%T read error: ", p), err) + } + + var issetOk bool = false + + for { + _, fieldTypeId, fieldId, err := iprot.ReadFieldBegin() + if err != nil { + return thrift.PrependError(fmt.Sprintf("%T field %d read error: ", p, fieldId), err) + } + if fieldTypeId == thrift.STOP { + break + } + switch fieldId { + case 1: + if err := p.readField1(iprot); err != nil { + return err + } + issetOk = true + default: + if err := iprot.Skip(fieldTypeId); err != nil { + return err + } + } + if err := iprot.ReadFieldEnd(); err != nil { + return err + } + } + if err := iprot.ReadStructEnd(); err != nil { + return thrift.PrependError(fmt.Sprintf("%T read struct end error: ", p), err) + } + if !issetOk { + return thrift.NewTProtocolExceptionWithType(thrift.INVALID_DATA, fmt.Errorf("Required field Ok is not set")) + } + return nil +} + +func (p *BatchSubmitResponse) readField1(iprot thrift.TProtocol) error { + if v, err := iprot.ReadBool(); err != nil { + return thrift.PrependError("error reading field 1: ", err) + } else { + p.Ok = v + } + return nil +} + +func (p *BatchSubmitResponse) Write(oprot thrift.TProtocol) error { + if err := oprot.WriteStructBegin("BatchSubmitResponse"); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write struct begin error: ", p), err) + } + if err := p.writeField1(oprot); err != nil { + return err + } + if err := oprot.WriteFieldStop(); err != nil { + return thrift.PrependError("write field stop error: ", err) + } + if err := oprot.WriteStructEnd(); err != nil { + return thrift.PrependError("write struct stop error: ", err) + } + return nil +} + +func (p *BatchSubmitResponse) writeField1(oprot thrift.TProtocol) (err error) { + if err := oprot.WriteFieldBegin("ok", thrift.BOOL, 1); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write field begin error 1:ok: ", p), err) + } + if err := oprot.WriteBool(bool(p.Ok)); err != nil { + return thrift.PrependError(fmt.Sprintf("%T.ok (1) field write error: ", p), err) + } + if err := oprot.WriteFieldEnd(); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write field end error 1:ok: ", p), err) + } + return err +} + +func (p *BatchSubmitResponse) String() string { + if p == nil { + return "" + } + return fmt.Sprintf("BatchSubmitResponse(%+v)", *p) +} diff --git a/vendor/github.com/uber/jaeger-client-go/thrift-gen/sampling/constants.go b/vendor/github.com/uber/jaeger-client-go/thrift-gen/sampling/constants.go new file mode 100644 index 000000000..728988b83 --- /dev/null +++ b/vendor/github.com/uber/jaeger-client-go/thrift-gen/sampling/constants.go @@ -0,0 +1,18 @@ +// Autogenerated by Thrift Compiler (0.9.3) +// DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING + +package sampling + +import ( + "bytes" + "fmt" + "github.com/apache/thrift/lib/go/thrift" +) + +// (needed to ensure safety because of naive import list construction.) +var _ = thrift.ZERO +var _ = fmt.Printf +var _ = bytes.Equal + +func init() { +} diff --git a/vendor/github.com/uber/jaeger-client-go/thrift-gen/sampling/samplingmanager.go b/vendor/github.com/uber/jaeger-client-go/thrift-gen/sampling/samplingmanager.go new file mode 100644 index 000000000..563e2b4c9 --- /dev/null +++ b/vendor/github.com/uber/jaeger-client-go/thrift-gen/sampling/samplingmanager.go @@ -0,0 +1,410 @@ +// Autogenerated by Thrift Compiler (0.9.3) +// DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING + +package sampling + +import ( + "bytes" + "fmt" + "github.com/apache/thrift/lib/go/thrift" +) + +// (needed to ensure safety because of naive import list construction.) +var _ = thrift.ZERO +var _ = fmt.Printf +var _ = bytes.Equal + +type SamplingManager interface { + // Parameters: + // - ServiceName + GetSamplingStrategy(serviceName string) (r *SamplingStrategyResponse, err error) +} + +type SamplingManagerClient struct { + Transport thrift.TTransport + ProtocolFactory thrift.TProtocolFactory + InputProtocol thrift.TProtocol + OutputProtocol thrift.TProtocol + SeqId int32 +} + +func NewSamplingManagerClientFactory(t thrift.TTransport, f thrift.TProtocolFactory) *SamplingManagerClient { + return &SamplingManagerClient{Transport: t, + ProtocolFactory: f, + InputProtocol: f.GetProtocol(t), + OutputProtocol: f.GetProtocol(t), + SeqId: 0, + } +} + +func NewSamplingManagerClientProtocol(t thrift.TTransport, iprot thrift.TProtocol, oprot thrift.TProtocol) *SamplingManagerClient { + return &SamplingManagerClient{Transport: t, + ProtocolFactory: nil, + InputProtocol: iprot, + OutputProtocol: oprot, + SeqId: 0, + } +} + +// Parameters: +// - ServiceName +func (p *SamplingManagerClient) GetSamplingStrategy(serviceName string) (r *SamplingStrategyResponse, err error) { + if err = p.sendGetSamplingStrategy(serviceName); err != nil { + return + } + return p.recvGetSamplingStrategy() +} + +func (p *SamplingManagerClient) sendGetSamplingStrategy(serviceName string) (err error) { + oprot := p.OutputProtocol + if oprot == nil { + oprot = p.ProtocolFactory.GetProtocol(p.Transport) + p.OutputProtocol = oprot + } + p.SeqId++ + if err = oprot.WriteMessageBegin("getSamplingStrategy", thrift.CALL, p.SeqId); err != nil { + return + } + args := SamplingManagerGetSamplingStrategyArgs{ + ServiceName: serviceName, + } + if err = args.Write(oprot); err != nil { + return + } + if err = oprot.WriteMessageEnd(); err != nil { + return + } + return oprot.Flush() +} + +func (p *SamplingManagerClient) recvGetSamplingStrategy() (value *SamplingStrategyResponse, err error) { + iprot := p.InputProtocol + if iprot == nil { + iprot = p.ProtocolFactory.GetProtocol(p.Transport) + p.InputProtocol = iprot + } + method, mTypeId, seqId, err := iprot.ReadMessageBegin() + if err != nil { + return + } + if method != "getSamplingStrategy" { + err = thrift.NewTApplicationException(thrift.WRONG_METHOD_NAME, "getSamplingStrategy failed: wrong method name") + return + } + if p.SeqId != seqId { + err = thrift.NewTApplicationException(thrift.BAD_SEQUENCE_ID, "getSamplingStrategy failed: out of sequence response") + return + } + if mTypeId == thrift.EXCEPTION { + error1 := thrift.NewTApplicationException(thrift.UNKNOWN_APPLICATION_EXCEPTION, "Unknown Exception") + var error2 error + error2, err = error1.Read(iprot) + if err != nil { + return + } + if err = iprot.ReadMessageEnd(); err != nil { + return + } + err = error2 + return + } + if mTypeId != thrift.REPLY { + err = thrift.NewTApplicationException(thrift.INVALID_MESSAGE_TYPE_EXCEPTION, "getSamplingStrategy failed: invalid message type") + return + } + result := SamplingManagerGetSamplingStrategyResult{} + if err = result.Read(iprot); err != nil { + return + } + if err = iprot.ReadMessageEnd(); err != nil { + return + } + value = result.GetSuccess() + return +} + +type SamplingManagerProcessor struct { + processorMap map[string]thrift.TProcessorFunction + handler SamplingManager +} + +func (p *SamplingManagerProcessor) AddToProcessorMap(key string, processor thrift.TProcessorFunction) { + p.processorMap[key] = processor +} + +func (p *SamplingManagerProcessor) GetProcessorFunction(key string) (processor thrift.TProcessorFunction, ok bool) { + processor, ok = p.processorMap[key] + return processor, ok +} + +func (p *SamplingManagerProcessor) ProcessorMap() map[string]thrift.TProcessorFunction { + return p.processorMap +} + +func NewSamplingManagerProcessor(handler SamplingManager) *SamplingManagerProcessor { + + self3 := &SamplingManagerProcessor{handler: handler, processorMap: make(map[string]thrift.TProcessorFunction)} + self3.processorMap["getSamplingStrategy"] = &samplingManagerProcessorGetSamplingStrategy{handler: handler} + return self3 +} + +func (p *SamplingManagerProcessor) Process(iprot, oprot thrift.TProtocol) (success bool, err thrift.TException) { + name, _, seqId, err := iprot.ReadMessageBegin() + if err != nil { + return false, err + } + if processor, ok := p.GetProcessorFunction(name); ok { + return processor.Process(seqId, iprot, oprot) + } + iprot.Skip(thrift.STRUCT) + iprot.ReadMessageEnd() + x4 := thrift.NewTApplicationException(thrift.UNKNOWN_METHOD, "Unknown function "+name) + oprot.WriteMessageBegin(name, thrift.EXCEPTION, seqId) + x4.Write(oprot) + oprot.WriteMessageEnd() + oprot.Flush() + return false, x4 + +} + +type samplingManagerProcessorGetSamplingStrategy struct { + handler SamplingManager +} + +func (p *samplingManagerProcessorGetSamplingStrategy) Process(seqId int32, iprot, oprot thrift.TProtocol) (success bool, err thrift.TException) { + args := SamplingManagerGetSamplingStrategyArgs{} + if err = args.Read(iprot); err != nil { + iprot.ReadMessageEnd() + x := thrift.NewTApplicationException(thrift.PROTOCOL_ERROR, err.Error()) + oprot.WriteMessageBegin("getSamplingStrategy", thrift.EXCEPTION, seqId) + x.Write(oprot) + oprot.WriteMessageEnd() + oprot.Flush() + return false, err + } + + iprot.ReadMessageEnd() + result := SamplingManagerGetSamplingStrategyResult{} + var retval *SamplingStrategyResponse + var err2 error + if retval, err2 = p.handler.GetSamplingStrategy(args.ServiceName); err2 != nil { + x := thrift.NewTApplicationException(thrift.INTERNAL_ERROR, "Internal error processing getSamplingStrategy: "+err2.Error()) + oprot.WriteMessageBegin("getSamplingStrategy", thrift.EXCEPTION, seqId) + x.Write(oprot) + oprot.WriteMessageEnd() + oprot.Flush() + return true, err2 + } else { + result.Success = retval + } + if err2 = oprot.WriteMessageBegin("getSamplingStrategy", thrift.REPLY, seqId); err2 != nil { + err = err2 + } + if err2 = result.Write(oprot); err == nil && err2 != nil { + err = err2 + } + if err2 = oprot.WriteMessageEnd(); err == nil && err2 != nil { + err = err2 + } + if err2 = oprot.Flush(); err == nil && err2 != nil { + err = err2 + } + if err != nil { + return + } + return true, err +} + +// HELPER FUNCTIONS AND STRUCTURES + +// Attributes: +// - ServiceName +type SamplingManagerGetSamplingStrategyArgs struct { + ServiceName string `thrift:"serviceName,1" json:"serviceName"` +} + +func NewSamplingManagerGetSamplingStrategyArgs() *SamplingManagerGetSamplingStrategyArgs { + return &SamplingManagerGetSamplingStrategyArgs{} +} + +func (p *SamplingManagerGetSamplingStrategyArgs) GetServiceName() string { + return p.ServiceName +} +func (p *SamplingManagerGetSamplingStrategyArgs) Read(iprot thrift.TProtocol) error { + if _, err := iprot.ReadStructBegin(); err != nil { + return thrift.PrependError(fmt.Sprintf("%T read error: ", p), err) + } + + for { + _, fieldTypeId, fieldId, err := iprot.ReadFieldBegin() + if err != nil { + return thrift.PrependError(fmt.Sprintf("%T field %d read error: ", p, fieldId), err) + } + if fieldTypeId == thrift.STOP { + break + } + switch fieldId { + case 1: + if err := p.readField1(iprot); err != nil { + return err + } + default: + if err := iprot.Skip(fieldTypeId); err != nil { + return err + } + } + if err := iprot.ReadFieldEnd(); err != nil { + return err + } + } + if err := iprot.ReadStructEnd(); err != nil { + return thrift.PrependError(fmt.Sprintf("%T read struct end error: ", p), err) + } + return nil +} + +func (p *SamplingManagerGetSamplingStrategyArgs) readField1(iprot thrift.TProtocol) error { + if v, err := iprot.ReadString(); err != nil { + return thrift.PrependError("error reading field 1: ", err) + } else { + p.ServiceName = v + } + return nil +} + +func (p *SamplingManagerGetSamplingStrategyArgs) Write(oprot thrift.TProtocol) error { + if err := oprot.WriteStructBegin("getSamplingStrategy_args"); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write struct begin error: ", p), err) + } + if err := p.writeField1(oprot); err != nil { + return err + } + if err := oprot.WriteFieldStop(); err != nil { + return thrift.PrependError("write field stop error: ", err) + } + if err := oprot.WriteStructEnd(); err != nil { + return thrift.PrependError("write struct stop error: ", err) + } + return nil +} + +func (p *SamplingManagerGetSamplingStrategyArgs) writeField1(oprot thrift.TProtocol) (err error) { + if err := oprot.WriteFieldBegin("serviceName", thrift.STRING, 1); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write field begin error 1:serviceName: ", p), err) + } + if err := oprot.WriteString(string(p.ServiceName)); err != nil { + return thrift.PrependError(fmt.Sprintf("%T.serviceName (1) field write error: ", p), err) + } + if err := oprot.WriteFieldEnd(); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write field end error 1:serviceName: ", p), err) + } + return err +} + +func (p *SamplingManagerGetSamplingStrategyArgs) String() string { + if p == nil { + return "" + } + return fmt.Sprintf("SamplingManagerGetSamplingStrategyArgs(%+v)", *p) +} + +// Attributes: +// - Success +type SamplingManagerGetSamplingStrategyResult struct { + Success *SamplingStrategyResponse `thrift:"success,0" json:"success,omitempty"` +} + +func NewSamplingManagerGetSamplingStrategyResult() *SamplingManagerGetSamplingStrategyResult { + return &SamplingManagerGetSamplingStrategyResult{} +} + +var SamplingManagerGetSamplingStrategyResult_Success_DEFAULT *SamplingStrategyResponse + +func (p *SamplingManagerGetSamplingStrategyResult) GetSuccess() *SamplingStrategyResponse { + if !p.IsSetSuccess() { + return SamplingManagerGetSamplingStrategyResult_Success_DEFAULT + } + return p.Success +} +func (p *SamplingManagerGetSamplingStrategyResult) IsSetSuccess() bool { + return p.Success != nil +} + +func (p *SamplingManagerGetSamplingStrategyResult) Read(iprot thrift.TProtocol) error { + if _, err := iprot.ReadStructBegin(); err != nil { + return thrift.PrependError(fmt.Sprintf("%T read error: ", p), err) + } + + for { + _, fieldTypeId, fieldId, err := iprot.ReadFieldBegin() + if err != nil { + return thrift.PrependError(fmt.Sprintf("%T field %d read error: ", p, fieldId), err) + } + if fieldTypeId == thrift.STOP { + break + } + switch fieldId { + case 0: + if err := p.readField0(iprot); err != nil { + return err + } + default: + if err := iprot.Skip(fieldTypeId); err != nil { + return err + } + } + if err := iprot.ReadFieldEnd(); err != nil { + return err + } + } + if err := iprot.ReadStructEnd(); err != nil { + return thrift.PrependError(fmt.Sprintf("%T read struct end error: ", p), err) + } + return nil +} + +func (p *SamplingManagerGetSamplingStrategyResult) readField0(iprot thrift.TProtocol) error { + p.Success = &SamplingStrategyResponse{} + if err := p.Success.Read(iprot); err != nil { + return thrift.PrependError(fmt.Sprintf("%T error reading struct: ", p.Success), err) + } + return nil +} + +func (p *SamplingManagerGetSamplingStrategyResult) Write(oprot thrift.TProtocol) error { + if err := oprot.WriteStructBegin("getSamplingStrategy_result"); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write struct begin error: ", p), err) + } + if err := p.writeField0(oprot); err != nil { + return err + } + if err := oprot.WriteFieldStop(); err != nil { + return thrift.PrependError("write field stop error: ", err) + } + if err := oprot.WriteStructEnd(); err != nil { + return thrift.PrependError("write struct stop error: ", err) + } + return nil +} + +func (p *SamplingManagerGetSamplingStrategyResult) writeField0(oprot thrift.TProtocol) (err error) { + if p.IsSetSuccess() { + if err := oprot.WriteFieldBegin("success", thrift.STRUCT, 0); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write field begin error 0:success: ", p), err) + } + if err := p.Success.Write(oprot); err != nil { + return thrift.PrependError(fmt.Sprintf("%T error writing struct: ", p.Success), err) + } + if err := oprot.WriteFieldEnd(); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write field end error 0:success: ", p), err) + } + } + return err +} + +func (p *SamplingManagerGetSamplingStrategyResult) String() string { + if p == nil { + return "" + } + return fmt.Sprintf("SamplingManagerGetSamplingStrategyResult(%+v)", *p) +} diff --git a/vendor/github.com/uber/jaeger-client-go/thrift-gen/sampling/ttypes.go b/vendor/github.com/uber/jaeger-client-go/thrift-gen/sampling/ttypes.go new file mode 100644 index 000000000..3e831af4a --- /dev/null +++ b/vendor/github.com/uber/jaeger-client-go/thrift-gen/sampling/ttypes.go @@ -0,0 +1,873 @@ +// Autogenerated by Thrift Compiler (0.9.3) +// DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING + +package sampling + +import ( + "bytes" + "fmt" + "github.com/apache/thrift/lib/go/thrift" +) + +// (needed to ensure safety because of naive import list construction.) +var _ = thrift.ZERO +var _ = fmt.Printf +var _ = bytes.Equal + +var GoUnusedProtection__ int + +type SamplingStrategyType int64 + +const ( + SamplingStrategyType_PROBABILISTIC SamplingStrategyType = 0 + SamplingStrategyType_RATE_LIMITING SamplingStrategyType = 1 +) + +func (p SamplingStrategyType) String() string { + switch p { + case SamplingStrategyType_PROBABILISTIC: + return "PROBABILISTIC" + case SamplingStrategyType_RATE_LIMITING: + return "RATE_LIMITING" + } + return "" +} + +func SamplingStrategyTypeFromString(s string) (SamplingStrategyType, error) { + switch s { + case "PROBABILISTIC": + return SamplingStrategyType_PROBABILISTIC, nil + case "RATE_LIMITING": + return SamplingStrategyType_RATE_LIMITING, nil + } + return SamplingStrategyType(0), fmt.Errorf("not a valid SamplingStrategyType string") +} + +func SamplingStrategyTypePtr(v SamplingStrategyType) *SamplingStrategyType { return &v } + +func (p SamplingStrategyType) MarshalText() ([]byte, error) { + return []byte(p.String()), nil +} + +func (p *SamplingStrategyType) UnmarshalText(text []byte) error { + q, err := SamplingStrategyTypeFromString(string(text)) + if err != nil { + return err + } + *p = q + return nil +} + +// Attributes: +// - SamplingRate +type ProbabilisticSamplingStrategy struct { + SamplingRate float64 `thrift:"samplingRate,1,required" json:"samplingRate"` +} + +func NewProbabilisticSamplingStrategy() *ProbabilisticSamplingStrategy { + return &ProbabilisticSamplingStrategy{} +} + +func (p *ProbabilisticSamplingStrategy) GetSamplingRate() float64 { + return p.SamplingRate +} +func (p *ProbabilisticSamplingStrategy) Read(iprot thrift.TProtocol) error { + if _, err := iprot.ReadStructBegin(); err != nil { + return thrift.PrependError(fmt.Sprintf("%T read error: ", p), err) + } + + var issetSamplingRate bool = false + + for { + _, fieldTypeId, fieldId, err := iprot.ReadFieldBegin() + if err != nil { + return thrift.PrependError(fmt.Sprintf("%T field %d read error: ", p, fieldId), err) + } + if fieldTypeId == thrift.STOP { + break + } + switch fieldId { + case 1: + if err := p.readField1(iprot); err != nil { + return err + } + issetSamplingRate = true + default: + if err := iprot.Skip(fieldTypeId); err != nil { + return err + } + } + if err := iprot.ReadFieldEnd(); err != nil { + return err + } + } + if err := iprot.ReadStructEnd(); err != nil { + return thrift.PrependError(fmt.Sprintf("%T read struct end error: ", p), err) + } + if !issetSamplingRate { + return thrift.NewTProtocolExceptionWithType(thrift.INVALID_DATA, fmt.Errorf("Required field SamplingRate is not set")) + } + return nil +} + +func (p *ProbabilisticSamplingStrategy) readField1(iprot thrift.TProtocol) error { + if v, err := iprot.ReadDouble(); err != nil { + return thrift.PrependError("error reading field 1: ", err) + } else { + p.SamplingRate = v + } + return nil +} + +func (p *ProbabilisticSamplingStrategy) Write(oprot thrift.TProtocol) error { + if err := oprot.WriteStructBegin("ProbabilisticSamplingStrategy"); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write struct begin error: ", p), err) + } + if err := p.writeField1(oprot); err != nil { + return err + } + if err := oprot.WriteFieldStop(); err != nil { + return thrift.PrependError("write field stop error: ", err) + } + if err := oprot.WriteStructEnd(); err != nil { + return thrift.PrependError("write struct stop error: ", err) + } + return nil +} + +func (p *ProbabilisticSamplingStrategy) writeField1(oprot thrift.TProtocol) (err error) { + if err := oprot.WriteFieldBegin("samplingRate", thrift.DOUBLE, 1); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write field begin error 1:samplingRate: ", p), err) + } + if err := oprot.WriteDouble(float64(p.SamplingRate)); err != nil { + return thrift.PrependError(fmt.Sprintf("%T.samplingRate (1) field write error: ", p), err) + } + if err := oprot.WriteFieldEnd(); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write field end error 1:samplingRate: ", p), err) + } + return err +} + +func (p *ProbabilisticSamplingStrategy) String() string { + if p == nil { + return "" + } + return fmt.Sprintf("ProbabilisticSamplingStrategy(%+v)", *p) +} + +// Attributes: +// - MaxTracesPerSecond +type RateLimitingSamplingStrategy struct { + MaxTracesPerSecond int16 `thrift:"maxTracesPerSecond,1,required" json:"maxTracesPerSecond"` +} + +func NewRateLimitingSamplingStrategy() *RateLimitingSamplingStrategy { + return &RateLimitingSamplingStrategy{} +} + +func (p *RateLimitingSamplingStrategy) GetMaxTracesPerSecond() int16 { + return p.MaxTracesPerSecond +} +func (p *RateLimitingSamplingStrategy) Read(iprot thrift.TProtocol) error { + if _, err := iprot.ReadStructBegin(); err != nil { + return thrift.PrependError(fmt.Sprintf("%T read error: ", p), err) + } + + var issetMaxTracesPerSecond bool = false + + for { + _, fieldTypeId, fieldId, err := iprot.ReadFieldBegin() + if err != nil { + return thrift.PrependError(fmt.Sprintf("%T field %d read error: ", p, fieldId), err) + } + if fieldTypeId == thrift.STOP { + break + } + switch fieldId { + case 1: + if err := p.readField1(iprot); err != nil { + return err + } + issetMaxTracesPerSecond = true + default: + if err := iprot.Skip(fieldTypeId); err != nil { + return err + } + } + if err := iprot.ReadFieldEnd(); err != nil { + return err + } + } + if err := iprot.ReadStructEnd(); err != nil { + return thrift.PrependError(fmt.Sprintf("%T read struct end error: ", p), err) + } + if !issetMaxTracesPerSecond { + return thrift.NewTProtocolExceptionWithType(thrift.INVALID_DATA, fmt.Errorf("Required field MaxTracesPerSecond is not set")) + } + return nil +} + +func (p *RateLimitingSamplingStrategy) readField1(iprot thrift.TProtocol) error { + if v, err := iprot.ReadI16(); err != nil { + return thrift.PrependError("error reading field 1: ", err) + } else { + p.MaxTracesPerSecond = v + } + return nil +} + +func (p *RateLimitingSamplingStrategy) Write(oprot thrift.TProtocol) error { + if err := oprot.WriteStructBegin("RateLimitingSamplingStrategy"); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write struct begin error: ", p), err) + } + if err := p.writeField1(oprot); err != nil { + return err + } + if err := oprot.WriteFieldStop(); err != nil { + return thrift.PrependError("write field stop error: ", err) + } + if err := oprot.WriteStructEnd(); err != nil { + return thrift.PrependError("write struct stop error: ", err) + } + return nil +} + +func (p *RateLimitingSamplingStrategy) writeField1(oprot thrift.TProtocol) (err error) { + if err := oprot.WriteFieldBegin("maxTracesPerSecond", thrift.I16, 1); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write field begin error 1:maxTracesPerSecond: ", p), err) + } + if err := oprot.WriteI16(int16(p.MaxTracesPerSecond)); err != nil { + return thrift.PrependError(fmt.Sprintf("%T.maxTracesPerSecond (1) field write error: ", p), err) + } + if err := oprot.WriteFieldEnd(); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write field end error 1:maxTracesPerSecond: ", p), err) + } + return err +} + +func (p *RateLimitingSamplingStrategy) String() string { + if p == nil { + return "" + } + return fmt.Sprintf("RateLimitingSamplingStrategy(%+v)", *p) +} + +// Attributes: +// - Operation +// - ProbabilisticSampling +type OperationSamplingStrategy struct { + Operation string `thrift:"operation,1,required" json:"operation"` + ProbabilisticSampling *ProbabilisticSamplingStrategy `thrift:"probabilisticSampling,2,required" json:"probabilisticSampling"` +} + +func NewOperationSamplingStrategy() *OperationSamplingStrategy { + return &OperationSamplingStrategy{} +} + +func (p *OperationSamplingStrategy) GetOperation() string { + return p.Operation +} + +var OperationSamplingStrategy_ProbabilisticSampling_DEFAULT *ProbabilisticSamplingStrategy + +func (p *OperationSamplingStrategy) GetProbabilisticSampling() *ProbabilisticSamplingStrategy { + if !p.IsSetProbabilisticSampling() { + return OperationSamplingStrategy_ProbabilisticSampling_DEFAULT + } + return p.ProbabilisticSampling +} +func (p *OperationSamplingStrategy) IsSetProbabilisticSampling() bool { + return p.ProbabilisticSampling != nil +} + +func (p *OperationSamplingStrategy) Read(iprot thrift.TProtocol) error { + if _, err := iprot.ReadStructBegin(); err != nil { + return thrift.PrependError(fmt.Sprintf("%T read error: ", p), err) + } + + var issetOperation bool = false + var issetProbabilisticSampling bool = false + + for { + _, fieldTypeId, fieldId, err := iprot.ReadFieldBegin() + if err != nil { + return thrift.PrependError(fmt.Sprintf("%T field %d read error: ", p, fieldId), err) + } + if fieldTypeId == thrift.STOP { + break + } + switch fieldId { + case 1: + if err := p.readField1(iprot); err != nil { + return err + } + issetOperation = true + case 2: + if err := p.readField2(iprot); err != nil { + return err + } + issetProbabilisticSampling = true + default: + if err := iprot.Skip(fieldTypeId); err != nil { + return err + } + } + if err := iprot.ReadFieldEnd(); err != nil { + return err + } + } + if err := iprot.ReadStructEnd(); err != nil { + return thrift.PrependError(fmt.Sprintf("%T read struct end error: ", p), err) + } + if !issetOperation { + return thrift.NewTProtocolExceptionWithType(thrift.INVALID_DATA, fmt.Errorf("Required field Operation is not set")) + } + if !issetProbabilisticSampling { + return thrift.NewTProtocolExceptionWithType(thrift.INVALID_DATA, fmt.Errorf("Required field ProbabilisticSampling is not set")) + } + return nil +} + +func (p *OperationSamplingStrategy) readField1(iprot thrift.TProtocol) error { + if v, err := iprot.ReadString(); err != nil { + return thrift.PrependError("error reading field 1: ", err) + } else { + p.Operation = v + } + return nil +} + +func (p *OperationSamplingStrategy) readField2(iprot thrift.TProtocol) error { + p.ProbabilisticSampling = &ProbabilisticSamplingStrategy{} + if err := p.ProbabilisticSampling.Read(iprot); err != nil { + return thrift.PrependError(fmt.Sprintf("%T error reading struct: ", p.ProbabilisticSampling), err) + } + return nil +} + +func (p *OperationSamplingStrategy) Write(oprot thrift.TProtocol) error { + if err := oprot.WriteStructBegin("OperationSamplingStrategy"); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write struct begin error: ", p), err) + } + if err := p.writeField1(oprot); err != nil { + return err + } + if err := p.writeField2(oprot); err != nil { + return err + } + if err := oprot.WriteFieldStop(); err != nil { + return thrift.PrependError("write field stop error: ", err) + } + if err := oprot.WriteStructEnd(); err != nil { + return thrift.PrependError("write struct stop error: ", err) + } + return nil +} + +func (p *OperationSamplingStrategy) writeField1(oprot thrift.TProtocol) (err error) { + if err := oprot.WriteFieldBegin("operation", thrift.STRING, 1); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write field begin error 1:operation: ", p), err) + } + if err := oprot.WriteString(string(p.Operation)); err != nil { + return thrift.PrependError(fmt.Sprintf("%T.operation (1) field write error: ", p), err) + } + if err := oprot.WriteFieldEnd(); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write field end error 1:operation: ", p), err) + } + return err +} + +func (p *OperationSamplingStrategy) writeField2(oprot thrift.TProtocol) (err error) { + if err := oprot.WriteFieldBegin("probabilisticSampling", thrift.STRUCT, 2); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write field begin error 2:probabilisticSampling: ", p), err) + } + if err := p.ProbabilisticSampling.Write(oprot); err != nil { + return thrift.PrependError(fmt.Sprintf("%T error writing struct: ", p.ProbabilisticSampling), err) + } + if err := oprot.WriteFieldEnd(); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write field end error 2:probabilisticSampling: ", p), err) + } + return err +} + +func (p *OperationSamplingStrategy) String() string { + if p == nil { + return "" + } + return fmt.Sprintf("OperationSamplingStrategy(%+v)", *p) +} + +// Attributes: +// - DefaultSamplingProbability +// - DefaultLowerBoundTracesPerSecond +// - PerOperationStrategies +// - DefaultUpperBoundTracesPerSecond +type PerOperationSamplingStrategies struct { + DefaultSamplingProbability float64 `thrift:"defaultSamplingProbability,1,required" json:"defaultSamplingProbability"` + DefaultLowerBoundTracesPerSecond float64 `thrift:"defaultLowerBoundTracesPerSecond,2,required" json:"defaultLowerBoundTracesPerSecond"` + PerOperationStrategies []*OperationSamplingStrategy `thrift:"perOperationStrategies,3,required" json:"perOperationStrategies"` + DefaultUpperBoundTracesPerSecond *float64 `thrift:"defaultUpperBoundTracesPerSecond,4" json:"defaultUpperBoundTracesPerSecond,omitempty"` +} + +func NewPerOperationSamplingStrategies() *PerOperationSamplingStrategies { + return &PerOperationSamplingStrategies{} +} + +func (p *PerOperationSamplingStrategies) GetDefaultSamplingProbability() float64 { + return p.DefaultSamplingProbability +} + +func (p *PerOperationSamplingStrategies) GetDefaultLowerBoundTracesPerSecond() float64 { + return p.DefaultLowerBoundTracesPerSecond +} + +func (p *PerOperationSamplingStrategies) GetPerOperationStrategies() []*OperationSamplingStrategy { + return p.PerOperationStrategies +} + +var PerOperationSamplingStrategies_DefaultUpperBoundTracesPerSecond_DEFAULT float64 + +func (p *PerOperationSamplingStrategies) GetDefaultUpperBoundTracesPerSecond() float64 { + if !p.IsSetDefaultUpperBoundTracesPerSecond() { + return PerOperationSamplingStrategies_DefaultUpperBoundTracesPerSecond_DEFAULT + } + return *p.DefaultUpperBoundTracesPerSecond +} +func (p *PerOperationSamplingStrategies) IsSetDefaultUpperBoundTracesPerSecond() bool { + return p.DefaultUpperBoundTracesPerSecond != nil +} + +func (p *PerOperationSamplingStrategies) Read(iprot thrift.TProtocol) error { + if _, err := iprot.ReadStructBegin(); err != nil { + return thrift.PrependError(fmt.Sprintf("%T read error: ", p), err) + } + + var issetDefaultSamplingProbability bool = false + var issetDefaultLowerBoundTracesPerSecond bool = false + var issetPerOperationStrategies bool = false + + for { + _, fieldTypeId, fieldId, err := iprot.ReadFieldBegin() + if err != nil { + return thrift.PrependError(fmt.Sprintf("%T field %d read error: ", p, fieldId), err) + } + if fieldTypeId == thrift.STOP { + break + } + switch fieldId { + case 1: + if err := p.readField1(iprot); err != nil { + return err + } + issetDefaultSamplingProbability = true + case 2: + if err := p.readField2(iprot); err != nil { + return err + } + issetDefaultLowerBoundTracesPerSecond = true + case 3: + if err := p.readField3(iprot); err != nil { + return err + } + issetPerOperationStrategies = true + case 4: + if err := p.readField4(iprot); err != nil { + return err + } + default: + if err := iprot.Skip(fieldTypeId); err != nil { + return err + } + } + if err := iprot.ReadFieldEnd(); err != nil { + return err + } + } + if err := iprot.ReadStructEnd(); err != nil { + return thrift.PrependError(fmt.Sprintf("%T read struct end error: ", p), err) + } + if !issetDefaultSamplingProbability { + return thrift.NewTProtocolExceptionWithType(thrift.INVALID_DATA, fmt.Errorf("Required field DefaultSamplingProbability is not set")) + } + if !issetDefaultLowerBoundTracesPerSecond { + return thrift.NewTProtocolExceptionWithType(thrift.INVALID_DATA, fmt.Errorf("Required field DefaultLowerBoundTracesPerSecond is not set")) + } + if !issetPerOperationStrategies { + return thrift.NewTProtocolExceptionWithType(thrift.INVALID_DATA, fmt.Errorf("Required field PerOperationStrategies is not set")) + } + return nil +} + +func (p *PerOperationSamplingStrategies) readField1(iprot thrift.TProtocol) error { + if v, err := iprot.ReadDouble(); err != nil { + return thrift.PrependError("error reading field 1: ", err) + } else { + p.DefaultSamplingProbability = v + } + return nil +} + +func (p *PerOperationSamplingStrategies) readField2(iprot thrift.TProtocol) error { + if v, err := iprot.ReadDouble(); err != nil { + return thrift.PrependError("error reading field 2: ", err) + } else { + p.DefaultLowerBoundTracesPerSecond = v + } + return nil +} + +func (p *PerOperationSamplingStrategies) readField3(iprot thrift.TProtocol) error { + _, size, err := iprot.ReadListBegin() + if err != nil { + return thrift.PrependError("error reading list begin: ", err) + } + tSlice := make([]*OperationSamplingStrategy, 0, size) + p.PerOperationStrategies = tSlice + for i := 0; i < size; i++ { + _elem0 := &OperationSamplingStrategy{} + if err := _elem0.Read(iprot); err != nil { + return thrift.PrependError(fmt.Sprintf("%T error reading struct: ", _elem0), err) + } + p.PerOperationStrategies = append(p.PerOperationStrategies, _elem0) + } + if err := iprot.ReadListEnd(); err != nil { + return thrift.PrependError("error reading list end: ", err) + } + return nil +} + +func (p *PerOperationSamplingStrategies) readField4(iprot thrift.TProtocol) error { + if v, err := iprot.ReadDouble(); err != nil { + return thrift.PrependError("error reading field 4: ", err) + } else { + p.DefaultUpperBoundTracesPerSecond = &v + } + return nil +} + +func (p *PerOperationSamplingStrategies) Write(oprot thrift.TProtocol) error { + if err := oprot.WriteStructBegin("PerOperationSamplingStrategies"); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write struct begin error: ", p), err) + } + if err := p.writeField1(oprot); err != nil { + return err + } + if err := p.writeField2(oprot); err != nil { + return err + } + if err := p.writeField3(oprot); err != nil { + return err + } + if err := p.writeField4(oprot); err != nil { + return err + } + if err := oprot.WriteFieldStop(); err != nil { + return thrift.PrependError("write field stop error: ", err) + } + if err := oprot.WriteStructEnd(); err != nil { + return thrift.PrependError("write struct stop error: ", err) + } + return nil +} + +func (p *PerOperationSamplingStrategies) writeField1(oprot thrift.TProtocol) (err error) { + if err := oprot.WriteFieldBegin("defaultSamplingProbability", thrift.DOUBLE, 1); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write field begin error 1:defaultSamplingProbability: ", p), err) + } + if err := oprot.WriteDouble(float64(p.DefaultSamplingProbability)); err != nil { + return thrift.PrependError(fmt.Sprintf("%T.defaultSamplingProbability (1) field write error: ", p), err) + } + if err := oprot.WriteFieldEnd(); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write field end error 1:defaultSamplingProbability: ", p), err) + } + return err +} + +func (p *PerOperationSamplingStrategies) writeField2(oprot thrift.TProtocol) (err error) { + if err := oprot.WriteFieldBegin("defaultLowerBoundTracesPerSecond", thrift.DOUBLE, 2); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write field begin error 2:defaultLowerBoundTracesPerSecond: ", p), err) + } + if err := oprot.WriteDouble(float64(p.DefaultLowerBoundTracesPerSecond)); err != nil { + return thrift.PrependError(fmt.Sprintf("%T.defaultLowerBoundTracesPerSecond (2) field write error: ", p), err) + } + if err := oprot.WriteFieldEnd(); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write field end error 2:defaultLowerBoundTracesPerSecond: ", p), err) + } + return err +} + +func (p *PerOperationSamplingStrategies) writeField3(oprot thrift.TProtocol) (err error) { + if err := oprot.WriteFieldBegin("perOperationStrategies", thrift.LIST, 3); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write field begin error 3:perOperationStrategies: ", p), err) + } + if err := oprot.WriteListBegin(thrift.STRUCT, len(p.PerOperationStrategies)); err != nil { + return thrift.PrependError("error writing list begin: ", err) + } + for _, v := range p.PerOperationStrategies { + if err := v.Write(oprot); err != nil { + return thrift.PrependError(fmt.Sprintf("%T error writing struct: ", v), err) + } + } + if err := oprot.WriteListEnd(); err != nil { + return thrift.PrependError("error writing list end: ", err) + } + if err := oprot.WriteFieldEnd(); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write field end error 3:perOperationStrategies: ", p), err) + } + return err +} + +func (p *PerOperationSamplingStrategies) writeField4(oprot thrift.TProtocol) (err error) { + if p.IsSetDefaultUpperBoundTracesPerSecond() { + if err := oprot.WriteFieldBegin("defaultUpperBoundTracesPerSecond", thrift.DOUBLE, 4); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write field begin error 4:defaultUpperBoundTracesPerSecond: ", p), err) + } + if err := oprot.WriteDouble(float64(*p.DefaultUpperBoundTracesPerSecond)); err != nil { + return thrift.PrependError(fmt.Sprintf("%T.defaultUpperBoundTracesPerSecond (4) field write error: ", p), err) + } + if err := oprot.WriteFieldEnd(); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write field end error 4:defaultUpperBoundTracesPerSecond: ", p), err) + } + } + return err +} + +func (p *PerOperationSamplingStrategies) String() string { + if p == nil { + return "" + } + return fmt.Sprintf("PerOperationSamplingStrategies(%+v)", *p) +} + +// Attributes: +// - StrategyType +// - ProbabilisticSampling +// - RateLimitingSampling +// - OperationSampling +type SamplingStrategyResponse struct { + StrategyType SamplingStrategyType `thrift:"strategyType,1,required" json:"strategyType"` + ProbabilisticSampling *ProbabilisticSamplingStrategy `thrift:"probabilisticSampling,2" json:"probabilisticSampling,omitempty"` + RateLimitingSampling *RateLimitingSamplingStrategy `thrift:"rateLimitingSampling,3" json:"rateLimitingSampling,omitempty"` + OperationSampling *PerOperationSamplingStrategies `thrift:"operationSampling,4" json:"operationSampling,omitempty"` +} + +func NewSamplingStrategyResponse() *SamplingStrategyResponse { + return &SamplingStrategyResponse{} +} + +func (p *SamplingStrategyResponse) GetStrategyType() SamplingStrategyType { + return p.StrategyType +} + +var SamplingStrategyResponse_ProbabilisticSampling_DEFAULT *ProbabilisticSamplingStrategy + +func (p *SamplingStrategyResponse) GetProbabilisticSampling() *ProbabilisticSamplingStrategy { + if !p.IsSetProbabilisticSampling() { + return SamplingStrategyResponse_ProbabilisticSampling_DEFAULT + } + return p.ProbabilisticSampling +} + +var SamplingStrategyResponse_RateLimitingSampling_DEFAULT *RateLimitingSamplingStrategy + +func (p *SamplingStrategyResponse) GetRateLimitingSampling() *RateLimitingSamplingStrategy { + if !p.IsSetRateLimitingSampling() { + return SamplingStrategyResponse_RateLimitingSampling_DEFAULT + } + return p.RateLimitingSampling +} + +var SamplingStrategyResponse_OperationSampling_DEFAULT *PerOperationSamplingStrategies + +func (p *SamplingStrategyResponse) GetOperationSampling() *PerOperationSamplingStrategies { + if !p.IsSetOperationSampling() { + return SamplingStrategyResponse_OperationSampling_DEFAULT + } + return p.OperationSampling +} +func (p *SamplingStrategyResponse) IsSetProbabilisticSampling() bool { + return p.ProbabilisticSampling != nil +} + +func (p *SamplingStrategyResponse) IsSetRateLimitingSampling() bool { + return p.RateLimitingSampling != nil +} + +func (p *SamplingStrategyResponse) IsSetOperationSampling() bool { + return p.OperationSampling != nil +} + +func (p *SamplingStrategyResponse) Read(iprot thrift.TProtocol) error { + if _, err := iprot.ReadStructBegin(); err != nil { + return thrift.PrependError(fmt.Sprintf("%T read error: ", p), err) + } + + var issetStrategyType bool = false + + for { + _, fieldTypeId, fieldId, err := iprot.ReadFieldBegin() + if err != nil { + return thrift.PrependError(fmt.Sprintf("%T field %d read error: ", p, fieldId), err) + } + if fieldTypeId == thrift.STOP { + break + } + switch fieldId { + case 1: + if err := p.readField1(iprot); err != nil { + return err + } + issetStrategyType = true + case 2: + if err := p.readField2(iprot); err != nil { + return err + } + case 3: + if err := p.readField3(iprot); err != nil { + return err + } + case 4: + if err := p.readField4(iprot); err != nil { + return err + } + default: + if err := iprot.Skip(fieldTypeId); err != nil { + return err + } + } + if err := iprot.ReadFieldEnd(); err != nil { + return err + } + } + if err := iprot.ReadStructEnd(); err != nil { + return thrift.PrependError(fmt.Sprintf("%T read struct end error: ", p), err) + } + if !issetStrategyType { + return thrift.NewTProtocolExceptionWithType(thrift.INVALID_DATA, fmt.Errorf("Required field StrategyType is not set")) + } + return nil +} + +func (p *SamplingStrategyResponse) readField1(iprot thrift.TProtocol) error { + if v, err := iprot.ReadI32(); err != nil { + return thrift.PrependError("error reading field 1: ", err) + } else { + temp := SamplingStrategyType(v) + p.StrategyType = temp + } + return nil +} + +func (p *SamplingStrategyResponse) readField2(iprot thrift.TProtocol) error { + p.ProbabilisticSampling = &ProbabilisticSamplingStrategy{} + if err := p.ProbabilisticSampling.Read(iprot); err != nil { + return thrift.PrependError(fmt.Sprintf("%T error reading struct: ", p.ProbabilisticSampling), err) + } + return nil +} + +func (p *SamplingStrategyResponse) readField3(iprot thrift.TProtocol) error { + p.RateLimitingSampling = &RateLimitingSamplingStrategy{} + if err := p.RateLimitingSampling.Read(iprot); err != nil { + return thrift.PrependError(fmt.Sprintf("%T error reading struct: ", p.RateLimitingSampling), err) + } + return nil +} + +func (p *SamplingStrategyResponse) readField4(iprot thrift.TProtocol) error { + p.OperationSampling = &PerOperationSamplingStrategies{} + if err := p.OperationSampling.Read(iprot); err != nil { + return thrift.PrependError(fmt.Sprintf("%T error reading struct: ", p.OperationSampling), err) + } + return nil +} + +func (p *SamplingStrategyResponse) Write(oprot thrift.TProtocol) error { + if err := oprot.WriteStructBegin("SamplingStrategyResponse"); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write struct begin error: ", p), err) + } + if err := p.writeField1(oprot); err != nil { + return err + } + if err := p.writeField2(oprot); err != nil { + return err + } + if err := p.writeField3(oprot); err != nil { + return err + } + if err := p.writeField4(oprot); err != nil { + return err + } + if err := oprot.WriteFieldStop(); err != nil { + return thrift.PrependError("write field stop error: ", err) + } + if err := oprot.WriteStructEnd(); err != nil { + return thrift.PrependError("write struct stop error: ", err) + } + return nil +} + +func (p *SamplingStrategyResponse) writeField1(oprot thrift.TProtocol) (err error) { + if err := oprot.WriteFieldBegin("strategyType", thrift.I32, 1); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write field begin error 1:strategyType: ", p), err) + } + if err := oprot.WriteI32(int32(p.StrategyType)); err != nil { + return thrift.PrependError(fmt.Sprintf("%T.strategyType (1) field write error: ", p), err) + } + if err := oprot.WriteFieldEnd(); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write field end error 1:strategyType: ", p), err) + } + return err +} + +func (p *SamplingStrategyResponse) writeField2(oprot thrift.TProtocol) (err error) { + if p.IsSetProbabilisticSampling() { + if err := oprot.WriteFieldBegin("probabilisticSampling", thrift.STRUCT, 2); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write field begin error 2:probabilisticSampling: ", p), err) + } + if err := p.ProbabilisticSampling.Write(oprot); err != nil { + return thrift.PrependError(fmt.Sprintf("%T error writing struct: ", p.ProbabilisticSampling), err) + } + if err := oprot.WriteFieldEnd(); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write field end error 2:probabilisticSampling: ", p), err) + } + } + return err +} + +func (p *SamplingStrategyResponse) writeField3(oprot thrift.TProtocol) (err error) { + if p.IsSetRateLimitingSampling() { + if err := oprot.WriteFieldBegin("rateLimitingSampling", thrift.STRUCT, 3); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write field begin error 3:rateLimitingSampling: ", p), err) + } + if err := p.RateLimitingSampling.Write(oprot); err != nil { + return thrift.PrependError(fmt.Sprintf("%T error writing struct: ", p.RateLimitingSampling), err) + } + if err := oprot.WriteFieldEnd(); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write field end error 3:rateLimitingSampling: ", p), err) + } + } + return err +} + +func (p *SamplingStrategyResponse) writeField4(oprot thrift.TProtocol) (err error) { + if p.IsSetOperationSampling() { + if err := oprot.WriteFieldBegin("operationSampling", thrift.STRUCT, 4); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write field begin error 4:operationSampling: ", p), err) + } + if err := p.OperationSampling.Write(oprot); err != nil { + return thrift.PrependError(fmt.Sprintf("%T error writing struct: ", p.OperationSampling), err) + } + if err := oprot.WriteFieldEnd(); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write field end error 4:operationSampling: ", p), err) + } + } + return err +} + +func (p *SamplingStrategyResponse) String() string { + if p == nil { + return "" + } + return fmt.Sprintf("SamplingStrategyResponse(%+v)", *p) +} diff --git a/vendor/github.com/uber/jaeger-client-go/thrift-gen/zipkincore/constants.go b/vendor/github.com/uber/jaeger-client-go/thrift-gen/zipkincore/constants.go new file mode 100644 index 000000000..dafd2b8e9 --- /dev/null +++ b/vendor/github.com/uber/jaeger-client-go/thrift-gen/zipkincore/constants.go @@ -0,0 +1,32 @@ +// Autogenerated by Thrift Compiler (0.9.3) +// DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING + +package zipkincore + +import ( + "bytes" + "fmt" + "github.com/apache/thrift/lib/go/thrift" +) + +// (needed to ensure safety because of naive import list construction.) +var _ = thrift.ZERO +var _ = fmt.Printf +var _ = bytes.Equal + +const CLIENT_SEND = "cs" +const CLIENT_RECV = "cr" +const SERVER_SEND = "ss" +const SERVER_RECV = "sr" +const WIRE_SEND = "ws" +const WIRE_RECV = "wr" +const CLIENT_SEND_FRAGMENT = "csf" +const CLIENT_RECV_FRAGMENT = "crf" +const SERVER_SEND_FRAGMENT = "ssf" +const SERVER_RECV_FRAGMENT = "srf" +const LOCAL_COMPONENT = "lc" +const CLIENT_ADDR = "ca" +const SERVER_ADDR = "sa" + +func init() { +} diff --git a/vendor/github.com/uber/jaeger-client-go/thrift-gen/zipkincore/ttypes.go b/vendor/github.com/uber/jaeger-client-go/thrift-gen/zipkincore/ttypes.go new file mode 100644 index 000000000..50c7a9944 --- /dev/null +++ b/vendor/github.com/uber/jaeger-client-go/thrift-gen/zipkincore/ttypes.go @@ -0,0 +1,1247 @@ +// Autogenerated by Thrift Compiler (0.9.3) +// DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING + +package zipkincore + +import ( + "bytes" + "fmt" + "github.com/apache/thrift/lib/go/thrift" +) + +// (needed to ensure safety because of naive import list construction.) +var _ = thrift.ZERO +var _ = fmt.Printf +var _ = bytes.Equal + +var GoUnusedProtection__ int + +type AnnotationType int64 + +const ( + AnnotationType_BOOL AnnotationType = 0 + AnnotationType_BYTES AnnotationType = 1 + AnnotationType_I16 AnnotationType = 2 + AnnotationType_I32 AnnotationType = 3 + AnnotationType_I64 AnnotationType = 4 + AnnotationType_DOUBLE AnnotationType = 5 + AnnotationType_STRING AnnotationType = 6 +) + +func (p AnnotationType) String() string { + switch p { + case AnnotationType_BOOL: + return "BOOL" + case AnnotationType_BYTES: + return "BYTES" + case AnnotationType_I16: + return "I16" + case AnnotationType_I32: + return "I32" + case AnnotationType_I64: + return "I64" + case AnnotationType_DOUBLE: + return "DOUBLE" + case AnnotationType_STRING: + return "STRING" + } + return "" +} + +func AnnotationTypeFromString(s string) (AnnotationType, error) { + switch s { + case "BOOL": + return AnnotationType_BOOL, nil + case "BYTES": + return AnnotationType_BYTES, nil + case "I16": + return AnnotationType_I16, nil + case "I32": + return AnnotationType_I32, nil + case "I64": + return AnnotationType_I64, nil + case "DOUBLE": + return AnnotationType_DOUBLE, nil + case "STRING": + return AnnotationType_STRING, nil + } + return AnnotationType(0), fmt.Errorf("not a valid AnnotationType string") +} + +func AnnotationTypePtr(v AnnotationType) *AnnotationType { return &v } + +func (p AnnotationType) MarshalText() ([]byte, error) { + return []byte(p.String()), nil +} + +func (p *AnnotationType) UnmarshalText(text []byte) error { + q, err := AnnotationTypeFromString(string(text)) + if err != nil { + return err + } + *p = q + return nil +} + +// Indicates the network context of a service recording an annotation with two +// exceptions. +// +// When a BinaryAnnotation, and key is CLIENT_ADDR or SERVER_ADDR, +// the endpoint indicates the source or destination of an RPC. This exception +// allows zipkin to display network context of uninstrumented services, or +// clients such as web browsers. +// +// Attributes: +// - Ipv4: IPv4 host address packed into 4 bytes. +// +// Ex for the ip 1.2.3.4, it would be (1 << 24) | (2 << 16) | (3 << 8) | 4 +// - Port: IPv4 port +// +// Note: this is to be treated as an unsigned integer, so watch for negatives. +// +// Conventionally, when the port isn't known, port = 0. +// - ServiceName: Service name in lowercase, such as "memcache" or "zipkin-web" +// +// Conventionally, when the service name isn't known, service_name = "unknown". +type Endpoint struct { + Ipv4 int32 `thrift:"ipv4,1" json:"ipv4"` + Port int16 `thrift:"port,2" json:"port"` + ServiceName string `thrift:"service_name,3" json:"service_name"` +} + +func NewEndpoint() *Endpoint { + return &Endpoint{} +} + +func (p *Endpoint) GetIpv4() int32 { + return p.Ipv4 +} + +func (p *Endpoint) GetPort() int16 { + return p.Port +} + +func (p *Endpoint) GetServiceName() string { + return p.ServiceName +} +func (p *Endpoint) Read(iprot thrift.TProtocol) error { + if _, err := iprot.ReadStructBegin(); err != nil { + return thrift.PrependError(fmt.Sprintf("%T read error: ", p), err) + } + + for { + _, fieldTypeId, fieldId, err := iprot.ReadFieldBegin() + if err != nil { + return thrift.PrependError(fmt.Sprintf("%T field %d read error: ", p, fieldId), err) + } + if fieldTypeId == thrift.STOP { + break + } + switch fieldId { + case 1: + if err := p.readField1(iprot); err != nil { + return err + } + case 2: + if err := p.readField2(iprot); err != nil { + return err + } + case 3: + if err := p.readField3(iprot); err != nil { + return err + } + default: + if err := iprot.Skip(fieldTypeId); err != nil { + return err + } + } + if err := iprot.ReadFieldEnd(); err != nil { + return err + } + } + if err := iprot.ReadStructEnd(); err != nil { + return thrift.PrependError(fmt.Sprintf("%T read struct end error: ", p), err) + } + return nil +} + +func (p *Endpoint) readField1(iprot thrift.TProtocol) error { + if v, err := iprot.ReadI32(); err != nil { + return thrift.PrependError("error reading field 1: ", err) + } else { + p.Ipv4 = v + } + return nil +} + +func (p *Endpoint) readField2(iprot thrift.TProtocol) error { + if v, err := iprot.ReadI16(); err != nil { + return thrift.PrependError("error reading field 2: ", err) + } else { + p.Port = v + } + return nil +} + +func (p *Endpoint) readField3(iprot thrift.TProtocol) error { + if v, err := iprot.ReadString(); err != nil { + return thrift.PrependError("error reading field 3: ", err) + } else { + p.ServiceName = v + } + return nil +} + +func (p *Endpoint) Write(oprot thrift.TProtocol) error { + if err := oprot.WriteStructBegin("Endpoint"); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write struct begin error: ", p), err) + } + if err := p.writeField1(oprot); err != nil { + return err + } + if err := p.writeField2(oprot); err != nil { + return err + } + if err := p.writeField3(oprot); err != nil { + return err + } + if err := oprot.WriteFieldStop(); err != nil { + return thrift.PrependError("write field stop error: ", err) + } + if err := oprot.WriteStructEnd(); err != nil { + return thrift.PrependError("write struct stop error: ", err) + } + return nil +} + +func (p *Endpoint) writeField1(oprot thrift.TProtocol) (err error) { + if err := oprot.WriteFieldBegin("ipv4", thrift.I32, 1); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write field begin error 1:ipv4: ", p), err) + } + if err := oprot.WriteI32(int32(p.Ipv4)); err != nil { + return thrift.PrependError(fmt.Sprintf("%T.ipv4 (1) field write error: ", p), err) + } + if err := oprot.WriteFieldEnd(); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write field end error 1:ipv4: ", p), err) + } + return err +} + +func (p *Endpoint) writeField2(oprot thrift.TProtocol) (err error) { + if err := oprot.WriteFieldBegin("port", thrift.I16, 2); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write field begin error 2:port: ", p), err) + } + if err := oprot.WriteI16(int16(p.Port)); err != nil { + return thrift.PrependError(fmt.Sprintf("%T.port (2) field write error: ", p), err) + } + if err := oprot.WriteFieldEnd(); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write field end error 2:port: ", p), err) + } + return err +} + +func (p *Endpoint) writeField3(oprot thrift.TProtocol) (err error) { + if err := oprot.WriteFieldBegin("service_name", thrift.STRING, 3); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write field begin error 3:service_name: ", p), err) + } + if err := oprot.WriteString(string(p.ServiceName)); err != nil { + return thrift.PrependError(fmt.Sprintf("%T.service_name (3) field write error: ", p), err) + } + if err := oprot.WriteFieldEnd(); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write field end error 3:service_name: ", p), err) + } + return err +} + +func (p *Endpoint) String() string { + if p == nil { + return "" + } + return fmt.Sprintf("Endpoint(%+v)", *p) +} + +// An annotation is similar to a log statement. It includes a host field which +// allows these events to be attributed properly, and also aggregatable. +// +// Attributes: +// - Timestamp: Microseconds from epoch. +// +// This value should use the most precise value possible. For example, +// gettimeofday or syncing nanoTime against a tick of currentTimeMillis. +// - Value +// - Host: Always the host that recorded the event. By specifying the host you allow +// rollup of all events (such as client requests to a service) by IP address. +type Annotation struct { + Timestamp int64 `thrift:"timestamp,1" json:"timestamp"` + Value string `thrift:"value,2" json:"value"` + Host *Endpoint `thrift:"host,3" json:"host,omitempty"` +} + +func NewAnnotation() *Annotation { + return &Annotation{} +} + +func (p *Annotation) GetTimestamp() int64 { + return p.Timestamp +} + +func (p *Annotation) GetValue() string { + return p.Value +} + +var Annotation_Host_DEFAULT *Endpoint + +func (p *Annotation) GetHost() *Endpoint { + if !p.IsSetHost() { + return Annotation_Host_DEFAULT + } + return p.Host +} +func (p *Annotation) IsSetHost() bool { + return p.Host != nil +} + +func (p *Annotation) Read(iprot thrift.TProtocol) error { + if _, err := iprot.ReadStructBegin(); err != nil { + return thrift.PrependError(fmt.Sprintf("%T read error: ", p), err) + } + + for { + _, fieldTypeId, fieldId, err := iprot.ReadFieldBegin() + if err != nil { + return thrift.PrependError(fmt.Sprintf("%T field %d read error: ", p, fieldId), err) + } + if fieldTypeId == thrift.STOP { + break + } + switch fieldId { + case 1: + if err := p.readField1(iprot); err != nil { + return err + } + case 2: + if err := p.readField2(iprot); err != nil { + return err + } + case 3: + if err := p.readField3(iprot); err != nil { + return err + } + default: + if err := iprot.Skip(fieldTypeId); err != nil { + return err + } + } + if err := iprot.ReadFieldEnd(); err != nil { + return err + } + } + if err := iprot.ReadStructEnd(); err != nil { + return thrift.PrependError(fmt.Sprintf("%T read struct end error: ", p), err) + } + return nil +} + +func (p *Annotation) readField1(iprot thrift.TProtocol) error { + if v, err := iprot.ReadI64(); err != nil { + return thrift.PrependError("error reading field 1: ", err) + } else { + p.Timestamp = v + } + return nil +} + +func (p *Annotation) readField2(iprot thrift.TProtocol) error { + if v, err := iprot.ReadString(); err != nil { + return thrift.PrependError("error reading field 2: ", err) + } else { + p.Value = v + } + return nil +} + +func (p *Annotation) readField3(iprot thrift.TProtocol) error { + p.Host = &Endpoint{} + if err := p.Host.Read(iprot); err != nil { + return thrift.PrependError(fmt.Sprintf("%T error reading struct: ", p.Host), err) + } + return nil +} + +func (p *Annotation) Write(oprot thrift.TProtocol) error { + if err := oprot.WriteStructBegin("Annotation"); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write struct begin error: ", p), err) + } + if err := p.writeField1(oprot); err != nil { + return err + } + if err := p.writeField2(oprot); err != nil { + return err + } + if err := p.writeField3(oprot); err != nil { + return err + } + if err := oprot.WriteFieldStop(); err != nil { + return thrift.PrependError("write field stop error: ", err) + } + if err := oprot.WriteStructEnd(); err != nil { + return thrift.PrependError("write struct stop error: ", err) + } + return nil +} + +func (p *Annotation) writeField1(oprot thrift.TProtocol) (err error) { + if err := oprot.WriteFieldBegin("timestamp", thrift.I64, 1); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write field begin error 1:timestamp: ", p), err) + } + if err := oprot.WriteI64(int64(p.Timestamp)); err != nil { + return thrift.PrependError(fmt.Sprintf("%T.timestamp (1) field write error: ", p), err) + } + if err := oprot.WriteFieldEnd(); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write field end error 1:timestamp: ", p), err) + } + return err +} + +func (p *Annotation) writeField2(oprot thrift.TProtocol) (err error) { + if err := oprot.WriteFieldBegin("value", thrift.STRING, 2); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write field begin error 2:value: ", p), err) + } + if err := oprot.WriteString(string(p.Value)); err != nil { + return thrift.PrependError(fmt.Sprintf("%T.value (2) field write error: ", p), err) + } + if err := oprot.WriteFieldEnd(); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write field end error 2:value: ", p), err) + } + return err +} + +func (p *Annotation) writeField3(oprot thrift.TProtocol) (err error) { + if p.IsSetHost() { + if err := oprot.WriteFieldBegin("host", thrift.STRUCT, 3); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write field begin error 3:host: ", p), err) + } + if err := p.Host.Write(oprot); err != nil { + return thrift.PrependError(fmt.Sprintf("%T error writing struct: ", p.Host), err) + } + if err := oprot.WriteFieldEnd(); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write field end error 3:host: ", p), err) + } + } + return err +} + +func (p *Annotation) String() string { + if p == nil { + return "" + } + return fmt.Sprintf("Annotation(%+v)", *p) +} + +// Binary annotations are tags applied to a Span to give it context. For +// example, a binary annotation of "http.uri" could the path to a resource in a +// RPC call. +// +// Binary annotations of type STRING are always queryable, though more a +// historical implementation detail than a structural concern. +// +// Binary annotations can repeat, and vary on the host. Similar to Annotation, +// the host indicates who logged the event. This allows you to tell the +// difference between the client and server side of the same key. For example, +// the key "http.uri" might be different on the client and server side due to +// rewriting, like "/api/v1/myresource" vs "/myresource. Via the host field, +// you can see the different points of view, which often help in debugging. +// +// Attributes: +// - Key +// - Value +// - AnnotationType +// - Host: The host that recorded tag, which allows you to differentiate between +// multiple tags with the same key. There are two exceptions to this. +// +// When the key is CLIENT_ADDR or SERVER_ADDR, host indicates the source or +// destination of an RPC. This exception allows zipkin to display network +// context of uninstrumented services, or clients such as web browsers. +type BinaryAnnotation struct { + Key string `thrift:"key,1" json:"key"` + Value []byte `thrift:"value,2" json:"value"` + AnnotationType AnnotationType `thrift:"annotation_type,3" json:"annotation_type"` + Host *Endpoint `thrift:"host,4" json:"host,omitempty"` +} + +func NewBinaryAnnotation() *BinaryAnnotation { + return &BinaryAnnotation{} +} + +func (p *BinaryAnnotation) GetKey() string { + return p.Key +} + +func (p *BinaryAnnotation) GetValue() []byte { + return p.Value +} + +func (p *BinaryAnnotation) GetAnnotationType() AnnotationType { + return p.AnnotationType +} + +var BinaryAnnotation_Host_DEFAULT *Endpoint + +func (p *BinaryAnnotation) GetHost() *Endpoint { + if !p.IsSetHost() { + return BinaryAnnotation_Host_DEFAULT + } + return p.Host +} +func (p *BinaryAnnotation) IsSetHost() bool { + return p.Host != nil +} + +func (p *BinaryAnnotation) Read(iprot thrift.TProtocol) error { + if _, err := iprot.ReadStructBegin(); err != nil { + return thrift.PrependError(fmt.Sprintf("%T read error: ", p), err) + } + + for { + _, fieldTypeId, fieldId, err := iprot.ReadFieldBegin() + if err != nil { + return thrift.PrependError(fmt.Sprintf("%T field %d read error: ", p, fieldId), err) + } + if fieldTypeId == thrift.STOP { + break + } + switch fieldId { + case 1: + if err := p.readField1(iprot); err != nil { + return err + } + case 2: + if err := p.readField2(iprot); err != nil { + return err + } + case 3: + if err := p.readField3(iprot); err != nil { + return err + } + case 4: + if err := p.readField4(iprot); err != nil { + return err + } + default: + if err := iprot.Skip(fieldTypeId); err != nil { + return err + } + } + if err := iprot.ReadFieldEnd(); err != nil { + return err + } + } + if err := iprot.ReadStructEnd(); err != nil { + return thrift.PrependError(fmt.Sprintf("%T read struct end error: ", p), err) + } + return nil +} + +func (p *BinaryAnnotation) readField1(iprot thrift.TProtocol) error { + if v, err := iprot.ReadString(); err != nil { + return thrift.PrependError("error reading field 1: ", err) + } else { + p.Key = v + } + return nil +} + +func (p *BinaryAnnotation) readField2(iprot thrift.TProtocol) error { + if v, err := iprot.ReadBinary(); err != nil { + return thrift.PrependError("error reading field 2: ", err) + } else { + p.Value = v + } + return nil +} + +func (p *BinaryAnnotation) readField3(iprot thrift.TProtocol) error { + if v, err := iprot.ReadI32(); err != nil { + return thrift.PrependError("error reading field 3: ", err) + } else { + temp := AnnotationType(v) + p.AnnotationType = temp + } + return nil +} + +func (p *BinaryAnnotation) readField4(iprot thrift.TProtocol) error { + p.Host = &Endpoint{} + if err := p.Host.Read(iprot); err != nil { + return thrift.PrependError(fmt.Sprintf("%T error reading struct: ", p.Host), err) + } + return nil +} + +func (p *BinaryAnnotation) Write(oprot thrift.TProtocol) error { + if err := oprot.WriteStructBegin("BinaryAnnotation"); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write struct begin error: ", p), err) + } + if err := p.writeField1(oprot); err != nil { + return err + } + if err := p.writeField2(oprot); err != nil { + return err + } + if err := p.writeField3(oprot); err != nil { + return err + } + if err := p.writeField4(oprot); err != nil { + return err + } + if err := oprot.WriteFieldStop(); err != nil { + return thrift.PrependError("write field stop error: ", err) + } + if err := oprot.WriteStructEnd(); err != nil { + return thrift.PrependError("write struct stop error: ", err) + } + return nil +} + +func (p *BinaryAnnotation) writeField1(oprot thrift.TProtocol) (err error) { + if err := oprot.WriteFieldBegin("key", thrift.STRING, 1); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write field begin error 1:key: ", p), err) + } + if err := oprot.WriteString(string(p.Key)); err != nil { + return thrift.PrependError(fmt.Sprintf("%T.key (1) field write error: ", p), err) + } + if err := oprot.WriteFieldEnd(); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write field end error 1:key: ", p), err) + } + return err +} + +func (p *BinaryAnnotation) writeField2(oprot thrift.TProtocol) (err error) { + if err := oprot.WriteFieldBegin("value", thrift.STRING, 2); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write field begin error 2:value: ", p), err) + } + if err := oprot.WriteBinary(p.Value); err != nil { + return thrift.PrependError(fmt.Sprintf("%T.value (2) field write error: ", p), err) + } + if err := oprot.WriteFieldEnd(); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write field end error 2:value: ", p), err) + } + return err +} + +func (p *BinaryAnnotation) writeField3(oprot thrift.TProtocol) (err error) { + if err := oprot.WriteFieldBegin("annotation_type", thrift.I32, 3); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write field begin error 3:annotation_type: ", p), err) + } + if err := oprot.WriteI32(int32(p.AnnotationType)); err != nil { + return thrift.PrependError(fmt.Sprintf("%T.annotation_type (3) field write error: ", p), err) + } + if err := oprot.WriteFieldEnd(); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write field end error 3:annotation_type: ", p), err) + } + return err +} + +func (p *BinaryAnnotation) writeField4(oprot thrift.TProtocol) (err error) { + if p.IsSetHost() { + if err := oprot.WriteFieldBegin("host", thrift.STRUCT, 4); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write field begin error 4:host: ", p), err) + } + if err := p.Host.Write(oprot); err != nil { + return thrift.PrependError(fmt.Sprintf("%T error writing struct: ", p.Host), err) + } + if err := oprot.WriteFieldEnd(); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write field end error 4:host: ", p), err) + } + } + return err +} + +func (p *BinaryAnnotation) String() string { + if p == nil { + return "" + } + return fmt.Sprintf("BinaryAnnotation(%+v)", *p) +} + +// A trace is a series of spans (often RPC calls) which form a latency tree. +// +// The root span is where trace_id = id and parent_id = Nil. The root span is +// usually the longest interval in the trace, starting with a SERVER_RECV +// annotation and ending with a SERVER_SEND. +// +// Attributes: +// - TraceID +// - Name: Span name in lowercase, rpc method for example +// +// Conventionally, when the span name isn't known, name = "unknown". +// - ID +// - ParentID +// - Annotations +// - BinaryAnnotations +// - Debug +// - Timestamp: Microseconds from epoch of the creation of this span. +// +// This value should be set directly by instrumentation, using the most +// precise value possible. For example, gettimeofday or syncing nanoTime +// against a tick of currentTimeMillis. +// +// For compatibilty with instrumentation that precede this field, collectors +// or span stores can derive this via Annotation.timestamp. +// For example, SERVER_RECV.timestamp or CLIENT_SEND.timestamp. +// +// This field is optional for compatibility with old data: first-party span +// stores are expected to support this at time of introduction. +// - Duration: Measurement of duration in microseconds, used to support queries. +// +// This value should be set directly, where possible. Doing so encourages +// precise measurement decoupled from problems of clocks, such as skew or NTP +// updates causing time to move backwards. +// +// For compatibilty with instrumentation that precede this field, collectors +// or span stores can derive this by subtracting Annotation.timestamp. +// For example, SERVER_SEND.timestamp - SERVER_RECV.timestamp. +// +// If this field is persisted as unset, zipkin will continue to work, except +// duration query support will be implementation-specific. Similarly, setting +// this field non-atomically is implementation-specific. +// +// This field is i64 vs i32 to support spans longer than 35 minutes. +type Span struct { + TraceID int64 `thrift:"trace_id,1" json:"trace_id"` + // unused field # 2 + Name string `thrift:"name,3" json:"name"` + ID int64 `thrift:"id,4" json:"id"` + ParentID *int64 `thrift:"parent_id,5" json:"parent_id,omitempty"` + Annotations []*Annotation `thrift:"annotations,6" json:"annotations"` + // unused field # 7 + BinaryAnnotations []*BinaryAnnotation `thrift:"binary_annotations,8" json:"binary_annotations"` + Debug bool `thrift:"debug,9" json:"debug,omitempty"` + Timestamp *int64 `thrift:"timestamp,10" json:"timestamp,omitempty"` + Duration *int64 `thrift:"duration,11" json:"duration,omitempty"` +} + +func NewSpan() *Span { + return &Span{} +} + +func (p *Span) GetTraceID() int64 { + return p.TraceID +} + +func (p *Span) GetName() string { + return p.Name +} + +func (p *Span) GetID() int64 { + return p.ID +} + +var Span_ParentID_DEFAULT int64 + +func (p *Span) GetParentID() int64 { + if !p.IsSetParentID() { + return Span_ParentID_DEFAULT + } + return *p.ParentID +} + +func (p *Span) GetAnnotations() []*Annotation { + return p.Annotations +} + +func (p *Span) GetBinaryAnnotations() []*BinaryAnnotation { + return p.BinaryAnnotations +} + +var Span_Debug_DEFAULT bool = false + +func (p *Span) GetDebug() bool { + return p.Debug +} + +var Span_Timestamp_DEFAULT int64 + +func (p *Span) GetTimestamp() int64 { + if !p.IsSetTimestamp() { + return Span_Timestamp_DEFAULT + } + return *p.Timestamp +} + +var Span_Duration_DEFAULT int64 + +func (p *Span) GetDuration() int64 { + if !p.IsSetDuration() { + return Span_Duration_DEFAULT + } + return *p.Duration +} +func (p *Span) IsSetParentID() bool { + return p.ParentID != nil +} + +func (p *Span) IsSetDebug() bool { + return p.Debug != Span_Debug_DEFAULT +} + +func (p *Span) IsSetTimestamp() bool { + return p.Timestamp != nil +} + +func (p *Span) IsSetDuration() bool { + return p.Duration != nil +} + +func (p *Span) Read(iprot thrift.TProtocol) error { + if _, err := iprot.ReadStructBegin(); err != nil { + return thrift.PrependError(fmt.Sprintf("%T read error: ", p), err) + } + + for { + _, fieldTypeId, fieldId, err := iprot.ReadFieldBegin() + if err != nil { + return thrift.PrependError(fmt.Sprintf("%T field %d read error: ", p, fieldId), err) + } + if fieldTypeId == thrift.STOP { + break + } + switch fieldId { + case 1: + if err := p.readField1(iprot); err != nil { + return err + } + case 3: + if err := p.readField3(iprot); err != nil { + return err + } + case 4: + if err := p.readField4(iprot); err != nil { + return err + } + case 5: + if err := p.readField5(iprot); err != nil { + return err + } + case 6: + if err := p.readField6(iprot); err != nil { + return err + } + case 8: + if err := p.readField8(iprot); err != nil { + return err + } + case 9: + if err := p.readField9(iprot); err != nil { + return err + } + case 10: + if err := p.readField10(iprot); err != nil { + return err + } + case 11: + if err := p.readField11(iprot); err != nil { + return err + } + default: + if err := iprot.Skip(fieldTypeId); err != nil { + return err + } + } + if err := iprot.ReadFieldEnd(); err != nil { + return err + } + } + if err := iprot.ReadStructEnd(); err != nil { + return thrift.PrependError(fmt.Sprintf("%T read struct end error: ", p), err) + } + return nil +} + +func (p *Span) readField1(iprot thrift.TProtocol) error { + if v, err := iprot.ReadI64(); err != nil { + return thrift.PrependError("error reading field 1: ", err) + } else { + p.TraceID = v + } + return nil +} + +func (p *Span) readField3(iprot thrift.TProtocol) error { + if v, err := iprot.ReadString(); err != nil { + return thrift.PrependError("error reading field 3: ", err) + } else { + p.Name = v + } + return nil +} + +func (p *Span) readField4(iprot thrift.TProtocol) error { + if v, err := iprot.ReadI64(); err != nil { + return thrift.PrependError("error reading field 4: ", err) + } else { + p.ID = v + } + return nil +} + +func (p *Span) readField5(iprot thrift.TProtocol) error { + if v, err := iprot.ReadI64(); err != nil { + return thrift.PrependError("error reading field 5: ", err) + } else { + p.ParentID = &v + } + return nil +} + +func (p *Span) readField6(iprot thrift.TProtocol) error { + _, size, err := iprot.ReadListBegin() + if err != nil { + return thrift.PrependError("error reading list begin: ", err) + } + tSlice := make([]*Annotation, 0, size) + p.Annotations = tSlice + for i := 0; i < size; i++ { + _elem0 := &Annotation{} + if err := _elem0.Read(iprot); err != nil { + return thrift.PrependError(fmt.Sprintf("%T error reading struct: ", _elem0), err) + } + p.Annotations = append(p.Annotations, _elem0) + } + if err := iprot.ReadListEnd(); err != nil { + return thrift.PrependError("error reading list end: ", err) + } + return nil +} + +func (p *Span) readField8(iprot thrift.TProtocol) error { + _, size, err := iprot.ReadListBegin() + if err != nil { + return thrift.PrependError("error reading list begin: ", err) + } + tSlice := make([]*BinaryAnnotation, 0, size) + p.BinaryAnnotations = tSlice + for i := 0; i < size; i++ { + _elem1 := &BinaryAnnotation{} + if err := _elem1.Read(iprot); err != nil { + return thrift.PrependError(fmt.Sprintf("%T error reading struct: ", _elem1), err) + } + p.BinaryAnnotations = append(p.BinaryAnnotations, _elem1) + } + if err := iprot.ReadListEnd(); err != nil { + return thrift.PrependError("error reading list end: ", err) + } + return nil +} + +func (p *Span) readField9(iprot thrift.TProtocol) error { + if v, err := iprot.ReadBool(); err != nil { + return thrift.PrependError("error reading field 9: ", err) + } else { + p.Debug = v + } + return nil +} + +func (p *Span) readField10(iprot thrift.TProtocol) error { + if v, err := iprot.ReadI64(); err != nil { + return thrift.PrependError("error reading field 10: ", err) + } else { + p.Timestamp = &v + } + return nil +} + +func (p *Span) readField11(iprot thrift.TProtocol) error { + if v, err := iprot.ReadI64(); err != nil { + return thrift.PrependError("error reading field 11: ", err) + } else { + p.Duration = &v + } + return nil +} + +func (p *Span) Write(oprot thrift.TProtocol) error { + if err := oprot.WriteStructBegin("Span"); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write struct begin error: ", p), err) + } + if err := p.writeField1(oprot); err != nil { + return err + } + if err := p.writeField3(oprot); err != nil { + return err + } + if err := p.writeField4(oprot); err != nil { + return err + } + if err := p.writeField5(oprot); err != nil { + return err + } + if err := p.writeField6(oprot); err != nil { + return err + } + if err := p.writeField8(oprot); err != nil { + return err + } + if err := p.writeField9(oprot); err != nil { + return err + } + if err := p.writeField10(oprot); err != nil { + return err + } + if err := p.writeField11(oprot); err != nil { + return err + } + if err := oprot.WriteFieldStop(); err != nil { + return thrift.PrependError("write field stop error: ", err) + } + if err := oprot.WriteStructEnd(); err != nil { + return thrift.PrependError("write struct stop error: ", err) + } + return nil +} + +func (p *Span) writeField1(oprot thrift.TProtocol) (err error) { + if err := oprot.WriteFieldBegin("trace_id", thrift.I64, 1); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write field begin error 1:trace_id: ", p), err) + } + if err := oprot.WriteI64(int64(p.TraceID)); err != nil { + return thrift.PrependError(fmt.Sprintf("%T.trace_id (1) field write error: ", p), err) + } + if err := oprot.WriteFieldEnd(); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write field end error 1:trace_id: ", p), err) + } + return err +} + +func (p *Span) writeField3(oprot thrift.TProtocol) (err error) { + if err := oprot.WriteFieldBegin("name", thrift.STRING, 3); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write field begin error 3:name: ", p), err) + } + if err := oprot.WriteString(string(p.Name)); err != nil { + return thrift.PrependError(fmt.Sprintf("%T.name (3) field write error: ", p), err) + } + if err := oprot.WriteFieldEnd(); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write field end error 3:name: ", p), err) + } + return err +} + +func (p *Span) writeField4(oprot thrift.TProtocol) (err error) { + if err := oprot.WriteFieldBegin("id", thrift.I64, 4); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write field begin error 4:id: ", p), err) + } + if err := oprot.WriteI64(int64(p.ID)); err != nil { + return thrift.PrependError(fmt.Sprintf("%T.id (4) field write error: ", p), err) + } + if err := oprot.WriteFieldEnd(); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write field end error 4:id: ", p), err) + } + return err +} + +func (p *Span) writeField5(oprot thrift.TProtocol) (err error) { + if p.IsSetParentID() { + if err := oprot.WriteFieldBegin("parent_id", thrift.I64, 5); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write field begin error 5:parent_id: ", p), err) + } + if err := oprot.WriteI64(int64(*p.ParentID)); err != nil { + return thrift.PrependError(fmt.Sprintf("%T.parent_id (5) field write error: ", p), err) + } + if err := oprot.WriteFieldEnd(); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write field end error 5:parent_id: ", p), err) + } + } + return err +} + +func (p *Span) writeField6(oprot thrift.TProtocol) (err error) { + if err := oprot.WriteFieldBegin("annotations", thrift.LIST, 6); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write field begin error 6:annotations: ", p), err) + } + if err := oprot.WriteListBegin(thrift.STRUCT, len(p.Annotations)); err != nil { + return thrift.PrependError("error writing list begin: ", err) + } + for _, v := range p.Annotations { + if err := v.Write(oprot); err != nil { + return thrift.PrependError(fmt.Sprintf("%T error writing struct: ", v), err) + } + } + if err := oprot.WriteListEnd(); err != nil { + return thrift.PrependError("error writing list end: ", err) + } + if err := oprot.WriteFieldEnd(); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write field end error 6:annotations: ", p), err) + } + return err +} + +func (p *Span) writeField8(oprot thrift.TProtocol) (err error) { + if err := oprot.WriteFieldBegin("binary_annotations", thrift.LIST, 8); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write field begin error 8:binary_annotations: ", p), err) + } + if err := oprot.WriteListBegin(thrift.STRUCT, len(p.BinaryAnnotations)); err != nil { + return thrift.PrependError("error writing list begin: ", err) + } + for _, v := range p.BinaryAnnotations { + if err := v.Write(oprot); err != nil { + return thrift.PrependError(fmt.Sprintf("%T error writing struct: ", v), err) + } + } + if err := oprot.WriteListEnd(); err != nil { + return thrift.PrependError("error writing list end: ", err) + } + if err := oprot.WriteFieldEnd(); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write field end error 8:binary_annotations: ", p), err) + } + return err +} + +func (p *Span) writeField9(oprot thrift.TProtocol) (err error) { + if p.IsSetDebug() { + if err := oprot.WriteFieldBegin("debug", thrift.BOOL, 9); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write field begin error 9:debug: ", p), err) + } + if err := oprot.WriteBool(bool(p.Debug)); err != nil { + return thrift.PrependError(fmt.Sprintf("%T.debug (9) field write error: ", p), err) + } + if err := oprot.WriteFieldEnd(); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write field end error 9:debug: ", p), err) + } + } + return err +} + +func (p *Span) writeField10(oprot thrift.TProtocol) (err error) { + if p.IsSetTimestamp() { + if err := oprot.WriteFieldBegin("timestamp", thrift.I64, 10); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write field begin error 10:timestamp: ", p), err) + } + if err := oprot.WriteI64(int64(*p.Timestamp)); err != nil { + return thrift.PrependError(fmt.Sprintf("%T.timestamp (10) field write error: ", p), err) + } + if err := oprot.WriteFieldEnd(); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write field end error 10:timestamp: ", p), err) + } + } + return err +} + +func (p *Span) writeField11(oprot thrift.TProtocol) (err error) { + if p.IsSetDuration() { + if err := oprot.WriteFieldBegin("duration", thrift.I64, 11); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write field begin error 11:duration: ", p), err) + } + if err := oprot.WriteI64(int64(*p.Duration)); err != nil { + return thrift.PrependError(fmt.Sprintf("%T.duration (11) field write error: ", p), err) + } + if err := oprot.WriteFieldEnd(); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write field end error 11:duration: ", p), err) + } + } + return err +} + +func (p *Span) String() string { + if p == nil { + return "" + } + return fmt.Sprintf("Span(%+v)", *p) +} + +// Attributes: +// - Ok +type Response struct { + Ok bool `thrift:"ok,1,required" json:"ok"` +} + +func NewResponse() *Response { + return &Response{} +} + +func (p *Response) GetOk() bool { + return p.Ok +} +func (p *Response) Read(iprot thrift.TProtocol) error { + if _, err := iprot.ReadStructBegin(); err != nil { + return thrift.PrependError(fmt.Sprintf("%T read error: ", p), err) + } + + var issetOk bool = false + + for { + _, fieldTypeId, fieldId, err := iprot.ReadFieldBegin() + if err != nil { + return thrift.PrependError(fmt.Sprintf("%T field %d read error: ", p, fieldId), err) + } + if fieldTypeId == thrift.STOP { + break + } + switch fieldId { + case 1: + if err := p.readField1(iprot); err != nil { + return err + } + issetOk = true + default: + if err := iprot.Skip(fieldTypeId); err != nil { + return err + } + } + if err := iprot.ReadFieldEnd(); err != nil { + return err + } + } + if err := iprot.ReadStructEnd(); err != nil { + return thrift.PrependError(fmt.Sprintf("%T read struct end error: ", p), err) + } + if !issetOk { + return thrift.NewTProtocolExceptionWithType(thrift.INVALID_DATA, fmt.Errorf("Required field Ok is not set")) + } + return nil +} + +func (p *Response) readField1(iprot thrift.TProtocol) error { + if v, err := iprot.ReadBool(); err != nil { + return thrift.PrependError("error reading field 1: ", err) + } else { + p.Ok = v + } + return nil +} + +func (p *Response) Write(oprot thrift.TProtocol) error { + if err := oprot.WriteStructBegin("Response"); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write struct begin error: ", p), err) + } + if err := p.writeField1(oprot); err != nil { + return err + } + if err := oprot.WriteFieldStop(); err != nil { + return thrift.PrependError("write field stop error: ", err) + } + if err := oprot.WriteStructEnd(); err != nil { + return thrift.PrependError("write struct stop error: ", err) + } + return nil +} + +func (p *Response) writeField1(oprot thrift.TProtocol) (err error) { + if err := oprot.WriteFieldBegin("ok", thrift.BOOL, 1); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write field begin error 1:ok: ", p), err) + } + if err := oprot.WriteBool(bool(p.Ok)); err != nil { + return thrift.PrependError(fmt.Sprintf("%T.ok (1) field write error: ", p), err) + } + if err := oprot.WriteFieldEnd(); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write field end error 1:ok: ", p), err) + } + return err +} + +func (p *Response) String() string { + if p == nil { + return "" + } + return fmt.Sprintf("Response(%+v)", *p) +} diff --git a/vendor/github.com/uber/jaeger-client-go/thrift-gen/zipkincore/zipkincollector.go b/vendor/github.com/uber/jaeger-client-go/thrift-gen/zipkincore/zipkincollector.go new file mode 100644 index 000000000..bcc54f36e --- /dev/null +++ b/vendor/github.com/uber/jaeger-client-go/thrift-gen/zipkincore/zipkincollector.go @@ -0,0 +1,446 @@ +// Autogenerated by Thrift Compiler (0.9.3) +// DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING + +package zipkincore + +import ( + "bytes" + "fmt" + "github.com/apache/thrift/lib/go/thrift" +) + +// (needed to ensure safety because of naive import list construction.) +var _ = thrift.ZERO +var _ = fmt.Printf +var _ = bytes.Equal + +type ZipkinCollector interface { + // Parameters: + // - Spans + SubmitZipkinBatch(spans []*Span) (r []*Response, err error) +} + +type ZipkinCollectorClient struct { + Transport thrift.TTransport + ProtocolFactory thrift.TProtocolFactory + InputProtocol thrift.TProtocol + OutputProtocol thrift.TProtocol + SeqId int32 +} + +func NewZipkinCollectorClientFactory(t thrift.TTransport, f thrift.TProtocolFactory) *ZipkinCollectorClient { + return &ZipkinCollectorClient{Transport: t, + ProtocolFactory: f, + InputProtocol: f.GetProtocol(t), + OutputProtocol: f.GetProtocol(t), + SeqId: 0, + } +} + +func NewZipkinCollectorClientProtocol(t thrift.TTransport, iprot thrift.TProtocol, oprot thrift.TProtocol) *ZipkinCollectorClient { + return &ZipkinCollectorClient{Transport: t, + ProtocolFactory: nil, + InputProtocol: iprot, + OutputProtocol: oprot, + SeqId: 0, + } +} + +// Parameters: +// - Spans +func (p *ZipkinCollectorClient) SubmitZipkinBatch(spans []*Span) (r []*Response, err error) { + if err = p.sendSubmitZipkinBatch(spans); err != nil { + return + } + return p.recvSubmitZipkinBatch() +} + +func (p *ZipkinCollectorClient) sendSubmitZipkinBatch(spans []*Span) (err error) { + oprot := p.OutputProtocol + if oprot == nil { + oprot = p.ProtocolFactory.GetProtocol(p.Transport) + p.OutputProtocol = oprot + } + p.SeqId++ + if err = oprot.WriteMessageBegin("submitZipkinBatch", thrift.CALL, p.SeqId); err != nil { + return + } + args := ZipkinCollectorSubmitZipkinBatchArgs{ + Spans: spans, + } + if err = args.Write(oprot); err != nil { + return + } + if err = oprot.WriteMessageEnd(); err != nil { + return + } + return oprot.Flush() +} + +func (p *ZipkinCollectorClient) recvSubmitZipkinBatch() (value []*Response, err error) { + iprot := p.InputProtocol + if iprot == nil { + iprot = p.ProtocolFactory.GetProtocol(p.Transport) + p.InputProtocol = iprot + } + method, mTypeId, seqId, err := iprot.ReadMessageBegin() + if err != nil { + return + } + if method != "submitZipkinBatch" { + err = thrift.NewTApplicationException(thrift.WRONG_METHOD_NAME, "submitZipkinBatch failed: wrong method name") + return + } + if p.SeqId != seqId { + err = thrift.NewTApplicationException(thrift.BAD_SEQUENCE_ID, "submitZipkinBatch failed: out of sequence response") + return + } + if mTypeId == thrift.EXCEPTION { + error2 := thrift.NewTApplicationException(thrift.UNKNOWN_APPLICATION_EXCEPTION, "Unknown Exception") + var error3 error + error3, err = error2.Read(iprot) + if err != nil { + return + } + if err = iprot.ReadMessageEnd(); err != nil { + return + } + err = error3 + return + } + if mTypeId != thrift.REPLY { + err = thrift.NewTApplicationException(thrift.INVALID_MESSAGE_TYPE_EXCEPTION, "submitZipkinBatch failed: invalid message type") + return + } + result := ZipkinCollectorSubmitZipkinBatchResult{} + if err = result.Read(iprot); err != nil { + return + } + if err = iprot.ReadMessageEnd(); err != nil { + return + } + value = result.GetSuccess() + return +} + +type ZipkinCollectorProcessor struct { + processorMap map[string]thrift.TProcessorFunction + handler ZipkinCollector +} + +func (p *ZipkinCollectorProcessor) AddToProcessorMap(key string, processor thrift.TProcessorFunction) { + p.processorMap[key] = processor +} + +func (p *ZipkinCollectorProcessor) GetProcessorFunction(key string) (processor thrift.TProcessorFunction, ok bool) { + processor, ok = p.processorMap[key] + return processor, ok +} + +func (p *ZipkinCollectorProcessor) ProcessorMap() map[string]thrift.TProcessorFunction { + return p.processorMap +} + +func NewZipkinCollectorProcessor(handler ZipkinCollector) *ZipkinCollectorProcessor { + + self4 := &ZipkinCollectorProcessor{handler: handler, processorMap: make(map[string]thrift.TProcessorFunction)} + self4.processorMap["submitZipkinBatch"] = &zipkinCollectorProcessorSubmitZipkinBatch{handler: handler} + return self4 +} + +func (p *ZipkinCollectorProcessor) Process(iprot, oprot thrift.TProtocol) (success bool, err thrift.TException) { + name, _, seqId, err := iprot.ReadMessageBegin() + if err != nil { + return false, err + } + if processor, ok := p.GetProcessorFunction(name); ok { + return processor.Process(seqId, iprot, oprot) + } + iprot.Skip(thrift.STRUCT) + iprot.ReadMessageEnd() + x5 := thrift.NewTApplicationException(thrift.UNKNOWN_METHOD, "Unknown function "+name) + oprot.WriteMessageBegin(name, thrift.EXCEPTION, seqId) + x5.Write(oprot) + oprot.WriteMessageEnd() + oprot.Flush() + return false, x5 + +} + +type zipkinCollectorProcessorSubmitZipkinBatch struct { + handler ZipkinCollector +} + +func (p *zipkinCollectorProcessorSubmitZipkinBatch) Process(seqId int32, iprot, oprot thrift.TProtocol) (success bool, err thrift.TException) { + args := ZipkinCollectorSubmitZipkinBatchArgs{} + if err = args.Read(iprot); err != nil { + iprot.ReadMessageEnd() + x := thrift.NewTApplicationException(thrift.PROTOCOL_ERROR, err.Error()) + oprot.WriteMessageBegin("submitZipkinBatch", thrift.EXCEPTION, seqId) + x.Write(oprot) + oprot.WriteMessageEnd() + oprot.Flush() + return false, err + } + + iprot.ReadMessageEnd() + result := ZipkinCollectorSubmitZipkinBatchResult{} + var retval []*Response + var err2 error + if retval, err2 = p.handler.SubmitZipkinBatch(args.Spans); err2 != nil { + x := thrift.NewTApplicationException(thrift.INTERNAL_ERROR, "Internal error processing submitZipkinBatch: "+err2.Error()) + oprot.WriteMessageBegin("submitZipkinBatch", thrift.EXCEPTION, seqId) + x.Write(oprot) + oprot.WriteMessageEnd() + oprot.Flush() + return true, err2 + } else { + result.Success = retval + } + if err2 = oprot.WriteMessageBegin("submitZipkinBatch", thrift.REPLY, seqId); err2 != nil { + err = err2 + } + if err2 = result.Write(oprot); err == nil && err2 != nil { + err = err2 + } + if err2 = oprot.WriteMessageEnd(); err == nil && err2 != nil { + err = err2 + } + if err2 = oprot.Flush(); err == nil && err2 != nil { + err = err2 + } + if err != nil { + return + } + return true, err +} + +// HELPER FUNCTIONS AND STRUCTURES + +// Attributes: +// - Spans +type ZipkinCollectorSubmitZipkinBatchArgs struct { + Spans []*Span `thrift:"spans,1" json:"spans"` +} + +func NewZipkinCollectorSubmitZipkinBatchArgs() *ZipkinCollectorSubmitZipkinBatchArgs { + return &ZipkinCollectorSubmitZipkinBatchArgs{} +} + +func (p *ZipkinCollectorSubmitZipkinBatchArgs) GetSpans() []*Span { + return p.Spans +} +func (p *ZipkinCollectorSubmitZipkinBatchArgs) Read(iprot thrift.TProtocol) error { + if _, err := iprot.ReadStructBegin(); err != nil { + return thrift.PrependError(fmt.Sprintf("%T read error: ", p), err) + } + + for { + _, fieldTypeId, fieldId, err := iprot.ReadFieldBegin() + if err != nil { + return thrift.PrependError(fmt.Sprintf("%T field %d read error: ", p, fieldId), err) + } + if fieldTypeId == thrift.STOP { + break + } + switch fieldId { + case 1: + if err := p.readField1(iprot); err != nil { + return err + } + default: + if err := iprot.Skip(fieldTypeId); err != nil { + return err + } + } + if err := iprot.ReadFieldEnd(); err != nil { + return err + } + } + if err := iprot.ReadStructEnd(); err != nil { + return thrift.PrependError(fmt.Sprintf("%T read struct end error: ", p), err) + } + return nil +} + +func (p *ZipkinCollectorSubmitZipkinBatchArgs) readField1(iprot thrift.TProtocol) error { + _, size, err := iprot.ReadListBegin() + if err != nil { + return thrift.PrependError("error reading list begin: ", err) + } + tSlice := make([]*Span, 0, size) + p.Spans = tSlice + for i := 0; i < size; i++ { + _elem6 := &Span{} + if err := _elem6.Read(iprot); err != nil { + return thrift.PrependError(fmt.Sprintf("%T error reading struct: ", _elem6), err) + } + p.Spans = append(p.Spans, _elem6) + } + if err := iprot.ReadListEnd(); err != nil { + return thrift.PrependError("error reading list end: ", err) + } + return nil +} + +func (p *ZipkinCollectorSubmitZipkinBatchArgs) Write(oprot thrift.TProtocol) error { + if err := oprot.WriteStructBegin("submitZipkinBatch_args"); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write struct begin error: ", p), err) + } + if err := p.writeField1(oprot); err != nil { + return err + } + if err := oprot.WriteFieldStop(); err != nil { + return thrift.PrependError("write field stop error: ", err) + } + if err := oprot.WriteStructEnd(); err != nil { + return thrift.PrependError("write struct stop error: ", err) + } + return nil +} + +func (p *ZipkinCollectorSubmitZipkinBatchArgs) writeField1(oprot thrift.TProtocol) (err error) { + if err := oprot.WriteFieldBegin("spans", thrift.LIST, 1); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write field begin error 1:spans: ", p), err) + } + if err := oprot.WriteListBegin(thrift.STRUCT, len(p.Spans)); err != nil { + return thrift.PrependError("error writing list begin: ", err) + } + for _, v := range p.Spans { + if err := v.Write(oprot); err != nil { + return thrift.PrependError(fmt.Sprintf("%T error writing struct: ", v), err) + } + } + if err := oprot.WriteListEnd(); err != nil { + return thrift.PrependError("error writing list end: ", err) + } + if err := oprot.WriteFieldEnd(); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write field end error 1:spans: ", p), err) + } + return err +} + +func (p *ZipkinCollectorSubmitZipkinBatchArgs) String() string { + if p == nil { + return "" + } + return fmt.Sprintf("ZipkinCollectorSubmitZipkinBatchArgs(%+v)", *p) +} + +// Attributes: +// - Success +type ZipkinCollectorSubmitZipkinBatchResult struct { + Success []*Response `thrift:"success,0" json:"success,omitempty"` +} + +func NewZipkinCollectorSubmitZipkinBatchResult() *ZipkinCollectorSubmitZipkinBatchResult { + return &ZipkinCollectorSubmitZipkinBatchResult{} +} + +var ZipkinCollectorSubmitZipkinBatchResult_Success_DEFAULT []*Response + +func (p *ZipkinCollectorSubmitZipkinBatchResult) GetSuccess() []*Response { + return p.Success +} +func (p *ZipkinCollectorSubmitZipkinBatchResult) IsSetSuccess() bool { + return p.Success != nil +} + +func (p *ZipkinCollectorSubmitZipkinBatchResult) Read(iprot thrift.TProtocol) error { + if _, err := iprot.ReadStructBegin(); err != nil { + return thrift.PrependError(fmt.Sprintf("%T read error: ", p), err) + } + + for { + _, fieldTypeId, fieldId, err := iprot.ReadFieldBegin() + if err != nil { + return thrift.PrependError(fmt.Sprintf("%T field %d read error: ", p, fieldId), err) + } + if fieldTypeId == thrift.STOP { + break + } + switch fieldId { + case 0: + if err := p.readField0(iprot); err != nil { + return err + } + default: + if err := iprot.Skip(fieldTypeId); err != nil { + return err + } + } + if err := iprot.ReadFieldEnd(); err != nil { + return err + } + } + if err := iprot.ReadStructEnd(); err != nil { + return thrift.PrependError(fmt.Sprintf("%T read struct end error: ", p), err) + } + return nil +} + +func (p *ZipkinCollectorSubmitZipkinBatchResult) readField0(iprot thrift.TProtocol) error { + _, size, err := iprot.ReadListBegin() + if err != nil { + return thrift.PrependError("error reading list begin: ", err) + } + tSlice := make([]*Response, 0, size) + p.Success = tSlice + for i := 0; i < size; i++ { + _elem7 := &Response{} + if err := _elem7.Read(iprot); err != nil { + return thrift.PrependError(fmt.Sprintf("%T error reading struct: ", _elem7), err) + } + p.Success = append(p.Success, _elem7) + } + if err := iprot.ReadListEnd(); err != nil { + return thrift.PrependError("error reading list end: ", err) + } + return nil +} + +func (p *ZipkinCollectorSubmitZipkinBatchResult) Write(oprot thrift.TProtocol) error { + if err := oprot.WriteStructBegin("submitZipkinBatch_result"); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write struct begin error: ", p), err) + } + if err := p.writeField0(oprot); err != nil { + return err + } + if err := oprot.WriteFieldStop(); err != nil { + return thrift.PrependError("write field stop error: ", err) + } + if err := oprot.WriteStructEnd(); err != nil { + return thrift.PrependError("write struct stop error: ", err) + } + return nil +} + +func (p *ZipkinCollectorSubmitZipkinBatchResult) writeField0(oprot thrift.TProtocol) (err error) { + if p.IsSetSuccess() { + if err := oprot.WriteFieldBegin("success", thrift.LIST, 0); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write field begin error 0:success: ", p), err) + } + if err := oprot.WriteListBegin(thrift.STRUCT, len(p.Success)); err != nil { + return thrift.PrependError("error writing list begin: ", err) + } + for _, v := range p.Success { + if err := v.Write(oprot); err != nil { + return thrift.PrependError(fmt.Sprintf("%T error writing struct: ", v), err) + } + } + if err := oprot.WriteListEnd(); err != nil { + return thrift.PrependError("error writing list end: ", err) + } + if err := oprot.WriteFieldEnd(); err != nil { + return thrift.PrependError(fmt.Sprintf("%T write field end error 0:success: ", p), err) + } + } + return err +} + +func (p *ZipkinCollectorSubmitZipkinBatchResult) String() string { + if p == nil { + return "" + } + return fmt.Sprintf("ZipkinCollectorSubmitZipkinBatchResult(%+v)", *p) +} diff --git a/vendor/github.com/uber/jaeger-client-go/tracer.go b/vendor/github.com/uber/jaeger-client-go/tracer.go new file mode 100644 index 000000000..49fb099e3 --- /dev/null +++ b/vendor/github.com/uber/jaeger-client-go/tracer.go @@ -0,0 +1,396 @@ +// Copyright (c) 2017 Uber Technologies, Inc. +// +// 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. + +package jaeger + +import ( + "fmt" + "io" + "os" + "reflect" + "sync" + "time" + + "github.com/opentracing/opentracing-go" + "github.com/opentracing/opentracing-go/ext" + + "github.com/uber/jaeger-client-go/internal/baggage" + "github.com/uber/jaeger-client-go/log" + "github.com/uber/jaeger-client-go/utils" +) + +// Tracer implements opentracing.Tracer. +type Tracer struct { + serviceName string + hostIPv4 uint32 // this is for zipkin endpoint conversion + + sampler Sampler + reporter Reporter + metrics Metrics + logger log.Logger + + timeNow func() time.Time + randomNumber func() uint64 + + options struct { + poolSpans bool + gen128Bit bool // whether to generate 128bit trace IDs + zipkinSharedRPCSpan bool + highTraceIDGenerator func() uint64 // custom high trace ID generator + // more options to come + } + // pool for Span objects + spanPool sync.Pool + + injectors map[interface{}]Injector + extractors map[interface{}]Extractor + + observer compositeObserver + + tags []Tag + + baggageRestrictionManager baggage.RestrictionManager + baggageSetter *baggageSetter +} + +// NewTracer creates Tracer implementation that reports tracing to Jaeger. +// The returned io.Closer can be used in shutdown hooks to ensure that the internal +// queue of the Reporter is drained and all buffered spans are submitted to collectors. +func NewTracer( + serviceName string, + sampler Sampler, + reporter Reporter, + options ...TracerOption, +) (opentracing.Tracer, io.Closer) { + t := &Tracer{ + serviceName: serviceName, + sampler: sampler, + reporter: reporter, + injectors: make(map[interface{}]Injector), + extractors: make(map[interface{}]Extractor), + metrics: *NewNullMetrics(), + spanPool: sync.Pool{New: func() interface{} { + return &Span{} + }}, + } + + for _, option := range options { + option(t) + } + + // register default injectors/extractors unless they are already provided via options + textPropagator := newTextMapPropagator(getDefaultHeadersConfig(), t.metrics) + t.addCodec(opentracing.TextMap, textPropagator, textPropagator) + + httpHeaderPropagator := newHTTPHeaderPropagator(getDefaultHeadersConfig(), t.metrics) + t.addCodec(opentracing.HTTPHeaders, httpHeaderPropagator, httpHeaderPropagator) + + binaryPropagator := newBinaryPropagator(t) + t.addCodec(opentracing.Binary, binaryPropagator, binaryPropagator) + + // TODO remove after TChannel supports OpenTracing + interopPropagator := &jaegerTraceContextPropagator{tracer: t} + t.addCodec(SpanContextFormat, interopPropagator, interopPropagator) + + zipkinPropagator := &zipkinPropagator{tracer: t} + t.addCodec(ZipkinSpanFormat, zipkinPropagator, zipkinPropagator) + + if t.baggageRestrictionManager != nil { + t.baggageSetter = newBaggageSetter(t.baggageRestrictionManager, &t.metrics) + } else { + t.baggageSetter = newBaggageSetter(baggage.NewDefaultRestrictionManager(0), &t.metrics) + } + if t.randomNumber == nil { + rng := utils.NewRand(time.Now().UnixNano()) + t.randomNumber = func() uint64 { + return uint64(rng.Int63()) + } + } + if t.timeNow == nil { + t.timeNow = time.Now + } + if t.logger == nil { + t.logger = log.NullLogger + } + // Set tracer-level tags + t.tags = append(t.tags, Tag{key: JaegerClientVersionTagKey, value: JaegerClientVersion}) + if hostname, err := os.Hostname(); err == nil { + t.tags = append(t.tags, Tag{key: TracerHostnameTagKey, value: hostname}) + } + if ip, err := utils.HostIP(); err == nil { + t.tags = append(t.tags, Tag{key: TracerIPTagKey, value: ip.String()}) + t.hostIPv4 = utils.PackIPAsUint32(ip) + } else { + t.logger.Error("Unable to determine this host's IP address: " + err.Error()) + } + + if t.options.gen128Bit { + if t.options.highTraceIDGenerator == nil { + t.options.highTraceIDGenerator = t.randomNumber + } + } else if t.options.highTraceIDGenerator != nil { + t.logger.Error("Overriding high trace ID generator but not generating " + + "128 bit trace IDs, consider enabling the \"Gen128Bit\" option") + } + + return t, t +} + +// addCodec adds registers injector and extractor for given propagation format if not already defined. +func (t *Tracer) addCodec(format interface{}, injector Injector, extractor Extractor) { + if _, ok := t.injectors[format]; !ok { + t.injectors[format] = injector + } + if _, ok := t.extractors[format]; !ok { + t.extractors[format] = extractor + } +} + +// StartSpan implements StartSpan() method of opentracing.Tracer. +func (t *Tracer) StartSpan( + operationName string, + options ...opentracing.StartSpanOption, +) opentracing.Span { + sso := opentracing.StartSpanOptions{} + for _, o := range options { + o.Apply(&sso) + } + return t.startSpanWithOptions(operationName, sso) +} + +func (t *Tracer) startSpanWithOptions( + operationName string, + options opentracing.StartSpanOptions, +) opentracing.Span { + if options.StartTime.IsZero() { + options.StartTime = t.timeNow() + } + + var references []Reference + var parent SpanContext + var hasParent bool // need this because `parent` is a value, not reference + for _, ref := range options.References { + ctx, ok := ref.ReferencedContext.(SpanContext) + if !ok { + t.logger.Error(fmt.Sprintf( + "Reference contains invalid type of SpanReference: %s", + reflect.ValueOf(ref.ReferencedContext))) + continue + } + if !(ctx.IsValid() || ctx.isDebugIDContainerOnly() || len(ctx.baggage) != 0) { + continue + } + references = append(references, Reference{Type: ref.Type, Context: ctx}) + if !hasParent { + parent = ctx + hasParent = ref.Type == opentracing.ChildOfRef + } + } + if !hasParent && parent.IsValid() { + // If ChildOfRef wasn't found but a FollowFromRef exists, use the context from + // the FollowFromRef as the parent + hasParent = true + } + + rpcServer := false + if v, ok := options.Tags[ext.SpanKindRPCServer.Key]; ok { + rpcServer = (v == ext.SpanKindRPCServerEnum || v == string(ext.SpanKindRPCServerEnum)) + } + + var samplerTags []Tag + var ctx SpanContext + newTrace := false + if !hasParent || !parent.IsValid() { + newTrace = true + ctx.traceID.Low = t.randomID() + if t.options.gen128Bit { + ctx.traceID.High = t.options.highTraceIDGenerator() + } + ctx.spanID = SpanID(ctx.traceID.Low) + ctx.parentID = 0 + ctx.flags = byte(0) + if hasParent && parent.isDebugIDContainerOnly() { + ctx.flags |= (flagSampled | flagDebug) + samplerTags = []Tag{{key: JaegerDebugHeader, value: parent.debugID}} + } else if sampled, tags := t.sampler.IsSampled(ctx.traceID, operationName); sampled { + ctx.flags |= flagSampled + samplerTags = tags + } + } else { + ctx.traceID = parent.traceID + if rpcServer && t.options.zipkinSharedRPCSpan { + // Support Zipkin's one-span-per-RPC model + ctx.spanID = parent.spanID + ctx.parentID = parent.parentID + } else { + ctx.spanID = SpanID(t.randomID()) + ctx.parentID = parent.spanID + } + ctx.flags = parent.flags + } + if hasParent { + // copy baggage items + if l := len(parent.baggage); l > 0 { + ctx.baggage = make(map[string]string, len(parent.baggage)) + for k, v := range parent.baggage { + ctx.baggage[k] = v + } + } + } + + sp := t.newSpan() + sp.context = ctx + sp.observer = t.observer.OnStartSpan(sp, operationName, options) + return t.startSpanInternal( + sp, + operationName, + options.StartTime, + samplerTags, + options.Tags, + newTrace, + rpcServer, + references, + ) +} + +// Inject implements Inject() method of opentracing.Tracer +func (t *Tracer) Inject(ctx opentracing.SpanContext, format interface{}, carrier interface{}) error { + c, ok := ctx.(SpanContext) + if !ok { + return opentracing.ErrInvalidSpanContext + } + if injector, ok := t.injectors[format]; ok { + return injector.Inject(c, carrier) + } + return opentracing.ErrUnsupportedFormat +} + +// Extract implements Extract() method of opentracing.Tracer +func (t *Tracer) Extract( + format interface{}, + carrier interface{}, +) (opentracing.SpanContext, error) { + if extractor, ok := t.extractors[format]; ok { + return extractor.Extract(carrier) + } + return nil, opentracing.ErrUnsupportedFormat +} + +// Close releases all resources used by the Tracer and flushes any remaining buffered spans. +func (t *Tracer) Close() error { + t.reporter.Close() + t.sampler.Close() + if mgr, ok := t.baggageRestrictionManager.(io.Closer); ok { + mgr.Close() + } + return nil +} + +// Tags returns a slice of tracer-level tags. +func (t *Tracer) Tags() []opentracing.Tag { + tags := make([]opentracing.Tag, len(t.tags)) + for i, tag := range t.tags { + tags[i] = opentracing.Tag{Key: tag.key, Value: tag.value} + } + return tags +} + +// newSpan returns an instance of a clean Span object. +// If options.PoolSpans is true, the spans are retrieved from an object pool. +func (t *Tracer) newSpan() *Span { + if !t.options.poolSpans { + return &Span{} + } + sp := t.spanPool.Get().(*Span) + sp.context = emptyContext + sp.tracer = nil + sp.tags = nil + sp.logs = nil + return sp +} + +func (t *Tracer) startSpanInternal( + sp *Span, + operationName string, + startTime time.Time, + internalTags []Tag, + tags opentracing.Tags, + newTrace bool, + rpcServer bool, + references []Reference, +) *Span { + sp.tracer = t + sp.operationName = operationName + sp.startTime = startTime + sp.duration = 0 + sp.references = references + sp.firstInProcess = rpcServer || sp.context.parentID == 0 + if len(tags) > 0 || len(internalTags) > 0 { + sp.tags = make([]Tag, len(internalTags), len(tags)+len(internalTags)) + copy(sp.tags, internalTags) + for k, v := range tags { + sp.observer.OnSetTag(k, v) + if k == string(ext.SamplingPriority) && setSamplingPriority(sp, v) { + continue + } + sp.setTagNoLocking(k, v) + } + } + // emit metrics + if sp.context.IsSampled() { + t.metrics.SpansStartedSampled.Inc(1) + if newTrace { + // We cannot simply check for parentID==0 because in Zipkin model the + // server-side RPC span has the exact same trace/span/parent IDs as the + // calling client-side span, but obviously the server side span is + // no longer a root span of the trace. + t.metrics.TracesStartedSampled.Inc(1) + } else if sp.firstInProcess { + t.metrics.TracesJoinedSampled.Inc(1) + } + } else { + t.metrics.SpansStartedNotSampled.Inc(1) + if newTrace { + t.metrics.TracesStartedNotSampled.Inc(1) + } else if sp.firstInProcess { + t.metrics.TracesJoinedNotSampled.Inc(1) + } + } + return sp +} + +func (t *Tracer) reportSpan(sp *Span) { + t.metrics.SpansFinished.Inc(1) + if sp.context.IsSampled() { + t.reporter.Report(sp) + } + if t.options.poolSpans { + t.spanPool.Put(sp) + } +} + +// randomID generates a random trace/span ID, using tracer.random() generator. +// It never returns 0. +func (t *Tracer) randomID() uint64 { + val := t.randomNumber() + for val == 0 { + val = t.randomNumber() + } + return val +} + +// (NB) span should hold the lock before making this call +func (t *Tracer) setBaggage(sp *Span, key, value string) { + t.baggageSetter.setBaggage(sp, key, value) +} diff --git a/vendor/github.com/uber/jaeger-client-go/tracer_options.go b/vendor/github.com/uber/jaeger-client-go/tracer_options.go new file mode 100644 index 000000000..72edf6dbb --- /dev/null +++ b/vendor/github.com/uber/jaeger-client-go/tracer_options.go @@ -0,0 +1,146 @@ +// Copyright (c) 2017 Uber Technologies, Inc. +// +// 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. + +package jaeger + +import ( + "time" + + "github.com/opentracing/opentracing-go" + + "github.com/uber/jaeger-client-go/internal/baggage" +) + +// TracerOption is a function that sets some option on the tracer +type TracerOption func(tracer *Tracer) + +// TracerOptions is a factory for all available TracerOption's +var TracerOptions tracerOptions + +type tracerOptions struct{} + +// Metrics creates a TracerOption that initializes Metrics on the tracer, +// which is used to emit statistics. +func (tracerOptions) Metrics(m *Metrics) TracerOption { + return func(tracer *Tracer) { + tracer.metrics = *m + } +} + +// Logger creates a TracerOption that gives the tracer a Logger. +func (tracerOptions) Logger(logger Logger) TracerOption { + return func(tracer *Tracer) { + tracer.logger = logger + } +} + +func (tracerOptions) CustomHeaderKeys(headerKeys *HeadersConfig) TracerOption { + return func(tracer *Tracer) { + if headerKeys == nil { + return + } + textPropagator := newTextMapPropagator(headerKeys.applyDefaults(), tracer.metrics) + tracer.addCodec(opentracing.TextMap, textPropagator, textPropagator) + + httpHeaderPropagator := newHTTPHeaderPropagator(headerKeys.applyDefaults(), tracer.metrics) + tracer.addCodec(opentracing.HTTPHeaders, httpHeaderPropagator, httpHeaderPropagator) + } +} + +// TimeNow creates a TracerOption that gives the tracer a function +// used to generate timestamps for spans. +func (tracerOptions) TimeNow(timeNow func() time.Time) TracerOption { + return func(tracer *Tracer) { + tracer.timeNow = timeNow + } +} + +// RandomNumber creates a TracerOption that gives the tracer +// a thread-safe random number generator function for generating trace IDs. +func (tracerOptions) RandomNumber(randomNumber func() uint64) TracerOption { + return func(tracer *Tracer) { + tracer.randomNumber = randomNumber + } +} + +// PoolSpans creates a TracerOption that tells the tracer whether it should use +// an object pool to minimize span allocations. +// This should be used with care, only if the service is not running any async tasks +// that can access parent spans after those spans have been finished. +func (tracerOptions) PoolSpans(poolSpans bool) TracerOption { + return func(tracer *Tracer) { + tracer.options.poolSpans = poolSpans + } +} + +// Deprecated: HostIPv4 creates a TracerOption that identifies the current service/process. +// If not set, the factory method will obtain the current IP address. +// The TracerOption is deprecated; the tracer will attempt to automatically detect the IP. +func (tracerOptions) HostIPv4(hostIPv4 uint32) TracerOption { + return func(tracer *Tracer) { + tracer.hostIPv4 = hostIPv4 + } +} + +func (tracerOptions) Injector(format interface{}, injector Injector) TracerOption { + return func(tracer *Tracer) { + tracer.injectors[format] = injector + } +} + +func (tracerOptions) Extractor(format interface{}, extractor Extractor) TracerOption { + return func(tracer *Tracer) { + tracer.extractors[format] = extractor + } +} + +func (t tracerOptions) Observer(observer Observer) TracerOption { + return t.ContribObserver(&oldObserver{obs: observer}) +} + +func (tracerOptions) ContribObserver(observer ContribObserver) TracerOption { + return func(tracer *Tracer) { + tracer.observer.append(observer) + } +} + +func (tracerOptions) Gen128Bit(gen128Bit bool) TracerOption { + return func(tracer *Tracer) { + tracer.options.gen128Bit = gen128Bit + } +} + +func (tracerOptions) HighTraceIDGenerator(highTraceIDGenerator func() uint64) TracerOption { + return func(tracer *Tracer) { + tracer.options.highTraceIDGenerator = highTraceIDGenerator + } +} + +func (tracerOptions) ZipkinSharedRPCSpan(zipkinSharedRPCSpan bool) TracerOption { + return func(tracer *Tracer) { + tracer.options.zipkinSharedRPCSpan = zipkinSharedRPCSpan + } +} + +func (tracerOptions) Tag(key string, value interface{}) TracerOption { + return func(tracer *Tracer) { + tracer.tags = append(tracer.tags, Tag{key: key, value: value}) + } +} + +func (tracerOptions) BaggageRestrictionManager(mgr baggage.RestrictionManager) TracerOption { + return func(tracer *Tracer) { + tracer.baggageRestrictionManager = mgr + } +} diff --git a/vendor/github.com/uber/jaeger-client-go/transport.go b/vendor/github.com/uber/jaeger-client-go/transport.go new file mode 100644 index 000000000..c5f5b1955 --- /dev/null +++ b/vendor/github.com/uber/jaeger-client-go/transport.go @@ -0,0 +1,38 @@ +// Copyright (c) 2017 Uber Technologies, Inc. +// +// 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. + +package jaeger + +import ( + "io" +) + +// Transport abstracts the method of sending spans out of process. +// Implementations are NOT required to be thread-safe; the RemoteReporter +// is expected to only call methods on the Transport from the same go-routine. +type Transport interface { + // Append converts the span to the wire representation and adds it + // to sender's internal buffer. If the buffer exceeds its designated + // size, the transport should call Flush() and return the number of spans + // flushed, otherwise return 0. If error is returned, the returned number + // of spans is treated as failed span, and reported to metrics accordingly. + Append(span *Span) (int, error) + + // Flush submits the internal buffer to the remote server. It returns the + // number of spans flushed. If error is returned, the returned number of + // spans is treated as failed span, and reported to metrics accordingly. + Flush() (int, error) + + io.Closer +} diff --git a/vendor/github.com/uber/jaeger-client-go/transport_udp.go b/vendor/github.com/uber/jaeger-client-go/transport_udp.go new file mode 100644 index 000000000..cb83cdf9b --- /dev/null +++ b/vendor/github.com/uber/jaeger-client-go/transport_udp.go @@ -0,0 +1,132 @@ +// Copyright (c) 2017 Uber Technologies, Inc. +// +// 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. + +package jaeger + +import ( + "errors" + + "github.com/apache/thrift/lib/go/thrift" + + j "github.com/uber/jaeger-client-go/thrift-gen/jaeger" + "github.com/uber/jaeger-client-go/utils" +) + +// Empirically obtained constant for how many bytes in the message are used for envelope. +// The total datagram size is: +// sizeof(Span) * numSpans + processByteSize + emitBatchOverhead <= maxPacketSize +// There is a unit test `TestEmitBatchOverhead` that validates this number. +// Note that due to the use of Compact Thrift protocol, overhead grows with the number of spans +// in the batch, because the length of the list is encoded as varint32, as well as SeqId. +const emitBatchOverhead = 30 + +const defaultUDPSpanServerHostPort = "localhost:6831" + +var errSpanTooLarge = errors.New("Span is too large") + +type udpSender struct { + client *utils.AgentClientUDP + maxPacketSize int // max size of datagram in bytes + maxSpanBytes int // max number of bytes to record spans (excluding envelope) in the datagram + byteBufferSize int // current number of span bytes accumulated in the buffer + spanBuffer []*j.Span // spans buffered before a flush + thriftBuffer *thrift.TMemoryBuffer // buffer used to calculate byte size of a span + thriftProtocol thrift.TProtocol + process *j.Process + processByteSize int +} + +// NewUDPTransport creates a reporter that submits spans to jaeger-agent +func NewUDPTransport(hostPort string, maxPacketSize int) (Transport, error) { + if len(hostPort) == 0 { + hostPort = defaultUDPSpanServerHostPort + } + if maxPacketSize == 0 { + maxPacketSize = utils.UDPPacketMaxLength + } + + protocolFactory := thrift.NewTCompactProtocolFactory() + + // Each span is first written to thriftBuffer to determine its size in bytes. + thriftBuffer := thrift.NewTMemoryBufferLen(maxPacketSize) + thriftProtocol := protocolFactory.GetProtocol(thriftBuffer) + + client, err := utils.NewAgentClientUDP(hostPort, maxPacketSize) + if err != nil { + return nil, err + } + + sender := &udpSender{ + client: client, + maxSpanBytes: maxPacketSize - emitBatchOverhead, + thriftBuffer: thriftBuffer, + thriftProtocol: thriftProtocol} + return sender, nil +} + +func (s *udpSender) calcSizeOfSerializedThrift(thriftStruct thrift.TStruct) int { + s.thriftBuffer.Reset() + thriftStruct.Write(s.thriftProtocol) + return s.thriftBuffer.Len() +} + +func (s *udpSender) Append(span *Span) (int, error) { + if s.process == nil { + s.process = BuildJaegerProcessThrift(span) + s.processByteSize = s.calcSizeOfSerializedThrift(s.process) + s.byteBufferSize += s.processByteSize + } + jSpan := BuildJaegerThrift(span) + spanSize := s.calcSizeOfSerializedThrift(jSpan) + if spanSize > s.maxSpanBytes { + return 1, errSpanTooLarge + } + + s.byteBufferSize += spanSize + if s.byteBufferSize <= s.maxSpanBytes { + s.spanBuffer = append(s.spanBuffer, jSpan) + if s.byteBufferSize < s.maxSpanBytes { + return 0, nil + } + return s.Flush() + } + // the latest span did not fit in the buffer + n, err := s.Flush() + s.spanBuffer = append(s.spanBuffer, jSpan) + s.byteBufferSize = spanSize + s.processByteSize + return n, err +} + +func (s *udpSender) Flush() (int, error) { + n := len(s.spanBuffer) + if n == 0 { + return 0, nil + } + err := s.client.EmitBatch(&j.Batch{Process: s.process, Spans: s.spanBuffer}) + s.resetBuffers() + + return n, err +} + +func (s *udpSender) Close() error { + return s.client.Close() +} + +func (s *udpSender) resetBuffers() { + for i := range s.spanBuffer { + s.spanBuffer[i] = nil + } + s.spanBuffer = s.spanBuffer[:0] + s.byteBufferSize = s.processByteSize +} diff --git a/vendor/github.com/uber/jaeger-client-go/utils/http_json.go b/vendor/github.com/uber/jaeger-client-go/utils/http_json.go new file mode 100644 index 000000000..237211f82 --- /dev/null +++ b/vendor/github.com/uber/jaeger-client-go/utils/http_json.go @@ -0,0 +1,54 @@ +// Copyright (c) 2017 Uber Technologies, Inc. +// +// 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. + +package utils + +import ( + "encoding/json" + "fmt" + "io" + "io/ioutil" + "net/http" +) + +// GetJSON makes an HTTP call to the specified URL and parses the returned JSON into `out`. +func GetJSON(url string, out interface{}) error { + resp, err := http.Get(url) + if err != nil { + return err + } + return ReadJSON(resp, out) +} + +// ReadJSON reads JSON from http.Response and parses it into `out` +func ReadJSON(resp *http.Response, out interface{}) error { + defer resp.Body.Close() + + if resp.StatusCode >= 400 { + body, err := ioutil.ReadAll(resp.Body) + if err != nil { + return err + } + + return fmt.Errorf("StatusCode: %d, Body: %s", resp.StatusCode, body) + } + + if out == nil { + io.Copy(ioutil.Discard, resp.Body) + return nil + } + + decoder := json.NewDecoder(resp.Body) + return decoder.Decode(out) +} diff --git a/vendor/github.com/uber/jaeger-client-go/utils/localip.go b/vendor/github.com/uber/jaeger-client-go/utils/localip.go new file mode 100644 index 000000000..b51af7713 --- /dev/null +++ b/vendor/github.com/uber/jaeger-client-go/utils/localip.go @@ -0,0 +1,84 @@ +// Copyright (c) 2017 Uber Technologies, Inc. +// +// 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. + +package utils + +import ( + "errors" + "net" +) + +// This code is borrowed from https://github.com/uber/tchannel-go/blob/dev/localip.go + +// scoreAddr scores how likely the given addr is to be a remote address and returns the +// IP to use when listening. Any address which receives a negative score should not be used. +// Scores are calculated as: +// -1 for any unknown IP addresses. +// +300 for IPv4 addresses +// +100 for non-local addresses, extra +100 for "up" interaces. +func scoreAddr(iface net.Interface, addr net.Addr) (int, net.IP) { + var ip net.IP + if netAddr, ok := addr.(*net.IPNet); ok { + ip = netAddr.IP + } else if netIP, ok := addr.(*net.IPAddr); ok { + ip = netIP.IP + } else { + return -1, nil + } + + var score int + if ip.To4() != nil { + score += 300 + } + if iface.Flags&net.FlagLoopback == 0 && !ip.IsLoopback() { + score += 100 + if iface.Flags&net.FlagUp != 0 { + score += 100 + } + } + return score, ip +} + +// HostIP tries to find an IP that can be used by other machines to reach this machine. +func HostIP() (net.IP, error) { + interfaces, err := net.Interfaces() + if err != nil { + return nil, err + } + + bestScore := -1 + var bestIP net.IP + // Select the highest scoring IP as the best IP. + for _, iface := range interfaces { + addrs, err := iface.Addrs() + if err != nil { + // Skip this interface if there is an error. + continue + } + + for _, addr := range addrs { + score, ip := scoreAddr(iface, addr) + if score > bestScore { + bestScore = score + bestIP = ip + } + } + } + + if bestScore == -1 { + return nil, errors.New("no addresses to listen on") + } + + return bestIP, nil +} diff --git a/vendor/github.com/uber/jaeger-client-go/utils/rand.go b/vendor/github.com/uber/jaeger-client-go/utils/rand.go new file mode 100644 index 000000000..9875f7f55 --- /dev/null +++ b/vendor/github.com/uber/jaeger-client-go/utils/rand.go @@ -0,0 +1,46 @@ +// Copyright (c) 2017 Uber Technologies, Inc. +// +// 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. + +package utils + +import ( + "math/rand" + "sync" +) + +// lockedSource allows a random number generator to be used by multiple goroutines concurrently. +// The code is very similar to math/rand.lockedSource, which is unfortunately not exposed. +type lockedSource struct { + mut sync.Mutex + src rand.Source +} + +// NewRand returns a rand.Rand that is threadsafe. +func NewRand(seed int64) *rand.Rand { + return rand.New(&lockedSource{src: rand.NewSource(seed)}) +} + +func (r *lockedSource) Int63() (n int64) { + r.mut.Lock() + n = r.src.Int63() + r.mut.Unlock() + return +} + +// Seed implements Seed() of Source +func (r *lockedSource) Seed(seed int64) { + r.mut.Lock() + r.src.Seed(seed) + r.mut.Unlock() +} diff --git a/vendor/github.com/uber/jaeger-client-go/utils/rate_limiter.go b/vendor/github.com/uber/jaeger-client-go/utils/rate_limiter.go new file mode 100644 index 000000000..1b8db9758 --- /dev/null +++ b/vendor/github.com/uber/jaeger-client-go/utils/rate_limiter.go @@ -0,0 +1,77 @@ +// Copyright (c) 2017 Uber Technologies, Inc. +// +// 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. + +package utils + +import ( + "sync" + "time" +) + +// RateLimiter is a filter used to check if a message that is worth itemCost units is within the rate limits. +type RateLimiter interface { + CheckCredit(itemCost float64) bool +} + +type rateLimiter struct { + sync.Mutex + + creditsPerSecond float64 + balance float64 + maxBalance float64 + lastTick time.Time + + timeNow func() time.Time +} + +// NewRateLimiter creates a new rate limiter based on leaky bucket algorithm, formulated in terms of a +// credits balance that is replenished every time CheckCredit() method is called (tick) by the amount proportional +// to the time elapsed since the last tick, up to max of creditsPerSecond. A call to CheckCredit() takes a cost +// of an item we want to pay with the balance. If the balance exceeds the cost of the item, the item is "purchased" +// and the balance reduced, indicated by returned value of true. Otherwise the balance is unchanged and return false. +// +// This can be used to limit a rate of messages emitted by a service by instantiating the Rate Limiter with the +// max number of messages a service is allowed to emit per second, and calling CheckCredit(1.0) for each message +// to determine if the message is within the rate limit. +// +// It can also be used to limit the rate of traffic in bytes, by setting creditsPerSecond to desired throughput +// as bytes/second, and calling CheckCredit() with the actual message size. +func NewRateLimiter(creditsPerSecond, maxBalance float64) RateLimiter { + return &rateLimiter{ + creditsPerSecond: creditsPerSecond, + balance: maxBalance, + maxBalance: maxBalance, + lastTick: time.Now(), + timeNow: time.Now} +} + +func (b *rateLimiter) CheckCredit(itemCost float64) bool { + b.Lock() + defer b.Unlock() + // calculate how much time passed since the last tick, and update current tick + currentTime := b.timeNow() + elapsedTime := currentTime.Sub(b.lastTick) + b.lastTick = currentTime + // calculate how much credit have we accumulated since the last tick + b.balance += elapsedTime.Seconds() * b.creditsPerSecond + if b.balance > b.maxBalance { + b.balance = b.maxBalance + } + // if we have enough credits to pay for current item, then reduce balance and allow + if b.balance >= itemCost { + b.balance -= itemCost + return true + } + return false +} diff --git a/vendor/github.com/uber/jaeger-client-go/utils/udp_client.go b/vendor/github.com/uber/jaeger-client-go/utils/udp_client.go new file mode 100644 index 000000000..2374686e5 --- /dev/null +++ b/vendor/github.com/uber/jaeger-client-go/utils/udp_client.go @@ -0,0 +1,98 @@ +// Copyright (c) 2017 Uber Technologies, Inc. +// +// 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. + +package utils + +import ( + "errors" + "fmt" + "io" + "net" + + "github.com/apache/thrift/lib/go/thrift" + + "github.com/uber/jaeger-client-go/thrift-gen/agent" + "github.com/uber/jaeger-client-go/thrift-gen/jaeger" + "github.com/uber/jaeger-client-go/thrift-gen/zipkincore" +) + +// UDPPacketMaxLength is the max size of UDP packet we want to send, synced with jaeger-agent +const UDPPacketMaxLength = 65000 + +// AgentClientUDP is a UDP client to Jaeger agent that implements agent.Agent interface. +type AgentClientUDP struct { + agent.Agent + io.Closer + + connUDP *net.UDPConn + client *agent.AgentClient + maxPacketSize int // max size of datagram in bytes + thriftBuffer *thrift.TMemoryBuffer // buffer used to calculate byte size of a span +} + +// NewAgentClientUDP creates a client that sends spans to Jaeger Agent over UDP. +func NewAgentClientUDP(hostPort string, maxPacketSize int) (*AgentClientUDP, error) { + if maxPacketSize == 0 { + maxPacketSize = UDPPacketMaxLength + } + + thriftBuffer := thrift.NewTMemoryBufferLen(maxPacketSize) + protocolFactory := thrift.NewTCompactProtocolFactory() + client := agent.NewAgentClientFactory(thriftBuffer, protocolFactory) + + destAddr, err := net.ResolveUDPAddr("udp", hostPort) + if err != nil { + return nil, err + } + + connUDP, err := net.DialUDP(destAddr.Network(), nil, destAddr) + if err != nil { + return nil, err + } + if err := connUDP.SetWriteBuffer(maxPacketSize); err != nil { + return nil, err + } + + clientUDP := &AgentClientUDP{ + connUDP: connUDP, + client: client, + maxPacketSize: maxPacketSize, + thriftBuffer: thriftBuffer} + return clientUDP, nil +} + +// EmitZipkinBatch implements EmitZipkinBatch() of Agent interface +func (a *AgentClientUDP) EmitZipkinBatch(spans []*zipkincore.Span) error { + return errors.New("Not implemented") +} + +// EmitBatch implements EmitBatch() of Agent interface +func (a *AgentClientUDP) EmitBatch(batch *jaeger.Batch) error { + a.thriftBuffer.Reset() + a.client.SeqId = 0 // we have no need for distinct SeqIds for our one-way UDP messages + if err := a.client.EmitBatch(batch); err != nil { + return err + } + if a.thriftBuffer.Len() > a.maxPacketSize { + return fmt.Errorf("Data does not fit within one UDP packet; size %d, max %d, spans %d", + a.thriftBuffer.Len(), a.maxPacketSize, len(batch.Spans)) + } + _, err := a.connUDP.Write(a.thriftBuffer.Bytes()) + return err +} + +// Close implements Close() of io.Closer and closes the underlying UDP connection. +func (a *AgentClientUDP) Close() error { + return a.connUDP.Close() +} diff --git a/vendor/github.com/uber/jaeger-client-go/utils/utils.go b/vendor/github.com/uber/jaeger-client-go/utils/utils.go new file mode 100644 index 000000000..ac3c325d1 --- /dev/null +++ b/vendor/github.com/uber/jaeger-client-go/utils/utils.go @@ -0,0 +1,87 @@ +// Copyright (c) 2017 Uber Technologies, Inc. +// +// 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. + +package utils + +import ( + "encoding/binary" + "errors" + "net" + "strconv" + "strings" + "time" +) + +var ( + // ErrEmptyIP an error for empty ip strings + ErrEmptyIP = errors.New("empty string given for ip") + + // ErrNotHostColonPort an error for invalid host port string + ErrNotHostColonPort = errors.New("expecting host:port") + + // ErrNotFourOctets an error for the wrong number of octets after splitting a string + ErrNotFourOctets = errors.New("Wrong number of octets") +) + +// ParseIPToUint32 converts a string ip (e.g. "x.y.z.w") to an uint32 +func ParseIPToUint32(ip string) (uint32, error) { + if ip == "" { + return 0, ErrEmptyIP + } + + if ip == "localhost" { + return 127<<24 | 1, nil + } + + octets := strings.Split(ip, ".") + if len(octets) != 4 { + return 0, ErrNotFourOctets + } + + var intIP uint32 + for i := 0; i < 4; i++ { + octet, err := strconv.Atoi(octets[i]) + if err != nil { + return 0, err + } + intIP = (intIP << 8) | uint32(octet) + } + + return intIP, nil +} + +// ParsePort converts port number from string to uin16 +func ParsePort(portString string) (uint16, error) { + port, err := strconv.ParseUint(portString, 10, 16) + return uint16(port), err +} + +// PackIPAsUint32 packs an IPv4 as uint32 +func PackIPAsUint32(ip net.IP) uint32 { + if ipv4 := ip.To4(); ipv4 != nil { + return binary.BigEndian.Uint32(ipv4) + } + return 0 +} + +// TimeToMicrosecondsSinceEpochInt64 converts Go time.Time to a long +// representing time since epoch in microseconds, which is used expected +// in the Jaeger spans encoded as Thrift. +func TimeToMicrosecondsSinceEpochInt64(t time.Time) int64 { + // ^^^ Passing time.Time by value is faster than passing a pointer! + // BenchmarkTimeByValue-8 2000000000 1.37 ns/op + // BenchmarkTimeByPtr-8 2000000000 1.98 ns/op + + return t.UnixNano() / 1000 +} diff --git a/vendor/github.com/uber/jaeger-client-go/zipkin.go b/vendor/github.com/uber/jaeger-client-go/zipkin.go new file mode 100644 index 000000000..636952b7f --- /dev/null +++ b/vendor/github.com/uber/jaeger-client-go/zipkin.go @@ -0,0 +1,76 @@ +// Copyright (c) 2017 Uber Technologies, Inc. +// +// 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. + +package jaeger + +import ( + "github.com/opentracing/opentracing-go" +) + +// ZipkinSpanFormat is an OpenTracing carrier format constant +const ZipkinSpanFormat = "zipkin-span-format" + +// ExtractableZipkinSpan is a type of Carrier used for integration with Zipkin-aware +// RPC frameworks (like TChannel). It does not support baggage, only trace IDs. +type ExtractableZipkinSpan interface { + TraceID() uint64 + SpanID() uint64 + ParentID() uint64 + Flags() byte +} + +// InjectableZipkinSpan is a type of Carrier used for integration with Zipkin-aware +// RPC frameworks (like TChannel). It does not support baggage, only trace IDs. +type InjectableZipkinSpan interface { + SetTraceID(traceID uint64) + SetSpanID(spanID uint64) + SetParentID(parentID uint64) + SetFlags(flags byte) +} + +type zipkinPropagator struct { + tracer *Tracer +} + +func (p *zipkinPropagator) Inject( + ctx SpanContext, + abstractCarrier interface{}, +) error { + carrier, ok := abstractCarrier.(InjectableZipkinSpan) + if !ok { + return opentracing.ErrInvalidCarrier + } + + carrier.SetTraceID(ctx.TraceID().Low) // TODO this cannot work with 128bit IDs + carrier.SetSpanID(uint64(ctx.SpanID())) + carrier.SetParentID(uint64(ctx.ParentID())) + carrier.SetFlags(ctx.flags) + return nil +} + +func (p *zipkinPropagator) Extract(abstractCarrier interface{}) (SpanContext, error) { + carrier, ok := abstractCarrier.(ExtractableZipkinSpan) + if !ok { + return emptyContext, opentracing.ErrInvalidCarrier + } + if carrier.TraceID() == 0 { + return emptyContext, opentracing.ErrSpanContextNotFound + } + var ctx SpanContext + ctx.traceID.Low = carrier.TraceID() + ctx.spanID = SpanID(carrier.SpanID()) + ctx.parentID = SpanID(carrier.ParentID()) + ctx.flags = carrier.Flags() + return ctx, nil +} diff --git a/vendor/github.com/uber/jaeger-client-go/zipkin_thrift_span.go b/vendor/github.com/uber/jaeger-client-go/zipkin_thrift_span.go new file mode 100644 index 000000000..b2e9a3e64 --- /dev/null +++ b/vendor/github.com/uber/jaeger-client-go/zipkin_thrift_span.go @@ -0,0 +1,325 @@ +// Copyright (c) 2017 Uber Technologies, Inc. +// +// 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. + +package jaeger + +import ( + "encoding/binary" + "fmt" + "time" + + "github.com/opentracing/opentracing-go/ext" + + "github.com/uber/jaeger-client-go/internal/spanlog" + z "github.com/uber/jaeger-client-go/thrift-gen/zipkincore" + "github.com/uber/jaeger-client-go/utils" +) + +const ( + // maxAnnotationLength is the max length of byte array or string allowed in the annotations + maxAnnotationLength = 256 + + // Zipkin UI does not work well with non-string tag values + allowPackedNumbers = false +) + +var specialTagHandlers = map[string]func(*zipkinSpan, interface{}){ + string(ext.SpanKind): setSpanKind, + string(ext.PeerHostIPv4): setPeerIPv4, + string(ext.PeerPort): setPeerPort, + string(ext.PeerService): setPeerService, + TracerIPTagKey: removeTag, +} + +// BuildZipkinThrift builds thrift span based on internal span. +func BuildZipkinThrift(s *Span) *z.Span { + span := &zipkinSpan{Span: s} + span.handleSpecialTags() + parentID := int64(span.context.parentID) + var ptrParentID *int64 + if parentID != 0 { + ptrParentID = &parentID + } + timestamp := utils.TimeToMicrosecondsSinceEpochInt64(span.startTime) + duration := span.duration.Nanoseconds() / int64(time.Microsecond) + endpoint := &z.Endpoint{ + ServiceName: span.tracer.serviceName, + Ipv4: int32(span.tracer.hostIPv4)} + thriftSpan := &z.Span{ + TraceID: int64(span.context.traceID.Low), // TODO upgrade zipkin thrift and use TraceIdHigh + ID: int64(span.context.spanID), + ParentID: ptrParentID, + Name: span.operationName, + Timestamp: ×tamp, + Duration: &duration, + Debug: span.context.IsDebug(), + Annotations: buildAnnotations(span, endpoint), + BinaryAnnotations: buildBinaryAnnotations(span, endpoint)} + return thriftSpan +} + +func buildAnnotations(span *zipkinSpan, endpoint *z.Endpoint) []*z.Annotation { + // automatically adding 2 Zipkin CoreAnnotations + annotations := make([]*z.Annotation, 0, 2+len(span.logs)) + var startLabel, endLabel string + if span.spanKind == string(ext.SpanKindRPCClientEnum) { + startLabel, endLabel = z.CLIENT_SEND, z.CLIENT_RECV + } else if span.spanKind == string(ext.SpanKindRPCServerEnum) { + startLabel, endLabel = z.SERVER_RECV, z.SERVER_SEND + } + if !span.startTime.IsZero() && startLabel != "" { + start := &z.Annotation{ + Timestamp: utils.TimeToMicrosecondsSinceEpochInt64(span.startTime), + Value: startLabel, + Host: endpoint} + annotations = append(annotations, start) + if span.duration != 0 { + endTs := span.startTime.Add(span.duration) + end := &z.Annotation{ + Timestamp: utils.TimeToMicrosecondsSinceEpochInt64(endTs), + Value: endLabel, + Host: endpoint} + annotations = append(annotations, end) + } + } + for _, log := range span.logs { + anno := &z.Annotation{ + Timestamp: utils.TimeToMicrosecondsSinceEpochInt64(log.Timestamp), + Host: endpoint} + if content, err := spanlog.MaterializeWithJSON(log.Fields); err == nil { + anno.Value = truncateString(string(content)) + } else { + anno.Value = err.Error() + } + annotations = append(annotations, anno) + } + return annotations +} + +func buildBinaryAnnotations(span *zipkinSpan, endpoint *z.Endpoint) []*z.BinaryAnnotation { + // automatically adding local component or server/client address tag, and client version + annotations := make([]*z.BinaryAnnotation, 0, 2+len(span.tags)) + + if span.peerDefined() && span.isRPC() { + peer := z.Endpoint{ + Ipv4: span.peer.Ipv4, + Port: span.peer.Port, + ServiceName: span.peer.ServiceName} + label := z.CLIENT_ADDR + if span.isRPCClient() { + label = z.SERVER_ADDR + } + anno := &z.BinaryAnnotation{ + Key: label, + Value: []byte{1}, + AnnotationType: z.AnnotationType_BOOL, + Host: &peer} + annotations = append(annotations, anno) + } + if !span.isRPC() { + componentName := endpoint.ServiceName + for _, tag := range span.tags { + if tag.key == string(ext.Component) { + componentName = stringify(tag.value) + break + } + } + local := &z.BinaryAnnotation{ + Key: z.LOCAL_COMPONENT, + Value: []byte(componentName), + AnnotationType: z.AnnotationType_STRING, + Host: endpoint} + annotations = append(annotations, local) + } + for _, tag := range span.tags { + // "Special tags" are already handled by this point, we'd be double reporting the + // tags if we don't skip here + if _, ok := specialTagHandlers[tag.key]; ok { + continue + } + if anno := buildBinaryAnnotation(tag.key, tag.value, nil); anno != nil { + annotations = append(annotations, anno) + } + } + return annotations +} + +func buildBinaryAnnotation(key string, val interface{}, endpoint *z.Endpoint) *z.BinaryAnnotation { + bann := &z.BinaryAnnotation{Key: key, Host: endpoint} + if value, ok := val.(string); ok { + bann.Value = []byte(truncateString(value)) + bann.AnnotationType = z.AnnotationType_STRING + } else if value, ok := val.([]byte); ok { + if len(value) > maxAnnotationLength { + value = value[:maxAnnotationLength] + } + bann.Value = value + bann.AnnotationType = z.AnnotationType_BYTES + } else if value, ok := val.(int32); ok && allowPackedNumbers { + bann.Value = int32ToBytes(value) + bann.AnnotationType = z.AnnotationType_I32 + } else if value, ok := val.(int64); ok && allowPackedNumbers { + bann.Value = int64ToBytes(value) + bann.AnnotationType = z.AnnotationType_I64 + } else if value, ok := val.(int); ok && allowPackedNumbers { + bann.Value = int64ToBytes(int64(value)) + bann.AnnotationType = z.AnnotationType_I64 + } else if value, ok := val.(bool); ok { + bann.Value = []byte{boolToByte(value)} + bann.AnnotationType = z.AnnotationType_BOOL + } else { + value := stringify(val) + bann.Value = []byte(truncateString(value)) + bann.AnnotationType = z.AnnotationType_STRING + } + return bann +} + +func stringify(value interface{}) string { + if s, ok := value.(string); ok { + return s + } + return fmt.Sprintf("%+v", value) +} + +func truncateString(value string) string { + // we ignore the problem of utf8 runes possibly being sliced in the middle, + // as it is rather expensive to iterate through each tag just to find rune + // boundaries. + if len(value) > maxAnnotationLength { + return value[:maxAnnotationLength] + } + return value +} + +func boolToByte(b bool) byte { + if b { + return 1 + } + return 0 +} + +// int32ToBytes converts int32 to bytes. +func int32ToBytes(i int32) []byte { + buf := make([]byte, 4) + binary.BigEndian.PutUint32(buf, uint32(i)) + return buf +} + +// int64ToBytes converts int64 to bytes. +func int64ToBytes(i int64) []byte { + buf := make([]byte, 8) + binary.BigEndian.PutUint64(buf, uint64(i)) + return buf +} + +type zipkinSpan struct { + *Span + + // peer points to the peer service participating in this span, + // e.g. the Client if this span is a server span, + // or Server if this span is a client span + peer struct { + Ipv4 int32 + Port int16 + ServiceName string + } + + // used to distinguish local vs. RPC Server vs. RPC Client spans + spanKind string +} + +func (s *zipkinSpan) handleSpecialTags() { + s.Lock() + defer s.Unlock() + if s.firstInProcess { + // append the process tags + s.tags = append(s.tags, s.tracer.tags...) + } + filteredTags := make([]Tag, 0, len(s.tags)) + for _, tag := range s.tags { + if handler, ok := specialTagHandlers[tag.key]; ok { + handler(s, tag.value) + } else { + filteredTags = append(filteredTags, tag) + } + } + s.tags = filteredTags +} + +func setSpanKind(s *zipkinSpan, value interface{}) { + if val, ok := value.(string); ok { + s.spanKind = val + return + } + if val, ok := value.(ext.SpanKindEnum); ok { + s.spanKind = string(val) + } +} + +func setPeerIPv4(s *zipkinSpan, value interface{}) { + if val, ok := value.(string); ok { + if ip, err := utils.ParseIPToUint32(val); err == nil { + s.peer.Ipv4 = int32(ip) + return + } + } + if val, ok := value.(uint32); ok { + s.peer.Ipv4 = int32(val) + return + } + if val, ok := value.(int32); ok { + s.peer.Ipv4 = val + } +} + +func setPeerPort(s *zipkinSpan, value interface{}) { + if val, ok := value.(string); ok { + if port, err := utils.ParsePort(val); err == nil { + s.peer.Port = int16(port) + return + } + } + if val, ok := value.(uint16); ok { + s.peer.Port = int16(val) + return + } + if val, ok := value.(int); ok { + s.peer.Port = int16(val) + } +} + +func setPeerService(s *zipkinSpan, value interface{}) { + if val, ok := value.(string); ok { + s.peer.ServiceName = val + } +} + +func removeTag(s *zipkinSpan, value interface{}) {} + +func (s *zipkinSpan) peerDefined() bool { + return s.peer.ServiceName != "" || s.peer.Ipv4 != 0 || s.peer.Port != 0 +} + +func (s *zipkinSpan) isRPC() bool { + s.RLock() + defer s.RUnlock() + return s.spanKind == string(ext.SpanKindRPCClientEnum) || s.spanKind == string(ext.SpanKindRPCServerEnum) +} + +func (s *zipkinSpan) isRPCClient() bool { + s.RLock() + defer s.RUnlock() + return s.spanKind == string(ext.SpanKindRPCClientEnum) +} diff --git a/vendor/github.com/uber/jaeger-lib/LICENSE b/vendor/github.com/uber/jaeger-lib/LICENSE new file mode 100644 index 000000000..261eeb9e9 --- /dev/null +++ b/vendor/github.com/uber/jaeger-lib/LICENSE @@ -0,0 +1,201 @@ + 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. diff --git a/vendor/github.com/uber/jaeger-lib/README.md b/vendor/github.com/uber/jaeger-lib/README.md new file mode 100644 index 000000000..1600e7905 --- /dev/null +++ b/vendor/github.com/uber/jaeger-lib/README.md @@ -0,0 +1,22 @@ +[![GoDoc][doc-img]][doc] [![Build Status][ci-img]][ci] [![Coverage Status][cov-img]][cov] + + +# jaeger-lib + +A collection of shared infrastructure libraries used by different +components of [Jaeger](https://github.com/uber/jaeger) backend and [jaeger-client-go](https://github.com/uber/jaeger-client-go). +This library is *not intended to be used standalone*, and provides *no guarantees of backwards compatibility*. + +The library's import path is `github.com/uber/jaeger-lib`. + +## How to Contribute + +Please see [CONTRIBUTING.md](CONTRIBUTING.md). + +[doc-img]: https://godoc.org/github.com/uber/jaeger-lib?status.svg +[doc]: https://godoc.org/github.com/uber/jaeger-lib +[ci-img]: https://travis-ci.org/jaegertracing/jaeger-lib.svg?branch=master +[ci]: https://travis-ci.org/jaegertracing/jaeger-lib +[cov-img]: https://coveralls.io/repos/jaegertracing/jaeger-lib/badge.svg?branch=master&service=github +[cov]: https://coveralls.io/github/jaegertracing/jaeger-lib?branch=master + diff --git a/vendor/github.com/uber/jaeger-lib/metrics/counter.go b/vendor/github.com/uber/jaeger-lib/metrics/counter.go new file mode 100644 index 000000000..2a6a43efd --- /dev/null +++ b/vendor/github.com/uber/jaeger-lib/metrics/counter.go @@ -0,0 +1,28 @@ +// Copyright (c) 2017 Uber Technologies, Inc. +// +// 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. + +package metrics + +// Counter tracks the number of times an event has occurred +type Counter interface { + // Inc adds the given value to the counter. + Inc(int64) +} + +// NullCounter counter that does nothing +var NullCounter Counter = nullCounter{} + +type nullCounter struct{} + +func (nullCounter) Inc(int64) {} diff --git a/vendor/github.com/uber/jaeger-lib/metrics/factory.go b/vendor/github.com/uber/jaeger-lib/metrics/factory.go new file mode 100644 index 000000000..a744a890d --- /dev/null +++ b/vendor/github.com/uber/jaeger-lib/metrics/factory.go @@ -0,0 +1,35 @@ +// Copyright (c) 2017 Uber Technologies, Inc. +// +// 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. + +package metrics + +// Factory creates new metrics +type Factory interface { + Counter(name string, tags map[string]string) Counter + Timer(name string, tags map[string]string) Timer + Gauge(name string, tags map[string]string) Gauge + + // Namespace returns a nested metrics factory. + Namespace(name string, tags map[string]string) Factory +} + +// NullFactory is a metrics factory that returns NullCounter, NullTimer, and NullGauge. +var NullFactory Factory = nullFactory{} + +type nullFactory struct{} + +func (nullFactory) Counter(name string, tags map[string]string) Counter { return NullCounter } +func (nullFactory) Timer(name string, tags map[string]string) Timer { return NullTimer } +func (nullFactory) Gauge(name string, tags map[string]string) Gauge { return NullGauge } +func (nullFactory) Namespace(name string, tags map[string]string) Factory { return NullFactory } diff --git a/vendor/github.com/uber/jaeger-lib/metrics/gauge.go b/vendor/github.com/uber/jaeger-lib/metrics/gauge.go new file mode 100644 index 000000000..3c606391a --- /dev/null +++ b/vendor/github.com/uber/jaeger-lib/metrics/gauge.go @@ -0,0 +1,28 @@ +// Copyright (c) 2017 Uber Technologies, Inc. +// +// 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. + +package metrics + +// Gauge returns instantaneous measurements of something as an int64 value +type Gauge interface { + // Update the gauge to the value passed in. + Update(int64) +} + +// NullGauge gauge that does nothing +var NullGauge Gauge = nullGauge{} + +type nullGauge struct{} + +func (nullGauge) Update(int64) {} diff --git a/vendor/github.com/uber/jaeger-lib/metrics/local.go b/vendor/github.com/uber/jaeger-lib/metrics/local.go new file mode 100644 index 000000000..8c3624849 --- /dev/null +++ b/vendor/github.com/uber/jaeger-lib/metrics/local.go @@ -0,0 +1,332 @@ +// Copyright (c) 2017 Uber Technologies, Inc. +// +// 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. + +package metrics + +import ( + "sort" + "sync" + "sync/atomic" + "time" + + "github.com/codahale/hdrhistogram" +) + +// This is intentionally very similar to github.com/codahale/metrics, the +// main difference being that counters/gauges are scoped to the provider +// rather than being global (to facilitate testing). + +// A LocalBackend is a metrics provider which aggregates data in-vm, and +// allows exporting snapshots to shove the data into a remote collector +type LocalBackend struct { + cm sync.Mutex + gm sync.Mutex + tm sync.Mutex + counters map[string]*int64 + gauges map[string]*int64 + timers map[string]*localBackendTimer + stop chan struct{} + wg sync.WaitGroup + TagsSep string + TagKVSep string +} + +// NewLocalBackend returns a new LocalBackend. The collectionInterval is the histogram +// time window for each timer. +func NewLocalBackend(collectionInterval time.Duration) *LocalBackend { + b := &LocalBackend{ + counters: make(map[string]*int64), + gauges: make(map[string]*int64), + timers: make(map[string]*localBackendTimer), + stop: make(chan struct{}), + TagsSep: "|", + TagKVSep: "=", + } + if collectionInterval == 0 { + // Use one histogram time window for all timers + return b + } + b.wg.Add(1) + go b.runLoop(collectionInterval) + return b +} + +// Clear discards accumulated stats +func (b *LocalBackend) Clear() { + b.cm.Lock() + defer b.cm.Unlock() + b.gm.Lock() + defer b.gm.Unlock() + b.tm.Lock() + defer b.tm.Unlock() + b.counters = make(map[string]*int64) + b.gauges = make(map[string]*int64) + b.timers = make(map[string]*localBackendTimer) +} + +func (b *LocalBackend) runLoop(collectionInterval time.Duration) { + defer b.wg.Done() + ticker := time.NewTicker(collectionInterval) + for { + select { + case <-ticker.C: + b.tm.Lock() + timers := make(map[string]*localBackendTimer, len(b.timers)) + for timerName, timer := range b.timers { + timers[timerName] = timer + } + b.tm.Unlock() + + for _, t := range timers { + t.Lock() + t.hist.Rotate() + t.Unlock() + } + case <-b.stop: + ticker.Stop() + return + } + } +} + +// IncCounter increments a counter value +func (b *LocalBackend) IncCounter(name string, tags map[string]string, delta int64) { + name = GetKey(name, tags, b.TagsSep, b.TagKVSep) + b.cm.Lock() + defer b.cm.Unlock() + counter := b.counters[name] + if counter == nil { + b.counters[name] = new(int64) + *b.counters[name] = delta + return + } + atomic.AddInt64(counter, delta) +} + +// UpdateGauge updates the value of a gauge +func (b *LocalBackend) UpdateGauge(name string, tags map[string]string, value int64) { + name = GetKey(name, tags, b.TagsSep, b.TagKVSep) + b.gm.Lock() + defer b.gm.Unlock() + gauge := b.gauges[name] + if gauge == nil { + b.gauges[name] = new(int64) + *b.gauges[name] = value + return + } + atomic.StoreInt64(gauge, value) +} + +// RecordTimer records a timing duration +func (b *LocalBackend) RecordTimer(name string, tags map[string]string, d time.Duration) { + name = GetKey(name, tags, b.TagsSep, b.TagKVSep) + timer := b.findOrCreateTimer(name) + timer.Lock() + timer.hist.Current.RecordValue(int64(d / time.Millisecond)) + timer.Unlock() +} + +func (b *LocalBackend) findOrCreateTimer(name string) *localBackendTimer { + b.tm.Lock() + defer b.tm.Unlock() + if t, ok := b.timers[name]; ok { + return t + } + + t := &localBackendTimer{ + hist: hdrhistogram.NewWindowed(5, 0, int64((5*time.Minute)/time.Millisecond), 1), + } + b.timers[name] = t + return t +} + +type localBackendTimer struct { + sync.Mutex + hist *hdrhistogram.WindowedHistogram +} + +var ( + percentiles = map[string]float64{ + "P50": 50, + "P75": 75, + "P90": 90, + "P95": 95, + "P99": 99, + "P999": 99.9, + } +) + +// Snapshot captures a snapshot of the current counter and gauge values +func (b *LocalBackend) Snapshot() (counters, gauges map[string]int64) { + b.cm.Lock() + defer b.cm.Unlock() + + counters = make(map[string]int64, len(b.counters)) + for name, value := range b.counters { + counters[name] = atomic.LoadInt64(value) + } + + b.gm.Lock() + defer b.gm.Unlock() + + gauges = make(map[string]int64, len(b.gauges)) + for name, value := range b.gauges { + gauges[name] = atomic.LoadInt64(value) + } + + b.tm.Lock() + timers := make(map[string]*localBackendTimer) + for timerName, timer := range b.timers { + timers[timerName] = timer + } + b.tm.Unlock() + + for timerName, timer := range timers { + timer.Lock() + hist := timer.hist.Merge() + timer.Unlock() + for name, q := range percentiles { + gauges[timerName+"."+name] = hist.ValueAtQuantile(q) + } + } + + return +} + +// Stop cleanly closes the background goroutine spawned by NewLocalBackend. +func (b *LocalBackend) Stop() { + close(b.stop) + b.wg.Wait() +} + +// GetKey converts name+tags into a single string of the form +// "name|tag1=value1|...|tagN=valueN", where tag names are +// sorted alphabetically. +func GetKey(name string, tags map[string]string, tagsSep string, tagKVSep string) string { + keys := make([]string, 0, len(tags)) + for k := range tags { + keys = append(keys, k) + } + sort.Strings(keys) + key := name + for _, k := range keys { + key = key + tagsSep + k + tagKVSep + tags[k] + } + return key +} + +type stats struct { + name string + tags map[string]string + localBackend *LocalBackend +} + +type localTimer struct { + stats +} + +func (l *localTimer) Record(d time.Duration) { + l.localBackend.RecordTimer(l.name, l.tags, d) +} + +type localCounter struct { + stats +} + +func (l *localCounter) Inc(delta int64) { + l.localBackend.IncCounter(l.name, l.tags, delta) +} + +type localGauge struct { + stats +} + +func (l *localGauge) Update(value int64) { + l.localBackend.UpdateGauge(l.name, l.tags, value) +} + +// LocalFactory stats factory that creates metrics that are stored locally +type LocalFactory struct { + *LocalBackend + namespace string + tags map[string]string +} + +// NewLocalFactory returns a new LocalMetricsFactory +func NewLocalFactory(collectionInterval time.Duration) *LocalFactory { + return &LocalFactory{ + LocalBackend: NewLocalBackend(collectionInterval), + } +} + +// appendTags adds the tags to the namespace tags and returns a combined map. +func (l *LocalFactory) appendTags(tags map[string]string) map[string]string { + newTags := make(map[string]string) + for k, v := range l.tags { + newTags[k] = v + } + for k, v := range tags { + newTags[k] = v + } + return newTags +} + +func (l *LocalFactory) newNamespace(name string) string { + if l.namespace == "" { + return name + } + return l.namespace + "." + name +} + +// Counter returns a local stats counter +func (l *LocalFactory) Counter(name string, tags map[string]string) Counter { + return &localCounter{ + stats{ + name: l.newNamespace(name), + tags: l.appendTags(tags), + localBackend: l.LocalBackend, + }, + } +} + +// Timer returns a local stats timer. +func (l *LocalFactory) Timer(name string, tags map[string]string) Timer { + return &localTimer{ + stats{ + name: l.newNamespace(name), + tags: l.appendTags(tags), + localBackend: l.LocalBackend, + }, + } +} + +// Gauge returns a local stats gauge. +func (l *LocalFactory) Gauge(name string, tags map[string]string) Gauge { + return &localGauge{ + stats{ + name: l.newNamespace(name), + tags: l.appendTags(tags), + localBackend: l.LocalBackend, + }, + } +} + +// Namespace returns a new namespace. +func (l *LocalFactory) Namespace(name string, tags map[string]string) Factory { + return &LocalFactory{ + namespace: l.newNamespace(name), + tags: l.appendTags(tags), + LocalBackend: l.LocalBackend, + } +} diff --git a/vendor/github.com/uber/jaeger-lib/metrics/metrics.go b/vendor/github.com/uber/jaeger-lib/metrics/metrics.go new file mode 100644 index 000000000..0b97707b0 --- /dev/null +++ b/vendor/github.com/uber/jaeger-lib/metrics/metrics.go @@ -0,0 +1,85 @@ +// Copyright (c) 2017 Uber Technologies, Inc. +// +// 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. + +package metrics + +import ( + "fmt" + "reflect" + "strings" +) + +// Init initializes the passed in metrics and initializes its fields using the passed in factory. +func Init(metrics interface{}, factory Factory, globalTags map[string]string) { + if err := initMetrics(metrics, factory, globalTags); err != nil { + panic(err.Error()) + } +} + +// initMetrics uses reflection to initialize a struct containing metrics fields +// by assigning new Counter/Gauge/Timer values with the metric name retrieved +// from the `metric` tag and stats tags retrieved from the `tags` tag. +// +// Note: all fields of the struct must be exported, have a `metric` tag, and be +// of type Counter or Gauge or Timer. +func initMetrics(m interface{}, factory Factory, globalTags map[string]string) error { + // Allow user to opt out of reporting metrics by passing in nil. + if factory == nil { + factory = NullFactory + } + + counterPtrType := reflect.TypeOf((*Counter)(nil)).Elem() + gaugePtrType := reflect.TypeOf((*Gauge)(nil)).Elem() + timerPtrType := reflect.TypeOf((*Timer)(nil)).Elem() + + v := reflect.ValueOf(m).Elem() + t := v.Type() + for i := 0; i < t.NumField(); i++ { + tags := make(map[string]string) + for k, v := range globalTags { + tags[k] = v + } + field := t.Field(i) + metric := field.Tag.Get("metric") + if metric == "" { + return fmt.Errorf("Field %s is missing a tag 'metric'", field.Name) + } + if tagString := field.Tag.Get("tags"); tagString != "" { + tagPairs := strings.Split(tagString, ",") + for _, tagPair := range tagPairs { + tag := strings.Split(tagPair, "=") + if len(tag) != 2 { + return fmt.Errorf( + "Field [%s]: Tag [%s] is not of the form key=value in 'tags' string [%s]", + field.Name, tagPair, tagString) + } + tags[tag[0]] = tag[1] + } + } + var obj interface{} + if field.Type.AssignableTo(counterPtrType) { + obj = factory.Counter(metric, tags) + } else if field.Type.AssignableTo(gaugePtrType) { + obj = factory.Gauge(metric, tags) + } else if field.Type.AssignableTo(timerPtrType) { + obj = factory.Timer(metric, tags) + } else { + return fmt.Errorf( + "Field %s is not a pointer to timer, gauge, or counter", + field.Name) + } + v.Field(i).Set(reflect.ValueOf(obj)) + } + return nil +} diff --git a/vendor/github.com/uber/jaeger-lib/metrics/stopwatch.go b/vendor/github.com/uber/jaeger-lib/metrics/stopwatch.go new file mode 100644 index 000000000..4a8abdb53 --- /dev/null +++ b/vendor/github.com/uber/jaeger-lib/metrics/stopwatch.go @@ -0,0 +1,43 @@ +// Copyright (c) 2017 Uber Technologies, Inc. +// +// 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. + +package metrics + +import ( + "time" +) + +// StartStopwatch begins recording the executing time of an event, returning +// a Stopwatch that should be used to stop the recording the time for +// that event. Multiple events can be occurring simultaneously each +// represented by different active Stopwatches +func StartStopwatch(timer Timer) Stopwatch { + return Stopwatch{t: timer, start: time.Now()} +} + +// A Stopwatch tracks the execution time of a specific event +type Stopwatch struct { + t Timer + start time.Time +} + +// Stop stops executing of the stopwatch and records the amount of elapsed time +func (s Stopwatch) Stop() { + s.t.Record(s.ElapsedTime()) +} + +// ElapsedTime returns the amount of elapsed time (in time.Duration) +func (s Stopwatch) ElapsedTime() time.Duration { + return time.Since(s.start) +} diff --git a/vendor/github.com/uber/jaeger-lib/metrics/timer.go b/vendor/github.com/uber/jaeger-lib/metrics/timer.go new file mode 100644 index 000000000..e18d222ab --- /dev/null +++ b/vendor/github.com/uber/jaeger-lib/metrics/timer.go @@ -0,0 +1,33 @@ +// Copyright (c) 2017 Uber Technologies, Inc. +// +// 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. + +package metrics + +import ( + "time" +) + +// Timer accumulates observations about how long some operation took, +// and also maintains a historgam of percentiles. +type Timer interface { + // Records the time passed in. + Record(time.Duration) +} + +// NullTimer timer that does nothing +var NullTimer Timer = nullTimer{} + +type nullTimer struct{} + +func (nullTimer) Record(time.Duration) {}