Commit f6caa48b authored by Yong Tang's avatar Yong Tang Committed by Miek Gieben

Update zipkin to the newer version (#1205)

* Update zipkin to the newer version

Also update thrift to use head commit
Signed-off-by: default avatarYong Tang <yong.tang.github@outlook.com>

* Update vendor directory.
Signed-off-by: default avatarYong Tang <yong.tang.github@outlook.com>
parent 3527be6c
......@@ -22,8 +22,7 @@
[[projects]]
name = "github.com/apache/thrift"
packages = ["lib/go/thrift"]
revision = "b2a4d4ae21c789b689dd162deb819665567f481c"
version = "0.10.0"
revision = "4f77ab8e296d64c57e6ea1c6e3f0f152bc7d6a3a"
[[projects]]
name = "github.com/asaskevich/govalidator"
......@@ -149,7 +148,7 @@
branch = "master"
name = "github.com/go-openapi/spec"
packages = ["."]
revision = "84b5bee7bcb76f3d17bcbaf421bac44bd5709ca6"
revision = "a4fa9574c7aa73b2fc54e251eb9524d0482bb592"
[[projects]]
branch = "master"
......@@ -197,7 +196,7 @@
branch = "master"
name = "github.com/grpc-ecosystem/grpc-opentracing"
packages = ["go/otgrpc"]
revision = "a570af39704b9f3d4bb530d83192a99ea6337d5a"
revision = "01f8541d537215b2867e2745a1eb85c58c7c6b81"
[[projects]]
branch = "master"
......@@ -233,7 +232,7 @@
branch = "master"
name = "github.com/mailru/easyjson"
packages = ["buffer","jlexer","jwriter"]
revision = "4d347d79dea0067c945f374f990601decb08abb5"
revision = "5f62e4f3afa2f576dc86531b7df4d966b19ef8f8"
[[projects]]
name = "github.com/matttproud/golang_protobuf_extensions"
......@@ -247,6 +246,12 @@
packages = ["."]
revision = "06020f85339e21b2478f756a78e295255ffa4d6a"
[[projects]]
branch = "master"
name = "github.com/opentracing-contrib/go-observer"
packages = ["."]
revision = "a52f2342449246d5bcc273e65cbdcfa5f7d6c63c"
[[projects]]
name = "github.com/opentracing/opentracing-go"
packages = [".","ext","log"]
......@@ -255,9 +260,8 @@
[[projects]]
name = "github.com/openzipkin/zipkin-go-opentracing"
packages = [".","_thrift/gen-go/scribe","_thrift/gen-go/zipkincore","flag","types","wire"]
revision = "d88c90182f3fb514be54a1c7adc11a04d41c7da9"
version = "v0.2.4"
packages = [".","flag","thrift/gen-go/scribe","thrift/gen-go/zipkincore","types","wire"]
revision = "45e90b00710a4c34a1a7d8a78d90f9b010b0bd4d"
[[projects]]
name = "github.com/pierrec/lz4"
......@@ -316,13 +320,13 @@
branch = "master"
name = "golang.org/x/crypto"
packages = ["ssh/terminal"]
revision = "bd6f299fb381e4c3393d1c4b1f0b94f5e77650c8"
revision = "6a293f2d4b14b8e6d3f0539e383f6d0d30fce3fd"
[[projects]]
branch = "master"
name = "golang.org/x/sys"
packages = ["unix","windows"]
revision = "4fe5d7925040acd225bf9c7cee65e82d07f06bff"
revision = "75813c647272dd855bda156405bf844a5414f5bf"
[[projects]]
branch = "master"
......@@ -374,6 +378,6 @@
[solve-meta]
analyzer-name = "dep"
analyzer-version = 1
inputs-digest = "9e6593b26c8f9a3841e988e46627fa440748742be455c2523b66b01501796ca4"
inputs-digest = "c7279ef091bb11a42d1421f51e53d761113ea23d9e9b993823605883da0f80ff"
solver-name = "gps-cdcl"
solver-version = 1
......@@ -15,7 +15,10 @@ ignored = [
[[constraint]]
name = "github.com/openzipkin/zipkin-go-opentracing"
version = "v0.2.3"
revision = "45e90b00710a4c34a1a7d8a78d90f9b010b0bd4d"
[[override]]
name = "github.com/apache/thrift"
revision = "4f77ab8e296d64c57e6ea1c6e3f0f152bc7d6a3a"
[[override]]
name = "github.com/ugorji/go"
......
......@@ -21,6 +21,7 @@
*.swp
*.hi
*~
tags
.*project
junit*.properties
......@@ -36,6 +37,8 @@ node_modules
compile
test-driver
erl_crash.dump
package-lock.json
project.lock.json
.sonar
.DS_Store
......@@ -101,6 +104,7 @@ erl_crash.dump
/lib/cpp/src/thrift/stamp-h2
/lib/cpp/test/Benchmark
/lib/cpp/test/AllProtocolsTest
/lib/cpp/test/AnnotationTest
/lib/cpp/test/DebugProtoTest
/lib/cpp/test/DenseProtoTest
/lib/cpp/test/EnumTest
......@@ -114,6 +118,7 @@ erl_crash.dump
/lib/cpp/test/TFileTransportTest
/lib/cpp/test/TInterruptTest
/lib/cpp/test/TNonblockingServerTest
/lib/cpp/test/TNonblockingSSLServerTest
/lib/cpp/test/TPipedTransportTest
/lib/cpp/test/TServerIntegrationTest
/lib/cpp/test/TSocketInterruptTest
......@@ -149,6 +154,7 @@ erl_crash.dump
/lib/c_glib/test/testframedtransport
/lib/c_glib/test/testmemorybuffer
/lib/c_glib/test/testoptionalrequired
/lib/c_glib/test/testtransportsslsocket
/lib/c_glib/test/testsimpleserver
/lib/c_glib/test/teststruct
/lib/c_glib/test/testthrifttest
......@@ -204,17 +210,26 @@ erl_crash.dump
/lib/delphi/test/typeregistry/*.identcache
/lib/delphi/test/typeregistry/*.local
/lib/delphi/test/typeregistry/*.dcu
/lib/erl/.generated
/lib/erl/.eunit
/lib/erl/ebin
/lib/erl/.generated
/lib/erl/.rebar/
/lib/erl/deps/
/lib/erl/ebin
/lib/erl/src/thrift.app.src
/lib/erl/test/*.hrl
/lib/erl/test/*.beam
/lib/erl/test/*.hrl
/lib/erl/test/Thrift_omit_without.thrift
/lib/haxe/test/bin
/lib/hs/dist
/lib/java/build
/lib/js/dist
/lib/js/doc
/lib/js/package-lock.json
/lib/js/test/build
/lib/netcore/**/.vs
/lib/netcore/**/bin
/lib/netcore/**/obj
/lib/netcore/**/gen-*
/lib/nodejs/coverage
/lib/nodejs/node_modules/
/lib/perl/MANIFEST
......@@ -254,8 +269,22 @@ erl_crash.dump
/lib/php/test/packages/
/lib/py/dist/
/lib/erl/logs/
/lib/go/pkg
/lib/go/src
/lib/go/test/gopath/
/lib/go/test/ThriftTest.thrift
/lib/rs/target/
/lib/rs/Cargo.lock
/lib/rs/test/Cargo.lock
/lib/rs/test/target/
/lib/rs/test/bin/
/lib/rs/test/src/base_one.rs
/lib/rs/test/src/base_two.rs
/lib/rs/test/src/midlayer.rs
/lib/rs/test/src/recursive.rs
/lib/rs/test/src/ultimate.rs
/lib/rs/*.iml
/lib/rs/**/*.iml
/libtool
/ltmain.sh
/missing
......@@ -276,20 +305,36 @@ erl_crash.dump
/test/log/
/test/test.log
/test/erl/.generated
/test/erl/.rebar
/test/erl/ebin
/test/go/bin/
/test/go/ThriftTest.thrift
/test/go/gopath
/test/go/pkg/
/test/go/src/code.google.com/
/test/go/src/common/mock_handler.go
/test/go/src/github.com/golang/
/test/go/src/golang.org/
/test/go/src/gen/
/test/go/src/thrift
/test/haxe/bin
/test/hs/TestClient
/test/hs/TestServer
/test/php/php_ext_dir/
/test/py.twisted/_trial_temp/
/test/rb/Gemfile.lock
/test/netcore/**/.vs
/test/netcore/**/bin
/test/netcore/**/obj
/test/netcore/**/gen-*
/test/netcore/Thrift
/test/php/php_ext_dir/
/test/rs/Cargo.lock
/test/rs/src/thrift_test.rs
/test/rs/bin/
/test/rs/target/
/test/rs/*.iml
/test/rs/**/*.iml
/tutorial/cpp/TutorialClient
/tutorial/cpp/TutorialServer
/tutorial/c_glib/tutorial_client
......@@ -314,13 +359,26 @@ erl_crash.dump
/tutorial/delphi/DelphiClient/*.identcache
/tutorial/delphi/DelphiServer/*.identcache
/tutorial/delphi/DelphiServer/*.local
/tutorial/go/gopath
/tutorial/go/go-tutorial
/tutorial/go/calculator-remote
/tutorial/go/src/shared
/tutorial/go/src/tutorial
/tutorial/go/src/git.apache.org
/tutorial/go/src/golang.org
/tutorial/haxe/bin
/tutorial/hs/dist/
/tutorial/java/build/
/tutorial/js/build/
/tutorial/netcore/**/.vs
/tutorial/netcore/**/bin
/tutorial/netcore/**/obj
/tutorial/netcore/**/gen-*
/tutorial/netcore/Thrift
/tutorial/rs/*.iml
/tutorial/rs/src/shared.rs
/tutorial/rs/src/tutorial.rs
/tutorial/rs/bin
/tutorial/rs/target
/tutorial/rs/Cargo.lock
/ylwrap
max_width = 100
fn_args_layout = "Block"
array_layout = "Block"
where_style = "Rfc"
generics_indent = "Block"
fn_call_style = "Block"
reorder_imported_names = true
This diff is collapsed.
......@@ -17,7 +17,14 @@
# under the License.
#
cmake_minimum_required(VERSION 2.8.12)
cmake_minimum_required(VERSION 3.1)
# CMake 3.1 supports C++ standards selection with CMAKE_CXX_STANDARD
# If you need CMake 3.1+ for Ubuntu 14.04, try
# https://launchpad.net/~george-edison55/+archive/ubuntu/cmake-3.x
# If you need CMake 3.1+ for debian "jessie", get it from jessie-backports
# Otherwise
# http://cmake.org
project("Apache Thrift")
......
## How to contribute
1. Help to review and verify existing patches
1. Make sure your issue is not all ready in the [Jira issue tracker](http://issues.apache.org/jira/browse/THRIFT)
1. If not, create a ticket describing the change you're proposing in the [Jira issue tracker](http://issues.apache.org/jira/browse/THRIFT)
1. Contribute your patch using one of the two methods below
# How to Contribute #
### Contributing via a patch
Thank you for your interest in contributing to the Apache Thrift project! Information on why and how to contribute is available on the Apache Software Foundation (ASF) web site. In particular, we recommend the following to become acquainted with Apache Contributions:
1. Check out the latest version of the source code
* [Contributors Tech Guide](http://www.apache.org/dev/contributors)
* [Get involved!](http://www.apache.org/foundation/getinvolved.html)
* [Legal aspects on Submission of Contributions (Patches)](http://www.apache.org/licenses/LICENSE-2.0.html#contributions)
* git clone https://git-wip-us.apache.org/repos/asf/thrift.git thrift
## If you want to review open issues... ##
1. Modify the source to include the improvement/bugfix
1. Review the [GitHub Pull Request Backlog](https://github.com/apache/thrift/pulls). Code reviews are open to all.
2. Review the [Jira issue tracker](http://issues.apache.org/jira/browse/THRIFT). You can search for tickets relating to languages you are interested in or currently using with thrift, for example a Jira search (Issues -> Search For Issues) query of ``project = THRIFT AND component in ("Erlang - Library") and status not in (resolved, closed)`` will locate all the open Erlang Library issues.
* Remember to provide *tests* for all submited changes
* When bugfixing: add test that will isolate bug *before* applying change that fixes it
* Verify that you follow [Thrift Coding Standards](/docs/coding_standards) (you can run 'make style', which ensures proper format for some languages)
## If you discovered a defect... ##
1. Create a patch from project root directory (e.g. you@dev:~/thrift $ ):
1. Check to see if the issue is already in the [Jira issue tracker](http://issues.apache.org/jira/browse/THRIFT).
1. If not, create a ticket describing the change you're proposing in the Jira issue tracker.
1. Contribute your code changes using the GitHub pull request method:
* git diff > ../thrift-XXX-my-new-feature.patch
## Contributing via GitHub pull requests ##
1. Attach the newly generated patch to the issue
1. Wait for other contributors or committers to review your new addition
1. Wait for a committer to commit your patch
This is the preferred method of submitting changes. When you submit a pull request through github, it activates the continuous integration (CI) build systems at Appveyor and Travis to build your changes on a variety of Windows and Linux configurations and run all the test suites.
### Contributing via GitHub pull requests
1. Create a fork in your GitHub account of http://github.com/apache/thrift
1. Clone the fork to your development system.
1. Create a branch for your changes (best practice is issue as branch name, e.g. THRIFT-9999).
1. Modify the source to include the improvement/bugfix, and:
1. Create a fork for http://github.com/apache/thrift
1. Create a branch for your changes(best practice is issue as branch name, e.g. THRIFT-9999)
1. Modify the source to include the improvement/bugfix
* Remember to provide *tests* for all submitted changes!
* Use test-driven development (TDD): add a test that will isolate the bug *before* applying a change that fixes it.
* Verify that you follow [Thrift Coding Standards](/docs/coding_standards) (you can run 'make style', which ensures proper format for some languages).
* [*optional*] Verify that your change works on other platforms by adding a GitHub service hook to [Travis CI](http://docs.travis-ci.com/user/getting-started/#Step-one%3A-Sign-in) and [AppVeyor](http://www.appveyor.com/docs). You can use this technique to run the Thrift CI jobs in your account to check your changes before they are made public. Every GitHub pull request into Thrift will run the full CI build and test suite on your changes.
* Remember to provide *tests* for all submited changes
* When bugfixing: add test that will isolate bug *before* applying change that fixes it
* Verify that you follow [Thrift Coding Standards](/docs/coding_standards) (you can run 'make style', which ensures proper format for some languages)
* Verify that your change works on other platforms by adding a GitHub service hook to [Travis CI](http://docs.travis-ci.com/user/getting-started/#Step-one%3A-Sign-in) and [AppVeyor](http://www.appveyor.com/docs)
1. Squash your changes to a single commit. This is very important as it makes the process of applying your commit upstream much easier.
1. Commit and push changes to your branch (please use issue name and description as commit title, e.g. "THRIFT-9999: make it perfect").
1. Use GitHub to create a pull request going from your branch to apache:master. Ensure that the Jira ticket number is at the beginning of the title of your pull request, same as the commit title.
1. Wait for other contributors or committers to review your new addition, and for a CI build to complete.
1. Wait for a committer to commit your patch. You can nudge the committers if necessary by sending a message to the [Apache Thrift mailing list](https://thrift.apache.org/mailing).
1. Commit and push changes to your branch (please use issue name and description as commit title, e.g. THRIFT-9999 make it perfect)
1. Issue a pull request with the jira ticket number you are working on in it's name
1. Wait for other contributors or committers to review your new addition
1. Wait for a committer to commit your patch
## Contributing via Patch ##
### More info
Some changes do not require a build, for example in documentation. For changes that are not code or build related, you can submit a patch on Jira for review. To create a patch from changes in your local directory:
git diff > ../THRIFT-NNNN.patch
then wait for contributors or committers to review your changes, and then for a committer to apply your patch.
## GitHub recipes for Pull Requests ##
Sometimes commmitters may ask you to take actions in your pull requests. Here are some recipes that will help you accomplish those requests. These examples assume you are working on Jira issue THRIFT-9999. You should also be familiar with the [upstream](https://help.github.com/articles/syncing-a-fork/) repository concept.
### Squash your changes ###
If you have not submitted a pull request yet, or if you have not yet rebased your existing pull request, you can squash all your commits down to a single commit. This makes life easier for the committers. If your pull request on GitHub has more than one commit, you should do this.
1. Use the command ``git log`` to identify how many commits you made since you began.
2. Use the command ``git rebase -i HEAD~N`` where N is the number of commits.
3. Leave "pull" in the first line.
4. Change all other lines from "pull" to "fixup".
5. All your changes are now in a single commit.
If you already have a pull request outstanding, you will need to do a "force push" to overwrite it since you changed your commit history:
git push -u origin THRIFT-9999 --force
A more detailed walkthrough of a squash can be found at [Git Ready](http://gitready.com/advanced/2009/02/10/squashing-commits-with-rebase.html).
### Rebase your pull request ###
If your pull request has a conflict with master, it needs to be rebased:
git checkout THRIFT-9999
git rebase upstream master
(resolve any conflicts, make sure it builds)
git push -u origin THRIFT-9999 --force
### Fix a bad merge ###
If your pull request contains commits that are not yours, then you should use the following technique to fix the bad merge in your branch:
git checkout master
git pull upstream master
git checkout -b THRIFT-9999-take-2
git cherry-pick ...
(pick only your commits from your original pull request in ascending chronological order)
squash your changes to a single commit if there is more than one (see above)
git push -u origin THRIFT-9999-take-2:THRIFT-9999
This procedure will apply only your commits in order to the current master, then you will squash them to a single commit, and then you force push your local THRIFT-9999-take-2 into remote THRIFT-9999 which represents your pull request, replacing all the commits with the new one.
Plenty of information on why and how to contribute is available on the Apache Software Foundation (ASF) web site. In particular, we recommend the following:
* [Contributors Tech Guide](http://www.apache.org/dev/contributors)
* [Get involved!](http://www.apache.org/foundation/getinvolved.html)
* [Legal aspects on Submission of Contributions (Patches)](http://www.apache.org/licenses/LICENSE-2.0.html#contributions)
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
#
# Goal: provide a thrift-compiler Docker image
#
# Usage:
# docker run -v "${PWD}:/data" thrift/thrift-compiler -gen cpp -o /data/ /data/test/ThriftTest.thrift
#
# further details on docker for thrift is here build/docker/
#
# TODO: push to apache/thrift-compiler instead of thrift/thrift-compiler
FROM debian:jessie
MAINTAINER Apache Thrift <dev@thrift.apache.org>
ENV DEBIAN_FRONTEND noninteractive
ADD . /thrift
RUN buildDeps=" \
flex \
bison \
g++ \
make \
cmake \
curl \
"; \
apt-get update && apt-get install -y --no-install-recommends $buildDeps \
&& mkdir /tmp/cmake-build && cd /tmp/cmake-build \
&& cmake \
-DBUILD_COMPILER=ON \
-DBUILD_LIBRARIES=OFF \
-DBUILD_TESTING=OFF \
-DBUILD_EXAMPLES=OFF \
/thrift \
&& cmake --build . --config Release \
&& make install \
&& curl -k -sSL "https://storage.googleapis.com/golang/go1.5.2.linux-amd64.tar.gz" -o /tmp/go.tar.gz \
&& tar xzf /tmp/go.tar.gz -C /tmp \
&& cp /tmp/go/bin/gofmt /usr/bin/gofmt \
&& apt-get purge -y --auto-remove $buildDeps \
&& apt-get clean \
&& rm -rf /tmp/* \
&& rm -rf /var/lib/apt/lists/*
ENTRYPOINT ["thrift"]
This diff is collapsed.
......@@ -43,7 +43,7 @@ dist-hook:
find $(distdir) -type d \( -iname ".svn" -or -iname ".git" \) | xargs rm -rf
print-version:
@echo $(VERSION)
@echo $(PACKAGE_VERSION)
.PHONY: precross cross
precross-%: all
......@@ -54,7 +54,7 @@ empty :=
space := $(empty) $(empty)
comma := ,
CROSS_LANGS = @MAYBE_CPP@ @MAYBE_C_GLIB@ @MAYBE_D@ @MAYBE_JAVA@ @MAYBE_CSHARP@ @MAYBE_PYTHON@ @MAYBE_PY3@ @MAYBE_RUBY@ @MAYBE_HASKELL@ @MAYBE_PERL@ @MAYBE_PHP@ @MAYBE_GO@ @MAYBE_NODEJS@ @MAYBE_DART@ @MAYBE_ERLANG@ @MAYBE_LUA@
CROSS_LANGS = @MAYBE_CPP@ @MAYBE_C_GLIB@ @MAYBE_D@ @MAYBE_JAVA@ @MAYBE_CSHARP@ @MAYBE_PYTHON@ @MAYBE_PY3@ @MAYBE_RUBY@ @MAYBE_HASKELL@ @MAYBE_PERL@ @MAYBE_PHP@ @MAYBE_GO@ @MAYBE_NODEJS@ @MAYBE_DART@ @MAYBE_ERLANG@ @MAYBE_LUA@ @MAYBE_RS@ @MAYBE_DOTNETCORE@
CROSS_LANGS_COMMA_SEPARATED = $(subst $(space),$(comma),$(CROSS_LANGS))
if WITH_PY3
......@@ -123,7 +123,7 @@ EXTRA_DIST = \
doap.rdf \
package.json \
sonar-project.properties \
Dockerfile \
LANGUAGES.md \
LICENSE \
CHANGES \
NOTICE \
......
Apache Thrift
Copyright 2006-2010 The Apache Software Foundation.
Copyright 2006-2017 The Apache Software Foundation.
This product includes software developed at
The Apache Software Foundation (http://www.apache.org/).
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)
Last Modified: 2014-03-16
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.
Introduction
============
......@@ -15,15 +33,22 @@ 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.
![Apache Thrift Layered Architecture](doc/images/thrift-layers.png)
Thrift makes it easy for programs written in different programming
languages to share data and call remote procedures. With support
for [over 20 programming languages](LANGUAGES.md), chances are Thrift
supports the ones that you currently use.
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
the Thrift whitepaper included in this distribution or at the README.md file
in your particular subdirectory of interest.
Hierarchy
=========
Project Hierarchy
=================
thrift/
......@@ -42,6 +67,7 @@ thrift/
php/
py/
rb/
...
test/
......@@ -145,22 +171,3 @@ To run the cross-language test suite, please run:
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.
Pod::Spec.new do |s|
s.name = "Thrift"
s.version = "0.10.0"
s.version = "1.0.0"
s.summary = "Apache Thrift is a lightweight, language-independent software stack with an associated code generation mechanism for RPC."
s.description = <<-DESC
The Apache Thrift software framework, for scalable cross-language services development, combines a software stack with a code generation engine to build services that work efficiently and seamlessly between C++, Java, Python, PHP, Ruby, Erlang, Perl, Haskell, C#, Cocoa, JavaScript, Node.js, Smalltalk, OCaml and Delphi and other languages.
......@@ -13,6 +13,6 @@ The Apache Thrift software framework, for scalable cross-language services devel
s.osx.deployment_target = '10.8'
s.ios.framework = 'CFNetwork'
s.osx.framework = 'CoreServices'
s.source = { :git => "https://github.com/apache/thrift.git", :tag => "thrift-0.10.0" }
s.source = { :git => "https://github.com/apache/thrift.git", :tag => "thrift-1.0.0" }
s.source_files = 'lib/cocoa/src/**/*.{h,m,swift}'
end
\ No newline at end of file
#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
......@@ -18,76 +19,83 @@
# build Apache Thrift on AppVeyor - https://ci.appveyor.com
version: '1.0.0-dev.{build}'
shallow_clone: true
clone_depth: 10
version: '{build}'
os:
# - Windows Server 2012 R2
- Visual Studio 2015
- Visual Studio 2015
cache:
- C:\projects\thrift\buildcache -> build\appveyor\MSVC-appveyor-install.bat
- C:\ProgramData\chocolatey\lib -> build\appveyor\MSVC-appveyor-install.bat
- C:\msys64\var\cache\pacman -> build\appveyor\MSYS-appveyor-install.bat
environment:
BOOST_ROOT: C:\Libraries\boost_1_59_0
BOOST_LIBRARYDIR: C:\Libraries\boost_1_59_0\lib64-msvc-14.0
# Unfurtunately, this version needs manual update because old versions are quickly deleted.
ANT_VERSION: 1.9.7
matrix:
- PROFILE: MSVC2010
PLATFORM: x86
CONFIGURATION: Debug
BOOST_VERSION: 1.54.0
LIBEVENT_VERSION: 2.0.22
QT_VERSION: 5.6
ZLIB_VERSION: 1.2.8
DISABLED_TESTS: StressTestNonBlocking
install:
- '"C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" x64'
- cd \
# Zlib
- appveyor DownloadFile https://github.com/madler/zlib/archive/v1.2.8.tar.gz
- 7z x v1.2.8.tar.gz -so | 7z x -si -ttar > nul
- cd zlib-1.2.8
- cmake -G "Visual Studio 14 2015 Win64" .
- cmake --build . --config release
- cd ..
# OpenSSL
- C:\Python35-x64\python %APPVEYOR_BUILD_FOLDER%\build\appveyor\download_openssl.py
- ps: Start-Process "Win64OpenSSL.exe" -ArgumentList "/silent /verysilent /sp- /suppressmsgboxes" -Wait
# Libevent
- appveyor DownloadFile https://github.com/libevent/libevent/releases/download/release-2.0.22-stable/libevent-2.0.22-stable.tar.gz
- 7z x libevent-2.0.22-stable.tar.gz -so | 7z x -si -ttar > nul
- cd libevent-2.0.22-stable
- nmake -f Makefile.nmake
- mkdir lib
- move *.lib lib\
- move WIN32-Code\event2\* include\event2\
- move *.h include\
- cd ..
- appveyor-retry cinst -y winflexbison
- appveyor DownloadFile http://www.us.apache.org/dist/ant/binaries/apache-ant-%ANT_VERSION%-bin.zip
- 7z x apache-ant-%ANT_VERSION%-bin.zip > nul
- cd %APPVEYOR_BUILD_FOLDER%
# TODO: Enable Haskell build
# - cinst HaskellPlatform -version 2014.2.0.0
- PROFILE: MSVC2015
PLATFORM: x64
CONFIGURATION: Release
BOOST_VERSION: 1.64.0
LIBEVENT_VERSION: 2.0.22
PYTHON_VERSION: 3.6
QT_VERSION: 5.8
ZLIB_VERSION: 1.2.11
DISABLED_TESTS: StressTestNonBlocking
- PROFILE: MINGW
PLATFORM: x64
CONFIGURATION: Release
matrix:
fast_finish: true
install:
- cd %APPVEYOR_BUILD_FOLDER%
- call build\appveyor\%PROFILE:~0,4%-appveyor-install.bat
- refreshenv
build_script:
- set PATH=C:\ProgramData\chocolatey\bin;C:\apache-ant-%ANT_VERSION%\bin;%PATH%
- set JAVA_HOME=C:\Program Files\Java\jdk1.7.0
- set PATH=%JAVA_HOME%\bin;%PATH%
# - set PATH=%PATH%;C:\Program Files (x86)\Haskell Platform\2014.2.0.0\bin
# - set PATH=%PATH%;C:\Program Files (x86)\Haskell Platform\2014.2.0.0\lib\extralibs\bin
- set PATH=C:\Python27-x64\scripts;C:\Python27-x64;%PATH%
- pip install ipaddress backports.ssl_match_hostname tornado twisted
- mkdir cmake-build
- cd cmake-build
- cmake -G "Visual Studio 14 2015 Win64" -DWITH_SHARED_LIB=OFF -DLIBEVENT_ROOT=C:\libevent-2.0.22-stable -DZLIB_INCLUDE_DIR=C:\zlib-1.2.8 -DZLIB_LIBRARY=C:\zlib-1.2.8\release\zlibstatic.lib -DBOOST_ROOT="%BOOST_ROOT%" -DBOOST_LIBRARYDIR="%BOOST_LIBRARYDIR%" ..
- findstr /b /e BUILD_COMPILER:BOOL=ON CMakeCache.txt
- findstr /b /e BUILD_CPP:BOOL=ON CMakeCache.txt
- findstr /b /e BUILD_JAVA:BOOL=ON CMakeCache.txt
- findstr /b /e BUILD_PYTHON:BOOL=ON CMakeCache.txt
# - findstr /b /e BUILD_C_GLIB:BOOL=ON CMakeCache.txt
# - findstr /b /e BUILD_HASKELL:BOOL=ON CMakeCache.txt
- findstr /b /e BUILD_TESTING:BOOL=ON CMakeCache.txt
# - cmake --build .
- cmake --build . --config Release
# TODO: Fix cpack
# - cpack
# TODO: Run more tests
# CTest fails to invoke ant seemingly due to "ant.bat" v.s. "ant" (shell script) conflict.
# Currently, everything that involves OpenSSL seems to hang forever on our Appveyor setup.
# Also a few C++ tests hang (on Appveyor or on Windows in general).
- ctest -C Release --timeout 600 -VV -E "(StressTestNonBlocking|PythonTestSSLSocket|python_test$|^Java)"
# TODO make it perfect ;-r
- cd %APPVEYOR_BUILD_FOLDER%
- call build\appveyor\%PROFILE:~0,4%-appveyor-build.bat
test_script:
- cd %APPVEYOR_BUILD_FOLDER%
- call build\appveyor\%PROFILE:~0,4%-appveyor-test.bat
# artifact capture disabled as it might increase service cost for little gain:
#
# artifacts:
# - path: local-thrift-inst
# name: cmake installed content
# type: zip
#
# - path: local-thrift-build\Testing
# name: ctest output
# type: zip
# RDP support: use one or the other...
#
# enables RDP for each build job so you can inspect the environment at the beginning of the job:
# init:
# - ps: iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1'))
#
# enables RDP at the end of the build job so you can login and re-run
# commands to see why something failed...
#on_finish:
# - ps: $blockRdp = $true; iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1'))
#
# also need:
# environment:
# APPVEYOR_RDP_PASSWORD: thr1FT2345$xyzZ
......@@ -46,9 +46,12 @@ if [ "$AUTOMAKE_VERSION" \< "1.13" ]; then
exit 1
fi
set -e
autoscan
$LIBTOOLIZE --copy --automake
aclocal -I ./aclocal
autoheader
sed '/undef VERSION/d' config.hin > config.hin2
mv config.hin2 config.hin
autoconf
automake --copy --add-missing --foreign
{
"name": "thrift",
"version": "0.10.0",
"homepage": "https://git-wip-us.apache.org/repos/asf/thrift.git",
"authors": [
"Apache Thrift <dev@thrift.apache.org>"
......
......@@ -24,7 +24,7 @@
"minimum-stability": "dev",
"extra": {
"branch-alias": {
"dev-master": "0.10.0"
"dev-master": "1.0.x-dev"
}
}
}
......@@ -71,6 +71,10 @@ if WITH_DART
SUBDIRS += dart
endif
if WITH_DOTNETCORE
SUBDIRS += netcore
endif
if WITH_GO
SUBDIRS += go
endif
......@@ -89,6 +93,10 @@ if WITH_LUA
SUBDIRS += lua
endif
if WITH_RS
SUBDIRS += rs
endif
# All of the libs that don't use Automake need to go in here
# so they will end up in our release tarballs.
EXTRA_DIST = \
......
......@@ -31,10 +31,15 @@ install:
@echo '##############################################################'
check-local:
$(GO) test ./thrift
GOPATH=`pwd` $(GO) get golang.org/x/net/context
GOPATH=`pwd` $(GO) test -race ./thrift
clean-local:
$(RM) -rf pkg
all-local:
$(GO) build ./thrift
GOPATH=`pwd` $(GO) get golang.org/x/net/context
GOPATH=`pwd` $(GO) build ./thrift
EXTRA_DIST = \
thrift \
......
......@@ -30,11 +30,22 @@ const (
PROTOCOL_ERROR = 7
)
var defaultApplicationExceptionMessage = map[int32]string{
UNKNOWN_APPLICATION_EXCEPTION: "unknown application exception",
UNKNOWN_METHOD: "unknown method",
INVALID_MESSAGE_TYPE_EXCEPTION: "invalid message type",
WRONG_METHOD_NAME: "wrong method name",
BAD_SEQUENCE_ID: "bad sequence ID",
MISSING_RESULT: "missing result",
INTERNAL_ERROR: "unknown internal error",
PROTOCOL_ERROR: "unknown protocol error",
}
// Application level Thrift exception
type TApplicationException interface {
TException
TypeId() int32
Read(iprot TProtocol) (TApplicationException, error)
Read(iprot TProtocol) error
Write(oprot TProtocol) error
}
......@@ -44,7 +55,10 @@ type tApplicationException struct {
}
func (e tApplicationException) Error() string {
if e.message != "" {
return e.message
}
return defaultApplicationExceptionMessage[e.type_]
}
func NewTApplicationException(type_ int32, message string) TApplicationException {
......@@ -55,10 +69,11 @@ func (p *tApplicationException) TypeId() int32 {
return p.type_
}
func (p *tApplicationException) Read(iprot TProtocol) (TApplicationException, error) {
func (p *tApplicationException) Read(iprot TProtocol) error {
// TODO: this should really be generated by the compiler
_, err := iprot.ReadStructBegin()
if err != nil {
return nil, err
return err
}
message := ""
......@@ -67,7 +82,7 @@ func (p *tApplicationException) Read(iprot TProtocol) (TApplicationException, er
for {
_, ttype, id, err := iprot.ReadFieldBegin()
if err != nil {
return nil, err
return err
}
if ttype == STOP {
break
......@@ -76,33 +91,40 @@ func (p *tApplicationException) Read(iprot TProtocol) (TApplicationException, er
case 1:
if ttype == STRING {
if message, err = iprot.ReadString(); err != nil {
return nil, err
return err
}
} else {
if err = SkipDefaultDepth(iprot, ttype); err != nil {
return nil, err
return err
}
}
case 2:
if ttype == I32 {
if type_, err = iprot.ReadI32(); err != nil {
return nil, err
return err
}
} else {
if err = SkipDefaultDepth(iprot, ttype); err != nil {
return nil, err
return err
}
}
default:
if err = SkipDefaultDepth(iprot, ttype); err != nil {
return nil, err
return err
}
}
if err = iprot.ReadFieldEnd(); err != nil {
return nil, err
return err
}
}
return NewTApplicationException(type_, message), iprot.ReadStructEnd()
if err := iprot.ReadStructEnd(); err != nil {
return err
}
p.message = message
p.type_ = type_
return nil
}
func (p *tApplicationException) Write(oprot TProtocol) (err error) {
......
......@@ -25,7 +25,7 @@ import (
func TestTApplicationException(t *testing.T) {
exc := NewTApplicationException(UNKNOWN_APPLICATION_EXCEPTION, "")
if exc.Error() != "" {
if exc.Error() != defaultApplicationExceptionMessage[UNKNOWN_APPLICATION_EXCEPTION] {
t.Fatalf("Expected empty string for exception but found '%s'", exc.Error())
}
if exc.TypeId() != UNKNOWN_APPLICATION_EXCEPTION {
......
......@@ -32,8 +32,8 @@ type TBufferedTransport struct {
tp TTransport
}
func (p *TBufferedTransportFactory) GetTransport(trans TTransport) TTransport {
return NewTBufferedTransport(trans, p.size)
func (p *TBufferedTransportFactory) GetTransport(trans TTransport) (TTransport, error) {
return NewTBufferedTransport(trans, p.size), nil
}
func NewTBufferedTransportFactory(bufferSize int) *TBufferedTransportFactory {
......
package thrift
import "fmt"
type TStandardClient struct {
seqId int32
iprot, oprot TProtocol
}
// TStandardClient implements TClient, and uses the standard message format for Thrift.
// It is not safe for concurrent use.
func NewTStandardClient(inputProtocol, outputProtocol TProtocol) *TStandardClient {
return &TStandardClient{
iprot: inputProtocol,
oprot: outputProtocol,
}
}
func (p *TStandardClient) Send(oprot TProtocol, seqId int32, method string, args TStruct) error {
if err := oprot.WriteMessageBegin(method, CALL, seqId); err != nil {
return err
}
if err := args.Write(oprot); err != nil {
return err
}
if err := oprot.WriteMessageEnd(); err != nil {
return err
}
return oprot.Flush()
}
func (p *TStandardClient) Recv(iprot TProtocol, seqId int32, method string, result TStruct) error {
rMethod, rTypeId, rSeqId, err := iprot.ReadMessageBegin()
if err != nil {
return err
}
if method != rMethod {
return NewTApplicationException(WRONG_METHOD_NAME, fmt.Sprintf("%s: wrong method name", method))
} else if seqId != rSeqId {
return NewTApplicationException(BAD_SEQUENCE_ID, fmt.Sprintf("%s: out of order sequence response", method))
} else if rTypeId == EXCEPTION {
var exception tApplicationException
if err := exception.Read(iprot); err != nil {
return err
}
if err := iprot.ReadMessageEnd(); err != nil {
return err
}
return &exception
} else if rTypeId != REPLY {
return NewTApplicationException(INVALID_MESSAGE_TYPE_EXCEPTION, fmt.Sprintf("%s: invalid message type", method))
}
if err := result.Read(iprot); err != nil {
return err
}
return iprot.ReadMessageEnd()
}
func (p *TStandardClient) call(method string, args, result TStruct) error {
p.seqId++
seqId := p.seqId
if err := p.Send(p.oprot, seqId, method, args); err != nil {
return err
}
// method is oneway
if result == nil {
return nil
}
return p.Recv(p.iprot, seqId, method, result)
}
// +build go1.7
package thrift
import "context"
type TClient interface {
Call(ctx context.Context, method string, args, result TStruct) error
}
func (p *TStandardClient) Call(ctx context.Context, method string, args, result TStruct) error {
return p.call(method, args, result)
}
// +build !go1.7
package thrift
import "golang.org/x/net/context"
type TClient interface {
Call(ctx context.Context, method string, args, result TStruct) error
}
func (p *TStandardClient) Call(ctx context.Context, method string, args, result TStruct) error {
return p.call(method, args, result)
}
// +build go1.7
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT 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 "context"
type mockProcessor struct {
ProcessFunc func(in, out TProtocol) (bool, TException)
}
func (m *mockProcessor) Process(ctx context.Context, in, out TProtocol) (bool, TException) {
return m.ProcessFunc(in, out)
}
// +build !go1.7
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT 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 "golang.org/x/net/context"
type mockProcessor struct {
ProcessFunc func(in, out TProtocol) (bool, TException)
}
func (m *mockProcessor) Process(ctx context.Context, in, out TProtocol) (bool, TException) {
return m.ProcessFunc(in, out)
}
......@@ -32,22 +32,22 @@ func TestReadWriteCompactProtocol(t *testing.T) {
NewTFramedTransport(NewTMemoryBuffer()),
}
for _, trans := range transports {
p := NewTCompactProtocol(trans);
ReadWriteBool(t, p, trans);
p = NewTCompactProtocol(trans);
ReadWriteByte(t, p, trans);
p = NewTCompactProtocol(trans);
ReadWriteI16(t, p, trans);
p = NewTCompactProtocol(trans);
ReadWriteI32(t, p, trans);
p = NewTCompactProtocol(trans);
ReadWriteI64(t, p, trans);
p = NewTCompactProtocol(trans);
ReadWriteDouble(t, p, trans);
p = NewTCompactProtocol(trans);
ReadWriteString(t, p, trans);
p = NewTCompactProtocol(trans);
ReadWriteBinary(t, p, trans);
trans.Close();
p := NewTCompactProtocol(trans)
ReadWriteBool(t, p, trans)
p = NewTCompactProtocol(trans)
ReadWriteByte(t, p, trans)
p = NewTCompactProtocol(trans)
ReadWriteI16(t, p, trans)
p = NewTCompactProtocol(trans)
ReadWriteI32(t, p, trans)
p = NewTCompactProtocol(trans)
ReadWriteI64(t, p, trans)
p = NewTCompactProtocol(trans)
ReadWriteDouble(t, p, trans)
p = NewTCompactProtocol(trans)
ReadWriteString(t, p, trans)
p = NewTCompactProtocol(trans)
ReadWriteBinary(t, p, trans)
trans.Close()
}
}
......@@ -51,8 +51,12 @@ func NewTFramedTransportFactoryMaxLength(factory TTransportFactory, maxLength ui
return &tFramedTransportFactory{factory: factory, maxLength: maxLength}
}
func (p *tFramedTransportFactory) GetTransport(base TTransport) TTransport {
return NewTFramedTransportMaxLength(p.factory.GetTransport(base), p.maxLength)
func (p *tFramedTransportFactory) GetTransport(base TTransport) (TTransport, error) {
tt, err := p.factory.GetTransport(base)
if err != nil {
return nil, err
}
return NewTFramedTransportMaxLength(tt, p.maxLength), nil
}
func NewTFramedTransport(transport TTransport) *TFramedTransport {
......@@ -137,11 +141,13 @@ func (p *TFramedTransport) Flush() error {
binary.BigEndian.PutUint32(buf, uint32(size))
_, err := p.transport.Write(buf)
if err != nil {
p.buf.Truncate(0)
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")
p.buf.Truncate(0)
return NewTTransportExceptionFromError(err)
}
}
......@@ -164,4 +170,3 @@ func (p *TFramedTransport) readFrameHeader() (uint32, error) {
func (p *TFramedTransport) RemainingBytes() (num_bytes uint64) {
return uint64(p.frameSize)
}
// +build go1.7
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT 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 "context"
var defaultCtx = context.Background()
......@@ -46,27 +46,16 @@ type THttpClient struct {
type THttpClientTransportFactory struct {
options THttpClientOptions
url string
isPost bool
}
func (p *THttpClientTransportFactory) GetTransport(trans TTransport) TTransport {
func (p *THttpClientTransportFactory) GetTransport(trans TTransport) (TTransport, error) {
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
return NewTHttpClientWithOptions(t.url.String(), p.options)
}
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
return NewTHttpClientWithOptions(p.url, p.options)
}
type THttpClientOptions struct {
......@@ -79,39 +68,10 @@ func NewTHttpClientTransportFactory(url string) *THttpClientTransportFactory {
}
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}
return &THttpClientTransportFactory{url: url, 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
......@@ -121,12 +81,12 @@ func NewTHttpPostClientWithOptions(urlstr string, options THttpClientOptions) (T
if client == nil {
client = DefaultHttpClient
}
httpHeader := map[string][]string{"Content-Type": []string{"application/x-thrift"}}
httpHeader := map[string][]string{"Content-Type": {"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{})
func NewTHttpClient(urlstr string) (TTransport, error) {
return NewTHttpClientWithOptions(urlstr, THttpClientOptions{})
}
// Set the HTTP Header for this specific Thrift Transport
......@@ -256,3 +216,23 @@ func (p *THttpClient) RemainingBytes() (num_bytes uint64) {
const maxSize = ^uint64(0)
return maxSize // the thruth is, we just don't know unless framed is used
}
// Deprecated: Use NewTHttpClientTransportFactory instead.
func NewTHttpPostClientTransportFactory(url string) *THttpClientTransportFactory {
return NewTHttpClientTransportFactoryWithOptions(url, THttpClientOptions{})
}
// Deprecated: Use NewTHttpClientTransportFactoryWithOptions instead.
func NewTHttpPostClientTransportFactoryWithOptions(url string, options THttpClientOptions) *THttpClientTransportFactory {
return NewTHttpClientTransportFactoryWithOptions(url, options)
}
// Deprecated: Use NewTHttpClientWithOptions instead.
func NewTHttpPostClientWithOptions(urlstr string, options THttpClientOptions) (TTransport, error) {
return NewTHttpClientWithOptions(urlstr, options)
}
// Deprecated: Use NewTHttpClient instead.
func NewTHttpPostClient(urlstr string) (TTransport, error) {
return NewTHttpClientWithOptions(urlstr, THttpClientOptions{})
}
......@@ -19,16 +19,33 @@
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) {
import (
"compress/gzip"
"io"
"net/http"
"strings"
)
// gz transparently compresses the HTTP response if the client supports it.
func gz(handler http.HandlerFunc) http.HandlerFunc {
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))
if !strings.Contains(r.Header.Get("Accept-Encoding"), "gzip") {
handler(w, r)
return
}
w.Header().Set("Content-Encoding", "gzip")
gz := gzip.NewWriter(w)
defer gz.Close()
gzw := gzipResponseWriter{Writer: gz, ResponseWriter: w}
handler(gzw, r)
}
}
type gzipResponseWriter struct {
io.Writer
http.ResponseWriter
}
func (w gzipResponseWriter) Write(b []byte) (int, error) {
return w.Writer.Write(b)
}
// +build go1.7
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT 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 gz(func(w http.ResponseWriter, r *http.Request) {
w.Header().Add("Content-Type", "application/x-thrift")
transport := NewStreamTransport(r.Body, w)
processor.Process(r.Context(), inPfactory.GetProtocol(transport), outPfactory.GetProtocol(transport))
})
}
// +build !go1.7
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT 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"
"golang.org/x/net/context"
)
// 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 gz(func(w http.ResponseWriter, r *http.Request) {
w.Header().Add("Content-Type", "application/x-thrift")
transport := NewStreamTransport(r.Body, w)
processor.Process(context.Background(), inPfactory.GetProtocol(transport), outPfactory.GetProtocol(transport))
})
}
......@@ -38,38 +38,38 @@ type StreamTransportFactory struct {
isReadWriter bool
}
func (p *StreamTransportFactory) GetTransport(trans TTransport) TTransport {
func (p *StreamTransportFactory) GetTransport(trans TTransport) (TTransport, error) {
if trans != nil {
t, ok := trans.(*StreamTransport)
if ok {
if t.isReadWriter {
return NewStreamTransportRW(t.Reader.(io.ReadWriter))
return NewStreamTransportRW(t.Reader.(io.ReadWriter)), nil
}
if t.Reader != nil && t.Writer != nil {
return NewStreamTransport(t.Reader, t.Writer)
return NewStreamTransport(t.Reader, t.Writer), nil
}
if t.Reader != nil && t.Writer == nil {
return NewStreamTransportR(t.Reader)
return NewStreamTransportR(t.Reader), nil
}
if t.Reader == nil && t.Writer != nil {
return NewStreamTransportW(t.Writer)
return NewStreamTransportW(t.Writer), nil
}
return &StreamTransport{}
return &StreamTransport{}, nil
}
}
if p.isReadWriter {
return NewStreamTransportRW(p.Reader.(io.ReadWriter))
return NewStreamTransportRW(p.Reader.(io.ReadWriter)), nil
}
if p.Reader != nil && p.Writer != nil {
return NewStreamTransport(p.Reader, p.Writer)
return NewStreamTransport(p.Reader, p.Writer), nil
}
if p.Reader != nil && p.Writer == nil {
return NewStreamTransportR(p.Reader)
return NewStreamTransportR(p.Reader), nil
}
if p.Reader == nil && p.Writer != nil {
return NewStreamTransportW(p.Writer)
return NewStreamTransportW(p.Writer), nil
}
return &StreamTransport{}
return &StreamTransport{}, nil
}
func NewStreamTransportFactory(reader io.Reader, writer io.Writer, isReadWriter bool) *StreamTransportFactory {
......@@ -211,4 +211,3 @@ 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
}
......@@ -33,14 +33,14 @@ type TMemoryBufferTransportFactory struct {
size int
}
func (p *TMemoryBufferTransportFactory) GetTransport(trans TTransport) TTransport {
func (p *TMemoryBufferTransportFactory) GetTransport(trans TTransport) (TTransport, error) {
if trans != nil {
t, ok := trans.(*TMemoryBuffer)
if ok && t.size > 0 {
return NewTMemoryBufferLen(t.size)
return NewTMemoryBufferLen(t.size), nil
}
}
return NewTMemoryBufferLen(p.size)
return NewTMemoryBufferLen(p.size), nil
}
func NewTMemoryBufferTransportFactory(size int) *TMemoryBufferTransportFactory {
......
......@@ -19,11 +19,6 @@
package thrift
import (
"fmt"
"strings"
)
/*
TMultiplexedProtocol is a protocol-independent concrete decorator
that allows a Thrift client to communicate with a multiplexing Thrift server,
......@@ -127,31 +122,6 @@ func (t *TMultiplexedProcessor) RegisterProcessor(name string, processor TProces
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
......
// +build go1.7
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT 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 (
"context"
"fmt"
"strings"
)
func (t *TMultiplexedProcessor) Process(ctx context.Context, 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(ctx, 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(ctx, smb, out)
}
// +build !go1.7
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT 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"
"golang.org/x/net/context"
)
func (t *TMultiplexedProcessor) Process(ctx context.Context, 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(ctx, 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(ctx, smb, out)
}
// +build !go1.7
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT 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 "golang.org/x/net/context"
var defaultCtx = context.Background()
// +build !go1.7
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
......@@ -19,12 +21,14 @@
package thrift
import "golang.org/x/net/context"
// 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)
Process(ctx context.Context, in, out TProtocol) (bool, TException)
}
type TProcessorFunction interface {
Process(seqId int32, in, out TProtocol) (bool, TException)
Process(ctx context.Context, seqId int32, in, out TProtocol) (bool, TException)
}
// +build go1.7
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT 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 "context"
// A processor is a generic object which operates upon an input stream and
// writes to some output stream.
type TProcessor interface {
Process(ctx context.Context, in, out TProtocol) (bool, TException)
}
type TProcessorFunction interface {
Process(ctx context.Context, seqId int32, in, out TProtocol) (bool, TException)
}
......@@ -21,6 +21,7 @@ package thrift
import (
"errors"
"fmt"
)
const (
......@@ -90,7 +91,7 @@ func SkipDefaultDepth(prot TProtocol, typeId TType) (err error) {
func Skip(self TProtocol, fieldType TType, maxDepth int) (err error) {
if maxDepth <= 0 {
return NewTProtocolExceptionWithType( DEPTH_LIMIT, errors.New("Depth limit exceeded"))
return NewTProtocolExceptionWithType(DEPTH_LIMIT, errors.New("Depth limit exceeded"))
}
switch fieldType {
......@@ -170,6 +171,8 @@ func Skip(self TProtocol, fieldType TType, maxDepth int) (err error) {
}
}
return self.ReadListEnd()
default:
return NewTProtocolExceptionWithType(INVALID_DATA, errors.New(fmt.Sprintf("Unknown data type %d", fieldType)))
}
return nil
}
......@@ -60,7 +60,7 @@ func NewTProtocolException(err error) TProtocolException {
if err == nil {
return nil
}
if e,ok := err.(TProtocolException); ok {
if e, ok := err.(TProtocolException); ok {
return e
}
if _, ok := err.(base64.CorruptInputError); ok {
......@@ -75,4 +75,3 @@ func NewTProtocolExceptionWithType(errType int, err error) TProtocolException {
}
return &tProtocolException{errType, err.Error()}
}
......@@ -123,55 +123,91 @@ func ReadWriteProtocolTest(t *testing.T, protocolFactory TProtocolFactory) {
NewTHttpPostClientTransportFactory("http://" + addr.String()),
}
for _, tf := range transports {
trans := tf.GetTransport(nil)
trans, err := tf.GetTransport(nil)
if err != nil {
t.Error(err)
continue
}
p := protocolFactory.GetProtocol(trans)
ReadWriteBool(t, p, trans)
trans.Close()
}
for _, tf := range transports {
trans := tf.GetTransport(nil)
trans, err := tf.GetTransport(nil)
if err != nil {
t.Error(err)
continue
}
p := protocolFactory.GetProtocol(trans)
ReadWriteByte(t, p, trans)
trans.Close()
}
for _, tf := range transports {
trans := tf.GetTransport(nil)
trans, err := tf.GetTransport(nil)
if err != nil {
t.Error(err)
continue
}
p := protocolFactory.GetProtocol(trans)
ReadWriteI16(t, p, trans)
trans.Close()
}
for _, tf := range transports {
trans := tf.GetTransport(nil)
trans, err := tf.GetTransport(nil)
if err != nil {
t.Error(err)
continue
}
p := protocolFactory.GetProtocol(trans)
ReadWriteI32(t, p, trans)
trans.Close()
}
for _, tf := range transports {
trans := tf.GetTransport(nil)
trans, err := tf.GetTransport(nil)
if err != nil {
t.Error(err)
continue
}
p := protocolFactory.GetProtocol(trans)
ReadWriteI64(t, p, trans)
trans.Close()
}
for _, tf := range transports {
trans := tf.GetTransport(nil)
trans, err := tf.GetTransport(nil)
if err != nil {
t.Error(err)
continue
}
p := protocolFactory.GetProtocol(trans)
ReadWriteDouble(t, p, trans)
trans.Close()
}
for _, tf := range transports {
trans := tf.GetTransport(nil)
trans, err := tf.GetTransport(nil)
if err != nil {
t.Error(err)
continue
}
p := protocolFactory.GetProtocol(trans)
ReadWriteString(t, p, trans)
trans.Close()
}
for _, tf := range transports {
trans := tf.GetTransport(nil)
trans, err := tf.GetTransport(nil)
if err != nil {
t.Error(err)
continue
}
p := protocolFactory.GetProtocol(trans)
ReadWriteBinary(t, p, trans)
trans.Close()
}
for _, tf := range transports {
trans := tf.GetTransport(nil)
trans, err := tf.GetTransport(nil)
if err != nil {
t.Error(err)
continue
}
p := protocolFactory.GetProtocol(trans)
ReadWriteI64(t, p, trans)
ReadWriteDouble(t, p, trans)
......
......@@ -66,4 +66,3 @@ func writeByte(w io.Writer, c byte) error {
_, err := w.Write(v[0:1])
return err
}
......@@ -37,7 +37,11 @@ func TestEnsureTransportsAreRich(t *testing.T) {
NewTHttpPostClientTransportFactory("http://127.0.0.1"),
}
for _, tf := range transports {
trans := tf.GetTransport(nil)
trans, err := tf.GetTransport(nil)
if err != nil {
t.Error(err)
continue
}
_, ok := trans.(TRichTransport)
if !ok {
t.Errorf("Transport %s does not implement TRichTransport interface", reflect.ValueOf(trans))
......
......@@ -598,7 +598,7 @@ func (p *MyTestStruct) writeField11(oprot TProtocol) (err error) {
if err := oprot.WriteSetBegin(STRING, len(p.StringSet)); err != nil {
return PrependError("error writing set begin: ", err)
}
for v, _ := range p.StringSet {
for v := range p.StringSet {
if err := oprot.WriteString(string(v)); err != nil {
return PrependError(fmt.Sprintf("%T. (0) field write error: ", p), err)
}
......
......@@ -47,7 +47,14 @@ func NewTServerSocketTimeout(listenAddr string, clientTimeout time.Duration) (*T
return &TServerSocket{addr: addr, clientTimeout: clientTimeout}, nil
}
// Creates a TServerSocket from a net.Addr
func NewTServerSocketFromAddrTimeout(addr net.Addr, clientTimeout time.Duration) *TServerSocket {
return &TServerSocket{addr: addr, clientTimeout: clientTimeout}
}
func (p *TServerSocket) Listen() error {
p.mu.Lock()
defer p.mu.Unlock()
if p.IsListening() {
return nil
}
......@@ -67,10 +74,13 @@ func (p *TServerSocket) Accept() (TTransport, error) {
if interrupted {
return nil, errTransportInterrupted
}
if p.listener == nil {
listener := p.listener
if listener == nil {
return nil, NewTTransportException(NOT_OPEN, "No underlying server socket")
}
conn, err := p.listener.Accept()
conn, err := listener.Accept()
if err != nil {
return nil, NewTTransportExceptionFromError(err)
}
......@@ -84,6 +94,8 @@ func (p *TServerSocket) IsListening() bool {
// Connects the socket, creating a new socket object if necessary.
func (p *TServerSocket) Open() error {
p.mu.Lock()
defer p.mu.Unlock()
if p.IsListening() {
return NewTTransportException(ALREADY_OPEN, "Server socket already open")
}
......@@ -114,9 +126,9 @@ func (p *TServerSocket) Close() error {
func (p *TServerSocket) Interrupt() error {
p.mu.Lock()
defer p.mu.Unlock()
p.interrupted = true
p.Close()
p.mu.Unlock()
return nil
}
......@@ -41,6 +41,16 @@ func TestSocketIsntListeningAfterInterrupt(t *testing.T) {
}
}
func TestSocketConcurrency(t *testing.T) {
host := "127.0.0.1"
port := 9090
addr := fmt.Sprintf("%s:%d", host, port)
socket := CreateServerSocket(t, addr)
go func() { socket.Listen() }()
go func() { socket.Interrupt() }()
}
func CreateServerSocket(t *testing.T, addr string) *TServerSocket {
socket, err := NewTServerSocket(addr)
if err != nil {
......
......@@ -23,11 +23,18 @@ import (
"log"
"runtime/debug"
"sync"
"sync/atomic"
)
// Simple, non-concurrent server for testing.
/*
* This is not a typical TSimpleServer as it is not blocked after accept a socket.
* It is more like a TThreadedServer that can handle different connections in different goroutines.
* This will work if golang user implements a conn-pool like thing in client side.
*/
type TSimpleServer struct {
quit chan struct{}
closed int32
wg sync.WaitGroup
mu sync.Mutex
processorFactory TProcessorFactory
serverTransport TServerTransport
......@@ -87,7 +94,6 @@ func NewTSimpleServerFactory6(processorFactory TProcessorFactory, serverTranspor
outputTransportFactory: outputTransportFactory,
inputProtocolFactory: inputProtocolFactory,
outputProtocolFactory: outputProtocolFactory,
quit: make(chan struct{}, 1),
}
}
......@@ -122,21 +128,23 @@ func (p *TSimpleServer) Listen() error {
func (p *TSimpleServer) AcceptLoop() error {
for {
client, err := p.serverTransport.Accept()
if err != nil {
select {
case <-p.quit:
p.mu.Lock()
if atomic.LoadInt32(&p.closed) != 0 {
return nil
default:
}
if err != nil {
return err
}
if client != nil {
p.wg.Add(1)
go func() {
defer p.wg.Done()
if err := p.processRequests(client); err != nil {
log.Println("error processing request:", err)
}
}()
}
p.mu.Unlock()
}
}
......@@ -149,21 +157,28 @@ func (p *TSimpleServer) Serve() error {
return nil
}
var once sync.Once
func (p *TSimpleServer) Stop() error {
q := func() {
p.quit <- struct{}{}
p.serverTransport.Interrupt()
p.mu.Lock()
defer p.mu.Unlock()
if atomic.LoadInt32(&p.closed) != 0 {
return nil
}
once.Do(q)
atomic.StoreInt32(&p.closed, 1)
p.serverTransport.Interrupt()
p.wg.Wait()
return nil
}
func (p *TSimpleServer) processRequests(client TTransport) error {
processor := p.processorFactory.GetProcessor(client)
inputTransport := p.inputTransportFactory.GetTransport(client)
outputTransport := p.outputTransportFactory.GetTransport(client)
inputTransport, err := p.inputTransportFactory.GetTransport(client)
if err != nil {
return err
}
outputTransport, err := p.outputTransportFactory.GetTransport(client)
if err != nil {
return err
}
inputProtocol := p.inputProtocolFactory.GetProtocol(inputTransport)
outputProtocol := p.outputProtocolFactory.GetProtocol(outputTransport)
defer func() {
......@@ -171,6 +186,7 @@ func (p *TSimpleServer) processRequests(client TTransport) error {
log.Printf("panic in processor: %s: %s", e, debug.Stack())
}
}()
if inputTransport != nil {
defer inputTransport.Close()
}
......@@ -178,11 +194,14 @@ func (p *TSimpleServer) processRequests(client TTransport) error {
defer outputTransport.Close()
}
for {
ok, err := processor.Process(inputProtocol, outputProtocol)
if atomic.LoadInt32(&p.closed) != 0 {
return nil
}
ok, err := processor.Process(defaultCtx, 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 {
......
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT 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 (
"testing"
"time"
)
type mockServerTransport struct {
ListenFunc func() error
AcceptFunc func() (TTransport, error)
CloseFunc func() error
InterruptFunc func() error
}
func (m *mockServerTransport) Listen() error {
return m.ListenFunc()
}
func (m *mockServerTransport) Accept() (TTransport, error) {
return m.AcceptFunc()
}
func (m *mockServerTransport) Close() error {
return m.CloseFunc()
}
func (m *mockServerTransport) Interrupt() error {
return m.InterruptFunc()
}
type mockTTransport struct {
TTransport
}
func (m *mockTTransport) Close() error {
return nil
}
func TestMultipleStop(t *testing.T) {
proc := &mockProcessor{
ProcessFunc: func(in, out TProtocol) (bool, TException) {
return false, nil
},
}
var interruptCalled bool
c := make(chan struct{})
trans := &mockServerTransport{
ListenFunc: func() error {
return nil
},
AcceptFunc: func() (TTransport, error) {
<-c
return nil, nil
},
CloseFunc: func() error {
c <- struct{}{}
return nil
},
InterruptFunc: func() error {
interruptCalled = true
return nil
},
}
serv := NewTSimpleServer2(proc, trans)
go serv.Serve()
serv.Stop()
if !interruptCalled {
t.Error("first server transport should have been interrupted")
}
serv = NewTSimpleServer2(proc, trans)
interruptCalled = false
go serv.Serve()
serv.Stop()
if !interruptCalled {
t.Error("second server transport should have been interrupted")
}
}
func TestWaitRace(t *testing.T) {
proc := &mockProcessor{
ProcessFunc: func(in, out TProtocol) (bool, TException) {
return false, nil
},
}
trans := &mockServerTransport{
ListenFunc: func() error {
return nil
},
AcceptFunc: func() (TTransport, error) {
return &mockTTransport{}, nil
},
CloseFunc: func() error {
return nil
},
InterruptFunc: func() error {
return nil
},
}
serv := NewTSimpleServer2(proc, trans)
go serv.Serve()
time.Sleep(1)
serv.Stop()
}
......@@ -163,4 +163,3 @@ 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
}
......@@ -20,9 +20,9 @@
package thrift
import (
"crypto/tls"
"net"
"time"
"crypto/tls"
)
type TSSLServerSocket struct {
......@@ -38,6 +38,9 @@ func NewTSSLServerSocket(listenAddr string, cfg *tls.Config) (*TSSLServerSocket,
}
func NewTSSLServerSocketTimeout(listenAddr string, cfg *tls.Config, clientTimeout time.Duration) (*TSSLServerSocket, error) {
if cfg.MinVersion == 0 {
cfg.MinVersion = tls.VersionTLS10
}
addr, err := net.ResolveTCPAddr("tcp", listenAddr)
if err != nil {
return nil, err
......
......@@ -48,6 +48,9 @@ func NewTSSLSocket(hostPort string, cfg *tls.Config) (*TSSLSocket, error) {
// 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) {
if cfg.MinVersion == 0 {
cfg.MinVersion = tls.VersionTLS10
}
return &TSSLSocket{hostPort: hostPort, timeout: timeout, cfg: cfg}, nil
}
......@@ -87,7 +90,8 @@ func (p *TSSLSocket) Open() 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 {
if p.conn, err = tls.DialWithDialer(&net.Dialer{
Timeout: p.timeout}, "tcp", p.hostPort, p.cfg); err != nil {
return NewTTransportException(NOT_OPEN, err.Error())
}
} else {
......@@ -103,7 +107,8 @@ func (p *TSSLSocket) Open() error {
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 {
if p.conn, err = tls.DialWithDialer(&net.Dialer{
Timeout: p.timeout}, p.addr.Network(), p.addr.String(), p.cfg); err != nil {
return NewTTransportException(NOT_OPEN, err.Error())
}
}
......@@ -168,4 +173,3 @@ 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
}
......@@ -34,7 +34,6 @@ type ReadSizeProvider interface {
RemainingBytes() (num_bytes uint64)
}
// Encapsulates the I/O layer
type TTransport interface {
io.ReadWriteCloser
......@@ -52,7 +51,6 @@ 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
......@@ -65,4 +63,3 @@ type TRichTransport interface {
Flusher
ReadSizeProvider
}
......@@ -24,14 +24,14 @@ package thrift
// 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
GetTransport(trans TTransport) (TTransport, error)
}
type tTransportFactory struct{}
// Return a wrapped instance of the base Transport.
func (p *tTransportFactory) GetTransport(trans TTransport) TTransport {
return trans
func (p *tTransportFactory) GetTransport(trans TTransport) (TTransport, error) {
return trans, nil
}
func NewTTransportFactory() TTransportFactory {
......
......@@ -28,6 +28,7 @@ import (
// TZlibTransportFactory is a factory for TZlibTransport instances
type TZlibTransportFactory struct {
level int
factory TTransportFactory
}
// TZlibTransport is a TTransport implementation that makes use of zlib compression.
......@@ -38,14 +39,27 @@ type TZlibTransport struct {
}
// GetTransport constructs a new instance of NewTZlibTransport
func (p *TZlibTransportFactory) GetTransport(trans TTransport) TTransport {
t, _ := NewTZlibTransport(trans, p.level)
return t
func (p *TZlibTransportFactory) GetTransport(trans TTransport) (TTransport, error) {
if p.factory != nil {
// wrap other factory
var err error
trans, err = p.factory.GetTransport(trans)
if err != nil {
return nil, err
}
}
return NewTZlibTransport(trans, p.level)
}
// NewTZlibTransportFactory constructs a new instance of NewTZlibTransportFactory
func NewTZlibTransportFactory(level int) *TZlibTransportFactory {
return &TZlibTransportFactory{level: level}
return &TZlibTransportFactory{level: level, factory: nil}
}
// NewTZlibTransportFactory constructs a new instance of TZlibTransportFactory
// as a wrapper over existing transport factory
func NewTZlibTransportFactoryWithFactory(level int, factory TTransportFactory) *TZlibTransportFactory {
return &TZlibTransportFactory{level: level, factory: factory}
}
// NewTZlibTransport constructs a new instance of TZlibTransport
......
......@@ -31,3 +31,32 @@ func TestZlibTransport(t *testing.T) {
}
TransportTest(t, trans, trans)
}
type DummyTransportFactory struct{}
func (p *DummyTransportFactory) GetTransport(trans TTransport) (TTransport, error) {
return NewTMemoryBuffer(), nil
}
func TestZlibFactoryTransportWithFactory(t *testing.T) {
factory := NewTZlibTransportFactoryWithFactory(
zlib.BestCompression,
&DummyTransportFactory{},
)
buffer := NewTMemoryBuffer()
trans, err := factory.GetTransport(buffer)
if err != nil {
t.Fatal(err)
}
TransportTest(t, trans, trans)
}
func TestZlibFactoryTransportWithoutFactory(t *testing.T) {
factory := NewTZlibTransportFactoryWithFactory(zlib.BestCompression, nil)
buffer := NewTMemoryBuffer()
trans, err := factory.GetTransport(buffer)
if err != nil {
t.Fatal(err)
}
TransportTest(t, trans, trans)
}
......@@ -6,7 +6,7 @@
"type": "git",
"url": "https://git-wip-us.apache.org/repos/asf/thrift.git"
},
"version": "0.10.0",
"version": "1.0.0-dev",
"author": {
"name": "Apache Thrift Developers",
"email": "dev@thrift.apache.org",
......@@ -32,20 +32,24 @@
},
"main": "./lib/nodejs/lib/thrift",
"engines": {
"node": ">= 0.2.4"
"node": ">= 4.1.0"
},
"dependencies": {
"node-int64": "~0.3.0",
"q": "1.0.x",
"ws": "~0.4.32"
"node-int64": "^0.4.0",
"q": "^1.5.0",
"ws": ">= 2.2.3"
},
"devDependencies": {
"buffer-equals": "^1.0.3",
"commander": "2.1.x",
"connect": "2.7.x",
"istanbul": "^0.3.5",
"run-browser": "^2.0.1",
"tape": "~3.5.0"
"buffer-equals": "^1.0.4",
"commander": "^2.11.0",
"connect": "^3.6.4",
"istanbul": "^0.4.5",
"jsdoc": ">=3.5.5",
"minimatch": "^3.0.4",
"phantomjs-prebuilt": "^2.1.7",
"run-browser": "^2.0.2",
"tape": "^4.8.0",
"utf-8-validate": "^3.0.0"
},
"scripts": {
"cover": "lib/nodejs/test/testAll.sh COVER",
......
......@@ -16,7 +16,7 @@ development, combines a software stack with a code generation engine to build
services that work efficiently and seamlessly between all major languages.
# Apache Thrift Version
sonar.projectVersion=0.10.0
sonar.projectVersion=1.0.0-dev
# use this to set another version string
# $ sonar-runner -D sonar.projectVersion=`git rev-parse HEAD`
# set projectDate in combination with projectVersion for imports of old releases
......@@ -54,7 +54,7 @@ module1.sonar.projectName=Apache Thrift - Java Library
module1.sonar.projectBaseDir=lib/java
module1.sonar.sources=src
module1.sonar.tests=test
module1.sonar.binaries=build/libthrift-0.10.0.jar
module1.sonar.binaries=build/libthrift-1.0.0.jar
module1.sonar.libraries=build/lib/*.jar
module1.sonar.language=java
......
......@@ -28,6 +28,7 @@ type SimpleSchema struct {
Items *Items `json:"items,omitempty"`
CollectionFormat string `json:"collectionFormat,omitempty"`
Default interface{} `json:"default,omitempty"`
Example interface{} `json:"example,omitempty"`
}
func (s *SimpleSchema) TypeName() string {
......
# Binaries for programs and plugins
*.exe
*.dll
*.so
*.dylib
# Test binary, build with `go test -c`
*.test
# Output of the go coverage tool, specifically when used with LiteIDE
*.out
# Project-local glide cache, RE: https://github.com/Masterminds/glide/issues/736
.glide/
This diff is collapsed.
# An Observer API for OpenTracing-go Tracers
OTObserver can be used to watch the span events like StartSpan(),
SetOperationName(), SetTag() and Finish(). A need for observers
arose when information (metrics) more than just the latency information was
required for the spans, in the distributed tracers. But, there can be a lot
of metrics in different domains and adding such metrics to any one (client)
tracer breaks cross-platform compatibility. There are various ways to
avoid such issues, however, an observer pattern is cleaner and provides loose
coupling between the packages exporting metrics (on span events) and the
tracer.
This information can be in the form of hardware metrics, RPC metrics,
useful metrics exported out of the kernel or other metrics, profiled for a
span. These additional metrics can help us in getting better Root-cause
analysis. With that being said, its not just for calculation of metrics,
it can be used for anything which needs watching the span events.
## Installation and Usage
The `otobserver` package provides an API to watch span's events and define
callbacks for these events. This API would be a functional option to a
tracer constructor that passes an Observer. 3rd party packages (who want to
watch the span events) should actually implement this observer API.
To do that, first fetch the package using go get :
```
go get -v github.com/opentracing-contrib/go-observer
```
and say :
```go
import "github.com/opentracing-contrib/go-observer"
```
and then, define the required span event callbacks. These registered
callbacks would then be called on span events if an observer is created.
Tracer may allow registering multiple observers. Have a look at the [jaeger's observer](https://github.com/uber/jaeger-client-go/blob/master/observer.go).
With the required setup implemented in the backend tracers, packages
watching the span events need to implement the observer api defining what
they need to do for the observed span events.
## Span events
An observer registered with this api, can observe for the following four
span events :
```go
StartSpan()
SetOperationName()
SetTag()
Finish()
```
### Tradeoffs
As noble as our thoughts might be in fetching additional metrics (other than
latency) for a span using an observer, there are some overhead costs. Not all
observers need to observe all the span events, in which case, we may have
to keep some callback functions empty. In effect, we will still call these
functions, and that will incur unnecessary overhead. To know more about this
and other tradeoffs, see this [discussion](https://github.com/opentracing/opentracing-go/pull/135#discussion_r105497329).
// This project is licensed under the Apache License 2.0, see LICENSE.
package otobserver
import opentracing "github.com/opentracing/opentracing-go"
// Observer can be registered with a Tracer to recieve notifications
// about new Spans. Tracers are not required to support the Observer API.
// The actual registration depends on the implementation, which might look
// like the below e.g :
// observer := myobserver.NewObserver()
// tracer := client.NewTracer(..., client.WithObserver(observer))
//
type Observer 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{}
// spanObserver, ok := observer.OnStartSpan(span, opName, sso);
// if ok {
// // we have a valid SpanObserver
// }
// ...
// }
OnStartSpan(sp opentracing.Span, operationName string, options opentracing.StartSpanOptions) (SpanObserver, bool)
}
// SpanObserver is created by the Observer and receives notifications about
// other Span events.
type SpanObserver interface {
// Callback called from opentracing.Span.SetOperationName()
OnSetOperationName(operationName string)
// Callback called from opentracing.Span.SetTag()
OnSetTag(key string, value interface{})
// Callback called from opentracing.Span.Finish()
OnFinish(options opentracing.FinishOptions)
}
language: go
go:
- 1.7
- 1.8
- 1.9
- tip
install:
......
......@@ -12,12 +12,15 @@ bench:
.PHONY: lint
lint:
# Ignore grep's exit code since no match returns 1.
-golint ./... | grep --invert-match -E '^.*\.pb\.go'
-golint ./... | grep --invert-match -E '^.*\.pb\.go|^thrift'
@
@! (golint ./... |grep --invert-match -E '^.*\.pb\.go' | read dummy)
@! (golint ./... | grep --invert-match -E '^.*\.pb\.go|^thrift' | read dummy)
.PHONY: vet
vet:
go vet ./...
.PHONY: all
all: vet lint test bench
.PHONY: example
// Autogenerated by Thrift Compiler (0.9.3)
// DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
package scribe
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 ResultCode int64
const (
ResultCode_OK ResultCode = 0
ResultCode_TRY_LATER ResultCode = 1
)
func (p ResultCode) String() string {
switch p {
case ResultCode_OK:
return "OK"
case ResultCode_TRY_LATER:
return "TRY_LATER"
}
return "<UNSET>"
}
func ResultCodeFromString(s string) (ResultCode, error) {
switch s {
case "OK":
return ResultCode_OK, nil
case "TRY_LATER":
return ResultCode_TRY_LATER, nil
}
return ResultCode(0), fmt.Errorf("not a valid ResultCode string")
}
func ResultCodePtr(v ResultCode) *ResultCode { return &v }
func (p ResultCode) MarshalText() ([]byte, error) {
return []byte(p.String()), nil
}
func (p *ResultCode) UnmarshalText(text []byte) error {
q, err := ResultCodeFromString(string(text))
if err != nil {
return err
}
*p = q
return nil
}
// Attributes:
// - Category
// - Message
type LogEntry struct {
Category string `thrift:"category,1" json:"category"`
Message string `thrift:"message,2" json:"message"`
}
func NewLogEntry() *LogEntry {
return &LogEntry{}
}
func (p *LogEntry) GetCategory() string {
return p.Category
}
func (p *LogEntry) GetMessage() string {
return p.Message
}
func (p *LogEntry) 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
}
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 *LogEntry) readField1(iprot thrift.TProtocol) error {
if v, err := iprot.ReadString(); err != nil {
return thrift.PrependError("error reading field 1: ", err)
} else {
p.Category = v
}
return nil
}
func (p *LogEntry) readField2(iprot thrift.TProtocol) error {
if v, err := iprot.ReadString(); err != nil {
return thrift.PrependError("error reading field 2: ", err)
} else {
p.Message = v
}
return nil
}
func (p *LogEntry) Write(oprot thrift.TProtocol) error {
if err := oprot.WriteStructBegin("LogEntry"); 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 *LogEntry) writeField1(oprot thrift.TProtocol) (err error) {
if err := oprot.WriteFieldBegin("category", thrift.STRING, 1); err != nil {
return thrift.PrependError(fmt.Sprintf("%T write field begin error 1:category: ", p), err)
}
if err := oprot.WriteString(string(p.Category)); err != nil {
return thrift.PrependError(fmt.Sprintf("%T.category (1) field write error: ", p), err)
}
if err := oprot.WriteFieldEnd(); err != nil {
return thrift.PrependError(fmt.Sprintf("%T write field end error 1:category: ", p), err)
}
return err
}
func (p *LogEntry) writeField2(oprot thrift.TProtocol) (err error) {
if err := oprot.WriteFieldBegin("message", thrift.STRING, 2); err != nil {
return thrift.PrependError(fmt.Sprintf("%T write field begin error 2:message: ", p), err)
}
if err := oprot.WriteString(string(p.Message)); err != nil {
return thrift.PrependError(fmt.Sprintf("%T.message (2) field write error: ", p), err)
}
if err := oprot.WriteFieldEnd(); err != nil {
return thrift.PrependError(fmt.Sprintf("%T write field end error 2:message: ", p), err)
}
return err
}
func (p *LogEntry) String() string {
if p == nil {
return "<nil>"
}
return fmt.Sprintf("LogEntry(%+v)", *p)
}
dependencies:
override:
- sudo rm -rf /home/ubuntu/.go_workspace/src/github.com/openzipkin
- mkdir -p /home/ubuntu/.go_workspace/src/github.com/openzipkin
- mv /home/ubuntu/zipkin-go-opentracing /home/ubuntu/.go_workspace/src/github.com/openzipkin
- ln -s /home/ubuntu/.go_workspace/src/github.com/openzipkin/zipkin-go-opentracing /home/ubuntu/zipkin-go-opentracing
- go get -u -t -v github.com/openzipkin/zipkin-go-opentracing/...
test:
override:
- make test bench
......@@ -8,7 +8,7 @@ import (
"github.com/apache/thrift/lib/go/thrift"
"github.com/openzipkin/zipkin-go-opentracing/_thrift/gen-go/zipkincore"
"github.com/openzipkin/zipkin-go-opentracing/thrift/gen-go/zipkincore"
)
// Default timeout for http request in seconds
......@@ -180,7 +180,7 @@ func (c *HTTPCollector) append(span *zipkincore.Span) (newBatchSize int) {
c.batch = append(c.batch, span)
if len(c.batch) > c.maxBacklog {
dispose := len(c.batch) - c.maxBacklog
c.logger.Log("Backlog too long, disposing spans.", "count", dispose)
c.logger.Log("msg", "backlog too long, disposing spans.", "count", dispose)
c.batch = c.batch[dispose:]
}
newBatchSize = len(c.batch)
......@@ -214,10 +214,16 @@ func (c *HTTPCollector) send() error {
if c.reqCallback != nil {
c.reqCallback(req)
}
if _, err = c.client.Do(req); err != nil {
resp, err := c.client.Do(req)
if err != nil {
c.logger.Log("err", err.Error())
return err
}
resp.Body.Close()
// non 2xx code
if resp.StatusCode < 200 || resp.StatusCode >= 300 {
c.logger.Log("err", "HTTP POST span failed", "code", resp.Status)
}
// Remove sent spans from the batch
c.batchMutex.Lock()
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment