Showing preview only (2,123K chars total). Download the full file or copy to clipboard to get everything.
Repository: uber/tchannel-go
Branch: dev
Commit: 8f6af1a4cf92
Files: 401
Total size: 2.0 MB
Directory structure:
gitextract_ixnw_gpx/
├── .github/
│ └── workflows/
│ └── tests.yaml
├── .gitignore
├── CHANGELOG.md
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── LICENSE.md
├── Makefile
├── README.md
├── RELEASE.md
├── all_channels.go
├── all_channels_test.go
├── arguments.go
├── arguments_test.go
├── benchmark/
│ ├── benchclient/
│ │ └── main.go
│ ├── benchserver/
│ │ └── main.go
│ ├── build_manager.go
│ ├── client_server_bench_test.go
│ ├── external_client.go
│ ├── external_common.go
│ ├── external_server.go
│ ├── frame_templates.go
│ ├── interfaces.go
│ ├── internal_client.go
│ ├── internal_multi_client.go
│ ├── internal_server.go
│ ├── internal_tcp_client.go
│ ├── internal_tcp_server.go
│ ├── matrix_test.go
│ ├── options.go
│ ├── real_relay.go
│ ├── req_bytes.go
│ ├── tcp_bench_test.go
│ ├── tcp_frame_relay.go
│ └── tcp_raw_relay.go
├── calloptions.go
├── calloptions_test.go
├── channel.go
├── channel_test.go
├── channel_utils_test.go
├── channelstate_string.go
├── checked_frame_pool.go
├── checked_frame_pool_test.go
├── checksum.go
├── close_test.go
├── codecov.yml
├── conn_leak_test.go
├── connection.go
├── connection_bench_test.go
├── connection_direction.go
├── connection_internal_test.go
├── connection_test.go
├── connectionstate_string.go
├── context.go
├── context_builder.go
├── context_header.go
├── context_internal_test.go
├── context_test.go
├── deps_test.go
├── dial_16.go
├── dial_17.go
├── dial_17_test.go
├── doc.go
├── errors.go
├── errors_test.go
├── examples/
│ ├── bench/
│ │ ├── client/
│ │ │ └── client.go
│ │ ├── runner.go
│ │ └── server/
│ │ └── server.go
│ ├── hyperbahn/
│ │ └── echo-server/
│ │ └── main.go
│ ├── hypercat/
│ │ └── main.go
│ ├── keyvalue/
│ │ ├── README.md
│ │ ├── client/
│ │ │ └── client.go
│ │ ├── gen-go/
│ │ │ └── keyvalue/
│ │ │ ├── admin.go
│ │ │ ├── baseservice.go
│ │ │ ├── constants.go
│ │ │ ├── keyvalue.go
│ │ │ ├── tchan-keyvalue.go
│ │ │ └── ttypes.go
│ │ ├── keyvalue.thrift
│ │ └── server/
│ │ └── server.go
│ ├── ping/
│ │ ├── README.md
│ │ └── main.go
│ ├── test_server/
│ │ └── server.go
│ └── thrift/
│ ├── example.thrift
│ ├── gen-go/
│ │ └── example/
│ │ ├── base.go
│ │ ├── constants.go
│ │ ├── first.go
│ │ ├── second.go
│ │ ├── tchan-example.go
│ │ └── ttypes.go
│ └── main.go
├── fragmentation_test.go
├── fragmenting_reader.go
├── fragmenting_writer.go
├── frame.go
├── frame_pool.go
├── frame_pool_b_test.go
├── frame_pool_test.go
├── frame_test.go
├── frame_utils_test.go
├── go.mod
├── go.sum
├── guide/
│ └── Thrift_Hyperbahn.md
├── handlers.go
├── handlers_test.go
├── handlers_with_skip_test.go
├── health.go
├── health_ext_test.go
├── health_test.go
├── http/
│ ├── buf.go
│ ├── buf_test.go
│ ├── http_test.go
│ ├── request.go
│ └── response.go
├── hyperbahn/
│ ├── advertise.go
│ ├── advertise_test.go
│ ├── call.go
│ ├── client.go
│ ├── client_test.go
│ ├── configuration.go
│ ├── discover.go
│ ├── discover_test.go
│ ├── event_string.go
│ ├── events.go
│ ├── gen-go/
│ │ └── hyperbahn/
│ │ ├── constants.go
│ │ ├── hyperbahn.go
│ │ ├── tchan-hyperbahn.go
│ │ └── ttypes.go
│ ├── hyperbahn.thrift
│ ├── utils.go
│ └── utils_test.go
├── idle_sweep.go
├── idle_sweep_test.go
├── inbound.go
├── inbound_internal_test.go
├── inbound_test.go
├── incoming_test.go
├── init_test.go
├── internal/
│ ├── argreader/
│ │ ├── empty.go
│ │ └── empty_test.go
│ └── testcert/
│ └── testcert.go
├── introspection.go
├── introspection_test.go
├── json/
│ ├── call.go
│ ├── context.go
│ ├── handler.go
│ ├── json_test.go
│ ├── retry_test.go
│ └── tracing_test.go
├── largereq_test.go
├── localip.go
├── localip_test.go
├── logger.go
├── logger_test.go
├── messages.go
├── messages_test.go
├── messagetype_string.go
├── mex.go
├── mex_utils_test.go
├── outbound.go
├── peer.go
├── peer_bench_test.go
├── peer_heap.go
├── peer_heap_test.go
├── peer_internal_test.go
├── peer_strategies.go
├── peer_test.go
├── peers/
│ ├── doc.go
│ ├── prefer.go
│ └── prefer_test.go
├── pprof/
│ ├── pprof.go
│ └── pprof_test.go
├── preinit_connection.go
├── raw/
│ ├── call.go
│ └── handler.go
├── relay/
│ ├── relay.go
│ └── relaytest/
│ ├── func_host.go
│ ├── mock_stats.go
│ └── stub_host.go
├── relay.go
├── relay_api.go
├── relay_benchmark_test.go
├── relay_fragment_sender_test.go
├── relay_internal_test.go
├── relay_messages.go
├── relay_messages_benchmark_test.go
├── relay_messages_test.go
├── relay_test.go
├── relay_timer_pool.go
├── reqres.go
├── reqresreaderstate_string.go
├── reqreswriterstate_string.go
├── retry.go
├── retry_request_test.go
├── retry_test.go
├── retryon_string.go
├── root_peer_list.go
├── scripts/
│ ├── install-thrift.sh
│ └── vbumper/
│ └── main.go
├── sockio_bsd.go
├── sockio_darwin.go
├── sockio_linux.go
├── sockio_non_unix.go
├── sockio_unix.go
├── stats/
│ ├── metrickey.go
│ ├── metrickey_test.go
│ ├── statsdreporter.go
│ ├── tally.go
│ └── tally_test.go
├── stats.go
├── stats_test.go
├── stats_utils_test.go
├── stream_test.go
├── stress_flag_test.go
├── subchannel.go
├── subchannel_test.go
├── systemerrcode_string.go
├── tchannel_test.go
├── testutils/
│ ├── call.go
│ ├── channel.go
│ ├── channel_opts.go
│ ├── channel_t.go
│ ├── conn.go
│ ├── counter.go
│ ├── counter_test.go
│ ├── data.go
│ ├── echo.go
│ ├── goroutines/
│ │ ├── stacks.go
│ │ ├── verify.go
│ │ └── verify_opts.go
│ ├── lists.go
│ ├── logfilter_test.go
│ ├── logger.go
│ ├── mockhyperbahn/
│ │ ├── hyperbahn.go
│ │ ├── hyperbahn_test.go
│ │ └── utils.go
│ ├── now.go
│ ├── random_bench_test.go
│ ├── relay.go
│ ├── sleep.go
│ ├── test_server.go
│ ├── testreader/
│ │ ├── chunk.go
│ │ ├── chunk_test.go
│ │ ├── loop.go
│ │ └── loop_test.go
│ ├── testtracing/
│ │ ├── propagation.go
│ │ └── propagation_test.go
│ ├── testwriter/
│ │ ├── limited.go
│ │ └── limited_test.go
│ ├── thriftarg2test/
│ │ ├── arg2_kv.go
│ │ └── arg2_kv_test.go
│ ├── ticker.go
│ ├── ticker_test.go
│ ├── timeout.go
│ └── wait.go
├── thirdparty/
│ └── github.com/
│ └── apache/
│ └── thrift/
│ └── lib/
│ └── go/
│ └── thrift/
│ ├── application_exception.go
│ ├── application_exception_test.go
│ ├── binary_protocol.go
│ ├── binary_protocol_test.go
│ ├── buffered_transport.go
│ ├── buffered_transport_test.go
│ ├── compact_protocol.go
│ ├── compact_protocol_test.go
│ ├── debug_protocol.go
│ ├── deserializer.go
│ ├── exception.go
│ ├── exception_test.go
│ ├── field.go
│ ├── framed_transport.go
│ ├── framed_transport_test.go
│ ├── http_client.go
│ ├── http_client_test.go
│ ├── http_transport.go
│ ├── iostream_transport.go
│ ├── iostream_transport_test.go
│ ├── json_protocol.go
│ ├── json_protocol_test.go
│ ├── lowlevel_benchmarks_test.go
│ ├── memory_buffer.go
│ ├── memory_buffer_test.go
│ ├── messagetype.go
│ ├── multiplexed_protocol.go
│ ├── numeric.go
│ ├── pointerize.go
│ ├── processor.go
│ ├── processor_factory.go
│ ├── protocol.go
│ ├── protocol_exception.go
│ ├── protocol_factory.go
│ ├── protocol_test.go
│ ├── rich_transport.go
│ ├── rich_transport_test.go
│ ├── serializer.go
│ ├── serializer_test.go
│ ├── serializer_types_test.go
│ ├── server.go
│ ├── server_socket.go
│ ├── server_socket_test.go
│ ├── server_test.go
│ ├── server_transport.go
│ ├── simple_json_protocol.go
│ ├── simple_json_protocol_test.go
│ ├── simple_server.go
│ ├── socket.go
│ ├── ssl_server_socket.go
│ ├── ssl_socket.go
│ ├── transport.go
│ ├── transport_exception.go
│ ├── transport_exception_test.go
│ ├── transport_factory.go
│ ├── transport_test.go
│ ├── type.go
│ ├── zlib_transport.go
│ └── zlib_transport_test.go
├── thrift/
│ ├── arg2/
│ │ ├── kv_iterator.go
│ │ └── kv_iterator_test.go
│ ├── client.go
│ ├── context.go
│ ├── context_test.go
│ ├── doc.go
│ ├── errors_test.go
│ ├── gen-go/
│ │ ├── meta/
│ │ │ ├── constants.go
│ │ │ ├── meta.go
│ │ │ └── ttypes.go
│ │ └── test/
│ │ ├── constants.go
│ │ ├── meta.go
│ │ ├── secondservice.go
│ │ ├── simpleservice.go
│ │ ├── tchan-test.go
│ │ └── ttypes.go
│ ├── headers.go
│ ├── headers_test.go
│ ├── interfaces.go
│ ├── meta.go
│ ├── meta.thrift
│ ├── meta_test.go
│ ├── mocks/
│ │ ├── TChanMeta.go
│ │ ├── TChanSecondService.go
│ │ └── TChanSimpleService.go
│ ├── options.go
│ ├── server.go
│ ├── server_test.go
│ ├── struct.go
│ ├── struct_test.go
│ ├── tchan-meta.go
│ ├── test.thrift
│ ├── thrift-gen/
│ │ ├── compile_test.go
│ │ ├── extends.go
│ │ ├── generate.go
│ │ ├── gopath.go
│ │ ├── gopath_test.go
│ │ ├── include.go
│ │ ├── main.go
│ │ ├── names.go
│ │ ├── tchannel-template.go
│ │ ├── template.go
│ │ ├── test_files/
│ │ │ ├── binary.thrift
│ │ │ ├── byte.thrift
│ │ │ ├── gokeywords.thrift
│ │ │ ├── include_test/
│ │ │ │ ├── namespace/
│ │ │ │ │ ├── a/
│ │ │ │ │ │ └── shared.thrift
│ │ │ │ │ ├── b/
│ │ │ │ │ │ └── shared.thrift
│ │ │ │ │ └── namespace.thrift
│ │ │ │ ├── simple/
│ │ │ │ │ ├── shared.thrift
│ │ │ │ │ ├── shared2.thrift
│ │ │ │ │ └── simple.thrift
│ │ │ │ └── svc_extend/
│ │ │ │ ├── shared.thrift
│ │ │ │ └── svc_extend.thrift
│ │ │ ├── multi_test/
│ │ │ │ ├── file1.thrift
│ │ │ │ └── file2.thrift
│ │ │ ├── service_extend.thrift
│ │ │ ├── sets.thrift
│ │ │ ├── test1.thrift
│ │ │ ├── typedefs.thrift
│ │ │ └── union.thrift
│ │ ├── typestate.go
│ │ ├── validate.go
│ │ └── wrap.go
│ ├── thrift_bench_test.go
│ ├── thrift_test.go
│ ├── tracing_test.go
│ ├── transport.go
│ └── transport_test.go
├── tnet/
│ ├── listener.go
│ └── listener_test.go
├── tos/
│ ├── tos.go
│ ├── tos_string.go
│ └── tos_test.go
├── trace/
│ └── doc.go
├── tracing.go
├── tracing_internal_test.go
├── tracing_keys.go
├── tracing_test.go
├── trand/
│ └── rand.go
├── typed/
│ ├── buffer.go
│ ├── buffer_test.go
│ ├── reader.go
│ ├── reader_test.go
│ ├── writer.go
│ └── writer_test.go
├── utils_for_test.go
├── verify_utils_test.go
└── version.go
================================================
FILE CONTENTS
================================================
================================================
FILE: .github/workflows/tests.yaml
================================================
name: Tests
on:
push:
branches: ['*']
tags: ['v*']
pull_request:
branches: ['**']
jobs:
test:
runs-on: ubuntu-latest
env:
GOPATH: ${{ github.workspace }}
GOBIN: ${{ github.workspace }}/bin
defaults:
run:
working-directory: ${{ env.GOPATH }}/src/github.com/${{ github.repository }}
strategy:
matrix:
go: ["stable", "oldstable"]
include:
- go: "stable"
latest: true
COVERAGE: "yes"
LINT: "yes"
- go: "oldstable"
LINT: "yes"
steps:
- name: Setup Go
uses: actions/setup-go@v5
with:
go-version: ${{ matrix.go }}
- name: Checkout code
uses: actions/checkout@v2
with:
path: ${{ env.GOPATH }}/src/github.com/${{ github.repository }}
- name: Load cache
uses: actions/cache@v1
with:
path: ~/.glide/cache
key: ${{ runner.os }}-go-${{ hashFiles('**/glide.lock') }}
restore-keys: |
${{ runner.os }}-go-
- name: Install CI
run: make install_ci
- name: Test CI
env:
NO_TEST: ${{ matrix.NO_TEST }}
run: test -n "$NO_TEST" || make test_ci
- name: Cover CI
env:
COVERAGE: ${{ matrix.COVERAGE }}
run: test -z "$COVERAGE" || make cover_ci
- name: Lint CI
env:
LINT: ${{ matrix.LINT }}
run: test -z "$LINT" || make install_lint lint
- name: Crossdock CI
run: make crossdock_logs_ci
================================================
FILE: .gitignore
================================================
build
Godeps/_workspace
vendor/
thrift-gen-release/
# Lint output
lint.log
# Cover profiles
*.out
# Editor and OS detritus
*~
*.swp
.DS_Store
.idea
tchannel-go.iml
.vscode
.bin/
.idea/
================================================
FILE: CHANGELOG.md
================================================
Changelog
=========
## [1.34.6] - 2025-01-07
### Fixed
* Fix compile issue on FreeBSD 14 (#925)
## [1.34.5] - 2024-10-07
### Changed
* Add component tag to tracing spans (#923)
## [1.34.4] - 2024-06-26
### Fixed
* fix getSysConn to work with TLS (#918)
### Changed
* Switch to aliases for Go versions in CI (#919)
## [1.34.3] - 2024-04-23
### Fixed
* Fix a DoS vulnerability of the vendored apache-thrift library (#915, #916)
## [1.34.2] - 2024-02-16
### Added
* Expose `inbound.cancels.{requested,honored}` metrics (#912)
## [1.34.1] - 2023-12-11
### Fixed
* Fix unknown error type in span tag rpc.tchannel.system_error_code (#907)
## [1.34.0] - 2023-10-17
### Added
* Emit the error code and type to the tracing span for inbound calls (#903)
### Changed
* Update go.mod and github test to go 1.21 (#899)
## [1.33.0] - 2023-03-20
### Added
* Optionally send cancelled frames when context is canceled (#890)
### Changed
* Update dependencies as per recommendations (#894)
* Test against Go 1.19 and 1.20 (#892)
## [1.32.1] - 2022-08-23
### Fixed
* Release unsent frames when flushing fragments (#887)
## [1.32.0] - 2022-07-12
### Changed
* Add TLS option in testutils.NewServerChannel (#882)
## [1.31.0] - 2022-05-04
### Changed
* thrift-gen going to use vendored apache-thrift code. Currently vendored apache-thrift pinned to b2a4d4ae21c789b689dd162deb819665567f481c.
## [1.22.3] - 2022-03-28
### Changed
* Fix memory leak due to unreturned frames in the relayer.
* Test against Go 1.17 and 1.18 in CI.
* Migrate to go mod.
## [1.22.2] - 2021-11-10
### Changed
* Fixes related to `SkipHandlerMethods` request handling.
## [1.22.1] - 2021-10-25
### Changed
* Fixes related to `SkipHandlerMethods` request handling.
## [1.22.0] - 2021-08-13
### Added
* Add `SkipHandlerMethods` option as an allow-list of metohds that are handled by the override handler.
### Changed
* Allow method registration if handler implements Register.
* Internal changes related to relaying.
## [1.21.2] - 2021-05-19
### Changed
* Internal changes related to relaying.
## [1.21.1] - 2021-03-17
### Changed
* Change log level for connection create/close from info level to debug level to reduce noisy logs.
## [1.21.0] - 2020-12-13
### Changed
* Internal changes related to relaying.
## [1.20.1] - 2020-09-24
### Fixed
* Set ConnContext in the channel instead of the connection to avoid serialization
errors since ConnectionOptions is sometimes embedded in configurations (#806)
## [1.20.0] - 2020-09-23
### Added
* Support per-connection base context propagation for inbound/outbound connections (#801)
### Changed
* Internal API changes related to relaying.
## [1.19.1] - 2020-08-03
### Fixed
* Move OS-specific logic into OS-specific files to avoid compile issues on
non-Unix platforms.
## [1.19.0] - 2020-05-21
### Fixed
* Internal API changes related to relaying.
## [1.18.0] - 2020-03-30
### Added
* Introspection now tracks last activity for reads and writes separately (#770)
* Add options to allow overriding SendBufferSize per process name prefix (#772)
## [1.17.0] - 2020-02-18
### Added
* Internal API changes related to relaying.
## [1.16.0] - 2019-10-14
### Added
* Support custom Dialer for outbound connections (#759)
### Fixed
* thrift: Handle TStruct serialization failures gracefully (#744)
## [1.15.0] - 2019-08-26
### Added
* introspection: Introspect any channel by ID. (#756)
### Fixed
* Ensure Introspection endpoints are always available. (#755)
* Fix testutils.WithTestServer incorrectly using RelayHost when creating the server. (#750)
## [1.14.0] - 2019-05-20
### Added
* Expose `CallOptions` caller name for transparent proxying (#741)
## [1.13.0] - 2019-04-04
### Added
* Add `MaxCloseTime` which sets a timeout for graceful connection close. (#724)
### Changed
* Optimize Thrift string field serialization by eliminating `[]byte(string)` allocation. (#729)
### Fixed
* Return an error if transport header keys/values exceed the maximum allowed string length. (#728)
## [1.12.0] - 2018-11-13
### Added
* Add a channel, `ClosedCh`, to wait for a channel to close. (#718)
* Add a Code of Conduct. (#711)
### Changed
* Tweak error message when sending a large error to mention that we're out of space. (#716)
* Idle sweeper now skips connections that have pending calls. (#712)
## [1.11.0] - 2018-06-25
### Added
* thrift: Support health check type in Health endpoint. (#696)
## [1.10.0] - 2018-04-02
### Added
* Support blackholing requests to trigger client timeout without holding
on to resources. (#681)
* introspection: Include channel state in output. (#692)
* introspection: Add inactive connections to output. (#686)
### Fixed
* Inherit deadlines from parent context if available, and timeout is
unspecified.
* Ensure outbound tracing headers take precedence over application
headers. (#683)
## [1.9.0] - 2018-01-31
### Added
* stats: Add tally reporter to emit tagged metrics. (#676)
* Add optional idle timeout, after which connections will be
closed. (#681)
## [1.8.1] - 2017-11-21
### Fixed
* Always log addresses as strings. (#669)
## [1.8.0] - 2017-11-06
### Added
* Add opt-in active connection health checks. (#318)
### Changed
* Improve error logging on `thrift.Server` errors. (#663)
* Reduce memory usage for idle connections. (#658)
* Unpin and reduce dependencies in `glide.yaml` by using `testImports`. (#649)
### Fixed
* Don't close connections on ping errors.(#655)
* Avoid holding on to closed connections' memory in peers. (#644)
## [1.7.0] - 2017-08-04
### Added
* Add `WithoutHeaders` to remove TChannel keys from a context.
### Changed
* Cancel the context on incoming calls if the client connection is closed.
## [1.6.0] - 2017-06-02
### Added
* Add `OnPeerStatusChanged` channel option to receive a notification each time
the number of available connections changes for any given peer.
### Changed
* Locks Apache Thrift to version 0.9.3, 0.10.0 to maintain backward-compatibility.
* Set DiffServ (QoS) bit on outbound connections.
### Fixed
* Improve resilience of the frame parser.
## [1.5.0] - 2017-03-21
### Added
* Add `PeerList.Len` to expose the number of peers in the peer list.
* Add `PeerList.GetNew` to only return previously unselected peers.
## [1.4.0] - 2017-03-01
### Added
* Add version information to the channel's LocalPeerInfo.
* Add peers package for peer management utilities such as
consistent peer selection.
### Fixed
* Fix SetScoreStrategy not rescoring existing peers. (#583).
## [1.3.0] - 2017-02-01
### Added
* Support Thrift namespaces for thrift-gen.
* Exposes the channel's RootPeerList with `channel.RootPeers()`.
## [1.2.3] - 2017-01-19
### Changed
* Improve error messages when an argument reader is closed without
reading the EOF. (#567)
### Fixed
* thrift: Fix an issue where we return `nil` if we expected a Thrift exception
but none was found (e.g., exception is from the future). (#566)
* Fix ListenIP selecting docker interfaces over physical networks. (#565)
* Fix for error when a Thrift payload has completed decoding and attempts
to close the argument reader without waiting until EOF. (#564)
* thrift-gen: Fix "namespace go" being ignored even though the Apache thrift
generated code was respecting it. (#559)
## [1.2.2] - 2016-12-21
### Added
* Add a unique channel ID for introspection (#548)
* Expose local peer information on {Inbound,Outbound}Call (#537)
* Add remote peer info to connection logger and introspection (#514)
### Fixed
* Don't drop existing headers on a context when using Wrap(ctx) (#547)
* Setting response headers is not goroutine safe, allow using a child context
for parallel sub-requests (#549).
* Fix context cancellation not cancelling Dial attempts (#541)
* Only select active connections for calls (#521)
* Treat hostPorts ending in ":0" in the init headers as ephemeral (#513)
## [1.2.1] - 2016-09-29
### Fixed
* Fix data race on headers when making concurrent calls using the same context. (#505)
## [1.2.0] - 2016-09-15
### Added
* Adds support for routing keys (the TChannel rk transport header).
## [1.1.0] - 2016-08-25
### Added
* Integrate OpenTracing for distributed tracing and context propagation.
As long as a Zipkin-style tracing is configured, TChannel frames still
send tracing information, and `CurrentSpan(ctx)` works as before.
All tracer configuration must be handled through OpenTracing.
(#426)
### Changed
* Improve error messages when using the json package and the host:port
fails to connect. (#475)
* mockhyperbahn now using inbuilt TChannel relaying to implement in-process
forwarding. (#472)
* Drop go1.4 support and add support for go1.7.
* Pass thrift.Context to the thrift.Server's response callback (#465)
## [1.0.9] - 2016-07-20
### Added
* Expose meta endpoints on the "tchannel" service name. (#459)
* Add Go version and tchannel-go library version to introspection. (#457)
* Expose the number of connections on a channel. (#451)
### Changed
* Better handling of peers where dialed host:port doesn't match the remote
connection's reported host:port. (#452)
## [1.0.8] - 2016-07-15
### Fixed
* Remove dependency on "testing" from "tchannel-go" introduced in v1.0.7.
## [1.0.7] - 2016-07-15
### Added
* Add CallOptions() to IncomingCall which can be used as the call option
when making outbound calls to proxy all transport headers.
* Add tracing information to all error frames generated by the library.
* Add GetHandlers for getting all registered methods on a subchannel.
* Expose the peer information for outbound calls.
* Support a separate connection timeout from the context timeout, useful for
streaming calls where the stream timeout may be much longer than the
connection timeout.
### Fixed
* Fix peer score not being calculated when adding a new outbound connections
## [1.0.6] - 2016-06-16
### Fixed
* Fix trace span encoding fields in the wrong order
## [1.0.5] - 2016-04-04
### Changed
* Use `context.Context` storage for headers so `thrift.Context` and
`tchannel.ContextWithHeaders` can be passed to functions that use
`context.Context`, and have them retain headers.
* `thrift.Server` allows a custom factory to be used for `thrift.Context`
creation based on the underlying `context.Context` and headers map.
* Store goroutine stack traces on channel creation that can be accessed
via introspection.
## [1.0.4] - 2016-03-09
### Added
* #228: Add registered methods to the introspection output.
* Add ability to set a global handler for a SubChannel.
### Fixed
* Improve handling of network failures during pending calls. Previously, calls
would timeout, but now they fail as soon as the network failure is detected.
* Remove ephemeral peers with closed outbound connections.
* #233: Ensure errors returned from Thrift handlers have a non-nil value.
# 1.0.3 (2016-02-15)
### Added
* Introspection now includes information about all channels created
in the current process.
### Changed
* Improved performance when writing Thrift structs
* Make closing message exchanges less disruptive, changes a panic due to
closing a channel twice to an error log.
## [1.0.2] - 2016-01-29
### Changed
* Extend the `ContextBuilder` API to support setting the transport-level
routing delegate header.
* Assorted logging and test improvements.
### Fixed
* Set a timeout when making new outbound connections to avoid hanging.
* Fix for #196: Make the initial Hyperbahn advertise more tolerant of transient
timeouts.
## [1.0.1] - 2016-01-19
### Added
* Peers can now be removed using PeerList.Remove.
* Add ErrorHandlerFunc to create raw handlers that return errors.
* Retries try to avoid previously selected hosts, rather than just the
host:port.
* Create an ArgReader interface (which is an alias for io.ReadCloser) for
symmetry with ArgWriter.
* Add ArgReadable and ArgWritable interfaces for the common methods between
calls and responses.
* Expose Thrift binary encoding methods (thrift.ReadStruct, thrift.WriteStruct,
thrift.ReadHeaders, thrift.WriteHeaders) so callers can easily send Thrift
payloads over the streaming interface.
### Fixed
* Bug fix for #181: Shuffle peers on PeerList.Add to avoid biases in peer
selection.
## 1.0.0 - 2016-01-11
### Added
* First stable release.
* Support making calls with JSON, Thrift or raw payloads.
* Services use thrift-gen, and implement handlers with a `func(ctx, arg) (res,
error)` signature.
* Support retries.
* Peer selection (peer heap, prefer incoming strategy, for use with Hyperbahn).
* Graceful channel shutdown.
* TCollector trace reporter with sampling support.
* Metrics collection with StatsD.
* Thrift support, including includes.
[//]: # (Version Links)
[1.34.6]: https://github.com/uber/tchannel-go/compare/v1.34.5...v1.34.6
[1.34.5]: https://github.com/uber/tchannel-go/compare/v1.34.4...v1.34.5
[1.34.4]: https://github.com/uber/tchannel-go/compare/v1.34.3...v1.34.4
[1.34.3]: https://github.com/uber/tchannel-go/compare/v1.34.2...v1.34.3
[1.34.2]: https://github.com/uber/tchannel-go/compare/v1.34.1...v1.34.2
[1.34.1]: https://github.com/uber/tchannel-go/compare/v1.34.0...v1.34.1
[1.34.0]: https://github.com/uber/tchannel-go/compare/v1.33.0...v1.34.0
[1.33.0]: https://github.com/uber/tchannel-go/compare/v1.32.1...v1.33.0
[1.32.1]: https://github.com/uber/tchannel-go/compare/v1.32.0...v1.32.1
[1.32.0]: https://github.com/uber/tchannel-go/compare/v1.31.0...v1.32.0
[1.31.0]: https://github.com/uber/tchannel-go/compare/v1.22.3...v1.31.0
[1.22.3]: https://github.com/uber/tchannel-go/compare/v1.22.2...v1.22.3
[1.22.1]: https://github.com/uber/tchannel-go/compare/v1.22.0...v1.22.1
[1.22.0]: https://github.com/uber/tchannel-go/compare/v1.21.2...v1.22.0
[1.21.2]: https://github.com/uber/tchannel-go/compare/v1.21.1...v1.21.2
[1.21.1]: https://github.com/uber/tchannel-go/compare/v1.21.0...v1.21.1
[1.21.0]: https://github.com/uber/tchannel-go/compare/v1.20.1...v1.21.0
[1.20.1]: https://github.com/uber/tchannel-go/compare/v1.20.0...v1.20.1
[1.20.0]: https://github.com/uber/tchannel-go/compare/v1.19.1...v1.20.0
[1.18.0]: https://github.com/uber/tchannel-go/compare/v1.17.0...v1.18.0
[1.17.0]: https://github.com/uber/tchannel-go/compare/v1.16.0...v1.17.0
[1.16.0]: https://github.com/uber/tchannel-go/compare/v1.15.0...v1.16.0
[1.15.0]: https://github.com/uber/tchannel-go/compare/v1.14.0...v1.15.0
[1.14.0]: https://github.com/uber/tchannel-go/compare/v1.13.0...v1.14.0
[1.13.0]: https://github.com/uber/tchannel-go/compare/v1.12.0...v1.13.0
[1.12.0]: https://github.com/uber/tchannel-go/compare/v1.11.0...v1.12.0
[1.11.0]: https://github.com/uber/tchannel-go/compare/v1.10.0...v1.11.0
[1.10.0]: https://github.com/uber/tchannel-go/compare/v1.9.0...v1.10.0
[1.9.0]: https://github.com/uber/tchannel-go/compare/v1.8.1...v1.9.0
[1.8.1]: https://github.com/uber/tchannel-go/compare/v1.8.0...v1.8.1
[1.8.0]: https://github.com/uber/tchannel-go/compare/v1.7.0...v1.8.0
[1.7.0]: https://github.com/uber/tchannel-go/compare/v1.6.0...v1.7.0
[1.6.0]: https://github.com/uber/tchannel-go/compare/v1.5.0...v1.6.0
[1.5.0]: https://github.com/uber/tchannel-go/compare/v1.4.0...v1.5.0
[1.4.0]: https://github.com/uber/tchannel-go/compare/v1.3.0...v1.4.0
[1.3.0]: https://github.com/uber/tchannel-go/compare/v1.2.3...v1.3.0
[1.2.3]: https://github.com/uber/tchannel-go/compare/v1.2.2...v1.2.3
[1.2.2]: https://github.com/uber/tchannel-go/compare/v1.2.1...v1.2.2
[1.2.1]: https://github.com/uber/tchannel-go/compare/v1.2.0...v1.2.1
[1.2.0]: https://github.com/uber/tchannel-go/compare/v1.1.0...v1.2.0
[1.1.0]: https://github.com/uber/tchannel-go/compare/v1.0.9...v1.1.0
[1.0.9]: https://github.com/uber/tchannel-go/compare/v1.0.8...v1.0.9
[1.0.8]: https://github.com/uber/tchannel-go/compare/v1.0.7...v1.0.8
[1.0.7]: https://github.com/uber/tchannel-go/compare/v1.0.6...v1.0.7
[1.0.6]: https://github.com/uber/tchannel-go/compare/v1.0.5...v1.0.6
[1.0.5]: https://github.com/uber/tchannel-go/compare/v1.0.4...v1.0.5
[1.0.4]: https://github.com/uber/tchannel-go/compare/v1.0.2...v1.0.4
[1.0.2]: https://github.com/uber/tchannel-go/compare/v1.0.1...v1.0.2
[1.0.1]: https://github.com/uber/tchannel-go/compare/v1.0.0...v1.0.1
================================================
FILE: CODE_OF_CONDUCT.md
================================================
# Contributor Covenant Code of Conduct
## Our Pledge
In the interest of fostering an open and welcoming environment, we as
contributors and maintainers pledge to making participation in our project and
our community a harassment-free experience for everyone, regardless of age,
body size, disability, ethnicity, gender identity and expression, level of
experience, nationality, personal appearance, race, religion, or sexual
identity and orientation.
## Our Standards
Examples of behavior that contributes to creating a positive environment
include:
* Using welcoming and inclusive language
* Being respectful of differing viewpoints and experiences
* Gracefully accepting constructive criticism
* Focusing on what is best for the community
* Showing empathy towards other community members
Examples of unacceptable behavior by participants include:
* The use of sexualized language or imagery and unwelcome sexual attention or
advances
* Trolling, insulting/derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or electronic
address, without explicit permission
* Other conduct which could reasonably be considered inappropriate in a
professional setting
## Our Responsibilities
Project maintainers are responsible for clarifying the standards of acceptable
behavior and are expected to take appropriate and fair corrective action in
response to any instances of unacceptable behavior.
Project maintainers have the right and responsibility to remove, edit, or
reject comments, commits, code, wiki edits, issues, and other contributions
that are not aligned to this Code of Conduct, or to ban temporarily or
permanently any contributor for other behaviors that they deem inappropriate,
threatening, offensive, or harmful.
## Scope
This Code of Conduct applies both within project spaces and in public spaces
when an individual is representing the project or its community. Examples of
representing a project or community include using an official project e-mail
address, posting via an official social media account, or acting as an
appointed representative at an online or offline event. Representation of a
project may be further defined and clarified by project maintainers.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported by contacting the project team at oss-conduct@uber.com. The project
team will review and investigate all complaints, and will respond in a way
that it deems appropriate to the circumstances. The project team is obligated
to maintain confidentiality with regard to the reporter of an incident.
Further details of specific enforcement policies may be posted separately.
Project maintainers who do not follow or enforce the Code of Conduct in good
faith may face temporary or permanent repercussions as determined by other
members of the project's leadership.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
version 1.4, available at
[http://contributor-covenant.org/version/1/4][version].
[homepage]: http://contributor-covenant.org
[version]: http://contributor-covenant.org/version/1/4/
================================================
FILE: CONTRIBUTING.md
================================================
Contributing
============
We'd love your help making tchannel-go great!
## Getting Started
TChannel uses [glide](https://github.com/Masterminds/glide) to manage
dependencies.
To get started:
```bash
go get github.com/uber/tchannel-go
make install_glide
make # tests should pass
```
## Making A Change
*Before making any significant changes, please [open an
issue](https://github.com/uber/tchannel-go/issues).* Discussing your proposed
changes ahead of time will make the contribution process smooth for everyone.
Once we've discussed your changes and you've got your code ready, make sure
that tests are passing (`make test` or `make cover`) and open your PR! Your
pull request is most likely to be accepted if it:
* Includes tests for new functionality.
* Follows the guidelines in [Effective
Go](https://golang.org/doc/effective_go.html) and the [Go team's common code
review comments](https://github.com/golang/go/wiki/CodeReviewComments).
* Has a [good commit
message](http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html).
## Cutting a Release
* Send a pull request against dev including:
* update CHANGELOG.md (`scripts/changelog_halp.sh`)
* update version.go
* Send a pull request for dev into master
* `git tag -m v0.0.0 -a v0.0.0`
* `git push origin --tags`
* Copy CHANGELOG.md fragment into release notes on
https://github.com/uber/tchannel-go/releases
================================================
FILE: LICENSE.md
================================================
Copyright (c) 2015 Uber Technologies, Inc.
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.
================================================
FILE: Makefile
================================================
PATH := $(GOPATH)/bin:$(PATH)
EXAMPLES=./examples/bench/server ./examples/bench/client ./examples/ping ./examples/thrift ./examples/hyperbahn/echo-server
ALL_PKGS := $(shell go list ./... | grep -v 'thirdparty')
PROD_PKGS := . ./http ./hyperbahn ./json ./peers ./pprof ./raw ./relay ./stats ./thrift $(EXAMPLES)
TEST_ARG ?= -race -v -timeout 10m
COV_PKG ?= ./
BUILD := ./build
THRIFT_GEN_RELEASE := ./thrift-gen-release
THRIFT_GEN_RELEASE_LINUX := $(THRIFT_GEN_RELEASE)/linux-x86_64
THRIFT_GEN_RELEASE_DARWIN := $(THRIFT_GEN_RELEASE)/darwin-x86_64
PLATFORM := $(shell uname -s | tr '[:upper:]' '[:lower:]')
ARCH := $(shell uname -m)
BIN := $(shell pwd)/.bin
# Cross language test args
TEST_HOST=127.0.0.1
TEST_PORT=0
-include crossdock/rules.mk
all: lint test examples
$(BIN)/thrift:
mkdir -p $(BIN)
scripts/install-thrift.sh $(BIN)
packages_test:
go list -json ./... | jq -r '. | select ((.TestGoFiles | length) > 0) | .ImportPath'
setup:
mkdir -p $(BUILD)
mkdir -p $(BUILD)/examples
mkdir -p $(THRIFT_GEN_RELEASE_LINUX)
mkdir -p $(THRIFT_GEN_RELEASE_DARWIN)
install:
go mod vendor
install_lint:
@echo "Installing golint, since we expect to lint"
go install golang.org/x/lint/golint@latest
install_ci: $(BIN)/thrift install
ifdef CROSSDOCK
$(MAKE) install_docker_ci
endif
help:
@egrep "^# target:" [Mm]akefile | sort -
clean:
echo Cleaning build artifacts...
go clean
rm -rf $(BUILD) $(THRIFT_GEN_RELEASE)
echo
fmt format:
echo Formatting Packages...
go fmt $(ALL_PKGS)
echo
test_ci:
ifdef CROSSDOCK
$(MAKE) crossdock_ci
else
$(MAKE) test
endif
test: clean setup check_no_test_deps $(BIN)/thrift
$(MAKE) test_vanilla
$(MAKE) test_relay_frame_leaks
# test_vanilla runs all unit tests without checking for frame leaks
test_vanilla:
@echo Testing packages:
PATH=$(BIN):$$PATH DISABLE_FRAME_POOLING_CHECKS=1 go test -parallel=4 $(TEST_ARG) $(ALL_PKGS)
@echo Running frame pool tests
PATH=$(BIN):$$PATH go test -run TestFramesReleased -stressTest $(TEST_ARG)
# test_relay_frame_leaks runs unit tests in relay_test.go with frame leak checks enabled
test_relay_frame_leaks:
@echo Testing relay frame leaks
PATH=$(BIN):$$PATH go test -parallel=4 $(TEST_ARG) relay_test.go
check_no_test_deps:
! go list -json $(PROD_PKGS) | jq -r '.Deps | select ((. | length) > 0) | .[]' | grep -e test -e mock | grep -v '^internal/testlog'
benchmark: clean setup $(BIN)/thrift
echo Running benchmarks:
PATH=$(BIN)::$$PATH go test $(ALL_PKGS) -bench=. -cpu=1 -benchmem -run NONE
cover_profile: clean setup $(BIN)/thrift
@echo Testing packages:
mkdir -p $(BUILD)
PATH=$(BIN)::$$PATH DISABLE_FRAME_POOLING_CHECKS=1 go test $(COV_PKG) $(TEST_ARG) -coverprofile=$(BUILD)/coverage.out
cover: cover_profile
go tool cover -html=$(BUILD)/coverage.out
cover_ci:
@echo "Uploading coverage"
$(MAKE) cover_profile
curl -s https://codecov.io/bash > $(BUILD)/codecov.bash
bash $(BUILD)/codecov.bash -f $(BUILD)/coverage.out
FILTER := grep -v -e '_string.go' -e '/gen-go/' -e '/mocks/' -e 'vendor/' -e 'thirdparty'
lint: install
@echo "Running golint"
-golint $(ALL_PKGS) | $(FILTER) | tee lint.log
@echo "Running go vet"
-go vet $(ALL_PKGS) 2>&1 | $(FILTER) | fgrep -v -e "possible formatting directiv" -e "exit status" | tee -a lint.log
@echo "Verifying files are gofmt'd"
-gofmt -l . | $(FILTER) | tee -a lint.log
@echo "Checking for unresolved FIXMEs"
-git grep -i -n fixme | $(FILTER) | grep -v -e Makefile | tee -a lint.log
@[ ! -s lint.log ]
thrift_example: thrift_gen
go build -o $(BUILD)/examples/thrift ./examples/thrift/main.go
test_server:
./build/examples/test_server --host ${TEST_HOST} --port ${TEST_PORT}
examples: clean setup thrift_example
echo Building examples...
mkdir -p $(BUILD)/examples/ping $(BUILD)/examples/bench
go build -o $(BUILD)/examples/ping/pong ./examples/ping/main.go
go build -o $(BUILD)/examples/hyperbahn/echo-server ./examples/hyperbahn/echo-server/main.go
go build -o $(BUILD)/examples/bench/server ./examples/bench/server
go build -o $(BUILD)/examples/bench/client ./examples/bench/client
go build -o $(BUILD)/examples/bench/runner ./examples/bench/runner.go
go build -o $(BUILD)/examples/test_server ./examples/test_server
thrift_gen: $(BIN)/thrift
go build -o $(BUILD)/thrift-gen ./thrift/thrift-gen
PATH=$(BIN):$$PATH $(BUILD)/thrift-gen --generateThrift --inputFile thrift/test.thrift --outputDir thrift/gen-go/
PATH=$(BIN):$$PATH $(BUILD)/thrift-gen --generateThrift --inputFile examples/keyvalue/keyvalue.thrift --outputDir examples/keyvalue/gen-go
PATH=$(BIN):$$PATH $(BUILD)/thrift-gen --generateThrift --inputFile examples/thrift/example.thrift --outputDir examples/thrift/gen-go
PATH=$(BIN):$$PATH $(BUILD)/thrift-gen --generateThrift --inputFile hyperbahn/hyperbahn.thrift --outputDir hyperbahn/gen-go
release_thrift_gen: clean setup
GOOS=linux GOARCH=amd64 go build -o $(THRIFT_GEN_RELEASE_LINUX)/thrift-gen ./thrift/thrift-gen
GOOS=darwin GOARCH=amd64 go build -o $(THRIFT_GEN_RELEASE_DARWIN)/thrift-gen ./thrift/thrift-gen
tar -czf thrift-gen-release.tar.gz $(THRIFT_GEN_RELEASE)
mv thrift-gen-release.tar.gz $(THRIFT_GEN_RELEASE)/
.PHONY: all help clean fmt format install install_ci install_lint release_thrift_gen packages_test check_no_test_deps test test_ci lint
.SILENT: all help clean fmt format test lint
================================================
FILE: README.md
================================================
# TChannel [![GoDoc][doc-img]][doc] [![Build Status][ci-img]][ci] [![Coverage Status][cov-img]][cov]
[TChannel][tchan-spec] is a multiplexing and framing protocol for RPC calls.
tchannel-go is a Go implementation of the protocol, including client libraries
for [Hyperbahn][hyperbahn].
If you'd like to start by writing a small Thrift and TChannel service, check
out [this guide](guide/Thrift_Hyperbahn.md). For a less opinionated setup, see
the [contribution guidelines](CONTRIBUTING.md).
## Overview
TChannel is a network protocol that supports:
* A request/response model,
* Multiplexing multiple requests across the same TCP socket,
* Out-of-order responses,
* Streaming requests and responses,
* Checksummed frames,
* Transport of arbitrary payloads,
* Easy implementation in many languages, and
* Redis-like performance.
This protocol is intended to run on datacenter networks for inter-process
communication.
## Protocol
TChannel frames have a fixed-length header and 3 variable-length fields. The
underlying protocol does not assign meaning to these fields, but the included
client/server implementation uses the first field to represent a unique
endpoint or function name in an RPC model. The next two fields can be used for
arbitrary data. Some suggested way to use the 3 fields are:
* URI path + HTTP method and headers as JSON + body, or
* Function name + headers + thrift/protobuf.
Note, however, that the only encoding supported by TChannel is UTF-8. If you
want JSON, you'll need to stringify and parse outside of TChannel.
This design supports efficient routing and forwarding: routers need to parse
the first or second field, but can forward the third field without parsing.
There is no notion of client and server in this system. Every TChannel instance
is capable of making and receiving requests, and thus requires a unique port on
which to listen. This requirement may change in the future.
See the [protocol specification][tchan-proto-spec] for more details.
## Examples
- [ping](examples/ping): A simple ping/pong example using raw TChannel.
- [thrift](examples/thrift): A Thrift server/client example.
- [keyvalue](examples/keyvalue): A keyvalue Thrift service with separate server and client binaries.
<hr>
This project is released under the [MIT License](LICENSE.md).
[doc-img]: https://godoc.org/github.com/uber/tchannel-go?status.svg
[doc]: https://godoc.org/github.com/uber/tchannel-go
[ci-img]: https://github.com/uber/tchannel-go/actions/workflows/tests.yaml/badge.svg?branch=master
[ci]: https://github.com/uber/tchannel-go/actions/workflows/tests.yaml
[cov-img]: https://coveralls.io/repos/uber/tchannel-go/badge.svg?branch=master&service=github
[cov]: https://coveralls.io/github/uber/tchannel-go?branch=master
[tchan-spec]: http://tchannel.readthedocs.org/en/latest/
[tchan-proto-spec]: http://tchannel.readthedocs.org/en/latest/protocol/
[hyperbahn]: https://github.com/uber/hyperbahn
================================================
FILE: RELEASE.md
================================================
Release process
===============
This document outlines how to create a release of tchannel-go
1. Set up some environment variables for use later.
```
# This is the version being released.
$ VERSION=1.8.0
```
2. Make sure you have the latest dev and create a branch off it.
```
$ git checkout dev
$ git pull
$ git checkout -b release
```
3. Update the `CHANGELOG.md` and `version.go` files.
```
$ go run ./scripts/vbumper/main.go --version $VERSION
```
4. Clean up the `CHANGELOG.md` to only mention noteworthy changes for users.
5. Commit changes and create a PR against `dev` to prepare for release.
6. Once the release PR has been accepted, run the following to release.
```
$ git checkout master
$ git pull
$ git merge dev
$ git tag -a "v$VERSION" -m "v$VERSION"
$ git push origin master v$VERSION
```
7. Go to <https://github.com/uber/tchannel-go/tags> and edit the release notes.
Copy changelog entries for this release and set the name to `v$VERSION`.
8. Switch back to development.
```
$ git checkout dev
$ git merge master
$ go run ./scripts/vbumper/main.go --version ${VERSION}-dev --skip-changelog
$ git commit -am "Back to development"
$ git push
```
================================================
FILE: all_channels.go
================================================
// Copyright (c) 2015 Uber Technologies, Inc.
// 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.
package tchannel
import (
"fmt"
"sync"
)
// channelMap is used to ensure that applications don't create multiple channels with
// the same service name in a single process.
var channelMap = struct {
sync.Mutex
existing map[string][]*Channel
}{
existing: make(map[string][]*Channel),
}
func registerNewChannel(ch *Channel) {
serviceName := ch.ServiceName()
ch.createdStack = string(getStacks(false /* all */))
ch.log.WithFields(
LogField{"channelPtr", fmt.Sprintf("%p", ch)},
LogField{"createdStack", ch.createdStack},
).Info("Created new channel.")
channelMap.Lock()
defer channelMap.Unlock()
existing := channelMap.existing[serviceName]
channelMap.existing[serviceName] = append(existing, ch)
}
func removeClosedChannel(ch *Channel) {
channelMap.Lock()
defer channelMap.Unlock()
channels := channelMap.existing[ch.ServiceName()]
for i, v := range channels {
if v != ch {
continue
}
// Replace current index with the last element, and truncate channels.
channels[i] = channels[len(channels)-1]
channels = channels[:len(channels)-1]
break
}
channelMap.existing[ch.ServiceName()] = channels
}
func findChannelByID(id uint32) (*Channel, bool) {
channelMap.Lock()
defer channelMap.Unlock()
for _, channels := range channelMap.existing {
for _, ch := range channels {
if ch.chID == id {
return ch, true
}
}
}
return nil, false
}
================================================
FILE: all_channels_test.go
================================================
// Copyright (c) 2015 Uber Technologies, Inc.
// 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.
package tchannel
import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestAllChannelsRegistered(t *testing.T) {
introspectOpts := &IntrospectionOptions{IncludeOtherChannels: true}
ch1_1, err := NewChannel("ch1", nil)
require.NoError(t, err, "Channel create failed")
ch1_2, err := NewChannel("ch1", nil)
require.NoError(t, err, "Channel create failed")
ch2_1, err := NewChannel("ch2", nil)
require.NoError(t, err, "Channel create failed")
state := ch1_1.IntrospectState(introspectOpts)
assert.Equal(t, 1, len(state.OtherChannels["ch1"]))
assert.Equal(t, 1, len(state.OtherChannels["ch2"]))
ch1_2.Close()
state = ch1_1.IntrospectState(introspectOpts)
assert.Equal(t, 0, len(state.OtherChannels["ch1"]))
assert.Equal(t, 1, len(state.OtherChannels["ch2"]))
ch2_2, err := NewChannel("ch2", nil)
state = ch1_1.IntrospectState(introspectOpts)
require.NoError(t, err, "Channel create failed")
assert.Equal(t, 0, len(state.OtherChannels["ch1"]))
assert.Equal(t, 2, len(state.OtherChannels["ch2"]))
ch1_1.Close()
ch2_1.Close()
ch2_2.Close()
state = ch1_1.IntrospectState(introspectOpts)
assert.Equal(t, 0, len(state.OtherChannels["ch1"]))
assert.Equal(t, 0, len(state.OtherChannels["ch2"]))
}
================================================
FILE: arguments.go
================================================
// Copyright (c) 2015 Uber Technologies, Inc.
// 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.
package tchannel
import (
"bufio"
"encoding/json"
"io"
"io/ioutil"
"github.com/uber/tchannel-go/internal/argreader"
)
// ArgReader is the interface for the arg2 and arg3 streams on an
// OutboundCallResponse and an InboundCall
type ArgReader io.ReadCloser
// ArgWriter is the interface for the arg2 and arg3 streams on an OutboundCall
// and an InboundCallResponse
type ArgWriter interface {
io.WriteCloser
// Flush flushes the currently written bytes without waiting for the frame
// to be filled.
Flush() error
}
// ArgWritable is an interface for providing arg2 and arg3 writer streams;
// implemented by reqResWriter e.g. OutboundCall and InboundCallResponse
type ArgWritable interface {
Arg2Writer() (ArgWriter, error)
Arg3Writer() (ArgWriter, error)
}
// ArgReadable is an interface for providing arg2 and arg3 reader streams;
// implemented by reqResReader e.g. InboundCall and OutboundCallResponse.
type ArgReadable interface {
Arg2Reader() (ArgReader, error)
Arg3Reader() (ArgReader, error)
}
// ArgReadHelper providers a simpler interface to reading arguments.
type ArgReadHelper struct {
reader ArgReader
err error
}
// NewArgReader wraps the result of calling ArgXReader to provide a simpler
// interface for reading arguments.
func NewArgReader(reader ArgReader, err error) ArgReadHelper {
return ArgReadHelper{reader, err}
}
func (r ArgReadHelper) read(f func() error) error {
if r.err != nil {
return r.err
}
if err := f(); err != nil {
return err
}
if err := argreader.EnsureEmpty(r.reader, "read arg"); err != nil {
return err
}
return r.reader.Close()
}
// Read reads from the reader into the byte slice.
func (r ArgReadHelper) Read(bs *[]byte) error {
return r.read(func() error {
var err error
*bs, err = ioutil.ReadAll(r.reader)
return err
})
}
// ReadJSON deserializes JSON from the underlying reader into data.
func (r ArgReadHelper) ReadJSON(data interface{}) error {
return r.read(func() error {
// TChannel allows for 0 length values (not valid JSON), so we use a bufio.Reader
// to check whether data is of 0 length.
reader := bufio.NewReader(r.reader)
if _, err := reader.Peek(1); err == io.EOF {
// If the data is 0 length, then we don't try to read anything.
return nil
} else if err != nil {
return err
}
d := json.NewDecoder(reader)
return d.Decode(data)
})
}
// ArgWriteHelper providers a simpler interface to writing arguments.
type ArgWriteHelper struct {
writer io.WriteCloser
err error
}
// NewArgWriter wraps the result of calling ArgXWriter to provider a simpler
// interface for writing arguments.
func NewArgWriter(writer io.WriteCloser, err error) ArgWriteHelper {
return ArgWriteHelper{writer, err}
}
func (w ArgWriteHelper) write(f func() error) error {
if w.err != nil {
return w.err
}
if err := f(); err != nil {
return err
}
return w.writer.Close()
}
// Write writes the given bytes to the underlying writer.
func (w ArgWriteHelper) Write(bs []byte) error {
return w.write(func() error {
_, err := w.writer.Write(bs)
return err
})
}
// WriteJSON writes the given object as JSON.
func (w ArgWriteHelper) WriteJSON(data interface{}) error {
return w.write(func() error {
e := json.NewEncoder(w.writer)
return e.Encode(data)
})
}
================================================
FILE: arguments_test.go
================================================
// Copyright (c) 2015 Uber Technologies, Inc.
// 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.
package tchannel
import (
"bytes"
"io"
"io/ioutil"
"strings"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
type bufferWithClose struct {
*bytes.Buffer
closed bool
}
var _ io.WriteCloser = &bufferWithClose{}
var _ io.ReadCloser = &bufferWithClose{}
func newWriter() *bufferWithClose {
return &bufferWithClose{bytes.NewBuffer(nil), false}
}
func newReader(bs []byte) *bufferWithClose {
return &bufferWithClose{bytes.NewBuffer(bs), false}
}
func (w *bufferWithClose) Close() error {
w.closed = true
return nil
}
type testObject struct {
Name string `json:"name"`
Value int `json:"value"`
}
func TestJSONInputOutput(t *testing.T) {
obj := testObject{Name: "Foo", Value: 20756}
writer := newWriter()
require.Nil(t, NewArgWriter(writer, nil).WriteJSON(obj))
assert.True(t, writer.closed)
assert.Equal(t, "{\"name\":\"Foo\",\"value\":20756}\n", writer.String())
reader := newReader(writer.Bytes())
outObj := testObject{}
require.Nil(t, NewArgReader(reader, nil).ReadJSON(&outObj))
assert.True(t, reader.closed)
assert.Equal(t, "Foo", outObj.Name)
assert.Equal(t, 20756, outObj.Value)
}
func TestReadNotEmpty(t *testing.T) {
// Note: The contents need to be larger than the default buffer size of bufio.NewReader.
r := bytes.NewReader([]byte("{}" + strings.Repeat("{}\n", 10000)))
var data map[string]interface{}
reader := NewArgReader(ioutil.NopCloser(r), nil)
require.Error(t, reader.ReadJSON(&data), "Read should fail due to extra bytes")
}
func BenchmarkArgReaderWriter(b *testing.B) {
obj := testObject{Name: "Foo", Value: 20756}
outObj := testObject{}
for i := 0; i < b.N; i++ {
writer := newWriter()
NewArgWriter(writer, nil).WriteJSON(obj)
reader := newReader(writer.Bytes())
NewArgReader(reader, nil).ReadJSON(&outObj)
}
b.StopTimer()
assert.Equal(b, obj, outObj)
}
================================================
FILE: benchmark/benchclient/main.go
================================================
// Copyright (c) 2015 Uber Technologies, Inc.
// 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.
// benchclient is used to make requests to a specific server.
package main
import (
"bufio"
"flag"
"fmt"
"log"
"os"
"strconv"
"strings"
"time"
"github.com/uber/tchannel-go/benchmark"
)
var (
serviceName = flag.String("service", "bench-server", "The benchmark server's service name")
timeout = flag.Duration("timeout", time.Second, "Timeout for each request")
requestSize = flag.Int("request-size", 10000, "The number of bytes of each request")
noLibrary = flag.Bool("no-library", false, "Whether to use the template based library instead of TChannel's client library")
numClients = flag.Int("num-clients", 1, "Number of concurrent clients to run in process")
noDurations = flag.Bool("no-durations", false, "Disable printing of latencies to stdout")
)
func main() {
flag.Parse()
opts := []benchmark.Option{
benchmark.WithServiceName(*serviceName),
benchmark.WithTimeout(*timeout),
benchmark.WithRequestSize(*requestSize),
benchmark.WithNumClients(*numClients),
}
if *noLibrary {
opts = append(opts, benchmark.WithNoLibrary())
}
client := benchmark.NewClient(flag.Args(), opts...)
fmt.Println("bench-client started")
rdr := bufio.NewScanner(os.Stdin)
for rdr.Scan() {
line := rdr.Text()
parts := strings.Split(line, " ")
var n int
var err error
if len(parts) >= 2 {
n, err = strconv.Atoi(parts[1])
if err != nil {
log.Fatalf("unrecognized number %q: %v", parts[1], err)
}
}
switch cmd := parts[0]; cmd {
case "warmup":
if err := client.Warmup(); err != nil {
log.Fatalf("warmup failed: %v", err)
}
fmt.Println("success")
continue
case "rcall":
makeCalls(n, client.RawCall)
case "tcall":
makeCalls(n, client.ThriftCall)
case "quit":
return
default:
log.Fatalf("unrecognized command: %v", line)
}
}
if err := rdr.Err(); err != nil {
log.Fatalf("Reader failed: %v", err)
}
}
func makeCalls(n int, f func(n int) ([]time.Duration, error)) {
durations, err := f(n)
if err != nil {
log.Fatalf("Call failed: %v", err)
}
if !*noDurations {
for i, d := range durations {
if i > 0 {
fmt.Printf(" ")
}
fmt.Printf("%v", d)
}
}
fmt.Println()
}
================================================
FILE: benchmark/benchserver/main.go
================================================
// Copyright (c) 2015 Uber Technologies, Inc.
// 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.
// benchserver is used to receive requests for benchmarks.
package main
import (
"bufio"
"flag"
"fmt"
"io"
"log"
"os"
"strings"
"github.com/uber/tchannel-go/benchmark"
)
var (
serviceName = flag.String("service", "bench-server", "The benchmark server's service name")
advertiseHosts = flag.String("advertise-hosts", "", "Comma-separated list of hosts to advertise to")
)
func main() {
flag.Parse()
var adHosts []string
if len(*advertiseHosts) > 0 {
adHosts = strings.Split(*advertiseHosts, ",")
}
server := benchmark.NewServer(
benchmark.WithServiceName(*serviceName),
benchmark.WithAdvertiseHosts(adHosts),
)
fmt.Println(server.HostPort())
rdr := bufio.NewReader(os.Stdin)
for {
line, err := rdr.ReadString('\n')
if err != nil {
if err == io.EOF {
return
}
log.Fatalf("stdin read failed: %v", err)
}
line = strings.TrimSuffix(line, "\n")
switch line {
case "count-raw":
fmt.Println(server.RawCalls())
case "count-thrift":
fmt.Println(server.ThriftCalls())
case "quit":
return
default:
log.Fatalf("unrecognized command: %v", line)
}
}
}
================================================
FILE: benchmark/build_manager.go
================================================
// Copyright (c) 2015 Uber Technologies, Inc.
// 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.
package benchmark
import (
"io/ioutil"
"os"
"os/exec"
"sync"
)
type buildManager struct {
sync.RWMutex
builds map[string]*build
}
type build struct {
once sync.Once
mainFile string
binaryFile string
buildErr error
}
func newBuildManager() *buildManager {
return &buildManager{
builds: make(map[string]*build),
}
}
func (m *buildManager) GoBinary(mainFile string) (string, error) {
m.Lock()
bld, ok := m.builds[mainFile]
if !ok {
bld = &build{mainFile: mainFile}
m.builds[mainFile] = bld
}
m.Unlock()
bld.once.Do(bld.Build)
return bld.binaryFile, bld.buildErr
}
func (b *build) Build() {
tempFile, err := ioutil.TempFile("", "bench")
if err != nil {
panic("Failed to create temp file: " + err.Error())
}
tempFile.Close()
buildCmd := exec.Command("go", "build", "-o", tempFile.Name(), b.mainFile)
buildCmd.Stdout = os.Stdout
buildCmd.Stderr = os.Stderr
if err := buildCmd.Run(); err != nil {
b.buildErr = err
return
}
b.binaryFile = tempFile.Name()
}
================================================
FILE: benchmark/client_server_bench_test.go
================================================
// Copyright (c) 2015 Uber Technologies, Inc.
// 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.
package benchmark
import (
"log"
"testing"
"time"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func BenchmarkServer(b *testing.B) {
server := NewServer()
client := NewClient([]string{server.HostPort()},
WithExternalProcess(),
WithNoLibrary(),
WithNumClients(10),
WithNoDurations(),
WithTimeout(10*time.Second),
)
assert.NoError(b, client.Warmup(), "Warmup failed")
b.ResetTimer()
started := time.Now()
_, err := client.RawCall(b.N)
total := time.Since(started)
assert.NoError(b, err, "client.RawCall failed")
if n := server.RawCalls(); b.N > n {
b.Errorf("Server received %v calls, expected at least %v calls", n, b.N)
}
log.Printf("Calls: %v Duration: %v RPS: %.0f", b.N, total, float64(b.N)/total.Seconds())
}
func BenchmarkClient(b *testing.B) {
servers := make([]Server, 3)
serverHosts := make([]string, len(servers))
for i := range servers {
servers[i] = NewServer(
WithExternalProcess(),
WithNoLibrary(),
)
serverHosts[i] = servers[i].HostPort()
}
// To saturate a single process, we need to have multiple clients.
client := NewClient(serverHosts,
WithNoChecking(),
WithNumClients(10),
)
require.NoError(b, client.Warmup(), "Warmup failed")
b.ResetTimer()
started := time.Now()
if _, err := client.RawCall(b.N); err != nil {
b.Fatalf("Call failed: %v", err)
}
total := time.Since(started)
log.Printf("Calls: %v Duration: %v RPS: %.0f", b.N, total, float64(b.N)/total.Seconds())
}
================================================
FILE: benchmark/external_client.go
================================================
// Copyright (c) 2015 Uber Technologies, Inc.
// 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.
package benchmark
import (
"fmt"
"strconv"
"strings"
"time"
)
// externalClient represents a benchmark client running out-of-process.
type externalClient struct {
*externalCmd
opts *options
}
func newExternalClient(hosts []string, opts *options) Client {
benchArgs := []string{
"--service", opts.svcName,
"--timeout", opts.timeout.String(),
"--request-size", strconv.Itoa(opts.reqSize),
"--num-clients", strconv.Itoa(opts.numClients),
}
if opts.noDurations {
benchArgs = append(benchArgs, "--no-durations")
}
if opts.noLibrary {
benchArgs = append(benchArgs, "--no-library")
}
benchArgs = append(benchArgs, hosts...)
cmd, initial := newExternalCmd("benchclient/main.go", benchArgs)
if !strings.Contains(initial, "started") {
panic("bench-client did not start, got: " + initial)
}
return &externalClient{cmd, opts}
}
func (c *externalClient) Warmup() error {
out, err := c.writeAndRead("warmup")
if err != nil {
return err
}
if out != "success" {
return fmt.Errorf("warmup failed: %v", out)
}
return nil
}
func (c *externalClient) callAndParse(cmd string) ([]time.Duration, error) {
out, err := c.writeAndRead(cmd)
if err != nil {
return nil, err
}
if out == "" {
return nil, nil
}
durationStrs := strings.Split(out, " ")
durations := make([]time.Duration, len(durationStrs))
for i, s := range durationStrs {
d, err := time.ParseDuration(s)
if err != nil {
return nil, fmt.Errorf("calls failed: %v", out)
}
durations[i] = d
}
return durations, nil
}
func (c *externalClient) RawCall(n int) ([]time.Duration, error) {
return c.callAndParse(fmt.Sprintf("rcall %v", n))
}
func (c *externalClient) ThriftCall(n int) ([]time.Duration, error) {
return c.callAndParse(fmt.Sprintf("tcall %v", n))
}
================================================
FILE: benchmark/external_common.go
================================================
// Copyright (c) 2015 Uber Technologies, Inc.
// 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.
package benchmark
import (
"bufio"
"io"
"os"
"os/exec"
)
var _bm = newBuildManager()
// externalCmd handles communication with an external benchmark client.
type externalCmd struct {
cmd *exec.Cmd
stdoutOrig io.ReadCloser
stdout *bufio.Scanner
stdin io.WriteCloser
}
func newExternalCmd(mainFile string, benchArgs []string) (*externalCmd, string) {
bin, err := _bm.GoBinary(BenchmarkDir + mainFile)
if err != nil {
panic("failed to compile " + mainFile + ": " + err.Error())
}
cmd := exec.Command(bin, benchArgs...)
cmd.Stderr = os.Stderr
stdout, err := cmd.StdoutPipe()
if err != nil {
panic("failed to create stdout: " + err.Error())
}
stdin, err := cmd.StdinPipe()
if err != nil {
panic("failed to create stdin: " + err.Error())
}
if err := cmd.Start(); err != nil {
panic("failed to start external process: " + err.Error())
}
stdoutScanner := bufio.NewScanner(stdout)
if !stdoutScanner.Scan() {
panic("failed to check if external process started: " + err.Error())
}
out := stdoutScanner.Text()
return &externalCmd{
cmd: cmd,
stdin: stdin,
stdout: stdoutScanner,
stdoutOrig: stdout,
}, out
}
func (c *externalCmd) writeAndRead(cmd string) (string, error) {
if _, err := io.WriteString(c.stdin, cmd+"\n"); err != nil {
return "", err
}
if c.stdout.Scan() {
return c.stdout.Text(), nil
}
return "", c.stdout.Err()
}
func (c *externalCmd) Close() {
c.stdin.Close()
c.stdoutOrig.Close()
c.cmd.Process.Kill()
}
================================================
FILE: benchmark/external_server.go
================================================
// Copyright (c) 2015 Uber Technologies, Inc.
// 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.
package benchmark
import (
"net"
"strconv"
"strings"
)
// externalServer represents a benchmark server running out-of-process.
type externalServer struct {
*externalCmd
hostPort string
opts *options
}
func newExternalServer(opts *options) Server {
benchArgs := []string{
"--service", opts.svcName,
}
if len(opts.advertiseHosts) > 0 {
benchArgs = append(benchArgs,
"--advertise-hosts", strings.Join(opts.advertiseHosts, ","))
}
cmd, hostPortStr := newExternalCmd("benchserver/main.go", benchArgs)
if _, _, err := net.SplitHostPort(hostPortStr); err != nil {
panic("bench-server did not print host:port on startup: " + err.Error())
}
return &externalServer{cmd, hostPortStr, opts}
}
func (s *externalServer) HostPort() string {
return s.hostPort
}
func (s *externalServer) RawCalls() int {
return s.writeAndReadInt("count-raw")
}
func (s *externalServer) ThriftCalls() int {
return s.writeAndReadInt("count-thrift")
}
func (s *externalServer) writeAndReadInt(cmd string) int {
v, err := s.writeAndRead(cmd)
if err != nil {
panic(err)
}
vInt, err := strconv.Atoi(v)
if err != nil {
panic(err)
}
return vInt
}
================================================
FILE: benchmark/frame_templates.go
================================================
// Copyright (c) 2015 Uber Technologies, Inc.
// 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.
package benchmark
import (
"bytes"
"encoding/binary"
"io"
"time"
"github.com/uber/tchannel-go"
"github.com/uber/tchannel-go/raw"
"github.com/uber/tchannel-go/testutils"
)
const (
_idOffset = 4 /* size (2) + type (1) + reserved (1) */
_idOffsetEnd = _idOffset + 4 /* length */
)
type frames struct {
outgoing [][]byte
incoming [][]byte
}
func (f frames) duplicate() frames {
return frames{
outgoing: deepCopyByteSlice(f.outgoing),
incoming: deepCopyByteSlice(f.incoming),
}
}
func deepCopyByteSlice(bs [][]byte) [][]byte {
newBs := make([][]byte, len(bs))
for i, b := range bs {
newBs[i] = make([]byte, len(b))
copy(newBs[i], b)
}
return newBs
}
func (f frames) writeInitReq(w io.Writer) error {
_, err := w.Write(f.outgoing[0])
return err
}
func (f frames) writeInitRes(w io.Writer) error {
_, err := w.Write(f.incoming[0])
return err
}
func (f frames) writeCallReq(id uint32, w io.Writer) (int, error) {
frames := f.outgoing[1:]
return f.writeMulti(id, w, frames)
}
func (f frames) writeCallRes(id uint32, w io.Writer) (int, error) {
frames := f.incoming[1:]
return f.writeMulti(id, w, frames)
}
func (f frames) writeMulti(id uint32, w io.Writer, frames [][]byte) (int, error) {
written := 0
for _, f := range frames {
binary.BigEndian.PutUint32(f[_idOffset:_idOffsetEnd], id)
if _, err := w.Write(f); err != nil {
return written, err
}
written++
}
return written, nil
}
func getRawCallFrames(timeout time.Duration, svcName string, reqSize int) frames {
var fs frames
modifier := func(fromClient bool, f *tchannel.Frame) *tchannel.Frame {
buf := &bytes.Buffer{}
if err := f.WriteOut(buf); err != nil {
panic(err)
}
if fromClient {
fs.outgoing = append(fs.outgoing, buf.Bytes())
} else {
fs.incoming = append(fs.incoming, buf.Bytes())
}
return f
}
withNewServerClient(svcName, func(server, client *tchannel.Channel) {
testutils.RegisterEcho(server, nil)
relay, err := NewTCPFrameRelay([]string{server.PeerInfo().HostPort}, modifier)
if err != nil {
panic(err)
}
defer relay.Close()
args := &raw.Args{
Arg2: getRequestBytes(reqSize),
Arg3: getRequestBytes(reqSize),
}
ctx, cancel := tchannel.NewContext(timeout)
defer cancel()
if _, _, _, err := raw.Call(ctx, client, relay.HostPort(), svcName, "echo", args.Arg2, args.Arg3); err != nil {
panic(err)
}
})
return fs
}
func withNewServerClient(svcName string, f func(server, client *tchannel.Channel)) {
opts := testutils.NewOpts().SetServiceName(svcName)
server, err := testutils.NewServerChannel(opts)
if err != nil {
panic(err)
}
defer server.Close()
client, err := testutils.NewClientChannel(opts)
if err != nil {
panic(err)
}
defer client.Close()
f(server, client)
}
================================================
FILE: benchmark/interfaces.go
================================================
// Copyright (c) 2015 Uber Technologies, Inc.
// 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.
package benchmark
import "time"
// BenchmarkDir should be set to the benchmark source directory.
var BenchmarkDir = "./"
// Client is a benchmark client that can be used to call a benchmark server.
type Client interface {
// Warmup will create connections to all host:ports the client was created with.
Warmup() error
// RawCall makes an echo call using raw.
RawCall(n int) ([]time.Duration, error)
// ThriftCall makes an echo call using thrift.
ThriftCall(n int) ([]time.Duration, error)
// Close closes the benchmark client.
Close()
}
// inProcClient represents a client that is running in the same process.
// It adds methods to reduce allocations.
type inProcClient interface {
Client
// RawCallBuffer will make n raw calls and store the latencies in the specified buffer.
RawCallBuffer(latencies []time.Duration) error
// ThriftCallBuffer will make n thrift calls and store the latencies in the specified buffer.
ThriftCallBuffer(latencies []time.Duration) error
}
// Server is a benchmark server that can receive requests.
type Server interface {
// HostPort returns the HostPort that the server is listening on.
HostPort() string
// Close closes the benchmark server.
Close()
// RawCalls returns the number of raw calls the server has received.
RawCalls() int
// ThriftCalls returns the number of Thrift calls the server has received.
ThriftCalls() int
}
// Relay represents a relay for benchmarking.
type Relay interface {
// HostPort is the host:port that the relay is listening on.
HostPort() string
// Close clsoes the relay.
Close()
}
================================================
FILE: benchmark/internal_client.go
================================================
// Copyright (c) 2015 Uber Technologies, Inc.
// 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.
package benchmark
import (
"bytes"
"fmt"
"os"
"time"
"github.com/uber/tchannel-go"
"github.com/uber/tchannel-go/raw"
"github.com/uber/tchannel-go/thrift"
gen "github.com/uber/tchannel-go/thrift/gen-go/test"
)
// internalClient represents a benchmark client.
type internalClient struct {
ch *tchannel.Channel
sc *tchannel.SubChannel
tClient gen.TChanSecondService
argStr string
argBytes []byte
checkResult bool
opts *options
}
// NewClient returns a new Client that can make calls to a benchmark server.
func NewClient(hosts []string, optFns ...Option) Client {
opts := getOptions(optFns)
if opts.external {
return newExternalClient(hosts, opts)
}
if opts.numClients > 1 {
return newInternalMultiClient(hosts, opts)
}
return newClient(hosts, opts)
}
func newClient(hosts []string, opts *options) inProcClient {
if opts.external || opts.numClients > 1 {
panic("newClient got options that should be handled by NewClient")
}
if opts.noLibrary {
return newInternalTCPClient(hosts, opts)
}
return newInternalClient(hosts, opts)
}
func newInternalClient(hosts []string, opts *options) inProcClient {
ch, err := tchannel.NewChannel(opts.svcName, &tchannel.ChannelOptions{
Logger: tchannel.NewLevelLogger(tchannel.NewLogger(os.Stderr), tchannel.LogLevelWarn),
})
if err != nil {
panic("failed to create channel: " + err.Error())
}
for _, host := range hosts {
ch.Peers().Add(host)
}
thriftClient := thrift.NewClient(ch, opts.svcName, nil)
client := gen.NewTChanSecondServiceClient(thriftClient)
return &internalClient{
ch: ch,
sc: ch.GetSubChannel(opts.svcName),
tClient: client,
argBytes: getRequestBytes(opts.reqSize),
argStr: getRequestString(opts.reqSize),
opts: opts,
}
}
func (c *internalClient) Warmup() error {
for _, peer := range c.ch.Peers().Copy() {
ctx, cancel := tchannel.NewContext(c.opts.timeout)
_, err := peer.GetConnection(ctx)
cancel()
if err != nil {
return err
}
}
return nil
}
func (c *internalClient) makeCalls(latencies []time.Duration, f func() (time.Duration, error)) error {
for i := range latencies {
var err error
latencies[i], err = f()
if err != nil {
return err
}
}
return nil
}
func (c *internalClient) RawCallBuffer(latencies []time.Duration) error {
return c.makeCalls(latencies, func() (time.Duration, error) {
ctx, cancel := tchannel.NewContext(c.opts.timeout)
defer cancel()
started := time.Now()
rArg2, rArg3, _, err := raw.CallSC(ctx, c.sc, "echo", c.argBytes, c.argBytes)
duration := time.Since(started)
if err != nil {
return 0, err
}
if c.checkResult {
if !bytes.Equal(rArg2, c.argBytes) || !bytes.Equal(rArg3, c.argBytes) {
fmt.Println("Arg2", rArg2, "Expect", c.argBytes)
fmt.Println("Arg3", rArg3, "Expect", c.argBytes)
panic("echo call returned wrong results")
}
}
return duration, nil
})
}
func (c *internalClient) RawCall(n int) ([]time.Duration, error) {
latencies := make([]time.Duration, n)
return latencies, c.RawCallBuffer(latencies)
}
func (c *internalClient) ThriftCallBuffer(latencies []time.Duration) error {
return c.makeCalls(latencies, func() (time.Duration, error) {
ctx, cancel := thrift.NewContext(c.opts.timeout)
defer cancel()
started := time.Now()
res, err := c.tClient.Echo(ctx, c.argStr)
duration := time.Since(started)
if err != nil {
return 0, err
}
if c.checkResult {
if res != c.argStr {
panic("thrift Echo returned wrong result")
}
}
return duration, nil
})
}
func (c *internalClient) ThriftCall(n int) ([]time.Duration, error) {
latencies := make([]time.Duration, n)
return latencies, c.ThriftCallBuffer(latencies)
}
func (c *internalClient) Close() {
c.ch.Close()
}
================================================
FILE: benchmark/internal_multi_client.go
================================================
// Copyright (c) 2015 Uber Technologies, Inc.
// 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.
package benchmark
import (
"time"
"github.com/uber/tchannel-go/testutils"
)
type internalMultiClient struct {
clients []inProcClient
}
func newInternalMultiClient(hosts []string, opts *options) Client {
clients := make([]inProcClient, opts.numClients)
opts.numClients = 1
for i := range clients {
clients[i] = newClient(hosts, opts)
}
return &internalMultiClient{clients: clients}
}
func (c *internalMultiClient) Warmup() error {
for _, c := range c.clients {
if err := c.Warmup(); err != nil {
return err
}
}
return nil
}
func (c *internalMultiClient) Close() {
for _, client := range c.clients {
client.Close()
}
}
func (c *internalMultiClient) RawCall(n int) ([]time.Duration, error) {
return c.makeCalls(n, func(c inProcClient) callFunc {
return c.RawCallBuffer
})
}
func (c *internalMultiClient) ThriftCall(n int) ([]time.Duration, error) {
return c.makeCalls(n, func(c inProcClient) callFunc {
return c.ThriftCallBuffer
})
}
type callFunc func([]time.Duration) error
type clientToCallFunc func(c inProcClient) callFunc
func (c *internalMultiClient) makeCalls(n int, f clientToCallFunc) ([]time.Duration, error) {
buckets := testutils.Buckets(n, len(c.clients))
errCs := make([]chan error, len(c.clients))
var start int
latencies := make([]time.Duration, n)
for i := range c.clients {
calls := buckets[i]
end := start + calls
errCs[i] = c.callUsingClient(latencies[start:end], f(c.clients[i]))
start = end
}
for _, errC := range errCs {
if err := <-errC; err != nil {
return nil, err
}
}
return latencies, nil
}
func (c *internalMultiClient) callUsingClient(latencies []time.Duration, f callFunc) chan error {
errC := make(chan error, 1)
if len(latencies) == 0 {
errC <- nil
return errC
}
go func() {
errC <- f(latencies)
}()
return errC
}
================================================
FILE: benchmark/internal_server.go
================================================
// Copyright (c) 2015 Uber Technologies, Inc.
// 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.
package benchmark
import (
"fmt"
"os"
"github.com/uber/tchannel-go"
"github.com/uber/tchannel-go/hyperbahn"
"github.com/uber/tchannel-go/raw"
"github.com/uber/tchannel-go/thrift"
gen "github.com/uber/tchannel-go/thrift/gen-go/test"
"go.uber.org/atomic"
"golang.org/x/net/context"
)
// internalServer represents a benchmark server.
type internalServer struct {
ch *tchannel.Channel
hc *hyperbahn.Client
opts *options
rawCalls atomic.Int64
thriftCalls atomic.Int64
}
// NewServer returns a new Server that can recieve Thrift calls or raw calls.
func NewServer(optFns ...Option) Server {
opts := getOptions(optFns)
if opts.external {
return newExternalServer(opts)
}
ch, err := tchannel.NewChannel(opts.svcName, &tchannel.ChannelOptions{
Logger: tchannel.NewLevelLogger(tchannel.NewLogger(os.Stderr), tchannel.LogLevelWarn),
})
if err != nil {
panic("failed to create channel: " + err.Error())
}
if err := ch.ListenAndServe("127.0.0.1:0"); err != nil {
panic("failed to listen on port 0: " + err.Error())
}
s := &internalServer{
ch: ch,
opts: opts,
}
tServer := thrift.NewServer(ch)
tServer.Register(gen.NewTChanSecondServiceServer(handler{calls: &s.thriftCalls}))
ch.Register(raw.Wrap(rawHandler{calls: &s.rawCalls}), "echo")
if len(opts.advertiseHosts) > 0 {
if err := s.Advertise(opts.advertiseHosts); err != nil {
panic("failed to advertise: " + err.Error())
}
}
return s
}
// HostPort returns the host:port that the server is listening on.
func (s *internalServer) HostPort() string {
return s.ch.PeerInfo().HostPort
}
// Advertise advertises with Hyperbahn.
func (s *internalServer) Advertise(hyperbahnHosts []string) error {
var err error
config := hyperbahn.Configuration{InitialNodes: hyperbahnHosts}
s.hc, err = hyperbahn.NewClient(s.ch, config, nil)
if err != nil {
panic("failed to setup Hyperbahn client: " + err.Error())
}
return s.hc.Advertise()
}
func (s *internalServer) Close() {
s.ch.Close()
if s.hc != nil {
s.hc.Close()
}
}
func (s *internalServer) RawCalls() int {
return int(s.rawCalls.Load())
}
func (s *internalServer) ThriftCalls() int {
return int(s.thriftCalls.Load())
}
type rawHandler struct {
calls *atomic.Int64
}
func (rawHandler) OnError(ctx context.Context, err error) {
fmt.Println("benchmark.Server error:", err)
}
func (h rawHandler) Handle(ctx context.Context, args *raw.Args) (*raw.Res, error) {
h.calls.Inc()
return &raw.Res{
Arg2: args.Arg2,
Arg3: args.Arg3,
}, nil
}
type handler struct {
calls *atomic.Int64
}
func (h handler) Echo(ctx thrift.Context, arg1 string) (string, error) {
h.calls.Inc()
return arg1, nil
}
================================================
FILE: benchmark/internal_tcp_client.go
================================================
// Copyright (c) 2015 Uber Technologies, Inc.
// 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.
package benchmark
import (
"fmt"
"math/rand"
"net"
"time"
"github.com/uber/tchannel-go"
)
// internalTCPClient represents a TCP client that makes
// TChannel calls using raw TCP packets.
type internalTCPClient struct {
host string
lastID uint32
responseIDs chan uint32
conn net.Conn
frames frames
opts *options
}
func newInternalTCPClient(hosts []string, opts *options) inProcClient {
return &internalTCPClient{
host: hosts[rand.Intn(len(hosts))],
responseIDs: make(chan uint32, 1000),
frames: getRawCallFrames(opts.timeout, opts.svcName, opts.reqSize),
lastID: 1,
opts: opts,
}
}
func (c *internalTCPClient) Warmup() error {
conn, err := net.Dial("tcp", c.host)
if err != nil {
return err
}
c.conn = conn
go c.readConn()
if err := c.frames.writeInitReq(conn); err != nil {
panic(err)
}
return nil
}
func (c *internalTCPClient) readConn() {
defer close(c.responseIDs)
wantFirstID := true
f := tchannel.NewFrame(tchannel.MaxFrameSize)
for {
err := f.ReadIn(c.conn)
if err != nil {
return
}
if wantFirstID {
if f.Header.ID != 1 {
panic(fmt.Errorf("Expected first response ID to be 1, got %v", f.Header.ID))
}
wantFirstID = false
continue
}
c.responseIDs <- f.Header.ID
}
}
type call struct {
id uint32
started time.Time
numFrames int
}
func (c *internalTCPClient) makeCalls(latencies []time.Duration, f func() (call, error)) error {
n := len(latencies)
calls := make(map[uint32]*call, n)
for i := 0; i < n; i++ {
c, err := f()
if err != nil {
return err
}
calls[c.id] = &c
}
timer := time.NewTimer(c.opts.timeout)
// Use the original underlying slice for latencies.
durations := latencies[:0]
for {
if len(calls) == 0 {
return nil
}
timer.Reset(c.opts.timeout)
select {
case id, ok := <-c.responseIDs:
if !ok {
panic("expecting more calls, but connection is closed")
}
call, ok := calls[id]
if !ok {
panic(fmt.Errorf("received unexpected response frame: %v", id))
}
call.numFrames--
if call.numFrames != 0 {
continue
}
durations = append(durations, time.Since(call.started))
delete(calls, id)
case <-timer.C:
return tchannel.ErrTimeout
}
}
}
func (c *internalTCPClient) RawCallBuffer(latencies []time.Duration) error {
return c.makeCalls(latencies, func() (call, error) {
c.lastID++
started := time.Now()
numFrames, err := c.frames.writeCallReq(c.lastID, c.conn)
if err != nil {
return call{}, err
}
return call{c.lastID, started, numFrames}, nil
})
}
func (c *internalTCPClient) RawCall(n int) ([]time.Duration, error) {
latencies := make([]time.Duration, n)
return latencies, c.RawCallBuffer(latencies)
}
func (c *internalTCPClient) ThriftCallBuffer(latencies []time.Duration) error {
panic("not yet implemented")
}
func (c *internalTCPClient) ThriftCall(n int) ([]time.Duration, error) {
panic("not yet implemented")
}
func (c *internalTCPClient) Close() {
c.conn.Close()
}
================================================
FILE: benchmark/internal_tcp_server.go
================================================
// Copyright (c) 2015 Uber Technologies, Inc.
// 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.
package benchmark
import (
"log"
"net"
"github.com/uber/tchannel-go"
"go.uber.org/atomic"
)
// internalTCPServer represents a TCP server responds to TChannel
// calls using raw TCP packets.
type internalTCPServer struct {
frames frames
ln net.Listener
opts *options
rawCalls atomic.Int64
}
func newInternalTCPServer(opts *options) Server {
ln, err := net.Listen("tcp", "127.0.0.1:0")
if err != nil {
panic(err)
}
s := &internalTCPServer{
ln: ln,
frames: getRawCallFrames(opts.timeout, opts.svcName, opts.reqSize),
opts: opts,
}
go s.acceptLoop()
return s
}
func (s *internalTCPServer) acceptLoop() {
for {
conn, err := s.ln.Accept()
if err, ok := err.(net.Error); ok && err.Temporary() {
continue
}
if err != nil {
return
}
go s.handleConn(conn)
}
}
func (s *internalTCPServer) handleConn(conn net.Conn) {
c := make(chan uint32, 1000)
defer close(c)
go s.writeResponses(conn, c)
var lastID uint32
f := tchannel.NewFrame(tchannel.MaxFrameSize)
for {
if err := f.ReadIn(conn); err != nil {
return
}
if f.Header.ID > lastID {
c <- f.Header.ID
lastID = f.Header.ID
}
}
}
func (s *internalTCPServer) writeResponses(conn net.Conn, ids chan uint32) {
frames := s.frames.duplicate()
for id := range ids {
if id == 1 {
if err := frames.writeInitRes(conn); err != nil {
log.Printf("writeInitRes failed: %v", err)
}
continue
}
s.rawCalls.Inc()
if _, err := frames.writeCallRes(id, conn); err != nil {
log.Printf("writeCallRes failed: %v", err)
return
}
}
}
func (s *internalTCPServer) HostPort() string {
return s.ln.Addr().String()
}
func (s *internalTCPServer) RawCalls() int {
return int(s.rawCalls.Load())
}
func (s *internalTCPServer) ThriftCalls() int {
// Server does not support Thrift calls currently.
return 0
}
func (s *internalTCPServer) Close() {
s.ln.Close()
}
================================================
FILE: benchmark/matrix_test.go
================================================
// Copyright (c) 2015 Uber Technologies, Inc.
// 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.
package benchmark
import (
"fmt"
"testing"
"github.com/uber/tchannel-go"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
// combinations will call f with every combination of selecting elements
// from a slice with the specified length.
// e.g. for 2, the callback would be:
// f(false, false)
// f(false, true)
// f(true, false)
// f(true, true)
func combinations(length int, f func([]bool)) {
cur := make([]bool, length)
toGenerate := (1 << uint(length))
f(cur)
for i := 0; i < toGenerate-1; i++ {
var digit int
for digit = length - 1; cur[digit]; digit-- {
cur[digit] = false
}
cur[digit] = true
f(cur)
}
}
func TestCombinations(t *testing.T) {
tests := []struct {
length int
want [][]bool
}{
{
length: 1,
want: [][]bool{{false}, {true}},
},
{
length: 2,
want: [][]bool{{false, false}, {false, true}, {true, false}, {true, true}},
},
}
for _, tt := range tests {
var got [][]bool
recordCombs := func(comb []bool) {
copied := append([]bool(nil), comb...)
got = append(got, copied)
}
combinations(tt.length, recordCombs)
assert.Equal(t, tt.want, got, "Mismatch for combinations of length %v", tt.length)
}
}
func selectOptions(options []Option, toSelect []bool) []Option {
var opts []Option
for i, v := range toSelect {
if v {
opts = append(opts, options[i])
}
}
return opts
}
func combineOpts(base, override []Option) []Option {
resultOpts := append([]Option(nil), base...)
return append(resultOpts, override...)
}
func runSingleTest(t *testing.T, baseOpts, serverOpts, clientOpts []Option) {
serverOpts = combineOpts(baseOpts, serverOpts)
clientOpts = combineOpts(baseOpts, clientOpts)
msgP := fmt.Sprintf("%+v: ", struct {
serverOpts options
clientOpts options
}{*(getOptions(serverOpts)), *(getOptions(clientOpts))})
server := NewServer(serverOpts...)
defer server.Close()
client := NewClient([]string{server.HostPort()}, clientOpts...)
defer client.Close()
require.NoError(t, client.Warmup(), msgP+"Client warmup failed")
durations, err := client.RawCall(0)
require.NoError(t, err, msgP+"Call(0) failed")
assert.Equal(t, 0, len(durations), msgP+"Wrong number of calls")
assert.Equal(t, 0, server.RawCalls(), msgP+"server.RawCalls mismatch")
assert.Equal(t, 0, server.ThriftCalls(), msgP+"server.ThriftCalls mismatch")
expectCalls := 0
for i := 1; i < 10; i *= 2 {
durations, err = client.RawCall(i)
require.NoError(t, err, msgP+"Call(%v) failed", i)
require.Equal(t, i, len(durations), msgP+"Wrong number of calls")
expectCalls += i
require.Equal(t, expectCalls, server.RawCalls(), msgP+"server.RawCalls mismatch")
require.Equal(t, 0, server.ThriftCalls(), msgP+"server.ThriftCalls mismatch")
}
}
func TestServerClientMatrix(t *testing.T) {
tests := [][]Option{
{WithServiceName("other")},
{WithRequestSize(tchannel.MaxFrameSize)},
}
// These options can be independently applied to the server or the client.
independentOpts := []Option{
WithExternalProcess(),
WithNoLibrary(),
}
// These options only apply to the client.
clientOnlyOpts := combineOpts(independentOpts, []Option{
WithNumClients(5),
})
for _, tt := range tests {
combinations(len(independentOpts), func(serverSelect []bool) {
combinations(len(clientOnlyOpts), func(clientSelect []bool) {
serverOpts := selectOptions(independentOpts, serverSelect)
clientOpts := selectOptions(clientOnlyOpts, clientSelect)
runSingleTest(t, tt, serverOpts, clientOpts)
})
})
}
}
================================================
FILE: benchmark/options.go
================================================
// Copyright (c) 2015 Uber Technologies, Inc.
// 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.
package benchmark
import "time"
type options struct {
external bool
svcName string
noLibrary bool
// Following options only make sense for clients.
noChecking bool
timeout time.Duration
reqSize int
numClients int
// noDurations disables printing of durations to stdout.
// This only applies to clients running out-of-process.
noDurations bool
// Following options only make sense for servers.
advertiseHosts []string
}
// Option represents a Benchmark option.
type Option func(*options)
// WithTimeout sets the timeout to use for each call.
func WithTimeout(timeout time.Duration) Option {
return func(opts *options) {
opts.timeout = timeout
}
}
// WithRequestSize sets the request size for each call.
func WithRequestSize(reqSize int) Option {
return func(opts *options) {
opts.reqSize = reqSize
}
}
// WithServiceName sets the service name of the benchmark server.
func WithServiceName(svcName string) Option {
return func(opts *options) {
opts.svcName = svcName
}
}
// WithExternalProcess creates a separate process to host the server/client.
func WithExternalProcess() Option {
return func(opts *options) {
opts.external = true
}
}
// WithNoLibrary uses the fast TCP-template based approach for generating
// TChannel frames rather than the TChannel client library.
func WithNoLibrary() Option {
return func(opts *options) {
opts.noLibrary = true
}
}
// WithNoChecking disables result verification on the client side, which
// may slow down the client (as it compares all request bytes against the
// response bytes).
func WithNoChecking() Option {
return func(opts *options) {
opts.noChecking = true
}
}
// WithNumClients sets the number of concurrent TChannel clients to use
// internally under a single benchmark.Client. This is used to generate
// generate a large amount of traffic, as a single TChannel client will
// not saturate a CPU since it will spend most of the time blocking and
// waiting for the remote side to respond.
func WithNumClients(numClients int) Option {
return func(opts *options) {
opts.numClients = numClients
}
}
// WithNoDurations disables printing of latencies to standard out.
func WithNoDurations() Option {
return func(opts *options) {
opts.noDurations = true
}
}
// WithAdvertiseHosts sets the hosts to advertise with on startup.
func WithAdvertiseHosts(hosts []string) Option {
return func(opts *options) {
opts.advertiseHosts = hosts
}
}
func getOptions(optFns []Option) *options {
opts := &options{
timeout: time.Second,
svcName: "bench-server",
}
for _, opt := range optFns {
opt(opts)
}
return opts
}
================================================
FILE: benchmark/real_relay.go
================================================
// Copyright (c) 2015 Uber Technologies, Inc.
// 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.
package benchmark
import (
"errors"
"os"
"github.com/uber/tchannel-go"
"github.com/uber/tchannel-go/relay"
"github.com/uber/tchannel-go/relay/relaytest"
"go.uber.org/atomic"
)
type fixedHosts struct {
hosts map[string][]string
appends []relay.KeyVal
pickI atomic.Int32
}
func (fh *fixedHosts) Get(cf relay.CallFrame, _ *relay.Conn) (string, error) {
peers := fh.hosts[string(cf.Service())]
if len(peers) == 0 {
return "", errors.New("no peers")
}
for _, kv := range fh.appends {
cf.Arg2Append(kv.Key, kv.Val)
}
pickI := int(fh.pickI.Inc()-1) % len(peers)
return peers[pickI], nil
}
type realRelay struct {
ch *tchannel.Channel
hosts *fixedHosts
}
// NewRealRelay creates a TChannel relay.
func NewRealRelay(services map[string][]string, appends []relay.KeyVal) (Relay, error) {
hosts := &fixedHosts{
hosts: services,
appends: appends,
}
ch, err := tchannel.NewChannel("relay", &tchannel.ChannelOptions{
RelayHost: relaytest.HostFunc(hosts.Get),
Logger: tchannel.NewLevelLogger(tchannel.NewLogger(os.Stderr), tchannel.LogLevelWarn),
})
if err != nil {
return nil, err
}
if err := ch.ListenAndServe("127.0.0.1:0"); err != nil {
return nil, err
}
return &realRelay{
ch: ch,
hosts: hosts,
}, nil
}
func (r *realRelay) HostPort() string {
return r.ch.PeerInfo().HostPort
}
func (r *realRelay) Close() {
r.ch.Close()
}
================================================
FILE: benchmark/req_bytes.go
================================================
// Copyright (c) 2015 Uber Technologies, Inc.
// 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.
package benchmark
func getRequestBytes(n int) []byte {
bs := make([]byte, n)
for i := range bs {
bs[i] = byte(i)
}
return bs
}
func getRequestString(n int) string {
// TODO: we should replace this with base64 once we drop go1.4 support.
chars := []byte("ABCDEFGHIJKLMNOPQRSTUVWXYZabcedefghijklmnopqrstuvwxyz")
bs := make([]byte, n)
for i := range bs {
bs[i] = chars[i%len(chars)]
}
return string(bs)
}
================================================
FILE: benchmark/tcp_bench_test.go
================================================
// Copyright (c) 2015 Uber Technologies, Inc.
// 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.
package benchmark
import (
"io"
"io/ioutil"
"net"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func echoServer(tb testing.TB) net.Listener {
ln, err := net.Listen("tcp", "127.0.0.1:0")
require.NoError(tb, err, "Listen failed")
go func() {
conn, err := ln.Accept()
require.NoError(tb, err, "Accept failed")
// Echo the connection back to itself.
io.Copy(conn, conn)
}()
return ln
}
func benchmarkClient(b *testing.B, dst string, reqSize int) {
req := getRequestBytes(reqSize)
totalExpected := b.N * reqSize
conn, err := net.Dial("tcp", dst)
require.NoError(b, err, "Failed to connect to destination")
defer conn.Close()
readerDone := make(chan struct{})
go func() {
defer close(readerDone)
n, err := io.CopyN(ioutil.Discard, conn, int64(totalExpected))
assert.NoError(b, err, "Expected %v response bytes, got %v", totalExpected, n)
}()
b.SetBytes(int64(reqSize))
for i := 0; i < b.N; i++ {
_, err := conn.Write(req)
require.NoError(b, err, "Write failed")
}
<-readerDone
}
func benchmarkTCPDirect(b *testing.B, reqSize int) {
ln := echoServer(b)
benchmarkClient(b, ln.Addr().String(), reqSize)
}
func BenchmarkTCPDirect100Bytes(b *testing.B) {
benchmarkTCPDirect(b, 100)
}
func BenchmarkTCPDirect1k(b *testing.B) {
benchmarkTCPDirect(b, 1024)
}
func BenchmarkTCPDirect4k(b *testing.B) {
benchmarkTCPDirect(b, 4*1024)
}
func benchmarkTCPRelay(b *testing.B, reqSize int) {
ln := echoServer(b)
relay, err := NewTCPRawRelay([]string{ln.Addr().String()})
require.NoError(b, err, "Relay failed")
defer relay.Close()
benchmarkClient(b, relay.HostPort(), reqSize)
}
func BenchmarkTCPRelay100Bytes(b *testing.B) {
benchmarkTCPRelay(b, 100)
}
func BenchmarkTCPRelay1kBytes(b *testing.B) {
benchmarkTCPRelay(b, 1024)
}
func BenchmarkTCPRelay4k(b *testing.B) {
benchmarkTCPRelay(b, 4*1024)
}
================================================
FILE: benchmark/tcp_frame_relay.go
================================================
// Copyright (c) 2015 Uber Technologies, Inc.
// 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.
package benchmark
import (
"log"
"net"
)
import "github.com/uber/tchannel-go"
type tcpFrameRelay struct {
*tcpRelay
modifier func(bool, *tchannel.Frame) *tchannel.Frame
}
// NewTCPFrameRelay relays frames from one connection to another. It reads
// and writes frames using the TChannel frame functions.
func NewTCPFrameRelay(dests []string, modifier func(bool, *tchannel.Frame) *tchannel.Frame) (Relay, error) {
var err error
r := &tcpFrameRelay{modifier: modifier}
r.tcpRelay, err = newTCPRelay(dests, r.handleConnFrameRelay)
if err != nil {
return nil, err
}
return r, nil
}
func (r *tcpFrameRelay) handleConnFrameRelay(fromClient bool, src, dst net.Conn) {
pool := tchannel.NewSyncFramePool()
frameCh := make(chan *tchannel.Frame, 100)
defer close(frameCh)
go func() {
for f := range frameCh {
if err := f.WriteOut(dst); err != nil {
log.Printf("Failed to write out frame: %v", err)
return
}
pool.Release(f)
}
}()
for {
f := pool.Get()
if err := f.ReadIn(src); err != nil {
return
}
if r.modifier != nil {
f = r.modifier(fromClient, f)
}
select {
case frameCh <- f:
default:
panic("frame buffer full")
}
}
}
================================================
FILE: benchmark/tcp_raw_relay.go
================================================
// Copyright (c) 2015 Uber Technologies, Inc.
// 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.
package benchmark
import (
"io"
"log"
"net"
"go.uber.org/atomic"
)
type tcpRelay struct {
destI atomic.Int32
dests []string
ln net.Listener
handleConn func(fromClient bool, src, dst net.Conn)
}
func newTCPRelay(dests []string, handleConn func(fromClient bool, src, dst net.Conn)) (*tcpRelay, error) {
ln, err := net.Listen("tcp", "127.0.0.1:0")
if err != nil {
return nil, err
}
relay := &tcpRelay{
dests: dests,
ln: ln,
handleConn: handleConn,
}
go relay.acceptLoop()
return relay, nil
}
// NewTCPRawRelay creates a relay that just pipes data from one connection
// to another directly.
func NewTCPRawRelay(dests []string) (Relay, error) {
return newTCPRelay(dests, func(_ bool, src, dst net.Conn) {
io.Copy(src, dst)
})
}
func (r *tcpRelay) acceptLoop() {
for {
conn, err := r.ln.Accept()
if err, ok := err.(net.Error); ok && err.Temporary() {
continue
}
if err != nil {
return
}
go r.handleIncoming(conn)
}
}
func (r *tcpRelay) handleIncoming(src net.Conn) {
defer src.Close()
dst, err := net.Dial("tcp", r.nextDestination())
if err != nil {
log.Printf("Connection failed: %v", err)
return
}
defer dst.Close()
go r.handleConn(true, src, dst)
r.handleConn(false, dst, src)
}
func (r *tcpRelay) nextDestination() string {
i := int(r.destI.Inc()-1) % len(r.dests)
return r.dests[i]
}
func (r *tcpRelay) HostPort() string {
return r.ln.Addr().String()
}
func (r *tcpRelay) Close() {
r.ln.Close()
}
================================================
FILE: calloptions.go
================================================
// Copyright (c) 2015 Uber Technologies, Inc.
// 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.
package tchannel
// Format is the arg scheme used for a specific call.
type Format string
// The list of formats supported by tchannel.
const (
HTTP Format = "http"
JSON Format = "json"
Raw Format = "raw"
Thrift Format = "thrift"
)
func (f Format) String() string {
return string(f)
}
// CallOptions are options for a specific call.
type CallOptions struct {
// Format is arg scheme used for this call, sent in the "as" header.
// This header is only set if the Format is set.
Format Format
// ShardKey determines where this call request belongs, used with ringpop applications.
ShardKey string
// RequestState stores request state across retry attempts.
RequestState *RequestState
// RoutingKey identifies the destined traffic group. Relays may favor the
// routing key over the service name to route the request to a specialized
// traffic group.
RoutingKey string
// RoutingDelegate identifies a traffic group capable of routing a request
// to an instance of the intended service.
RoutingDelegate string
// CallerName defaults to the channel's service name for an outbound call.
// Optionally override this field to support transparent proxying when inbound
// caller names vary across calls.
CallerName string
}
var defaultCallOptions = &CallOptions{}
func (c *CallOptions) setHeaders(headers transportHeaders) {
headers[ArgScheme] = Raw.String()
c.overrideHeaders(headers)
}
// overrideHeaders sets headers if the call options contains non-default values.
func (c *CallOptions) overrideHeaders(headers transportHeaders) {
if c.Format != "" {
headers[ArgScheme] = c.Format.String()
}
if c.ShardKey != "" {
headers[ShardKey] = c.ShardKey
}
if c.RoutingKey != "" {
headers[RoutingKey] = c.RoutingKey
}
if c.RoutingDelegate != "" {
headers[RoutingDelegate] = c.RoutingDelegate
}
if c.CallerName != "" {
headers[CallerName] = c.CallerName
}
}
// setResponseHeaders copies some headers from the incoming call request to the response.
func setResponseHeaders(reqHeaders, respHeaders transportHeaders) {
respHeaders[ArgScheme] = reqHeaders[ArgScheme]
}
================================================
FILE: calloptions_test.go
================================================
// Copyright (c) 2015 Uber Technologies, Inc.
// 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.
package tchannel
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestSetHeaders(t *testing.T) {
tests := []struct {
format Format
routingDelegate string
routingKey string
callerName string
expectedHeaders transportHeaders
}{
{
// When no format is specified, Raw should be used by default.
format: "",
expectedHeaders: transportHeaders{ArgScheme: Raw.String()},
},
{
format: Thrift,
expectedHeaders: transportHeaders{ArgScheme: Thrift.String()},
},
{
callerName: "foo-caller",
expectedHeaders: transportHeaders{
ArgScheme: Raw.String(),
CallerName: "foo-caller",
},
},
{
format: JSON,
routingDelegate: "xpr",
expectedHeaders: transportHeaders{
ArgScheme: JSON.String(),
RoutingDelegate: "xpr",
},
},
{
format: JSON,
routingKey: "canary",
expectedHeaders: transportHeaders{
ArgScheme: JSON.String(),
RoutingKey: "canary",
},
},
}
for _, tt := range tests {
callOpts := &CallOptions{
Format: tt.format,
RoutingDelegate: tt.routingDelegate,
RoutingKey: tt.routingKey,
CallerName: tt.callerName,
}
headers := make(transportHeaders)
callOpts.setHeaders(headers)
assert.Equal(t, tt.expectedHeaders, headers)
}
}
================================================
FILE: channel.go
================================================
// Copyright (c) 2015 Uber Technologies, Inc.
// 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.
package tchannel
import (
"errors"
"fmt"
"net"
"os"
"path/filepath"
"runtime"
"strings"
"sync"
"time"
"github.com/uber/tchannel-go/tnet"
"github.com/opentracing/opentracing-go"
"go.uber.org/atomic"
"golang.org/x/net/context"
)
var (
errAlreadyListening = errors.New("channel already listening")
errInvalidStateForOp = errors.New("channel is in an invalid state for that method")
errMaxIdleTimeNotSet = errors.New("IdleCheckInterval is set but MaxIdleTime is zero")
// ErrNoServiceName is returned when no service name is provided when
// creating a new channel.
ErrNoServiceName = errors.New("no service name provided")
)
const ephemeralHostPort = "0.0.0.0:0"
// ChannelOptions are used to control parameters on a create a TChannel
type ChannelOptions struct {
// Default Connection options
DefaultConnectionOptions ConnectionOptions
// The name of the process, for logging and reporting to peers
ProcessName string
// OnPeerStatusChanged is an optional callback that receives a notification
// whenever the channel establishes a usable connection to a peer, or loses
// a connection to a peer.
OnPeerStatusChanged func(*Peer)
// The logger to use for this channel
Logger Logger
// The host:port selection implementation to use for relaying. This is an
// unstable API - breaking changes are likely.
RelayHost RelayHost
// The list of service names that should be handled locally by this channel.
// This is an unstable API - breaking changes are likely.
RelayLocalHandlers []string
// The maximum allowable timeout for relayed calls (longer timeouts are
// clamped to this value). Passing zero uses the default of 2m.
// This is an unstable API - breaking changes are likely.
RelayMaxTimeout time.Duration
// If the relay needs to connect while processing a frame, this specifies
// the max connection timeout used.
RelayMaxConnectionTimeout time.Duration
// RelayMaxTombs is the maximum number of timed-out calls that the relay
// will keep track of per-connection to avoid spurious logs
// for late-arriving frames.
// This is an unstable API - breaking changes are likely.
RelayMaxTombs uint64
// RelayTimerVerification will disable pooling of relay timers, and instead
// verify that timers are not used once they are released.
// This is an unstable API - breaking changes are likely.
RelayTimerVerification bool
// The reporter to use for reporting stats for this channel.
StatsReporter StatsReporter
// TimeNow is a variable for overriding time.Now in unit tests.
// Note: This is not a stable part of the API and may change.
TimeNow func() time.Time
// TimeTicker is a variable for overriding time.Ticker in unit tests.
// Note: This is not a stable part of the API and may change.
TimeTicker func(d time.Duration) *time.Ticker
// MaxIdleTime controls how long we allow an idle connection to exist
// before tearing it down. Must be set to non-zero if IdleCheckInterval
// is set.
MaxIdleTime time.Duration
// IdleCheckInterval controls how often the channel runs a sweep over
// all active connections to see if they can be dropped. Connections that
// are idle for longer than MaxIdleTime are disconnected. If this is set to
// zero (the default), idle checking is disabled.
IdleCheckInterval time.Duration
// Tracer is an OpenTracing Tracer used to manage distributed tracing spans.
// If not set, opentracing.GlobalTracer() is used.
Tracer opentracing.Tracer
// Handler is an alternate handler for all inbound requests, overriding the
// default handler that delegates to a subchannel.
Handler Handler
// SkipHandlerMethods allow users to configure TChannel server such that
// requests with specified methods can be ignored by the above passed-in handler
// and handled natively by TChannel.
// Requests with other methods will be handled by passed-in handler.
// Methods should be in the format of Service::Method.
// This is useful for the gradual migration purpose.
SkipHandlerMethods []string
// Dialer is optional factory method which can be used for overriding
// outbound connections for things like TLS handshake
Dialer func(ctx context.Context, network, hostPort string) (net.Conn, error)
// ConnContext runs when a connection is established, which updates
// the per-connection base context. This context is used as the parent context
// for incoming calls.
ConnContext func(ctx context.Context, conn net.Conn) context.Context
}
// ChannelState is the state of a channel.
type ChannelState int
const (
// ChannelClient is a channel that can be used as a client.
ChannelClient ChannelState = iota + 1
// ChannelListening is a channel that is listening for new connnections.
ChannelListening
// ChannelStartClose is a channel that has received a Close request.
// The channel is no longer listening, and all new incoming connections are rejected.
ChannelStartClose
// ChannelInboundClosed is a channel that has drained all incoming connections, but may
// have outgoing connections. All incoming calls and new outgoing calls are rejected.
ChannelInboundClosed
// ChannelClosed is a channel that has closed completely.
ChannelClosed
)
//go:generate stringer -type=ChannelState
// A Channel is a bi-directional connection to the peering and routing network.
// Applications can use a Channel to make service calls to remote peers via
// BeginCall, or to listen for incoming calls from peers. Applications that
// want to receive requests should call one of Serve or ListenAndServe
// TODO(prashant): Shutdown all subchannels + peers when channel is closed.
type Channel struct {
channelConnectionCommon
chID uint32
createdStack string
commonStatsTags map[string]string
connectionOptions ConnectionOptions
peers *PeerList
relayHost RelayHost
relayMaxTimeout time.Duration
relayMaxConnTimeout time.Duration
relayMaxTombs uint64
relayTimerVerify bool
internalHandlers *handlerMap
handler Handler
onPeerStatusChanged func(*Peer)
dialer func(ctx context.Context, hostPort string) (net.Conn, error)
connContext func(ctx context.Context, conn net.Conn) context.Context
closed chan struct{}
// mutable contains all the members of Channel which are mutable.
mutable struct {
sync.RWMutex // protects members of the mutable struct.
state ChannelState
peerInfo LocalPeerInfo // May be ephemeral if this is a client only channel
l net.Listener // May be nil if this is a client only channel
idleSweep *idleSweep
conns map[uint32]*Connection
}
}
// channelConnectionCommon is the list of common objects that both use
// and can be copied directly from the channel to the connection.
type channelConnectionCommon struct {
log Logger
relayLocal map[string]struct{}
statsReporter StatsReporter
tracer opentracing.Tracer
subChannels *subChannelMap
timeNow func() time.Time
timeTicker func(time.Duration) *time.Ticker
}
// _nextChID is used to allocate unique IDs to every channel for debugging purposes.
var _nextChID atomic.Uint32
// Tracer returns the OpenTracing Tracer for this channel. If no tracer was provided
// in the configuration, returns opentracing.GlobalTracer(). Note that this approach
// allows opentracing.GlobalTracer() to be initialized _after_ the channel is created.
func (ccc channelConnectionCommon) Tracer() opentracing.Tracer {
if ccc.tracer != nil {
return ccc.tracer
}
return opentracing.GlobalTracer()
}
// NewChannel creates a new Channel. The new channel can be used to send outbound requests
// to peers, but will not listen or handling incoming requests until one of ListenAndServe
// or Serve is called. The local service name should be passed to serviceName.
func NewChannel(serviceName string, opts *ChannelOptions) (*Channel, error) {
if serviceName == "" {
return nil, ErrNoServiceName
}
if opts == nil {
opts = &ChannelOptions{}
}
processName := opts.ProcessName
if processName == "" {
processName = fmt.Sprintf("%s[%d]", filepath.Base(os.Args[0]), os.Getpid())
}
logger := opts.Logger
if logger == nil {
logger = NullLogger
}
statsReporter := opts.StatsReporter
if statsReporter == nil {
statsReporter = NullStatsReporter
}
timeNow := opts.TimeNow
if timeNow == nil {
timeNow = time.Now
}
timeTicker := opts.TimeTicker
if timeTicker == nil {
timeTicker = time.NewTicker
}
chID := _nextChID.Inc()
logger = logger.WithFields(
LogField{"serviceName", serviceName},
LogField{"process", processName},
LogField{"chID", chID},
)
if err := opts.validateIdleCheck(); err != nil {
return nil, err
}
// Default to dialContext if dialer is not passed in as an option
dialCtx := dialContext
if opts.Dialer != nil {
dialCtx = func(ctx context.Context, hostPort string) (net.Conn, error) {
return opts.Dialer(ctx, "tcp", hostPort)
}
}
if opts.ConnContext == nil {
opts.ConnContext = func(ctx context.Context, conn net.Conn) context.Context {
return ctx
}
}
ch := &Channel{
channelConnectionCommon: channelConnectionCommon{
log: logger,
relayLocal: toStringSet(opts.RelayLocalHandlers),
statsReporter: statsReporter,
subChannels: &subChannelMap{},
timeNow: timeNow,
timeTicker: timeTicker,
tracer: opts.Tracer,
},
chID: chID,
connectionOptions: opts.DefaultConnectionOptions.withDefaults(),
relayHost: opts.RelayHost,
relayMaxTimeout: validateRelayMaxTimeout(opts.RelayMaxTimeout, logger),
relayMaxConnTimeout: opts.RelayMaxConnectionTimeout,
relayMaxTombs: opts.RelayMaxTombs,
relayTimerVerify: opts.RelayTimerVerification,
dialer: dialCtx,
connContext: opts.ConnContext,
closed: make(chan struct{}),
}
ch.peers = newRootPeerList(ch, opts.OnPeerStatusChanged).newChild()
switch {
case len(opts.SkipHandlerMethods) > 0 && opts.Handler != nil:
sm, err := toServiceMethodSet(opts.SkipHandlerMethods)
if err != nil {
return nil, err
}
ch.handler = userHandlerWithSkip{
localHandler: channelHandler{ch},
ignoreUserHandler: sm,
userHandler: opts.Handler,
}
case opts.Handler != nil:
ch.handler = opts.Handler
default:
ch.handler = channelHandler{ch}
}
ch.mutable.peerInfo = LocalPeerInfo{
PeerInfo: PeerInfo{
ProcessName: processName,
HostPort: ephemeralHostPort,
IsEphemeral: true,
Version: PeerVersion{
Language: "go",
LanguageVersion: strings.TrimPrefix(runtime.Version(), "go"),
TChannelVersion: VersionInfo,
},
},
ServiceName: serviceName,
}
ch.mutable.state = ChannelClient
ch.mutable.conns = make(map[uint32]*Connection)
ch.createCommonStats()
ch.internalHandlers = ch.createInternalHandlers()
registerNewChannel(ch)
if opts.RelayHost != nil {
opts.RelayHost.SetChannel(ch)
}
// Start the idle connection timer.
ch.mutable.idleSweep = startIdleSweep(ch, opts)
return ch, nil
}
// ConnectionOptions returns the channel's connection options.
func (ch *Channel) ConnectionOptions() *ConnectionOptions {
return &ch.connectionOptions
}
// Serve serves incoming requests using the provided listener.
// The local peer info is set synchronously, but the actual socket listening is done in
// a separate goroutine.
func (ch *Channel) Serve(l net.Listener) error {
mutable := &ch.mutable
mutable.Lock()
defer mutable.Unlock()
if mutable.l != nil {
return errAlreadyListening
}
mutable.l = tnet.Wrap(l)
if mutable.state != ChannelClient {
return errInvalidStateForOp
}
mutable.state = ChannelListening
mutable.peerInfo.HostPort = l.Addr().String()
mutable.peerInfo.IsEphemeral = false
ch.log = ch.log.WithFields(LogField{"hostPort", mutable.peerInfo.HostPort})
ch.log.Info("Channel is listening.")
go ch.serve()
return nil
}
// ListenAndServe listens on the given address and serves incoming requests.
// The port may be 0, in which case the channel will use an OS assigned port
// This method does not block as the handling of connections is done in a goroutine.
func (ch *Channel) ListenAndServe(hostPort string) error {
mutable := &ch.mutable
mutable.RLock()
if mutable.l != nil {
mutable.RUnlock()
return errAlreadyListening
}
l, err := net.Listen("tcp", hostPort)
if err != nil {
mutable.RUnlock()
return err
}
mutable.RUnlock()
return ch.Serve(l)
}
// Registrar is the base interface for registering handlers on either the base
// Channel or the SubChannel
type Registrar interface {
// ServiceName returns the service name that this Registrar is for.
ServiceName() string
// Register registers a handler for ServiceName and the given method.
Register(h Handler, methodName string)
// Logger returns the logger for this Registrar.
Logger() Logger
// StatsReporter returns the stats reporter for this Registrar
StatsReporter() StatsReporter
// StatsTags returns the tags that should be used.
StatsTags() map[string]string
// Peers returns the peer list for this Registrar.
Peers() *PeerList
}
// Register registers a handler for a method.
//
// The handler is registered with the service name used when the Channel was
// created. To register a handler with a different service name, obtain a
// SubChannel for that service with GetSubChannel, and Register a handler
// under that. You may also use SetHandler on a SubChannel to set up a
// catch-all Handler for that service. See the docs for SetHandler for more
// information.
//
// Register panics if the channel was constructed with an alternate root
// handler that does not support Register.
func (ch *Channel) Register(h Handler, methodName string) {
r, ok := ch.handler.(registrar)
if !ok {
panic("can't register handler when channel configured with alternate root handler without Register method")
}
r.Register(h, methodName)
}
// PeerInfo returns the current peer info for the channel
func (ch *Channel) PeerInfo() LocalPeerInfo {
ch.mutable.RLock()
peerInfo := ch.mutable.peerInfo
ch.mutable.RUnlock()
return peerInfo
}
func (ch *Channel) createCommonStats() {
ch.commonStatsTags = map[string]string{
"app": ch.mutable.peerInfo.ProcessName,
"service": ch.mutable.peerInfo.ServiceName,
}
host, err := os.Hostname()
if err != nil {
ch.log.WithFields(ErrField(err)).Info("Channel creation failed to get host.")
return
}
ch.commonStatsTags["host"] = host
// TODO(prashant): Allow user to pass extra tags (such as cluster, version).
}
// GetSubChannel returns a SubChannel for the given service name. If the subchannel does not
// exist, it is created.
func (ch *Channel) GetSubChannel(serviceName string, opts ...SubChannelOption) *SubChannel {
sub, added := ch.subChannels.getOrAdd(serviceName, ch)
if added {
for _, opt := range opts {
opt(sub)
}
}
return sub
}
// Peers returns the PeerList for the channel.
func (ch *Channel) Peers() *PeerList {
return ch.peers
}
// RootPeers returns the root PeerList for the channel, which is the sole place
// new Peers are created. All children of the root list (including ch.Peers())
// automatically re-use peers from the root list and create new peers in the
// root list.
func (ch *Channel) RootPeers() *RootPeerList {
return ch.peers.parent
}
// BeginCall starts a new call to a remote peer, returning an OutboundCall that can
// be used to write the arguments of the call.
func (ch *Channel) BeginCall(ctx context.Context, hostPort, serviceName, methodName string, callOptions *CallOptions) (*OutboundCall, error) {
p := ch.RootPeers().GetOrAdd(hostPort)
return p.BeginCall(ctx, serviceName, methodName, callOptions)
}
// serve runs the listener to accept and manage new incoming connections, blocking
// until the channel is closed.
func (ch *Channel) serve() {
acceptBackoff := 0 * time.Millisecond
for {
netConn, err := ch.mutable.l.Accept()
if err != nil {
// Backoff from new accepts if this is a temporary error
if ne, ok := err.(net.Error); ok && ne.Temporary() {
if acceptBackoff == 0 {
acceptBackoff = 5 * time.Millisecond
} else {
acceptBackoff *= 2
}
if max := 1 * time.Second; acceptBackoff > max {
acceptBackoff = max
}
ch.log.WithFields(
ErrField(err),
LogField{"backoff", acceptBackoff},
).Warn("Accept error, will wait and retry.")
time.Sleep(acceptBackoff)
continue
} else {
// Only log an error if this didn't happen due to a Close.
if ch.State() >= ChannelStartClose {
return
}
ch.log.WithFields(ErrField(err)).Fatal("Unrecoverable accept error, closing server.")
return
}
}
acceptBackoff = 0
// Perform the connection handshake in a background goroutine.
go func() {
// Register the connection in the peer once the channel is set up.
events := connectionEvents{
OnActive: ch.inboundConnectionActive,
OnCloseStateChange: ch.connectionCloseStateChange,
OnExchangeUpdated: ch.exchangeUpdated,
}
if _, err := ch.inboundHandshake(context.Background(), netConn, events); err != nil {
netConn.Close()
}
}()
}
}
// Ping sends a ping message to the given hostPort and waits for a response.
func (ch *Channel) Ping(ctx context.Context, hostPort string) error {
peer := ch.RootPeers().GetOrAdd(hostPort)
conn, err := peer.GetConnection(ctx)
if err != nil {
return err
}
return conn.ping(ctx)
}
// Logger returns the logger for this channel.
func (ch *Channel) Logger() Logger {
return ch.log
}
// StatsReporter returns the stats reporter for this channel.
func (ch *Channel) StatsReporter() StatsReporter {
return ch.statsReporter
}
// StatsTags returns the common tags that should be used when reporting stats.
// It returns a new map for each call.
func (ch *Channel) StatsTags() map[string]string {
m := make(map[string]string)
for k, v := range ch.commonStatsTags {
m[k] = v
}
return m
}
// ServiceName returns the serviceName that this channel was created for.
func (ch *Channel) ServiceName() string {
return ch.PeerInfo().ServiceName
}
// Connect creates a new outbound connection to hostPort.
func (ch *Channel) Connect(ctx context.Context, hostPort string) (*Connection, error) {
switch state := ch.State(); state {
case ChannelClient, ChannelListening:
break
default:
ch.log.Debugf("Connect rejecting new connection as state is %v", state)
return nil, errInvalidStateForOp
}
// The context timeout applies to the whole call, but users may want a lower
// connect timeout (e.g. for streams).
if params := getTChannelParams(ctx); params != nil && params.connectTimeout > 0 {
var cancel context.CancelFunc
ctx, cancel = context.WithTimeout(ctx, params.connectTimeout)
defer cancel()
}
events := connectionEvents{
OnActive: ch.outboundConnectionActive,
OnCloseStateChange: ch.connectionCloseStateChange,
OnExchangeUpdated: ch.exchangeUpdated,
}
if err := ctx.Err(); err != nil {
return nil, GetContextError(err)
}
timeout := getTimeout(ctx)
tcpConn, err := ch.dialer(ctx, hostPort)
if err != nil {
if ne, ok := err.(net.Error); ok && ne.Timeout() {
ch.log.WithFields(
LogField{"remoteHostPort", hostPort},
LogField{"timeout", timeout},
).Info("Outbound net.Dial timed out.")
err = ErrTimeout
} else if ctx.Err() == context.Canceled {
ch.log.WithFields(
LogField{"remoteHostPort", hostPort},
).Info("Outbound net.Dial was cancelled.")
err = GetContextError(ErrRequestCancelled)
} else {
ch.log.WithFields(
ErrField(err),
LogField{"remoteHostPort", hostPort},
).Info("Outbound net.Dial failed.")
}
return nil, err
}
conn, err := ch.outboundHandshake(ctx, tcpConn, hostPort, events)
if conn != nil {
// It's possible that the connection we just created responds with a host:port
// that is not what we tried to connect to. E.g., we may have connected to
// 127.0.0.1:1234, but the returned host:port may be 10.0.0.1:1234.
// In this case, the connection won't be added to 127.0.0.1:1234 peer
// and so future calls to that peer may end up creating new connections. To
// avoid this issue, and to avoid clients being aware of any TCP relays, we
// add the connection to the intended peer.
if hostPort != conn.remotePeerInfo.HostPort {
conn.log.Debugf("Outbound connection host:port mismatch, adding to peer %v", conn.remotePeerInfo.HostPort)
ch.addConnectionToPeer(hostPort, conn, outbound)
}
}
return conn, err
}
// exchangeUpdated updates the peer heap.
func (ch *Channel) exchangeUpdated(c *Connection) {
if c.remotePeerInfo.HostPort == "" {
// Hostport is unknown until we get init resp.
return
}
p, ok := ch.RootPeers().Get(c.remotePeerInfo.HostPort)
if !ok {
return
}
ch.updatePeer(p)
}
// updatePeer updates the score of the peer and update it's position in heap as well.
func (ch *Channel) updatePeer(p *Peer) {
ch.peers.onPeerChange(p)
ch.subChannels.updatePeer(p)
p.callOnUpdateComplete()
}
// addConnection adds the connection to the channel's list of connection
// if the channel is in a valid state to accept this connection. It returns
// whether the connection was added.
func (ch *Channel) addConnection(c *Connection, direction connectionDirection) bool {
ch.mutable.Lock()
defer ch.mutable.Unlock()
if c.readState() != connectionActive {
return false
}
switch state := ch.mutable.state; state {
case ChannelClient, ChannelListening:
break
default:
return false
}
ch.mutable.conns[c.connID] = c
return true
}
func (ch *Channel) connectionActive(c *Connection, direction connectionDirection) {
c.log.Debugf("New active %v connection for peer %v", direction, c.remotePeerInfo.HostPort)
if added := ch.addConnection(c, direction); !added {
// The channel isn't in a valid state to accept this connection, close the connection.
c.close(LogField{"reason", "new active connection on closing channel"})
return
}
ch.addConnectionToPeer(c.remotePeerInfo.HostPort, c, direction)
}
func (ch *Channel) addConnectionToPeer(hostPort string, c *Connection, direction connectionDirection) {
p := ch.RootPeers().GetOrAdd(hostPort)
if err := p.addConnection(c, direction); err != nil {
c.log.WithFields(
LogField{"remoteHostPort", c.remotePeerInfo.HostPort},
LogField{"direction", direction},
ErrField(err),
).Warn("Failed to add connection to peer.")
}
ch.updatePeer(p)
}
func (ch *Channel) inboundConnectionActive(c *Connection) {
ch.connectionActive(c, inbound)
}
func (ch *Channel) outboundConnectionActive(c *Connection) {
ch.connectionActive(c, outbound)
}
// removeClosedConn removes a connection if it's closed.
// Until a connection is fully closed, the channel must keep track of it.
func (ch *Channel) removeClosedConn(c *Connection) {
if c.readState() != connectionClosed {
return
}
ch.mutable.Lock()
delete(ch.mutable.conns, c.connID)
ch.mutable.Unlock()
}
func (ch *Channel) getMinConnectionState() connectionState {
minState := connectionClosed
for _, c := range ch.mutable.conns {
if s := c.readState(); s < minState {
minState = s
}
}
return minState
}
// connectionCloseStateChange is called when a connection's close state changes.
func (ch *Channel) connectionCloseStateChange(c *Connection) {
ch.removeClosedConn(c)
if peer, ok := ch.RootPeers().Get(c.remotePeerInfo.HostPort); ok {
peer.connectionCloseStateChange(c)
ch.updatePeer(peer)
}
if c.outboundHP != "" && c.outboundHP != c.remotePeerInfo.HostPort {
// Outbound connections may be in multiple peers.
if peer, ok := ch.RootPeers().Get(c.outboundHP); ok {
peer.connectionCloseStateChange(c)
ch.updatePeer(peer)
}
}
chState := ch.State()
if chState != ChannelStartClose && chState != ChannelInboundClosed {
return
}
ch.mutable.RLock()
minState := ch.getMinConnectionState()
ch.mutable.RUnlock()
var updateTo ChannelState
if minState >= connectionClosed {
updateTo = ChannelClosed
} else if minState >= connectionInboundClosed && chState == ChannelStartClose {
updateTo = ChannelInboundClosed
}
var updatedToState ChannelState
if updateTo > 0 {
ch.mutable.Lock()
// Recheck the state as it's possible another goroutine changed the state
// from what we expected, and so we might make a stale change.
if ch.mutable.state == chState {
ch.mutable.state = updateTo
updatedToState = updateTo
}
ch.mutable.Unlock()
chState = updateTo
}
c.log.Debugf("ConnectionCloseStateChange channel state = %v connection minState = %v",
chState, minState)
if updatedToState == ChannelClosed {
ch.onClosed()
}
}
func (ch *Channel) onClosed() {
removeClosedChannel(ch)
close(ch.closed)
ch.log.Infof("Channel closed.")
}
// Closed returns whether this channel has been closed with .Close()
func (ch *Channel) Closed() bool {
return ch.State() == ChannelClosed
}
// ClosedChan returns a channel that will close when the Channel has completely
// closed.
func (ch *Channel) ClosedChan() <-chan struct{} {
return ch.closed
}
// State returns the current channel state.
func (ch *Channel) State() ChannelState {
ch.mutable.RLock()
state := ch.mutable.state
ch.mutable.RUnlock()
return state
}
// Close starts a graceful Close for the channel. This does not happen immediately:
// 1. This call closes the Listener and starts closing connections.
// 2. When all incoming connections are drained, the connection blocks new outgoing calls.
// 3. When all connections are drained, the channel's state is updated to Closed.
func (ch *Channel) Close() {
ch.Logger().Info("Channel.Close called.")
var connections []*Connection
var channelClosed bool
func() {
ch.mutable.Lock()
defer ch.mutable.Unlock()
if ch.mutable.state == ChannelClosed {
ch.Logger().Info("Channel already closed, skipping additional Close() calls")
return
}
if ch.mutable.l != nil {
ch.mutable.l.Close()
}
// Stop the idle connections timer.
ch.mutable.idleSweep.Stop()
ch.mutable.state = ChannelStartClose
if len(ch.mutable.conns) == 0 {
ch.mutable.state = ChannelClosed
channelClosed = true
}
for _, c := range ch.mutable.conns {
connections = append(connections, c)
}
}()
for _, c := range connections {
c.close(LogField{"reason", "channel closing"})
}
if channelClosed {
ch.onClosed()
}
}
// RelayHost returns the channel's RelayHost, if any.
func (ch *Channel) RelayHost() RelayHost {
return ch.relayHost
}
func (o *ChannelOptions) validateIdleCheck() error {
if o.IdleCheckInterval > 0 && o.MaxIdleTime <= 0 {
return errMaxIdleTimeNotSet
}
return nil
}
func toStringSet(ss []string) map[string]struct{} {
set := make(map[string]struct{}, len(ss))
for _, s := range ss {
set[s] = struct{}{}
}
return set
}
// take a list of service::method formatted string and make
// the map[service::method]struct{} set
func toServiceMethodSet(sms []string) (map[string]struct{}, error) {
set := map[string]struct{}{}
for _, sm := range sms {
if len(strings.Split(sm, "::")) != 2 {
return nil, fmt.Errorf("each %q value should be of service::Method format but got %q", "SkipHandlerMethods", sm)
}
set[sm] = struct{}{}
}
return set, nil
}
================================================
FILE: channel_test.go
================================================
// Copyright (c) 2015 Uber Technologies, Inc.
// 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.
package tchannel
import (
"io/ioutil"
"math"
"os"
"runtime"
"strings"
"testing"
"time"
"github.com/opentracing/opentracing-go"
"github.com/opentracing/opentracing-go/mocktracer"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func toMap(fields LogFields) map[string]interface{} {
m := make(map[string]interface{})
for _, f := range fields {
m[f.Key] = f.Value
}
return m
}
func TestNewChannel(t *testing.T) {
ch, err := NewChannel("svc", &ChannelOptions{
ProcessName: "pname",
})
require.NoError(t, err, "NewChannel failed")
assert.Equal(t, LocalPeerInfo{
ServiceName: "svc",
PeerInfo: PeerInfo{
ProcessName: "pname",
HostPort: ephemeralHostPort,
IsEphemeral: true,
Version: PeerVersion{
Language: "go",
LanguageVersion: strings.TrimPrefix(runtime.Version(), "go"),
TChannelVersion: VersionInfo,
},
},
}, ch.PeerInfo(), "Wrong local peer info")
}
func TestLoggers(t *testing.T) {
ch, err := NewChannel("svc", &ChannelOptions{
Logger: NewLogger(ioutil.Discard),
})
require.NoError(t, err, "NewChannel failed")
defer ch.Close()
peerInfo := ch.PeerInfo()
fields := toMap(ch.Logger().Fields())
assert.Equal(t, peerInfo.ServiceName, fields["serviceName"])
sc := ch.GetSubChannel("subch")
fields = toMap(sc.Logger().Fields())
assert.Equal(t, peerInfo.ServiceName, fields["serviceName"])
assert.Equal(t, "subch", fields["subchannel"])
}
func TestStats(t *testing.T) {
ch, err := NewChannel("svc", &ChannelOptions{
Logger: NewLogger(ioutil.Discard),
})
require.NoError(t, err, "NewChannel failed")
defer ch.Close()
hostname, err := os.Hostname()
require.NoError(t, err, "Hostname failed")
peerInfo := ch.PeerInfo()
tags := ch.StatsTags()
assert.NotNil(t, ch.StatsReporter(), "StatsReporter missing")
assert.Equal(t, peerInfo.ProcessName, tags["app"], "app tag")
assert.Equal(t, peerInfo.ServiceName, tags["service"], "service tag")
assert.Equal(t, hostname, tags["host"], "hostname tag")
sc := ch.GetSubChannel("subch")
subTags := sc.StatsTags()
assert.NotNil(t, sc.StatsReporter(), "StatsReporter missing")
for k, v := range tags {
assert.Equal(t, v, subTags[k], "subchannel missing tag %v", k)
}
assert.Equal(t, "subch", subTags["subchannel"], "subchannel tag missing")
}
func TestRelayMaxTTL(t *testing.T) {
tests := []struct {
max time.Duration
expected time.Duration
}{
{time.Second, time.Second},
{-time.Second, _defaultRelayMaxTimeout},
{0, _defaultRelayMaxTimeout},
{time.Microsecond, _defaultRelayMaxTimeout},
{math.MaxUint32 * time.Millisecond, math.MaxUint32 * time.Millisecond},
{(math.MaxUint32 + 1) * time.Millisecond, _defaultRelayMaxTimeout},
}
for _, tt := range tests {
ch, err := NewChannel("svc", &ChannelOptions{
RelayMaxTimeout: tt.max,
})
assert.NoError(t, err, "Unexpected error when creating channel.")
assert.Equal(t, ch.relayMaxTimeout, tt.expected, "Unexpected max timeout on channel.")
}
}
func TestIsolatedSubChannelsDontSharePeers(t *testing.T) {
ch, err := NewChannel("svc", &ChannelOptions{
Logger: NewLogger(ioutil.Discard),
})
require.NoError(t, err, "NewChannel failed")
defer ch.Close()
sub := ch.GetSubChannel("svc-ringpop")
if ch.peers != sub.peers {
t.Log("Channel and subchannel don't share the same peer list.")
t.Fail()
}
isolatedSub := ch.GetSubChannel("svc-shy-ringpop", Isolated)
if ch.peers == isolatedSub.peers {
t.Log("Channel and isolated subchannel share the same peer list.")
t.Fail()
}
// Nobody knows about the peer.
assert.Nil(t, ch.peers.peersByHostPort["127.0.0.1:3000"])
assert.Nil(t, sub.peers.peersByHostPort["127.0.0.1:3000"])
assert.Nil(t, isolatedSub.peers.peersByHostPort["127.0.0.1:3000"])
// Uses of the parent channel should be reflected in the subchannel, but
// not the isolated subchannel.
ch.Peers().Add("127.0.0.1:3000")
assert.NotNil(t, ch.peers.peersByHostPort["127.0.0.1:3000"])
assert.NotNil(t, sub.peers.peersByHostPort["127.0.0.1:3000"])
assert.Nil(t, isolatedSub.peers.peersByHostPort["127.0.0.1:3000"])
}
func TestChannelTracerMethod(t *testing.T) {
mockTracer := mocktracer.New()
ch, err := NewChannel("svc", &ChannelOptions{
Tracer: mockTracer,
})
require.NoError(t, err)
defer ch.Close()
assert.Equal(t, mockTracer, ch.Tracer(), "expecting tracer passed at initialization")
ch, err = NewChannel("svc", &ChannelOptions{})
require.NoError(t, err)
defer ch.Close()
assert.EqualValues(t, opentracing.GlobalTracer(), ch.Tracer(), "expecting default tracer")
// because ch.Tracer() function is doing dynamic lookup, we can change global tracer
origTracer := opentracing.GlobalTracer()
defer opentracing.InitGlobalTracer(origTracer)
opentracing.InitGlobalTracer(mockTracer)
assert.Equal(t, mockTracer, ch.Tracer(), "expecting tracer set as global tracer")
}
func TestToServiceMethodSet(t *testing.T) {
tests := []struct {
desc string
sms []string
want map[string]struct{}
wantErr string
}{
{
desc: "single service, single method",
sms: []string{"service::Method"},
want: map[string]struct{}{
"service::Method": struct{}{},
},
},
{
desc: "single service, multiple methods",
sms: []string{"service::Method1", "service::Method2", "service::Method3"},
want: map[string]struct{}{
"service::Method1": struct{}{},
"service::Method2": struct{}{},
"service::Method3": struct{}{},
},
},
{
desc: "invalid input",
sms: []string{"notDelimitedByDoubleColons"},
wantErr: `each "SkipHandlerMethods" value should be of service::Method format but got "notDelimitedByDoubleColons"`,
},
}
for _, tt := range tests {
t.Run(tt.desc, func(t *testing.T) {
r, err := toServiceMethodSet(tt.sms)
if tt.wantErr != "" {
assert.EqualError(t, err, tt.wantErr)
return
}
assert.Equal(t, tt.want, r)
})
}
}
================================================
FILE: channel_utils_test.go
================================================
// Copyright (c) 2015 Uber Technologies, Inc.
// 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.
package tchannel_test
import (
"testing"
. "github.com/uber/tchannel-go"
"github.com/uber/tchannel-go/testutils"
)
// NewServer creates a new server and returns the channel, service name, and host port.
func NewServer(t testing.TB, opts *testutils.ChannelOpts) (*Channel, string, string) {
ch := testutils.NewServer(t, opts)
peerInfo := ch.PeerInfo()
return ch, peerInfo.ServiceName, peerInfo.HostPort
}
================================================
FILE: channelstate_string.go
================================================
// generated by stringer -type=ChannelState; DO NOT EDIT
package tchannel
import "fmt"
const _ChannelState_name = "ChannelClientChannelListeningChannelStartCloseChannelInboundClosedChannelClosed"
var _ChannelState_index = [...]uint8{0, 13, 29, 46, 66, 79}
func (i ChannelState) String() string {
i -= 1
if i < 0 || i+1 >= ChannelState(len(_ChannelState_index)) {
return fmt.Sprintf("ChannelState(%d)", i+1)
}
return _ChannelState_name[_ChannelState_index[i]:_ChannelState_index[i+1]]
}
================================================
FILE: checked_frame_pool.go
================================================
package tchannel
import (
"fmt"
"runtime"
"sync"
)
// CheckedFramePoolForTest tracks gets and releases of frames, verifies that
// frames aren't double released, and can be used to check for frame leaks.
// As such, it is not performant, nor is it even a proper frame pool.
//
// It is intended to be used ONLY in tests.
type CheckedFramePoolForTest struct {
mu sync.Mutex
allocations map[*Frame]string
badRelease []string
}
// NewCheckedFramePoolForTest initializes a new CheckedFramePoolForTest.
func NewCheckedFramePoolForTest() *CheckedFramePoolForTest {
return &CheckedFramePoolForTest{
allocations: make(map[*Frame]string),
}
}
// Get implements FramePool
func (p *CheckedFramePoolForTest) Get() *Frame {
p.mu.Lock()
defer p.mu.Unlock()
frame := NewFrame(MaxFramePayloadSize)
p.allocations[frame] = recordStack()
return frame
}
// Release implements FramePool
func (p *CheckedFramePoolForTest) Release(f *Frame) {
// Make sure the payload is not used after this point by clearing the frame.
zeroOut(f.Payload)
f.Payload = nil
zeroOut(f.buffer)
f.buffer = nil
zeroOut(f.headerBuffer)
f.headerBuffer = nil
f.Header = FrameHeader{}
p.mu.Lock()
defer p.mu.Unlock()
if _, ok := p.allocations[f]; !ok {
p.badRelease = append(p.badRelease, "bad Release at "+recordStack())
return
}
delete(p.allocations, f)
}
// CheckedFramePoolForTestResult contains info on mismatched gets/releases
type CheckedFramePoolForTestResult struct {
BadReleases []string
Unreleased []string
}
// HasIssues indicates whether there were any issues with gets/releases
func (r CheckedFramePoolForTestResult) HasIssues() bool {
return len(r.BadReleases)+len(r.Unreleased) > 0
}
// CheckEmpty returns the number of unreleased frames in the pool
func (p *CheckedFramePoolForTest) CheckEmpty() CheckedFramePoolForTestResult {
p.mu.Lock()
defer p.mu.Unlock()
var badCalls []string
for f, s := range p.allocations {
badCalls = append(badCalls, fmt.Sprintf("frame %p: %v not released, get from: %v", f, f.Header, s))
}
return CheckedFramePoolForTestResult{
Unreleased: badCalls,
BadReleases: p.badRelease,
}
}
func recordStack() string {
buf := make([]byte, 4096)
runtime.Stack(buf, false /* all */)
return string(buf)
}
func zeroOut(bs []byte) {
for i := range bs {
bs[i] = 0
}
}
================================================
FILE: checked_frame_pool_test.go
================================================
package tchannel
import (
"strings"
"testing"
"github.com/stretchr/testify/assert"
"github.com/uber/tchannel-go/testutils/goroutines"
)
func TestCheckedFramePoolForTest(t *testing.T) {
tests := []struct {
msg string
operations func(pool *CheckedFramePoolForTest)
wantHasIssues bool
wantBadAllocations int
wantBadReleases int
}{
{
msg: "no bad releases or leaks",
operations: func(pool *CheckedFramePoolForTest) {
for i := 0; i < 10; i++ {
pool.Release(pool.Get())
}
},
},
{
msg: "frames are leaked",
operations: func(pool *CheckedFramePoolForTest) {
for i := 0; i < 10; i++ {
pool.Release(pool.Get())
}
for i := 0; i < 10; i++ {
_ = pool.Get()
}
},
wantHasIssues: true,
wantBadAllocations: 10,
},
{
msg: "frames are double released",
operations: func(pool *CheckedFramePoolForTest) {
for i := 0; i < 10; i++ {
pool.Release(pool.Get())
}
f := pool.Get()
pool.Release(f)
pool.Release(f)
},
wantHasIssues: true,
wantBadReleases: 1,
},
}
for _, tt := range tests {
t.Run(tt.msg, func(t *testing.T) {
pool := NewCheckedFramePoolForTest()
tt.operations(pool)
results := pool.CheckEmpty()
assert.Equal(t, tt.wantHasIssues, results.HasIssues(), "Unexpected HasIssues() state")
assert.Equal(t, tt.wantBadAllocations, len(results.Unreleased), "Unexpected allocs")
assert.Equal(t, tt.wantBadReleases, len(results.BadReleases), "Unexpected bad releases")
})
}
}
func CheckFramePoolIsEmpty(t testing.TB, pool *CheckedFramePoolForTest) {
t.Helper()
stacks := goroutines.GetAll()
if result := pool.CheckEmpty(); result.HasIssues() {
if len(result.Unreleased) > 0 {
t.Errorf("Frame pool has %v unreleased frames, errors:\n%v\nStacks:%v",
len(result.Unreleased), strings.Join(result.Unreleased, "\n"), stacks)
}
if len(result.BadReleases) > 0 {
t.Errorf("Frame pool has %v bad releases, errors:\n%v\nStacks:%v",
len(result.BadReleases), strings.Join(result.BadReleases, "\n"), stacks)
}
}
}
================================================
FILE: checksum.go
================================================
// Copyright (c) 2015 Uber Technologies, Inc.
// 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.
package tchannel
import (
"hash"
"hash/crc32"
"sync"
)
var checksumPools [checksumCount]sync.Pool
// A ChecksumType is a checksum algorithm supported by TChannel for checksumming call bodies
type ChecksumType byte
const (
// ChecksumTypeNone indicates no checksum is included in the message
ChecksumTypeNone ChecksumType = 0
// ChecksumTypeCrc32 indicates the message checksum is calculated using crc32
ChecksumTypeCrc32 ChecksumType = 1
// ChecksumTypeFarmhash indicates the message checksum is calculated using Farmhash
ChecksumTypeFarmhash ChecksumType = 2
// ChecksumTypeCrc32C indicates the message checksum is calculated using crc32c
ChecksumTypeCrc32C ChecksumType = 3
checksumCount = 4
)
func init() {
crc32CastagnoliTable := crc32.MakeTable(crc32.Castagnoli)
ChecksumTypeNone.pool().New = func() interface{} {
return nullChecksum{}
}
ChecksumTypeCrc32.pool().New = func() interface{} {
return newHashChecksum(ChecksumTypeCrc32, crc32.NewIEEE())
}
ChecksumTypeCrc32C.pool().New = func() interface{} {
return newHashChecksum(ChecksumTypeCrc32C, crc32.New(crc32CastagnoliTable))
}
// TODO: Implement farm hash.
ChecksumTypeFarmhash.pool().New = func() interface{} {
return nullChecksum{}
}
}
// ChecksumSize returns the size in bytes of the checksum calculation
func (t ChecksumType) ChecksumSize() int {
switch t {
case ChecksumTypeNone:
return 0
case ChecksumTypeCrc32, ChecksumTypeCrc32C:
return crc32.Size
case ChecksumTypeFarmhash:
return 4
default:
return 0
}
}
// pool returns the sync.Pool used to pool checksums for this type.
func (t ChecksumType) pool() *sync.Pool {
return &checksumPools[int(t)]
}
// New creates a new Checksum of the given type
func (t ChecksumType) New() Checksum {
s := t.pool().Get().(Checksum)
s.Reset()
return s
}
// Release puts a Checksum back in the pool.
func (t ChecksumType) Release(checksum Checksum) {
t.pool().Put(checksum)
}
// A Checksum calculates a running checksum against a bytestream
type Checksum interface {
// TypeCode returns the type of this checksum
TypeCode() ChecksumType
// Size returns the size of the calculated checksum
Size() int
// Add adds bytes to the checksum calculation
Add(b []byte) []byte
// Sum returns the current checksum value
Sum() []byte
// Release puts a Checksum back in the pool.
Release()
// Reset resets the checksum state to the default 0 value.
Reset()
}
// No checksum
type nullChecksum struct{}
// TypeCode returns the type of the checksum
func (c nullChecksum) TypeCode() ChecksumType { return ChecksumTypeNone }
// Size returns the size of the checksum data, in the case the null checksum this is zero
func (c nullChecksum) Size() int { return 0 }
// Add adds a byteslice to the checksum calculation
func (c nullChecksum) Add(b []byte) []byte { return nil }
// Sum returns the current checksum calculation
func (c nullChecksum) Sum() []byte { return nil }
// Release puts a Checksum back in the pool.
func (c nullChecksum) Release() {
c.TypeCode().Release(c)
}
// Reset resets the checksum state to the default 0 value.
func (c nullChecksum) Reset() {}
// Hash Checksum
type hashChecksum struct {
checksumType ChecksumType
hash hash.Hash
sumCache []byte
}
func newHashChecksum(t ChecksumType, hash hash.Hash) *hashChecksum {
return &hashChecksum{
checksumType: t,
hash: hash,
sumCache: make([]byte, 0, 4),
}
}
// TypeCode returns the type of the checksum
func (h *hashChecksum) TypeCode() ChecksumType { return h.checksumType }
// Size returns the size of the checksum data
func (h *hashChecksum) Size() int { return h.hash.Size() }
// Add adds a byte slice to the checksum calculation
func (h *hashChecksum) Add(b []byte) []byte { h.hash.Write(b); return h.Sum() }
// Sum returns the current value of the checksum calculation
func (h *hashChecksum) Sum() []byte { return h.hash.Sum(h.sumCache) }
// Release puts a Checksum back in the pool.
func (h *hashChecksum) Release() { h.TypeCode().Release(h) }
// Reset resets the checksum state to the default 0 value.
func (h *hashChecksum) Reset() { h.hash.Reset() }
// noReleaseChecksum overrides .Release() with a NOOP so that the checksum won't
// be released by the fragmentingWriter when it is managed externally, e.g. by the
// relayer
type noReleaseChecksum struct {
Checksum
}
func (n *noReleaseChecksum) Release() {}
================================================
FILE: close_test.go
================================================
// Copyright (c) 2015 Uber Technologies, Inc.
// 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.
package tchannel_test
import (
"math/rand"
"sync"
"testing"
"time"
. "github.com/uber/tchannel-go"
"github.com/uber/tchannel-go/raw"
"github.com/uber/tchannel-go/testutils"
"github.com/uber/tchannel-go/testutils/goroutines"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"go.uber.org/atomic"
"golang.org/x/net/context"
)
type channelState struct {
testServer *testutils.TestServer
closeCh chan struct{}
closed bool
}
func makeCall(client *Channel, server *testutils.TestServer) error {
ctx, cancel := NewContext(time.Second)
defer cancel()
_, _, _, err := raw.Call(ctx, client, server.HostPort(), server.ServiceName(), "test", nil, nil)
return err
}
func assertStateChangesTo(t testing.TB, ch *Channel, state ChannelState) {
var lastState ChannelState
require.True(t, testutils.WaitFor(time.Second, func() bool {
lastState = ch.State()
return lastState == state
}), "Channel state is %v expected %v", lastState, state)
}
func TestCloseOnlyListening(t *testing.T) {
ch := testutils.NewServer(t, nil)
// If there are no connections, then the channel should close immediately.
ch.Close()
assert.Equal(t, ChannelClosed, ch.State())
assert.True(t, ch.Closed(), "Channel should be closed")
}
func TestCloseNewClient(t *testing.T) {
ch := testutils.NewClient(t, nil)
// If there are no connections, then the channel should close immediately.
ch.Close()
assert.Equal(t, ChannelClosed, ch.State())
assert.True(t, ch.Closed(), "Channel should be closed")
}
func ignoreError(h *testHandler) Handler {
return raw.Wrap(onErrorTestHandler{
testHandler: h,
onError: func(_ context.Context, err error) {},
})
}
func TestCloseAfterTimeout(t *testing.T) {
// Disable log verfication since connections are closed after a timeout
// and the relay might still be reading/writing to the connection.
// TODO: Ideally, we only disable log verification on the relay.
opts := testutils.NewOpts().DisableLogVerification()
testutils.WithTestServer(t, opts, func(t testing.TB, ts *testutils.TestServer) {
testHandler := newTestHandler(t)
ts.Register(ignoreError(testHandler), "block")
ctx, cancel := NewContext(100 * time.Millisecond)
defer cancel()
// Make a call, wait for it to timeout.
clientCh := ts.NewClient(nil)
_, _, _, err := raw.Call(ctx, clientCh, ts.HostPort(), ts.ServiceName(), "block", nil, nil)
require.Equal(t, ErrTimeout, err, "Expected call to timeout")
// The client channel should also close immediately.
clientCh.Close()
assertStateChangesTo(t, clientCh, ChannelClosed)
assert.True(t, clientCh.Closed(), "Channel should be closed")
})
}
func TestRelayCloseTimeout(t *testing.T) {
opts := testutils.NewOpts().
SetRelayOnly(). // this is a relay-specific test.
DisableLogVerification() // we're causing errors on purpose.
opts.DefaultConnectionOptions.MaxCloseTime = 100 * time.Millisecond
testutils.WithTestServer(t, opts, func(t testing.TB, ts *testutils.TestServer) {
gotCall := make(chan struct{})
unblock := make(chan struct{})
defer close(unblock)
testutils.RegisterEcho(ts.Server(), func() {
close(gotCall)
<-unblock
})
clientCh := ts.NewClient(opts)
// Start a call in the background, since it will block
go func() {
ctx, cancel := NewContext(10 * time.Second)
defer cancel()
_, _, _, err := raw.Call(ctx, clientCh, ts.HostPort(), ts.ServiceName(), "echo", nil, nil)
require.Error(t, err)
assert.Equal(t, ErrCodeNetwork, GetSystemErrorCode(err),
"expect network error from relay closing connection on timeout")
}()
<-gotCall
ts.Relay().Close()
// The relay should close within the timeout.
<-ts.Relay().ClosedChan()
})
}
func TestRaceExchangesWithClose(t *testing.T) {
var wg sync.WaitGroup
opts := testutils.NewOpts().DisableLogVerification()
testutils.WithTestServer(t, opts, func(t testing.TB, ts *testutils.TestServer) {
var (
server = ts.Server()
gotCall = make(chan struct{})
completeCall = make(chan struct{})
)
testutils.RegisterFunc(server, "dummy", func(ctx context.Context, args *raw.Args) (*raw.Res, error) {
return &raw.Res{}, nil
})
testutils.RegisterEcho(server, func() {
close(gotCall)
<-completeCall
})
client := ts.NewClient(opts)
defer client.Close()
callDone := make(chan struct{})
go func() {
// n.b. Use a longer context here; server shutdown is inherently
// nondeterministic, and now that it's blocking on channel and
// connection closure, it can take anywhere from 0-2s to fully
// close all of its internals.
ctx, cancel := context.WithTimeout(
context.Background(),
testutils.Timeout(5*time.Second),
)
defer cancel()
assert.NoError(
t,
testutils.CallEchoWithContext(
ctx,
client,
ts.HostPort(),
server.ServiceName(),
&raw.Args{},
),
"Echo failed",
)
close(callDone)
}()
// Wait until the server recieves a call, so it has an active inbound.
<-gotCall
// Start a bunch of clients to trigger races between connecting and close.
var closed atomic.Bool
for i := 0; i < 100; i++ {
wg.Add(1)
go func() {
defer wg.Done()
// We don't use ts.NewClient here to avoid data races.
c := testutils.NewClient(t, opts)
defer c.Close()
if closed.Load() {
return
}
ctx, cancel := NewContext(testutils.Timeout(time.Second))
defer cancel()
if err := c.Ping(ctx, ts.HostPort()); err != nil {
return
}
if closed.Load() {
return
}
raw.Call(ctx, c, ts.HostPort(), server.ServiceName(), "dummy", nil, nil)
}()
}
// Now try to close the channel, it should block since there's active exchanges.
server.Close()
closed.Store(true)
// n.b. As it's shutting down, server state can be in any of the
// outlined states below. It doesn't matter which specific state
// it's in, as long as we're verifying that it's at least in the
// process of shutting down.
var (
timeout = time.After(testutils.Timeout(time.Second))
validState = func() bool {
switch ts.Server().State() {
case ChannelStartClose, ChannelInboundClosed, ChannelClosed:
return true
default:
return false
}
}
)
ticker := time.NewTicker(25 * time.Millisecond)
defer ticker.Stop()
for !validState() {
select {
case <-ticker.C:
case <-timeout:
require.FailNow(
t,
"server state did not transition as expected: %v",
ts.Server().State(),
)
}
}
closed.Store(true)
close(completeCall)
<-callDone
})
// Wait for all calls to complete
wg.Wait()
}
// TestCloseStress ensures that once a Channel is closed, it cannot be reached.
func TestCloseStress(t *testing.T) {
CheckStress(t)
const numHandlers = 5
handler := &swapper{t}
var lock sync.RWMutex
var wg sync.WaitGroup
var channels []*channelState
// Start numHandlers servers, and don't close the connections till they are signalled.
for i := 0; i < numHandlers; i++ {
wg.Add(1)
go func() {
testutils.WithTestServer(t, nil, func(t testing.TB, ts *testutils.TestServer) {
ts.Register(raw.Wrap(handler), "test")
chState := &channelState{
testServer: ts,
closeCh: make(chan struct{}),
}
lock.Lock()
channels = append(channels, chState)
lock.Unlock()
wg.Done()
// Wait for a close signal.
<-chState.closeCh
// Lock until the connection is closed.
lock.Lock()
chState.closed = true
})
}()
}
// Wait till all the channels have been registered.
wg.Wait()
// Start goroutines to make calls until the test has ended.
testEnded := make(chan struct{})
for i := 0; i < 10; i++ {
go func() {
for {
select {
case <-testEnded:
return
default:
// Keep making requests till the test ends.
}
// Get 2 random channels and make a call from one to the other.
lock.RLock()
chState1 := channels[rand.Intn(len(channels))]
chState2 := channels[rand.Intn(len(channels))]
if chState1 == chState2 {
lock.RUnlock()
continue
}
// Grab a read lock to make sure channels aren't closed while we call.
ch1Closed := chState1.closed
ch2Closed := chState2.closed
err := makeCall(chState1.testServer.NewClient(nil), chState2.testServer)
lock.RUnlock()
if ch1Closed || ch2Closed {
assert.Error(
t,
err,
"Call from %v (%v) to %v (%v) should fail",
chState1.testServer.ServiceName(),
chState1.testServer.HostPort(),
chState2.testServer.ServiceName(),
chState2.testServer.HostPort(),
)
} else {
assert.NoError(
t,
err,
"Call from %v (%v) to %v (%v) should not fail",
chState1.testServer.ServiceName(),
chState1.testServer.HostPort(),
chState2.testServer.ServiceName(),
chState2.testServer.HostPort(),
)
}
}
}()
}
// Kill connections till all of the connections are dead.
for i := 0; i < numHandlers; i++ {
time.Sleep(time.Duration(rand.Intn(50)) * time.Millisecond)
channels[i].closeCh <- struct{}{}
}
}
type closeSemanticsTest struct {
*testing.T
isolated bool
}
func (t *closeSemanticsTest) makeServer(name string) (*Channel, chan struct{}) {
ch := testutils.NewServer(t.T, &testutils.ChannelOpts{ServiceName: name})
c := make(chan struct{})
testutils.RegisterFunc(ch, "stream", func(ctx context.Context, args *raw.Args) (*raw.Res, error) {
<-c
return &raw.Res{}, nil
})
testutils.RegisterFunc(ch, "call", func(ctx context.Context, args *raw.Args) (*raw.Res, error) {
return &raw.Res{}, nil
})
return ch, c
}
func (t *closeSemanticsTest) withNewClient(f func(ch *Channel)) {
ch := testutils.NewClient(t.T, &testutils.ChannelOpts{ServiceName: "client"})
f(ch)
ch.Close()
}
func (t *closeSemanticsTest) startCall(from *Channel, to *Channel, method string) (*OutboundCall, error) {
ctx, _ := NewContext(time.Second)
var call *OutboundCall
var err error
toPeer := to.PeerInfo()
if t.isolated {
sc := from.GetSubChannel(toPeer.ServiceName, Isolated)
sc.Peers().Add(toPeer.HostPort)
call, err = sc.BeginCall(ctx, method, nil)
} else {
call, err = from.BeginCall(ctx, toPeer.HostPort, toPeer.ServiceName, method, nil)
}
return call, err
}
func (t *closeSemanticsTest) call(from *Channel, to *Channel) error {
call, err := t.startCall(from, to, "call")
if err == nil {
_, _, _, err = raw.WriteArgs(call, nil, nil)
}
return err
}
func (t *closeSemanticsTest) callStream(from *Channel, to *Channel) <-chan struct{} {
c := make(chan struct{})
call, err := t.startCall(from, to, "stream")
require.NoError(t, err, "stream call failed to start")
require.NoError(t, NewArgWriter(call.Arg2Writer()).Write(nil), "write arg2")
require.NoError(t, NewArgWriter(call.Arg3Writer()).Write(nil), "write arg3")
go func() {
var d []byte
assert.NoError(t, NewArgReader(call.Response().Arg2Reader()).Read(&d), "read arg2 from %v to %v", from.PeerInfo(), to.PeerInfo())
assert.NoError(t, NewArgReader(call.Response().Arg3Reader()).Read(&d), "read arg3")
c <- struct{}{}
}()
return c
}
func (t *closeSemanticsTest) runTest() {
s1, s1C := t.makeServer("s1")
s2, s2C := t.makeServer("s2")
// Make a call from s1 -> s2, and s2 -> s1
call1 := t.callStream(s1, s2)
call2 := t.callStream(s2, s1)
// s1 and s2 are both open, so calls to it should be successful.
t.withNewClient(func(ch *Channel) {
require.NoError(t, t.call(ch, s1), "failed to call s1")
require.NoError(t, t.call(ch, s2), "failed to call s2")
})
require.NoError(t, t.call(s1, s2), "call s1 -> s2 failed")
require.NoError(t, t.call(s2, s1), "call s2 -> s1 failed")
// Close s1, should no longer be able to call it.
s1.Close()
assert.Equal(t, ChannelStartClose, s1.State())
t.withNewClient(func(ch *Channel) {
assert.Error(t, t.call(ch, s1), "closed channel should not accept incoming calls")
require.NoError(t, t.call(ch, s2),
"closed channel with pending incoming calls should allow outgoing calls")
})
// Even an existing connection (e.g. from s2) should fail.
// TODO: this will fail until the peer is shared.
if !assert.Equal(t, ErrChannelClosed, t.call(s2, s1),
"closed channel should not accept incoming calls") {
t.Errorf("err %v", t.call(s2, s1))
}
require.Error(t, t.call(s1, s2),
"closed channel with pending incoming calls disallows outgoing calls")
// Once the incoming connection is drained, outgoing calls should fail.
s1C <- struct{}{}
<-call2
assertStateChangesTo(t.T, s1, ChannelInboundClosed)
require.Error(t, t.call(s1, s2),
"closed channel with no pending incoming calls should not allow outgoing calls")
// Now the channel should be completely closed as there are no pending connections.
s2C <- struct{}{}
<-call1
assertStateChangesTo(t.T, s1, ChannelClosed)
// Close s2 so we don't leave any goroutines running.
s2.Close()
}
func TestCloseSemantics(t *testing.T) {
// We defer the check as we want it to run after the SetTimeout clears the timeout.
defer goroutines.VerifyNoLeaks(t, nil)
defer testutils.SetTimeout(t, 2*time.Second)()
ct := &closeSemanticsTest{t, false /* isolated */}
ct.runTest()
}
func TestCloseSemanticsIsolated(t *testing.T) {
// We defer the check as we want it to run after the SetTimeout clears the timeout.
defer goroutines.VerifyNoLeaks(t, nil)
defer testutils.SetTimeout(t, 2*time.Second)()
ct := &closeSemanticsTest{t, true /* isolated */}
ct.runTest()
}
func TestCloseSingleChannel(t *testing.T) {
ch := testutils.NewServer(t, nil)
var connected sync.WaitGroup
var completed sync.WaitGroup
blockCall := make(chan struct{})
testutils.RegisterFunc(ch, "echo", func(ctx context.Context, args *raw.Args) (*raw.Res, error) {
connected.Done()
<-blockCall
return &raw.Res{
Arg2: args.Arg2,
Arg3: args.Arg3,
}, nil
})
for i := 0; i < 10; i++ {
connected.Add(1)
completed.Add(1)
go func() {
ctx, cancel := NewContext(time.Second)
defer cancel()
peerInfo := ch.PeerInfo()
_, _, _, err := raw.Call(ctx, ch, peerInfo.HostPort, peerInfo.ServiceName, "echo", nil, nil)
assert.NoError(t, err, "Call failed")
completed.Done()
}()
}
// Wait for all calls to connect before triggerring the Close (so they do not fail).
connected.Wait()
ch.Close()
// Unblock the calls, and wait for all the calls to complete.
close(blockCall)
completed.Wait()
// Once all calls are complete, the channel should be closed.
assertStateChangesTo(t, ch, ChannelClosed)
goroutines.VerifyNoLeaks(t, nil)
}
func TestCloseOneSide(t *testing.T) {
ch1 := testutils.NewServer(t, &testutils.ChannelOpts{ServiceName: "client"})
ch2 := testutils.NewServer(t, &testutils.ChannelOpts{ServiceName: "server"})
connected := make(chan struct{})
completed := make(chan struct{})
blockCall := make(chan struct{})
testutils.RegisterFunc(ch2, "echo", func(ctx context.Context, args *raw.Args) (*raw.Res, error) {
connected <- struct{}{}
<-blockCall
return &raw.Res{
Arg2: args.Arg2,
Arg3: args.Arg3,
}, nil
})
go func() {
ctx, cancel := NewContext(time.Second)
defer cancel()
ch2Peer := ch2.PeerInfo()
_, _, _, err := raw.Call(ctx, ch1, ch2Peer.HostPort, ch2Peer.ServiceName, "echo", nil, nil)
assert.NoError(t, err, "Call failed")
completed <- struct{}{}
}()
// Wait for connected before calling Close.
<-connected
ch1.Close()
// Now unblock the call and wait for the call to complete.
close(blockCall)
<-completed
// Once the call completes, the channel should be closed.
assertStateChangesTo(t, ch1, ChannelClosed)
// We need to close all open TChannels before verifying blocked goroutines.
ch2.Close()
goroutines.VerifyNoLeaks(t, nil)
}
// TestCloseSendError tests that system errors are not attempted to be sent when
// a connection is closed, and ensures there's no race conditions such as the error
// frame being added to the channel just as it is closed.
func TestCloseSendError(t *testing.T) {
var (
closed atomic.Uint32
counter atomic.Uint32
)
opts := testutils.NewOpts().DisableLogVerification()
serverCh := testutils.NewServer(t, opts)
testutils.RegisterEcho(serverCh, func() {
if counter.Inc() > 10 {
// Close the server in a goroutine to possibly trigger more race conditions.
go func() {
closed.Inc()
serverCh.Close()
}()
}
})
clientCh := testutils.NewClient(t, opts)
// Create a connection that will be shared.
require.NoError(t, testutils.Ping(clientCh, serverCh), "Ping from client to server failed")
var wg sync.WaitGroup
for i := 0; i < 100; i++ {
wg.Add(1)
go func() {
time.Sleep(time.Duration(rand.Intn(1000)) * time.Microsecond)
err := testutils.CallEcho(clientCh, serverCh.PeerInfo().HostPort, serverCh.ServiceName(), nil)
if err != nil && closed.Load() == 0 {
t.Errorf("Call failed: %v", err)
}
wg.Done()
}()
}
// Wait for all the goroutines to end
wg.Wait()
clientCh.Close()
goroutines.VerifyNoLeaks(t, nil)
}
================================================
FILE: codecov.yml
================================================
coverage:
range: 75..100
round: down
precision: 2
status:
project:
default:
enabled: yes
target: 85%
if_not_found: success
if_ci_failed: error
ignore:
- "*_string.go"
================================================
FILE: conn_leak_test.go
================================================
// Copyright (c) 2017 Uber Technologies, Inc.
// 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.
package tchannel_test
import (
"io/ioutil"
"runtime"
"testing"
"time"
. "github.com/uber/tchannel-go"
"github.com/uber/tchannel-go/testutils"
"github.com/stretchr/testify/require"
)
// This is a regression test for https://github.com/uber/tchannel-go/issues/643
// We want to ensure that once a connection is closed, there are no references
// to the closed connection, and the GC frees the connection.
// We use `runtime.SetFinalizer` to detect whether the GC has freed the object.
// However, finalizers cannot be set on objects with circular references,
// so we cannot set a finalizer on the connection, but instead set a finalizer
// on a field of the connection which has the same lifetime. The connection
// logger is unique per connection and does not have circular references
// so we can use the logger, but need a pointer for `runtime.SetFinalizer`.
// loggerPtr is a Logger implementation that uses a pointer unlike other
// TChannel loggers.
type loggerPtr struct {
Logger
}
func (l *loggerPtr) WithFields(fields ...LogField) Logger {
return &loggerPtr{l.Logger.WithFields(fields...)}
}
func TestPeerConnectionLeaks(t *testing.T) {
// Disable log verification since we want to set our own logger.
opts := testutils.NewOpts().NoRelay().DisableLogVerification()
opts.Logger = &loggerPtr{NullLogger}
connFinalized := make(chan struct{})
setFinalizer := func(p *Peer) {
ctx, cancel := NewContext(time.Second)
defer cancel()
conn, err := p.GetConnection(ctx)
require.NoError(t, err, "Failed to get connection")
runtime.SetFinalizer(conn.Logger(), func(interface{}) {
close(connFinalized)
})
}
testutils.WithTestServer(t, opts, func(t testing.TB, ts *testutils.TestServer) {
s2Opts := testutils.NewOpts().SetServiceName("s2")
s2Opts.Logger = NewLogger(ioutil.Discard)
s2 := ts.NewServer(s2Opts)
// Set a finalizer to detect when the connection from s1 -> s2 is freed.
peer := ts.Server().Peers().GetOrAdd(s2.PeerInfo().HostPort)
setFinalizer(peer)
// Close s2, so that the connection in s1 to s2 is released.
s2.Close()
closed := testutils.WaitFor(3*time.Second, s2.Closed)
require.True(t, closed, "s2 didn't close")
// Trigger the GC which will call the finalizer, and ensure
// that the connection logger was finalized.
finalized := testutils.WaitFor(3*time.Second, func() bool {
runtime.GC()
select {
case <-connFinalized:
return true
default:
return false
}
})
require.True(t, finalized, "Connection was not freed")
})
}
================================================
FILE: connection.go
================================================
// Copyright (c) 2015 Uber Technologies, Inc.
// 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.
package tchannel
import (
"crypto/tls"
"errors"
"fmt"
"io"
"net"
"strings"
"sync"
"syscall"
"time"
"github.com/uber/tchannel-go/tos"
"go.uber.org/atomic"
"golang.org/x/net/context"
"golang.org/x/net/ipv4"
"golang.org/x/net/ipv6"
)
const (
// CurrentProtocolVersion is the current version of the TChannel protocol
// supported by this stack
CurrentProtocolVersion = 0x02
// DefaultConnectTimeout is the default timeout used by net.Dial, if no timeout
// is specified in the context.
DefaultConnectTimeout = 5 * time.Second
// DefaultConnectionBufferSize is the default size for the connection's read
//and write channels.
DefaultConnectionBufferSize = 512
)
// PeerVersion contains version related information for a specific peer.
// These values are extracted from the init headers.
type PeerVersion struct {
Language string `json:"language"`
LanguageVersion string `json:"languageVersion"`
TChannelVersion string `json:"tchannelVersion"`
}
// PeerInfo contains information about a TChannel peer
type PeerInfo struct {
// The host and port that can be used to contact the peer, as encoded by net.JoinHostPort
HostPort string `json:"hostPort"`
// The logical process name for the peer, used for only for logging / debugging
ProcessName string `json:"processName"`
// IsEphemeral returns whether the remote host:port is ephemeral (e.g. not listening).
IsEphemeral bool `json:"isEphemeral"`
// Version returns the version information for the remote peer.
Version PeerVersion `json:"version"`
}
func (p PeerInfo) String() string {
return fmt.Sprintf("%s(%s)", p.HostPort, p.ProcessName)
}
// IsEphemeralHostPort returns whether the connection is from an ephemeral host:port.
func (p PeerInfo) IsEphemeralHostPort() bool {
return p.IsEphemeral
}
// LocalPeerInfo adds service name to the peer info, only required for the local peer.
type LocalPeerInfo struct {
PeerInfo
// ServiceName is the service name for the local peer.
ServiceName string `json:"serviceName"`
}
func (p LocalPeerInfo) String() string {
return fmt.Sprintf("%v: %v", p.ServiceName, p.PeerInfo)
}
var (
// ErrConnectionClosed is returned when a caller performs an method
// on a closed connection
ErrConnectionClosed = errors.New("connection is closed")
// ErrSendBufferFull is returned when a message cannot be sent to the
// peer because the frame sending buffer has become full. Typically
// this indicates that the connection is stuck and writes have become
// backed up
ErrSendBufferFull = errors.New("connection send buffer is full, cannot send frame")
// ErrConnectionNotReady is no longer used.
ErrConnectionNotReady = errors.New("connection is not yet ready")
errNoSyscallConn = errors.New("no syscall.RawConn available")
)
// errConnectionInvalidState is returned when the connection is in an unknown state.
type errConnectionUnknownState struct {
site string
state connectionState
}
func (e errConnectionUnknownState) Error() string {
return fmt.Sprintf("connection is in unknown state: %v at %v", e.state, e.site)
}
// SendBufferSizeOverride is used for overriding per-process send buffer channel size for a
// connection, using process name prefix matching.
type SendBufferSizeOverride struct {
ProcessNamePrefix string
SendBufferSize int
}
// ConnectionOptions are options that control the behavior of a Connection
type ConnectionOptions struct {
// The frame pool, allowing better management of frame buffers. Defaults to using raw heap.
FramePool FramePool
// NOTE: This is deprecated and not used for anything.
RecvBufferSize int
// The size of send channel buffers. Defaults to 512.
SendBufferSize int
// Per-process name prefix override for SendBufferSize
// Note that order matters, if there are multiple matches, the first one is used.
SendBufferSizeOverrides []SendBufferSizeOverride
// The type of checksum to use when sending messages.
ChecksumType ChecksumType
// ToS class name marked on outbound packets.
TosPriority tos.ToS
// HealthChecks configures active connection health checking for this channel.
// By default, health checks are not enabled.
HealthChecks HealthCheckOptions
// MaxCloseTime controls how long we allow a connection to complete pending
// calls before shutting down. Only used if it is non-zero.
MaxCloseTime time.Duration
// PropagateCancel enables cancel messages to cancel contexts.
// By default, cancel messages are ignored.
// This only affects inbounds (servers handling calls).
PropagateCancel bool
// SendCancelOnContextCanceled enables sending cancel messages
// when a request context is canceled before receiving a response.
// This only affects outbounds (clients making calls).
SendCancelOnContextCanceled bool
}
// connectionEvents are the events that can be triggered by a connection.
type connectionEvents struct {
// OnActive is called when a connection becomes active.
OnActive func(c *Connection)
// OnCloseStateChange is called when a connection that is closing changes state.
OnCloseStateChange func(c *Connection)
// OnExchangeUpdated is called when a message exchange added or removed.
OnExchangeUpdated func(c *Connection)
}
// Connection represents a connection to a remote peer.
type Connection struct {
channelConnectionCommon
connID uint32
connDirection connectionDirection
opts ConnectionOptions
conn net.Conn
sysConn syscall.RawConn // may be nil if conn cannot be converted
localPeerInfo LocalPeerInfo
remotePeerInfo PeerInfo
sendCh chan *Frame
stopCh chan struct{}
state connectionState
stateMut sync.RWMutex
inbound *messageExchangeSet
outbound *messageExchangeSet
internalHandlers *handlerMap
handler Handler
nextMessageID atomic.Uint32
events connectionEvents
commonStatsTags map[string]string
relay *Relayer
baseContext context.Context
// outboundHP is the host:port we used to create this outbound connection.
// It may not match remotePeerInfo.HostPort, in which case the connection is
// added to peers for both host:ports. For inbound connections, this is empty.
outboundHP string
// closeNetworkCalled is used to avoid errors from being logged
// when this side closes a connection.
closeNetworkCalled atomic.Bool
// stoppedExchanges is atomically set when exchanges are stopped due to error.
stoppedExchanges atomic.Bool
// remotePeerAddress is used as a cache for remote peer address parsed into individual
// components that can be used to set peer tags on OpenTracing Span.
remotePeerAddress peerAddressComponents
// healthCheckCtx/Quit are used to stop health checks.
healthCheckCtx context.Context
healthCheckQuit context.CancelFunc
healthCheckDone chan struct{}
healthCheckHistory *healthHistory
// lastActivity{Read,Write} is used to track how long the connection has been
// idle for the recieve and send connections respectively. (unix time, nano)
lastActivityRead atomic.Int64
lastActivityWrite atomic.Int64
}
type peerAddressComponents struct {
port uint16
ipv4 uint32
ipv6 string
hostname string
}
// _nextConnID is used to allocate unique IDs to every connection for debugging purposes.
var _nextConnID atomic.Uint32
type connectionState int
const (
// Connection is fully active
connectionActive connectionState = iota + 1
// Connection is starting to close; new incoming requests are rejected, outbound
// requests are allowed to proceed
connectionStartClose
// Connection has finished processing all active inbound, and is
// waiting for outbound requests to complete or timeout
connectionInboundClosed
// Connection is fully closed
connectionClosed
)
//go:generate stringer -type=connectionState
func getTimeout(ctx context.Context) time.Duration {
deadline, ok := ctx.Deadline()
if !ok {
return DefaultConnectTimeout
}
return deadline.Sub(time.Now())
}
func (co ConnectionOptions) withDefaults() ConnectionOptions {
if co.ChecksumType == ChecksumTypeNone {
co.ChecksumType = ChecksumTypeCrc32
}
if co.FramePool == nil {
co.FramePool = DefaultFramePool
}
if co.SendBufferSize <= 0 {
co.Sen
gitextract_ixnw_gpx/ ├── .github/ │ └── workflows/ │ └── tests.yaml ├── .gitignore ├── CHANGELOG.md ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE.md ├── Makefile ├── README.md ├── RELEASE.md ├── all_channels.go ├── all_channels_test.go ├── arguments.go ├── arguments_test.go ├── benchmark/ │ ├── benchclient/ │ │ └── main.go │ ├── benchserver/ │ │ └── main.go │ ├── build_manager.go │ ├── client_server_bench_test.go │ ├── external_client.go │ ├── external_common.go │ ├── external_server.go │ ├── frame_templates.go │ ├── interfaces.go │ ├── internal_client.go │ ├── internal_multi_client.go │ ├── internal_server.go │ ├── internal_tcp_client.go │ ├── internal_tcp_server.go │ ├── matrix_test.go │ ├── options.go │ ├── real_relay.go │ ├── req_bytes.go │ ├── tcp_bench_test.go │ ├── tcp_frame_relay.go │ └── tcp_raw_relay.go ├── calloptions.go ├── calloptions_test.go ├── channel.go ├── channel_test.go ├── channel_utils_test.go ├── channelstate_string.go ├── checked_frame_pool.go ├── checked_frame_pool_test.go ├── checksum.go ├── close_test.go ├── codecov.yml ├── conn_leak_test.go ├── connection.go ├── connection_bench_test.go ├── connection_direction.go ├── connection_internal_test.go ├── connection_test.go ├── connectionstate_string.go ├── context.go ├── context_builder.go ├── context_header.go ├── context_internal_test.go ├── context_test.go ├── deps_test.go ├── dial_16.go ├── dial_17.go ├── dial_17_test.go ├── doc.go ├── errors.go ├── errors_test.go ├── examples/ │ ├── bench/ │ │ ├── client/ │ │ │ └── client.go │ │ ├── runner.go │ │ └── server/ │ │ └── server.go │ ├── hyperbahn/ │ │ └── echo-server/ │ │ └── main.go │ ├── hypercat/ │ │ └── main.go │ ├── keyvalue/ │ │ ├── README.md │ │ ├── client/ │ │ │ └── client.go │ │ ├── gen-go/ │ │ │ └── keyvalue/ │ │ │ ├── admin.go │ │ │ ├── baseservice.go │ │ │ ├── constants.go │ │ │ ├── keyvalue.go │ │ │ ├── tchan-keyvalue.go │ │ │ └── ttypes.go │ │ ├── keyvalue.thrift │ │ └── server/ │ │ └── server.go │ ├── ping/ │ │ ├── README.md │ │ └── main.go │ ├── test_server/ │ │ └── server.go │ └── thrift/ │ ├── example.thrift │ ├── gen-go/ │ │ └── example/ │ │ ├── base.go │ │ ├── constants.go │ │ ├── first.go │ │ ├── second.go │ │ ├── tchan-example.go │ │ └── ttypes.go │ └── main.go ├── fragmentation_test.go ├── fragmenting_reader.go ├── fragmenting_writer.go ├── frame.go ├── frame_pool.go ├── frame_pool_b_test.go ├── frame_pool_test.go ├── frame_test.go ├── frame_utils_test.go ├── go.mod ├── go.sum ├── guide/ │ └── Thrift_Hyperbahn.md ├── handlers.go ├── handlers_test.go ├── handlers_with_skip_test.go ├── health.go ├── health_ext_test.go ├── health_test.go ├── http/ │ ├── buf.go │ ├── buf_test.go │ ├── http_test.go │ ├── request.go │ └── response.go ├── hyperbahn/ │ ├── advertise.go │ ├── advertise_test.go │ ├── call.go │ ├── client.go │ ├── client_test.go │ ├── configuration.go │ ├── discover.go │ ├── discover_test.go │ ├── event_string.go │ ├── events.go │ ├── gen-go/ │ │ └── hyperbahn/ │ │ ├── constants.go │ │ ├── hyperbahn.go │ │ ├── tchan-hyperbahn.go │ │ └── ttypes.go │ ├── hyperbahn.thrift │ ├── utils.go │ └── utils_test.go ├── idle_sweep.go ├── idle_sweep_test.go ├── inbound.go ├── inbound_internal_test.go ├── inbound_test.go ├── incoming_test.go ├── init_test.go ├── internal/ │ ├── argreader/ │ │ ├── empty.go │ │ └── empty_test.go │ └── testcert/ │ └── testcert.go ├── introspection.go ├── introspection_test.go ├── json/ │ ├── call.go │ ├── context.go │ ├── handler.go │ ├── json_test.go │ ├── retry_test.go │ └── tracing_test.go ├── largereq_test.go ├── localip.go ├── localip_test.go ├── logger.go ├── logger_test.go ├── messages.go ├── messages_test.go ├── messagetype_string.go ├── mex.go ├── mex_utils_test.go ├── outbound.go ├── peer.go ├── peer_bench_test.go ├── peer_heap.go ├── peer_heap_test.go ├── peer_internal_test.go ├── peer_strategies.go ├── peer_test.go ├── peers/ │ ├── doc.go │ ├── prefer.go │ └── prefer_test.go ├── pprof/ │ ├── pprof.go │ └── pprof_test.go ├── preinit_connection.go ├── raw/ │ ├── call.go │ └── handler.go ├── relay/ │ ├── relay.go │ └── relaytest/ │ ├── func_host.go │ ├── mock_stats.go │ └── stub_host.go ├── relay.go ├── relay_api.go ├── relay_benchmark_test.go ├── relay_fragment_sender_test.go ├── relay_internal_test.go ├── relay_messages.go ├── relay_messages_benchmark_test.go ├── relay_messages_test.go ├── relay_test.go ├── relay_timer_pool.go ├── reqres.go ├── reqresreaderstate_string.go ├── reqreswriterstate_string.go ├── retry.go ├── retry_request_test.go ├── retry_test.go ├── retryon_string.go ├── root_peer_list.go ├── scripts/ │ ├── install-thrift.sh │ └── vbumper/ │ └── main.go ├── sockio_bsd.go ├── sockio_darwin.go ├── sockio_linux.go ├── sockio_non_unix.go ├── sockio_unix.go ├── stats/ │ ├── metrickey.go │ ├── metrickey_test.go │ ├── statsdreporter.go │ ├── tally.go │ └── tally_test.go ├── stats.go ├── stats_test.go ├── stats_utils_test.go ├── stream_test.go ├── stress_flag_test.go ├── subchannel.go ├── subchannel_test.go ├── systemerrcode_string.go ├── tchannel_test.go ├── testutils/ │ ├── call.go │ ├── channel.go │ ├── channel_opts.go │ ├── channel_t.go │ ├── conn.go │ ├── counter.go │ ├── counter_test.go │ ├── data.go │ ├── echo.go │ ├── goroutines/ │ │ ├── stacks.go │ │ ├── verify.go │ │ └── verify_opts.go │ ├── lists.go │ ├── logfilter_test.go │ ├── logger.go │ ├── mockhyperbahn/ │ │ ├── hyperbahn.go │ │ ├── hyperbahn_test.go │ │ └── utils.go │ ├── now.go │ ├── random_bench_test.go │ ├── relay.go │ ├── sleep.go │ ├── test_server.go │ ├── testreader/ │ │ ├── chunk.go │ │ ├── chunk_test.go │ │ ├── loop.go │ │ └── loop_test.go │ ├── testtracing/ │ │ ├── propagation.go │ │ └── propagation_test.go │ ├── testwriter/ │ │ ├── limited.go │ │ └── limited_test.go │ ├── thriftarg2test/ │ │ ├── arg2_kv.go │ │ └── arg2_kv_test.go │ ├── ticker.go │ ├── ticker_test.go │ ├── timeout.go │ └── wait.go ├── thirdparty/ │ └── github.com/ │ └── apache/ │ └── thrift/ │ └── lib/ │ └── go/ │ └── thrift/ │ ├── application_exception.go │ ├── application_exception_test.go │ ├── binary_protocol.go │ ├── binary_protocol_test.go │ ├── buffered_transport.go │ ├── buffered_transport_test.go │ ├── compact_protocol.go │ ├── compact_protocol_test.go │ ├── debug_protocol.go │ ├── deserializer.go │ ├── exception.go │ ├── exception_test.go │ ├── field.go │ ├── framed_transport.go │ ├── framed_transport_test.go │ ├── http_client.go │ ├── http_client_test.go │ ├── http_transport.go │ ├── iostream_transport.go │ ├── iostream_transport_test.go │ ├── json_protocol.go │ ├── json_protocol_test.go │ ├── lowlevel_benchmarks_test.go │ ├── memory_buffer.go │ ├── memory_buffer_test.go │ ├── messagetype.go │ ├── multiplexed_protocol.go │ ├── numeric.go │ ├── pointerize.go │ ├── processor.go │ ├── processor_factory.go │ ├── protocol.go │ ├── protocol_exception.go │ ├── protocol_factory.go │ ├── protocol_test.go │ ├── rich_transport.go │ ├── rich_transport_test.go │ ├── serializer.go │ ├── serializer_test.go │ ├── serializer_types_test.go │ ├── server.go │ ├── server_socket.go │ ├── server_socket_test.go │ ├── server_test.go │ ├── server_transport.go │ ├── simple_json_protocol.go │ ├── simple_json_protocol_test.go │ ├── simple_server.go │ ├── socket.go │ ├── ssl_server_socket.go │ ├── ssl_socket.go │ ├── transport.go │ ├── transport_exception.go │ ├── transport_exception_test.go │ ├── transport_factory.go │ ├── transport_test.go │ ├── type.go │ ├── zlib_transport.go │ └── zlib_transport_test.go ├── thrift/ │ ├── arg2/ │ │ ├── kv_iterator.go │ │ └── kv_iterator_test.go │ ├── client.go │ ├── context.go │ ├── context_test.go │ ├── doc.go │ ├── errors_test.go │ ├── gen-go/ │ │ ├── meta/ │ │ │ ├── constants.go │ │ │ ├── meta.go │ │ │ └── ttypes.go │ │ └── test/ │ │ ├── constants.go │ │ ├── meta.go │ │ ├── secondservice.go │ │ ├── simpleservice.go │ │ ├── tchan-test.go │ │ └── ttypes.go │ ├── headers.go │ ├── headers_test.go │ ├── interfaces.go │ ├── meta.go │ ├── meta.thrift │ ├── meta_test.go │ ├── mocks/ │ │ ├── TChanMeta.go │ │ ├── TChanSecondService.go │ │ └── TChanSimpleService.go │ ├── options.go │ ├── server.go │ ├── server_test.go │ ├── struct.go │ ├── struct_test.go │ ├── tchan-meta.go │ ├── test.thrift │ ├── thrift-gen/ │ │ ├── compile_test.go │ │ ├── extends.go │ │ ├── generate.go │ │ ├── gopath.go │ │ ├── gopath_test.go │ │ ├── include.go │ │ ├── main.go │ │ ├── names.go │ │ ├── tchannel-template.go │ │ ├── template.go │ │ ├── test_files/ │ │ │ ├── binary.thrift │ │ │ ├── byte.thrift │ │ │ ├── gokeywords.thrift │ │ │ ├── include_test/ │ │ │ │ ├── namespace/ │ │ │ │ │ ├── a/ │ │ │ │ │ │ └── shared.thrift │ │ │ │ │ ├── b/ │ │ │ │ │ │ └── shared.thrift │ │ │ │ │ └── namespace.thrift │ │ │ │ ├── simple/ │ │ │ │ │ ├── shared.thrift │ │ │ │ │ ├── shared2.thrift │ │ │ │ │ └── simple.thrift │ │ │ │ └── svc_extend/ │ │ │ │ ├── shared.thrift │ │ │ │ └── svc_extend.thrift │ │ │ ├── multi_test/ │ │ │ │ ├── file1.thrift │ │ │ │ └── file2.thrift │ │ │ ├── service_extend.thrift │ │ │ ├── sets.thrift │ │ │ ├── test1.thrift │ │ │ ├── typedefs.thrift │ │ │ └── union.thrift │ │ ├── typestate.go │ │ ├── validate.go │ │ └── wrap.go │ ├── thrift_bench_test.go │ ├── thrift_test.go │ ├── tracing_test.go │ ├── transport.go │ └── transport_test.go ├── tnet/ │ ├── listener.go │ └── listener_test.go ├── tos/ │ ├── tos.go │ ├── tos_string.go │ └── tos_test.go ├── trace/ │ └── doc.go ├── tracing.go ├── tracing_internal_test.go ├── tracing_keys.go ├── tracing_test.go ├── trand/ │ └── rand.go ├── typed/ │ ├── buffer.go │ ├── buffer_test.go │ ├── reader.go │ ├── reader_test.go │ ├── writer.go │ └── writer_test.go ├── utils_for_test.go ├── verify_utils_test.go └── version.go
Showing preview only (393K chars total). Download the full file or copy to clipboard to get everything.
SYMBOL INDEX (4358 symbols across 356 files)
FILE: all_channels.go
function registerNewChannel (line 37) | func registerNewChannel(ch *Channel) {
function removeClosedChannel (line 52) | func removeClosedChannel(ch *Channel) {
function findChannelByID (line 71) | func findChannelByID(id uint32) (*Channel, bool) {
FILE: all_channels_test.go
function TestAllChannelsRegistered (line 30) | func TestAllChannelsRegistered(t *testing.T) {
FILE: arguments.go
type ArgReader (line 34) | type ArgReader
type ArgWriter (line 38) | type ArgWriter interface
type ArgWritable (line 48) | type ArgWritable interface
type ArgReadable (line 55) | type ArgReadable interface
type ArgReadHelper (line 61) | type ArgReadHelper struct
method read (line 72) | func (r ArgReadHelper) read(f func() error) error {
method Read (line 86) | func (r ArgReadHelper) Read(bs *[]byte) error {
method ReadJSON (line 95) | func (r ArgReadHelper) ReadJSON(data interface{}) error {
function NewArgReader (line 68) | func NewArgReader(reader ArgReader, err error) ArgReadHelper {
type ArgWriteHelper (line 113) | type ArgWriteHelper struct
method write (line 124) | func (w ArgWriteHelper) write(f func() error) error {
method Write (line 137) | func (w ArgWriteHelper) Write(bs []byte) error {
method WriteJSON (line 145) | func (w ArgWriteHelper) WriteJSON(data interface{}) error {
function NewArgWriter (line 120) | func NewArgWriter(writer io.WriteCloser, err error) ArgWriteHelper {
FILE: arguments_test.go
type bufferWithClose (line 34) | type bufferWithClose struct
method Close (line 50) | func (w *bufferWithClose) Close() error {
function newWriter (line 42) | func newWriter() *bufferWithClose {
function newReader (line 46) | func newReader(bs []byte) *bufferWithClose {
type testObject (line 55) | type testObject struct
function TestJSONInputOutput (line 60) | func TestJSONInputOutput(t *testing.T) {
function TestReadNotEmpty (line 77) | func TestReadNotEmpty(t *testing.T) {
function BenchmarkArgReaderWriter (line 86) | func BenchmarkArgReaderWriter(b *testing.B) {
FILE: benchmark/benchclient/main.go
function main (line 46) | func main() {
function makeCalls (line 98) | func makeCalls(n int, f func(n int) ([]time.Duration, error)) {
FILE: benchmark/benchserver/main.go
function main (line 41) | func main() {
FILE: benchmark/build_manager.go
type buildManager (line 30) | type buildManager struct
method GoBinary (line 49) | func (m *buildManager) GoBinary(mainFile string) (string, error) {
type build (line 35) | type build struct
method Build (line 62) | func (b *build) Build() {
function newBuildManager (line 43) | func newBuildManager() *buildManager {
FILE: benchmark/client_server_bench_test.go
function BenchmarkServer (line 32) | func BenchmarkServer(b *testing.B) {
function BenchmarkClient (line 57) | func BenchmarkClient(b *testing.B) {
FILE: benchmark/external_client.go
type externalClient (line 31) | type externalClient struct
method Warmup (line 59) | func (c *externalClient) Warmup() error {
method callAndParse (line 70) | func (c *externalClient) callAndParse(cmd string) ([]time.Duration, er...
method RawCall (line 94) | func (c *externalClient) RawCall(n int) ([]time.Duration, error) {
method ThriftCall (line 98) | func (c *externalClient) ThriftCall(n int) ([]time.Duration, error) {
function newExternalClient (line 36) | func newExternalClient(hosts []string, opts *options) Client {
FILE: benchmark/external_common.go
type externalCmd (line 33) | type externalCmd struct
method writeAndRead (line 76) | func (c *externalCmd) writeAndRead(cmd string) (string, error) {
method Close (line 88) | func (c *externalCmd) Close() {
function newExternalCmd (line 40) | func newExternalCmd(mainFile string, benchArgs []string) (*externalCmd, ...
FILE: benchmark/external_server.go
type externalServer (line 30) | type externalServer struct
method HostPort (line 53) | func (s *externalServer) HostPort() string {
method RawCalls (line 57) | func (s *externalServer) RawCalls() int {
method ThriftCalls (line 61) | func (s *externalServer) ThriftCalls() int {
method writeAndReadInt (line 65) | func (s *externalServer) writeAndReadInt(cmd string) int {
function newExternalServer (line 36) | func newExternalServer(opts *options) Server {
FILE: benchmark/frame_templates.go
constant _idOffset (line 35) | _idOffset = 4
constant _idOffsetEnd (line 36) | _idOffsetEnd = _idOffset + 4
type frames (line 39) | type frames struct
method duplicate (line 44) | func (f frames) duplicate() frames {
method writeInitReq (line 60) | func (f frames) writeInitReq(w io.Writer) error {
method writeInitRes (line 65) | func (f frames) writeInitRes(w io.Writer) error {
method writeCallReq (line 70) | func (f frames) writeCallReq(id uint32, w io.Writer) (int, error) {
method writeCallRes (line 75) | func (f frames) writeCallRes(id uint32, w io.Writer) (int, error) {
method writeMulti (line 80) | func (f frames) writeMulti(id uint32, w io.Writer, frames [][]byte) (i...
function deepCopyByteSlice (line 51) | func deepCopyByteSlice(bs [][]byte) [][]byte {
function getRawCallFrames (line 93) | func getRawCallFrames(timeout time.Duration, svcName string, reqSize int...
function withNewServerClient (line 135) | func withNewServerClient(svcName string, f func(server, client *tchannel...
FILE: benchmark/interfaces.go
type Client (line 29) | type Client interface
type inProcClient (line 45) | type inProcClient interface
type Server (line 56) | type Server interface
type Relay (line 71) | type Relay interface
FILE: benchmark/internal_client.go
type internalClient (line 36) | type internalClient struct
method Warmup (line 92) | func (c *internalClient) Warmup() error {
method makeCalls (line 106) | func (c *internalClient) makeCalls(latencies []time.Duration, f func()...
method RawCallBuffer (line 117) | func (c *internalClient) RawCallBuffer(latencies []time.Duration) error {
method RawCall (line 140) | func (c *internalClient) RawCall(n int) ([]time.Duration, error) {
method ThriftCallBuffer (line 145) | func (c *internalClient) ThriftCallBuffer(latencies []time.Duration) e...
method ThriftCall (line 166) | func (c *internalClient) ThriftCall(n int) ([]time.Duration, error) {
method Close (line 171) | func (c *internalClient) Close() {
function NewClient (line 47) | func NewClient(hosts []string, optFns ...Option) Client {
function newClient (line 58) | func newClient(hosts []string, opts *options) inProcClient {
function newInternalClient (line 69) | func newInternalClient(hosts []string, opts *options) inProcClient {
FILE: benchmark/internal_multi_client.go
type internalMultiClient (line 29) | type internalMultiClient struct
method Warmup (line 44) | func (c *internalMultiClient) Warmup() error {
method Close (line 53) | func (c *internalMultiClient) Close() {
method RawCall (line 59) | func (c *internalMultiClient) RawCall(n int) ([]time.Duration, error) {
method ThriftCall (line 65) | func (c *internalMultiClient) ThriftCall(n int) ([]time.Duration, erro...
method makeCalls (line 75) | func (c *internalMultiClient) makeCalls(n int, f clientToCallFunc) ([]...
method callUsingClient (line 98) | func (c *internalMultiClient) callUsingClient(latencies []time.Duratio...
function newInternalMultiClient (line 33) | func newInternalMultiClient(hosts []string, opts *options) Client {
type callFunc (line 71) | type callFunc
type clientToCallFunc (line 73) | type clientToCallFunc
FILE: benchmark/internal_server.go
type internalServer (line 38) | type internalServer struct
method HostPort (line 82) | func (s *internalServer) HostPort() string {
method Advertise (line 87) | func (s *internalServer) Advertise(hyperbahnHosts []string) error {
method Close (line 97) | func (s *internalServer) Close() {
method RawCalls (line 104) | func (s *internalServer) RawCalls() int {
method ThriftCalls (line 108) | func (s *internalServer) ThriftCalls() int {
function NewServer (line 47) | func NewServer(optFns ...Option) Server {
type rawHandler (line 112) | type rawHandler struct
method OnError (line 116) | func (rawHandler) OnError(ctx context.Context, err error) {
method Handle (line 120) | func (h rawHandler) Handle(ctx context.Context, args *raw.Args) (*raw....
type handler (line 128) | type handler struct
method Echo (line 132) | func (h handler) Echo(ctx thrift.Context, arg1 string) (string, error) {
FILE: benchmark/internal_tcp_client.go
type internalTCPClient (line 34) | type internalTCPClient struct
method Warmup (line 53) | func (c *internalTCPClient) Warmup() error {
method readConn (line 69) | func (c *internalTCPClient) readConn() {
method makeCalls (line 98) | func (c *internalTCPClient) makeCalls(latencies []time.Duration, f fun...
method RawCallBuffer (line 143) | func (c *internalTCPClient) RawCallBuffer(latencies []time.Duration) e...
method RawCall (line 157) | func (c *internalTCPClient) RawCall(n int) ([]time.Duration, error) {
method ThriftCallBuffer (line 162) | func (c *internalTCPClient) ThriftCallBuffer(latencies []time.Duration...
method ThriftCall (line 166) | func (c *internalTCPClient) ThriftCall(n int) ([]time.Duration, error) {
method Close (line 170) | func (c *internalTCPClient) Close() {
function newInternalTCPClient (line 43) | func newInternalTCPClient(hosts []string, opts *options) inProcClient {
type call (line 92) | type call struct
FILE: benchmark/internal_tcp_server.go
type internalTCPServer (line 34) | type internalTCPServer struct
method acceptLoop (line 56) | func (s *internalTCPServer) acceptLoop() {
method handleConn (line 70) | func (s *internalTCPServer) handleConn(conn net.Conn) {
method writeResponses (line 90) | func (s *internalTCPServer) writeResponses(conn net.Conn, ids chan uin...
method HostPort (line 109) | func (s *internalTCPServer) HostPort() string {
method RawCalls (line 113) | func (s *internalTCPServer) RawCalls() int {
method ThriftCalls (line 117) | func (s *internalTCPServer) ThriftCalls() int {
method Close (line 122) | func (s *internalTCPServer) Close() {
function newInternalTCPServer (line 41) | func newInternalTCPServer(opts *options) Server {
FILE: benchmark/matrix_test.go
function combinations (line 40) | func combinations(length int, f func([]bool)) {
function TestCombinations (line 55) | func TestCombinations(t *testing.T) {
function selectOptions (line 81) | func selectOptions(options []Option, toSelect []bool) []Option {
function combineOpts (line 91) | func combineOpts(base, override []Option) []Option {
function runSingleTest (line 96) | func runSingleTest(t *testing.T, baseOpts, serverOpts, clientOpts []Opti...
function TestServerClientMatrix (line 132) | func TestServerClientMatrix(t *testing.T) {
FILE: benchmark/options.go
type options (line 25) | type options struct
type Option (line 45) | type Option
function WithTimeout (line 48) | func WithTimeout(timeout time.Duration) Option {
function WithRequestSize (line 55) | func WithRequestSize(reqSize int) Option {
function WithServiceName (line 62) | func WithServiceName(svcName string) Option {
function WithExternalProcess (line 69) | func WithExternalProcess() Option {
function WithNoLibrary (line 77) | func WithNoLibrary() Option {
function WithNoChecking (line 86) | func WithNoChecking() Option {
function WithNumClients (line 97) | func WithNumClients(numClients int) Option {
function WithNoDurations (line 104) | func WithNoDurations() Option {
function WithAdvertiseHosts (line 111) | func WithAdvertiseHosts(hosts []string) Option {
function getOptions (line 117) | func getOptions(optFns []Option) *options {
FILE: benchmark/real_relay.go
type fixedHosts (line 33) | type fixedHosts struct
method Get (line 39) | func (fh *fixedHosts) Get(cf relay.CallFrame, _ *relay.Conn) (string, ...
type realRelay (line 53) | type realRelay struct
method HostPort (line 82) | func (r *realRelay) HostPort() string {
method Close (line 86) | func (r *realRelay) Close() {
function NewRealRelay (line 59) | func NewRealRelay(services map[string][]string, appends []relay.KeyVal) ...
FILE: benchmark/req_bytes.go
function getRequestBytes (line 23) | func getRequestBytes(n int) []byte {
function getRequestString (line 31) | func getRequestString(n int) string {
FILE: benchmark/tcp_bench_test.go
function echoServer (line 33) | func echoServer(tb testing.TB) net.Listener {
function benchmarkClient (line 48) | func benchmarkClient(b *testing.B, dst string, reqSize int) {
function benchmarkTCPDirect (line 72) | func benchmarkTCPDirect(b *testing.B, reqSize int) {
function BenchmarkTCPDirect100Bytes (line 77) | func BenchmarkTCPDirect100Bytes(b *testing.B) {
function BenchmarkTCPDirect1k (line 81) | func BenchmarkTCPDirect1k(b *testing.B) {
function BenchmarkTCPDirect4k (line 85) | func BenchmarkTCPDirect4k(b *testing.B) {
function benchmarkTCPRelay (line 89) | func benchmarkTCPRelay(b *testing.B, reqSize int) {
function BenchmarkTCPRelay100Bytes (line 99) | func BenchmarkTCPRelay100Bytes(b *testing.B) {
function BenchmarkTCPRelay1kBytes (line 103) | func BenchmarkTCPRelay1kBytes(b *testing.B) {
function BenchmarkTCPRelay4k (line 107) | func BenchmarkTCPRelay4k(b *testing.B) {
FILE: benchmark/tcp_frame_relay.go
type tcpFrameRelay (line 29) | type tcpFrameRelay struct
method handleConnFrameRelay (line 48) | func (r *tcpFrameRelay) handleConnFrameRelay(fromClient bool, src, dst...
function NewTCPFrameRelay (line 36) | func NewTCPFrameRelay(dests []string, modifier func(bool, *tchannel.Fram...
FILE: benchmark/tcp_raw_relay.go
type tcpRelay (line 31) | type tcpRelay struct
method acceptLoop (line 61) | func (r *tcpRelay) acceptLoop() {
method handleIncoming (line 75) | func (r *tcpRelay) handleIncoming(src net.Conn) {
method nextDestination (line 89) | func (r *tcpRelay) nextDestination() string {
method HostPort (line 94) | func (r *tcpRelay) HostPort() string {
method Close (line 98) | func (r *tcpRelay) Close() {
function newTCPRelay (line 38) | func newTCPRelay(dests []string, handleConn func(fromClient bool, src, d...
function NewTCPRawRelay (line 55) | func NewTCPRawRelay(dests []string) (Relay, error) {
FILE: calloptions.go
type Format (line 24) | type Format
method String (line 34) | func (f Format) String() string {
constant HTTP (line 28) | HTTP Format = "http"
constant JSON (line 29) | JSON Format = "json"
constant Raw (line 30) | Raw Format = "raw"
constant Thrift (line 31) | Thrift Format = "thrift"
type CallOptions (line 39) | type CallOptions struct
method setHeaders (line 67) | func (c *CallOptions) setHeaders(headers transportHeaders) {
method overrideHeaders (line 73) | func (c *CallOptions) overrideHeaders(headers transportHeaders) {
function setResponseHeaders (line 92) | func setResponseHeaders(reqHeaders, respHeaders transportHeaders) {
FILE: calloptions_test.go
function TestSetHeaders (line 29) | func TestSetHeaders(t *testing.T) {
FILE: channel.go
constant ephemeralHostPort (line 51) | ephemeralHostPort = "0.0.0.0:0"
type ChannelOptions (line 54) | type ChannelOptions struct
method validateIdleCheck (line 895) | func (o *ChannelOptions) validateIdleCheck() error {
type ChannelState (line 146) | type ChannelState
constant ChannelClient (line 150) | ChannelClient ChannelState = iota + 1
constant ChannelListening (line 153) | ChannelListening
constant ChannelStartClose (line 157) | ChannelStartClose
constant ChannelInboundClosed (line 161) | ChannelInboundClosed
constant ChannelClosed (line 164) | ChannelClosed
type Channel (line 174) | type Channel struct
method ConnectionOptions (line 363) | func (ch *Channel) ConnectionOptions() *ConnectionOptions {
method Serve (line 370) | func (ch *Channel) Serve(l net.Listener) error {
method ListenAndServe (line 396) | func (ch *Channel) ListenAndServe(hostPort string) error {
method Register (line 448) | func (ch *Channel) Register(h Handler, methodName string) {
method PeerInfo (line 458) | func (ch *Channel) PeerInfo() LocalPeerInfo {
method createCommonStats (line 466) | func (ch *Channel) createCommonStats() {
method GetSubChannel (line 482) | func (ch *Channel) GetSubChannel(serviceName string, opts ...SubChanne...
method Peers (line 493) | func (ch *Channel) Peers() *PeerList {
method RootPeers (line 501) | func (ch *Channel) RootPeers() *RootPeerList {
method BeginCall (line 507) | func (ch *Channel) BeginCall(ctx context.Context, hostPort, serviceNam...
method serve (line 514) | func (ch *Channel) serve() {
method Ping (line 564) | func (ch *Channel) Ping(ctx context.Context, hostPort string) error {
method Logger (line 575) | func (ch *Channel) Logger() Logger {
method StatsReporter (line 580) | func (ch *Channel) StatsReporter() StatsReporter {
method StatsTags (line 586) | func (ch *Channel) StatsTags() map[string]string {
method ServiceName (line 595) | func (ch *Channel) ServiceName() string {
method Connect (line 600) | func (ch *Channel) Connect(ctx context.Context, hostPort string) (*Con...
method exchangeUpdated (line 669) | func (ch *Channel) exchangeUpdated(c *Connection) {
method updatePeer (line 684) | func (ch *Channel) updatePeer(p *Peer) {
method addConnection (line 693) | func (ch *Channel) addConnection(c *Connection, direction connectionDi...
method connectionActive (line 712) | func (ch *Channel) connectionActive(c *Connection, direction connectio...
method addConnectionToPeer (line 724) | func (ch *Channel) addConnectionToPeer(hostPort string, c *Connection,...
method inboundConnectionActive (line 737) | func (ch *Channel) inboundConnectionActive(c *Connection) {
method outboundConnectionActive (line 741) | func (ch *Channel) outboundConnectionActive(c *Connection) {
method removeClosedConn (line 747) | func (ch *Channel) removeClosedConn(c *Connection) {
method getMinConnectionState (line 757) | func (ch *Channel) getMinConnectionState() connectionState {
method connectionCloseStateChange (line 768) | func (ch *Channel) connectionCloseStateChange(c *Connection) {
method onClosed (line 819) | func (ch *Channel) onClosed() {
method Closed (line 827) | func (ch *Channel) Closed() bool {
method ClosedChan (line 833) | func (ch *Channel) ClosedChan() <-chan struct{} {
method State (line 838) | func (ch *Channel) State() ChannelState {
method Close (line 850) | func (ch *Channel) Close() {
method RelayHost (line 891) | func (ch *Channel) RelayHost() RelayHost {
type channelConnectionCommon (line 207) | type channelConnectionCommon struct
method Tracer (line 223) | func (ccc channelConnectionCommon) Tracer() opentracing.Tracer {
function NewChannel (line 233) | func NewChannel(serviceName string, opts *ChannelOptions) (*Channel, err...
type Registrar (line 417) | type Registrar interface
function toStringSet (line 903) | func toStringSet(ss []string) map[string]struct{} {
function toServiceMethodSet (line 913) | func toServiceMethodSet(sms []string) (map[string]struct{}, error) {
FILE: channel_test.go
function toMap (line 38) | func toMap(fields LogFields) map[string]interface{} {
function TestNewChannel (line 46) | func TestNewChannel(t *testing.T) {
function TestLoggers (line 67) | func TestLoggers(t *testing.T) {
function TestStats (line 84) | func TestStats(t *testing.T) {
function TestRelayMaxTTL (line 110) | func TestRelayMaxTTL(t *testing.T) {
function TestIsolatedSubChannelsDontSharePeers (line 132) | func TestIsolatedSubChannelsDontSharePeers(t *testing.T) {
function TestChannelTracerMethod (line 164) | func TestChannelTracerMethod(t *testing.T) {
function TestToServiceMethodSet (line 186) | func TestToServiceMethodSet(t *testing.T) {
FILE: channel_utils_test.go
function NewServer (line 32) | func NewServer(t testing.TB, opts *testutils.ChannelOpts) (*Channel, str...
FILE: channelstate_string.go
constant _ChannelState_name (line 7) | _ChannelState_name = "ChannelClientChannelListeningChannelStartCloseChan...
method String (line 11) | func (i ChannelState) String() string {
FILE: checked_frame_pool.go
type CheckedFramePoolForTest (line 14) | type CheckedFramePoolForTest struct
method Get (line 29) | func (p *CheckedFramePoolForTest) Get() *Frame {
method Release (line 39) | func (p *CheckedFramePoolForTest) Release(f *Frame) {
method CheckEmpty (line 72) | func (p *CheckedFramePoolForTest) CheckEmpty() CheckedFramePoolForTest...
function NewCheckedFramePoolForTest (line 22) | func NewCheckedFramePoolForTest() *CheckedFramePoolForTest {
type CheckedFramePoolForTestResult (line 61) | type CheckedFramePoolForTestResult struct
method HasIssues (line 67) | func (r CheckedFramePoolForTestResult) HasIssues() bool {
function recordStack (line 87) | func recordStack() string {
function zeroOut (line 93) | func zeroOut(bs []byte) {
FILE: checked_frame_pool_test.go
function TestCheckedFramePoolForTest (line 11) | func TestCheckedFramePoolForTest(t *testing.T) {
function CheckFramePoolIsEmpty (line 69) | func CheckFramePoolIsEmpty(t testing.TB, pool *CheckedFramePoolForTest) {
FILE: checksum.go
type ChecksumType (line 32) | type ChecksumType
method ChecksumSize (line 70) | func (t ChecksumType) ChecksumSize() int {
method pool (line 84) | func (t ChecksumType) pool() *sync.Pool {
method New (line 89) | func (t ChecksumType) New() Checksum {
method Release (line 96) | func (t ChecksumType) Release(checksum Checksum) {
constant ChecksumTypeNone (line 36) | ChecksumTypeNone ChecksumType = 0
constant ChecksumTypeCrc32 (line 39) | ChecksumTypeCrc32 ChecksumType = 1
constant ChecksumTypeFarmhash (line 42) | ChecksumTypeFarmhash ChecksumType = 2
constant ChecksumTypeCrc32C (line 45) | ChecksumTypeCrc32C ChecksumType = 3
constant checksumCount (line 47) | checksumCount = 4
function init (line 50) | func init() {
type Checksum (line 101) | type Checksum interface
type nullChecksum (line 122) | type nullChecksum struct
method TypeCode (line 125) | func (c nullChecksum) TypeCode() ChecksumType { return ChecksumTypeNone }
method Size (line 128) | func (c nullChecksum) Size() int { return 0 }
method Add (line 131) | func (c nullChecksum) Add(b []byte) []byte { return nil }
method Sum (line 134) | func (c nullChecksum) Sum() []byte { return nil }
method Release (line 137) | func (c nullChecksum) Release() {
method Reset (line 142) | func (c nullChecksum) Reset() {}
type hashChecksum (line 145) | type hashChecksum struct
method TypeCode (line 160) | func (h *hashChecksum) TypeCode() ChecksumType { return h.checksumType }
method Size (line 163) | func (h *hashChecksum) Size() int { return h.hash.Size() }
method Add (line 166) | func (h *hashChecksum) Add(b []byte) []byte { h.hash.Write(b); return ...
method Sum (line 169) | func (h *hashChecksum) Sum() []byte { return h.hash.Sum(h.sumCache) }
method Release (line 172) | func (h *hashChecksum) Release() { h.TypeCode().Release(h) }
method Reset (line 175) | func (h *hashChecksum) Reset() { h.hash.Reset() }
function newHashChecksum (line 151) | func newHashChecksum(t ChecksumType, hash hash.Hash) *hashChecksum {
type noReleaseChecksum (line 180) | type noReleaseChecksum struct
method Release (line 184) | func (n *noReleaseChecksum) Release() {}
FILE: close_test.go
type channelState (line 40) | type channelState struct
function makeCall (line 46) | func makeCall(client *Channel, server *testutils.TestServer) error {
function assertStateChangesTo (line 54) | func assertStateChangesTo(t testing.TB, ch *Channel, state ChannelState) {
function TestCloseOnlyListening (line 62) | func TestCloseOnlyListening(t *testing.T) {
function TestCloseNewClient (line 71) | func TestCloseNewClient(t *testing.T) {
function ignoreError (line 80) | func ignoreError(h *testHandler) Handler {
function TestCloseAfterTimeout (line 87) | func TestCloseAfterTimeout(t *testing.T) {
function TestRelayCloseTimeout (line 111) | func TestRelayCloseTimeout(t *testing.T) {
function TestRaceExchangesWithClose (line 148) | func TestRaceExchangesWithClose(t *testing.T) {
function TestCloseStress (line 275) | func TestCloseStress(t *testing.T) {
type closeSemanticsTest (line 372) | type closeSemanticsTest struct
method makeServer (line 377) | func (t *closeSemanticsTest) makeServer(name string) (*Channel, chan s...
method withNewClient (line 391) | func (t *closeSemanticsTest) withNewClient(f func(ch *Channel)) {
method startCall (line 397) | func (t *closeSemanticsTest) startCall(from *Channel, to *Channel, met...
method call (line 412) | func (t *closeSemanticsTest) call(from *Channel, to *Channel) error {
method callStream (line 420) | func (t *closeSemanticsTest) callStream(from *Channel, to *Channel) <-...
method runTest (line 438) | func (t *closeSemanticsTest) runTest() {
function TestCloseSemantics (line 490) | func TestCloseSemantics(t *testing.T) {
function TestCloseSemanticsIsolated (line 499) | func TestCloseSemanticsIsolated(t *testing.T) {
function TestCloseSingleChannel (line 508) | func TestCloseSingleChannel(t *testing.T) {
function TestCloseOneSide (line 551) | func TestCloseOneSide(t *testing.T) {
function TestCloseSendError (line 595) | func TestCloseSendError(t *testing.T) {
FILE: conn_leak_test.go
type loggerPtr (line 45) | type loggerPtr struct
method WithFields (line 49) | func (l *loggerPtr) WithFields(fields ...LogField) Logger {
function TestPeerConnectionLeaks (line 53) | func TestPeerConnectionLeaks(t *testing.T) {
FILE: connection.go
constant CurrentProtocolVersion (line 45) | CurrentProtocolVersion = 0x02
constant DefaultConnectTimeout (line 49) | DefaultConnectTimeout = 5 * time.Second
constant DefaultConnectionBufferSize (line 53) | DefaultConnectionBufferSize = 512
type PeerVersion (line 58) | type PeerVersion struct
type PeerInfo (line 65) | type PeerInfo struct
method String (line 79) | func (p PeerInfo) String() string {
method IsEphemeralHostPort (line 84) | func (p PeerInfo) IsEphemeralHostPort() bool {
type LocalPeerInfo (line 89) | type LocalPeerInfo struct
method String (line 96) | func (p LocalPeerInfo) String() string {
type errConnectionUnknownState (line 118) | type errConnectionUnknownState struct
method Error (line 123) | func (e errConnectionUnknownState) Error() string {
type SendBufferSizeOverride (line 129) | type SendBufferSizeOverride struct
type ConnectionOptions (line 135) | type ConnectionOptions struct
method withDefaults (line 276) | func (co ConnectionOptions) withDefaults() ConnectionOptions {
method getSendBufferSize (line 290) | func (co ConnectionOptions) getSendBufferSize(processName string) int {
type connectionEvents (line 175) | type connectionEvents struct
type Connection (line 187) | type Connection struct
method onCancel (line 391) | func (c *Connection) onCancel(msgID uint32) {
method onExchangeAdded (line 405) | func (c *Connection) onExchangeAdded() {
method IsActive (line 410) | func (c *Connection) IsActive() bool {
method callOnActive (line 414) | func (c *Connection) callOnActive() {
method callOnCloseStateChange (line 436) | func (c *Connection) callOnCloseStateChange() {
method callOnExchangeChange (line 442) | func (c *Connection) callOnExchangeChange() {
method ping (line 449) | func (c *Connection) ping(ctx context.Context) error {
method handlePingRes (line 465) | func (c *Connection) handlePingRes(frame *Frame) bool {
method handlePingReq (line 475) | func (c *Connection) handlePingReq(frame *Frame) {
method sendMessage (line 488) | func (c *Connection) sendMessage(msg message) error {
method recvMessage (line 505) | func (c *Connection) recvMessage(ctx context.Context, msg message, mex...
method RemotePeerInfo (line 520) | func (c *Connection) RemotePeerInfo() PeerInfo {
method NextMessageID (line 525) | func (c *Connection) NextMessageID() uint32 {
method SendSystemError (line 530) | func (c *Connection) SendSystemError(id uint32, span Span, err error) ...
method logConnectionError (line 582) | func (c *Connection) logConnectionError(site string, err error) error {
method connectionError (line 605) | func (c *Connection) connectionError(site string, err error) error {
method protocolError (line 631) | func (c *Connection) protocolError(id uint32, err error) error {
method withStateLock (line 650) | func (c *Connection) withStateLock(f func() error) error {
method withStateRLock (line 659) | func (c *Connection) withStateRLock(f func() error) error {
method readState (line 667) | func (c *Connection) readState() connectionState {
method readFrames (line 679) | func (c *Connection) readFrames(_ uint32) {
method handleFrameRelay (line 719) | func (c *Connection) handleFrameRelay(frame *Frame) bool {
method handleFrameNoRelay (line 744) | func (c *Connection) handleFrameNoRelay(frame *Frame) bool {
method writeFrames (line 778) | func (c *Connection) writeFrames(_ uint32) {
method updateLastActivityRead (line 816) | func (c *Connection) updateLastActivityRead(frame *Frame) {
method updateLastActivityWrite (line 824) | func (c *Connection) updateLastActivityWrite(frame *Frame) {
method hasPendingCalls (line 831) | func (c *Connection) hasPendingCalls() bool {
method checkExchanges (line 843) | func (c *Connection) checkExchanges() {
method close (line 903) | func (c *Connection) close(fields ...LogField) error {
method Close (line 938) | func (c *Connection) Close() error {
method closeNetwork (line 945) | func (c *Connection) closeNetwork() {
method getLastActivityReadTime (line 963) | func (c *Connection) getLastActivityReadTime() time.Time {
method getLastActivityWriteTime (line 970) | func (c *Connection) getLastActivityWriteTime() time.Time {
type peerAddressComponents (line 237) | type peerAddressComponents struct
type connectionState (line 247) | type connectionState
constant connectionActive (line 251) | connectionActive connectionState = iota + 1
constant connectionStartClose (line 255) | connectionStartClose
constant connectionInboundClosed (line 259) | connectionInboundClosed
constant connectionClosed (line 262) | connectionClosed
function getTimeout (line 267) | func getTimeout(ctx context.Context) time.Duration {
method setConnectionTosPriority (line 299) | func (ch *Channel) setConnectionTosPriority(tosPriority tos.ToS, c net.C...
method newConnection (line 316) | func (ch *Channel) newConnection(baseCtx context.Context, conn net.Conn,...
function getSysConn (line 974) | func getSysConn(conn net.Conn, log Logger) syscall.RawConn {
function isMessageTypeCall (line 1002) | func isMessageTypeCall(frame *Frame) bool {
FILE: connection_bench_test.go
constant benchService (line 39) | benchService = "bench-server"
type benchmarkHandler (line 41) | type benchmarkHandler struct
method Handle (line 43) | func (h *benchmarkHandler) Handle(ctx context.Context, args *raw.Args)...
method OnError (line 50) | func (h *benchmarkHandler) OnError(ctx context.Context, err error) {
type latencyTracker (line 53) | type latencyTracker struct
method addLatency (line 73) | func (lt *latencyTracker) addLatency(d time.Duration) {
method report (line 79) | func (lt *latencyTracker) report(t testing.TB) {
function newLatencyTracker (line 60) | func newLatencyTracker() *latencyTracker {
function setupServer (line 94) | func setupServer(t testing.TB) *Channel {
type benchmarkConfig (line 101) | type benchmarkConfig struct
function benchmarkCallsN (line 109) | func benchmarkCallsN(b *testing.B, c benchmarkConfig) {
function BenchmarkCallsSerial (line 171) | func BenchmarkCallsSerial(b *testing.B) {
function BenchmarkCallsConcurrentServer (line 180) | func BenchmarkCallsConcurrentServer(b *testing.B) {
function BenchmarkCallsConcurrentClient (line 189) | func BenchmarkCallsConcurrentClient(b *testing.B) {
FILE: connection_direction.go
type connectionDirection (line 25) | type connectionDirection
method String (line 32) | func (d connectionDirection) String() string {
constant inbound (line 28) | inbound connectionDirection = iota + 1
constant outbound (line 29) | outbound
FILE: connection_internal_test.go
type errSyscallConn (line 35) | type errSyscallConn struct
method SyscallConn (line 39) | func (c errSyscallConn) SyscallConn() (syscall.RawConn, error) {
function TestGetSysConn (line 43) | func TestGetSysConn(t *testing.T) {
FILE: connection_test.go
constant inbound (line 54) | inbound = 0
constant outbound (line 55) | outbound = 1
type testHandler (line 63) | type testHandler struct
method Handle (line 76) | func (h *testHandler) Handle(ctx context.Context, args *raw.Args) (*ra...
method OnError (line 108) | func (h *testHandler) OnError(ctx context.Context, err error) {
function newTestHandler (line 72) | func newTestHandler(t testing.TB) *testHandler {
function writeFlushStr (line 114) | func writeFlushStr(w ArgWriter, d string) error {
function isTosPriority (line 121) | func isTosPriority(c net.Conn, tosPriority tos.ToS) (bool, error) {
function getErrorFrame (line 135) | func getErrorFrame(t testing.TB) *Frame {
function TestRoundTrip (line 153) | func TestRoundTrip(t *testing.T) {
function TestDefaultFormat (line 183) | func TestDefaultFormat(t *testing.T) {
function TestRemotePeer (line 201) | func TestRemotePeer(t *testing.T) {
function TestReuseConnection (line 262) | func TestReuseConnection(t *testing.T) {
function TestPing (line 318) | func TestPing(t *testing.T) {
function TestBadRequest (line 350) | func TestBadRequest(t *testing.T) {
function TestNoTimeout (line 367) | func TestNoTimeout(t *testing.T) {
function TestCancelled (line 379) | func TestCancelled(t *testing.T) {
function TestNoServiceNaming (line 396) | func TestNoServiceNaming(t *testing.T) {
function TestServerBusy (line 408) | func TestServerBusy(t *testing.T) {
function TestUnexpectedHandlerError (line 430) | func TestUnexpectedHandlerError(t *testing.T) {
type onErrorTestHandler (line 455) | type onErrorTestHandler struct
method OnError (line 460) | func (h onErrorTestHandler) OnError(ctx context.Context, err error) {
function TestTimeout (line 464) | func TestTimeout(t *testing.T) {
function TestServerClientCancellation (line 494) | func TestServerClientCancellation(t *testing.T) {
function TestCancelWithoutSendCancelOnContextCanceled (line 537) | func TestCancelWithoutSendCancelOnContextCanceled(t *testing.T) {
function TestLargeMethod (line 606) | func TestLargeMethod(t *testing.T) {
function TestLargeTimeout (line 617) | func TestLargeTimeout(t *testing.T) {
function TestFragmentation (line 633) | func TestFragmentation(t *testing.T) {
function TestFragmentationSlowReader (line 661) | func TestFragmentationSlowReader(t *testing.T) {
function TestWriteArg3AfterTimeout (line 701) | func TestWriteArg3AfterTimeout(t *testing.T) {
function TestLargeSendSystemError (line 749) | func TestLargeSendSystemError(t *testing.T) {
function TestWriteErrorAfterTimeout (line 788) | func TestWriteErrorAfterTimeout(t *testing.T) {
function TestWriteAfterConnectionError (line 822) | func TestWriteAfterConnectionError(t *testing.T) {
function TestReadTimeout (line 859) | func TestReadTimeout(t *testing.T) {
function TestWriteTimeout (line 890) | func TestWriteTimeout(t *testing.T) {
function TestGracefulClose (line 913) | func TestGracefulClose(t *testing.T) {
function TestNetDialTimeout (line 930) | func TestNetDialTimeout(t *testing.T) {
function TestConnectTimeout (line 957) | func TestConnectTimeout(t *testing.T) {
function TestParallelConnectionAccepts (line 999) | func TestParallelConnectionAccepts(t *testing.T) {
function TestConnectionIDs (line 1017) | func TestConnectionIDs(t *testing.T) {
function TestTosPriority (line 1055) | func TestTosPriority(t *testing.T) {
function TestPeerStatusChangeClientReduction (line 1075) | func TestPeerStatusChangeClientReduction(t *testing.T) {
function TestPeerStatusChangeClient (line 1105) | func TestPeerStatusChangeClient(t *testing.T) {
function TestPeerStatusChangeServer (line 1146) | func TestPeerStatusChangeServer(t *testing.T) {
function TestContextCanceledOnTCPClose (line 1177) | func TestContextCanceledOnTCPClose(t *testing.T) {
function getConnection (line 1250) | func getConnection(t testing.TB, ch *Channel, direction int) *Connection...
function TestLastActivityTime (line 1271) | func TestLastActivityTime(t *testing.T) {
function TestLastActivityTimePings (line 1356) | func TestLastActivityTimePings(t *testing.T) {
function TestSendBufferSize (line 1397) | func TestSendBufferSize(t *testing.T) {
function TestInvalidTransportHeaders (line 1457) | func TestInvalidTransportHeaders(t *testing.T) {
function TestCustomDialer (line 1520) | func TestCustomDialer(t *testing.T) {
function TestInboundConnContext (line 1544) | func TestInboundConnContext(t *testing.T) {
function TestOutboundConnContext (line 1564) | func TestOutboundConnContext(t *testing.T) {
function TestWithTLSNoRelay (line 1587) | func TestWithTLSNoRelay(t *testing.T) {
function TestWithTLSRelayOnly (line 1617) | func TestWithTLSRelayOnly(t *testing.T) {
FILE: connectionstate_string.go
constant _connectionState_name (line 7) | _connectionState_name = "connectionActiveconnectionStartCloseconnectionI...
method String (line 11) | func (i connectionState) String() string {
FILE: context.go
constant defaultTimeout (line 29) | defaultTimeout = time.Second
type contextKey (line 31) | type contextKey
constant contextKeyTChannel (line 34) | contextKeyTChannel contextKey = iota
constant contextKeyHeaders (line 35) | contextKeyHeaders
type tchannelCtxParams (line 38) | type tchannelCtxParams struct
type IncomingCall (line 49) | type IncomingCall interface
function getTChannelParams (line 77) | func getTChannelParams(ctx context.Context) *tchannelCtxParams {
function NewContext (line 85) | func NewContext(timeout time.Duration) (context.Context, context.CancelF...
function WrapContextForTest (line 92) | func WrapContextForTest(ctx context.Context, call IncomingCall) context....
function newIncomingContext (line 98) | func newIncomingContext(ctx context.Context, call IncomingCall, timeout ...
function CurrentCall (line 106) | func CurrentCall(ctx context.Context) IncomingCall {
function currentCallOptions (line 113) | func currentCallOptions(ctx context.Context) *CallOptions {
function isTracingDisabled (line 120) | func isTracingDisabled(ctx context.Context) bool {
FILE: context_builder.go
type ContextBuilder (line 31) | type ContextBuilder struct
method SetTimeout (line 80) | func (cb *ContextBuilder) SetTimeout(timeout time.Duration) *ContextBu...
method AddHeader (line 86) | func (cb *ContextBuilder) AddHeader(key, value string) *ContextBuilder {
method SetHeaders (line 97) | func (cb *ContextBuilder) SetHeaders(headers map[string]string) *Conte...
method SetShardKey (line 104) | func (cb *ContextBuilder) SetShardKey(sk string) *ContextBuilder {
method SetFormat (line 113) | func (cb *ContextBuilder) SetFormat(f Format) *ContextBuilder {
method SetRoutingKey (line 122) | func (cb *ContextBuilder) SetRoutingKey(rk string) *ContextBuilder {
method SetRoutingDelegate (line 131) | func (cb *ContextBuilder) SetRoutingDelegate(rd string) *ContextBuilder {
method SetConnectTimeout (line 142) | func (cb *ContextBuilder) SetConnectTimeout(d time.Duration) *ContextB...
method SetConnectBaseContext (line 148) | func (cb *ContextBuilder) SetConnectBaseContext(ctx context.Context) *...
method HideListeningOnOutbound (line 155) | func (cb *ContextBuilder) HideListeningOnOutbound() *ContextBuilder {
method DisableTracing (line 161) | func (cb *ContextBuilder) DisableTracing() *ContextBuilder {
method SetIncomingCallForTest (line 168) | func (cb *ContextBuilder) SetIncomingCallForTest(call IncomingCall) *C...
method SetRetryOptions (line 173) | func (cb *ContextBuilder) SetRetryOptions(retryOptions *RetryOptions) ...
method SetTimeoutPerAttempt (line 179) | func (cb *ContextBuilder) SetTimeoutPerAttempt(timeoutPerAttempt time....
method SetParentContext (line 188) | func (cb *ContextBuilder) SetParentContext(ctx context.Context) *Conte...
method setIncomingCall (line 193) | func (cb *ContextBuilder) setIncomingCall(call IncomingCall) *ContextB...
method getHeaders (line 198) | func (cb *ContextBuilder) getHeaders() map[string]string {
method Build (line 219) | func (cb *ContextBuilder) Build() (ContextWithHeaders, context.CancelF...
function NewContextBuilder (line 73) | func NewContextBuilder(timeout time.Duration) *ContextBuilder {
FILE: context_header.go
type ContextWithHeaders (line 26) | type ContextWithHeaders interface
type headerCtx (line 43) | type headerCtx struct
method headers (line 53) | func (c headerCtx) headers() *headersContainer {
method Headers (line 61) | func (c headerCtx) Headers() map[string]string {
method ResponseHeaders (line 69) | func (c headerCtx) ResponseHeaders() map[string]string {
method SetResponseHeaders (line 77) | func (c headerCtx) SetResponseHeaders(headers map[string]string) {
method Child (line 86) | func (c headerCtx) Child() ContextWithHeaders {
type headersContainer (line 48) | type headersContainer struct
function Wrap (line 97) | func Wrap(ctx context.Context) ContextWithHeaders {
function WrapWithHeaders (line 110) | func WrapWithHeaders(ctx context.Context, headers map[string]string) Con...
function WithoutHeaders (line 119) | func WithoutHeaders(ctx context.Context) context.Context {
FILE: context_internal_test.go
function TestNewContextBuilderDisableTracing (line 33) | func TestNewContextBuilderDisableTracing(t *testing.T) {
function TestCurrentSpan (line 41) | func TestCurrentSpan(t *testing.T) {
function TestContextWithoutHeadersKeyHeaders (line 59) | func TestContextWithoutHeadersKeyHeaders(t *testing.T) {
function TestContextWithoutHeadersKeyTChannel (line 68) | func TestContextWithoutHeadersKeyTChannel(t *testing.T) {
FILE: context_test.go
function TestWrapContextForTest (line 39) | func TestWrapContextForTest(t *testing.T) {
function TestNewContextTimeoutZero (line 47) | func TestNewContextTimeoutZero(t *testing.T) {
function TestRoutingDelegatePropagates (line 56) | func TestRoutingDelegatePropagates(t *testing.T) {
function TestRoutingKeyPropagates (line 79) | func TestRoutingKeyPropagates(t *testing.T) {
function TestShardKeyPropagates (line 102) | func TestShardKeyPropagates(t *testing.T) {
function TestCurrentCallWithNilResult (line 126) | func TestCurrentCallWithNilResult(t *testing.T) {
function getParentContext (line 133) | func getParentContext(t *testing.T) ContextWithHeaders {
function TestContextBuilderParentContextNoHeaders (line 145) | func TestContextBuilderParentContextNoHeaders(t *testing.T) {
function TestContextBuilderParentContextMergeHeaders (line 151) | func TestContextBuilderParentContextMergeHeaders(t *testing.T) {
function TestContextBuilderParentContextReplaceHeaders (line 180) | func TestContextBuilderParentContextReplaceHeaders(t *testing.T) {
function TestContextWrapWithHeaders (line 198) | func TestContextWrapWithHeaders(t *testing.T) {
function TestContextWithHeadersAsContext (line 214) | func TestContextWithHeadersAsContext(t *testing.T) {
function TestContextBuilderParentContextSpan (line 219) | func TestContextBuilderParentContextSpan(t *testing.T) {
function TestContextWrapChild (line 231) | func TestContextWrapChild(t *testing.T) {
function TestContextInheritParentTimeout (line 291) | func TestContextInheritParentTimeout(t *testing.T) {
FILE: deps_test.go
function TestJaegerDeps (line 36) | func TestJaegerDeps(t *testing.T) {
FILE: dial_16.go
function dialContext (line 32) | func dialContext(ctx context.Context, hostPort string) (net.Conn, error) {
FILE: dial_17.go
function dialContext (line 31) | func dialContext(ctx context.Context, hostPort string) (net.Conn, error) {
FILE: dial_17_test.go
function TestNetDialCancelContext (line 37) | func TestNetDialCancelContext(t *testing.T) {
FILE: errors.go
constant invalidMessageID (line 31) | invalidMessageID uint32 = 0xFFFFFFFF
type SystemErrCode (line 35) | type SystemErrCode
method MetricsKey (line 102) | func (c SystemErrCode) MetricsKey() string {
method relayMetricsKey (line 128) | func (c SystemErrCode) relayMetricsKey() string {
constant ErrCodeInvalid (line 41) | ErrCodeInvalid SystemErrCode = 0x00
constant ErrCodeTimeout (line 45) | ErrCodeTimeout SystemErrCode = 0x01
constant ErrCodeCancelled (line 49) | ErrCodeCancelled SystemErrCode = 0x02
constant ErrCodeBusy (line 54) | ErrCodeBusy SystemErrCode = 0x03
constant ErrCodeDeclined (line 60) | ErrCodeDeclined SystemErrCode = 0x04
constant ErrCodeUnexpected (line 65) | ErrCodeUnexpected SystemErrCode = 0x05
constant ErrCodeBadRequest (line 69) | ErrCodeBadRequest SystemErrCode = 0x06
constant ErrCodeNetwork (line 73) | ErrCodeNetwork SystemErrCode = 0x07
constant ErrCodeProtocol (line 77) | ErrCodeProtocol SystemErrCode = 0xFF
type SystemError (line 156) | type SystemError struct
method Error (line 177) | func (se SystemError) Error() string {
method Wrapped (line 182) | func (se SystemError) Wrapped() error { return se.wrapped }
method Code (line 185) | func (se SystemError) Code() SystemErrCode {
method Message (line 190) | func (se SystemError) Message() string {
function NewSystemError (line 163) | func NewSystemError(code SystemErrCode, msg string, args ...interface{})...
function NewWrappedSystemError (line 168) | func NewWrappedSystemError(code SystemErrCode, wrapped error) error {
function GetContextError (line 195) | func GetContextError(err error) error {
function GetSystemErrorCode (line 207) | func GetSystemErrorCode(err error) SystemErrCode {
function GetSystemErrorMessage (line 221) | func GetSystemErrorMessage(err error) string {
type errConnNotActive (line 229) | type errConnNotActive struct
method Error (line 234) | func (e errConnNotActive) Error() string {
FILE: errors_test.go
function TestErrorMetricKeys (line 31) | func TestErrorMetricKeys(t *testing.T) {
function TestInvalidError (line 55) | func TestInvalidError(t *testing.T) {
function TestUnexpectedError (line 60) | func TestUnexpectedError(t *testing.T) {
function TestSystemError (line 65) | func TestSystemError(t *testing.T) {
function TestRelayMetricsKey (line 70) | func TestRelayMetricsKey(t *testing.T) {
FILE: examples/bench/client/client.go
function main (line 49) | func main() {
function requestCountReporter (line 71) | func requestCountReporter() {
function worker (line 79) | func worker(ch *tchannel.Channel) {
function setRequest (line 98) | func setRequest(ch *tchannel.Channel, key, value string) error {
function getRequest (line 104) | func getRequest(ch *tchannel.Channel, key string) (string, error) {
FILE: examples/bench/runner.go
function main (line 46) | func main() {
function runServer (line 100) | func runServer(hostPort string, numThreads int) (*exec.Cmd, error) {
function runClient (line 112) | func runClient(clientArgs []string) (*exec.Cmd, error) {
function dumpProfile (line 116) | func dumpProfile(baseHostPort, profileFile string) (*exec.Cmd, error) {
function runCmd (line 122) | func runCmd(cmdBinary string, args ...string) (*exec.Cmd, error) {
FILE: examples/bench/server/server.go
function main (line 46) | func main() {
function setupServer (line 67) | func setupServer(host string, basePort, instanceNum int) error {
type kvHandler (line 88) | type kvHandler struct
method WithLock (line 93) | func (h *kvHandler) WithLock(write bool, f func()) {
method Ping (line 109) | func (h *kvHandler) Ping(ctx context.Context, args *raw.Args) (*raw.Re...
method Get (line 115) | func (h *kvHandler) Get(ctx context.Context, args *raw.Args) (*raw.Res...
method Set (line 127) | func (h *kvHandler) Set(ctx context.Context, args *raw.Args) (*raw.Res...
method Handle (line 137) | func (h *kvHandler) Handle(ctx context.Context, args *raw.Args) (*raw....
method OnError (line 150) | func (h *kvHandler) OnError(ctx context.Context, err error) {
FILE: examples/hyperbahn/echo-server/main.go
function main (line 37) | func main() {
type eventHandler (line 80) | type eventHandler struct
method On (line 82) | func (eventHandler) On(event hyperbahn.Event) {
method OnError (line 86) | func (eventHandler) OnError(err error) {
type handler (line 90) | type handler struct
method OnError (line 94) | func (h handler) OnError(ctx context.Context, err error) {
method Handle (line 98) | func (h handler) Handle(ctx context.Context, args *raw.Args) (*raw.Res...
FILE: examples/hypercat/main.go
function parseArgs (line 54) | func parseArgs() {
function main (line 79) | func main() {
function onError (line 100) | func onError(msg string, args ...interface{}) {
function handler (line 104) | func handler(ctx context.Context, call *tchannel.InboundCall) {
function spawnProcess (line 140) | func spawnProcess(reader io.Reader, writer io.Writer) error {
FILE: examples/keyvalue/client/client.go
function printHelp (line 39) | func printHelp() {
function main (line 44) | func main() {
function get (line 102) | func get(client keyvalue.TChanKeyValue, key string) {
function set (line 122) | func set(client keyvalue.TChanKeyValue, key, value string) {
function clear (line 139) | func clear(adminClient keyvalue.TChanAdmin) {
function createContext (line 156) | func createContext() (thrift.Context, func()) {
FILE: examples/keyvalue/gen-go/keyvalue/admin.go
type Admin (line 17) | type Admin interface
type AdminClient (line 23) | type AdminClient struct
method ClearAll (line 35) | func (p *AdminClient) ClearAll() (err error) {
method sendClearAll (line 42) | func (p *AdminClient) sendClearAll() (err error) {
method recvClearAll (line 62) | func (p *AdminClient) recvClearAll() (err error) {
function NewAdminClientFactory (line 27) | func NewAdminClientFactory(t thrift.TTransport, f thrift.TProtocolFactor...
function NewAdminClientProtocol (line 31) | func NewAdminClientProtocol(t thrift.TTransport, iprot thrift.TProtocol,...
type AdminProcessor (line 111) | type AdminProcessor struct
function NewAdminProcessor (line 115) | func NewAdminProcessor(handler Admin) *AdminProcessor {
type adminProcessorClearAll (line 121) | type adminProcessorClearAll struct
method Process (line 125) | func (p *adminProcessorClearAll) Process(seqId int32, iprot, oprot thr...
type AdminClearAllArgs (line 173) | type AdminClearAllArgs struct
method Read (line 180) | func (p *AdminClearAllArgs) Read(iprot thrift.TProtocol) error {
method Write (line 206) | func (p *AdminClearAllArgs) Write(oprot thrift.TProtocol) error {
method String (line 219) | func (p *AdminClearAllArgs) String() string {
function NewAdminClearAllArgs (line 176) | func NewAdminClearAllArgs() *AdminClearAllArgs {
type AdminClearAllResult (line 228) | type AdminClearAllResult struct
method GetNotAuthorized (line 238) | func (p *AdminClearAllResult) GetNotAuthorized() *NotAuthorized {
method IsSetNotAuthorized (line 244) | func (p *AdminClearAllResult) IsSetNotAuthorized() bool {
method Read (line 248) | func (p *AdminClearAllResult) Read(iprot thrift.TProtocol) error {
method ReadField1 (line 281) | func (p *AdminClearAllResult) ReadField1(iprot thrift.TProtocol) error {
method Write (line 289) | func (p *AdminClearAllResult) Write(oprot thrift.TProtocol) error {
method writeField1 (line 305) | func (p *AdminClearAllResult) writeField1(oprot thrift.TProtocol) (err...
method String (line 320) | func (p *AdminClearAllResult) String() string {
function NewAdminClearAllResult (line 232) | func NewAdminClearAllResult() *AdminClearAllResult {
FILE: examples/keyvalue/gen-go/keyvalue/baseservice.go
type BaseService (line 17) | type BaseService interface
type BaseServiceClient (line 21) | type BaseServiceClient struct
method HealthCheck (line 47) | func (p *BaseServiceClient) HealthCheck() (r string, err error) {
method sendHealthCheck (line 54) | func (p *BaseServiceClient) sendHealthCheck() (err error) {
method recvHealthCheck (line 74) | func (p *BaseServiceClient) recvHealthCheck() (value string, err error) {
function NewBaseServiceClientFactory (line 29) | func NewBaseServiceClientFactory(t thrift.TTransport, f thrift.TProtocol...
function NewBaseServiceClientProtocol (line 38) | func NewBaseServiceClientProtocol(t thrift.TTransport, iprot thrift.TPro...
type BaseServiceProcessor (line 120) | type BaseServiceProcessor struct
method AddToProcessorMap (line 125) | func (p *BaseServiceProcessor) AddToProcessorMap(key string, processor...
method GetProcessorFunction (line 129) | func (p *BaseServiceProcessor) GetProcessorFunction(key string) (proce...
method ProcessorMap (line 134) | func (p *BaseServiceProcessor) ProcessorMap() map[string]thrift.TProce...
method Process (line 145) | func (p *BaseServiceProcessor) Process(iprot, oprot thrift.TProtocol) ...
function NewBaseServiceProcessor (line 138) | func NewBaseServiceProcessor(handler BaseService) *BaseServiceProcessor {
type baseServiceProcessorHealthCheck (line 164) | type baseServiceProcessorHealthCheck struct
method Process (line 168) | func (p *baseServiceProcessorHealthCheck) Process(seqId int32, iprot, ...
type BaseServiceHealthCheckArgs (line 214) | type BaseServiceHealthCheckArgs struct
method Read (line 221) | func (p *BaseServiceHealthCheckArgs) Read(iprot thrift.TProtocol) error {
method Write (line 247) | func (p *BaseServiceHealthCheckArgs) Write(oprot thrift.TProtocol) err...
method String (line 260) | func (p *BaseServiceHealthCheckArgs) String() string {
function NewBaseServiceHealthCheckArgs (line 217) | func NewBaseServiceHealthCheckArgs() *BaseServiceHealthCheckArgs {
type BaseServiceHealthCheckResult (line 269) | type BaseServiceHealthCheckResult struct
method GetSuccess (line 279) | func (p *BaseServiceHealthCheckResult) GetSuccess() string {
method IsSetSuccess (line 285) | func (p *BaseServiceHealthCheckResult) IsSetSuccess() bool {
method Read (line 289) | func (p *BaseServiceHealthCheckResult) Read(iprot thrift.TProtocol) er...
method ReadField0 (line 322) | func (p *BaseServiceHealthCheckResult) ReadField0(iprot thrift.TProtoc...
method Write (line 331) | func (p *BaseServiceHealthCheckResult) Write(oprot thrift.TProtocol) e...
method writeField0 (line 347) | func (p *BaseServiceHealthCheckResult) writeField0(oprot thrift.TProto...
method String (line 362) | func (p *BaseServiceHealthCheckResult) String() string {
function NewBaseServiceHealthCheckResult (line 273) | func NewBaseServiceHealthCheckResult() *BaseServiceHealthCheckResult {
FILE: examples/keyvalue/gen-go/keyvalue/constants.go
function init (line 17) | func init() {
FILE: examples/keyvalue/gen-go/keyvalue/keyvalue.go
type KeyValue (line 17) | type KeyValue interface
type KeyValueClient (line 29) | type KeyValueClient struct
method Get (line 43) | func (p *KeyValueClient) Get(key string) (r string, err error) {
method sendGet (line 50) | func (p *KeyValueClient) sendGet(key string) (err error) {
method recvGet (line 72) | func (p *KeyValueClient) recvGet() (value string, err error) {
method Set (line 128) | func (p *KeyValueClient) Set(key string, value string) (err error) {
method sendSet (line 135) | func (p *KeyValueClient) sendSet(key string, value string) (err error) {
method recvSet (line 158) | func (p *KeyValueClient) recvSet() (err error) {
function NewKeyValueClientFactory (line 33) | func NewKeyValueClientFactory(t thrift.TTransport, f thrift.TProtocolFac...
function NewKeyValueClientProtocol (line 37) | func NewKeyValueClientProtocol(t thrift.TTransport, iprot thrift.TProtoc...
type KeyValueProcessor (line 207) | type KeyValueProcessor struct
function NewKeyValueProcessor (line 211) | func NewKeyValueProcessor(handler KeyValue) *KeyValueProcessor {
type keyValueProcessorGet (line 218) | type keyValueProcessorGet struct
method Process (line 222) | func (p *keyValueProcessorGet) Process(seqId int32, iprot, oprot thrif...
type keyValueProcessorSet (line 273) | type keyValueProcessorSet struct
method Process (line 277) | func (p *keyValueProcessorSet) Process(seqId int32, iprot, oprot thrif...
type KeyValueGetArgs (line 327) | type KeyValueGetArgs struct
method GetKey (line 335) | func (p *KeyValueGetArgs) GetKey() string {
method Read (line 338) | func (p *KeyValueGetArgs) Read(iprot thrift.TProtocol) error {
method ReadField1 (line 371) | func (p *KeyValueGetArgs) ReadField1(iprot thrift.TProtocol) error {
method Write (line 380) | func (p *KeyValueGetArgs) Write(oprot thrift.TProtocol) error {
method writeField1 (line 396) | func (p *KeyValueGetArgs) writeField1(oprot thrift.TProtocol) (err err...
method String (line 409) | func (p *KeyValueGetArgs) String() string {
function NewKeyValueGetArgs (line 331) | func NewKeyValueGetArgs() *KeyValueGetArgs {
type KeyValueGetResult (line 420) | type KeyValueGetResult struct
method GetSuccess (line 432) | func (p *KeyValueGetResult) GetSuccess() string {
method GetNotFound (line 441) | func (p *KeyValueGetResult) GetNotFound() *KeyNotFound {
method GetInvalidKey (line 450) | func (p *KeyValueGetResult) GetInvalidKey() *InvalidKey {
method IsSetSuccess (line 456) | func (p *KeyValueGetResult) IsSetSuccess() bool {
method IsSetNotFound (line 460) | func (p *KeyValueGetResult) IsSetNotFound() bool {
method IsSetInvalidKey (line 464) | func (p *KeyValueGetResult) IsSetInvalidKey() bool {
method Read (line 468) | func (p *KeyValueGetResult) Read(iprot thrift.TProtocol) error {
method ReadField0 (line 509) | func (p *KeyValueGetResult) ReadField0(iprot thrift.TProtocol) error {
method ReadField1 (line 518) | func (p *KeyValueGetResult) ReadField1(iprot thrift.TProtocol) error {
method ReadField2 (line 526) | func (p *KeyValueGetResult) ReadField2(iprot thrift.TProtocol) error {
method Write (line 534) | func (p *KeyValueGetResult) Write(oprot thrift.TProtocol) error {
method writeField0 (line 556) | func (p *KeyValueGetResult) writeField0(oprot thrift.TProtocol) (err e...
method writeField1 (line 571) | func (p *KeyValueGetResult) writeField1(oprot thrift.TProtocol) (err e...
method writeField2 (line 586) | func (p *KeyValueGetResult) writeField2(oprot thrift.TProtocol) (err e...
method String (line 601) | func (p *KeyValueGetResult) String() string {
function NewKeyValueGetResult (line 426) | func NewKeyValueGetResult() *KeyValueGetResult {
type KeyValueSetArgs (line 611) | type KeyValueSetArgs struct
method GetKey (line 620) | func (p *KeyValueSetArgs) GetKey() string {
method GetValue (line 624) | func (p *KeyValueSetArgs) GetValue() string {
method Read (line 627) | func (p *KeyValueSetArgs) Read(iprot thrift.TProtocol) error {
method ReadField1 (line 664) | func (p *KeyValueSetArgs) ReadField1(iprot thrift.TProtocol) error {
method ReadField2 (line 673) | func (p *KeyValueSetArgs) ReadField2(iprot thrift.TProtocol) error {
method Write (line 682) | func (p *KeyValueSetArgs) Write(oprot thrift.TProtocol) error {
method writeField1 (line 701) | func (p *KeyValueSetArgs) writeField1(oprot thrift.TProtocol) (err err...
method writeField2 (line 714) | func (p *KeyValueSetArgs) writeField2(oprot thrift.TProtocol) (err err...
method String (line 727) | func (p *KeyValueSetArgs) String() string {
function NewKeyValueSetArgs (line 616) | func NewKeyValueSetArgs() *KeyValueSetArgs {
type KeyValueSetResult (line 736) | type KeyValueSetResult struct
method GetInvalidKey (line 746) | func (p *KeyValueSetResult) GetInvalidKey() *InvalidKey {
method IsSetInvalidKey (line 752) | func (p *KeyValueSetResult) IsSetInvalidKey() bool {
method Read (line 756) | func (p *KeyValueSetResult) Read(iprot thrift.TProtocol) error {
method ReadField1 (line 789) | func (p *KeyValueSetResult) ReadField1(iprot thrift.TProtocol) error {
method Write (line 797) | func (p *KeyValueSetResult) Write(oprot thrift.TProtocol) error {
method writeField1 (line 813) | func (p *KeyValueSetResult) writeField1(oprot thrift.TProtocol) (err e...
method String (line 828) | func (p *KeyValueSetResult) String() string {
function NewKeyValueSetResult (line 740) | func NewKeyValueSetResult() *KeyValueSetResult {
FILE: examples/keyvalue/gen-go/keyvalue/tchan-keyvalue.go
type TChanAdmin (line 16) | type TChanAdmin interface
type TChanKeyValue (line 23) | type TChanKeyValue interface
type TChanBaseService (line 31) | type TChanBaseService interface
type tchanAdminClient (line 37) | type tchanAdminClient struct
method ClearAll (line 57) | func (c *tchanAdminClient) ClearAll(ctx thrift.Context) error {
function NewTChanAdminInheritedClient (line 44) | func NewTChanAdminInheritedClient(thriftService string, client thrift.TC...
function NewTChanAdminClient (line 53) | func NewTChanAdminClient(client thrift.TChanClient) TChanAdmin {
type tchanAdminServer (line 73) | type tchanAdminServer struct
method Service (line 88) | func (s *tchanAdminServer) Service() string {
method Methods (line 92) | func (s *tchanAdminServer) Methods() []string {
method Handle (line 100) | func (s *tchanAdminServer) Handle(ctx thrift.Context, methodName strin...
method handleClearAll (line 112) | func (s *tchanAdminServer) handleClearAll(ctx thrift.Context, protocol...
function NewTChanAdminServer (line 81) | func NewTChanAdminServer(handler TChanAdmin) thrift.TChanServer {
type tchanKeyValueClient (line 139) | type tchanKeyValueClient struct
method Get (line 159) | func (c *tchanKeyValueClient) Get(ctx thrift.Context, key string) (str...
method Set (line 179) | func (c *tchanKeyValueClient) Set(ctx thrift.Context, key string, valu...
function NewTChanKeyValueInheritedClient (line 146) | func NewTChanKeyValueInheritedClient(thriftService string, client thrift...
function NewTChanKeyValueClient (line 155) | func NewTChanKeyValueClient(client thrift.TChanClient) TChanKeyValue {
type tchanKeyValueServer (line 198) | type tchanKeyValueServer struct
method Service (line 213) | func (s *tchanKeyValueServer) Service() string {
method Methods (line 217) | func (s *tchanKeyValueServer) Methods() []string {
method Handle (line 226) | func (s *tchanKeyValueServer) Handle(ctx thrift.Context, methodName st...
method handleGet (line 240) | func (s *tchanKeyValueServer) handleGet(ctx thrift.Context, protocol a...
method handleSet (line 273) | func (s *tchanKeyValueServer) handleSet(ctx thrift.Context, protocol a...
function NewTChanKeyValueServer (line 206) | func NewTChanKeyValueServer(handler TChanKeyValue) thrift.TChanServer {
type tchanBaseServiceClient (line 300) | type tchanBaseServiceClient struct
method HealthCheck (line 317) | func (c *tchanBaseServiceClient) HealthCheck(ctx thrift.Context) (stri...
function NewTChanBaseServiceInheritedClient (line 305) | func NewTChanBaseServiceInheritedClient(thriftService string, client thr...
function NewTChanBaseServiceClient (line 313) | func NewTChanBaseServiceClient(client thrift.TChanClient) TChanBaseServi...
type tchanBaseServiceServer (line 331) | type tchanBaseServiceServer struct
method Service (line 343) | func (s *tchanBaseServiceServer) Service() string {
method Methods (line 347) | func (s *tchanBaseServiceServer) Methods() []string {
method Handle (line 353) | func (s *tchanBaseServiceServer) Handle(ctx thrift.Context, methodName...
method handleHealthCheck (line 363) | func (s *tchanBaseServiceServer) handleHealthCheck(ctx thrift.Context,...
function NewTChanBaseServiceServer (line 337) | func NewTChanBaseServiceServer(handler TChanBaseService) thrift.TChanSer...
FILE: examples/keyvalue/gen-go/keyvalue/ttypes.go
type KeyNotFound (line 21) | type KeyNotFound struct
method GetKey (line 29) | func (p *KeyNotFound) GetKey() string {
method Read (line 32) | func (p *KeyNotFound) Read(iprot thrift.TProtocol) error {
method ReadField1 (line 65) | func (p *KeyNotFound) ReadField1(iprot thrift.TProtocol) error {
method Write (line 74) | func (p *KeyNotFound) Write(oprot thrift.TProtocol) error {
method writeField1 (line 90) | func (p *KeyNotFound) writeField1(oprot thrift.TProtocol) (err error) {
method String (line 103) | func (p *KeyNotFound) String() string {
method Error (line 110) | func (p *KeyNotFound) Error() string {
function NewKeyNotFound (line 25) | func NewKeyNotFound() *KeyNotFound {
type InvalidKey (line 114) | type InvalidKey struct
method Read (line 121) | func (p *InvalidKey) Read(iprot thrift.TProtocol) error {
method Write (line 147) | func (p *InvalidKey) Write(oprot thrift.TProtocol) error {
method String (line 160) | func (p *InvalidKey) String() string {
method Error (line 167) | func (p *InvalidKey) Error() string {
function NewInvalidKey (line 117) | func NewInvalidKey() *InvalidKey {
type NotAuthorized (line 171) | type NotAuthorized struct
method Read (line 178) | func (p *NotAuthorized) Read(iprot thrift.TProtocol) error {
method Write (line 204) | func (p *NotAuthorized) Write(oprot thrift.TProtocol) error {
method String (line 217) | func (p *NotAuthorized) String() string {
method Error (line 224) | func (p *NotAuthorized) Error() string {
function NewNotAuthorized (line 174) | func NewNotAuthorized() *NotAuthorized {
FILE: examples/keyvalue/server/server.go
function main (line 38) | func main() {
type kvHandler (line 80) | type kvHandler struct
method Get (line 91) | func (h *kvHandler) Get(ctx thrift.Context, key string) (string, error) {
method Set (line 107) | func (h *kvHandler) Set(ctx thrift.Context, key, value string) error {
method HealthCheck (line 122) | func (h *kvHandler) HealthCheck(ctx thrift.Context) (string, error) {
method ClearAll (line 127) | func (h *kvHandler) ClearAll(ctx thrift.Context) error {
function newKVHandler (line 86) | func newKVHandler() *kvHandler {
function isValidKey (line 139) | func isValidKey(key string) error {
function isAdmin (line 147) | func isAdmin(ctx thrift.Context) bool {
FILE: examples/ping/main.go
type Ping (line 36) | type Ping struct
type Pong (line 41) | type Pong
function pingHandler (line 43) | func pingHandler(ctx json.Context, ping *Ping) (*Pong, error) {
function pingOtherHandler (line 49) | func pingOtherHandler(ctx json.Context, ping *Ping) (*Pong, error) {
function onError (line 55) | func onError(ctx context.Context, err error) {
function listenAndHandle (line 59) | func listenAndHandle(s *tchannel.Channel, hostPort string) {
function main (line 71) | func main() {
FILE: examples/test_server/server.go
type rawHandler (line 39) | type rawHandler struct
method Handle (line 41) | func (rawHandler) Handle(ctx context.Context, args *raw.Args) (*raw.Re...
method OnError (line 48) | func (rawHandler) OnError(ctx context.Context, err error) {
function main (line 52) | func main() {
FILE: examples/thrift/gen-go/example/base.go
type Base (line 17) | type Base interface
type BaseClient (line 21) | type BaseClient struct
method BaseCall (line 47) | func (p *BaseClient) BaseCall() (err error) {
method sendBaseCall (line 54) | func (p *BaseClient) sendBaseCall() (err error) {
method recvBaseCall (line 74) | func (p *BaseClient) recvBaseCall() (err error) {
function NewBaseClientFactory (line 29) | func NewBaseClientFactory(t thrift.TTransport, f thrift.TProtocolFactory...
function NewBaseClientProtocol (line 38) | func NewBaseClientProtocol(t thrift.TTransport, iprot thrift.TProtocol, ...
type BaseProcessor (line 119) | type BaseProcessor struct
method AddToProcessorMap (line 124) | func (p *BaseProcessor) AddToProcessorMap(key string, processor thrift...
method GetProcessorFunction (line 128) | func (p *BaseProcessor) GetProcessorFunction(key string) (processor th...
method ProcessorMap (line 133) | func (p *BaseProcessor) ProcessorMap() map[string]thrift.TProcessorFun...
method Process (line 144) | func (p *BaseProcessor) Process(iprot, oprot thrift.TProtocol) (succes...
function NewBaseProcessor (line 137) | func NewBaseProcessor(handler Base) *BaseProcessor {
type baseProcessorBaseCall (line 163) | type baseProcessorBaseCall struct
method Process (line 167) | func (p *baseProcessorBaseCall) Process(seqId int32, iprot, oprot thri...
type BaseBaseCallArgs (line 210) | type BaseBaseCallArgs struct
method Read (line 217) | func (p *BaseBaseCallArgs) Read(iprot thrift.TProtocol) error {
method Write (line 243) | func (p *BaseBaseCallArgs) Write(oprot thrift.TProtocol) error {
method String (line 256) | func (p *BaseBaseCallArgs) String() string {
function NewBaseBaseCallArgs (line 213) | func NewBaseBaseCallArgs() *BaseBaseCallArgs {
type BaseBaseCallResult (line 263) | type BaseBaseCallResult struct
method Read (line 270) | func (p *BaseBaseCallResult) Read(iprot thrift.TProtocol) error {
method Write (line 296) | func (p *BaseBaseCallResult) Write(oprot thrift.TProtocol) error {
method String (line 309) | func (p *BaseBaseCallResult) String() string {
function NewBaseBaseCallResult (line 266) | func NewBaseBaseCallResult() *BaseBaseCallResult {
FILE: examples/thrift/gen-go/example/constants.go
function init (line 17) | func init() {
FILE: examples/thrift/gen-go/example/first.go
type First (line 17) | type First interface
type FirstClient (line 27) | type FirstClient struct
method Echo (line 41) | func (p *FirstClient) Echo(msg string) (r string, err error) {
method sendEcho (line 48) | func (p *FirstClient) sendEcho(msg string) (err error) {
method recvEcho (line 70) | func (p *FirstClient) recvEcho() (value string, err error) {
method Healthcheck (line 116) | func (p *FirstClient) Healthcheck() (r *HealthCheckRes, err error) {
method sendHealthcheck (line 123) | func (p *FirstClient) sendHealthcheck() (err error) {
method recvHealthcheck (line 143) | func (p *FirstClient) recvHealthcheck() (value *HealthCheckRes, err er...
method AppError (line 189) | func (p *FirstClient) AppError() (err error) {
method sendAppError (line 196) | func (p *FirstClient) sendAppError() (err error) {
method recvAppError (line 216) | func (p *FirstClient) recvAppError() (err error) {
function NewFirstClientFactory (line 31) | func NewFirstClientFactory(t thrift.TTransport, f thrift.TProtocolFactor...
function NewFirstClientProtocol (line 35) | func NewFirstClientProtocol(t thrift.TTransport, iprot thrift.TProtocol,...
type FirstProcessor (line 261) | type FirstProcessor struct
function NewFirstProcessor (line 265) | func NewFirstProcessor(handler First) *FirstProcessor {
type firstProcessorEcho (line 273) | type firstProcessorEcho struct
method Process (line 277) | func (p *firstProcessorEcho) Process(seqId int32, iprot, oprot thrift....
type firstProcessorHealthcheck (line 321) | type firstProcessorHealthcheck struct
method Process (line 325) | func (p *firstProcessorHealthcheck) Process(seqId int32, iprot, oprot ...
type firstProcessorAppError (line 369) | type firstProcessorAppError struct
method Process (line 373) | func (p *firstProcessorAppError) Process(seqId int32, iprot, oprot thr...
type FirstEchoArgs (line 418) | type FirstEchoArgs struct
method GetMsg (line 426) | func (p *FirstEchoArgs) GetMsg() string {
method Read (line 429) | func (p *FirstEchoArgs) Read(iprot thrift.TProtocol) error {
method ReadField1 (line 462) | func (p *FirstEchoArgs) ReadField1(iprot thrift.TProtocol) error {
method Write (line 471) | func (p *FirstEchoArgs) Write(oprot thrift.TProtocol) error {
method writeField1 (line 487) | func (p *FirstEchoArgs) writeField1(oprot thrift.TProtocol) (err error) {
method String (line 500) | func (p *FirstEchoArgs) String() string {
function NewFirstEchoArgs (line 422) | func NewFirstEchoArgs() *FirstEchoArgs {
type FirstEchoResult (line 509) | type FirstEchoResult struct
method GetSuccess (line 519) | func (p *FirstEchoResult) GetSuccess() string {
method IsSetSuccess (line 525) | func (p *FirstEchoResult) IsSetSuccess() bool {
method Read (line 529) | func (p *FirstEchoResult) Read(iprot thrift.TProtocol) error {
method ReadField0 (line 562) | func (p *FirstEchoResult) ReadField0(iprot thrift.TProtocol) error {
method Write (line 571) | func (p *FirstEchoResult) Write(oprot thrift.TProtocol) error {
method writeField0 (line 587) | func (p *FirstEchoResult) writeField0(oprot thrift.TProtocol) (err err...
method String (line 602) | func (p *FirstEchoResult) String() string {
function NewFirstEchoResult (line 513) | func NewFirstEchoResult() *FirstEchoResult {
type FirstHealthcheckArgs (line 609) | type FirstHealthcheckArgs struct
method Read (line 616) | func (p *FirstHealthcheckArgs) Read(iprot thrift.TProtocol) error {
method Write (line 642) | func (p *FirstHealthcheckArgs) Write(oprot thrift.TProtocol) error {
method String (line 655) | func (p *FirstHealthcheckArgs) String() string {
function NewFirstHealthcheckArgs (line 612) | func NewFirstHealthcheckArgs() *FirstHealthcheckArgs {
type FirstHealthcheckResult (line 664) | type FirstHealthcheckResult struct
method GetSuccess (line 674) | func (p *FirstHealthcheckResult) GetSuccess() *HealthCheckRes {
method IsSetSuccess (line 680) | func (p *FirstHealthcheckResult) IsSetSuccess() bool {
method Read (line 684) | func (p *FirstHealthcheckResult) Read(iprot thrift.TProtocol) error {
method ReadField0 (line 717) | func (p *FirstHealthcheckResult) ReadField0(iprot thrift.TProtocol) er...
method Write (line 725) | func (p *FirstHealthcheckResult) Write(oprot thrift.TProtocol) error {
method writeField0 (line 741) | func (p *FirstHealthcheckResult) writeField0(oprot thrift.TProtocol) (...
method String (line 756) | func (p *FirstHealthcheckResult) String() string {
function NewFirstHealthcheckResult (line 668) | func NewFirstHealthcheckResult() *FirstHealthcheckResult {
type FirstAppErrorArgs (line 763) | type FirstAppErrorArgs struct
method Read (line 770) | func (p *FirstAppErrorArgs) Read(iprot thrift.TProtocol) error {
method Write (line 796) | func (p *FirstAppErrorArgs) Write(oprot thrift.TProtocol) error {
method String (line 809) | func (p *FirstAppErrorArgs) String() string {
function NewFirstAppErrorArgs (line 766) | func NewFirstAppErrorArgs() *FirstAppErrorArgs {
type FirstAppErrorResult (line 816) | type FirstAppErrorResult struct
method Read (line 823) | func (p *FirstAppErrorResult) Read(iprot thrift.TProtocol) error {
method Write (line 849) | func (p *FirstAppErrorResult) Write(oprot thrift.TProtocol) error {
method String (line 862) | func (p *FirstAppErrorResult) String() string {
function NewFirstAppErrorResult (line 819) | func NewFirstAppErrorResult() *FirstAppErrorResult {
FILE: examples/thrift/gen-go/example/second.go
type Second (line 17) | type Second interface
type SecondClient (line 21) | type SecondClient struct
method Test (line 47) | func (p *SecondClient) Test() (err error) {
method sendTest (line 54) | func (p *SecondClient) sendTest() (err error) {
method recvTest (line 74) | func (p *SecondClient) recvTest() (err error) {
function NewSecondClientFactory (line 29) | func NewSecondClientFactory(t thrift.TTransport, f thrift.TProtocolFacto...
function NewSecondClientProtocol (line 38) | func NewSecondClientProtocol(t thrift.TTransport, iprot thrift.TProtocol...
type SecondProcessor (line 119) | type SecondProcessor struct
method AddToProcessorMap (line 124) | func (p *SecondProcessor) AddToProcessorMap(key string, processor thri...
method GetProcessorFunction (line 128) | func (p *SecondProcessor) GetProcessorFunction(key string) (processor ...
method ProcessorMap (line 133) | func (p *SecondProcessor) ProcessorMap() map[string]thrift.TProcessorF...
method Process (line 144) | func (p *SecondProcessor) Process(iprot, oprot thrift.TProtocol) (succ...
function NewSecondProcessor (line 137) | func NewSecondProcessor(handler Second) *SecondProcessor {
type secondProcessorTest (line 163) | type secondProcessorTest struct
method Process (line 167) | func (p *secondProcessorTest) Process(seqId int32, iprot, oprot thrift...
type SecondTestArgs (line 210) | type SecondTestArgs struct
method Read (line 217) | func (p *SecondTestArgs) Read(iprot thrift.TProtocol) error {
method Write (line 243) | func (p *SecondTestArgs) Write(oprot thrift.TProtocol) error {
method String (line 256) | func (p *SecondTestArgs) String() string {
function NewSecondTestArgs (line 213) | func NewSecondTestArgs() *SecondTestArgs {
type SecondTestResult (line 263) | type SecondTestResult struct
method Read (line 270) | func (p *SecondTestResult) Read(iprot thrift.TProtocol) error {
method Write (line 296) | func (p *SecondTestResult) Write(oprot thrift.TProtocol) error {
method String (line 309) | func (p *SecondTestResult) String() string {
function NewSecondTestResult (line 266) | func NewSecondTestResult() *SecondTestResult {
FILE: examples/thrift/gen-go/example/tchan-example.go
type TChanBase (line 16) | type TChanBase interface
type TChanFirst (line 21) | type TChanFirst interface
type TChanSecond (line 30) | type TChanSecond interface
type tchanBaseClient (line 36) | type tchanBaseClient struct
method BaseCall (line 53) | func (c *tchanBaseClient) BaseCall(ctx thrift.Context) error {
function NewTChanBaseInheritedClient (line 41) | func NewTChanBaseInheritedClient(thriftService string, client thrift.TCh...
function NewTChanBaseClient (line 49) | func NewTChanBaseClient(client thrift.TChanClient) TChanBase {
type tchanBaseServer (line 67) | type tchanBaseServer struct
method Service (line 79) | func (s *tchanBaseServer) Service() string {
method Methods (line 83) | func (s *tchanBaseServer) Methods() []string {
method Handle (line 89) | func (s *tchanBaseServer) Handle(ctx thrift.Context, methodName string...
method handleBaseCall (line 99) | func (s *tchanBaseServer) handleBaseCall(ctx thrift.Context, protocol ...
function NewTChanBaseServer (line 73) | func NewTChanBaseServer(handler TChanBase) thrift.TChanServer {
type tchanFirstClient (line 118) | type tchanFirstClient struct
method AppError (line 138) | func (c *tchanFirstClient) AppError(ctx thrift.Context) error {
method Echo (line 152) | func (c *tchanFirstClient) Echo(ctx thrift.Context, msg string) (strin...
method Healthcheck (line 168) | func (c *tchanFirstClient) Healthcheck(ctx thrift.Context) (*HealthChe...
function NewTChanFirstInheritedClient (line 125) | func NewTChanFirstInheritedClient(thriftService string, client thrift.TC...
function NewTChanFirstClient (line 134) | func NewTChanFirstClient(client thrift.TChanClient) TChanFirst {
type tchanFirstServer (line 182) | type tchanFirstServer struct
method Service (line 197) | func (s *tchanFirstServer) Service() string {
method Methods (line 201) | func (s *tchanFirstServer) Methods() []string {
method Handle (line 211) | func (s *tchanFirstServer) Handle(ctx thrift.Context, methodName strin...
method handleAppError (line 227) | func (s *tchanFirstServer) handleAppError(ctx thrift.Context, protocol...
method handleEcho (line 246) | func (s *tchanFirstServer) handleEcho(ctx thrift.Context, protocol ath...
method handleHealthcheck (line 266) | func (s *tchanFirstServer) handleHealthcheck(ctx thrift.Context, proto...
function NewTChanFirstServer (line 190) | func NewTChanFirstServer(handler TChanFirst) thrift.TChanServer {
type tchanSecondClient (line 286) | type tchanSecondClient struct
method Test (line 303) | func (c *tchanSecondClient) Test(ctx thrift.Context) error {
function NewTChanSecondInheritedClient (line 291) | func NewTChanSecondInheritedClient(thriftService string, client thrift.T...
function NewTChanSecondClient (line 299) | func NewTChanSecondClient(client thrift.TChanClient) TChanSecond {
type tchanSecondServer (line 317) | type tchanSecondServer struct
method Service (line 329) | func (s *tchanSecondServer) Service() string {
method Methods (line 333) | func (s *tchanSecondServer) Methods() []string {
method Handle (line 339) | func (s *tchanSecondServer) Handle(ctx thrift.Context, methodName stri...
method handleTest (line 349) | func (s *tchanSecondServer) handleTest(ctx thrift.Context, protocol at...
function NewTChanSecondServer (line 323) | func NewTChanSecondServer(handler TChanSecond) thrift.TChanServer {
FILE: examples/thrift/gen-go/example/ttypes.go
type HealthCheckRes (line 22) | type HealthCheckRes struct
method GetHealthy (line 31) | func (p *HealthCheckRes) GetHealthy() bool {
method GetMsg (line 35) | func (p *HealthCheckRes) GetMsg() string {
method Read (line 38) | func (p *HealthCheckRes) Read(iprot thrift.TProtocol) error {
method ReadField1 (line 75) | func (p *HealthCheckRes) ReadField1(iprot thrift.TProtocol) error {
method ReadField2 (line 84) | func (p *HealthCheckRes) ReadField2(iprot thrift.TProtocol) error {
method Write (line 93) | func (p *HealthCheckRes) Write(oprot thrift.TProtocol) error {
method writeField1 (line 112) | func (p *HealthCheckRes) writeField1(oprot thrift.TProtocol) (err erro...
method writeField2 (line 125) | func (p *HealthCheckRes) writeField2(oprot thrift.TProtocol) (err erro...
method String (line 138) | func (p *HealthCheckRes) String() string {
function NewHealthCheckRes (line 27) | func NewHealthCheckRes() *HealthCheckRes {
FILE: examples/thrift/main.go
function main (line 39) | func main() {
function setupServer (line 63) | func setupServer() (net.Listener, error) {
function runClient1 (line 83) | func runClient1(hyperbahnService string, addr net.Addr) error {
function runClient2 (line 106) | func runClient2(hyperbahnService string, addr net.Addr) error {
function listenConsole (line 126) | func listenConsole() {
function printStack (line 139) | func printStack() {
type firstHandler (line 145) | type firstHandler struct
method Healthcheck (line 147) | func (h *firstHandler) Healthcheck(ctx thrift.Context) (*gen.HealthChe...
method BaseCall (line 154) | func (h *firstHandler) BaseCall(ctx thrift.Context) error {
method Echo (line 159) | func (h *firstHandler) Echo(ctx thrift.Context, msg string) (r string,...
method AppError (line 164) | func (h *firstHandler) AppError(ctx thrift.Context) error {
method OneWay (line 169) | func (h *firstHandler) OneWay(ctx thrift.Context) error {
type secondHandler (line 174) | type secondHandler struct
method Test (line 176) | func (h *secondHandler) Test(ctx thrift.Context) error {
function optsFor (line 181) | func optsFor(processName string) *tchannel.ChannelOptions {
FILE: fragmentation_test.go
constant testFragmentHeaderSize (line 37) | testFragmentHeaderSize = 1 /* flags */ + 1 /* checksum type */ + 4
constant testFragmentPayloadSize (line 39) | testFragmentPayloadSize = 10
constant testFragmentSize (line 40) | testFragmentSize = testFragmentHeaderSize + testFragmentPayloadSize
function TestFragmentationEmptyArgs (line 43) | func TestFragmentationEmptyArgs(t *testing.T) {
function TestFragmentationSingleFragment (line 53) | func TestFragmentationSingleFragment(t *testing.T) {
function TestFragmentationMultipleFragments (line 63) | func TestFragmentationMultipleFragments(t *testing.T) {
function TestFragmentationMiddleArgNearFragmentBoundary (line 90) | func TestFragmentationMiddleArgNearFragmentBoundary(t *testing.T) {
function TestFragmentationMiddleArgOnExactFragmentBoundary (line 108) | func TestFragmentationMiddleArgOnExactFragmentBoundary(t *testing.T) {
function TestFragmentationLastArgOnNearFragmentBoundary (line 124) | func TestFragmentationLastArgOnNearFragmentBoundary(t *testing.T) {
function TestFragmentationLastArgOnExactFragmentBoundary (line 135) | func TestFragmentationLastArgOnExactFragmentBoundary(t *testing.T) {
function TestFragmentationWriterErrors (line 146) | func TestFragmentationWriterErrors(t *testing.T) {
function TestFragmentationReaderErrors (line 174) | func TestFragmentationReaderErrors(t *testing.T) {
function TestFragmentationChecksumTypeErrors (line 253) | func TestFragmentationChecksumTypeErrors(t *testing.T) {
function TestFragmentationChecksumMismatch (line 280) | func TestFragmentationChecksumMismatch(t *testing.T) {
function runFragmentationErrorTest (line 307) | func runFragmentationErrorTest(f func(w *fragmentingWriter, r *fragmenti...
function runFragmentationTest (line 314) | func runFragmentationTest(t *testing.T, args []string, expectedFragments...
type fragmentChannel (line 374) | type fragmentChannel
method newFragment (line 376) | func (ch fragmentChannel) newFragment(initial bool, checksum Checksum)...
method flushFragment (line 387) | func (ch fragmentChannel) flushFragment(fragment *writableFragment) er...
method recvNextFragment (line 394) | func (ch fragmentChannel) recvNextFragment(initial bool) (*readableFra...
method doneReading (line 405) | func (ch fragmentChannel) doneReading(unexpected error) {}
method doneSending (line 406) | func (ch fragmentChannel) doneSending() {}
function buffers (line 408) | func buffers(elements ...[][]byte) [][]byte {
FILE: fragmenting_reader.go
type readableFragment (line 42) | type readableFragment struct
method done (line 51) | func (f *readableFragment) done() {
type fragmentReceiver (line 59) | type fragmentReceiver interface
type fragmentingReadState (line 69) | type fragmentingReadState
method isReadingArgument (line 79) | func (s fragmentingReadState) isReadingArgument() bool {
constant fragmentingReadStart (line 72) | fragmentingReadStart fragmentingReadState = iota
constant fragmentingReadInArgument (line 73) | fragmentingReadInArgument
constant fragmentingReadInLastArgument (line 74) | fragmentingReadInLastArgument
constant fragmentingReadWaitingForArgument (line 75) | fragmentingReadWaitingForArgument
constant fragmentingReadComplete (line 76) | fragmentingReadComplete
type fragmentingReader (line 83) | type fragmentingReader struct
method ArgReader (line 105) | func (r *fragmentingReader) ArgReader(last bool) (ArgReader, error) {
method BeginArgument (line 112) | func (r *fragmentingReader) BeginArgument(last bool) error {
method Read (line 142) | func (r *fragmentingReader) Read(b []byte) (int, error) {
method Close (line 187) | func (r *fragmentingReader) Close() error {
method recvAndParseNextFragment (line 256) | func (r *fragmentingReader) recvAndParseNextFragment(initial bool) err...
method doneReading (line 311) | func (r *fragmentingReader) doneReading(err error) {
function newFragmentingReader (line 95) | func newFragmentingReader(logger Logger, receiver fragmentReceiver) *fra...
FILE: fragmenting_writer.go
constant chunkHeaderSize (line 37) | chunkHeaderSize = 2
constant hasMoreFragmentsFlag (line 38) | hasMoreFragmentsFlag = 0x01
type writableFragment (line 44) | type writableFragment struct
method finish (line 53) | func (f *writableFragment) finish(hasMoreFragments bool) {
type writableChunk (line 67) | type writableChunk struct
method writeAsFits (line 85) | func (c *writableChunk) writeAsFits(b []byte) int {
method finish (line 99) | func (c *writableChunk) finish() {
function newWritableChunk (line 75) | func newWritableChunk(checksum Checksum, contents *typed.WriteBuffer) *w...
type fragmentSender (line 104) | type fragmentSender interface
type fragmentingWriterState (line 115) | type fragmentingWriterState
method isWritingArgument (line 125) | func (s fragmentingWriterState) isWritingArgument() bool {
constant fragmentingWriteStart (line 118) | fragmentingWriteStart fragmentingWriterState = iota
constant fragmentingWriteInArgument (line 119) | fragmentingWriteInArgument
constant fragmentingWriteInLastArgument (line 120) | fragmentingWriteInLastArgument
constant fragmentingWriteWaitingForArgument (line 121) | fragmentingWriteWaitingForArgument
constant fragmentingWriteComplete (line 122) | fragmentingWriteComplete
type fragmentingWriter (line 133) | type fragmentingWriter struct
method ArgWriter (line 155) | func (w *fragmentingWriter) ArgWriter(last bool) (ArgWriter, error) {
method BeginArgument (line 164) | func (w *fragmentingWriter) BeginArgument(last bool) error {
method Write (line 203) | func (w *fragmentingWriter) Write(b []byte) (int, error) {
method Flush (line 233) | func (w *fragmentingWriter) Flush() error {
method Close (line 249) | func (w *fragmentingWriter) Close() error {
function newFragmentingWriter (line 144) | func newFragmentingWriter(logger Logger, sender fragmentSender, checksum...
FILE: frame.go
constant MaxFrameSize (line 34) | MaxFrameSize = math.MaxUint16
constant FrameHeaderSize (line 37) | FrameHeaderSize = 16
constant MaxFramePayloadSize (line 40) | MaxFramePayloadSize = MaxFrameSize - FrameHeaderSize
type FrameHeader (line 44) | type FrameHeader struct
method SetPayloadSize (line 62) | func (fh *FrameHeader) SetPayloadSize(size uint16) {
method PayloadSize (line 67) | func (fh FrameHeader) PayloadSize() uint16 {
method FrameSize (line 72) | func (fh FrameHeader) FrameSize() uint16 {
method MessageType (line 77) | func (fh FrameHeader) MessageType() byte {
method String (line 81) | func (fh FrameHeader) String() string { return fmt.Sprintf("%v[%d]", f...
method MarshalJSON (line 84) | func (fh FrameHeader) MarshalJSON() ([]byte, error) {
method read (line 93) | func (fh *FrameHeader) read(r *typed.ReadBuffer) error {
method write (line 102) | func (fh *FrameHeader) write(w *typed.WriteBuffer) error {
type Frame (line 112) | type Frame struct
method ReadBody (line 135) | func (f *Frame) ReadBody(header []byte, r io.Reader) error {
method ReadIn (line 160) | func (f *Frame) ReadIn(r io.Reader) error {
method WriteOut (line 170) | func (f *Frame) WriteOut(w io.Writer) error {
method SizedPayload (line 187) | func (f *Frame) SizedPayload() []byte {
method messageType (line 192) | func (f *Frame) messageType() messageType {
method write (line 196) | func (f *Frame) write(msg message) error {
method read (line 210) | func (f *Frame) read(msg message) error {
function NewFrame (line 124) | func NewFrame(payloadCapacity int) *Frame {
FILE: frame_pool.go
type FramePool (line 26) | type FramePool interface
type disabledFramePool (line 40) | type disabledFramePool struct
method Get (line 42) | func (p disabledFramePool) Get() *Frame { return NewFrame(MaxFram...
method Release (line 43) | func (p disabledFramePool) Release(f *Frame) {}
type syncFramePool (line 45) | type syncFramePool struct
method Get (line 56) | func (p syncFramePool) Get() *Frame {
method Release (line 60) | func (p syncFramePool) Release(f *Frame) {
function NewSyncFramePool (line 50) | func NewSyncFramePool() FramePool {
type channelFramePool (line 64) | type channelFramePool
method Get (line 71) | func (c channelFramePool) Get() *Frame {
method Release (line 80) | func (c channelFramePool) Release(f *Frame) {
function NewChannelFramePool (line 67) | func NewChannelFramePool(capacity int) FramePool {
FILE: frame_pool_b_test.go
function benchmarkUsing (line 33) | func benchmarkUsing(b *testing.B, pool FramePool) {
function BenchmarkFramePoolDisabled (line 69) | func BenchmarkFramePoolDisabled(b *testing.B) {
function BenchmarkFramePoolSync (line 73) | func BenchmarkFramePoolSync(b *testing.B) {
function BenchmarkFramePoolChannel1000 (line 77) | func BenchmarkFramePoolChannel1000(b *testing.B) {
function BenchmarkFramePoolChannel10000 (line 81) | func BenchmarkFramePoolChannel10000(b *testing.B) {
FILE: frame_pool_test.go
type swapper (line 45) | type swapper struct
method OnError (line 49) | func (s *swapper) OnError(ctx context.Context, err error) {
method Handle (line 53) | func (*swapper) Handle(ctx context.Context, args *raw.Args) (*raw.Res,...
function doPingAndCall (line 60) | func doPingAndCall(t testing.TB, clientCh *Channel, hostPort string) {
function doErrorCall (line 84) | func doErrorCall(t testing.TB, clientCh *Channel, hostPort string) {
function TestFramesReleased (line 93) | func TestFramesReleased(t *testing.T) {
type dirtyFramePool (line 138) | type dirtyFramePool struct
method Get (line 140) | func (p dirtyFramePool) Get() *Frame {
method Release (line 147) | func (p dirtyFramePool) Release(f *Frame) {}
function TestDirtyFrameRequests (line 149) | func TestDirtyFrameRequests(t *testing.T) {
FILE: frame_test.go
function fakeHeader (line 40) | func fakeHeader(t messageType) FrameHeader {
function TestFrameHeaderJSON (line 48) | func TestFrameHeaderJSON(t *testing.T) {
function TestFraming (line 60) | func TestFraming(t *testing.T) {
function TestPartialRead (line 78) | func TestPartialRead(t *testing.T) {
function TestFrameReadShortFrame (line 102) | func TestFrameReadShortFrame(t *testing.T) {
function TestEmptyPayload (line 120) | func TestEmptyPayload(t *testing.T) {
function TestReservedBytes (line 136) | func TestReservedBytes(t *testing.T) {
function TestMessageType (line 160) | func TestMessageType(t *testing.T) {
function TestFrameReadIn (line 167) | func TestFrameReadIn(t *testing.T) {
function frameReadIn (line 274) | func frameReadIn(bs []byte) (decoded bool) {
function TestQuickFrameReadIn (line 287) | func TestQuickFrameReadIn(t *testing.T) {
FILE: frame_utils_test.go
type protectMemAllocs (line 31) | type protectMemAllocs struct
type ProtectMemFramePool (line 36) | type ProtectMemFramePool struct
method Get (line 49) | func (p *ProtectMemFramePool) Get() *Frame {
method Release (line 68) | func (p *ProtectMemFramePool) Release(f *Frame) {
function NewProtectMemFramePool (line 44) | func NewProtectMemFramePool() FramePool {
FILE: handlers.go
type Handler (line 33) | type Handler interface
type registrar (line 39) | type registrar interface
type HandlerFunc (line 46) | type HandlerFunc
method Handle (line 49) | func (f HandlerFunc) Handle(ctx context.Context, call *InboundCall) { ...
type ErrorHandlerFunc (line 55) | type ErrorHandlerFunc
method Handle (line 58) | func (f ErrorHandlerFunc) Handle(ctx context.Context, call *InboundCal...
method getLogFields (line 67) | func (f ErrorHandlerFunc) getLogFields() LogFields {
type handlerMap (line 79) | type handlerMap struct
method Register (line 86) | func (hmap *handlerMap) Register(h Handler, method string) {
method find (line 99) | func (hmap *handlerMap) find(method []byte) Handler {
method Handle (line 107) | func (hmap *handlerMap) Handle(ctx context.Context, call *InboundCall) {
type channelHandler (line 128) | type channelHandler struct
method Handle (line 130) | func (c channelHandler) Handle(ctx context.Context, call *InboundCall) {
method Register (line 135) | func (c channelHandler) Register(h Handler, methodName string) {
type userHandlerWithSkip (line 143) | type userHandlerWithSkip struct
method Handle (line 149) | func (u userHandlerWithSkip) Handle(ctx context.Context, call *Inbound...
method Register (line 157) | func (u userHandlerWithSkip) Register(h Handler, methodName string) {
FILE: handlers_test.go
type dummyHandler (line 30) | type dummyHandler struct
method Handle (line 32) | func (dummyHandler) Handle(ctx context.Context, call *InboundCall) {}
function TestHandlers (line 34) | func TestHandlers(t *testing.T) {
FILE: handlers_with_skip_test.go
function procedure (line 37) | func procedure(svc, method string) string {
function TestUserHandlerWithSkip (line 41) | func TestUserHandlerWithSkip(t *testing.T) {
function TestUserHandlerWithSkipInvalidInput (line 81) | func TestUserHandlerWithSkipInvalidInput(t *testing.T) {
type recordHandler (line 90) | type recordHandler struct
method Handle (line 92) | func (r *recordHandler) Handle(ctx context.Context, call *InboundCall) {
FILE: health.go
constant _defaultHealthCheckTimeout (line 31) | _defaultHealthCheckTimeout = time.Second
constant _defaultHealthCheckFailuresToClose (line 32) | _defaultHealthCheckFailuresToClose = 5
constant _healthHistorySize (line 34) | _healthHistorySize = 256
type HealthCheckOptions (line 41) | type HealthCheckOptions struct
method enabled (line 95) | func (hco HealthCheckOptions) enabled() bool {
method withDefaults (line 99) | func (hco HealthCheckOptions) withDefaults() HealthCheckOptions {
type healthHistory (line 56) | type healthHistory struct
method add (line 71) | func (hh *healthHistory) add(b bool) {
method asBools (line 80) | func (hh *healthHistory) asBools() []bool {
function newHealthHistory (line 65) | func newHealthHistory() *healthHistory {
method healthCheck (line 111) | func (c *Connection) healthCheck(connID uint32) {
method stopHealthCheck (line 163) | func (c *Connection) stopHealthCheck() {
FILE: health_ext_test.go
function TestHealthCheckStopBeforeStart (line 36) | func TestHealthCheckStopBeforeStart(t *testing.T) {
function TestHealthCheckStopNoError (line 71) | func TestHealthCheckStopNoError(t *testing.T) {
function TestHealthCheckIntegration (line 113) | func TestHealthCheckIntegration(t *testing.T) {
function waitForNHealthChecks (line 209) | func waitForNHealthChecks(t testing.TB, conn *Connection, n int) {
function introspectConn (line 215) | func introspectConn(c *Connection) ConnectionRuntimeState {
FILE: health_test.go
function TestHealthCheckEnabled (line 31) | func TestHealthCheckEnabled(t *testing.T) {
function TestHealthCheckOptionsDefaults (line 39) | func TestHealthCheckOptionsDefaults(t *testing.T) {
function TestHealthHistory (line 68) | func TestHealthHistory(t *testing.T) {
FILE: http/buf.go
function writeHeaders (line 29) | func writeHeaders(wb *typed.WriteBuffer, form http.Header) {
function readHeaders (line 42) | func readHeaders(rb *typed.ReadBuffer, form http.Header) {
function readVarintString (line 51) | func readVarintString(rb *typed.ReadBuffer) string {
function writeVarintString (line 56) | func writeVarintString(wb *typed.WriteBuffer, s string) {
FILE: http/buf_test.go
function TestHeaders (line 32) | func TestHeaders(t *testing.T) {
function TestVarintString (line 53) | func TestVarintString(t *testing.T) {
FILE: http/http_test.go
function dumpHandler (line 43) | func dumpHandler(w http.ResponseWriter, r *http.Request) {
function setupHTTP (line 70) | func setupHTTP(t *testing.T, serveMux *http.ServeMux) (string, func()) {
function setupTChan (line 79) | func setupTChan(t *testing.T, mux *http.ServeMux) (string, func()) {
function setupProxy (line 96) | func setupProxy(t *testing.T, tchanAddr string) (string, func()) {
function setupServer (line 132) | func setupServer(t *testing.T) (string, string, func()) {
function makeHTTPCall (line 146) | func makeHTTPCall(t *testing.T, req *http.Request) *http.Response {
function makeTChanCall (line 152) | func makeTChanCall(t *testing.T, tchanAddr string, req *http.Request) *h...
function compareResponseBasic (line 167) | func compareResponseBasic(t *testing.T, testName string, resp1, resp2 *h...
function compareResponses (line 178) | func compareResponses(t *testing.T, testName string, resp1, resp2 *http....
type requestTest (line 186) | type requestTest struct
function getRequestTests (line 191) | func getRequestTests(t *testing.T) []requestTest {
function TestDirectRequests (line 223) | func TestDirectRequests(t *testing.T) {
function TestProxyRequests (line 235) | func TestProxyRequests(t *testing.T) {
FILE: http/request.go
function WriteRequest (line 32) | func WriteRequest(call tchannel.ArgWritable, req *http.Request) error {
function ReadRequest (line 64) | func ReadRequest(call tchannel.ArgReadable) (*http.Request, error) {
FILE: http/response.go
function ReadResponse (line 33) | func ReadResponse(call tchannel.ArgReadable) (*http.Response, error) {
type tchanResponseWriter (line 65) | type tchanResponseWriter struct
method Header (line 81) | func (w *tchanResponseWriter) Header() http.Header {
method WriteHeader (line 85) | func (w *tchanResponseWriter) WriteHeader(statusCode int) {
method writeHeaders (line 90) | func (w *tchanResponseWriter) writeHeaders() {
method Write (line 112) | func (w *tchanResponseWriter) Write(bs []byte) (int, error) {
method finish (line 127) | func (w *tchanResponseWriter) finish() error {
function newTChanResponseWriter (line 73) | func newTChanResponseWriter(response tchannel.ArgWritable) *tchanRespons...
function ResponseWriter (line 136) | func ResponseWriter(response tchannel.ArgWritable) (http.ResponseWriter,...
FILE: hyperbahn/advertise.go
constant maxAdvertiseFailures (line 34) | maxAdvertiseFailures = 5
constant advertiseInterval (line 36) | advertiseInterval = 50 * time.Second
constant advertiseFuzzInterval (line 38) | advertiseFuzzInterval = 20 * time.Second
constant advertiseRetryInterval (line 41) | advertiseRetryInterval = 1 * time.Second
type ErrAdvertiseFailed (line 45) | type ErrAdvertiseFailed struct
method Error (line 52) | func (e ErrAdvertiseFailed) Error() string {
function fuzzInterval (line 58) | func fuzzInterval(interval time.Duration) time.Duration {
method fuzzedAdvertiseInterval (line 63) | func (c *Client) fuzzedAdvertiseInterval() time.Duration {
method logFailedRegistrationRetry (line 69) | func (c *Client) logFailedRegistrationRetry(errLogger tchannel.Logger, c...
method advertiseLoop (line 79) | func (c *Client) advertiseLoop() {
method initialAdvertise (line 116) | func (c *Client) initialAdvertise() error {
method sleep (line 134) | func (c *Client) sleep(d time.Duration) {
FILE: hyperbahn/advertise_test.go
function TestInitialAdvertiseFailedRetryBackoff (line 38) | func TestInitialAdvertiseFailedRetryBackoff(t *testing.T) {
function TestInitialAdvertiseFailedRetryTimeout (line 67) | func TestInitialAdvertiseFailedRetryTimeout(t *testing.T) {
function TestNotListeningChannel (line 95) | func TestNotListeningChannel(t *testing.T) {
type retryTest (line 111) | type retryTest struct
method On (line 128) | func (r *retryTest) On(event Event) {
method OnError (line 131) | func (r *retryTest) OnError(err error) {
method adHandler (line 135) | func (r *retryTest) adHandler(ctx json.Context, req *AdRequest) (*AdRe...
method setup (line 144) | func (r *retryTest) setup() {
method setAdvertiseSuccess (line 150) | func (r *retryTest) setAdvertiseSuccess() {
method setAdvertiseFailure (line 154) | func (r *retryTest) setAdvertiseFailure() {
function runRetryTest (line 158) | func runRetryTest(t *testing.T, f func(r *retryTest)) {
function TestAdvertiseSuccess (line 187) | func TestAdvertiseSuccess(t *testing.T) {
function TestMutlipleAdvertise (line 215) | func TestMutlipleAdvertise(t *testing.T) {
function TestRetryTemporaryFailure (line 251) | func TestRetryTemporaryFailure(t *testing.T) {
function TestRetryFailure (line 288) | func TestRetryFailure(t *testing.T) {
function checkAdvertiseInterval (line 343) | func checkAdvertiseInterval(t *testing.T, sleptFor time.Duration) {
function checkRetryInterval (line 350) | func checkRetryInterval(t *testing.T, sleptFor time.Duration, retryNum i...
function configFor (line 356) | func configFor(node string) Configuration {
function stubbedSleep (line 362) | func stubbedSleep() *ClientOptions {
function withSetup (line 368) | func withSetup(t *testing.T, f func(ch *tchannel.Channel, hostPort strin...
FILE: hyperbahn/call.go
type service (line 32) | type service struct
type AdRequest (line 38) | type AdRequest struct
type AdResponse (line 43) | type AdResponse struct
method createRequest (line 47) | func (c *Client) createRequest() *AdRequest {
method sendAdvertise (line 60) | func (c *Client) sendAdvertise() error {
FILE: hyperbahn/client.go
type Client (line 37) | type Client struct
method getServiceNames (line 170) | func (c *Client) getServiceNames(otherServices []tchannel.Registrar) {
method Advertise (line 182) | func (c *Client) Advertise(otherServices ...tchannel.Registrar) error {
method IsClosed (line 195) | func (c *Client) IsClosed() bool {
method Close (line 205) | func (c *Client) Close() {
type FailStrategy (line 49) | type FailStrategy
method UnmarshalText (line 65) | func (f *FailStrategy) UnmarshalText(text []byte) error {
constant FailStrategyFatal (line 54) | FailStrategyFatal FailStrategy = iota
constant FailStrategyIgnore (line 57) | FailStrategyIgnore
constant hyperbahnServiceName (line 60) | hyperbahnServiceName = "hyperbahn"
type ClientOptions (line 78) | type ClientOptions struct
function NewClient (line 94) | func NewClient(ch *tchannel.Channel, config Configuration, opts *ClientO...
function parseConfig (line 136) | func parseConfig(config *Configuration) error {
function addPeer (line 165) | func addPeer(ch *tchannel.Channel, hostPort string) {
FILE: hyperbahn/client_test.go
function getPeers (line 37) | func getPeers(ch *tchannel.Channel) []string {
function TestParseConfiguration (line 46) | func TestParseConfiguration(t *testing.T) {
function TestUnmarshalFailStrategyFormats (line 126) | func TestUnmarshalFailStrategyFormats(t *testing.T) {
function TestUnmarshalText (line 159) | func TestUnmarshalText(t *testing.T) {
FILE: hyperbahn/configuration.go
type Configuration (line 24) | type Configuration struct
FILE: hyperbahn/discover.go
method Discover (line 32) | func (c *Client) Discover(serviceName string) ([]string, error) {
FILE: hyperbahn/discover_test.go
function withSetup (line 35) | func withSetup(t *testing.T, f func(mh *mockhyperbahn.Mock, client *Clie...
function TestDiscoverSuccess (line 48) | func TestDiscoverSuccess(t *testing.T) {
function TestDiscoverFails (line 65) | func TestDiscoverFails(t *testing.T) {
FILE: hyperbahn/event_string.go
constant _Event_name (line 7) | _Event_name = "UnknownEventRegistrationAttemptRegisteredRegistrationRefr...
method String (line 11) | func (i Event) String() string {
FILE: hyperbahn/events.go
type Event (line 24) | type Event
constant UnknownEvent (line 28) | UnknownEvent Event = iota
constant SendAdvertise (line 30) | SendAdvertise
constant Advertised (line 32) | Advertised
constant Readvertised (line 34) | Readvertised
type Handler (line 40) | type Handler interface
type nullHandler (line 48) | type nullHandler struct
method On (line 50) | func (nullHandler) On(event Event) {}
method OnError (line 51) | func (nullHandler) OnError(err error) {}
FILE: hyperbahn/gen-go/hyperbahn/constants.go
function init (line 17) | func init() {
FILE: hyperbahn/gen-go/hyperbahn/hyperbahn.go
type Hyperbahn (line 17) | type Hyperbahn interface
type HyperbahnClient (line 23) | type HyperbahnClient struct
method Discover (line 51) | func (p *HyperbahnClient) Discover(query *DiscoveryQuery) (r *Discover...
method sendDiscover (line 58) | func (p *HyperbahnClient) sendDiscover(query *DiscoveryQuery) (err err...
method recvDiscover (line 80) | func (p *HyperbahnClient) recvDiscover() (value *DiscoveryResult_, err...
function NewHyperbahnClientFactory (line 31) | func NewHyperbahnClientFactory(t thrift.TTransport, f thrift.TProtocolFa...
function NewHyperbahnClientProtocol (line 40) | func NewHyperbahnClientProtocol(t thrift.TTransport, iprot thrift.TProto...
type HyperbahnProcessor (line 133) | type HyperbahnProcessor struct
method AddToProcessorMap (line 138) | func (p *HyperbahnProcessor) AddToProcessorMap(key string, processor t...
method GetProcessorFunction (line 142) | func (p *HyperbahnProcessor) GetProcessorFunction(key string) (process...
method ProcessorMap (line 147) | func (p *HyperbahnProcessor) ProcessorMap() map[string]thrift.TProcess...
method Process (line 158) | func (p *HyperbahnProcessor) Process(iprot, oprot thrift.TProtocol) (s...
function NewHyperbahnProcessor (line 151) | func NewHyperbahnProcessor(handler Hyperbahn) *HyperbahnProcessor {
type hyperbahnProcessorDiscover (line 177) | type hyperbahnProcessorDiscover struct
method Process (line 181) | func (p *hyperbahnProcessorDiscover) Process(seqId int32, iprot, oprot...
type HyperbahnDiscoverArgs (line 236) | type HyperbahnDiscoverArgs struct
method GetQuery (line 246) | func (p *HyperbahnDiscoverArgs) GetQuery() *DiscoveryQuery {
method IsSetQuery (line 252) | func (p *HyperbahnDiscoverArgs) IsSetQuery() bool {
method Read (line 256) | func (p *HyperbahnDiscoverArgs) Read(iprot thrift.TProtocol) error {
method ReadField1 (line 295) | func (p *HyperbahnDiscoverArgs) ReadField1(iprot thrift.TProtocol) err...
method Write (line 303) | func (p *HyperbahnDiscoverArgs) Write(oprot thrift.TProtocol) error {
method writeField1 (line 319) | func (p *HyperbahnDiscoverArgs) writeField1(oprot thrift.TProtocol) (e...
method String (line 332) | func (p *HyperbahnDiscoverArgs) String() string {
function NewHyperbahnDiscoverArgs (line 240) | func NewHyperbahnDiscoverArgs() *HyperbahnDiscoverArgs {
type HyperbahnDiscoverResult (line 343) | type HyperbahnDiscoverResult struct
method GetSuccess (line 355) | func (p *HyperbahnDiscoverResult) GetSuccess() *DiscoveryResult_ {
method GetNoPeersAvailable (line 364) | func (p *HyperbahnDiscoverResult) GetNoPeersAvailable() *NoPeersAvaila...
method GetInvalidServiceName (line 373) | func (p *HyperbahnDiscoverResult) GetInvalidServiceName() *InvalidServ...
method IsSetSuccess (line 379) | func (p *HyperbahnDiscoverResult) IsSetSuccess() bool {
method IsSetNoPeersAvailable (line 383) | func (p *HyperbahnDiscoverResult) IsSetNoPeersAvailable() bool {
method IsSetInvalidServiceName (line 387) | func (p *HyperbahnDiscoverResult) IsSetInvalidServiceName() bool {
method Read (line 391) | func (p *HyperbahnDiscoverResult) Read(iprot thrift.TProtocol) error {
method ReadField0 (line 432) | func (p *HyperbahnDiscoverResult) ReadField0(iprot thrift.TProtocol) e...
method ReadField1 (line 440) | func (p *HyperbahnDiscoverResult) ReadField1(iprot thrift.TProtocol) e...
method ReadField2 (line 448) | func (p *HyperbahnDiscoverResult) ReadField2(iprot thrift.TProtocol) e...
method Write (line 456) | func (p *HyperbahnDiscoverResult) Write(oprot thrift.TProtocol) error {
method writeField0 (line 478) | func (p *HyperbahnDiscoverResult) writeField0(oprot thrift.TProtocol) ...
method writeField1 (line 493) | func (p *HyperbahnDiscoverResult) writeField1(oprot thrift.TProtocol) ...
method writeField2 (line 508) | func (p *HyperbahnDiscoverResult) writeField2(oprot thrift.TProtocol) ...
method String (line 523) | func (p *HyperbahnDiscoverResult) String() string {
function NewHyperbahnDiscoverResult (line 349) | func NewHyperbahnDiscoverResult() *HyperbahnDiscoverResult {
FILE: hyperbahn/gen-go/hyperbahn/tchan-hyperbahn.go
type TChanHyperbahn (line 16) | type TChanHyperbahn interface
type tchanHyperbahnClient (line 22) | type tchanHyperbahnClient struct
method Discover (line 39) | func (c *tchanHyperbahnClient) Discover(ctx thrift.Context, query *Dis...
function NewTChanHyperbahnInheritedClient (line 27) | func NewTChanHyperbahnInheritedClient(thriftService string, client thrif...
function NewTChanHyperbahnClient (line 35) | func NewTChanHyperbahnClient(client thrift.TChanClient) TChanHyperbahn {
type tchanHyperbahnServer (line 59) | type tchanHyperbahnServer struct
method Service (line 71) | func (s *tchanHyperbahnServer) Service() string {
method Methods (line 75) | func (s *tchanHyperbahnServer) Methods() []string {
method Handle (line 81) | func (s *tchanHyperbahnServer) Handle(ctx thrift.Context, methodName s...
method handleDiscover (line 91) | func (s *tchanHyperbahnServer) handleDiscover(ctx thrift.Context, prot...
function NewTChanHyperbahnServer (line 65) | func NewTChanHyperbahnServer(handler TChanHyperbahn) thrift.TChanServer {
FILE: hyperbahn/gen-go/hyperbahn/ttypes.go
type NoPeersAvailable (line 22) | type NoPeersAvailable struct
method GetMessage (line 31) | func (p *NoPeersAvailable) GetMessage() string {
method GetServiceName (line 35) | func (p *NoPeersAvailable) GetServiceName() string {
method Read (line 38) | func (p *NoPeersAvailable) Read(iprot thrift.TProtocol) error {
method ReadField1 (line 86) | func (p *NoPeersAvailable) ReadField1(iprot thrift.TProtocol) error {
method ReadField2 (line 95) | func (p *NoPeersAvailable) ReadField2(iprot thrift.TProtocol) error {
method Write (line 104) | func (p *NoPeersAvailable) Write(oprot thrift.TProtocol) error {
method writeField1 (line 123) | func (p *NoPeersAvailable) writeField1(oprot thrift.TProtocol) (err er...
method writeField2 (line 136) | func (p *NoPeersAvailable) writeField2(oprot thrift.TProtocol) (err er...
method String (line 149) | func (p *NoPeersAvailable) String() string {
method Error (line 156) | func (p *NoPeersAvailable) Error() string {
function NewNoPeersAvailable (line 27) | func NewNoPeersAvailable() *NoPeersAvailable {
type InvalidServiceName (line 163) | type InvalidServiceName struct
method GetMessage (line 172) | func (p *InvalidServiceName) GetMessage() string {
method GetServiceName (line 176) | func (p *InvalidServiceName) GetServiceName() string {
method Read (line 179) | func (p *InvalidServiceName) Read(iprot thrift.TProtocol) error {
method ReadField1 (line 227) | func (p *InvalidServiceName) ReadField1(iprot thrift.TProtocol) error {
method ReadField2 (line 236) | func (p *InvalidServiceName) ReadField2(iprot thrift.TProtocol) error {
method Write (line 245) | func (p *InvalidServiceName) Write(oprot thrift.TProtocol) error {
method writeField1 (line 264) | func (p *InvalidServiceName) writeField1(oprot thrift.TProtocol) (err ...
method writeField2 (line 277) | func (p *InvalidServiceName) writeField2(oprot thrift.TProtocol) (err ...
method String (line 290) | func (p *InvalidServiceName) String() string {
method Error (line 297) | func (p *InvalidServiceName) Error() string {
function NewInvalidServiceName (line 168) | func NewInvalidServiceName() *InvalidServiceName {
type DiscoveryQuery (line 303) | type DiscoveryQuery struct
method GetServiceName (line 311) | func (p *DiscoveryQuery) GetServiceName() string {
method Read (line 314) | func (p *DiscoveryQuery) Read(iprot thrift.TProtocol) error {
method ReadField1 (line 353) | func (p *DiscoveryQuery) ReadField1(iprot thrift.TProtocol) error {
method Write (line 362) | func (p *DiscoveryQuery) Write(oprot thrift.TProtocol) error {
method writeField1 (line 378) | func (p *DiscoveryQuery) writeField1(oprot thrift.TProtocol) (err erro...
method String (line 391) | func (p *DiscoveryQuery) String() string {
function NewDiscoveryQuery (line 307) | func NewDiscoveryQuery() *DiscoveryQuery {
type IpAddress (line 400) | type IpAddress struct
method GetIpv4 (line 410) | func (p *IpAddress) GetIpv4() int32 {
method CountSetFieldsIpAddress (line 416) | func (p *IpAddress) CountSetFieldsIpAddress() int {
method IsSetIpv4 (line 425) | func (p *IpAddress) IsSetIpv4() bool {
method Read (line 429) | func (p *IpAddress) Read(iprot thrift.TProtocol) error {
method ReadField1 (line 462) | func (p *IpAddress) ReadField1(iprot thrift.TProtocol) error {
method Write (line 471) | func (p *IpAddress) Write(oprot thrift.TProtocol) error {
method writeField1 (line 490) | func (p *IpAddress) writeField1(oprot thrift.TProtocol) (err error) {
method String (line 505) | func (p *IpAddress) String() string {
function NewIpAddress (line 404) | func NewIpAddress() *IpAddress {
type ServicePeer (line 515) | type ServicePeer struct
method GetIP (line 526) | func (p *ServicePeer) GetIP() *IpAddress {
method GetPort (line 533) | func (p *ServicePeer) GetPort() int32 {
method IsSetIP (line 536) | func (p *ServicePeer) IsSetIP() bool {
method Read (line 540) | func (p *ServicePeer) Read(iprot thrift.TProtocol) error {
method ReadField1 (line 588) | func (p *ServicePeer) ReadField1(iprot thrift.TProtocol) error {
method ReadField2 (line 596) | func (p *ServicePeer) ReadField2(iprot thrift.TProtocol) error {
method Write (line 605) | func (p *ServicePeer) Write(oprot thrift.TProtocol) error {
method writeField1 (line 624) | func (p *ServicePeer) writeField1(oprot thrift.TProtocol) (err error) {
method writeField2 (line 637) | func (p *ServicePeer) writeField2(oprot thrift.TProtocol) (err error) {
method String (line 650) | func (p *ServicePeer) String() string {
function NewServicePeer (line 520) | func NewServicePeer() *ServicePeer {
type DiscoveryResult_ (line 659) | type DiscoveryResult_ struct
method GetPeers (line 667) | func (p *DiscoveryResult_) GetPeers() []*ServicePeer {
method Read (line 670) | func (p *DiscoveryResult_) Read(iprot thrift.TProtocol) error {
method ReadField1 (line 709) | func (p *DiscoveryResult_) ReadField1(iprot thrift.TProtocol) error {
method Write (line 729) | func (p *DiscoveryResult_) Write(oprot thrift.TProtocol) error {
method writeField1 (line 745) | func (p *DiscoveryResult_) writeField1(oprot thrift.TProtocol) (err er...
method String (line 766) | func (p *DiscoveryResult_) String() string {
function NewDiscoveryResult_ (line 663) | func NewDiscoveryResult_() *DiscoveryResult_ {
FILE: hyperbahn/utils.go
function intToIP4 (line 31) | func intToIP4(ip uint32) net.IP {
function servicePeerToHostPort (line 41) | func servicePeerToHostPort(peer *hyperbahn.ServicePeer) string {
FILE: hyperbahn/utils_test.go
function TestIntToIP4 (line 29) | func TestIntToIP4(t *testing.T) {
FILE: idle_sweep.go
type idleSweep (line 29) | type idleSweep struct
method start (line 51) | func (is *idleSweep) start() {
method Stop (line 67) | func (is *idleSweep) Stop() {
method pollerLoop (line 77) | func (is *idleSweep) pollerLoop() {
method checkIdleConnections (line 91) | func (is *idleSweep) checkIdleConnections() {
function startIdleSweep (line 39) | func startIdleSweep(ch *Channel, opts *ChannelOptions) *idleSweep {
FILE: idle_sweep_test.go
type peerStatusListener (line 40) | type peerStatusListener struct
method onStatusChange (line 50) | func (pl *peerStatusListener) onStatusChange(p *Peer) {
method waitForZeroConnections (line 54) | func (pl *peerStatusListener) waitForZeroConnections(t testing.TB, cha...
method waitForZeroExchanges (line 69) | func (pl *peerStatusListener) waitForZeroExchanges(t testing.TB, chann...
function newPeerStatusListener (line 44) | func newPeerStatusListener() *peerStatusListener {
function allConnectionsClosed (line 82) | func allConnectionsClosed(channels []*Channel) bool {
function allExchangesEmpty (line 92) | func allExchangesEmpty(channels []*Channel) (isEmpty bool, status []stri...
function numConnections (line 104) | func numConnections(ch *Channel) int {
function numExchanges (line 116) | func numExchanges(ch *Channel) int {
function connectionStatus (line 131) | func connectionStatus(channels []*Channel) string {
function TestServerBasedSweep (line 141) | func TestServerBasedSweep(t *testing.T) {
function TestClientBasedSweep (line 184) | func TestClientBasedSweep(t *testing.T) {
function TestRelayBasedSweep (line 225) | func TestRelayBasedSweep(t *testing.T) {
function TestIdleSweepWithPings (line 267) | func TestIdleSweepWithPings(t *testing.T) {
function TestIdleSweepMisconfiguration (line 312) | func TestIdleSweepMisconfiguration(t *testing.T) {
function TestIdleSweepIgnoresConnectionsWithCalls (line 321) | func TestIdleSweepIgnoresConnectionsWithCalls(t *testing.T) {
FILE: inbound.go
constant systemErrorType (line 35) | systemErrorType = "system"
constant appErrorType (line 36) | appErrorType = "application"
method handleCallReq (line 44) | func (c *Connection) handleCallReq(frame *Frame) bool {
method handleCallReqContinue (line 138) | func (c *Connection) handleCallReqContinue(frame *Frame) bool {
method handleCancel (line 146) | func (c *Connection) handleCancel(frame *Frame) bool {
method dispatchInbound (line 175) | func (c *Connection) dispatchInbound(_ uint32, _ uint32, call *InboundCa...
type InboundCall (line 231) | type InboundCall struct
method createStatsTags (line 165) | func (call *InboundCall) createStatsTags(connectionTags map[string]str...
method ServiceName (line 245) | func (call *InboundCall) ServiceName() string {
method Method (line 250) | func (call *InboundCall) Method() []byte {
method MethodString (line 255) | func (call *InboundCall) MethodString() string {
method Format (line 260) | func (call *InboundCall) Format() Format {
method CallerName (line 265) | func (call *InboundCall) CallerName() string {
method ShardKey (line 270) | func (call *InboundCall) ShardKey() string {
method RoutingKey (line 275) | func (call *InboundCall) RoutingKey() string {
method RoutingDelegate (line 280) | func (call *InboundCall) RoutingDelegate() string {
method LocalPeer (line 285) | func (call *InboundCall) LocalPeer() LocalPeerInfo {
method RemotePeer (line 290) | func (call *InboundCall) RemotePeer() PeerInfo {
method Connection (line 295) | func (call *InboundCall) Connection() net.Conn {
method CallOptions (line 300) | func (call *InboundCall) CallOptions() *CallOptions {
method readMethod (line 311) | func (call *InboundCall) readMethod() error {
method Arg2Reader (line 324) | func (call *InboundCall) Arg2Reader() (ArgReader, error) {
method Arg3Reader (line 330) | func (call *InboundCall) Arg3Reader() (ArgReader, error) {
method Response (line 336) | func (call *InboundCall) Response() *InboundCallResponse {
method doneReading (line 347) | func (call *InboundCall) doneReading(unexpected error) {}
type InboundCallResponse (line 350) | type InboundCallResponse struct
method SendSystemError (line 368) | func (response *InboundCallResponse) SendSystemError(err error) error {
method SetApplicationError (line 386) | func (response *InboundCallResponse) SetApplicationError() error {
method Blackhole (line 401) | func (response *InboundCallResponse) Blackhole() {
method Arg2Writer (line 407) | func (response *InboundCallResponse) Arg2Writer() (ArgWriter, error) {
method Arg3Writer (line 416) | func (response *InboundCallResponse) Arg3Writer() (ArgWriter, error) {
method setSpanErrorDetails (line 421) | func (response *InboundCallResponse) setSpanErrorDetails(err error) {
method doneSending (line 437) | func (response *InboundCallResponse) doneSending() {
FILE: inbound_internal_test.go
type statsReporter (line 32) | type statsReporter struct
method IncCounter (line 34) | func (w *statsReporter) IncCounter(name string, tags map[string]string...
method UpdateGauge (line 37) | func (w *statsReporter) UpdateGauge(name string, tags map[string]strin...
method RecordTimer (line 40) | func (w *statsReporter) RecordTimer(name string, tags map[string]strin...
type testCase (line 43) | type testCase struct
function TestTracingSpanError (line 53) | func TestTracingSpanError(t *testing.T) {
FILE: inbound_test.go
function TestSpanReportingForErrors (line 39) | func TestSpanReportingForErrors(t *testing.T) {
function TestActiveCallReq (line 145) | func TestActiveCallReq(t *testing.T) {
function TestInboundConnection (line 196) | func TestInboundConnection(t *testing.T) {
function TestInboundConnection_CallOptions (line 217) | func TestInboundConnection_CallOptions(t *testing.T) {
function TestCallOptionsPropogated (line 254) | func TestCallOptionsPropogated(t *testing.T) {
function TestBlackhole (line 288) | func TestBlackhole(t *testing.T) {
FILE: incoming_test.go
function TestPeersIncomingConnection (line 34) | func TestPeersIncomingConnection(t *testing.T) {
FILE: init_test.go
function writeMessage (line 36) | func writeMessage(w io.Writer, msg message) error {
function readFrame (line 44) | func readFrame(r io.Reader) (*Frame, error) {
function TestUnexpectedInitReq (line 49) | func TestUnexpectedInitReq(t *testing.T) {
function TestUnexpectedInitRes (line 128) | func TestUnexpectedInitRes(t *testing.T) {
function TestHandleInitReqNewVersion (line 211) | func TestHandleInitReqNewVersion(t *testing.T) {
function TestHandleInitRes (line 253) | func TestHandleInitRes(t *testing.T) {
function TestInitReqGetsError (line 294) | func TestInitReqGetsError(t *testing.T) {
function newListener (line 339) | func newListener(t *testing.T) net.Listener {
FILE: internal/argreader/empty.go
function EnsureEmpty (line 38) | func EnsureEmpty(r io.Reader, stage string) error {
FILE: internal/argreader/empty_test.go
function TestEnsureEmptySuccess (line 33) | func TestEnsureEmptySuccess(t *testing.T) {
function TestEnsureEmptyHasBytes (line 39) | func TestEnsureEmptyHasBytes(t *testing.T) {
function TestEnsureEmptyError (line 46) | func TestEnsureEmptyError(t *testing.T) {
FILE: introspection.go
type IntrospectionOptions (line 35) | type IntrospectionOptions struct
type RuntimeVersion (line 52) | type RuntimeVersion struct
type RuntimeState (line 58) | type RuntimeState struct
type GoRuntimeStateOptions (line 95) | type GoRuntimeStateOptions struct
type ChannelInfo (line 101) | type ChannelInfo struct
type GoRuntimeState (line 108) | type GoRuntimeState struct
type SubChannelRuntimeState (line 117) | type SubChannelRuntimeState struct
type HandlerRuntimeState (line 126) | type HandlerRuntimeState struct
type handlerType (line 131) | type handlerType
method String (line 133) | func (h handlerType) String() string { return string(h) }
constant methodHandler (line 136) | methodHandler handlerType = "methods"
constant overrideHandler (line 137) | overrideHandler = "overriden"
type SubPeerScore (line 141) | type SubPeerScore struct
type ConnectionRuntimeState (line 147) | type ConnectionRuntimeState struct
type RelayerRuntimeState (line 167) | type RelayerRuntimeState struct
type ExchangeSetRuntimeState (line 176) | type ExchangeSetRuntimeState struct
type RelayItemSetState (line 183) | type RelayItemSetState struct
type ExchangeRuntimeState (line 190) | type ExchangeRuntimeState struct
type RelayItemState (line 196) | type RelayItemState struct
type PeerRuntimeState (line 204) | type PeerRuntimeState struct
method IntrospectState (line 214) | func (ch *Channel) IntrospectState(opts *IntrospectionOptions) *RuntimeS...
method IntrospectOthers (line 251) | func (ch *Channel) IntrospectOthers(opts *IntrospectionOptions) map[stri...
method ReportInfo (line 275) | func (ch *Channel) ReportInfo(opts *IntrospectionOptions) ChannelInfo {
type containsPeerList (line 283) | type containsPeerList interface
function fromPeerList (line 287) | func fromPeerList(peers containsPeerList, opts *IntrospectionOptions) ma...
method IntrospectState (line 299) | func (l *RootPeerList) IntrospectState(opts *IntrospectionOptions) map[s...
method IntrospectState (line 304) | func (subChMap *subChannelMap) IntrospectState(opts *IntrospectionOption...
function getConnectionRuntimeState (line 332) | func getConnectionRuntimeState(conns []*Connection, opts *IntrospectionO...
method IntrospectState (line 343) | func (p *Peer) IntrospectState(opts *IntrospectionOptions) PeerRuntimeSt...
method IntrospectState (line 357) | func (c *Connection) IntrospectState(opts *IntrospectionOptions) Connect...
method IntrospectState (line 389) | func (r *Relayer) IntrospectState(opts *IntrospectionOptions) RelayerRun...
method IntrospectState (line 401) | func (ri *relayItems) IntrospectState(opts *IntrospectionOptions, name s...
method IntrospectState (line 429) | func (mexset *messageExchangeSet) IntrospectState(opts *IntrospectionOpt...
function getStacks (line 451) | func getStacks(all bool) []byte {
method handleIntrospection (line 464) | func (ch *Channel) handleIntrospection(arg3 []byte) interface{} {
method IntrospectList (line 487) | func (l *PeerList) IntrospectList(opts *IntrospectionOptions) []SubPeerS...
method IntrospectNumConnections (line 503) | func (ch *Channel) IntrospectNumConnections() int {
function handleInternalRuntime (line 510) | func handleInternalRuntime(arg3 []byte) interface{} {
function introspectRuntimeVersion (line 527) | func introspectRuntimeVersion() RuntimeVersion {
method createInternalHandlers (line 538) | func (ch *Channel) createInternalHandlers() *handlerMap {
FILE: introspection_test.go
function TestIntrospection (line 40) | func TestIntrospection(t *testing.T) {
function TestIntrospectByID (line 71) | func TestIntrospectByID(t *testing.T) {
function TestIntrospectClosedConn (line 101) | func TestIntrospectClosedConn(t *testing.T) {
function TestIntrospectionNotBlocked (line 150) | func TestIntrospectionNotBlocked(t *testing.T) {
FILE: json/call.go
type ErrApplication (line 32) | type ErrApplication
method Error (line 34) | func (e ErrApplication) Error() string {
type Client (line 39) | type Client struct
method startCall (line 93) | func (c *Client) startCall(ctx context.Context, method string, callOpt...
method Call (line 102) | func (c *Client) Call(ctx Context, method string, arg, resp interface{...
type ClientOptions (line 46) | type ClientOptions struct
function NewClient (line 51) | func NewClient(ch *tchannel.Channel, targetService string, opts *ClientO...
function makeCall (line 62) | func makeCall(call *tchannel.OutboundCall, headers, arg3In, respHeaders,...
function wrapCall (line 139) | func wrapCall(ctx Context, call *tchannel.OutboundCall, method string, a...
function CallPeer (line 155) | func CallPeer(ctx Context, peer *tchannel.Peer, serviceName, method stri...
function CallSC (line 165) | func CallSC(ctx Context, sc *tchannel.SubChannel, method string, arg, re...
FILE: json/context.go
type Context (line 32) | type Context
function NewContext (line 35) | func NewContext(timeout time.Duration) (Context, context.CancelFunc) {
function Wrap (line 41) | func Wrap(ctx context.Context) Context {
function WithHeaders (line 46) | func WithHeaders(ctx context.Context, headers map[string]string) Context {
FILE: json/handler.go
type Handlers (line 39) | type Handlers
function verifyHandler (line 43) | func verifyHandler(t reflect.Type) error {
type handler (line 77) | type handler struct
method Handle (line 127) | func (h *handler) Handle(tctx context.Context, call *tchannel.InboundC...
function toHandler (line 84) | func toHandler(f interface{}) (*handler, error) {
function Register (line 96) | func Register(registrar tchannel.Registrar, funcs Handlers, onError func...
FILE: json/json_test.go
type ForwardArgs (line 36) | type ForwardArgs struct
type Res (line 44) | type Res struct
type testHandler (line 48) | type testHandler struct
method forward (line 55) | func (h *testHandler) forward(ctx Context, args *ForwardArgs) (*Res, e...
method leaf (line 83) | func (h *testHandler) leaf(ctx Context, _ *struct{}) (*Res, error) {
method onError (line 90) | func (h *testHandler) onError(ctx context.Context, err error) {
function TestForwardChain (line 94) | func TestForwardChain(t *testing.T) {
function TestHeadersForwarded (line 181) | func TestHeadersForwarded(t *testing.T) {
function TestEmptyRequestHeader (line 211) | func TestEmptyRequestHeader(t *testing.T) {
function TestMapInputOutput (line 242) | func TestMapInputOutput(t *testing.T) {
FILE: json/retry_test.go
function TestRetryJSONCall (line 35) | func TestRetryJSONCall(t *testing.T) {
function TestRetryJSONNoConnect (line 60) | func TestRetryJSONNoConnect(t *testing.T) {
FILE: json/tracing_test.go
type JSONHandler (line 14) | type JSONHandler struct
method firstCall (line 19) | func (h *JSONHandler) firstCall(ctx context.Context, req *TracingReque...
method callJSON (line 29) | func (h *JSONHandler) callJSON(ctx json.Context, req *TracingRequest) ...
method onError (line 42) | func (h *JSONHandler) onError(ctx context.Context, err error) { h.t.Er...
function TestJSONTracingPropagation (line 44) | func TestJSONTracingPropagation(t *testing.T) {
FILE: largereq_test.go
function TestLargeRequest (line 37) | func TestLargeRequest(t *testing.T) {
FILE: localip.go
function scoreAddr (line 34) | func scoreAddr(iface net.Interface, addr net.Addr) (int, net.IP) {
function listenIP (line 60) | func listenIP(interfaces []net.Interface) (net.IP, error) {
function ListenIP (line 89) | func ListenIP() (net.IP, error) {
function mustParseMAC (line 97) | func mustParseMAC(s string) net.HardwareAddr {
function isLocalMacAddr (line 107) | func isLocalMacAddr(addr net.HardwareAddr) bool {
FILE: localip_test.go
function TestScoreAddr (line 30) | func TestScoreAddr(t *testing.T) {
FILE: logger.go
type Logger (line 38) | type Logger interface
type LogField (line 71) | type LogField struct
function ErrField (line 77) | func ErrField(err error) LogField {
type LogFields (line 82) | type LogFields
type nullLogger (line 87) | type nullLogger struct
method Enabled (line 91) | func (nullLogger) Enabled(_ LogLevel) bool { return fal...
method Fatal (line 92) | func (nullLogger) Fatal(msg string) { os.Exit(1) }
method Error (line 93) | func (nullLogger) Error(msg string) {}
method Warn (line 94) | func (nullLogger) Warn(msg string) {}
method Infof (line 95) | func (nullLogger) Infof(msg string, args ...interface{}) {}
method Info (line 96) | func (nullLogger) Info(msg string) {}
method Debugf (line 97) | func (nullLogger) Debugf(msg string, args ...interface{}) {}
method Debug (line 98) | func (nullLogger) Debug(msg string) {}
method Fields (line 99) | func (l nullLogger) Fields() LogFields { return l.f...
method WithFields (line 101) | func (l nullLogger) WithFields(fields ...LogField) Logger {
type writerLogger (line 111) | type writerLogger struct
method Fatal (line 123) | func (l writerLogger) Fatal(msg string) {
method Enabled (line 128) | func (l writerLogger) Enabled(_ LogLevel) bool { return...
method Error (line 129) | func (l writerLogger) Error(msg string) { l.prin...
method Warn (line 130) | func (l writerLogger) Warn(msg string) { l.prin...
method Infof (line 131) | func (l writerLogger) Infof(msg string, args ...interface{}) { l.prin...
method Info (line 132) | func (l writerLogger) Info(msg string) { l.prin...
method Debugf (line 133) | func (l writerLogger) Debugf(msg string, args ...interface{}) { l.prin...
method Debug (line 134) | func (l writerLogger) Debug(msg string) { l.prin...
method printfn (line 135) | func (l writerLogger) printfn(prefix, msg string, args ...interface{}) {
method Fields (line 139) | func (l writerLogger) Fields() LogFields {
method WithFields (line 143) | func (l writerLogger) WithFields(newFields ...LogField) Logger {
constant writerLoggerStamp (line 116) | writerLoggerStamp = "15:04:05.000000"
function NewLogger (line 119) | func NewLogger(writer io.Writer, fields ...LogField) Logger {
type LogLevel (line 152) | type LogLevel
constant LogLevelAll (line 156) | LogLevelAll LogLevel = iota
constant LogLevelDebug (line 157) | LogLevelDebug
constant LogLevelInfo (line 158) | LogLevelInfo
constant LogLevelWarn (line 159) | LogLevelWarn
constant LogLevelError (line 160) | LogLevelError
constant LogLevelFatal (line 161) | LogLevelFatal
type levelLogger (line 164) | type levelLogger struct
method Enabled (line 174) | func (l levelLogger) Enabled(level LogLevel) bool {
method Fatal (line 178) | func (l levelLogger) Fatal(msg string) {
method Error (line 184) | func (l levelLogger) Error(msg string) {
method Warn (line 190) | func (l levelLogger) Warn(msg string) {
method Infof (line 196) | func (l levelLogger) Infof(msg string, args ...interface{}) {
method Info (line 202) | func (l levelLogger) Info(msg string) {
method Debugf (line 208) | func (l levelLogger) Debugf(msg string, args ...interface{}) {
method Debug (line 214) | func (l levelLogger) Debug(msg string) {
method Fields (line 220) | func (l levelLogger) Fields() LogFields {
method WithFields (line 224) | func (l levelLogger) WithFields(fields ...LogField) Logger {
function NewLevelLogger (line 170) | func NewLevelLogger(logger Logger, level LogLevel) Logger {
FILE: logger_test.go
function field (line 33) | func field(k string, v interface{}) LogField {
function TestErrField (line 37) | func TestErrField(t *testing.T) {
function TestWriterLogger (line 41) | func TestWriterLogger(t *testing.T) {
function TestWriterLoggerNoSubstitution (line 83) | func TestWriterLoggerNoSubstitution(t *testing.T) {
function TestLevelLogger (line 129) | func TestLevelLogger(t *testing.T) {
FILE: messages.go
type messageType (line 30) | type messageType
constant messageTypeInitReq (line 33) | messageTypeInitReq messageType = 0x01
constant messageTypeInitRes (line 34) | messageTypeInitRes messageType = 0x02
constant messageTypeCallReq (line 35) | messageTypeCallReq messageType = 0x03
constant messageTypeCallRes (line 36) | messageTypeCallRes messageType = 0x04
constant messageTypeCallReqContinue (line 37) | messageTypeCallReqContinue messageType = 0x13
constant messageTypeCallResContinue (line 38) | messageTypeCallResContinue messageType = 0x14
constant messageTypeCancel (line 39) | messageTypeCancel messageType = 0xC0
constant messageTypePingReq (line 40) | messageTypePingReq messageType = 0xd0
constant messageTypePingRes (line 41) | messageTypePingRes messageType = 0xd1
constant messageTypeError (line 42) | messageTypeError messageType = 0xFF
type message (line 49) | type message interface
type noBodyMsg (line 63) | type noBodyMsg struct
method read (line 65) | func (noBodyMsg) read(r *typed.ReadBuffer) error { return nil }
method write (line 66) | func (noBodyMsg) write(w *typed.WriteBuffer) error { return nil }
type initParams (line 69) | type initParams
constant InitParamHostPort (line 73) | InitParamHostPort = "host_port"
constant InitParamProcessName (line 75) | InitParamProcessName = "process_name"
constant InitParamTChannelLanguage (line 77) | InitParamTChannelLanguage = "tchannel_language"
constant InitParamTChannelLanguageVersion (line 79) | InitParamTChannelLanguageVersion = "tchannel_language_version"
constant InitParamTChannelVersion (line 81) | InitParamTChannelVersion = "tchannel_version"
type initMessage (line 85) | type initMessage struct
method read (line 91) | func (m *initMessage) read(r *typed.ReadBuffer) error {
method write (line 105) | func (m *initMessage) write(w *typed.WriteBuffer) error {
method ID (line 117) | func (m *initMessage) ID() uint32 {
type initReq (line 122) | type initReq struct
method messageType (line 126) | func (m *initReq) messageType() messageType { return messageTypeInitReq }
type initRes (line 129) | type initRes struct
method messageType (line 133) | func (m *initRes) messageType() messageType { return messageTypeInitRes }
type TransportHeaderName (line 136) | type TransportHeaderName
method String (line 138) | func (cn TransportHeaderName) String() string { return string(cn) }
constant ArgScheme (line 145) | ArgScheme TransportHeaderName = "as"
constant CallerName (line 148) | CallerName TransportHeaderName = "cn"
constant ClaimAtFinish (line 152) | ClaimAtFinish TransportHeaderName = "caf"
constant ClaimAtStart (line 156) | ClaimAtStart TransportHeaderName = "cas"
constant FailureDomain (line 160) | FailureDomain TransportHeaderName = "fd"
constant ShardKey (line 163) | ShardKey TransportHeaderName = "sk"
constant RetryFlags (line 166) | RetryFlags TransportHeaderName = "re"
constant SpeculativeExecution (line 169) | SpeculativeExecution TransportHeaderName = "se"
constant RoutingDelegate (line 173) | RoutingDelegate TransportHeaderName = "rd"
constant RoutingKey (line 178) | RoutingKey TransportHeaderName = "rk"
type transportHeaders (line 182) | type transportHeaders
method read (line 184) | func (ch transportHeaders) read(r *typed.ReadBuffer) {
method write (line 193) | func (ch transportHeaders) write(w *typed.WriteBuffer) {
type callReq (line 203) | type callReq struct
method ID (line 211) | func (m *callReq) ID() uint32 { return m.id }
method messageType (line 212) | func (m *callReq) messageType() messageType { return messageTypeCallReq }
method read (line 213) | func (m *callReq) read(r *typed.ReadBuffer) error {
method write (line 222) | func (m *callReq) write(w *typed.WriteBuffer) error {
type callReqContinue (line 231) | type callReqContinue struct
method ID (line 236) | func (c *callReqContinue) ID() uint32 { return c.id }
method messageType (line 237) | func (c *callReqContinue) messageType() messageType { return messageTy...
type ResponseCode (line 240) | type ResponseCode
constant responseOK (line 243) | responseOK ResponseCode = 0x00
constant responseApplicationError (line 244) | responseApplicationError ResponseCode = 0x01
type callRes (line 248) | type callRes struct
method ID (line 255) | func (m *callRes) ID() uint32 { return m.id }
method messageType (line 256) | func (m *callRes) messageType() messageType { return messageTypeCallRes }
method read (line 258) | func (m *callRes) read(r *typed.ReadBuffer) error {
method write (line 266) | func (m *callRes) write(w *typed.WriteBuffer) error {
type callResContinue (line 274) | type callResContinue struct
method ID (line 278) | func (c *callResContinue) ID() uint32 { return c...
method messageType (line 279) | func (c *callResContinue) messageType() messageType { return m...
method read (line 280) | func (c *callResContinue) read(r *typed.ReadBuffer) error { return n...
method write (line 281) | func (c *callResContinue) write(w *typed.WriteBuffer) error { return n...
type errorMessage (line 284) | type errorMessage struct
method ID (line 291) | func (m *errorMessage) ID() uint32 { return m.id }
method messageType (line 292) | func (m *errorMessage) messageType() messageType { return messageTypeE...
method read (line 293) | func (m *errorMessage) read(r *typed.ReadBuffer) error {
method write (line 300) | func (m *errorMessage) write(w *typed.WriteBuffer) error {
method AsSystemError (line 307) | func (m errorMessage) AsSystemError() error {
method Error (line 313) | func (m errorMessage) Error() string {
type cancelMessage (line 317) | type cancelMessage struct
method ID (line 324) | func (m *cancelMessage) ID() uint32 { return m.id }
method messageType (line 325) | func (m *cancelMessage) messageType() messageType { return messageType...
method read (line 326) | func (m *cancelMessage) read(r *typed.ReadBuffer) error {
method write (line 333) | func (m *cancelMessage) write(w *typed.WriteBuffer) error {
method AsSystemError (line 340) | func (m *cancelMessage) AsSystemError() error {
type pingReq (line 344) | type pingReq struct
method ID (line 349) | func (c *pingReq) ID() uint32 { return c.id }
method messageType (line 350) | func (c *pingReq) messageType() messageType { return messageTypePingReq }
type pingRes (line 353) | type pingRes struct
method ID (line 358) | func (c *pingRes) ID() uint32 { return c.id }
method messageType (line 359) | func (c *pingRes) messageType() messageType { return messageTypePingRes }
function callReqSpan (line 361) | func callReqSpan(f *Frame) Span {
FILE: messages_test.go
function TestInitReq (line 35) | func TestInitReq(t *testing.T) {
function TestInitRes (line 52) | func TestInitRes(t *testing.T) {
function TestCallReq (line 69) | func TestCallReq(t *testing.T) {
function TestCallReqContinue (line 91) | func TestCallReqContinue(t *testing.T) {
function TestCallRes (line 101) | func TestCallRes(t *testing.T) {
function TestCallResContinue (line 122) | func TestCallResContinue(t *testing.T) {
function TestErrorMessage (line 132) | func TestErrorMessage(t *testing.T) {
function assertRoundTrip (line 142) | func assertRoundTrip(t *testing.T, expected message, actual message) {
FILE: messagetype_string.go
function _ (line 7) | func _() {
constant _messageType_name_0 (line 24) | _messageType_name_0 = "messageTypeInitReqmessageTypeInitResmessageTypeCa...
constant _messageType_name_1 (line 25) | _messageType_name_1 = "messageTypeCallReqContinuemessageTypeCallResConti...
constant _messageType_name_2 (line 26) | _messageType_name_2 = "messageTypeCancel"
constant _messageType_name_3 (line 27) | _messageType_name_3 = "messageTypePingReqmessageTypePingRes"
constant _messageType_name_4 (line 28) | _messageType_name_4 = "messageTypeError"
method String (line 37) | func (i messageType) String() string {
FILE: mex.go
constant messageExchangeSetInbound (line 43) | messageExchangeSetInbound = "inbound"
constant messageExchangeSetOutbound (line 44) | messageExchangeSetOutbound = "outbound"
constant mexChannelBufferSize (line 47) | mexChannelBufferSize = 2
type errNotifier (line 50) | type errNotifier struct
method Notify (line 61) | func (e *errNotifier) Notify(err error) error {
method checkErr (line 78) | func (e *errNotifier) checkErr() error {
function newErrNotifier (line 56) | func newErrNotifier() errNotifier {
type messageExchange (line 91) | type messageExchange struct
method checkError (line 107) | func (mex *messageExchange) checkError() error {
method forwardPeerFrame (line 117) | func (mex *messageExchange) forwardPeerFrame(frame *Frame) error {
method handleCancel (line 147) | func (mex *messageExchange) handleCancel(_ *Frame) {
method checkFrame (line 153) | func (mex *messageExchange) checkFrame(frame *Frame) error {
method recvPeerFrame (line 166) | func (mex *messageExchange) recvPeerFrame() (*Frame, error) {
method recvPeerFrameOfType (line 205) | func (mex *messageExchange) recvPeerFrameOfType(msgType messageType) (...
method onCtxErr (line 240) | func (mex *messageExchange) onCtxErr(err error) {
method shutdown (line 255) | func (mex *messageExchange) shutdown() {
method inboundExpired (line 274) | func (mex *messageExchange) inboundExpired() {
type messageExchangeSet (line 286) | type messageExchangeSet struct
method addExchange (line 312) | func (mexset *messageExchangeSet) addExchange(mex *messageExchange) er...
method newExchange (line 326) | func (mexset *messageExchangeSet) newExchange(ctx context.Context, ctx...
method deleteExchange (line 370) | func (mexset *messageExchangeSet) deleteExchange(msgID uint32) (found,...
method removeExchange (line 385) | func (mexset *messageExchangeSet) removeExchange(msgID uint32) {
method expireExchange (line 408) | func (mexset *messageExchangeSet) expireExchange(msgID uint32) {
method count (line 431) | func (mexset *messageExchangeSet) count() int {
method forwardPeerFrame (line 441) | func (mexset *messageExchangeSet) forwardPeerFrame(frame *Frame) error {
method handleCancel (line 472) | func (mexset *messageExchangeSet) handleCancel(frame *Frame) {
method copyExchanges (line 495) | func (mexset *messageExchangeSet) copyExchanges() (shutdown bool, exch...
method stopExchanges (line 510) | func (mexset *messageExchangeSet) stopExchanges(err error) {
function newMessageExchangeSet (line 302) | func newMessageExchangeSet(log Logger, name string) *messageExchangeSet {
FILE: mex_utils_test.go
function CheckEmptyExchangesConn (line 30) | func CheckEmptyExchangesConn(c *ConnectionRuntimeState) string {
function CheckEmptyExchangesConns (line 50) | func CheckEmptyExchangesConns(connections []*ConnectionRuntimeState) str...
function CheckEmptyExchanges (line 64) | func CheckEmptyExchanges(ch *Channel) string {
FILE: outbound.go
constant maxMethodSize (line 35) | maxMethodSize = 16 * 1024
method beginCall (line 38) | func (c *Connection) beginCall(ctx context.Context, serviceName, methodN...
method outboundCtxCancel (line 140) | func (c *Connection) outboundCtxCancel() {
method handleCallRes (line 148) | func (c *Connection) handleCallRes(frame *Frame) bool {
method handleCallResContinue (line 157) | func (c *Connection) handleCallResContinue(frame *Frame) bool {
type OutboundCall (line 168) | type OutboundCall struct
method Response (line 179) | func (call *OutboundCall) Response() *OutboundCallResponse {
method createStatsTags (line 184) | func (call *OutboundCall) createStatsTags(connectionTags map[string]st...
method writeMethod (line 197) | func (call *OutboundCall) writeMethod(method []byte) error {
method Arg2Writer (line 204) | func (call *OutboundCall) Arg2Writer() (ArgWriter, error) {
method Arg3Writer (line 210) | func (call *OutboundCall) Arg3Writer() (ArgWriter, error) {
method LocalPeer (line 215) | func (call *OutboundCall) LocalPeer() LocalPeerInfo {
method RemotePeer (line 220) | func (call *OutboundCall) RemotePeer() PeerInfo {
method doneSending (line 224) | func (call *OutboundCall) doneSending() {}
type OutboundCallResponse (line 227) | type OutboundCallResponse struct
method ApplicationError (line 245) | func (response *OutboundCallResponse) ApplicationError() bool {
method Format (line 251) | func (response *OutboundCallResponse) Format() Format {
method Arg2Reader (line 257) | func (response *OutboundCallResponse) Arg2Reader() (ArgReader, error) {
method Arg3Reader (line 268) | func (response *OutboundCallResponse) Arg3Reader() (ArgReader, error) {
method doneReading (line 326) | func (response *OutboundCallResponse) doneReading(unexpected error) {
method handleError (line 278) | func (c *Connection) handleError(frame *Frame) bool {
function cloneTags (line 316) | func cloneTags(tags map[string]string) map[string]string {
function validateCall (line 371) | func validateCall(ctx context.Context, serviceName, methodName string, c...
FILE: peer.go
type Connectable (line 55) | type Connectable interface
type PeerList (line 63) | type PeerList struct
method SetStrategy (line 83) | func (l *PeerList) SetStrategy(sc ScoreCalculator) {
method newSibling (line 96) | func (l *PeerList) newSibling() *PeerList {
method Add (line 102) | func (l *PeerList) Add(hostPort string) *Peer {
method GetNew (line 124) | func (l *PeerList) GetNew(prevSelected map[string]struct{}) (*Peer, er...
method Get (line 145) | func (l *PeerList) Get(prevSelected map[string]struct{}) (*Peer, error) {
method Remove (line 162) | func (l *PeerList) Remove(hostPort string) error {
method choosePeer (line 177) | func (l *PeerList) choosePeer(prevSelected map[string]struct{}, avoidH...
method GetOrAdd (line 218) | func (l *PeerList) GetOrAdd(hostPort string) *Peer {
method Copy (line 224) | func (l *PeerList) Copy() map[string]*Peer {
method Len (line 236) | func (l *PeerList) Len() int {
method exists (line 243) | func (l *PeerList) exists(hostPort string) (*peerScore, bool) {
method getPeerScore (line 253) | func (l *PeerList) getPeerScore(hostPort string) (*peerScore, uint64, ...
method onPeerChange (line 263) | func (l *PeerList) onPeerChange(p *Peer) {
method updatePeer (line 284) | func (l *PeerList) updatePeer(ps *peerScore, newScore uint64) {
function newPeerList (line 73) | func newPeerList(root *RootPeerList) *PeerList {
type peerScore (line 295) | type peerScore struct
function newPeerScore (line 307) | func newPeerScore(p *Peer, score uint64) *peerScore {
type Peer (line 316) | type Peer struct
method HostPort (line 353) | func (p *Peer) HostPort() string {
method getConn (line 359) | func (p *Peer) getConn(i int) *Connection {
method getActiveConnLocked (line 368) | func (p *Peer) getActiveConnLocked() (*Connection, bool) {
method getActiveConn (line 393) | func (p *Peer) getActiveConn() (*Connection, bool) {
method GetConnection (line 403) | func (p *Peer) GetConnection(ctx context.Context) (*Connection, error) {
method getConnectionRelay (line 423) | func (p *Peer) getConnectionRelay(callTimeout, relayMaxConnTimeout tim...
method addSC (line 454) | func (p *Peer) addSC() {
method delSC (line 461) | func (p *Peer) delSC() {
method canRemove (line 468) | func (p *Peer) canRemove() bool {
method addConnection (line 477) | func (p *Peer) addConnection(c *Connection, direction connectionDirect...
method connectionsFor (line 494) | func (p *Peer) connectionsFor(direction connectionDirection) *[]*Conne...
method removeConnection (line 503) | func (p *Peer) removeConnection(connsPtr *[]*Connection, changed *Conn...
method connectionCloseStateChange (line 521) | func (p *Peer) connectionCloseStateChange(changed *Connection) {
method Connect (line 541) | func (p *Peer) Connect(ctx context.Context) (*Connection, error) {
method BeginCall (line 547) | func (p *Peer) BeginCall(ctx context.Context, serviceName, methodName ...
method NumConnections (line 571) | func (p *Peer) NumConnections() (inbound int, outbound int) {
method NumPendingOutbound (line 580) | func (p *Peer) NumPendingOutbound() int {
method runWithConnections (line 594) | func (p *Peer) runWithConnections(f func(*Connection)) {
method callOnUpdateComplete (line 606) | func (p *Peer) callOnUpdateComplete() {
function newPeer (line 337) | func newPeer(channel Connectable, hostPort string, onStatusChanged func(...
function noopOnStatusChanged (line 616) | func noopOnStatusChanged(*Peer) {}
function isEphemeralHostPort (line 619) | func isEphemeralHostPort(hostPort string) bool {
FILE: peer_bench_test.go
function benchmarkGetConnection (line 34) | func benchmarkGetConnection(b *testing.B, numIncoming, numOutgoing int) {
function BenchmarkGetConnection0In1Out (line 59) | func BenchmarkGetConnection0In1Out(b *testing.B) { benchmarkGetConnectio...
function BenchmarkGetConnection1In0Out (line 60) | func BenchmarkGetConnection1In0Out(b *testing.B) { benchmarkGetConnectio...
function BenchmarkGetConnection5In5Out (line 61) | func BenchmarkGetConnection5In5Out(b *testing.B) { benchmarkGetConnectio...
FILE: peer_heap.go
type peerHeap (line 32) | type peerHeap struct
method Len (line 42) | func (ph peerHeap) Len() int { return len(ph.peerScores) }
method Less (line 44) | func (ph *peerHeap) Less(i, j int) bool {
method Swap (line 51) | func (ph peerHeap) Swap(i, j int) {
method Push (line 58) | func (ph *peerHeap) Push(x interface{}) {
method Pop (line 66) | func (ph *peerHeap) Pop() interface{} {
method updatePeer (line 76) | func (ph *peerHeap) updatePeer(peerScore *peerScore) {
method removePeer (line 81) | func (ph *peerHeap) removePeer(peerScore *peerScore) {
method popPeer (line 86) | func (ph *peerHeap) popPeer() *peerScore {
method pushPeer (line 91) | func (ph *peerHeap) pushPeer(peerScore *peerScore) {
method swapOrder (line 100) | func (ph *peerHeap) swapOrder(i, j int) {
method addPeer (line 111) | func (ph *peerHeap) addPeer(peerScore *peerScore) {
method peek (line 120) | func (ph *peerHeap) peek() *peerScore {
function newPeerHeap (line 38) | func newPeerHeap() *peerHeap {
FILE: peer_heap_test.go
function TestPeerHeap (line 32) | func TestPeerHeap(t *testing.T) {
FILE: peer_internal_test.go
function TestIsEphemeralHostPort (line 29) | func TestIsEphemeralHostPort(t *testing.T) {
FILE: peer_strategies.go
type ScoreCalculator (line 26) | type ScoreCalculator interface
type ScoreCalculatorFunc (line 31) | type ScoreCalculatorFunc
method GetScore (line 34) | func (f ScoreCalculatorFunc) GetScore(p *Peer) uint64 {
type zeroCalculator (line 38) | type zeroCalculator struct
method GetScore (line 40) | func (zeroCalculator) GetScore(p *Peer) uint64 {
function newZeroCalculator (line 44) | func newZeroCalculator() zeroCalculator {
type leastPendingCalculator (line 48) | type leastPendingCalculator struct
method GetScore (line 50) | func (leastPendingCalculator) GetScore(p *Peer) uint64 {
function newLeastPendingCalculator (line 62) | func newLeastPendingCalculator() leastPendingCalculator {
type preferIncomingCalculator (line 66) | type preferIncomingCalculator struct
method GetScore (line 68) | func (preferIncomingCalculator) GetScore(p *Peer) uint64 {
function newPreferIncomingCalculator (line 87) | func newPreferIncomingCalculator() preferIncomingCalculator {
FILE: peer_test.go
function fakePeer (line 41) | func fakePeer(t *testing.T, ch *Channel, hostPort string) *Peer {
function assertNumConnections (line 55) | func assertNumConnections(t *testing.T, peer *Peer, in, out int) {
function TestGetPeerNoPeer (line 61) | func TestGetPeerNoPeer(t *testing.T) {
function TestGetPeerSinglePeer (line 69) | func TestGetPeerSinglePeer(t *testing.T) {
function TestPeerUpdatesLen (line 79) | func TestPeerUpdatesLen(t *testing.T) {
function TestGetPeerAvoidPrevSelected (line 94) | func TestGetPeerAvoidPrevSelected(t *testing.T) {
function TestPeerRemoveClosedConnection (line 191) | func TestPeerRemoveClosedConnection(t *testing.T) {
function TestPeerConnectCancelled (line 219) | func TestPeerConnectCancelled(t *testing.T) {
function TestPeerGetConnectionWithNoActiveConnections (line 230) | func TestPeerGetConnectionWithNoActiveConnections(t *testing.T) {
function TestInboundEphemeralPeerRemoved (line 272) | func TestInboundEphemeralPeerRemoved(t *testing.T) {
function TestOutboundEphemeralPeerRemoved (line 299) | func TestOutboundEphemeralPeerRemoved(t *testing.T) {
function TestOutboundPeerNotAdded (line 319) | func TestOutboundPeerNotAdded(t *testing.T) {
function TestRemovePeerNotFound (line 338) | func TestRemovePeerNotFound(t *testing.T) {
function TestPeerRemovedFromRootPeers (line 348) | func TestPeerRemovedFromRootPeers(t *testing.T) {
function TestPeerSelectionConnClosed (line 399) | func TestPeerSelectionConnClosed(t *testing.T) {
function TestPeerSelectionPreferIncoming (line 426) | func TestPeerSelectionPreferIncoming(t *testing.T) {
type peerTest (line 575) | type peerTest struct
method NewService (line 581) | func (pt *peerTest) NewService(t testing.TB, svcName, processName stri...
method CleanUp (line 589) | func (pt *peerTest) CleanUp() {
function TestPeerSelection (line 595) | func TestPeerSelection(t *testing.T) {
function getAllPeers (line 617) | func getAllPeers(t *testing.T, pl *PeerList) []string {
function reverse (line 637) | func reverse(s []string) {
function TestIsolatedPeerHeap (line 644) | func TestIsolatedPeerHeap(t *testing.T) {
function TestPeerSelectionRanking (line 667) | func TestPeerSelectionRanking(t *testing.T) {
function createScoreStrategy (line 700) | func createScoreStrategy(initial, delta int64) (calc ScoreCalculator, re...
function createSubChannelWNewStrategy (line 712) | func createSubChannelWNewStrategy(ch *Channel, name string, initial, del...
function testDistribution (line 720) | func testDistribution(t testing.TB, counts map[string]int, min, max floa...
function waitTillNConnections (line 731) | func waitTillNConnections(t *testing.T, ch *Channel, hostPort string, in...
function waitTillInboundEmpty (line 767) | func waitTillInboundEmpty(t *testing.T, ch *Channel, hostPort string, f ...
type peerSelectionTest (line 771) | type peerSelectionTest struct
method setup (line 791) | func (pt *peerSelectionTest) setup(t testing.TB) {
method setupServers (line 798) | func (pt *peerSelectionTest) setupServers(t testing.TB) {
method setupAffinity (line 808) | func (pt *peerSelectionTest) setupAffinity(t testing.TB) {
method setupClient (line 844) | func (pt *peerSelectionTest) setupClient(t testing.TB) {
method makeCall (line 852) | func (pt *peerSelectionTest) makeCall(sc *SubChannel) {
method sendPing (line 859) | func (pt *peerSelectionTest) sendPing(ch *Channel, hostport string) {
method runStressSimple (line 866) | func (pt *peerSelectionTest) runStressSimple(b *testing.B) {
method runStress (line 884) | func (pt *peerSelectionTest) runStress() {
function BenchmarkSimplePeerHeapPerf (line 944) | func BenchmarkSimplePeerHeapPerf(b *testing.B) {
function TestPeerHeapPerf (line 956) | func TestPeerHeapPerf(t *testing.T) {
function peerHeapStress (line 990) | func peerHeapStress(t testing.TB, numserver int, affinityRatio float64, ...
function validateStressTest (line 1005) | func validateStressTest(t testing.TB, server *Channel, numAffinity int, ...
function TestPeerSelectionAfterClosed (line 1028) | func TestPeerSelectionAfterClosed(t *testing.T) {
function TestPeerScoreOnNewConnection (line 1051) | func TestPeerScoreOnNewConnection(t *testing.T) {
function TestConnectToPeerHostPortMismatch (line 1106) | func TestConnectToPeerHostPortMismatch(t *testing.T) {
function TestPeerConnectionsClosing (line 1128) | func TestPeerConnectionsClosing(t *testing.T) {
function BenchmarkAddPeers (line 1169) | func BenchmarkAddPeers(b *testing.B) {
function TestPeerSelectionStrategyChange (line 1179) | func TestPeerSelectionStrategyChange(t *testing.T) {
function createConstScoreStrategy (line 1197) | func createConstScoreStrategy(score uint64) (calc ScoreCalculator) {
FILE: peers/prefer.go
type hrwScoreCalc (line 25) | type hrwScoreCalc struct
method GetScore (line 40) | func (s *hrwScoreCalc) GetScore(p *tchannel.Peer) uint64 {
function NewHRWScorer (line 36) | func NewHRWScorer(clientID uint32) tchannel.ScoreCalculator {
function mod2_31 (line 49) | func mod2_31(v uint32) uint32 {
function fnv32a (line 58) | func fnv32a(s string) uint32 {
FILE: peers/prefer_test.go
function TestHRWScorerGetScore (line 39) | func TestHRWScorerGetScore(t *testing.T) {
function TestHRWScorerDistribution (line 49) | func TestHRWScorerDistribution(t *testing.T) {
function countingServer (line 86) | func countingServer(t *testing.T, opts *testutils.ChannelOpts) (*tchanne...
function TestHRWScorerIntegration (line 93) | func TestHRWScorerIntegration(t *testing.T) {
function stdFnv32a (line 163) | func stdFnv32a(s string) uint32 {
function TestFnv32a (line 169) | func TestFnv32a(t *testing.T) {
function BenchmarkHrwScoreCalc (line 181) | func BenchmarkHrwScoreCalc(b *testing.B) {
FILE: pprof/pprof.go
function serveHTTP (line 33) | func serveHTTP(req *http.Request, response *tchannel.InboundCallResponse) {
function Register (line 41) | func Register(registrar tchannel.Registrar) {
FILE: pprof/pprof_test.go
function TestPProfEndpoint (line 37) | func TestPProfEndpoint(t *testing.T) {
FILE: preinit_connection.go
method outboundHandshake (line 35) | func (ch *Channel) outboundHandshake(ctx context.Context, c net.Conn, ou...
method inboundHandshake (line 73) | func (ch *Channel) inboundHandshake(ctx context.Context, c net.Conn, eve...
method getInitParams (line 104) | func (ch *Channel) getInitParams() initParams {
method getInitMessage (line 115) | func (ch *Channel) getInitMessage(ctx context.Context, id uint32) initMe...
method initError (line 128) | func (ch *Channel) initError(c net.Conn, connDir connectionDirection, id...
method writeMessage (line 155) | func (ch *Channel) writeMessage(c net.Conn, msg message) error {
method readMessage (line 165) | func (ch *Channel) readMessage(c net.Conn, msg message) (uint32, error) {
function parseRemotePeer (line 183) | func parseRemotePeer(p initParams, remoteAddr net.Addr) (PeerInfo, peerA...
function setInitDeadline (line 230) | func setInitDeadline(ctx context.Context, c net.Conn) func() {
function readError (line 242) | func readError(frame *Frame) error {
function unsupportedProtocolVersion (line 253) | func unsupportedProtocolVersion(got uint16) error {
FILE: raw/call.go
function ReadArgsV2 (line 35) | func ReadArgsV2(r tchannel.ArgReadable) ([]byte, []byte, error) {
function WriteArgs (line 50) | func WriteArgs(call *tchannel.OutboundCall, arg2, arg3 []byte) ([]byte, ...
function Call (line 74) | func Call(ctx context.Context, ch *tchannel.Channel, hostPort string, se...
function CallSC (line 86) | func CallSC(ctx context.Context, sc *tchannel.SubChannel, method string,...
type CArgs (line 98) | type CArgs struct
type CRes (line 106) | type CRes struct
function CallV2 (line 113) | func CallV2(ctx context.Context, sc *tchannel.SubChannel, cArgs CArgs) (...
FILE: raw/handler.go
type Handler (line 30) | type Handler interface
type Args (line 38) | type Args struct
type Res (line 47) | type Res struct
function ReadArgs (line 56) | func ReadArgs(call *tchannel.InboundCall) (*Args, error) {
function WriteResponse (line 71) | func WriteResponse(response *tchannel.InboundCallResponse, resp *Res) er...
function Wrap (line 87) | func Wrap(handler Handler) tchannel.Handler {
FILE: relay.go
constant _defaultRelayMaxTombs (line 41) | _defaultRelayMaxTombs = 3e4
constant _relayTombTTL (line 43) | _relayTombTTL = 3 * time.Second
constant _defaultRelayMaxTimeout (line 45) | _defaultRelayMaxTimeout = 2 * time.Minute
constant _relayErrorNotFound (line 50) | _relayErrorNotFound = "relay-not-found"
constant _relayErrorDestConnSlow (line 51) | _relayErrorDestConnSlow = "relay-dest-conn-slow"
constant _relayErrorSourceConnSlow (line 52) | _relayErrorSourceConnSlow = "relay-source-conn-slow"
constant _relayArg2ModifyFailed (line 53) | _relayArg2ModifyFailed = "relay-arg2-modify-failed"
constant _relayNoRelease (line 59) | _relayNoRelease = false
constant _relayShouldRelease (line 60) | _relayShouldRelease = true
type relayItem (line 74) | type relayItem struct
method reportRelayBytes (line 110) | func (ri *relayItem) reportRelayBytes(fType frameType, frameSize uint1...
type relayItems (line 85) | type relayItems struct
method Count (line 119) | func (r *relayItems) Count() int {
method Get (line 129) | func (r *relayItems) Get(id uint32, stopTimeout bool) (_ relayItem, st...
method Add (line 146) | func (r *relayItems) Add(id uint32, item relayItem) {
method Delete (line 155) | func (r *relayItems) Delete(id uint32) (relayItem, bool) {
method Entomb (line 176) | func (r *relayItems) Entomb(id uint32, deleteAfter time.Duration) (rel...
type frameReceiver (line 95) | type frameReceiver interface
function newRelayItems (line 99) | func newRelayItems(logger Logger, maxTombs uint64) *relayItems {
type frameType (line 205) | type frameType
constant requestFrame (line 208) | requestFrame frameType = 0
constant responseFrame (line 209) | responseFrame frameType = 1
type Relayer (line 215) | type Relayer struct
method Relay (line 269) | func (r *Relayer) Relay(f *Frame) (shouldRelease bool, _ error) {
method Receive (line 293) | func (r *Relayer) Receive(f *Frame, fType frameType) (sent bool, failu...
method canHandleNewCall (line 371) | func (r *Relayer) canHandleNewCall() (bool, connectionState) {
method getDestination (line 388) | func (r *Relayer) getDestination(f *lazyCallReq, call RelayCall) (*Con...
method handleCallReq (line 426) | func (r *Relayer) handleCallReq(f *lazyCallReq) (shouldRelease bool, _...
method handleNonCallReq (line 535) | func (r *Relayer) handleNonCallReq(f *Frame) (shouldRelease bool, _ er...
method addRelayItem (line 597) | func (r *Relayer) addRelayItem(isOriginator bool, id, remapID uint32, ...
method timeoutRelayItem (line 617) | func (r *Relayer) timeoutRelayItem(items *relayItems, id uint32, isOri...
method failRelayItem (line 634) | func (r *Relayer) failRelayItem(items *relayItems, id uint32, reason s...
method finishRelayItem (line 663) | func (r *Relayer) finishRelayItem(items *relayItems, id uint32) {
method decrementPending (line 677) | func (r *Relayer) decrementPending() {
method canClose (line 682) | func (r *Relayer) canClose() bool {
method countPending (line 689) | func (r *Relayer) countPending() uint32 {
method receiverItems (line 693) | func (r *Relayer) receiverItems(fType frameType) *relayItems {
method handleLocalCallReq (line 700) | func (r *Relayer) handleLocalCallReq(cr *lazyCallReq) (shouldRelease b...
method fragmentingSend (line 728) | func (r *Relayer) fragmentingSend(call RelayCall, f *lazyCallReq, rela...
method updateMutatedCallReqContinueChecksum (line 763) | func (r *Relayer) updateMutatedCallReqContinueChecksum(f *Frame, cs Ch...
method newFragmentSender (line 871) | func (r *Relayer) newFragmentSender(dstRelay frameReceiver, cr *lazyCa...
function NewRelayer (line 246) | func NewRelayer(ch *Channel, conn *Connection) *Relayer {
function writeArg2WithAppends (line 788) | func writeArg2WithAppends(w io.WriteCloser, arg2 []byte, appends []relay...
function frameTypeFor (line 814) | func frameTypeFor(f *Frame) frameType {
function determinesCallSuccess (line 825) | func determinesCallSuccess(f *Frame) (succeeded bool, failMsg string) {
function validateRelayMaxTimeout (line 842) | func validateRelayMaxTimeout(d time.Duration, logger Logger) time.Durati...
type sentBytesReporter (line 857) | type sentBytesReporter interface
type relayFragmentSender (line 861) | type relayFragmentSender struct
method newFragment (line 884) | func (rfs *relayFragmentSender) newFragment(initial bool, checksum Che...
method flushFragment (line 931) | func (rfs *relayFragmentSender) flushFragment(wf *writableFragment) er...
method doneSending (line 944) | func (rfs *relayFragmentSender) doneSending() {}
FILE: relay/relay.go
type KeyVal (line 35) | type KeyVal struct
type CallFrame (line 41) | type CallFrame interface
type RespFrame (line 71) | type RespFrame interface
type Conn (line 86) | type Conn struct
type RateLimitDropError (line 108) | type RateLimitDropError struct
method Error (line 110) | func (e RateLimitDropError) Error() string {
FILE: relay/relaytest/func_host.go
type hostFunc (line 13) | type hostFunc struct
method SetChannel (line 31) | func (hf *hostFunc) SetChannel(ch *tchannel.Channel) {
method Start (line 36) | func (hf *hostFunc) Start(cf relay.CallFrame, conn *relay.Conn) (tchan...
method Stats (line 48) | func (hf *hostFunc) Stats() *MockStats {
type hostFuncPeer (line 19) | type hostFuncPeer struct
method Destination (line 52) | func (p *hostFuncPeer) Destination() (*tchannel.Peer, bool) {
method CallResponse (line 56) | func (p *hostFuncPeer) CallResponse(frame relay.RespFrame) {
function HostFunc (line 27) | func HostFunc(fn func(relay.CallFrame, *relay.Conn) (string, error)) tch...
FILE: relay/relaytest/mock_stats.go
type MockCallStats (line 36) | type MockCallStats struct
method Succeeded (line 49) | func (m *MockCallStats) Succeeded() {
method Failed (line 54) | func (m *MockCallStats) Failed(reason string) {
method SentBytes (line 59) | func (m *MockCallStats) SentBytes(size uint16) {
method ReceivedBytes (line 64) | func (m *MockCallStats) ReceivedBytes(size uint16) {
method End (line 69) | func (m *MockCallStats) End() {
type FluentMockCallStats (line 75) | type FluentMockCallStats struct
method Succeeded (line 80) | func (f *FluentMockCallStats) Succeeded() *FluentMockCallStats {
method Failed (line 86) | func (f *FluentMockCallStats) Failed(reason string) *FluentMockCallSta...
type MockStats (line 92) | type MockStats struct
method Begin (line 106) | func (m *MockStats) Begin(f relay.CallFrame) *MockCallStats {
method Add (line 111) | func (m *MockStats) Add(caller, callee, procedure string) *FluentMockC...
method AssertEqual (line 122) | func (m *MockStats) AssertEqual(t testing.TB, expected *MockStats) {
method WaitForEnd (line 139) | func (m *MockStats) WaitForEnd() {
method assertEdgeEqual (line 143) | func (m *MockStats) assertEdgeEqual(t testing.TB, expected *MockStats,...
method assertCallEqual (line 153) | func (m *MockStats) assertCallEqual(t testing.TB, expected *MockCallSt...
method tripleToKey (line 173) | func (m *MockStats) tripleToKey(caller, callee, procedure string) stri...
method Map (line 188) | func (m *MockStats) Map() map[string]int {
function NewMockStats (line 99) | func NewMockStats() *MockStats {
function getEdges (line 177) | func getEdges(m map[string][]*MockCallStats) []string {
FILE: relay/relaytest/stub_host.go
type StubRelayHost (line 35) | type StubRelayHost struct
method SetFrameFn (line 58) | func (rh *StubRelayHost) SetFrameFn(f func(relay.CallFrame, *relay.Con...
method SetRespFrameFn (line 63) | func (rh *StubRelayHost) SetRespFrameFn(f func(relay.RespFrame)) {
method SetChannel (line 69) | func (rh *StubRelayHost) SetChannel(ch *tchannel.Channel) {
method Start (line 74) | func (rh *StubRelayHost) Start(cf relay.CallFrame, conn *relay.Conn) (...
method Add (line 89) | func (rh *StubRelayHost) Add(service, hostPort string) {
method Stats (line 94) | func (rh *StubRelayHost) Stats() *MockStats {
type stubCall (line 42) | type stubCall struct
method Destination (line 99) | func (c *stubCall) Destination() (*tchannel.Peer, bool) {
method CallResponse (line 103) | func (c *stubCall) CallResponse(frame relay.RespFrame) {
function NewStubRelayHost (line 50) | func NewStubRelayHost() *StubRelayHost {
FILE: relay_api.go
type RelayHost (line 27) | type RelayHost interface
type RelayCall (line 42) | type RelayCall interface
FILE: relay_benchmark_test.go
type benchmarkParams (line 17) | type benchmarkParams struct
type workerControl (line 23) | type workerControl struct
method WaitForStart (line 42) | func (c *workerControl) WaitForStart(f func()) {
method WaitForEnd (line 48) | func (c *workerControl) WaitForEnd() {
method WorkerStart (line 52) | func (c *workerControl) WorkerStart() {
method WorkerDone (line 57) | func (c *workerControl) WorkerDone() {
function init (line 29) | func init() {
function newWorkerControl (line 33) | func newWorkerControl(numWorkers int) *workerControl {
function defaultParams (line 61) | func defaultParams() benchmarkParams {
function closeAndVerify (line 69) | func closeAndVerify(b *testing.B, ch *Channel) {
function benchmarkRelay (line 79) | func benchmarkRelay(b *testing.B, p benchmarkParams) {
function BenchmarkRelayNoLatencies (line 181) | func BenchmarkRelayNoLatencies(b *testing.B) {
function BenchmarkRelay2Servers5Clients1k (line 218) | func BenchmarkRelay2Servers5Clients1k(b *testing.B) {
function BenchmarkRelay4Servers20Clients1k (line 225) | func BenchmarkRelay4Servers20Clients1k(b *testing.B) {
function BenchmarkRelay2Servers5Clients4k (line 232) | func BenchmarkRelay2Servers5Clients4k(b *testing.B) {
function BenchmarkRelayAppends (line 240) | func BenchmarkRelayAppends(b *testing.B) {
FILE: relay_fragment_sender_test.go
type dummyFrameReceiver (line 15) | type dummyFrameReceiver struct
method Receive (line 32) | func (d *dummyFrameReceiver) Receive(f *Frame, fType frameType) (sent ...
function newDummyFrameReceiver (line 24) | func newDummyFrameReceiver(retSent bool, retFailureReason string, pool F...
type noopSentReporter (line 45) | type noopSentReporter struct
method SentBytes (line 47) | func (r *noopSentReporter) SentBytes(_ uint16) {}
function TestRelayFragmentSender (line 49) | func TestRelayFragmentSender(t *testing.T) {
type dummyArgWriter (line 110) | type dummyArgWriter struct
method Write (line 117) | func (w *dummyArgWriter) Write(b []byte) (int, error) {
method Close (line 127) | func (w *dummyArgWriter) Close() error {
function TestWriteArg2WithAppends (line 134) | func TestWriteArg2WithAppends(t *testing.T) {
FILE: relay_internal_test.go
function TestFinishesCallResponses (line 12) | func TestFinishesCallResponses(t *testing.T) {
function TestRelayTimerPoolMisuse (line 51) | func TestRelayTimerPoolMisuse(t *testing.T) {
FILE: relay_messages.go
constant _flagsIndex (line 46) | _flagsIndex = 0
constant _ttlIndex (line 50) | _ttlIndex int = 1
constant _ttlLen (line 51) | _ttlLen int = 4
constant _spanIndex (line 52) | _spanIndex int = _ttlIndex + _ttlLen
constant _spanLength (line 53) | _spanLength int = 25
constant _serviceLenIndex (line 54) | _serviceLenIndex int = _spanIndex + _spanLength
constant _serviceNameIndex (line 55) | _serviceNameIndex int = _serviceLenIndex + 1
constant _resCodeOK (line 58) | _resCodeOK = 0x00
constant _resCodeIndex (line 59) | _resCodeIndex int = 1
constant _errCodeIndex (line 62) | _errCodeIndex int = 0
type lazyError (line 65) | type lazyError struct
method Code (line 76) | func (e lazyError) Code() SystemErrCode {
function newLazyError (line 69) | func newLazyError(f *Frame) lazyError {
type lazyCallRes (line 80) | type lazyCallRes struct
method OK (line 140) | func (cr lazyCallRes) OK() bool {
method ArgScheme (line 145) | func (cr lazyCallRes) ArgScheme() []byte {
method Arg2IsFragmented (line 150) | func (cr lazyCallRes) Arg2IsFragmented() bool {
method Arg2 (line 155) | func (cr lazyCallRes) Arg2() []byte {
function newLazyCallRes (line 88) | func newLazyCallRes(f *Frame) (lazyCallRes, error) {
type lazyCallReq (line 159) | type lazyCallReq struct
method Caller (line 244) | func (f *lazyCallReq) Caller() []byte {
method Service (line 249) | func (f *lazyCallReq) Service() []byte {
method Method (line 255) | func (f *lazyCallReq) Method() []byte {
method RoutingDelegate (line 260) | func (f *lazyCallReq) RoutingDelegate() []byte {
method RoutingKey (line 265) | func (f *lazyCallReq) RoutingKey() []byte {
method TTL (line 270) | func (f *lazyCallReq) TTL() time.Duration {
method SetTTL (line 276) | func (f *lazyCallReq) SetTTL(d time.Duration) {
method Span (line 282) | func (f *lazyCallReq) Span() Span {
method HasMoreFragments (line 287) | func (f *lazyCallReq) HasMoreFragments() bool {
method Arg2EndOffset (line 294) | func (f *lazyCallReq) Arg2EndOffset() (_ int, hasMore bool) {
method Arg2StartOffset (line 300) | func (f *lazyCallReq) Arg2StartOffset() int {
method arg2 (line 304) | func (f *lazyCallReq) arg2() []byte {
method arg3 (line 308) | func (f *lazyCallReq) arg3() []byte {
method Arg2Iterator (line 314) | func (f *lazyCallReq) Arg2Iterator() (arg2.KeyValIterator, error) {
method Arg2Append (line 321) | func (f *lazyCallReq) Arg2Append(key, val []byte) {
function newLazyCallReq (line 177) | func newLazyCallReq(f *Frame) (*lazyCallReq, error) {
function finishesCall (line 327) | func finishesCall(f *Frame) bool {
function isCallResOK (line 340) | func isCallResOK(f *Frame) bool {
function hasMoreFragments (line 345) | func hasMoreFragments(f *Frame) bool {
FILE: relay_messages_benchmark_test.go
function BenchmarkCallReqFrame (line 29) | func BenchmarkCallReqFrame(b *testing.B) {
FILE: relay_messages_test.go
type testCallReq (line 41) | type testCallReq
method req (line 77) | func (cr testCallReq) req(tb testing.TB) lazyCallReq {
method reqWithParams (line 81) | func (cr testCallReq) reqWithParams(tb testing.TB, p testCallReqParams...
method frameWithParams (line 87) | func (cr testCallReq) frameWithParams(t testing.TB, p testCallReqParam...
constant reqHasHeaders (line 44) | reqHasHeaders testCallReq = (1 << iota)
constant reqHasCaller (line 45) | reqHasCaller
constant reqHasDelegate (line 46) | reqHasDelegate
constant reqHasRoutingKey (line 47) | reqHasRoutingKey
constant reqHasChecksum (line 48) | reqHasChecksum
constant reqTotalCombinations (line 49) | reqTotalCombinations
constant reqHasAll (line 50) | reqHasAll testCallReq = reqTotalCombinations - 1
constant exampleService (line 61) | exampleService = "fooservice"
constant exampleArg3Data (line 62) | exampleArg3Data = "some arg3 data"
type testCallReqParams (line 65) | type testCallReqParams struct
function withLazyCallReqCombinations (line 158) | func withLazyCallReqCombinations(f func(cr testCallReq)) {
type testCallRes (line 164) | type testCallRes
method res (line 192) | func (cr testCallRes) res(tb testing.TB) lazyCallRes {
type testCallResParams (line 166) | type testCallResParams struct
constant resIsContinued (line 182) | resIsContinued testCallRes = (1 << iota)
constant resIsOK (line 183) | resIsOK
constant resHasHeaders (line 184) | resHasHeaders
constant resHasChecksum (line 185) | resHasChecksum
constant resIsThrift (line 186) | resIsThrift
constant resHasArg2 (line 187) | resHasArg2
constant resHasFragmentedArg2 (line 188) | resHasFragmentedArg2
constant resTotalCombinations (line 189) | resTotalCombinations
function withLazyCallResCombinations (line 227) | func withLazyCallResCombinations(t *testing.T, f func(t *testing.T, cr t...
function newCallResFrame (line 235) | func newCallResFrame(tb testing.TB, p testCallResParams) *Frame {
method fakeErrFrame (line 305) | func (ec SystemErrCode) fakeErrFrame() lazyError {
function withLazyErrorCombinations (line 325) | func withLazyErrorCombinations(f func(ec SystemErrCode)) {
function addRandomHeaders (line 342) | func addRandomHeaders(headers map[string]string) {
function writeHeaders (line 348) | func writeHeaders(w *typed.WriteBuffer, headers map[string]string) {
function assertWrappingPanics (line 356) | func assertWrappingPanics(t testing.TB, f *Frame, wrap func(f *Frame)) {
function TestLazyCallReqRejectsOtherFrames (line 362) | func TestLazyCallReqRejectsOtherFrames(t *testing.T) {
function TestLazyCallReqService (line 370) | func TestLazyCallReqService(t *testing.T) {
function TestLazyCallReqCaller (line 377) | func TestLazyCallReqCaller(t *testing.T) {
function TestLazyCallReqRoutingDelegate (line 388) | func TestLazyCallReqRoutingDelegate(t *testing.T) {
function TestLazyCallReqRoutingKey (line 399) | func TestLazyCallReqRoutingKey(t *testing.T) {
function TestLazyCallReqMethod (line 410) | func TestLazyCallReqMethod(t *testing.T) {
function TestLazyCallReqTTL (line 417) | func TestLazyCallReqTTL(t *testing.T) {
function TestLazyCallReqSetTTL (line 424) | func TestLazyCallReqSetTTL(t *testing.T) {
function TestLazyCallArg2Offset (line 432) | func TestLazyCallArg2Offset(t *testing.T) {
function TestLazyCallReqSetTChanThriftArg2 (line 520) | func TestLazyCallReqSetTChanThriftArg2(t *testing.T) {
function TestLazyCallResRejectsOtherFrames (line 638) | func TestLazyCallResRejectsOtherFrames(t *testing.T) {
function TestLazyCallRes (line 646) | func TestLazyCallRes(t *testing.T) {
function TestNewLazyCallResCorruptedFrame (line 691) | func TestNewLazyCallResCorruptedFrame(t *testing.T) {
function TestLazyErrorRejectsOtherFrames (line 700) | func TestLazyErrorRejectsOtherFrames(t *testing.T) {
function TestLazyErrorCodes (line 708) | func TestLazyErrorCodes(t *testing.T) {
function uint16KeyValToMap (line 716) | func uint16KeyValToMap(tb testing.TB, buffer []byte) map[string]string {
function TestLazyCallReqContents (line 731) | func TestLazyCallReqContents(t *testing.T) {
function TestLazyCallReqLargeService (line 752) | func TestLazyCallReqLargeService(t *testing.T) {
FILE: relay_test.go
type relayTest (line 55) | type relayTest struct
function serviceNameOpts (line 59) | func serviceNameOpts(s string) *testutils.ChannelOpts {
function withRelayedEcho (line 63) | func withRelayedEcho(t testing.TB, f func(relay, server, client *Channel...
function TestRelay (line 75) | func TestRelay(t *testing.T) {
function TestRelaySetHost (line 103) | func TestRelaySetHost(t *testing.T) {
function TestRelayHandlesClosedPeers (line 118) | func TestRelayHandlesClosedPeers(t *testing.T) {
function TestRelayConnectionCloseDrainsRelayItems (line 143) | func TestRelayConnectionCloseDrainsRelayItems(t *testing.T) {
function TestRelayIDClash (line 170) | func TestRelayIDClash(t *testing.T) {
function TestRelayErrorsOnGetPeer (line 202) | func TestRelayErrorsOnGetPeer(t *testing.T) {
function TestErrorFrameEndsRelay (line 258) | func TestErrorFrameEndsRelay(t *testing.T) {
function TestRaceCloseWithNewCall (line 287) | func TestRaceCloseWithNewCall(t *testing.T) {
function TestTimeoutCallsThenClose (line 337) | func TestTimeoutCallsThenClose(t *testing.T) {
function TestLargeTimeoutsAreClamped (line 373) | func TestLargeTimeoutsAreClamped(t *testing.T) {
function TestRelayConcurrentCalls (line 425) | func TestRelayConcurrentCalls(t *testing.T) {
function TestRelayOutgoingConnectionsEphemeral (line 455) | func TestRelayOutgoingConnectionsEphemeral(t *testing.T) {
function TestRelayHandleLocalCall (line 475) | func TestRelayHandleLocalCall(t *testing.T) {
function TestRelayHandleLargeLocalCall (line 507) | func TestRelayHandleLargeLocalCall(t *testing.T) {
function TestRelayMakeOutgoingCall (line 535) | func TestRelayMakeOutgoingCall(t *testing.T) {
function TestRelayInboundConnContext (line 557) | func TestRelayInboundConnContext(t *testing.T) {
function TestRelayContextInheritsFromOutboundConnection (line 581) | func TestRelayContextInheritsFromOutboundConnection(t *testing.T) {
function TestRelayConnection (line 609) | func TestRelayConnection(t *testing.T) {
function TestRelayConnectionClosed (line 700) | func TestRelayConnectionClosed(t *testing.T) {
function TestRelayUsesRootPeers (line 727) | func TestRelayUsesRootPeers(t *testing.T) {
function TestRelayRejectsDuringClose (line 742) | func TestRelayRejectsDuringClose(t *testing.T) {
function TestRelayRateLimitDrop (line 785) | func TestRelayRateLimitDrop(t *testing.T) {
function TestRelayStalledConnection (line 826) | func TestRelayStalledConnection(t *testing.T) {
function TestRelayStalledClientConnection (line 914) | func TestRelayStalledClientConnection(t *testing.T) {
function TestRelayCorruptedCallResFrame (line 993) | func TestRelayCorruptedCallResFrame(t *testing.T) {
function TestRelayThroughSeparateRelay (line 1050) | func TestRelayThroughSeparateRelay(t *testing.T) {
function TestRelayConcurrentNewConnectionAttempts (line 1083) | func TestRelayConcurrentNewConnectionAttempts(t *testing.T) {
function TestRelayRaceTimerCausesStuckConnectionOnClose (line 1130) | func TestRelayRaceTimerCausesStuckConnectionOnClose(t *testing.T) {
function TestRelayRaceCompletionAndTimeout (line 1180) | func TestRelayRaceCompletionAndTimeout(t *testing.T) {
function TestRelayArg2OffsetIntegration (line 1220) | func TestRelayArg2OffsetIntegration(t *testing.T) {
function TestRelayThriftArg2KeyValueIteration (line 1356) | func TestRelayThriftArg2KeyValueIteration(t *testing.T) {
function TestRelayConnectionTimeout (line 1407) | func TestRelayConnectionTimeout(t *testing.T) {
function TestRelayTransferredBytes (line 1474) | func TestRelayTransferredBytes(t *testing.T) {
function TestRelayCallResponse (line 1549) | func TestRelayCallResponse(t *testing.T) {
function TestRelayAppendArg2SentBytes (line 1604) | func TestRelayAppendArg2SentBytes(t *testing.T) {
function inspectFrames (line 1686) | func inspectFrames(rh *relaytest.StubRelayHost) chan relay.CallFrame {
type relayModifier (line 1694) | type relayModifier interface
type noopRelayModifer (line 1699) | type noopRelayModifer struct
method frameFn (line 1701) | func (nrm *noopRelayModifer) frameFn(_ relay.CallFrame, _ *relay.Conn) {}
method modifyArg2 (line 1703) | func (nrm *noopRelayModifer) modifyArg2(m map[string]string) map[strin...
type keyVal (line 1705) | type keyVal struct
type arg2KeyValRelayModifier (line 1709) | type arg2KeyValRelayModifier struct
method frameFn (line 1743) | func (rm *arg2KeyValRelayModifier) frameFn(cf relay.CallFrame, _ *rela...
method modifyArg2 (line 1749) | func (rm *arg2KeyValRelayModifier) modifyArg2(m map[string]string) map...
function addFixedKeyVal (line 1713) | func addFixedKeyVal(kvPairs []keyVal) *arg2KeyValRelayModifier {
function fillFrameWithArg2 (line 1719) | func fillFrameWithArg2(t *testing.T, checksumType ChecksumType, arg1 str...
function TestRelayModifyArg2 (line 1759) | func TestRelayModifyArg2(t *testing.T) {
function TestRelayModifyArg2ShouldFail (line 2005) | func TestRelayModifyArg2ShouldFail(t *testing.T) {
type echoVerifyHandler (line 2079) | type echoVerifyHandler struct
method Handle (line 2088) | func (h echoVerifyHandler) Handle(ctx context.Context, args *raw.Args)...
method OnError (line 2100) | func (h echoVerifyHandler) OnError(ctx context.Context, err error) {
function encodeThriftHeaders (line 2104) | func encodeThriftHeaders(t testing.TB, m map[string]string) []byte {
function decodeThriftHeaders (line 2110) | func decodeThriftHeaders(t testing.TB, bs []byte) map[string]string {
function copyHeaders (line 2124) | func copyHeaders(m map[string]string) map[string]string {
FILE: relay_timer_pool.go
type relayTimerTrigger (line 29) | type relayTimerTrigger
type relayTimerPool (line 31) | type relayTimerPool struct
method Get (line 67) | func (tp *relayTimerPool) Get() *relayTimer {
method Put (line 89) | func (tp *relayTimerPool) Put(rt *relayTimer) {
type relayTimer (line 37) | type relayTimer struct
method OnTimer (line 51) | func (rt *relayTimer) OnTimer() {
method Start (line 99) | func (rt *relayTimer) Start(d time.Duration, items *relayItems, id uin...
method markTimerInactive (line 116) | func (rt *relayTimer) markTimerInactive() {
method Stop (line 127) | func (rt *relayTimer) Stop() bool {
method Release (line 145) | func (rt *relayTimer) Release() {
method verifyNotReleased (line 154) | func (rt *relayTimer) verifyNotReleased() {
function newRelayTimerPool (line 58) | func newRelayTimerPool(trigger relayTimerTrigger, verify bool) *relayTim...
FILE: reqres.go
type errReqResWriterStateMismatch (line 29) | type errReqResWriterStateMismatch struct
method Error (line 34) | func (e errReqResWriterStateMismatch) Error() string {
type errReqResReaderStateMismatch (line 39) | type errReqResReaderStateMismatch struct
method Error (line 44) | func (e errReqResReaderStateMismatch) Error() string {
type reqResWriterState (line 50) | type reqResWriterState
constant reqResWriterPreArg1 (line 53) | reqResWriterPreArg1 reqResWriterState = iota
constant reqResWriterPreArg2 (line 54) | reqResWriterPreArg2
constant reqResWriterPreArg3 (line 55) | reqResWriterPreArg3
constant reqResWriterComplete (line 56) | reqResWriterComplete
type messageForFragment (line 63) | type messageForFragment
type reqResWriter (line 68) | type reqResWriter struct
method argWriter (line 80) | func (w *reqResWriter) argWriter(last bool, inState reqResWriterState,...
method arg1Writer (line 98) | func (w *reqResWriter) arg1Writer() (ArgWriter, error) {
method arg2Writer (line 102) | func (w *reqResWriter) arg2Writer() (ArgWriter, error) {
method arg3Writer (line 106) | func (w *reqResWriter) arg3Writer() (ArgWriter, error) {
method newFragment (line 111) | func (w *reqResWriter) newFragment(initial bool, checksum Checksum) (*...
method flushFragment (line 139) | func (w *reqResWriter) flushFragment(fragment *writableFragment) error {
method failed (line 161) | func (w *reqResWriter) failed(err error) error {
type reqResReaderState (line 173) | type reqResReaderState
constant reqResReaderPreArg1 (line 176) | reqResReaderPreArg1 reqResReaderState = iota
constant reqResReaderPreArg2 (line 177) | reqResReaderPreArg2
constant reqResReaderPreArg3 (line 178) | reqResReaderPreArg3
constant reqResReaderComplete (line 179) | reqResReaderComplete
type reqResReader (line 183) | type reqResReader struct
method arg1Reader (line 195) | func (r *reqResReader) arg1Reader() (ArgReader, error) {
method arg2Reader (line 200) | func (r *reqResReader) arg2Reader() (ArgReader, error) {
method arg3Reader (line 205) | func (r *reqResReader) arg3Reader() (ArgReader, error) {
method argReader (line 211) | func (r *reqResReader) argReader(last bool, inState reqResReaderState,...
method recvNextFragment (line 226) | func (r *reqResReader) recvNextFragment(initial bool) (*readableFragme...
method releasePreviousFragment (line 260) | func (r *reqResReader) releasePreviousFragment() {
method failed (line 269) | func (r *reqResReader) failed(err error) error {
function parseInboundFragment (line 281) | func parseInboundFragment(framePool FramePool, frame *Frame, message mes...
FILE: reqresreaderstate_string.go
constant _reqResReaderState_name (line 7) | _reqResReaderState_name = "reqResReaderPreArg1reqResReaderPreArg2reqResR...
method String (line 11) | func (i reqResReaderState) String() string {
FILE: reqreswriterstate_string.go
constant _reqResWriterState_name (line 7) | _reqResWriterState_name = "reqResWriterPreArg1reqResWriterPreArg2reqResW...
method String (line 11) | func (i reqResWriterState) String() string {
FILE: retry.go
type RetryOn (line 32) | type RetryOn
method CanRetry (line 89) | func (r RetryOn) CanRetry(err error) bool {
constant RetryDefault (line 38) | RetryDefault RetryOn = iota
constant RetryConnectionError (line 41) | RetryConnectionError
constant RetryNever (line 44) | RetryNever
constant RetryNonIdempotent (line 49) | RetryNonIdempotent
constant RetryUnexpected (line 52) | RetryUnexpected
constant RetryIdempotent (line 56) | RetryIdempotent
type RequestState (line 60) | type RequestState struct
method HasRetries (line 159) | func (rs *RequestState) HasRetries(err error) bool {
method SinceStart (line 169) | func (rs *RequestState) SinceStart(now time.Time, fallback time.Durati...
method PrevSelectedPeers (line 177) | func (rs *RequestState) PrevSelectedPeers() map[string]struct{} {
method AddSelectedPeer (line 185) | func (rs *RequestState) AddSelectedPeer(hostPort string) {
method RetryCount (line 203) | func (rs *RequestState) RetryCount() int {
type RetriableFunc (line 71) | type RetriableFunc
function isNetError (line 73) | func isNetError(err error) bool {
function getErrCode (line 80) | func getErrCode(err error) SystemErrCode {
type RetryOptions (line 120) | type RetryOptions struct
function getRetryOptions (line 141) | func getRetryOptions(ctx context.Context) *RetryOptions {
method RunWithRetry (line 212) | func (ch *Channel) RunWithRetry(runCtx context.Context, f RetriableFunc)...
method getRequestState (line 251) | func (ch *Channel) getRequestState(retryOpts *RetryOptions) *RequestState {
function getHost (line 262) | func getHost(hostPort string) string {
FILE: retry_request_test.go
function TestRequestStateRetry (line 36) | func TestRequestStateRetry(t *testing.T) {
FILE: retry_test.go
function createFuncToRetry (line 37) | func createFuncToRetry(t *testing.T, errors ...error) (RetriableFunc, *i...
type testErrors (line 51) | type testErrors struct
function getTestErrors (line 64) | func getTestErrors() testErrors {
function TestCanRetry (line 80) | func TestCanRetry(t *testing.T) {
function TestNoRetry (line 108) | func TestNoRetry(t *testing.T) {
function TestRetryTillMaxAttempts (line 125) | func TestRetryTillMaxAttempts(t *testing.T) {
function TestRetrySubContextNoTimeoutPerAttempt (line 167) | func TestRetrySubContextNoTimeoutPerAttempt(t *testing.T) {
function TestRetrySubContextTimeoutPerAttempt (line 184) | func TestRetrySubContextTimeoutPerAttempt(t *testing.T) {
function TestRetryNetConnect (line 212) | func TestRetryNetConnect(t *testing.T) {
function TestRequestStateSince (line 244) | func TestRequestStateSince(t *testing.T) {
FILE: retryon_string.go
constant _RetryOn_name (line 7) | _RetryOn_name = "RetryDefaultRetryConnectionErrorRetryNeverRetryNonIdemp...
method String (line 11) | func (i RetryOn) String() string {
FILE: root_peer_list.go
type RootPeerList (line 27) | type RootPeerList struct
method newChild (line 45) | func (l *RootPeerList) newChild() *PeerList {
method Add (line 51) | func (l *RootPeerList) Add(hostPort string) *Peer {
method GetOrAdd (line 76) | func (l *RootPeerList) GetOrAdd(hostPort string) *Peer {
method Get (line 86) | func (l *RootPeerList) Get(hostPort string) (*Peer, bool) {
method onClosedConnRemoved (line 93) | func (l *RootPeerList) onClosedConnRemoved(peer *Peer) {
method Copy (line 113) | func (l *RootPeerList) Copy() map[string]*Peer {
function newRootPeerList (line 35) | func newRootPeerList(ch Connectable, onPeerStatusChanged func(*Peer)) *R...
FILE: scripts/vbumper/main.go
function main (line 46) | func main() {
function updateVersion (line 65) | func updateVersion(prevVersion string) error {
function insertNewVersion (line 75) | func insertNewVersion(contents, prevVersion, newVersion string) string {
function updateChangelog (line 83) | func updateChangelog() (oldVersion string, _ error) {
function insertNewChangelog (l
Condensed preview — 401 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (2,231K chars).
[
{
"path": ".github/workflows/tests.yaml",
"chars": 1503,
"preview": "name: Tests\n\non:\n push:\n branches: ['*']\n tags: ['v*']\n pull_request:\n branches: ['**']\n\njobs:\n test:\n ru"
},
{
"path": ".gitignore",
"chars": 188,
"preview": "build\nGodeps/_workspace\nvendor/\nthrift-gen-release/\n\n# Lint output\nlint.log\n\n# Cover profiles\n*.out\n\n# Editor and OS det"
},
{
"path": "CHANGELOG.md",
"chars": 16262,
"preview": "Changelog\n=========\n\n## [1.34.6] - 2025-01-07\n### Fixed\n\n * Fix compile issue on FreeBSD 14 (#925)\n\n## [1.34.5] - 2024-1"
},
{
"path": "CODE_OF_CONDUCT.md",
"chars": 3224,
"preview": "# Contributor Covenant Code of Conduct\n\n## Our Pledge\n\nIn the interest of fostering an open and welcoming environment, w"
},
{
"path": "CONTRIBUTING.md",
"chars": 1403,
"preview": "Contributing\n============\n\nWe'd love your help making tchannel-go great!\n\n## Getting Started\n\nTChannel uses [glide](http"
},
{
"path": "LICENSE.md",
"chars": 1067,
"preview": "Copyright (c) 2015 Uber Technologies, Inc.\n\nPermission is hereby granted, free of charge, to any person obtaining a copy"
},
{
"path": "Makefile",
"chars": 5342,
"preview": "PATH := $(GOPATH)/bin:$(PATH)\nEXAMPLES=./examples/bench/server ./examples/bench/client ./examples/ping ./examples/thrift"
},
{
"path": "README.md",
"chars": 2950,
"preview": "# TChannel [![GoDoc][doc-img]][doc] [![Build Status][ci-img]][ci] [![Coverage Status][cov-img]][cov]\n\n[TChannel][tchan-s"
},
{
"path": "RELEASE.md",
"chars": 1292,
"preview": "Release process\n===============\n\nThis document outlines how to create a release of tchannel-go\n\n1. Set up some environm"
},
{
"path": "all_channels.go",
"chars": 2513,
"preview": "// Copyright (c) 2015 Uber Technologies, Inc.\n\n// Permission is hereby granted, free of charge, to any person obtaining "
},
{
"path": "all_channels_test.go",
"chars": 2390,
"preview": "// Copyright (c) 2015 Uber Technologies, Inc.\n\n// Permission is hereby granted, free of charge, to any person obtaining "
},
{
"path": "arguments.go",
"chars": 4408,
"preview": "// Copyright (c) 2015 Uber Technologies, Inc.\n\n// Permission is hereby granted, free of charge, to any person obtaining "
},
{
"path": "arguments_test.go",
"chars": 2994,
"preview": "// Copyright (c) 2015 Uber Technologies, Inc.\n\n// Permission is hereby granted, free of charge, to any person obtaining "
},
{
"path": "benchmark/benchclient/main.go",
"chars": 3296,
"preview": "// Copyright (c) 2015 Uber Technologies, Inc.\n\n// Permission is hereby granted, free of charge, to any person obtaining "
},
{
"path": "benchmark/benchserver/main.go",
"chars": 2240,
"preview": "// Copyright (c) 2015 Uber Technologies, Inc.\n\n// Permission is hereby granted, free of charge, to any person obtaining "
},
{
"path": "benchmark/build_manager.go",
"chars": 2126,
"preview": "// Copyright (c) 2015 Uber Technologies, Inc.\n\n// Permission is hereby granted, free of charge, to any person obtaining "
},
{
"path": "benchmark/client_server_bench_test.go",
"chars": 2609,
"preview": "// Copyright (c) 2015 Uber Technologies, Inc.\n\n// Permission is hereby granted, free of charge, to any person obtaining "
},
{
"path": "benchmark/external_client.go",
"chars": 2891,
"preview": "// Copyright (c) 2015 Uber Technologies, Inc.\n\n// Permission is hereby granted, free of charge, to any person obtaining "
},
{
"path": "benchmark/external_common.go",
"chars": 2631,
"preview": "// Copyright (c) 2015 Uber Technologies, Inc.\n\n// Permission is hereby granted, free of charge, to any person obtaining "
},
{
"path": "benchmark/external_server.go",
"chars": 2278,
"preview": "// Copyright (c) 2015 Uber Technologies, Inc.\n\n// Permission is hereby granted, free of charge, to any person obtaining "
},
{
"path": "benchmark/frame_templates.go",
"chars": 3903,
"preview": "// Copyright (c) 2015 Uber Technologies, Inc.\n\n// Permission is hereby granted, free of charge, to any person obtaining "
},
{
"path": "benchmark/interfaces.go",
"chars": 2707,
"preview": "// Copyright (c) 2015 Uber Technologies, Inc.\n\n// Permission is hereby granted, free of charge, to any person obtaining "
},
{
"path": "benchmark/internal_client.go",
"chars": 4906,
"preview": "// Copyright (c) 2015 Uber Technologies, Inc.\n\n// Permission is hereby granted, free of charge, to any person obtaining "
},
{
"path": "benchmark/internal_multi_client.go",
"chars": 2952,
"preview": "// Copyright (c) 2015 Uber Technologies, Inc.\n\n// Permission is hereby granted, free of charge, to any person obtaining "
},
{
"path": "benchmark/internal_server.go",
"chars": 3805,
"preview": "// Copyright (c) 2015 Uber Technologies, Inc.\n\n// Permission is hereby granted, free of charge, to any person obtaining "
},
{
"path": "benchmark/internal_tcp_client.go",
"chars": 4164,
"preview": "// Copyright (c) 2015 Uber Technologies, Inc.\n\n// Permission is hereby granted, free of charge, to any person obtaining "
},
{
"path": "benchmark/internal_tcp_server.go",
"chars": 3025,
"preview": "// Copyright (c) 2015 Uber Technologies, Inc.\n\n// Permission is hereby granted, free of charge, to any person obtaining "
},
{
"path": "benchmark/matrix_test.go",
"chars": 4665,
"preview": "// Copyright (c) 2015 Uber Technologies, Inc.\n\n// Permission is hereby granted, free of charge, to any person obtaining "
},
{
"path": "benchmark/options.go",
"chars": 3751,
"preview": "// Copyright (c) 2015 Uber Technologies, Inc.\n\n// Permission is hereby granted, free of charge, to any person obtaining "
},
{
"path": "benchmark/real_relay.go",
"chars": 2510,
"preview": "// Copyright (c) 2015 Uber Technologies, Inc.\n\n// Permission is hereby granted, free of charge, to any person obtaining "
},
{
"path": "benchmark/req_bytes.go",
"chars": 1538,
"preview": "// Copyright (c) 2015 Uber Technologies, Inc.\n\n// Permission is hereby granted, free of charge, to any person obtaining "
},
{
"path": "benchmark/tcp_bench_test.go",
"chars": 3016,
"preview": "// Copyright (c) 2015 Uber Technologies, Inc.\n\n// Permission is hereby granted, free of charge, to any person obtaining "
},
{
"path": "benchmark/tcp_frame_relay.go",
"chars": 2308,
"preview": "// Copyright (c) 2015 Uber Technologies, Inc.\n\n// Permission is hereby granted, free of charge, to any person obtaining "
},
{
"path": "benchmark/tcp_raw_relay.go",
"chars": 2624,
"preview": "// Copyright (c) 2015 Uber Technologies, Inc.\n\n// Permission is hereby granted, free of charge, to any person obtaining "
},
{
"path": "calloptions.go",
"chars": 3237,
"preview": "// Copyright (c) 2015 Uber Technologies, Inc.\n\n// Permission is hereby granted, free of charge, to any person obtaining "
},
{
"path": "calloptions_test.go",
"chars": 2453,
"preview": "// Copyright (c) 2015 Uber Technologies, Inc.\n\n// Permission is hereby granted, free of charge, to any person obtaining "
},
{
"path": "channel.go",
"chars": 28417,
"preview": "// Copyright (c) 2015 Uber Technologies, Inc.\n\n// Permission is hereby granted, free of charge, to any person obtaining "
},
{
"path": "channel_test.go",
"chars": 7018,
"preview": "// Copyright (c) 2015 Uber Technologies, Inc.\n\n// Permission is hereby granted, free of charge, to any person obtaining "
},
{
"path": "channel_utils_test.go",
"chars": 1534,
"preview": "// Copyright (c) 2015 Uber Technologies, Inc.\n\n// Permission is hereby granted, free of charge, to any person obtaining "
},
{
"path": "channelstate_string.go",
"chars": 497,
"preview": "// generated by stringer -type=ChannelState; DO NOT EDIT\n\npackage tchannel\n\nimport \"fmt\"\n\nconst _ChannelState_name = \"Ch"
},
{
"path": "checked_frame_pool.go",
"chars": 2322,
"preview": "package tchannel\n\nimport (\n\t\"fmt\"\n\t\"runtime\"\n\t\"sync\"\n)\n\n// CheckedFramePoolForTest tracks gets and releases of frames, v"
},
{
"path": "checked_frame_pool_test.go",
"chars": 2102,
"preview": "package tchannel\n\nimport (\n\t\"strings\"\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n\t\"github.com/uber/tchannel-go/te"
},
{
"path": "checksum.go",
"chars": 5522,
"preview": "// Copyright (c) 2015 Uber Technologies, Inc.\n\n// Permission is hereby granted, free of charge, to any person obtaining "
},
{
"path": "close_test.go",
"chars": 18167,
"preview": "// Copyright (c) 2015 Uber Technologies, Inc.\n\n// Permission is hereby granted, free of charge, to any person obtaining "
},
{
"path": "codecov.yml",
"chars": 219,
"preview": "coverage:\n range: 75..100\n round: down\n precision: 2\n\n status:\n project:\n default:\n enabled: yes\n "
},
{
"path": "conn_leak_test.go",
"chars": 3649,
"preview": "// Copyright (c) 2017 Uber Technologies, Inc.\n\n// Permission is hereby granted, free of charge, to any person obtaining "
},
{
"path": "connection.go",
"chars": 30532,
"preview": "// Copyright (c) 2015 Uber Technologies, Inc.\n\n// Permission is hereby granted, free of charge, to any person obtaining "
},
{
"path": "connection_bench_test.go",
"chars": 5257,
"preview": "// Copyright (c) 2015 Uber Technologies, Inc.\n\n// Permission is hereby granted, free of charge, to any person obtaining "
},
{
"path": "connection_direction.go",
"chars": 1443,
"preview": "// Copyright (c) 2015 Uber Technologies, Inc.\n\n// Permission is hereby granted, free of charge, to any person obtaining "
},
{
"path": "connection_internal_test.go",
"chars": 4329,
"preview": "// Copyright (c) 2020 Uber Technologies, Inc.\n\n// Permission is hereby granted, free of charge, to any person obtaining "
},
{
"path": "connection_test.go",
"chars": 55252,
"preview": "// Copyright (c) 2015 Uber Technologies, Inc.\n\n// Permission is hereby granted, free of charge, to any person obtaining "
},
{
"path": "connectionstate_string.go",
"chars": 526,
"preview": "// Code generated by \"stringer -type=connectionState\"; DO NOT EDIT\n\npackage tchannel\n\nimport \"fmt\"\n\nconst _connectionSta"
},
{
"path": "context.go",
"chars": 4170,
"preview": "// Copyright (c) 2015 Uber Technologies, Inc.\n\n// Permission is hereby granted, free of charge, to any person obtaining "
},
{
"path": "context_builder.go",
"chars": 8425,
"preview": "// Copyright (c) 2015 Uber Technologies, Inc.\n\n// Permission is hereby granted, free of charge, to any person obtaining "
},
{
"path": "context_header.go",
"chars": 4137,
"preview": "// Copyright (c) 2015 Uber Technologies, Inc.\n\n// Permission is hereby granted, free of charge, to any person obtaining "
},
{
"path": "context_internal_test.go",
"chars": 2885,
"preview": "// Copyright (c) 2015 Uber Technologies, Inc.\n\n// Permission is hereby granted, free of charge, to any person obtaining "
},
{
"path": "context_test.go",
"chars": 10194,
"preview": "// Copyright (c) 2015 Uber Technologies, Inc.\n// Permission is hereby granted, free of charge, to any person obtaining a"
},
{
"path": "deps_test.go",
"chars": 1674,
"preview": "// Copyright (c) 2017 Uber Technologies, Inc.\n\n// Permission is hereby granted, free of charge, to any person obtaining "
},
{
"path": "dial_16.go",
"chars": 1377,
"preview": "// Copyright (c) 2015 Uber Technologies, Inc.\n\n// Permission is hereby granted, free of charge, to any person obtaining "
},
{
"path": "dial_17.go",
"chars": 1342,
"preview": "// Copyright (c) 2015 Uber Technologies, Inc.\n\n// Permission is hereby granted, free of charge, to any person obtaining "
},
{
"path": "dial_17_test.go",
"chars": 2312,
"preview": "// Copyright (c) 2015 Uber Technologies, Inc.\n\n// Permission is hereby granted, free of charge, to any person obtaining "
},
{
"path": "doc.go",
"chars": 1319,
"preview": "// Copyright (c) 2015 Uber Technologies, Inc.\n\n// Permission is hereby granted, free of charge, to any person obtaining "
},
{
"path": "errors.go",
"chars": 7979,
"preview": "// Copyright (c) 2015 Uber Technologies, Inc.\n\n// Permission is hereby granted, free of charge, to any person obtaining "
},
{
"path": "errors_test.go",
"chars": 2689,
"preview": "// Copyright (c) 2015 Uber Technologies, Inc.\n\n// Permission is hereby granted, free of charge, to any person obtaining "
},
{
"path": "examples/bench/client/client.go",
"chars": 3419,
"preview": "// Copyright (c) 2015 Uber Technologies, Inc.\n\n// Permission is hereby granted, free of charge, to any person obtaining "
},
{
"path": "examples/bench/runner.go",
"chars": 4166,
"preview": "// Copyright (c) 2015 Uber Technologies, Inc.\n\n// Permission is hereby granted, free of charge, to any person obtaining "
},
{
"path": "examples/bench/server/server.go",
"chars": 4039,
"preview": "// Copyright (c) 2015 Uber Technologies, Inc.\n\n// Permission is hereby granted, free of charge, to any person obtaining "
},
{
"path": "examples/hyperbahn/echo-server/main.go",
"chars": 2993,
"preview": "// Copyright (c) 2015 Uber Technologies, Inc.\n\n// Permission is hereby granted, free of charge, to any person obtaining "
},
{
"path": "examples/hypercat/main.go",
"chars": 4483,
"preview": "// Copyright (c) 2015 Uber Technologies, Inc.\n\n// Permission is hereby granted, free of charge, to any person obtaining "
},
{
"path": "examples/keyvalue/README.md",
"chars": 266,
"preview": "# Key-Value Store\n\n```bash\n./build/examples/keyvalue/server\n./build/examples/keyvalue/client\n```\n\nThis example exposes a"
},
{
"path": "examples/keyvalue/client/client.go",
"chars": 4312,
"preview": "// Copyright (c) 2015 Uber Technologies, Inc.\n\n// Permission is hereby granted, free of charge, to any person obtaining "
},
{
"path": "examples/keyvalue/gen-go/keyvalue/admin.go",
"chars": 8717,
"preview": "// Autogenerated by Thrift Compiler (1.0.0-dev)\n// DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING\n\npac"
},
{
"path": "examples/keyvalue/gen-go/keyvalue/baseservice.go",
"chars": 10278,
"preview": "// Autogenerated by Thrift Compiler (1.0.0-dev)\n// DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING\n\npac"
},
{
"path": "examples/keyvalue/gen-go/keyvalue/constants.go",
"chars": 392,
"preview": "// Autogenerated by Thrift Compiler (1.0.0-dev)\n// DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING\n\npac"
},
{
"path": "examples/keyvalue/gen-go/keyvalue/keyvalue.go",
"chars": 22355,
"preview": "// Autogenerated by Thrift Compiler (1.0.0-dev)\n// DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING\n\npac"
},
{
"path": "examples/keyvalue/gen-go/keyvalue/tchan-keyvalue.go",
"chars": 9554,
"preview": "// @generated Code generated by thrift-gen. Do not modify.\n\n// Package keyvalue is generated code used to make or handle"
},
{
"path": "examples/keyvalue/gen-go/keyvalue/ttypes.go",
"chars": 5702,
"preview": "// Autogenerated by Thrift Compiler (1.0.0-dev)\n// DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING\n\npac"
},
{
"path": "examples/keyvalue/keyvalue.thrift",
"chars": 712,
"preview": "service baseService {\n string HealthCheck()\n}\n\nexception KeyNotFound {\n 1: string key\n}\n\nexception InvalidKey {}\n\nserv"
},
{
"path": "examples/keyvalue/server/server.go",
"chars": 4461,
"preview": "// Copyright (c) 2015 Uber Technologies, Inc.\n\n// Permission is hereby granted, free of charge, to any person obtaining "
},
{
"path": "examples/ping/README.md",
"chars": 492,
"preview": "# Ping-Pong\n\n```bash\n./build/examples/ping/pong\n```\n\nThis example creates a client and server channel. The server chann"
},
{
"path": "examples/ping/main.go",
"chars": 3836,
"preview": "// Copyright (c) 2015 Uber Technologies, Inc.\n\n// Permission is hereby granted, free of charge, to any person obtaining "
},
{
"path": "examples/test_server/server.go",
"chars": 2150,
"preview": "// Copyright (c) 2015 Uber Technologies, Inc.\n\n// Permission is hereby granted, free of charge, to any person obtaining "
},
{
"path": "examples/thrift/example.thrift",
"chars": 241,
"preview": "struct HealthCheckRes {\n 1: bool healthy,\n 2: string msg,\n}\n\nservice Base {\n void BaseCall()\n}\n\nservice First extends"
},
{
"path": "examples/thrift/gen-go/example/base.go",
"chars": 8279,
"preview": "// Autogenerated by Thrift Compiler (1.0.0-dev)\n// DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING\n\npac"
},
{
"path": "examples/thrift/gen-go/example/constants.go",
"chars": 391,
"preview": "// Autogenerated by Thrift Compiler (1.0.0-dev)\n// DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING\n\npac"
},
{
"path": "examples/thrift/gen-go/example/first.go",
"chars": 23020,
"preview": "// Autogenerated by Thrift Compiler (1.0.0-dev)\n// DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING\n\npac"
},
{
"path": "examples/thrift/gen-go/example/second.go",
"chars": 8212,
"preview": "// Autogenerated by Thrift Compiler (1.0.0-dev)\n// DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING\n\npac"
},
{
"path": "examples/thrift/gen-go/example/tchan-example.go",
"chars": 8694,
"preview": "// @generated Code generated by thrift-gen. Do not modify.\n\n// Package example is generated code used to make or handle "
},
{
"path": "examples/thrift/gen-go/example/ttypes.go",
"chars": 3897,
"preview": "// Autogenerated by Thrift Compiler (1.0.0-dev)\n// DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING\n\npac"
},
{
"path": "examples/thrift/main.go",
"chars": 4934,
"preview": "// Copyright (c) 2015 Uber Technologies, Inc.\n\n// Permission is hereby granted, free of charge, to any person obtaining "
},
{
"path": "fragmentation_test.go",
"chars": 15055,
"preview": "// Copyright (c) 2015 Uber Technologies, Inc.\n\n// Permission is hereby granted, free of charge, to any person obtaining "
},
{
"path": "fragmenting_reader.go",
"chars": 9663,
"preview": "// Copyright (c) 2015 Uber Technologies, Inc.\n\n// Permission is hereby granted, free of charge, to any person obtaining "
},
{
"path": "fragmenting_writer.go",
"chars": 9266,
"preview": "// Copyright (c) 2015 Uber Technologies, Inc.\n\n// Permission is hereby granted, free of charge, to any person obtaining "
},
{
"path": "frame.go",
"chars": 6106,
"preview": "// Copyright (c) 2015 Uber Technologies, Inc.\n\n// Permission is hereby granted, free of charge, to any person obtaining "
},
{
"path": "frame_pool.go",
"chars": 2624,
"preview": "// Copyright (c) 2015 Uber Technologies, Inc.\n\n// Permission is hereby granted, free of charge, to any person obtaining "
},
{
"path": "frame_pool_b_test.go",
"chars": 2236,
"preview": "// Copyright (c) 2015 Uber Technologies, Inc.\n\n// Permission is hereby granted, free of charge, to any person obtaining "
},
{
"path": "frame_pool_test.go",
"chars": 5318,
"preview": "// Copyright (c) 2015 Uber Technologies, Inc.\n\n// Permission is hereby granted, free of charge, to any person obtaining "
},
{
"path": "frame_test.go",
"chars": 8831,
"preview": "// Copyright (c) 2015 Uber Technologies, Inc.\n\n// Permission is hereby granted, free of charge, to any person obtaining "
},
{
"path": "frame_utils_test.go",
"chars": 2484,
"preview": "// Copyright (c) 2015 Uber Technologies, Inc.\n\n// Permission is hereby granted, free of charge, to any person obtaining "
},
{
"path": "go.mod",
"chars": 1315,
"preview": "module github.com/uber/tchannel-go\n\ngo 1.21\n\nrequire (\n\tgithub.com/HdrHistogram/hdrhistogram-go v0.9.0 // indirect\n\tgith"
},
{
"path": "go.sum",
"chars": 6654,
"preview": "github.com/HdrHistogram/hdrhistogram-go v0.9.0 h1:dpujRju0R4M/QZzcnR1LH1qm+TVG3UzkWdp5tH1WMcg=\ngithub.com/HdrHistogram/h"
},
{
"path": "guide/Thrift_Hyperbahn.md",
"chars": 10256,
"preview": "# Set up a Go + Thrift + Hyperbahn Service\n\nThe code matching this guide is [here](../examples/keyvalue).\n\nThe TChannel+"
},
{
"path": "handlers.go",
"chars": 5521,
"preview": "// Copyright (c) 2015 Uber Technologies, Inc.\n\n// Permission is hereby granted, free of charge, to any person obtaining "
},
{
"path": "handlers_test.go",
"chars": 1771,
"preview": "// Copyright (c) 2015 Uber Technologies, Inc.\n\n// Permission is hereby granted, free of charge, to any person obtaining "
},
{
"path": "handlers_with_skip_test.go",
"chars": 3449,
"preview": "// Copyright (c) 2015 Uber Technologies, Inc.\n\n// Permission is hereby granted, free of charge, to any person obtaining "
},
{
"path": "health.go",
"chars": 4889,
"preview": "// Copyright (c) 2017 Uber Technologies, Inc.\n\n// Permission is hereby granted, free of charge, to any person obtaining "
},
{
"path": "health_ext_test.go",
"chars": 6971,
"preview": "// Copyright (c) 2017 Uber Technologies, Inc.\n\n// Permission is hereby granted, free of charge, to any person obtaining "
},
{
"path": "health_test.go",
"chars": 2671,
"preview": "// Copyright (c) 2017 Uber Technologies, Inc.\n\n// Permission is hereby granted, free of charge, to any person obtaining "
},
{
"path": "http/buf.go",
"chars": 1953,
"preview": "// Copyright (c) 2015 Uber Technologies, Inc.\n\n// Permission is hereby granted, free of charge, to any person obtaining "
},
{
"path": "http/buf_test.go",
"chars": 2068,
"preview": "// Copyright (c) 2015 Uber Technologies, Inc.\n\n// Permission is hereby granted, free of charge, to any person obtaining "
},
{
"path": "http/http_test.go",
"chars": 7827,
"preview": "// Copyright (c) 2015 Uber Technologies, Inc.\n\n// Permission is hereby granted, free of charge, to any person obtaining "
},
{
"path": "http/request.go",
"chars": 2560,
"preview": "// Copyright (c) 2015 Uber Technologies, Inc.\n\n// Permission is hereby granted, free of charge, to any person obtaining "
},
{
"path": "http/response.go",
"chars": 3918,
"preview": "// Copyright (c) 2015 Uber Technologies, Inc.\n\n// Permission is hereby granted, free of charge, to any person obtaining "
},
{
"path": "hyperbahn/advertise.go",
"chars": 5035,
"preview": "// Copyright (c) 2015 Uber Technologies, Inc.\n\n// Permission is hereby granted, free of charge, to any person obtaining "
},
{
"path": "hyperbahn/advertise_test.go",
"chars": 11808,
"preview": "// Copyright (c) 2015 Uber Technologies, Inc.\n\n// Permission is hereby granted, free of charge, to any person obtaining "
},
{
"path": "hyperbahn/call.go",
"chars": 2574,
"preview": "// Copyright (c) 2015 Uber Technologies, Inc.\n\n// Permission is hereby granted, free of charge, to any person obtaining "
},
{
"path": "hyperbahn/client.go",
"chars": 6395,
"preview": "// Copyright (c) 2015 Uber Technologies, Inc.\n\n// Permission is hereby granted, free of charge, to any person obtaining "
},
{
"path": "hyperbahn/client_test.go",
"chars": 4936,
"preview": "// Copyright (c) 2015 Uber Technologies, Inc.\n\n// Permission is hereby granted, free of charge, to any person obtaining "
},
{
"path": "hyperbahn/configuration.go",
"chars": 1474,
"preview": "// Copyright (c) 2015 Uber Technologies, Inc.\n\n// Permission is hereby granted, free of charge, to any person obtaining "
},
{
"path": "hyperbahn/discover.go",
"chars": 1798,
"preview": "// Copyright (c) 2015 Uber Technologies, Inc.\n\n// Permission is hereby granted, free of charge, to any person obtaining "
},
{
"path": "hyperbahn/discover_test.go",
"chars": 2394,
"preview": "// Copyright (c) 2015 Uber Technologies, Inc.\n\n// Permission is hereby granted, free of charge, to any person obtaining "
},
{
"path": "hyperbahn/event_string.go",
"chars": 397,
"preview": "// generated by stringer -type=Event; DO NOT EDIT\n\npackage hyperbahn\n\nimport \"fmt\"\n\nconst _Event_name = \"UnknownEventReg"
},
{
"path": "hyperbahn/events.go",
"chars": 2020,
"preview": "// Copyright (c) 2015 Uber Technologies, Inc.\n\n// Permission is hereby granted, free of charge, to any person obtaining "
},
{
"path": "hyperbahn/gen-go/hyperbahn/constants.go",
"chars": 393,
"preview": "// Autogenerated by Thrift Compiler (1.0.0-dev)\n// DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING\n\npac"
},
{
"path": "hyperbahn/gen-go/hyperbahn/hyperbahn.go",
"chars": 15387,
"preview": "// Autogenerated by Thrift Compiler (1.0.0-dev)\n// DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING\n\npac"
},
{
"path": "hyperbahn/gen-go/hyperbahn/tchan-hyperbahn.go",
"chars": 3389,
"preview": "// @generated Code generated by thrift-gen. Do not modify.\n\n// Package hyperbahn is generated code used to make or handl"
},
{
"path": "hyperbahn/gen-go/hyperbahn/ttypes.go",
"chars": 21553,
"preview": "// Autogenerated by Thrift Compiler (1.0.0-dev)\n// DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING\n\npac"
},
{
"path": "hyperbahn/hyperbahn.thrift",
"chars": 642,
"preview": "exception NoPeersAvailable {\n 1: required string message\n 2: required string serviceName\n}\n\nexception InvalidServi"
},
{
"path": "hyperbahn/utils.go",
"chars": 1729,
"preview": "// Copyright (c) 2015 Uber Technologies, Inc.\n\n// Permission is hereby granted, free of charge, to any person obtaining "
},
{
"path": "hyperbahn/utils_test.go",
"chars": 1674,
"preview": "// Copyright (c) 2015 Uber Technologies, Inc.\n\n// Permission is hereby granted, free of charge, to any person obtaining "
},
{
"path": "idle_sweep.go",
"chars": 3968,
"preview": "// Copyright (c) 2017 Uber Technologies, Inc.\n\n// Permission is hereby granted, free of charge, to any person obtaining "
},
{
"path": "idle_sweep_test.go",
"chars": 12723,
"preview": "// Copyright (c) 2017 Uber Technologies, Inc.\n\n// Permission is hereby granted, free of charge, to any person obtaining "
},
{
"path": "inbound.go",
"chars": 15637,
"preview": "// Copyright (c) 2015 Uber Technologies, Inc.\n\n// Permission is hereby granted, free of charge, to any person obtaining "
},
{
"path": "inbound_internal_test.go",
"chars": 3613,
"preview": "// Copyright (c) 2015 Uber Technologies, Inc.\n\n// Permission is hereby granted, free of charge, to any person obtaining "
},
{
"path": "inbound_test.go",
"chars": 11423,
"preview": "// Copyright (c) 2015 Uber Technologies, Inc.\n\n// Permission is hereby granted, free of charge, to any person obtaining "
},
{
"path": "incoming_test.go",
"chars": 3737,
"preview": "// Copyright (c) 2015 Uber Technologies, Inc.\n\n// Permission is hereby granted, free of charge, to any person obtaining "
},
{
"path": "init_test.go",
"chars": 10238,
"preview": "// Copyright (c) 2015 Uber Technologies, Inc.\n\n// Permission is hereby granted, free of charge, to any person obtaining "
},
{
"path": "internal/argreader/empty.go",
"chars": 1722,
"preview": "// Copyright (c) 2015 Uber Technologies, Inc.\n\n// Permission is hereby granted, free of charge, to any person obtaining "
},
{
"path": "internal/argreader/empty_test.go",
"chars": 2080,
"preview": "// Copyright (c) 2015 Uber Technologies, Inc.\n\n// Permission is hereby granted, free of charge, to any person obtaining "
},
{
"path": "internal/testcert/testcert.go",
"chars": 4438,
"preview": "// Copyright (c) 2022 Uber Technologies, Inc.\n\n// Permission is hereby granted, free of charge, to any person obtaining "
},
{
"path": "introspection.go",
"chars": 18924,
"preview": "// Copyright (c) 2015 Uber Technologies, Inc.\n\n// Permission is hereby granted, free of charge, to any person obtaining "
},
{
"path": "introspection_test.go",
"chars": 6625,
"preview": "// Copyright (c) 2015 Uber Technologies, Inc.\n\n// Permission is hereby granted, free of charge, to any person obtaining "
},
{
"path": "json/call.go",
"chars": 5512,
"preview": "// Copyright (c) 2015 Uber Technologies, Inc.\n\n// Permission is hereby granted, free of charge, to any person obtaining "
},
{
"path": "json/context.go",
"chars": 1928,
"preview": "// Copyright (c) 2015 Uber Technologies, Inc.\n\n// Permission is hereby granted, free of charge, to any person obtaining "
},
{
"path": "json/handler.go",
"chars": 5736,
"preview": "// Copyright (c) 2015 Uber Technologies, Inc.\n\n// Permission is hereby granted, free of charge, to any person obtaining "
},
{
"path": "json/json_test.go",
"chars": 8570,
"preview": "// Copyright (c) 2015 Uber Technologies, Inc.\n\n// Permission is hereby granted, free of charge, to any person obtaining "
},
{
"path": "json/retry_test.go",
"chars": 2426,
"preview": "// Copyright (c) 2015 Uber Technologies, Inc.\n\n// Permission is hereby granted, free of charge, to any person obtaining "
},
{
"path": "json/tracing_test.go",
"chars": 2365,
"preview": "package json_test\n\nimport (\n\t\"testing\"\n\n\t\"github.com/uber/tchannel-go\"\n\t\"github.com/uber/tchannel-go/json\"\n\n\t. \"github.c"
},
{
"path": "largereq_test.go",
"chars": 2214,
"preview": "// Copyright (c) 2015 Uber Technologies, Inc.\n\n// Permission is hereby granted, free of charge, to any person obtaining "
},
{
"path": "localip.go",
"chars": 3213,
"preview": "// Copyright (c) 2015 Uber Technologies, Inc.\n\n// Permission is hereby granted, free of charge, to any person obtaining "
},
{
"path": "localip_test.go",
"chars": 2859,
"preview": "// Copyright (c) 2015 Uber Technologies, Inc.\n\n// Permission is hereby granted, free of charge, to any person obtaining "
},
{
"path": "logger.go",
"chars": 6821,
"preview": "// Copyright (c) 2015 Uber Technologies, Inc.\n\n// Permission is hereby granted, free of charge, to any person obtaining "
},
{
"path": "logger_test.go",
"chars": 4894,
"preview": "// Copyright (c) 2015 Uber Technologies, Inc.\n\n// Permission is hereby granted, free of charge, to any person obtaining "
},
{
"path": "messages.go",
"chars": 10964,
"preview": "// Copyright (c) 2015 Uber Technologies, Inc.\n\n// Permission is hereby granted, free of charge, to any person obtaining "
},
{
"path": "messages_test.go",
"chars": 4220,
"preview": "// Copyright (c) 2015 Uber Technologies, Inc.\n\n// Permission is hereby granted, free of charge, to any person obtaining "
},
{
"path": "messagetype_string.go",
"chars": 1651,
"preview": "// Code generated by \"stringer -type=messageType\"; DO NOT EDIT.\n\npackage tchannel\n\nimport \"strconv\"\n\nfunc _() {\n\t// An \""
},
{
"path": "mex.go",
"chars": 16355,
"preview": "// Copyright (c) 2015 Uber Technologies, Inc.\n\n// Permission is hereby granted, free of charge, to any person obtaining "
},
{
"path": "mex_utils_test.go",
"chars": 2902,
"preview": "// Copyright (c) 2015 Uber Technologies, Inc.\n\n// Permission is hereby granted, free of charge, to any person obtaining "
},
{
"path": "outbound.go",
"chars": 13026,
"preview": "// Copyright (c) 2015 Uber Technologies, Inc.\n\n// Permission is hereby granted, free of charge, to any person obtaining "
},
{
"path": "peer.go",
"chars": 16940,
"preview": "// Copyright (c) 2015 Uber Technologies, Inc.\n\n// Permission is hereby granted, free of charge, to any person obtaining "
},
{
"path": "peer_bench_test.go",
"chars": 2216,
"preview": "// Copyright (c) 2015 Uber Technologies, Inc.\n\n// Permission is hereby granted, free of charge, to any person obtaining "
},
{
"path": "peer_heap.go",
"chars": 3642,
"preview": "// Copyright (c) 2015 Uber Technologies, Inc.\n\n// Permission is hereby granted, free of charge, to any person obtaining "
},
{
"path": "peer_heap_test.go",
"chars": 2134,
"preview": "// Copyright (c) 2015 Uber Technologies, Inc.\n\n// Permission is hereby granted, free of charge, to any person obtaining "
},
{
"path": "peer_internal_test.go",
"chars": 1599,
"preview": "// Copyright (c) 2015 Uber Technologies, Inc.\n\n// Permission is hereby granted, free of charge, to any person obtaining "
},
{
"path": "peer_strategies.go",
"chars": 2980,
"preview": "// Copyright (c) 2015 Uber Technologies, Inc.\n\n// Permission is hereby granted, free of charge, to any person obtaining "
},
{
"path": "peer_test.go",
"chars": 33242,
"preview": "// Copyright (c) 2015 Uber Technologies, Inc.\n\n// Permission is hereby granted, free of charge, to any person obtaining "
},
{
"path": "peers/doc.go",
"chars": 1200,
"preview": "// Copyright (c) 2017 Uber Technologies, Inc.\n\n// Permission is hereby granted, free of charge, to any person obtaining "
},
{
"path": "peers/prefer.go",
"chars": 2629,
"preview": "// Copyright (c) 2017 Uber Technologies, Inc.\n\n// Permission is hereby granted, free of charge, to any person obtaining "
},
{
"path": "peers/prefer_test.go",
"chars": 5894,
"preview": "// Copyright (c) 2017 Uber Technologies, Inc.\n\n// Permission is hereby granted, free of charge, to any person obtaining "
},
{
"path": "pprof/pprof.go",
"chars": 2084,
"preview": "// Copyright (c) 2015 Uber Technologies, Inc.\n\n// Permission is hereby granted, free of charge, to any person obtaining "
},
{
"path": "pprof/pprof_test.go",
"chars": 2225,
"preview": "// Copyright (c) 2015 Uber Technologies, Inc.\n\n// Permission is hereby granted, free of charge, to any person obtaining "
},
{
"path": "preinit_connection.go",
"chars": 7618,
"preview": "// Copyright (c) 2017 Uber Technologies, Inc.\n\n// Permission is hereby granted, free of charge, to any person obtaining "
},
{
"path": "raw/call.go",
"chars": 3965,
"preview": "// Copyright (c) 2015 Uber Technologies, Inc.\n\n// Permission is hereby granted, free of charge, to any person obtaining "
},
{
"path": "raw/handler.go",
"chars": 3394,
"preview": "// Copyright (c) 2015 Uber Technologies, Inc.\n\n// Permission is hereby granted, free of charge, to any person obtaining "
},
{
"path": "relay/relay.go",
"chars": 4070,
"preview": "// Copyright (c) 2015 Uber Technologies, Inc.\n\n// Permission is hereby granted, free of charge, to any person obtaining "
},
{
"path": "relay/relaytest/func_host.go",
"chars": 1452,
"preview": "package relaytest\n\nimport (\n\t\"github.com/uber/tchannel-go\"\n\t\"github.com/uber/tchannel-go/relay\"\n)\n\n// Ensure that the ho"
},
{
"path": "relay/relaytest/mock_stats.go",
"chars": 6494,
"preview": "// Copyright (c) 2015 Uber Technologies, Inc.\n\n// Permission is hereby granted, free of charge, to any person obtaining "
},
{
"path": "relay/relaytest/stub_host.go",
"chars": 3547,
"preview": "// Copyright (c) 2015 Uber Technologies, Inc.\n\n// Permission is hereby granted, free of charge, to any person obtaining "
},
{
"path": "relay.go",
"chars": 29737,
"preview": "// Copyright (c) 2015 Uber Technologies, Inc.\n\n// Permission is hereby granted, free of charge, to any person obtaining "
},
{
"path": "relay_api.go",
"chars": 2613,
"preview": "// Copyright (c) 2015 Uber Technologies, Inc.\n\n// Permission is hereby granted, free of charge, to any person obtaining "
},
{
"path": "relay_benchmark_test.go",
"chars": 5664,
"preview": "package tchannel_test\n\nimport (\n\t\"fmt\"\n\t\"sync\"\n\t\"testing\"\n\t\"time\"\n\n\t\"github.com/bmizerany/perks/quantile\"\n\t\"github.com/s"
},
{
"path": "relay_fragment_sender_test.go",
"chars": 7469,
"preview": "package tchannel\n\nimport (\n\t\"errors\"\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n\t\"github.com/stretchr/testify/req"
},
{
"path": "relay_internal_test.go",
"chars": 2341,
"preview": "package tchannel\n\nimport (\n\t\"testing\"\n\t\"time\"\n\n\t\"github.com/uber/tchannel-go/typed\"\n\n\t\"github.com/stretchr/testify/asser"
},
{
"path": "relay_messages.go",
"chars": 9912,
"preview": "// Copyright (c) 2015 Uber Technologies, Inc.\n\n// Permission is hereby granted, free of charge, to any person obtaining "
},
{
"path": "relay_messages_benchmark_test.go",
"chars": 1664,
"preview": "// Copyright (c) 2015 Uber Technologies, Inc.\n\n// Permission is hereby granted, free of charge, to any person obtaining "
},
{
"path": "relay_messages_test.go",
"chars": 21318,
"preview": "// Copyright (c) 2015 Uber Technologies, Inc.\n\n// Permission is hereby granted, free of charge, to any person obtaining "
},
{
"path": "relay_test.go",
"chars": 69858,
"preview": "// Copyright (c) 2015 Uber Technologies, Inc.\n\n// Permission is hereby granted, free of charge, to any person obtaining "
},
{
"path": "relay_timer_pool.go",
"chars": 4570,
"preview": "// Copyright (c) 2017 Uber Technologies, Inc.\n\n// Permission is hereby granted, free of charge, to any person obtaining "
},
{
"path": "reqres.go",
"chars": 9077,
"preview": "// Copyright (c) 2015 Uber Technologies, Inc.\n\n// Permission is hereby granted, free of charge, to any person obtaining "
},
{
"path": "reqresreaderstate_string.go",
"chars": 531,
"preview": "// generated by stringer -type=reqResReaderState; DO NOT EDIT\n\npackage tchannel\n\nimport \"fmt\"\n\nconst _reqResReaderState_"
},
{
"path": "reqreswriterstate_string.go",
"chars": 531,
"preview": "// generated by stringer -type=reqResWriterState; DO NOT EDIT\n\npackage tchannel\n\nimport \"fmt\"\n\nconst _reqResWriterState_"
},
{
"path": "retry.go",
"chars": 7348,
"preview": "// Copyright (c) 2015 Uber Technologies, Inc.\n\n// Permission is hereby granted, free of charge, to any person obtaining "
},
{
"path": "retry_request_test.go",
"chars": 2780,
"preview": "// Copyright (c) 2015 Uber Technologies, Inc.\n\n// Permission is hereby granted, free of charge, to any person obtaining "
},
{
"path": "retry_test.go",
"chars": 7854,
"preview": "// Copyright (c) 2015 Uber Technologies, Inc.\n\n// Permission is hereby granted, free of charge, to any person obtaining "
},
{
"path": "retryon_string.go",
"chars": 452,
"preview": "// generated by stringer -type=RetryOn; DO NOT EDIT\n\npackage tchannel\n\nimport \"fmt\"\n\nconst _RetryOn_name = \"RetryDefault"
},
{
"path": "root_peer_list.go",
"chars": 3681,
"preview": "// Copyright (c) 2015 Uber Technologies, Inc.\n\n// Permission is hereby granted, free of charge, to any person obtaining "
},
{
"path": "scripts/install-thrift.sh",
"chars": 428,
"preview": "#!/bin/bash\n\nset -euo pipefail\n\nif [ -z \"${1}\" ]; then\n echo \"usage: ${0} installDirPath\" >&2\n exit 1\nfi\n\nBIN_FILE=\"th"
},
{
"path": "scripts/vbumper/main.go",
"chars": 6023,
"preview": "// Copyright (c) 2015 Uber Technologies, Inc.\n\n// Permission is hereby granted, free of charge, to any person obtaining "
},
{
"path": "sockio_bsd.go",
"chars": 1396,
"preview": "// Copyright (c) 2020 Uber Technologies, Inc.\n\n// Permission is hereby granted, free of charge, to any person obtaining "
},
{
"path": "sockio_darwin.go",
"chars": 1377,
"preview": "// Copyright (c) 2020 Uber Technologies, Inc.\n\n// Permission is hereby granted, free of charge, to any person obtaining "
}
]
// ... and 201 more files (download for full content)
About this extraction
This page contains the full source code of the uber/tchannel-go GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 401 files (2.0 MB), approximately 530.9k tokens, and a symbol index with 4358 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.