Merge pull request #10450 from containers/dependabot/go_modules/github.com/uber/jaeger-client-go-2.29.1incompatible

Bump github.com/uber/jaeger-client-go from 2.28.0+incompatible to 2.29.1+incompatible
This commit is contained in:
OpenShift Merge Robot 2021-05-31 16:20:34 +02:00 committed by GitHub
commit 8f5f0cf448
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
44 changed files with 8161 additions and 5018 deletions

2
go.mod
View File

@ -58,7 +58,7 @@ require (
github.com/spf13/pflag v1.0.5 github.com/spf13/pflag v1.0.5
github.com/stretchr/testify v1.7.0 github.com/stretchr/testify v1.7.0
github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635 github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635
github.com/uber/jaeger-client-go v2.28.0+incompatible github.com/uber/jaeger-client-go v2.29.1+incompatible
github.com/vbauerster/mpb/v6 v6.0.4 github.com/vbauerster/mpb/v6 v6.0.4
github.com/vishvananda/netlink v1.1.1-0.20201029203352-d40f9887b852 github.com/vishvananda/netlink v1.1.1-0.20201029203352-d40f9887b852
go.etcd.io/bbolt v1.3.5 go.etcd.io/bbolt v1.3.5

4
go.sum
View File

@ -827,8 +827,8 @@ github.com/tchap/go-patricia v2.3.0+incompatible/go.mod h1:bmLyhP68RS6kStMGxByiQ
github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
github.com/u-root/u-root v7.0.0+incompatible/go.mod h1:RYkpo8pTHrNjW08opNd/U6p/RJE7K0D8fXO0d47+3YY= github.com/u-root/u-root v7.0.0+incompatible/go.mod h1:RYkpo8pTHrNjW08opNd/U6p/RJE7K0D8fXO0d47+3YY=
github.com/uber/jaeger-client-go v2.28.0+incompatible h1:G4QSBfvPKvg5ZM2j9MrJFdfI5iSljY/WnJqOGFao6HI= github.com/uber/jaeger-client-go v2.29.1+incompatible h1:R9ec3zO3sGpzs0abd43Y+fBZRJ9uiH6lXyR/+u6brW4=
github.com/uber/jaeger-client-go v2.28.0+incompatible/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk= github.com/uber/jaeger-client-go v2.29.1+incompatible/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk=
github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc=
github.com/ulikunitz/xz v0.5.10 h1:t92gobL9l3HE202wg3rlk19F6X+JOxl9BBrCCMYEYd8= github.com/ulikunitz/xz v0.5.10 h1:t92gobL9l3HE202wg3rlk19F6X+JOxl9BBrCCMYEYd8=
github.com/ulikunitz/xz v0.5.10/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= github.com/ulikunitz/xz v0.5.10/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=

View File

@ -0,0 +1,6 @@
// Code generated by Thrift Compiler (0.14.1). DO NOT EDIT.
package agent
var GoUnusedProtection__ int;

View File

@ -1,19 +1,23 @@
// Autogenerated by Thrift Compiler (0.9.3) // Code generated by Thrift Compiler (0.14.1). DO NOT EDIT.
// DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
package agent package agent
import ( import(
"bytes" "bytes"
"context"
"fmt" "fmt"
"time"
"github.com/uber/jaeger-client-go/thrift" "github.com/uber/jaeger-client-go/thrift"
"github.com/uber/jaeger-client-go/thrift-gen/jaeger" "github.com/uber/jaeger-client-go/thrift-gen/jaeger"
"github.com/uber/jaeger-client-go/thrift-gen/zipkincore" "github.com/uber/jaeger-client-go/thrift-gen/zipkincore"
) )
// (needed to ensure safety because of naive import list construction.) // (needed to ensure safety because of naive import list construction.)
var _ = thrift.ZERO var _ = thrift.ZERO
var _ = fmt.Printf var _ = fmt.Printf
var _ = context.Background
var _ = time.Now
var _ = bytes.Equal var _ = bytes.Equal
var _ = jaeger.GoUnusedProtection__ var _ = jaeger.GoUnusedProtection__
@ -21,3 +25,4 @@ var _ = zipkincore.GoUnusedProtection__
func init() { func init() {
} }

View File

@ -1,411 +1,396 @@
// Autogenerated by Thrift Compiler (0.9.3) // Code generated by Thrift Compiler (0.14.1). DO NOT EDIT.
// DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
package agent package agent
import ( import(
"bytes" "bytes"
"context"
"fmt" "fmt"
"time"
"github.com/uber/jaeger-client-go/thrift" "github.com/uber/jaeger-client-go/thrift"
"github.com/uber/jaeger-client-go/thrift-gen/jaeger" "github.com/uber/jaeger-client-go/thrift-gen/jaeger"
"github.com/uber/jaeger-client-go/thrift-gen/zipkincore" "github.com/uber/jaeger-client-go/thrift-gen/zipkincore"
) )
// (needed to ensure safety because of naive import list construction.) // (needed to ensure safety because of naive import list construction.)
var _ = thrift.ZERO var _ = thrift.ZERO
var _ = fmt.Printf var _ = fmt.Printf
var _ = context.Background
var _ = time.Now
var _ = bytes.Equal var _ = bytes.Equal
var _ = jaeger.GoUnusedProtection__ var _ = jaeger.GoUnusedProtection__
var _ = zipkincore.GoUnusedProtection__ var _ = zipkincore.GoUnusedProtection__
type Agent interface { type Agent interface {
// Parameters: // Parameters:
// - Spans // - Spans
EmitZipkinBatch(spans []*zipkincore.Span) (err error) EmitZipkinBatch(ctx context.Context, spans []*zipkincore.Span) (_err error)
// Parameters: // Parameters:
// - Batch // - Batch
EmitBatch(batch *jaeger.Batch) (err error) EmitBatch(ctx context.Context, batch *jaeger.Batch) (_err error)
} }
type AgentClient struct { type AgentClient struct {
Transport thrift.TTransport c thrift.TClient
ProtocolFactory thrift.TProtocolFactory meta thrift.ResponseMeta
InputProtocol thrift.TProtocol
OutputProtocol thrift.TProtocol
SeqId int32
} }
func NewAgentClientFactory(t thrift.TTransport, f thrift.TProtocolFactory) *AgentClient { func NewAgentClientFactory(t thrift.TTransport, f thrift.TProtocolFactory) *AgentClient {
return &AgentClient{Transport: t, return &AgentClient{
ProtocolFactory: f, c: thrift.NewTStandardClient(f.GetProtocol(t), f.GetProtocol(t)),
InputProtocol: f.GetProtocol(t), }
OutputProtocol: f.GetProtocol(t),
SeqId: 0,
}
} }
func NewAgentClientProtocol(t thrift.TTransport, iprot thrift.TProtocol, oprot thrift.TProtocol) *AgentClient { func NewAgentClientProtocol(t thrift.TTransport, iprot thrift.TProtocol, oprot thrift.TProtocol) *AgentClient {
return &AgentClient{Transport: t, return &AgentClient{
ProtocolFactory: nil, c: thrift.NewTStandardClient(iprot, oprot),
InputProtocol: iprot, }
OutputProtocol: oprot, }
SeqId: 0,
} func NewAgentClient(c thrift.TClient) *AgentClient {
return &AgentClient{
c: c,
}
}
func (p *AgentClient) Client_() thrift.TClient {
return p.c
}
func (p *AgentClient) LastResponseMeta_() thrift.ResponseMeta {
return p.meta
}
func (p *AgentClient) SetLastResponseMeta_(meta thrift.ResponseMeta) {
p.meta = meta
} }
// Parameters: // Parameters:
// - Spans // - Spans
func (p *AgentClient) EmitZipkinBatch(spans []*zipkincore.Span) (err error) { func (p *AgentClient) EmitZipkinBatch(ctx context.Context, spans []*zipkincore.Span) (_err error) {
if err = p.sendEmitZipkinBatch(spans); err != nil { var _args0 AgentEmitZipkinBatchArgs
return _args0.Spans = spans
} p.SetLastResponseMeta_(thrift.ResponseMeta{})
return if _, err := p.Client_().Call(ctx, "emitZipkinBatch", &_args0, nil); err != nil {
} return err
}
func (p *AgentClient) sendEmitZipkinBatch(spans []*zipkincore.Span) (err error) { return nil
oprot := p.OutputProtocol
if oprot == nil {
oprot = p.ProtocolFactory.GetProtocol(p.Transport)
p.OutputProtocol = oprot
}
p.SeqId++
if err = oprot.WriteMessageBegin("emitZipkinBatch", thrift.ONEWAY, p.SeqId); err != nil {
return
}
args := AgentEmitZipkinBatchArgs{
Spans: spans,
}
if err = args.Write(oprot); err != nil {
return
}
if err = oprot.WriteMessageEnd(); err != nil {
return
}
return oprot.Flush()
} }
// Parameters: // Parameters:
// - Batch // - Batch
func (p *AgentClient) EmitBatch(batch *jaeger.Batch) (err error) { func (p *AgentClient) EmitBatch(ctx context.Context, batch *jaeger.Batch) (_err error) {
if err = p.sendEmitBatch(batch); err != nil { var _args1 AgentEmitBatchArgs
return _args1.Batch = batch
} p.SetLastResponseMeta_(thrift.ResponseMeta{})
return if _, err := p.Client_().Call(ctx, "emitBatch", &_args1, nil); err != nil {
} return err
}
func (p *AgentClient) sendEmitBatch(batch *jaeger.Batch) (err error) { return nil
oprot := p.OutputProtocol
if oprot == nil {
oprot = p.ProtocolFactory.GetProtocol(p.Transport)
p.OutputProtocol = oprot
}
p.SeqId++
if err = oprot.WriteMessageBegin("emitBatch", thrift.ONEWAY, p.SeqId); err != nil {
return
}
args := AgentEmitBatchArgs{
Batch: batch,
}
if err = args.Write(oprot); err != nil {
return
}
if err = oprot.WriteMessageEnd(); err != nil {
return
}
return oprot.Flush()
} }
type AgentProcessor struct { type AgentProcessor struct {
processorMap map[string]thrift.TProcessorFunction processorMap map[string]thrift.TProcessorFunction
handler Agent handler Agent
} }
func (p *AgentProcessor) AddToProcessorMap(key string, processor thrift.TProcessorFunction) { func (p *AgentProcessor) AddToProcessorMap(key string, processor thrift.TProcessorFunction) {
p.processorMap[key] = processor p.processorMap[key] = processor
} }
func (p *AgentProcessor) GetProcessorFunction(key string) (processor thrift.TProcessorFunction, ok bool) { func (p *AgentProcessor) GetProcessorFunction(key string) (processor thrift.TProcessorFunction, ok bool) {
processor, ok = p.processorMap[key] processor, ok = p.processorMap[key]
return processor, ok return processor, ok
} }
func (p *AgentProcessor) ProcessorMap() map[string]thrift.TProcessorFunction { func (p *AgentProcessor) ProcessorMap() map[string]thrift.TProcessorFunction {
return p.processorMap return p.processorMap
} }
func NewAgentProcessor(handler Agent) *AgentProcessor { func NewAgentProcessor(handler Agent) *AgentProcessor {
self0 := &AgentProcessor{handler: handler, processorMap: make(map[string]thrift.TProcessorFunction)} self2 := &AgentProcessor{handler:handler, processorMap:make(map[string]thrift.TProcessorFunction)}
self0.processorMap["emitZipkinBatch"] = &agentProcessorEmitZipkinBatch{handler: handler} self2.processorMap["emitZipkinBatch"] = &agentProcessorEmitZipkinBatch{handler:handler}
self0.processorMap["emitBatch"] = &agentProcessorEmitBatch{handler: handler} self2.processorMap["emitBatch"] = &agentProcessorEmitBatch{handler:handler}
return self0 return self2
} }
func (p *AgentProcessor) Process(iprot, oprot thrift.TProtocol) (success bool, err thrift.TException) { func (p *AgentProcessor) Process(ctx context.Context, iprot, oprot thrift.TProtocol) (success bool, err thrift.TException) {
name, _, seqId, err := iprot.ReadMessageBegin() name, _, seqId, err2 := iprot.ReadMessageBegin(ctx)
if err != nil { if err2 != nil { return false, thrift.WrapTException(err2) }
return false, err if processor, ok := p.GetProcessorFunction(name); ok {
} return processor.Process(ctx, seqId, iprot, oprot)
if processor, ok := p.GetProcessorFunction(name); ok { }
return processor.Process(seqId, iprot, oprot) iprot.Skip(ctx, thrift.STRUCT)
} iprot.ReadMessageEnd(ctx)
iprot.Skip(thrift.STRUCT) x3 := thrift.NewTApplicationException(thrift.UNKNOWN_METHOD, "Unknown function " + name)
iprot.ReadMessageEnd() oprot.WriteMessageBegin(ctx, name, thrift.EXCEPTION, seqId)
x1 := thrift.NewTApplicationException(thrift.UNKNOWN_METHOD, "Unknown function "+name) x3.Write(ctx, oprot)
oprot.WriteMessageBegin(name, thrift.EXCEPTION, seqId) oprot.WriteMessageEnd(ctx)
x1.Write(oprot) oprot.Flush(ctx)
oprot.WriteMessageEnd() return false, x3
oprot.Flush()
return false, x1
} }
type agentProcessorEmitZipkinBatch struct { type agentProcessorEmitZipkinBatch struct {
handler Agent handler Agent
} }
func (p *agentProcessorEmitZipkinBatch) Process(seqId int32, iprot, oprot thrift.TProtocol) (success bool, err thrift.TException) { func (p *agentProcessorEmitZipkinBatch) Process(ctx context.Context, seqId int32, iprot, oprot thrift.TProtocol) (success bool, err thrift.TException) {
args := AgentEmitZipkinBatchArgs{} args := AgentEmitZipkinBatchArgs{}
if err = args.Read(iprot); err != nil { var err2 error
iprot.ReadMessageEnd() if err2 = args.Read(ctx, iprot); err2 != nil {
return false, err iprot.ReadMessageEnd(ctx)
} return false, thrift.WrapTException(err2)
}
iprot.ReadMessageEnd(ctx)
iprot.ReadMessageEnd() tickerCancel := func() {}
var err2 error _ = tickerCancel
if err2 = p.handler.EmitZipkinBatch(args.Spans); err2 != nil {
return true, err2 if err2 = p.handler.EmitZipkinBatch(ctx, args.Spans); err2 != nil {
} tickerCancel()
return true, nil return true, thrift.WrapTException(err2)
}
tickerCancel()
return true, nil
} }
type agentProcessorEmitBatch struct { type agentProcessorEmitBatch struct {
handler Agent handler Agent
} }
func (p *agentProcessorEmitBatch) Process(seqId int32, iprot, oprot thrift.TProtocol) (success bool, err thrift.TException) { func (p *agentProcessorEmitBatch) Process(ctx context.Context, seqId int32, iprot, oprot thrift.TProtocol) (success bool, err thrift.TException) {
args := AgentEmitBatchArgs{} args := AgentEmitBatchArgs{}
if err = args.Read(iprot); err != nil { var err2 error
iprot.ReadMessageEnd() if err2 = args.Read(ctx, iprot); err2 != nil {
return false, err iprot.ReadMessageEnd(ctx)
} return false, thrift.WrapTException(err2)
}
iprot.ReadMessageEnd(ctx)
iprot.ReadMessageEnd() tickerCancel := func() {}
var err2 error _ = tickerCancel
if err2 = p.handler.EmitBatch(args.Batch); err2 != nil {
return true, err2 if err2 = p.handler.EmitBatch(ctx, args.Batch); err2 != nil {
} tickerCancel()
return true, nil return true, thrift.WrapTException(err2)
}
tickerCancel()
return true, nil
} }
// HELPER FUNCTIONS AND STRUCTURES // HELPER FUNCTIONS AND STRUCTURES
// Attributes: // Attributes:
// - Spans // - Spans
type AgentEmitZipkinBatchArgs struct { type AgentEmitZipkinBatchArgs struct {
Spans []*zipkincore.Span `thrift:"spans,1" json:"spans"` Spans []*zipkincore.Span `thrift:"spans,1" db:"spans" json:"spans"`
} }
func NewAgentEmitZipkinBatchArgs() *AgentEmitZipkinBatchArgs { func NewAgentEmitZipkinBatchArgs() *AgentEmitZipkinBatchArgs {
return &AgentEmitZipkinBatchArgs{} return &AgentEmitZipkinBatchArgs{}
} }
func (p *AgentEmitZipkinBatchArgs) GetSpans() []*zipkincore.Span { func (p *AgentEmitZipkinBatchArgs) GetSpans() []*zipkincore.Span {
return p.Spans return p.Spans
} }
func (p *AgentEmitZipkinBatchArgs) Read(iprot thrift.TProtocol) error { func (p *AgentEmitZipkinBatchArgs) Read(ctx context.Context, iprot thrift.TProtocol) error {
if _, err := iprot.ReadStructBegin(); err != nil { if _, err := iprot.ReadStructBegin(ctx); err != nil {
return thrift.PrependError(fmt.Sprintf("%T read error: ", p), err) return thrift.PrependError(fmt.Sprintf("%T read error: ", p), err)
} }
for {
_, fieldTypeId, fieldId, err := iprot.ReadFieldBegin() for {
if err != nil { _, fieldTypeId, fieldId, err := iprot.ReadFieldBegin(ctx)
return thrift.PrependError(fmt.Sprintf("%T field %d read error: ", p, fieldId), err) if err != nil {
} return thrift.PrependError(fmt.Sprintf("%T field %d read error: ", p, fieldId), err)
if fieldTypeId == thrift.STOP { }
break if fieldTypeId == thrift.STOP { break; }
} switch fieldId {
switch fieldId { case 1:
case 1: if fieldTypeId == thrift.LIST {
if err := p.readField1(iprot); err != nil { if err := p.ReadField1(ctx, iprot); err != nil {
return err return err
} }
default: } else {
if err := iprot.Skip(fieldTypeId); err != nil { if err := iprot.Skip(ctx, fieldTypeId); err != nil {
return err return err
} }
} }
if err := iprot.ReadFieldEnd(); err != nil { default:
return err if err := iprot.Skip(ctx, fieldTypeId); err != nil {
} return err
} }
if err := iprot.ReadStructEnd(); err != nil { }
return thrift.PrependError(fmt.Sprintf("%T read struct end error: ", p), err) if err := iprot.ReadFieldEnd(ctx); err != nil {
} return err
return nil }
}
if err := iprot.ReadStructEnd(ctx); err != nil {
return thrift.PrependError(fmt.Sprintf("%T read struct end error: ", p), err)
}
return nil
} }
func (p *AgentEmitZipkinBatchArgs) readField1(iprot thrift.TProtocol) error { func (p *AgentEmitZipkinBatchArgs) ReadField1(ctx context.Context, iprot thrift.TProtocol) error {
_, size, err := iprot.ReadListBegin() _, size, err := iprot.ReadListBegin(ctx)
if err != nil { if err != nil {
return thrift.PrependError("error reading list begin: ", err) return thrift.PrependError("error reading list begin: ", err)
} }
tSlice := make([]*zipkincore.Span, 0, size) tSlice := make([]*zipkincore.Span, 0, size)
p.Spans = tSlice p.Spans = tSlice
for i := 0; i < size; i++ { for i := 0; i < size; i ++ {
_elem2 := &zipkincore.Span{} _elem4 := &zipkincore.Span{}
if err := _elem2.Read(iprot); err != nil { if err := _elem4.Read(ctx, iprot); err != nil {
return thrift.PrependError(fmt.Sprintf("%T error reading struct: ", _elem2), err) return thrift.PrependError(fmt.Sprintf("%T error reading struct: ", _elem4), err)
} }
p.Spans = append(p.Spans, _elem2) p.Spans = append(p.Spans, _elem4)
} }
if err := iprot.ReadListEnd(); err != nil { if err := iprot.ReadListEnd(ctx); err != nil {
return thrift.PrependError("error reading list end: ", err) return thrift.PrependError("error reading list end: ", err)
} }
return nil return nil
} }
func (p *AgentEmitZipkinBatchArgs) Write(oprot thrift.TProtocol) error { func (p *AgentEmitZipkinBatchArgs) Write(ctx context.Context, oprot thrift.TProtocol) error {
if err := oprot.WriteStructBegin("emitZipkinBatch_args"); err != nil { if err := oprot.WriteStructBegin(ctx, "emitZipkinBatch_args"); err != nil {
return thrift.PrependError(fmt.Sprintf("%T write struct begin error: ", p), err) return thrift.PrependError(fmt.Sprintf("%T write struct begin error: ", p), err) }
} if p != nil {
if err := p.writeField1(oprot); err != nil { if err := p.writeField1(ctx, oprot); err != nil { return err }
return err }
} if err := oprot.WriteFieldStop(ctx); err != nil {
if err := oprot.WriteFieldStop(); err != nil { return thrift.PrependError("write field stop error: ", err) }
return thrift.PrependError("write field stop error: ", err) if err := oprot.WriteStructEnd(ctx); err != nil {
} return thrift.PrependError("write struct stop error: ", err) }
if err := oprot.WriteStructEnd(); err != nil { return nil
return thrift.PrependError("write struct stop error: ", err)
}
return nil
} }
func (p *AgentEmitZipkinBatchArgs) writeField1(oprot thrift.TProtocol) (err error) { func (p *AgentEmitZipkinBatchArgs) writeField1(ctx context.Context, oprot thrift.TProtocol) (err error) {
if err := oprot.WriteFieldBegin("spans", thrift.LIST, 1); err != nil { if err := oprot.WriteFieldBegin(ctx, "spans", thrift.LIST, 1); err != nil {
return thrift.PrependError(fmt.Sprintf("%T write field begin error 1:spans: ", p), err) return thrift.PrependError(fmt.Sprintf("%T write field begin error 1:spans: ", p), err) }
} if err := oprot.WriteListBegin(ctx, thrift.STRUCT, len(p.Spans)); err != nil {
if err := oprot.WriteListBegin(thrift.STRUCT, len(p.Spans)); err != nil { return thrift.PrependError("error writing list begin: ", err)
return thrift.PrependError("error writing list begin: ", err) }
} for _, v := range p.Spans {
for _, v := range p.Spans { if err := v.Write(ctx, oprot); err != nil {
if err := v.Write(oprot); err != nil { return thrift.PrependError(fmt.Sprintf("%T error writing struct: ", v), err)
return thrift.PrependError(fmt.Sprintf("%T error writing struct: ", v), err) }
} }
} if err := oprot.WriteListEnd(ctx); err != nil {
if err := oprot.WriteListEnd(); err != nil { return thrift.PrependError("error writing list end: ", err)
return thrift.PrependError("error writing list end: ", err) }
} if err := oprot.WriteFieldEnd(ctx); err != nil {
if err := oprot.WriteFieldEnd(); err != nil { return thrift.PrependError(fmt.Sprintf("%T write field end error 1:spans: ", p), err) }
return thrift.PrependError(fmt.Sprintf("%T write field end error 1:spans: ", p), err) return err
}
return err
} }
func (p *AgentEmitZipkinBatchArgs) String() string { func (p *AgentEmitZipkinBatchArgs) String() string {
if p == nil { if p == nil {
return "<nil>" return "<nil>"
} }
return fmt.Sprintf("AgentEmitZipkinBatchArgs(%+v)", *p) return fmt.Sprintf("AgentEmitZipkinBatchArgs(%+v)", *p)
} }
// Attributes: // Attributes:
// - Batch // - Batch
type AgentEmitBatchArgs struct { type AgentEmitBatchArgs struct {
Batch *jaeger.Batch `thrift:"batch,1" json:"batch"` Batch *jaeger.Batch `thrift:"batch,1" db:"batch" json:"batch"`
} }
func NewAgentEmitBatchArgs() *AgentEmitBatchArgs { func NewAgentEmitBatchArgs() *AgentEmitBatchArgs {
return &AgentEmitBatchArgs{} return &AgentEmitBatchArgs{}
} }
var AgentEmitBatchArgs_Batch_DEFAULT *jaeger.Batch var AgentEmitBatchArgs_Batch_DEFAULT *jaeger.Batch
func (p *AgentEmitBatchArgs) GetBatch() *jaeger.Batch { func (p *AgentEmitBatchArgs) GetBatch() *jaeger.Batch {
if !p.IsSetBatch() { if !p.IsSetBatch() {
return AgentEmitBatchArgs_Batch_DEFAULT return AgentEmitBatchArgs_Batch_DEFAULT
} }
return p.Batch return p.Batch
} }
func (p *AgentEmitBatchArgs) IsSetBatch() bool { func (p *AgentEmitBatchArgs) IsSetBatch() bool {
return p.Batch != nil return p.Batch != nil
} }
func (p *AgentEmitBatchArgs) Read(iprot thrift.TProtocol) error { func (p *AgentEmitBatchArgs) Read(ctx context.Context, iprot thrift.TProtocol) error {
if _, err := iprot.ReadStructBegin(); err != nil { if _, err := iprot.ReadStructBegin(ctx); err != nil {
return thrift.PrependError(fmt.Sprintf("%T read error: ", p), err) return thrift.PrependError(fmt.Sprintf("%T read error: ", p), err)
} }
for {
_, fieldTypeId, fieldId, err := iprot.ReadFieldBegin() for {
if err != nil { _, fieldTypeId, fieldId, err := iprot.ReadFieldBegin(ctx)
return thrift.PrependError(fmt.Sprintf("%T field %d read error: ", p, fieldId), err) if err != nil {
} return thrift.PrependError(fmt.Sprintf("%T field %d read error: ", p, fieldId), err)
if fieldTypeId == thrift.STOP { }
break if fieldTypeId == thrift.STOP { break; }
} switch fieldId {
switch fieldId { case 1:
case 1: if fieldTypeId == thrift.STRUCT {
if err := p.readField1(iprot); err != nil { if err := p.ReadField1(ctx, iprot); err != nil {
return err return err
} }
default: } else {
if err := iprot.Skip(fieldTypeId); err != nil { if err := iprot.Skip(ctx, fieldTypeId); err != nil {
return err return err
} }
} }
if err := iprot.ReadFieldEnd(); err != nil { default:
return err if err := iprot.Skip(ctx, fieldTypeId); err != nil {
} return err
} }
if err := iprot.ReadStructEnd(); err != nil { }
return thrift.PrependError(fmt.Sprintf("%T read struct end error: ", p), err) if err := iprot.ReadFieldEnd(ctx); err != nil {
} return err
return nil }
}
if err := iprot.ReadStructEnd(ctx); err != nil {
return thrift.PrependError(fmt.Sprintf("%T read struct end error: ", p), err)
}
return nil
} }
func (p *AgentEmitBatchArgs) readField1(iprot thrift.TProtocol) error { func (p *AgentEmitBatchArgs) ReadField1(ctx context.Context, iprot thrift.TProtocol) error {
p.Batch = &jaeger.Batch{} p.Batch = &jaeger.Batch{}
if err := p.Batch.Read(iprot); err != nil { if err := p.Batch.Read(ctx, iprot); err != nil {
return thrift.PrependError(fmt.Sprintf("%T error reading struct: ", p.Batch), err) return thrift.PrependError(fmt.Sprintf("%T error reading struct: ", p.Batch), err)
} }
return nil return nil
} }
func (p *AgentEmitBatchArgs) Write(oprot thrift.TProtocol) error { func (p *AgentEmitBatchArgs) Write(ctx context.Context, oprot thrift.TProtocol) error {
if err := oprot.WriteStructBegin("emitBatch_args"); err != nil { if err := oprot.WriteStructBegin(ctx, "emitBatch_args"); err != nil {
return thrift.PrependError(fmt.Sprintf("%T write struct begin error: ", p), err) return thrift.PrependError(fmt.Sprintf("%T write struct begin error: ", p), err) }
} if p != nil {
if err := p.writeField1(oprot); err != nil { if err := p.writeField1(ctx, oprot); err != nil { return err }
return err }
} if err := oprot.WriteFieldStop(ctx); err != nil {
if err := oprot.WriteFieldStop(); err != nil { return thrift.PrependError("write field stop error: ", err) }
return thrift.PrependError("write field stop error: ", err) if err := oprot.WriteStructEnd(ctx); err != nil {
} return thrift.PrependError("write struct stop error: ", err) }
if err := oprot.WriteStructEnd(); err != nil { return nil
return thrift.PrependError("write struct stop error: ", err)
}
return nil
} }
func (p *AgentEmitBatchArgs) writeField1(oprot thrift.TProtocol) (err error) { func (p *AgentEmitBatchArgs) writeField1(ctx context.Context, oprot thrift.TProtocol) (err error) {
if err := oprot.WriteFieldBegin("batch", thrift.STRUCT, 1); err != nil { if err := oprot.WriteFieldBegin(ctx, "batch", thrift.STRUCT, 1); err != nil {
return thrift.PrependError(fmt.Sprintf("%T write field begin error 1:batch: ", p), err) return thrift.PrependError(fmt.Sprintf("%T write field begin error 1:batch: ", p), err) }
} if err := p.Batch.Write(ctx, oprot); err != nil {
if err := p.Batch.Write(oprot); err != nil { return thrift.PrependError(fmt.Sprintf("%T error writing struct: ", p.Batch), err)
return thrift.PrependError(fmt.Sprintf("%T error writing struct: ", p.Batch), err) }
} if err := oprot.WriteFieldEnd(ctx); err != nil {
if err := oprot.WriteFieldEnd(); err != nil { return thrift.PrependError(fmt.Sprintf("%T write field end error 1:batch: ", p), err) }
return thrift.PrependError(fmt.Sprintf("%T write field end error 1:batch: ", p), err) return err
}
return err
} }
func (p *AgentEmitBatchArgs) String() string { func (p *AgentEmitBatchArgs) String() string {
if p == nil { if p == nil {
return "<nil>" return "<nil>"
} }
return fmt.Sprintf("AgentEmitBatchArgs(%+v)", *p) return fmt.Sprintf("AgentEmitBatchArgs(%+v)", *p)
} }

View File

@ -1,21 +0,0 @@
// Autogenerated by Thrift Compiler (0.9.3)
// DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
package agent
import (
"bytes"
"fmt"
"github.com/uber/jaeger-client-go/thrift"
"github.com/uber/jaeger-client-go/thrift-gen/jaeger"
"github.com/uber/jaeger-client-go/thrift-gen/zipkincore"
)
// (needed to ensure safety because of naive import list construction.)
var _ = thrift.ZERO
var _ = fmt.Printf
var _ = bytes.Equal
var _ = jaeger.GoUnusedProtection__
var _ = zipkincore.GoUnusedProtection__
var GoUnusedProtection__ int

View File

@ -0,0 +1,6 @@
// Code generated by Thrift Compiler (0.14.1). DO NOT EDIT.
package jaeger
var GoUnusedProtection__ int;

View File

@ -1,242 +0,0 @@
// Autogenerated by Thrift Compiler (0.9.3)
// DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
package jaeger
import (
"bytes"
"fmt"
"github.com/uber/jaeger-client-go/thrift"
)
// (needed to ensure safety because of naive import list construction.)
var _ = thrift.ZERO
var _ = fmt.Printf
var _ = bytes.Equal
type Agent interface {
// Parameters:
// - Batch
EmitBatch(batch *Batch) (err error)
}
type AgentClient struct {
Transport thrift.TTransport
ProtocolFactory thrift.TProtocolFactory
InputProtocol thrift.TProtocol
OutputProtocol thrift.TProtocol
SeqId int32
}
func NewAgentClientFactory(t thrift.TTransport, f thrift.TProtocolFactory) *AgentClient {
return &AgentClient{Transport: t,
ProtocolFactory: f,
InputProtocol: f.GetProtocol(t),
OutputProtocol: f.GetProtocol(t),
SeqId: 0,
}
}
func NewAgentClientProtocol(t thrift.TTransport, iprot thrift.TProtocol, oprot thrift.TProtocol) *AgentClient {
return &AgentClient{Transport: t,
ProtocolFactory: nil,
InputProtocol: iprot,
OutputProtocol: oprot,
SeqId: 0,
}
}
// Parameters:
// - Batch
func (p *AgentClient) EmitBatch(batch *Batch) (err error) {
if err = p.sendEmitBatch(batch); err != nil {
return
}
return
}
func (p *AgentClient) sendEmitBatch(batch *Batch) (err error) {
oprot := p.OutputProtocol
if oprot == nil {
oprot = p.ProtocolFactory.GetProtocol(p.Transport)
p.OutputProtocol = oprot
}
p.SeqId++
if err = oprot.WriteMessageBegin("emitBatch", thrift.ONEWAY, p.SeqId); err != nil {
return
}
args := AgentEmitBatchArgs{
Batch: batch,
}
if err = args.Write(oprot); err != nil {
return
}
if err = oprot.WriteMessageEnd(); err != nil {
return
}
return oprot.Flush()
}
type AgentProcessor struct {
processorMap map[string]thrift.TProcessorFunction
handler Agent
}
func (p *AgentProcessor) AddToProcessorMap(key string, processor thrift.TProcessorFunction) {
p.processorMap[key] = processor
}
func (p *AgentProcessor) GetProcessorFunction(key string) (processor thrift.TProcessorFunction, ok bool) {
processor, ok = p.processorMap[key]
return processor, ok
}
func (p *AgentProcessor) ProcessorMap() map[string]thrift.TProcessorFunction {
return p.processorMap
}
func NewAgentProcessor(handler Agent) *AgentProcessor {
self6 := &AgentProcessor{handler: handler, processorMap: make(map[string]thrift.TProcessorFunction)}
self6.processorMap["emitBatch"] = &agentProcessorEmitBatch{handler: handler}
return self6
}
func (p *AgentProcessor) Process(iprot, oprot thrift.TProtocol) (success bool, err thrift.TException) {
name, _, seqId, err := iprot.ReadMessageBegin()
if err != nil {
return false, err
}
if processor, ok := p.GetProcessorFunction(name); ok {
return processor.Process(seqId, iprot, oprot)
}
iprot.Skip(thrift.STRUCT)
iprot.ReadMessageEnd()
x7 := thrift.NewTApplicationException(thrift.UNKNOWN_METHOD, "Unknown function "+name)
oprot.WriteMessageBegin(name, thrift.EXCEPTION, seqId)
x7.Write(oprot)
oprot.WriteMessageEnd()
oprot.Flush()
return false, x7
}
type agentProcessorEmitBatch struct {
handler Agent
}
func (p *agentProcessorEmitBatch) Process(seqId int32, iprot, oprot thrift.TProtocol) (success bool, err thrift.TException) {
args := AgentEmitBatchArgs{}
if err = args.Read(iprot); err != nil {
iprot.ReadMessageEnd()
return false, err
}
iprot.ReadMessageEnd()
var err2 error
if err2 = p.handler.EmitBatch(args.Batch); err2 != nil {
return true, err2
}
return true, nil
}
// HELPER FUNCTIONS AND STRUCTURES
// Attributes:
// - Batch
type AgentEmitBatchArgs struct {
Batch *Batch `thrift:"batch,1" json:"batch"`
}
func NewAgentEmitBatchArgs() *AgentEmitBatchArgs {
return &AgentEmitBatchArgs{}
}
var AgentEmitBatchArgs_Batch_DEFAULT *Batch
func (p *AgentEmitBatchArgs) GetBatch() *Batch {
if !p.IsSetBatch() {
return AgentEmitBatchArgs_Batch_DEFAULT
}
return p.Batch
}
func (p *AgentEmitBatchArgs) IsSetBatch() bool {
return p.Batch != nil
}
func (p *AgentEmitBatchArgs) Read(iprot thrift.TProtocol) error {
if _, err := iprot.ReadStructBegin(); err != nil {
return thrift.PrependError(fmt.Sprintf("%T read error: ", p), err)
}
for {
_, fieldTypeId, fieldId, err := iprot.ReadFieldBegin()
if err != nil {
return thrift.PrependError(fmt.Sprintf("%T field %d read error: ", p, fieldId), err)
}
if fieldTypeId == thrift.STOP {
break
}
switch fieldId {
case 1:
if err := p.readField1(iprot); err != nil {
return err
}
default:
if err := iprot.Skip(fieldTypeId); err != nil {
return err
}
}
if err := iprot.ReadFieldEnd(); err != nil {
return err
}
}
if err := iprot.ReadStructEnd(); err != nil {
return thrift.PrependError(fmt.Sprintf("%T read struct end error: ", p), err)
}
return nil
}
func (p *AgentEmitBatchArgs) readField1(iprot thrift.TProtocol) error {
p.Batch = &Batch{}
if err := p.Batch.Read(iprot); err != nil {
return thrift.PrependError(fmt.Sprintf("%T error reading struct: ", p.Batch), err)
}
return nil
}
func (p *AgentEmitBatchArgs) Write(oprot thrift.TProtocol) error {
if err := oprot.WriteStructBegin("emitBatch_args"); err != nil {
return thrift.PrependError(fmt.Sprintf("%T write struct begin error: ", p), err)
}
if err := p.writeField1(oprot); err != nil {
return err
}
if err := oprot.WriteFieldStop(); err != nil {
return thrift.PrependError("write field stop error: ", err)
}
if err := oprot.WriteStructEnd(); err != nil {
return thrift.PrependError("write struct stop error: ", err)
}
return nil
}
func (p *AgentEmitBatchArgs) writeField1(oprot thrift.TProtocol) (err error) {
if err := oprot.WriteFieldBegin("batch", thrift.STRUCT, 1); err != nil {
return thrift.PrependError(fmt.Sprintf("%T write field begin error 1:batch: ", p), err)
}
if err := p.Batch.Write(oprot); err != nil {
return thrift.PrependError(fmt.Sprintf("%T error writing struct: ", p.Batch), err)
}
if err := oprot.WriteFieldEnd(); err != nil {
return thrift.PrependError(fmt.Sprintf("%T write field end error 1:batch: ", p), err)
}
return err
}
func (p *AgentEmitBatchArgs) String() string {
if p == nil {
return "<nil>"
}
return fmt.Sprintf("AgentEmitBatchArgs(%+v)", *p)
}

View File

@ -1,18 +1,23 @@
// Autogenerated by Thrift Compiler (0.9.3) // Code generated by Thrift Compiler (0.14.1). DO NOT EDIT.
// DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
package jaeger package jaeger
import ( import(
"bytes" "bytes"
"context"
"fmt" "fmt"
"time"
"github.com/uber/jaeger-client-go/thrift" "github.com/uber/jaeger-client-go/thrift"
) )
// (needed to ensure safety because of naive import list construction.) // (needed to ensure safety because of naive import list construction.)
var _ = thrift.ZERO var _ = thrift.ZERO
var _ = fmt.Printf var _ = fmt.Printf
var _ = context.Background
var _ = time.Now
var _ = bytes.Equal var _ = bytes.Equal
func init() { func init() {
} }

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,6 @@
// Code generated by Thrift Compiler (0.14.1). DO NOT EDIT.
package zipkincore
var GoUnusedProtection__ int;

File diff suppressed because it is too large Load Diff

View File

@ -1,446 +0,0 @@
// Autogenerated by Thrift Compiler (0.9.3)
// DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
package zipkincore
import (
"bytes"
"fmt"
"github.com/uber/jaeger-client-go/thrift"
)
// (needed to ensure safety because of naive import list construction.)
var _ = thrift.ZERO
var _ = fmt.Printf
var _ = bytes.Equal
type ZipkinCollector interface {
// Parameters:
// - Spans
SubmitZipkinBatch(spans []*Span) (r []*Response, err error)
}
type ZipkinCollectorClient struct {
Transport thrift.TTransport
ProtocolFactory thrift.TProtocolFactory
InputProtocol thrift.TProtocol
OutputProtocol thrift.TProtocol
SeqId int32
}
func NewZipkinCollectorClientFactory(t thrift.TTransport, f thrift.TProtocolFactory) *ZipkinCollectorClient {
return &ZipkinCollectorClient{Transport: t,
ProtocolFactory: f,
InputProtocol: f.GetProtocol(t),
OutputProtocol: f.GetProtocol(t),
SeqId: 0,
}
}
func NewZipkinCollectorClientProtocol(t thrift.TTransport, iprot thrift.TProtocol, oprot thrift.TProtocol) *ZipkinCollectorClient {
return &ZipkinCollectorClient{Transport: t,
ProtocolFactory: nil,
InputProtocol: iprot,
OutputProtocol: oprot,
SeqId: 0,
}
}
// Parameters:
// - Spans
func (p *ZipkinCollectorClient) SubmitZipkinBatch(spans []*Span) (r []*Response, err error) {
if err = p.sendSubmitZipkinBatch(spans); err != nil {
return
}
return p.recvSubmitZipkinBatch()
}
func (p *ZipkinCollectorClient) sendSubmitZipkinBatch(spans []*Span) (err error) {
oprot := p.OutputProtocol
if oprot == nil {
oprot = p.ProtocolFactory.GetProtocol(p.Transport)
p.OutputProtocol = oprot
}
p.SeqId++
if err = oprot.WriteMessageBegin("submitZipkinBatch", thrift.CALL, p.SeqId); err != nil {
return
}
args := ZipkinCollectorSubmitZipkinBatchArgs{
Spans: spans,
}
if err = args.Write(oprot); err != nil {
return
}
if err = oprot.WriteMessageEnd(); err != nil {
return
}
return oprot.Flush()
}
func (p *ZipkinCollectorClient) recvSubmitZipkinBatch() (value []*Response, err error) {
iprot := p.InputProtocol
if iprot == nil {
iprot = p.ProtocolFactory.GetProtocol(p.Transport)
p.InputProtocol = iprot
}
method, mTypeId, seqId, err := iprot.ReadMessageBegin()
if err != nil {
return
}
if method != "submitZipkinBatch" {
err = thrift.NewTApplicationException(thrift.WRONG_METHOD_NAME, "submitZipkinBatch failed: wrong method name")
return
}
if p.SeqId != seqId {
err = thrift.NewTApplicationException(thrift.BAD_SEQUENCE_ID, "submitZipkinBatch failed: out of sequence response")
return
}
if mTypeId == thrift.EXCEPTION {
error2 := thrift.NewTApplicationException(thrift.UNKNOWN_APPLICATION_EXCEPTION, "Unknown Exception")
var error3 error
error3, err = error2.Read(iprot)
if err != nil {
return
}
if err = iprot.ReadMessageEnd(); err != nil {
return
}
err = error3
return
}
if mTypeId != thrift.REPLY {
err = thrift.NewTApplicationException(thrift.INVALID_MESSAGE_TYPE_EXCEPTION, "submitZipkinBatch failed: invalid message type")
return
}
result := ZipkinCollectorSubmitZipkinBatchResult{}
if err = result.Read(iprot); err != nil {
return
}
if err = iprot.ReadMessageEnd(); err != nil {
return
}
value = result.GetSuccess()
return
}
type ZipkinCollectorProcessor struct {
processorMap map[string]thrift.TProcessorFunction
handler ZipkinCollector
}
func (p *ZipkinCollectorProcessor) AddToProcessorMap(key string, processor thrift.TProcessorFunction) {
p.processorMap[key] = processor
}
func (p *ZipkinCollectorProcessor) GetProcessorFunction(key string) (processor thrift.TProcessorFunction, ok bool) {
processor, ok = p.processorMap[key]
return processor, ok
}
func (p *ZipkinCollectorProcessor) ProcessorMap() map[string]thrift.TProcessorFunction {
return p.processorMap
}
func NewZipkinCollectorProcessor(handler ZipkinCollector) *ZipkinCollectorProcessor {
self4 := &ZipkinCollectorProcessor{handler: handler, processorMap: make(map[string]thrift.TProcessorFunction)}
self4.processorMap["submitZipkinBatch"] = &zipkinCollectorProcessorSubmitZipkinBatch{handler: handler}
return self4
}
func (p *ZipkinCollectorProcessor) Process(iprot, oprot thrift.TProtocol) (success bool, err thrift.TException) {
name, _, seqId, err := iprot.ReadMessageBegin()
if err != nil {
return false, err
}
if processor, ok := p.GetProcessorFunction(name); ok {
return processor.Process(seqId, iprot, oprot)
}
iprot.Skip(thrift.STRUCT)
iprot.ReadMessageEnd()
x5 := thrift.NewTApplicationException(thrift.UNKNOWN_METHOD, "Unknown function "+name)
oprot.WriteMessageBegin(name, thrift.EXCEPTION, seqId)
x5.Write(oprot)
oprot.WriteMessageEnd()
oprot.Flush()
return false, x5
}
type zipkinCollectorProcessorSubmitZipkinBatch struct {
handler ZipkinCollector
}
func (p *zipkinCollectorProcessorSubmitZipkinBatch) Process(seqId int32, iprot, oprot thrift.TProtocol) (success bool, err thrift.TException) {
args := ZipkinCollectorSubmitZipkinBatchArgs{}
if err = args.Read(iprot); err != nil {
iprot.ReadMessageEnd()
x := thrift.NewTApplicationException(thrift.PROTOCOL_ERROR, err.Error())
oprot.WriteMessageBegin("submitZipkinBatch", thrift.EXCEPTION, seqId)
x.Write(oprot)
oprot.WriteMessageEnd()
oprot.Flush()
return false, err
}
iprot.ReadMessageEnd()
result := ZipkinCollectorSubmitZipkinBatchResult{}
var retval []*Response
var err2 error
if retval, err2 = p.handler.SubmitZipkinBatch(args.Spans); err2 != nil {
x := thrift.NewTApplicationException(thrift.INTERNAL_ERROR, "Internal error processing submitZipkinBatch: "+err2.Error())
oprot.WriteMessageBegin("submitZipkinBatch", thrift.EXCEPTION, seqId)
x.Write(oprot)
oprot.WriteMessageEnd()
oprot.Flush()
return true, err2
} else {
result.Success = retval
}
if err2 = oprot.WriteMessageBegin("submitZipkinBatch", thrift.REPLY, seqId); err2 != nil {
err = err2
}
if err2 = result.Write(oprot); err == nil && err2 != nil {
err = err2
}
if err2 = oprot.WriteMessageEnd(); err == nil && err2 != nil {
err = err2
}
if err2 = oprot.Flush(); err == nil && err2 != nil {
err = err2
}
if err != nil {
return
}
return true, err
}
// HELPER FUNCTIONS AND STRUCTURES
// Attributes:
// - Spans
type ZipkinCollectorSubmitZipkinBatchArgs struct {
Spans []*Span `thrift:"spans,1" json:"spans"`
}
func NewZipkinCollectorSubmitZipkinBatchArgs() *ZipkinCollectorSubmitZipkinBatchArgs {
return &ZipkinCollectorSubmitZipkinBatchArgs{}
}
func (p *ZipkinCollectorSubmitZipkinBatchArgs) GetSpans() []*Span {
return p.Spans
}
func (p *ZipkinCollectorSubmitZipkinBatchArgs) Read(iprot thrift.TProtocol) error {
if _, err := iprot.ReadStructBegin(); err != nil {
return thrift.PrependError(fmt.Sprintf("%T read error: ", p), err)
}
for {
_, fieldTypeId, fieldId, err := iprot.ReadFieldBegin()
if err != nil {
return thrift.PrependError(fmt.Sprintf("%T field %d read error: ", p, fieldId), err)
}
if fieldTypeId == thrift.STOP {
break
}
switch fieldId {
case 1:
if err := p.readField1(iprot); err != nil {
return err
}
default:
if err := iprot.Skip(fieldTypeId); err != nil {
return err
}
}
if err := iprot.ReadFieldEnd(); err != nil {
return err
}
}
if err := iprot.ReadStructEnd(); err != nil {
return thrift.PrependError(fmt.Sprintf("%T read struct end error: ", p), err)
}
return nil
}
func (p *ZipkinCollectorSubmitZipkinBatchArgs) readField1(iprot thrift.TProtocol) error {
_, size, err := iprot.ReadListBegin()
if err != nil {
return thrift.PrependError("error reading list begin: ", err)
}
tSlice := make([]*Span, 0, size)
p.Spans = tSlice
for i := 0; i < size; i++ {
_elem6 := &Span{}
if err := _elem6.Read(iprot); err != nil {
return thrift.PrependError(fmt.Sprintf("%T error reading struct: ", _elem6), err)
}
p.Spans = append(p.Spans, _elem6)
}
if err := iprot.ReadListEnd(); err != nil {
return thrift.PrependError("error reading list end: ", err)
}
return nil
}
func (p *ZipkinCollectorSubmitZipkinBatchArgs) Write(oprot thrift.TProtocol) error {
if err := oprot.WriteStructBegin("submitZipkinBatch_args"); err != nil {
return thrift.PrependError(fmt.Sprintf("%T write struct begin error: ", p), err)
}
if err := p.writeField1(oprot); err != nil {
return err
}
if err := oprot.WriteFieldStop(); err != nil {
return thrift.PrependError("write field stop error: ", err)
}
if err := oprot.WriteStructEnd(); err != nil {
return thrift.PrependError("write struct stop error: ", err)
}
return nil
}
func (p *ZipkinCollectorSubmitZipkinBatchArgs) writeField1(oprot thrift.TProtocol) (err error) {
if err := oprot.WriteFieldBegin("spans", thrift.LIST, 1); err != nil {
return thrift.PrependError(fmt.Sprintf("%T write field begin error 1:spans: ", p), err)
}
if err := oprot.WriteListBegin(thrift.STRUCT, len(p.Spans)); err != nil {
return thrift.PrependError("error writing list begin: ", err)
}
for _, v := range p.Spans {
if err := v.Write(oprot); err != nil {
return thrift.PrependError(fmt.Sprintf("%T error writing struct: ", v), err)
}
}
if err := oprot.WriteListEnd(); err != nil {
return thrift.PrependError("error writing list end: ", err)
}
if err := oprot.WriteFieldEnd(); err != nil {
return thrift.PrependError(fmt.Sprintf("%T write field end error 1:spans: ", p), err)
}
return err
}
func (p *ZipkinCollectorSubmitZipkinBatchArgs) String() string {
if p == nil {
return "<nil>"
}
return fmt.Sprintf("ZipkinCollectorSubmitZipkinBatchArgs(%+v)", *p)
}
// Attributes:
// - Success
type ZipkinCollectorSubmitZipkinBatchResult struct {
Success []*Response `thrift:"success,0" json:"success,omitempty"`
}
func NewZipkinCollectorSubmitZipkinBatchResult() *ZipkinCollectorSubmitZipkinBatchResult {
return &ZipkinCollectorSubmitZipkinBatchResult{}
}
var ZipkinCollectorSubmitZipkinBatchResult_Success_DEFAULT []*Response
func (p *ZipkinCollectorSubmitZipkinBatchResult) GetSuccess() []*Response {
return p.Success
}
func (p *ZipkinCollectorSubmitZipkinBatchResult) IsSetSuccess() bool {
return p.Success != nil
}
func (p *ZipkinCollectorSubmitZipkinBatchResult) Read(iprot thrift.TProtocol) error {
if _, err := iprot.ReadStructBegin(); err != nil {
return thrift.PrependError(fmt.Sprintf("%T read error: ", p), err)
}
for {
_, fieldTypeId, fieldId, err := iprot.ReadFieldBegin()
if err != nil {
return thrift.PrependError(fmt.Sprintf("%T field %d read error: ", p, fieldId), err)
}
if fieldTypeId == thrift.STOP {
break
}
switch fieldId {
case 0:
if err := p.readField0(iprot); err != nil {
return err
}
default:
if err := iprot.Skip(fieldTypeId); err != nil {
return err
}
}
if err := iprot.ReadFieldEnd(); err != nil {
return err
}
}
if err := iprot.ReadStructEnd(); err != nil {
return thrift.PrependError(fmt.Sprintf("%T read struct end error: ", p), err)
}
return nil
}
func (p *ZipkinCollectorSubmitZipkinBatchResult) readField0(iprot thrift.TProtocol) error {
_, size, err := iprot.ReadListBegin()
if err != nil {
return thrift.PrependError("error reading list begin: ", err)
}
tSlice := make([]*Response, 0, size)
p.Success = tSlice
for i := 0; i < size; i++ {
_elem7 := &Response{}
if err := _elem7.Read(iprot); err != nil {
return thrift.PrependError(fmt.Sprintf("%T error reading struct: ", _elem7), err)
}
p.Success = append(p.Success, _elem7)
}
if err := iprot.ReadListEnd(); err != nil {
return thrift.PrependError("error reading list end: ", err)
}
return nil
}
func (p *ZipkinCollectorSubmitZipkinBatchResult) Write(oprot thrift.TProtocol) error {
if err := oprot.WriteStructBegin("submitZipkinBatch_result"); err != nil {
return thrift.PrependError(fmt.Sprintf("%T write struct begin error: ", p), err)
}
if err := p.writeField0(oprot); err != nil {
return err
}
if err := oprot.WriteFieldStop(); err != nil {
return thrift.PrependError("write field stop error: ", err)
}
if err := oprot.WriteStructEnd(); err != nil {
return thrift.PrependError("write struct stop error: ", err)
}
return nil
}
func (p *ZipkinCollectorSubmitZipkinBatchResult) writeField0(oprot thrift.TProtocol) (err error) {
if p.IsSetSuccess() {
if err := oprot.WriteFieldBegin("success", thrift.LIST, 0); err != nil {
return thrift.PrependError(fmt.Sprintf("%T write field begin error 0:success: ", p), err)
}
if err := oprot.WriteListBegin(thrift.STRUCT, len(p.Success)); err != nil {
return thrift.PrependError("error writing list begin: ", err)
}
for _, v := range p.Success {
if err := v.Write(oprot); err != nil {
return thrift.PrependError(fmt.Sprintf("%T error writing struct: ", v), err)
}
}
if err := oprot.WriteListEnd(); err != nil {
return thrift.PrependError("error writing list end: ", err)
}
if err := oprot.WriteFieldEnd(); err != nil {
return thrift.PrependError(fmt.Sprintf("%T write field end error 0:success: ", p), err)
}
}
return err
}
func (p *ZipkinCollectorSubmitZipkinBatchResult) String() string {
if p == nil {
return "<nil>"
}
return fmt.Sprintf("ZipkinCollectorSubmitZipkinBatchResult(%+v)", *p)
}

View File

@ -1,17 +1,20 @@
// Autogenerated by Thrift Compiler (0.9.3) // Code generated by Thrift Compiler (0.14.1). DO NOT EDIT.
// DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
package zipkincore package zipkincore
import ( import(
"bytes" "bytes"
"context"
"fmt" "fmt"
"time"
"github.com/uber/jaeger-client-go/thrift" "github.com/uber/jaeger-client-go/thrift"
) )
// (needed to ensure safety because of naive import list construction.) // (needed to ensure safety because of naive import list construction.)
var _ = thrift.ZERO var _ = thrift.ZERO
var _ = fmt.Printf var _ = fmt.Printf
var _ = context.Background
var _ = time.Now
var _ = bytes.Equal var _ = bytes.Equal
const CLIENT_SEND = "cs" const CLIENT_SEND = "cs"
@ -33,3 +36,4 @@ const MESSAGE_ADDR = "ma"
func init() { func init() {
} }

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,11 @@
# Apache Thrift # Apache Thrift
This is a partial copy of Apache Thrift v0.10 (https://github.com/apache/thrift/commit/b2a4d4ae21c789b689dd162deb819665567f481c). This is a partial copy of Apache Thrift v0.14.1 (https://github.com/apache/thrift/commit/f6fa1794539e68ac294038ac388d6bde40a6c237).
It is vendored code to avoid compatibility issues introduced in Thrift v0.11. It is vendored code to avoid compatibility issues with Thrift versions.
See https://github.com/jaegertracing/jaeger-client-go/pull/303. The file logger.go is modified to remove dependency on "testing" (see Issue #585).
See:
* https://github.com/jaegertracing/jaeger-client-go/pull/584
* https://github.com/jaegertracing/jaeger-client-go/pull/303

View File

@ -19,6 +19,10 @@
package thrift package thrift
import (
"context"
)
const ( const (
UNKNOWN_APPLICATION_EXCEPTION = 0 UNKNOWN_APPLICATION_EXCEPTION = 0
UNKNOWN_METHOD = 1 UNKNOWN_METHOD = 1
@ -28,14 +32,31 @@ const (
MISSING_RESULT = 5 MISSING_RESULT = 5
INTERNAL_ERROR = 6 INTERNAL_ERROR = 6
PROTOCOL_ERROR = 7 PROTOCOL_ERROR = 7
INVALID_TRANSFORM = 8
INVALID_PROTOCOL = 9
UNSUPPORTED_CLIENT_TYPE = 10
) )
var defaultApplicationExceptionMessage = map[int32]string{
UNKNOWN_APPLICATION_EXCEPTION: "unknown application exception",
UNKNOWN_METHOD: "unknown method",
INVALID_MESSAGE_TYPE_EXCEPTION: "invalid message type",
WRONG_METHOD_NAME: "wrong method name",
BAD_SEQUENCE_ID: "bad sequence ID",
MISSING_RESULT: "missing result",
INTERNAL_ERROR: "unknown internal error",
PROTOCOL_ERROR: "unknown protocol error",
INVALID_TRANSFORM: "Invalid transform",
INVALID_PROTOCOL: "Invalid protocol",
UNSUPPORTED_CLIENT_TYPE: "Unsupported client type",
}
// Application level Thrift exception // Application level Thrift exception
type TApplicationException interface { type TApplicationException interface {
TException TException
TypeId() int32 TypeId() int32
Read(iprot TProtocol) (TApplicationException, error) Read(ctx context.Context, iprot TProtocol) error
Write(oprot TProtocol) error Write(ctx context.Context, oprot TProtocol) error
} }
type tApplicationException struct { type tApplicationException struct {
@ -43,8 +64,17 @@ type tApplicationException struct {
type_ int32 type_ int32
} }
var _ TApplicationException = (*tApplicationException)(nil)
func (tApplicationException) TExceptionType() TExceptionType {
return TExceptionTypeApplication
}
func (e tApplicationException) Error() string { func (e tApplicationException) Error() string {
return e.message if e.message != "" {
return e.message
}
return defaultApplicationExceptionMessage[e.type_]
} }
func NewTApplicationException(type_ int32, message string) TApplicationException { func NewTApplicationException(type_ int32, message string) TApplicationException {
@ -55,19 +85,20 @@ func (p *tApplicationException) TypeId() int32 {
return p.type_ return p.type_
} }
func (p *tApplicationException) Read(iprot TProtocol) (TApplicationException, error) { func (p *tApplicationException) Read(ctx context.Context, iprot TProtocol) error {
_, err := iprot.ReadStructBegin() // TODO: this should really be generated by the compiler
_, err := iprot.ReadStructBegin(ctx)
if err != nil { if err != nil {
return nil, err return err
} }
message := "" message := ""
type_ := int32(UNKNOWN_APPLICATION_EXCEPTION) type_ := int32(UNKNOWN_APPLICATION_EXCEPTION)
for { for {
_, ttype, id, err := iprot.ReadFieldBegin() _, ttype, id, err := iprot.ReadFieldBegin(ctx)
if err != nil { if err != nil {
return nil, err return err
} }
if ttype == STOP { if ttype == STOP {
break break
@ -75,68 +106,75 @@ func (p *tApplicationException) Read(iprot TProtocol) (TApplicationException, er
switch id { switch id {
case 1: case 1:
if ttype == STRING { if ttype == STRING {
if message, err = iprot.ReadString(); err != nil { if message, err = iprot.ReadString(ctx); err != nil {
return nil, err return err
} }
} else { } else {
if err = SkipDefaultDepth(iprot, ttype); err != nil { if err = SkipDefaultDepth(ctx, iprot, ttype); err != nil {
return nil, err return err
} }
} }
case 2: case 2:
if ttype == I32 { if ttype == I32 {
if type_, err = iprot.ReadI32(); err != nil { if type_, err = iprot.ReadI32(ctx); err != nil {
return nil, err return err
} }
} else { } else {
if err = SkipDefaultDepth(iprot, ttype); err != nil { if err = SkipDefaultDepth(ctx, iprot, ttype); err != nil {
return nil, err return err
} }
} }
default: default:
if err = SkipDefaultDepth(iprot, ttype); err != nil { if err = SkipDefaultDepth(ctx, iprot, ttype); err != nil {
return nil, err return err
} }
} }
if err = iprot.ReadFieldEnd(); err != nil { if err = iprot.ReadFieldEnd(ctx); err != nil {
return nil, err return err
} }
} }
return NewTApplicationException(type_, message), iprot.ReadStructEnd() if err := iprot.ReadStructEnd(ctx); err != nil {
return err
}
p.message = message
p.type_ = type_
return nil
} }
func (p *tApplicationException) Write(oprot TProtocol) (err error) { func (p *tApplicationException) Write(ctx context.Context, oprot TProtocol) (err error) {
err = oprot.WriteStructBegin("TApplicationException") err = oprot.WriteStructBegin(ctx, "TApplicationException")
if len(p.Error()) > 0 { if len(p.Error()) > 0 {
err = oprot.WriteFieldBegin("message", STRING, 1) err = oprot.WriteFieldBegin(ctx, "message", STRING, 1)
if err != nil { if err != nil {
return return
} }
err = oprot.WriteString(p.Error()) err = oprot.WriteString(ctx, p.Error())
if err != nil { if err != nil {
return return
} }
err = oprot.WriteFieldEnd() err = oprot.WriteFieldEnd(ctx)
if err != nil { if err != nil {
return return
} }
} }
err = oprot.WriteFieldBegin("type", I32, 2) err = oprot.WriteFieldBegin(ctx, "type", I32, 2)
if err != nil { if err != nil {
return return
} }
err = oprot.WriteI32(p.type_) err = oprot.WriteI32(ctx, p.type_)
if err != nil { if err != nil {
return return
} }
err = oprot.WriteFieldEnd() err = oprot.WriteFieldEnd(ctx)
if err != nil { if err != nil {
return return
} }
err = oprot.WriteFieldStop() err = oprot.WriteFieldStop(ctx)
if err != nil { if err != nil {
return return
} }
err = oprot.WriteStructEnd() err = oprot.WriteStructEnd(ctx)
return return
} }

View File

@ -21,6 +21,7 @@ package thrift
import ( import (
"bytes" "bytes"
"context"
"encoding/binary" "encoding/binary"
"errors" "errors"
"fmt" "fmt"
@ -31,190 +32,220 @@ import (
type TBinaryProtocol struct { type TBinaryProtocol struct {
trans TRichTransport trans TRichTransport
origTransport TTransport origTransport TTransport
reader io.Reader cfg *TConfiguration
writer io.Writer
strictRead bool
strictWrite bool
buffer [64]byte buffer [64]byte
} }
type TBinaryProtocolFactory struct { type TBinaryProtocolFactory struct {
strictRead bool cfg *TConfiguration
strictWrite bool
} }
// Deprecated: Use NewTBinaryProtocolConf instead.
func NewTBinaryProtocolTransport(t TTransport) *TBinaryProtocol { func NewTBinaryProtocolTransport(t TTransport) *TBinaryProtocol {
return NewTBinaryProtocol(t, false, true) return NewTBinaryProtocolConf(t, &TConfiguration{
noPropagation: true,
})
} }
// Deprecated: Use NewTBinaryProtocolConf instead.
func NewTBinaryProtocol(t TTransport, strictRead, strictWrite bool) *TBinaryProtocol { func NewTBinaryProtocol(t TTransport, strictRead, strictWrite bool) *TBinaryProtocol {
p := &TBinaryProtocol{origTransport: t, strictRead: strictRead, strictWrite: strictWrite} return NewTBinaryProtocolConf(t, &TConfiguration{
TBinaryStrictRead: &strictRead,
TBinaryStrictWrite: &strictWrite,
noPropagation: true,
})
}
func NewTBinaryProtocolConf(t TTransport, conf *TConfiguration) *TBinaryProtocol {
PropagateTConfiguration(t, conf)
p := &TBinaryProtocol{
origTransport: t,
cfg: conf,
}
if et, ok := t.(TRichTransport); ok { if et, ok := t.(TRichTransport); ok {
p.trans = et p.trans = et
} else { } else {
p.trans = NewTRichTransport(t) p.trans = NewTRichTransport(t)
} }
p.reader = p.trans
p.writer = p.trans
return p return p
} }
// Deprecated: Use NewTBinaryProtocolFactoryConf instead.
func NewTBinaryProtocolFactoryDefault() *TBinaryProtocolFactory { func NewTBinaryProtocolFactoryDefault() *TBinaryProtocolFactory {
return NewTBinaryProtocolFactory(false, true) return NewTBinaryProtocolFactoryConf(&TConfiguration{
noPropagation: true,
})
} }
// Deprecated: Use NewTBinaryProtocolFactoryConf instead.
func NewTBinaryProtocolFactory(strictRead, strictWrite bool) *TBinaryProtocolFactory { func NewTBinaryProtocolFactory(strictRead, strictWrite bool) *TBinaryProtocolFactory {
return &TBinaryProtocolFactory{strictRead: strictRead, strictWrite: strictWrite} return NewTBinaryProtocolFactoryConf(&TConfiguration{
TBinaryStrictRead: &strictRead,
TBinaryStrictWrite: &strictWrite,
noPropagation: true,
})
}
func NewTBinaryProtocolFactoryConf(conf *TConfiguration) *TBinaryProtocolFactory {
return &TBinaryProtocolFactory{
cfg: conf,
}
} }
func (p *TBinaryProtocolFactory) GetProtocol(t TTransport) TProtocol { func (p *TBinaryProtocolFactory) GetProtocol(t TTransport) TProtocol {
return NewTBinaryProtocol(t, p.strictRead, p.strictWrite) return NewTBinaryProtocolConf(t, p.cfg)
}
func (p *TBinaryProtocolFactory) SetTConfiguration(conf *TConfiguration) {
p.cfg = conf
} }
/** /**
* Writing Methods * Writing Methods
*/ */
func (p *TBinaryProtocol) WriteMessageBegin(name string, typeId TMessageType, seqId int32) error { func (p *TBinaryProtocol) WriteMessageBegin(ctx context.Context, name string, typeId TMessageType, seqId int32) error {
if p.strictWrite { if p.cfg.GetTBinaryStrictWrite() {
version := uint32(VERSION_1) | uint32(typeId) version := uint32(VERSION_1) | uint32(typeId)
e := p.WriteI32(int32(version)) e := p.WriteI32(ctx, int32(version))
if e != nil { if e != nil {
return e return e
} }
e = p.WriteString(name) e = p.WriteString(ctx, name)
if e != nil { if e != nil {
return e return e
} }
e = p.WriteI32(seqId) e = p.WriteI32(ctx, seqId)
return e return e
} else { } else {
e := p.WriteString(name) e := p.WriteString(ctx, name)
if e != nil { if e != nil {
return e return e
} }
e = p.WriteByte(int8(typeId)) e = p.WriteByte(ctx, int8(typeId))
if e != nil { if e != nil {
return e return e
} }
e = p.WriteI32(seqId) e = p.WriteI32(ctx, seqId)
return e return e
} }
return nil return nil
} }
func (p *TBinaryProtocol) WriteMessageEnd() error { func (p *TBinaryProtocol) WriteMessageEnd(ctx context.Context) error {
return nil return nil
} }
func (p *TBinaryProtocol) WriteStructBegin(name string) error { func (p *TBinaryProtocol) WriteStructBegin(ctx context.Context, name string) error {
return nil return nil
} }
func (p *TBinaryProtocol) WriteStructEnd() error { func (p *TBinaryProtocol) WriteStructEnd(ctx context.Context) error {
return nil return nil
} }
func (p *TBinaryProtocol) WriteFieldBegin(name string, typeId TType, id int16) error { func (p *TBinaryProtocol) WriteFieldBegin(ctx context.Context, name string, typeId TType, id int16) error {
e := p.WriteByte(int8(typeId)) e := p.WriteByte(ctx, int8(typeId))
if e != nil { if e != nil {
return e return e
} }
e = p.WriteI16(id) e = p.WriteI16(ctx, id)
return e return e
} }
func (p *TBinaryProtocol) WriteFieldEnd() error { func (p *TBinaryProtocol) WriteFieldEnd(ctx context.Context) error {
return nil return nil
} }
func (p *TBinaryProtocol) WriteFieldStop() error { func (p *TBinaryProtocol) WriteFieldStop(ctx context.Context) error {
e := p.WriteByte(STOP) e := p.WriteByte(ctx, STOP)
return e return e
} }
func (p *TBinaryProtocol) WriteMapBegin(keyType TType, valueType TType, size int) error { func (p *TBinaryProtocol) WriteMapBegin(ctx context.Context, keyType TType, valueType TType, size int) error {
e := p.WriteByte(int8(keyType)) e := p.WriteByte(ctx, int8(keyType))
if e != nil { if e != nil {
return e return e
} }
e = p.WriteByte(int8(valueType)) e = p.WriteByte(ctx, int8(valueType))
if e != nil { if e != nil {
return e return e
} }
e = p.WriteI32(int32(size)) e = p.WriteI32(ctx, int32(size))
return e return e
} }
func (p *TBinaryProtocol) WriteMapEnd() error { func (p *TBinaryProtocol) WriteMapEnd(ctx context.Context) error {
return nil return nil
} }
func (p *TBinaryProtocol) WriteListBegin(elemType TType, size int) error { func (p *TBinaryProtocol) WriteListBegin(ctx context.Context, elemType TType, size int) error {
e := p.WriteByte(int8(elemType)) e := p.WriteByte(ctx, int8(elemType))
if e != nil { if e != nil {
return e return e
} }
e = p.WriteI32(int32(size)) e = p.WriteI32(ctx, int32(size))
return e return e
} }
func (p *TBinaryProtocol) WriteListEnd() error { func (p *TBinaryProtocol) WriteListEnd(ctx context.Context) error {
return nil return nil
} }
func (p *TBinaryProtocol) WriteSetBegin(elemType TType, size int) error { func (p *TBinaryProtocol) WriteSetBegin(ctx context.Context, elemType TType, size int) error {
e := p.WriteByte(int8(elemType)) e := p.WriteByte(ctx, int8(elemType))
if e != nil { if e != nil {
return e return e
} }
e = p.WriteI32(int32(size)) e = p.WriteI32(ctx, int32(size))
return e return e
} }
func (p *TBinaryProtocol) WriteSetEnd() error { func (p *TBinaryProtocol) WriteSetEnd(ctx context.Context) error {
return nil return nil
} }
func (p *TBinaryProtocol) WriteBool(value bool) error { func (p *TBinaryProtocol) WriteBool(ctx context.Context, value bool) error {
if value { if value {
return p.WriteByte(1) return p.WriteByte(ctx, 1)
} }
return p.WriteByte(0) return p.WriteByte(ctx, 0)
} }
func (p *TBinaryProtocol) WriteByte(value int8) error { func (p *TBinaryProtocol) WriteByte(ctx context.Context, value int8) error {
e := p.trans.WriteByte(byte(value)) e := p.trans.WriteByte(byte(value))
return NewTProtocolException(e) return NewTProtocolException(e)
} }
func (p *TBinaryProtocol) WriteI16(value int16) error { func (p *TBinaryProtocol) WriteI16(ctx context.Context, value int16) error {
v := p.buffer[0:2] v := p.buffer[0:2]
binary.BigEndian.PutUint16(v, uint16(value)) binary.BigEndian.PutUint16(v, uint16(value))
_, e := p.writer.Write(v) _, e := p.trans.Write(v)
return NewTProtocolException(e) return NewTProtocolException(e)
} }
func (p *TBinaryProtocol) WriteI32(value int32) error { func (p *TBinaryProtocol) WriteI32(ctx context.Context, value int32) error {
v := p.buffer[0:4] v := p.buffer[0:4]
binary.BigEndian.PutUint32(v, uint32(value)) binary.BigEndian.PutUint32(v, uint32(value))
_, e := p.writer.Write(v) _, e := p.trans.Write(v)
return NewTProtocolException(e) return NewTProtocolException(e)
} }
func (p *TBinaryProtocol) WriteI64(value int64) error { func (p *TBinaryProtocol) WriteI64(ctx context.Context, value int64) error {
v := p.buffer[0:8] v := p.buffer[0:8]
binary.BigEndian.PutUint64(v, uint64(value)) binary.BigEndian.PutUint64(v, uint64(value))
_, err := p.writer.Write(v) _, err := p.trans.Write(v)
return NewTProtocolException(err) return NewTProtocolException(err)
} }
func (p *TBinaryProtocol) WriteDouble(value float64) error { func (p *TBinaryProtocol) WriteDouble(ctx context.Context, value float64) error {
return p.WriteI64(int64(math.Float64bits(value))) return p.WriteI64(ctx, int64(math.Float64bits(value)))
} }
func (p *TBinaryProtocol) WriteString(value string) error { func (p *TBinaryProtocol) WriteString(ctx context.Context, value string) error {
e := p.WriteI32(int32(len(value))) e := p.WriteI32(ctx, int32(len(value)))
if e != nil { if e != nil {
return e return e
} }
@ -222,12 +253,12 @@ func (p *TBinaryProtocol) WriteString(value string) error {
return NewTProtocolException(err) return NewTProtocolException(err)
} }
func (p *TBinaryProtocol) WriteBinary(value []byte) error { func (p *TBinaryProtocol) WriteBinary(ctx context.Context, value []byte) error {
e := p.WriteI32(int32(len(value))) e := p.WriteI32(ctx, int32(len(value)))
if e != nil { if e != nil {
return e return e
} }
_, err := p.writer.Write(value) _, err := p.trans.Write(value)
return NewTProtocolException(err) return NewTProtocolException(err)
} }
@ -235,8 +266,8 @@ func (p *TBinaryProtocol) WriteBinary(value []byte) error {
* Reading methods * Reading methods
*/ */
func (p *TBinaryProtocol) ReadMessageBegin() (name string, typeId TMessageType, seqId int32, err error) { func (p *TBinaryProtocol) ReadMessageBegin(ctx context.Context) (name string, typeId TMessageType, seqId int32, err error) {
size, e := p.ReadI32() size, e := p.ReadI32(ctx)
if e != nil { if e != nil {
return "", typeId, 0, NewTProtocolException(e) return "", typeId, 0, NewTProtocolException(e)
} }
@ -246,79 +277,79 @@ func (p *TBinaryProtocol) ReadMessageBegin() (name string, typeId TMessageType,
if version != VERSION_1 { if version != VERSION_1 {
return name, typeId, seqId, NewTProtocolExceptionWithType(BAD_VERSION, fmt.Errorf("Bad version in ReadMessageBegin")) return name, typeId, seqId, NewTProtocolExceptionWithType(BAD_VERSION, fmt.Errorf("Bad version in ReadMessageBegin"))
} }
name, e = p.ReadString() name, e = p.ReadString(ctx)
if e != nil { if e != nil {
return name, typeId, seqId, NewTProtocolException(e) return name, typeId, seqId, NewTProtocolException(e)
} }
seqId, e = p.ReadI32() seqId, e = p.ReadI32(ctx)
if e != nil { if e != nil {
return name, typeId, seqId, NewTProtocolException(e) return name, typeId, seqId, NewTProtocolException(e)
} }
return name, typeId, seqId, nil return name, typeId, seqId, nil
} }
if p.strictRead { if p.cfg.GetTBinaryStrictRead() {
return name, typeId, seqId, NewTProtocolExceptionWithType(BAD_VERSION, fmt.Errorf("Missing version in ReadMessageBegin")) return name, typeId, seqId, NewTProtocolExceptionWithType(BAD_VERSION, fmt.Errorf("Missing version in ReadMessageBegin"))
} }
name, e2 := p.readStringBody(size) name, e2 := p.readStringBody(size)
if e2 != nil { if e2 != nil {
return name, typeId, seqId, e2 return name, typeId, seqId, e2
} }
b, e3 := p.ReadByte() b, e3 := p.ReadByte(ctx)
if e3 != nil { if e3 != nil {
return name, typeId, seqId, e3 return name, typeId, seqId, e3
} }
typeId = TMessageType(b) typeId = TMessageType(b)
seqId, e4 := p.ReadI32() seqId, e4 := p.ReadI32(ctx)
if e4 != nil { if e4 != nil {
return name, typeId, seqId, e4 return name, typeId, seqId, e4
} }
return name, typeId, seqId, nil return name, typeId, seqId, nil
} }
func (p *TBinaryProtocol) ReadMessageEnd() error { func (p *TBinaryProtocol) ReadMessageEnd(ctx context.Context) error {
return nil return nil
} }
func (p *TBinaryProtocol) ReadStructBegin() (name string, err error) { func (p *TBinaryProtocol) ReadStructBegin(ctx context.Context) (name string, err error) {
return return
} }
func (p *TBinaryProtocol) ReadStructEnd() error { func (p *TBinaryProtocol) ReadStructEnd(ctx context.Context) error {
return nil return nil
} }
func (p *TBinaryProtocol) ReadFieldBegin() (name string, typeId TType, seqId int16, err error) { func (p *TBinaryProtocol) ReadFieldBegin(ctx context.Context) (name string, typeId TType, seqId int16, err error) {
t, err := p.ReadByte() t, err := p.ReadByte(ctx)
typeId = TType(t) typeId = TType(t)
if err != nil { if err != nil {
return name, typeId, seqId, err return name, typeId, seqId, err
} }
if t != STOP { if t != STOP {
seqId, err = p.ReadI16() seqId, err = p.ReadI16(ctx)
} }
return name, typeId, seqId, err return name, typeId, seqId, err
} }
func (p *TBinaryProtocol) ReadFieldEnd() error { func (p *TBinaryProtocol) ReadFieldEnd(ctx context.Context) error {
return nil return nil
} }
var invalidDataLength = NewTProtocolExceptionWithType(INVALID_DATA, errors.New("Invalid data length")) var invalidDataLength = NewTProtocolExceptionWithType(INVALID_DATA, errors.New("Invalid data length"))
func (p *TBinaryProtocol) ReadMapBegin() (kType, vType TType, size int, err error) { func (p *TBinaryProtocol) ReadMapBegin(ctx context.Context) (kType, vType TType, size int, err error) {
k, e := p.ReadByte() k, e := p.ReadByte(ctx)
if e != nil { if e != nil {
err = NewTProtocolException(e) err = NewTProtocolException(e)
return return
} }
kType = TType(k) kType = TType(k)
v, e := p.ReadByte() v, e := p.ReadByte(ctx)
if e != nil { if e != nil {
err = NewTProtocolException(e) err = NewTProtocolException(e)
return return
} }
vType = TType(v) vType = TType(v)
size32, e := p.ReadI32() size32, e := p.ReadI32(ctx)
if e != nil { if e != nil {
err = NewTProtocolException(e) err = NewTProtocolException(e)
return return
@ -331,18 +362,18 @@ func (p *TBinaryProtocol) ReadMapBegin() (kType, vType TType, size int, err erro
return kType, vType, size, nil return kType, vType, size, nil
} }
func (p *TBinaryProtocol) ReadMapEnd() error { func (p *TBinaryProtocol) ReadMapEnd(ctx context.Context) error {
return nil return nil
} }
func (p *TBinaryProtocol) ReadListBegin() (elemType TType, size int, err error) { func (p *TBinaryProtocol) ReadListBegin(ctx context.Context) (elemType TType, size int, err error) {
b, e := p.ReadByte() b, e := p.ReadByte(ctx)
if e != nil { if e != nil {
err = NewTProtocolException(e) err = NewTProtocolException(e)
return return
} }
elemType = TType(b) elemType = TType(b)
size32, e := p.ReadI32() size32, e := p.ReadI32(ctx)
if e != nil { if e != nil {
err = NewTProtocolException(e) err = NewTProtocolException(e)
return return
@ -356,18 +387,18 @@ func (p *TBinaryProtocol) ReadListBegin() (elemType TType, size int, err error)
return return
} }
func (p *TBinaryProtocol) ReadListEnd() error { func (p *TBinaryProtocol) ReadListEnd(ctx context.Context) error {
return nil return nil
} }
func (p *TBinaryProtocol) ReadSetBegin() (elemType TType, size int, err error) { func (p *TBinaryProtocol) ReadSetBegin(ctx context.Context) (elemType TType, size int, err error) {
b, e := p.ReadByte() b, e := p.ReadByte(ctx)
if e != nil { if e != nil {
err = NewTProtocolException(e) err = NewTProtocolException(e)
return return
} }
elemType = TType(b) elemType = TType(b)
size32, e := p.ReadI32() size32, e := p.ReadI32(ctx)
if e != nil { if e != nil {
err = NewTProtocolException(e) err = NewTProtocolException(e)
return return
@ -380,12 +411,12 @@ func (p *TBinaryProtocol) ReadSetBegin() (elemType TType, size int, err error) {
return elemType, size, nil return elemType, size, nil
} }
func (p *TBinaryProtocol) ReadSetEnd() error { func (p *TBinaryProtocol) ReadSetEnd(ctx context.Context) error {
return nil return nil
} }
func (p *TBinaryProtocol) ReadBool() (bool, error) { func (p *TBinaryProtocol) ReadBool(ctx context.Context) (bool, error) {
b, e := p.ReadByte() b, e := p.ReadByte(ctx)
v := true v := true
if b != 1 { if b != 1 {
v = false v = false
@ -393,122 +424,132 @@ func (p *TBinaryProtocol) ReadBool() (bool, error) {
return v, e return v, e
} }
func (p *TBinaryProtocol) ReadByte() (int8, error) { func (p *TBinaryProtocol) ReadByte(ctx context.Context) (int8, error) {
v, err := p.trans.ReadByte() v, err := p.trans.ReadByte()
return int8(v), err return int8(v), err
} }
func (p *TBinaryProtocol) ReadI16() (value int16, err error) { func (p *TBinaryProtocol) ReadI16(ctx context.Context) (value int16, err error) {
buf := p.buffer[0:2] buf := p.buffer[0:2]
err = p.readAll(buf) err = p.readAll(ctx, buf)
value = int16(binary.BigEndian.Uint16(buf)) value = int16(binary.BigEndian.Uint16(buf))
return value, err return value, err
} }
func (p *TBinaryProtocol) ReadI32() (value int32, err error) { func (p *TBinaryProtocol) ReadI32(ctx context.Context) (value int32, err error) {
buf := p.buffer[0:4] buf := p.buffer[0:4]
err = p.readAll(buf) err = p.readAll(ctx, buf)
value = int32(binary.BigEndian.Uint32(buf)) value = int32(binary.BigEndian.Uint32(buf))
return value, err return value, err
} }
func (p *TBinaryProtocol) ReadI64() (value int64, err error) { func (p *TBinaryProtocol) ReadI64(ctx context.Context) (value int64, err error) {
buf := p.buffer[0:8] buf := p.buffer[0:8]
err = p.readAll(buf) err = p.readAll(ctx, buf)
value = int64(binary.BigEndian.Uint64(buf)) value = int64(binary.BigEndian.Uint64(buf))
return value, err return value, err
} }
func (p *TBinaryProtocol) ReadDouble() (value float64, err error) { func (p *TBinaryProtocol) ReadDouble(ctx context.Context) (value float64, err error) {
buf := p.buffer[0:8] buf := p.buffer[0:8]
err = p.readAll(buf) err = p.readAll(ctx, buf)
value = math.Float64frombits(binary.BigEndian.Uint64(buf)) value = math.Float64frombits(binary.BigEndian.Uint64(buf))
return value, err return value, err
} }
func (p *TBinaryProtocol) ReadString() (value string, err error) { func (p *TBinaryProtocol) ReadString(ctx context.Context) (value string, err error) {
size, e := p.ReadI32() size, e := p.ReadI32(ctx)
if e != nil { if e != nil {
return "", e return "", e
} }
err = checkSizeForProtocol(size, p.cfg)
if err != nil {
return
}
if size < 0 { if size < 0 {
err = invalidDataLength err = invalidDataLength
return return
} }
if size == 0 {
return "", nil
}
if size < int32(len(p.buffer)) {
// Avoid allocation on small reads
buf := p.buffer[:size]
read, e := io.ReadFull(p.trans, buf)
return string(buf[:read]), NewTProtocolException(e)
}
return p.readStringBody(size) return p.readStringBody(size)
} }
func (p *TBinaryProtocol) ReadBinary() ([]byte, error) { func (p *TBinaryProtocol) ReadBinary(ctx context.Context) ([]byte, error) {
size, e := p.ReadI32() size, e := p.ReadI32(ctx)
if e != nil { if e != nil {
return nil, e return nil, e
} }
if size < 0 { if err := checkSizeForProtocol(size, p.cfg); err != nil {
return nil, invalidDataLength return nil, err
}
if uint64(size) > p.trans.RemainingBytes() {
return nil, invalidDataLength
} }
isize := int(size) buf, err := safeReadBytes(size, p.trans)
buf := make([]byte, isize)
_, err := io.ReadFull(p.trans, buf)
return buf, NewTProtocolException(err) return buf, NewTProtocolException(err)
} }
func (p *TBinaryProtocol) Flush() (err error) { func (p *TBinaryProtocol) Flush(ctx context.Context) (err error) {
return NewTProtocolException(p.trans.Flush()) return NewTProtocolException(p.trans.Flush(ctx))
} }
func (p *TBinaryProtocol) Skip(fieldType TType) (err error) { func (p *TBinaryProtocol) Skip(ctx context.Context, fieldType TType) (err error) {
return SkipDefaultDepth(p, fieldType) return SkipDefaultDepth(ctx, p, fieldType)
} }
func (p *TBinaryProtocol) Transport() TTransport { func (p *TBinaryProtocol) Transport() TTransport {
return p.origTransport return p.origTransport
} }
func (p *TBinaryProtocol) readAll(buf []byte) error { func (p *TBinaryProtocol) readAll(ctx context.Context, buf []byte) (err error) {
_, err := io.ReadFull(p.reader, buf) var read int
_, deadlineSet := ctx.Deadline()
for {
read, err = io.ReadFull(p.trans, buf)
if deadlineSet && read == 0 && isTimeoutError(err) && ctx.Err() == nil {
// This is I/O timeout without anything read,
// and we still have time left, keep retrying.
continue
}
// For anything else, don't retry
break
}
return NewTProtocolException(err) return NewTProtocolException(err)
} }
const readLimit = 32768
func (p *TBinaryProtocol) readStringBody(size int32) (value string, err error) { func (p *TBinaryProtocol) readStringBody(size int32) (value string, err error) {
if size < 0 { buf, err := safeReadBytes(size, p.trans)
return "", nil return string(buf), NewTProtocolException(err)
} }
if uint64(size) > p.trans.RemainingBytes() {
return "", invalidDataLength func (p *TBinaryProtocol) SetTConfiguration(conf *TConfiguration) {
} PropagateTConfiguration(p.trans, conf)
PropagateTConfiguration(p.origTransport, conf)
var ( p.cfg = conf
buf bytes.Buffer }
e error
b []byte var (
) _ TConfigurationSetter = (*TBinaryProtocolFactory)(nil)
_ TConfigurationSetter = (*TBinaryProtocol)(nil)
switch { )
case int(size) <= len(p.buffer):
b = p.buffer[:size] // avoids allocation for small reads // This function is shared between TBinaryProtocol and TCompactProtocol.
case int(size) < readLimit: //
b = make([]byte, size) // It tries to read size bytes from trans, in a way that prevents large
default: // allocations when size is insanely large (mostly caused by malformed message).
b = make([]byte, readLimit) func safeReadBytes(size int32, trans io.Reader) ([]byte, error) {
} if size < 0 {
return nil, nil
for size > 0 { }
_, e = io.ReadFull(p.trans, b)
buf.Write(b) buf := new(bytes.Buffer)
if e != nil { _, err := io.CopyN(buf, trans, int64(size))
break return buf.Bytes(), err
}
size -= readLimit
if size < readLimit && size > 0 {
b = b[:size]
}
}
return buf.String(), NewTProtocolException(e)
} }

View File

@ -0,0 +1,109 @@
package thrift
import (
"context"
"fmt"
)
// ResponseMeta represents the metadata attached to the response.
type ResponseMeta struct {
// The headers in the response, if any.
// If the underlying transport/protocol is not THeader, this will always be nil.
Headers THeaderMap
}
type TClient interface {
Call(ctx context.Context, method string, args, result TStruct) (ResponseMeta, error)
}
type TStandardClient struct {
seqId int32
iprot, oprot TProtocol
}
// TStandardClient implements TClient, and uses the standard message format for Thrift.
// It is not safe for concurrent use.
func NewTStandardClient(inputProtocol, outputProtocol TProtocol) *TStandardClient {
return &TStandardClient{
iprot: inputProtocol,
oprot: outputProtocol,
}
}
func (p *TStandardClient) Send(ctx context.Context, oprot TProtocol, seqId int32, method string, args TStruct) error {
// Set headers from context object on THeaderProtocol
if headerProt, ok := oprot.(*THeaderProtocol); ok {
headerProt.ClearWriteHeaders()
for _, key := range GetWriteHeaderList(ctx) {
if value, ok := GetHeader(ctx, key); ok {
headerProt.SetWriteHeader(key, value)
}
}
}
if err := oprot.WriteMessageBegin(ctx, method, CALL, seqId); err != nil {
return err
}
if err := args.Write(ctx, oprot); err != nil {
return err
}
if err := oprot.WriteMessageEnd(ctx); err != nil {
return err
}
return oprot.Flush(ctx)
}
func (p *TStandardClient) Recv(ctx context.Context, iprot TProtocol, seqId int32, method string, result TStruct) error {
rMethod, rTypeId, rSeqId, err := iprot.ReadMessageBegin(ctx)
if err != nil {
return err
}
if method != rMethod {
return NewTApplicationException(WRONG_METHOD_NAME, fmt.Sprintf("%s: wrong method name", method))
} else if seqId != rSeqId {
return NewTApplicationException(BAD_SEQUENCE_ID, fmt.Sprintf("%s: out of order sequence response", method))
} else if rTypeId == EXCEPTION {
var exception tApplicationException
if err := exception.Read(ctx, iprot); err != nil {
return err
}
if err := iprot.ReadMessageEnd(ctx); err != nil {
return err
}
return &exception
} else if rTypeId != REPLY {
return NewTApplicationException(INVALID_MESSAGE_TYPE_EXCEPTION, fmt.Sprintf("%s: invalid message type", method))
}
if err := result.Read(ctx, iprot); err != nil {
return err
}
return iprot.ReadMessageEnd(ctx)
}
func (p *TStandardClient) Call(ctx context.Context, method string, args, result TStruct) (ResponseMeta, error) {
p.seqId++
seqId := p.seqId
if err := p.Send(ctx, p.oprot, seqId, method, args); err != nil {
return ResponseMeta{}, err
}
// method is oneway
if result == nil {
return ResponseMeta{}, nil
}
err := p.Recv(ctx, p.iprot, seqId, method, result)
var headers THeaderMap
if hp, ok := p.iprot.(*THeaderProtocol); ok {
headers = hp.transport.readHeaders
}
return ResponseMeta{
Headers: headers,
}, err
}

View File

@ -20,7 +20,9 @@
package thrift package thrift
import ( import (
"context"
"encoding/binary" "encoding/binary"
"errors"
"fmt" "fmt"
"io" "io"
"math" "math"
@ -73,20 +75,37 @@ func init() {
} }
} }
type TCompactProtocolFactory struct{} type TCompactProtocolFactory struct {
cfg *TConfiguration
}
// Deprecated: Use NewTCompactProtocolFactoryConf instead.
func NewTCompactProtocolFactory() *TCompactProtocolFactory { func NewTCompactProtocolFactory() *TCompactProtocolFactory {
return &TCompactProtocolFactory{} return NewTCompactProtocolFactoryConf(&TConfiguration{
noPropagation: true,
})
}
func NewTCompactProtocolFactoryConf(conf *TConfiguration) *TCompactProtocolFactory {
return &TCompactProtocolFactory{
cfg: conf,
}
} }
func (p *TCompactProtocolFactory) GetProtocol(trans TTransport) TProtocol { func (p *TCompactProtocolFactory) GetProtocol(trans TTransport) TProtocol {
return NewTCompactProtocol(trans) return NewTCompactProtocolConf(trans, p.cfg)
}
func (p *TCompactProtocolFactory) SetTConfiguration(conf *TConfiguration) {
p.cfg = conf
} }
type TCompactProtocol struct { type TCompactProtocol struct {
trans TRichTransport trans TRichTransport
origTransport TTransport origTransport TTransport
cfg *TConfiguration
// Used to keep track of the last field for the current and previous structs, // Used to keep track of the last field for the current and previous structs,
// so we can do the delta stuff. // so we can do the delta stuff.
lastField []int lastField []int
@ -105,9 +124,19 @@ type TCompactProtocol struct {
buffer [64]byte buffer [64]byte
} }
// Create a TCompactProtocol given a TTransport // Deprecated: Use NewTCompactProtocolConf instead.
func NewTCompactProtocol(trans TTransport) *TCompactProtocol { func NewTCompactProtocol(trans TTransport) *TCompactProtocol {
p := &TCompactProtocol{origTransport: trans, lastField: []int{}} return NewTCompactProtocolConf(trans, &TConfiguration{
noPropagation: true,
})
}
func NewTCompactProtocolConf(trans TTransport, conf *TConfiguration) *TCompactProtocol {
PropagateTConfiguration(trans, conf)
p := &TCompactProtocol{
origTransport: trans,
cfg: conf,
}
if et, ok := trans.(TRichTransport); ok { if et, ok := trans.(TRichTransport); ok {
p.trans = et p.trans = et
} else { } else {
@ -115,7 +144,6 @@ func NewTCompactProtocol(trans TTransport) *TCompactProtocol {
} }
return p return p
} }
// //
@ -124,7 +152,7 @@ func NewTCompactProtocol(trans TTransport) *TCompactProtocol {
// Write a message header to the wire. Compact Protocol messages contain the // Write a message header to the wire. Compact Protocol messages contain the
// protocol version so we can migrate forwards in the future if need be. // protocol version so we can migrate forwards in the future if need be.
func (p *TCompactProtocol) WriteMessageBegin(name string, typeId TMessageType, seqid int32) error { func (p *TCompactProtocol) WriteMessageBegin(ctx context.Context, name string, typeId TMessageType, seqid int32) error {
err := p.writeByteDirect(COMPACT_PROTOCOL_ID) err := p.writeByteDirect(COMPACT_PROTOCOL_ID)
if err != nil { if err != nil {
return NewTProtocolException(err) return NewTProtocolException(err)
@ -137,17 +165,17 @@ func (p *TCompactProtocol) WriteMessageBegin(name string, typeId TMessageType, s
if err != nil { if err != nil {
return NewTProtocolException(err) return NewTProtocolException(err)
} }
e := p.WriteString(name) e := p.WriteString(ctx, name)
return e return e
} }
func (p *TCompactProtocol) WriteMessageEnd() error { return nil } func (p *TCompactProtocol) WriteMessageEnd(ctx context.Context) error { return nil }
// Write a struct begin. This doesn't actually put anything on the wire. We // Write a struct begin. This doesn't actually put anything on the wire. We
// use it as an opportunity to put special placeholder markers on the field // use it as an opportunity to put special placeholder markers on the field
// stack so we can get the field id deltas correct. // stack so we can get the field id deltas correct.
func (p *TCompactProtocol) WriteStructBegin(name string) error { func (p *TCompactProtocol) WriteStructBegin(ctx context.Context, name string) error {
p.lastField = append(p.lastField, p.lastFieldId) p.lastField = append(p.lastField, p.lastFieldId)
p.lastFieldId = 0 p.lastFieldId = 0
return nil return nil
@ -156,26 +184,29 @@ func (p *TCompactProtocol) WriteStructBegin(name string) error {
// Write a struct end. This doesn't actually put anything on the wire. We use // Write a struct end. This doesn't actually put anything on the wire. We use
// this as an opportunity to pop the last field from the current struct off // this as an opportunity to pop the last field from the current struct off
// of the field stack. // of the field stack.
func (p *TCompactProtocol) WriteStructEnd() error { func (p *TCompactProtocol) WriteStructEnd(ctx context.Context) error {
if len(p.lastField) <= 0 {
return NewTProtocolExceptionWithType(INVALID_DATA, errors.New("WriteStructEnd called without matching WriteStructBegin call before"))
}
p.lastFieldId = p.lastField[len(p.lastField)-1] p.lastFieldId = p.lastField[len(p.lastField)-1]
p.lastField = p.lastField[:len(p.lastField)-1] p.lastField = p.lastField[:len(p.lastField)-1]
return nil return nil
} }
func (p *TCompactProtocol) WriteFieldBegin(name string, typeId TType, id int16) error { func (p *TCompactProtocol) WriteFieldBegin(ctx context.Context, name string, typeId TType, id int16) error {
if typeId == BOOL { if typeId == BOOL {
// we want to possibly include the value, so we'll wait. // we want to possibly include the value, so we'll wait.
p.booleanFieldName, p.booleanFieldId, p.booleanFieldPending = name, id, true p.booleanFieldName, p.booleanFieldId, p.booleanFieldPending = name, id, true
return nil return nil
} }
_, err := p.writeFieldBeginInternal(name, typeId, id, 0xFF) _, err := p.writeFieldBeginInternal(ctx, name, typeId, id, 0xFF)
return NewTProtocolException(err) return NewTProtocolException(err)
} }
// The workhorse of writeFieldBegin. It has the option of doing a // The workhorse of writeFieldBegin. It has the option of doing a
// 'type override' of the type header. This is used specifically in the // 'type override' of the type header. This is used specifically in the
// boolean field case. // boolean field case.
func (p *TCompactProtocol) writeFieldBeginInternal(name string, typeId TType, id int16, typeOverride byte) (int, error) { func (p *TCompactProtocol) writeFieldBeginInternal(ctx context.Context, name string, typeId TType, id int16, typeOverride byte) (int, error) {
// short lastField = lastField_.pop(); // short lastField = lastField_.pop();
// if there's a type override, use that. // if there's a type override, use that.
@ -200,7 +231,7 @@ func (p *TCompactProtocol) writeFieldBeginInternal(name string, typeId TType, id
if err != nil { if err != nil {
return 0, err return 0, err
} }
err = p.WriteI16(id) err = p.WriteI16(ctx, id)
written = 1 + 2 written = 1 + 2
if err != nil { if err != nil {
return 0, err return 0, err
@ -208,18 +239,17 @@ func (p *TCompactProtocol) writeFieldBeginInternal(name string, typeId TType, id
} }
p.lastFieldId = fieldId p.lastFieldId = fieldId
// p.lastField.Push(field.id);
return written, nil return written, nil
} }
func (p *TCompactProtocol) WriteFieldEnd() error { return nil } func (p *TCompactProtocol) WriteFieldEnd(ctx context.Context) error { return nil }
func (p *TCompactProtocol) WriteFieldStop() error { func (p *TCompactProtocol) WriteFieldStop(ctx context.Context) error {
err := p.writeByteDirect(STOP) err := p.writeByteDirect(STOP)
return NewTProtocolException(err) return NewTProtocolException(err)
} }
func (p *TCompactProtocol) WriteMapBegin(keyType TType, valueType TType, size int) error { func (p *TCompactProtocol) WriteMapBegin(ctx context.Context, keyType TType, valueType TType, size int) error {
if size == 0 { if size == 0 {
err := p.writeByteDirect(0) err := p.writeByteDirect(0)
return NewTProtocolException(err) return NewTProtocolException(err)
@ -232,32 +262,32 @@ func (p *TCompactProtocol) WriteMapBegin(keyType TType, valueType TType, size in
return NewTProtocolException(err) return NewTProtocolException(err)
} }
func (p *TCompactProtocol) WriteMapEnd() error { return nil } func (p *TCompactProtocol) WriteMapEnd(ctx context.Context) error { return nil }
// Write a list header. // Write a list header.
func (p *TCompactProtocol) WriteListBegin(elemType TType, size int) error { func (p *TCompactProtocol) WriteListBegin(ctx context.Context, elemType TType, size int) error {
_, err := p.writeCollectionBegin(elemType, size) _, err := p.writeCollectionBegin(elemType, size)
return NewTProtocolException(err) return NewTProtocolException(err)
} }
func (p *TCompactProtocol) WriteListEnd() error { return nil } func (p *TCompactProtocol) WriteListEnd(ctx context.Context) error { return nil }
// Write a set header. // Write a set header.
func (p *TCompactProtocol) WriteSetBegin(elemType TType, size int) error { func (p *TCompactProtocol) WriteSetBegin(ctx context.Context, elemType TType, size int) error {
_, err := p.writeCollectionBegin(elemType, size) _, err := p.writeCollectionBegin(elemType, size)
return NewTProtocolException(err) return NewTProtocolException(err)
} }
func (p *TCompactProtocol) WriteSetEnd() error { return nil } func (p *TCompactProtocol) WriteSetEnd(ctx context.Context) error { return nil }
func (p *TCompactProtocol) WriteBool(value bool) error { func (p *TCompactProtocol) WriteBool(ctx context.Context, value bool) error {
v := byte(COMPACT_BOOLEAN_FALSE) v := byte(COMPACT_BOOLEAN_FALSE)
if value { if value {
v = byte(COMPACT_BOOLEAN_TRUE) v = byte(COMPACT_BOOLEAN_TRUE)
} }
if p.booleanFieldPending { if p.booleanFieldPending {
// we haven't written the field header yet // we haven't written the field header yet
_, err := p.writeFieldBeginInternal(p.booleanFieldName, BOOL, p.booleanFieldId, v) _, err := p.writeFieldBeginInternal(ctx, p.booleanFieldName, BOOL, p.booleanFieldId, v)
p.booleanFieldPending = false p.booleanFieldPending = false
return NewTProtocolException(err) return NewTProtocolException(err)
} }
@ -267,31 +297,31 @@ func (p *TCompactProtocol) WriteBool(value bool) error {
} }
// Write a byte. Nothing to see here! // Write a byte. Nothing to see here!
func (p *TCompactProtocol) WriteByte(value int8) error { func (p *TCompactProtocol) WriteByte(ctx context.Context, value int8) error {
err := p.writeByteDirect(byte(value)) err := p.writeByteDirect(byte(value))
return NewTProtocolException(err) return NewTProtocolException(err)
} }
// Write an I16 as a zigzag varint. // Write an I16 as a zigzag varint.
func (p *TCompactProtocol) WriteI16(value int16) error { func (p *TCompactProtocol) WriteI16(ctx context.Context, value int16) error {
_, err := p.writeVarint32(p.int32ToZigzag(int32(value))) _, err := p.writeVarint32(p.int32ToZigzag(int32(value)))
return NewTProtocolException(err) return NewTProtocolException(err)
} }
// Write an i32 as a zigzag varint. // Write an i32 as a zigzag varint.
func (p *TCompactProtocol) WriteI32(value int32) error { func (p *TCompactProtocol) WriteI32(ctx context.Context, value int32) error {
_, err := p.writeVarint32(p.int32ToZigzag(value)) _, err := p.writeVarint32(p.int32ToZigzag(value))
return NewTProtocolException(err) return NewTProtocolException(err)
} }
// Write an i64 as a zigzag varint. // Write an i64 as a zigzag varint.
func (p *TCompactProtocol) WriteI64(value int64) error { func (p *TCompactProtocol) WriteI64(ctx context.Context, value int64) error {
_, err := p.writeVarint64(p.int64ToZigzag(value)) _, err := p.writeVarint64(p.int64ToZigzag(value))
return NewTProtocolException(err) return NewTProtocolException(err)
} }
// Write a double to the wire as 8 bytes. // Write a double to the wire as 8 bytes.
func (p *TCompactProtocol) WriteDouble(value float64) error { func (p *TCompactProtocol) WriteDouble(ctx context.Context, value float64) error {
buf := p.buffer[0:8] buf := p.buffer[0:8]
binary.LittleEndian.PutUint64(buf, math.Float64bits(value)) binary.LittleEndian.PutUint64(buf, math.Float64bits(value))
_, err := p.trans.Write(buf) _, err := p.trans.Write(buf)
@ -299,7 +329,7 @@ func (p *TCompactProtocol) WriteDouble(value float64) error {
} }
// Write a string to the wire with a varint size preceding. // Write a string to the wire with a varint size preceding.
func (p *TCompactProtocol) WriteString(value string) error { func (p *TCompactProtocol) WriteString(ctx context.Context, value string) error {
_, e := p.writeVarint32(int32(len(value))) _, e := p.writeVarint32(int32(len(value)))
if e != nil { if e != nil {
return NewTProtocolException(e) return NewTProtocolException(e)
@ -311,7 +341,7 @@ func (p *TCompactProtocol) WriteString(value string) error {
} }
// Write a byte array, using a varint for the size. // Write a byte array, using a varint for the size.
func (p *TCompactProtocol) WriteBinary(bin []byte) error { func (p *TCompactProtocol) WriteBinary(ctx context.Context, bin []byte) error {
_, e := p.writeVarint32(int32(len(bin))) _, e := p.writeVarint32(int32(len(bin)))
if e != nil { if e != nil {
return NewTProtocolException(e) return NewTProtocolException(e)
@ -328,9 +358,20 @@ func (p *TCompactProtocol) WriteBinary(bin []byte) error {
// //
// Read a message header. // Read a message header.
func (p *TCompactProtocol) ReadMessageBegin() (name string, typeId TMessageType, seqId int32, err error) { func (p *TCompactProtocol) ReadMessageBegin(ctx context.Context) (name string, typeId TMessageType, seqId int32, err error) {
var protocolId byte
protocolId, err := p.readByteDirect() _, deadlineSet := ctx.Deadline()
for {
protocolId, err = p.readByteDirect()
if deadlineSet && isTimeoutError(err) && ctx.Err() == nil {
// keep retrying I/O timeout errors since we still have
// time left
continue
}
// For anything else, don't retry
break
}
if err != nil { if err != nil {
return return
} }
@ -357,15 +398,15 @@ func (p *TCompactProtocol) ReadMessageBegin() (name string, typeId TMessageType,
err = NewTProtocolException(e) err = NewTProtocolException(e)
return return
} }
name, err = p.ReadString() name, err = p.ReadString(ctx)
return return
} }
func (p *TCompactProtocol) ReadMessageEnd() error { return nil } func (p *TCompactProtocol) ReadMessageEnd(ctx context.Context) error { return nil }
// Read a struct begin. There's nothing on the wire for this, but it is our // Read a struct begin. There's nothing on the wire for this, but it is our
// opportunity to push a new struct begin marker onto the field stack. // opportunity to push a new struct begin marker onto the field stack.
func (p *TCompactProtocol) ReadStructBegin() (name string, err error) { func (p *TCompactProtocol) ReadStructBegin(ctx context.Context) (name string, err error) {
p.lastField = append(p.lastField, p.lastFieldId) p.lastField = append(p.lastField, p.lastFieldId)
p.lastFieldId = 0 p.lastFieldId = 0
return return
@ -373,15 +414,18 @@ func (p *TCompactProtocol) ReadStructBegin() (name string, err error) {
// Doesn't actually consume any wire data, just removes the last field for // Doesn't actually consume any wire data, just removes the last field for
// this struct from the field stack. // this struct from the field stack.
func (p *TCompactProtocol) ReadStructEnd() error { func (p *TCompactProtocol) ReadStructEnd(ctx context.Context) error {
// consume the last field we read off the wire. // consume the last field we read off the wire.
if len(p.lastField) <= 0 {
return NewTProtocolExceptionWithType(INVALID_DATA, errors.New("ReadStructEnd called without matching ReadStructBegin call before"))
}
p.lastFieldId = p.lastField[len(p.lastField)-1] p.lastFieldId = p.lastField[len(p.lastField)-1]
p.lastField = p.lastField[:len(p.lastField)-1] p.lastField = p.lastField[:len(p.lastField)-1]
return nil return nil
} }
// Read a field header off the wire. // Read a field header off the wire.
func (p *TCompactProtocol) ReadFieldBegin() (name string, typeId TType, id int16, err error) { func (p *TCompactProtocol) ReadFieldBegin(ctx context.Context) (name string, typeId TType, id int16, err error) {
t, err := p.readByteDirect() t, err := p.readByteDirect()
if err != nil { if err != nil {
return return
@ -396,7 +440,7 @@ func (p *TCompactProtocol) ReadFieldBegin() (name string, typeId TType, id int16
modifier := int16((t & 0xf0) >> 4) modifier := int16((t & 0xf0) >> 4)
if modifier == 0 { if modifier == 0 {
// not a delta. look ahead for the zigzag varint field id. // not a delta. look ahead for the zigzag varint field id.
id, err = p.ReadI16() id, err = p.ReadI16(ctx)
if err != nil { if err != nil {
return return
} }
@ -422,12 +466,12 @@ func (p *TCompactProtocol) ReadFieldBegin() (name string, typeId TType, id int16
return return
} }
func (p *TCompactProtocol) ReadFieldEnd() error { return nil } func (p *TCompactProtocol) ReadFieldEnd(ctx context.Context) error { return nil }
// Read a map header off the wire. If the size is zero, skip reading the key // Read a map header off the wire. If the size is zero, skip reading the key
// and value type. This means that 0-length maps will yield TMaps without the // and value type. This means that 0-length maps will yield TMaps without the
// "correct" types. // "correct" types.
func (p *TCompactProtocol) ReadMapBegin() (keyType TType, valueType TType, size int, err error) { func (p *TCompactProtocol) ReadMapBegin(ctx context.Context) (keyType TType, valueType TType, size int, err error) {
size32, e := p.readVarint32() size32, e := p.readVarint32()
if e != nil { if e != nil {
err = NewTProtocolException(e) err = NewTProtocolException(e)
@ -451,13 +495,13 @@ func (p *TCompactProtocol) ReadMapBegin() (keyType TType, valueType TType, size
return return
} }
func (p *TCompactProtocol) ReadMapEnd() error { return nil } func (p *TCompactProtocol) ReadMapEnd(ctx context.Context) error { return nil }
// Read a list header off the wire. If the list size is 0-14, the size will // Read a list header off the wire. If the list size is 0-14, the size will
// be packed into the element type header. If it's a longer list, the 4 MSB // be packed into the element type header. If it's a longer list, the 4 MSB
// of the element type header will be 0xF, and a varint will follow with the // of the element type header will be 0xF, and a varint will follow with the
// true size. // true size.
func (p *TCompactProtocol) ReadListBegin() (elemType TType, size int, err error) { func (p *TCompactProtocol) ReadListBegin(ctx context.Context) (elemType TType, size int, err error) {
size_and_type, err := p.readByteDirect() size_and_type, err := p.readByteDirect()
if err != nil { if err != nil {
return return
@ -483,22 +527,22 @@ func (p *TCompactProtocol) ReadListBegin() (elemType TType, size int, err error)
return return
} }
func (p *TCompactProtocol) ReadListEnd() error { return nil } func (p *TCompactProtocol) ReadListEnd(ctx context.Context) error { return nil }
// Read a set header off the wire. If the set size is 0-14, the size will // Read a set header off the wire. If the set size is 0-14, the size will
// be packed into the element type header. If it's a longer set, the 4 MSB // be packed into the element type header. If it's a longer set, the 4 MSB
// of the element type header will be 0xF, and a varint will follow with the // of the element type header will be 0xF, and a varint will follow with the
// true size. // true size.
func (p *TCompactProtocol) ReadSetBegin() (elemType TType, size int, err error) { func (p *TCompactProtocol) ReadSetBegin(ctx context.Context) (elemType TType, size int, err error) {
return p.ReadListBegin() return p.ReadListBegin(ctx)
} }
func (p *TCompactProtocol) ReadSetEnd() error { return nil } func (p *TCompactProtocol) ReadSetEnd(ctx context.Context) error { return nil }
// Read a boolean off the wire. If this is a boolean field, the value should // Read a boolean off the wire. If this is a boolean field, the value should
// already have been read during readFieldBegin, so we'll just consume the // already have been read during readFieldBegin, so we'll just consume the
// pre-stored value. Otherwise, read a byte. // pre-stored value. Otherwise, read a byte.
func (p *TCompactProtocol) ReadBool() (value bool, err error) { func (p *TCompactProtocol) ReadBool(ctx context.Context) (value bool, err error) {
if p.boolValueIsNotNull { if p.boolValueIsNotNull {
p.boolValueIsNotNull = false p.boolValueIsNotNull = false
return p.boolValue, nil return p.boolValue, nil
@ -508,7 +552,7 @@ func (p *TCompactProtocol) ReadBool() (value bool, err error) {
} }
// Read a single byte off the wire. Nothing interesting here. // Read a single byte off the wire. Nothing interesting here.
func (p *TCompactProtocol) ReadByte() (int8, error) { func (p *TCompactProtocol) ReadByte(ctx context.Context) (int8, error) {
v, err := p.readByteDirect() v, err := p.readByteDirect()
if err != nil { if err != nil {
return 0, NewTProtocolException(err) return 0, NewTProtocolException(err)
@ -517,13 +561,13 @@ func (p *TCompactProtocol) ReadByte() (int8, error) {
} }
// Read an i16 from the wire as a zigzag varint. // Read an i16 from the wire as a zigzag varint.
func (p *TCompactProtocol) ReadI16() (value int16, err error) { func (p *TCompactProtocol) ReadI16(ctx context.Context) (value int16, err error) {
v, err := p.ReadI32() v, err := p.ReadI32(ctx)
return int16(v), err return int16(v), err
} }
// Read an i32 from the wire as a zigzag varint. // Read an i32 from the wire as a zigzag varint.
func (p *TCompactProtocol) ReadI32() (value int32, err error) { func (p *TCompactProtocol) ReadI32(ctx context.Context) (value int32, err error) {
v, e := p.readVarint32() v, e := p.readVarint32()
if e != nil { if e != nil {
return 0, NewTProtocolException(e) return 0, NewTProtocolException(e)
@ -533,7 +577,7 @@ func (p *TCompactProtocol) ReadI32() (value int32, err error) {
} }
// Read an i64 from the wire as a zigzag varint. // Read an i64 from the wire as a zigzag varint.
func (p *TCompactProtocol) ReadI64() (value int64, err error) { func (p *TCompactProtocol) ReadI64(ctx context.Context) (value int64, err error) {
v, e := p.readVarint64() v, e := p.readVarint64()
if e != nil { if e != nil {
return 0, NewTProtocolException(e) return 0, NewTProtocolException(e)
@ -543,7 +587,7 @@ func (p *TCompactProtocol) ReadI64() (value int64, err error) {
} }
// No magic here - just read a double off the wire. // No magic here - just read a double off the wire.
func (p *TCompactProtocol) ReadDouble() (value float64, err error) { func (p *TCompactProtocol) ReadDouble(ctx context.Context) (value float64, err error) {
longBits := p.buffer[0:8] longBits := p.buffer[0:8]
_, e := io.ReadFull(p.trans, longBits) _, e := io.ReadFull(p.trans, longBits)
if e != nil { if e != nil {
@ -553,58 +597,53 @@ func (p *TCompactProtocol) ReadDouble() (value float64, err error) {
} }
// Reads a []byte (via readBinary), and then UTF-8 decodes it. // Reads a []byte (via readBinary), and then UTF-8 decodes it.
func (p *TCompactProtocol) ReadString() (value string, err error) { func (p *TCompactProtocol) ReadString(ctx context.Context) (value string, err error) {
length, e := p.readVarint32() length, e := p.readVarint32()
if e != nil { if e != nil {
return "", NewTProtocolException(e) return "", NewTProtocolException(e)
} }
if length < 0 { err = checkSizeForProtocol(length, p.cfg)
return "", invalidDataLength if err != nil {
return
} }
if uint64(length) > p.trans.RemainingBytes() {
return "", invalidDataLength
}
if length == 0 { if length == 0 {
return "", nil return "", nil
} }
var buf []byte if length < int32(len(p.buffer)) {
if length <= int32(len(p.buffer)) { // Avoid allocation on small reads
buf = p.buffer[0:length] buf := p.buffer[:length]
} else { read, e := io.ReadFull(p.trans, buf)
buf = make([]byte, length) return string(buf[:read]), NewTProtocolException(e)
} }
_, e = io.ReadFull(p.trans, buf)
buf, e := safeReadBytes(length, p.trans)
return string(buf), NewTProtocolException(e) return string(buf), NewTProtocolException(e)
} }
// Read a []byte from the wire. // Read a []byte from the wire.
func (p *TCompactProtocol) ReadBinary() (value []byte, err error) { func (p *TCompactProtocol) ReadBinary(ctx context.Context) (value []byte, err error) {
length, e := p.readVarint32() length, e := p.readVarint32()
if e != nil { if e != nil {
return nil, NewTProtocolException(e) return nil, NewTProtocolException(e)
} }
err = checkSizeForProtocol(length, p.cfg)
if err != nil {
return
}
if length == 0 { if length == 0 {
return []byte{}, nil return []byte{}, nil
} }
if length < 0 {
return nil, invalidDataLength
}
if uint64(length) > p.trans.RemainingBytes() {
return nil, invalidDataLength
}
buf := make([]byte, length) buf, e := safeReadBytes(length, p.trans)
_, e = io.ReadFull(p.trans, buf)
return buf, NewTProtocolException(e) return buf, NewTProtocolException(e)
} }
func (p *TCompactProtocol) Flush() (err error) { func (p *TCompactProtocol) Flush(ctx context.Context) (err error) {
return NewTProtocolException(p.trans.Flush()) return NewTProtocolException(p.trans.Flush(ctx))
} }
func (p *TCompactProtocol) Skip(fieldType TType) (err error) { func (p *TCompactProtocol) Skip(ctx context.Context, fieldType TType) (err error) {
return SkipDefaultDepth(p, fieldType) return SkipDefaultDepth(ctx, p, fieldType)
} }
func (p *TCompactProtocol) Transport() TTransport { func (p *TCompactProtocol) Transport() TTransport {
@ -806,10 +845,21 @@ func (p *TCompactProtocol) getTType(t tCompactType) (TType, error) {
case COMPACT_STRUCT: case COMPACT_STRUCT:
return STRUCT, nil return STRUCT, nil
} }
return STOP, TException(fmt.Errorf("don't know what type: %d", t&0x0f)) return STOP, NewTProtocolException(fmt.Errorf("don't know what type: %v", t&0x0f))
} }
// Given a TType value, find the appropriate TCompactProtocol.Types constant. // Given a TType value, find the appropriate TCompactProtocol.Types constant.
func (p *TCompactProtocol) getCompactType(t TType) tCompactType { func (p *TCompactProtocol) getCompactType(t TType) tCompactType {
return ttypeToCompactType[t] return ttypeToCompactType[t]
} }
func (p *TCompactProtocol) SetTConfiguration(conf *TConfiguration) {
PropagateTConfiguration(p.trans, conf)
PropagateTConfiguration(p.origTransport, conf)
p.cfg = conf
}
var (
_ TConfigurationSetter = (*TCompactProtocolFactory)(nil)
_ TConfigurationSetter = (*TCompactProtocol)(nil)
)

View File

@ -0,0 +1,378 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package thrift
import (
"crypto/tls"
"fmt"
"time"
)
// Default TConfiguration values.
const (
DEFAULT_MAX_MESSAGE_SIZE = 100 * 1024 * 1024
DEFAULT_MAX_FRAME_SIZE = 16384000
DEFAULT_TBINARY_STRICT_READ = false
DEFAULT_TBINARY_STRICT_WRITE = true
DEFAULT_CONNECT_TIMEOUT = 0
DEFAULT_SOCKET_TIMEOUT = 0
)
// TConfiguration defines some configurations shared between TTransport,
// TProtocol, TTransportFactory, TProtocolFactory, and other implementations.
//
// When constructing TConfiguration, you only need to specify the non-default
// fields. All zero values have sane default values.
//
// Not all configurations defined are applicable to all implementations.
// Implementations are free to ignore the configurations not applicable to them.
//
// All functions attached to this type are nil-safe.
//
// See [1] for spec.
//
// NOTE: When using TConfiguration, fill in all the configurations you want to
// set across the stack, not only the ones you want to set in the immediate
// TTransport/TProtocol.
//
// For example, say you want to migrate this old code into using TConfiguration:
//
// sccket := thrift.NewTSocketTimeout("host:port", time.Second)
// transFactory := thrift.NewTFramedTransportFactoryMaxLength(
// thrift.NewTTransportFactory(),
// 1024 * 1024 * 256,
// )
// protoFactory := thrift.NewTBinaryProtocolFactory(true, true)
//
// This is the wrong way to do it because in the end the TConfiguration used by
// socket and transFactory will be overwritten by the one used by protoFactory
// because of TConfiguration propagation:
//
// // bad example, DO NOT USE
// sccket := thrift.NewTSocketConf("host:port", &thrift.TConfiguration{
// ConnectTimeout: time.Second,
// SocketTimeout: time.Second,
// })
// transFactory := thrift.NewTFramedTransportFactoryConf(
// thrift.NewTTransportFactory(),
// &thrift.TConfiguration{
// MaxFrameSize: 1024 * 1024 * 256,
// },
// )
// protoFactory := thrift.NewTBinaryProtocolFactoryConf(&thrift.TConfiguration{
// TBinaryStrictRead: thrift.BoolPtr(true),
// TBinaryStrictWrite: thrift.BoolPtr(true),
// })
//
// This is the correct way to do it:
//
// conf := &thrift.TConfiguration{
// ConnectTimeout: time.Second,
// SocketTimeout: time.Second,
//
// MaxFrameSize: 1024 * 1024 * 256,
//
// TBinaryStrictRead: thrift.BoolPtr(true),
// TBinaryStrictWrite: thrift.BoolPtr(true),
// }
// sccket := thrift.NewTSocketConf("host:port", conf)
// transFactory := thrift.NewTFramedTransportFactoryConf(thrift.NewTTransportFactory(), conf)
// protoFactory := thrift.NewTBinaryProtocolFactoryConf(conf)
//
// [1]: https://github.com/apache/thrift/blob/master/doc/specs/thrift-tconfiguration.md
type TConfiguration struct {
// If <= 0, DEFAULT_MAX_MESSAGE_SIZE will be used instead.
MaxMessageSize int32
// If <= 0, DEFAULT_MAX_FRAME_SIZE will be used instead.
//
// Also if MaxMessageSize < MaxFrameSize,
// MaxMessageSize will be used instead.
MaxFrameSize int32
// Connect and socket timeouts to be used by TSocket and TSSLSocket.
//
// 0 means no timeout.
//
// If <0, DEFAULT_CONNECT_TIMEOUT and DEFAULT_SOCKET_TIMEOUT will be
// used.
ConnectTimeout time.Duration
SocketTimeout time.Duration
// TLS config to be used by TSSLSocket.
TLSConfig *tls.Config
// Strict read/write configurations for TBinaryProtocol.
//
// BoolPtr helper function is available to use literal values.
TBinaryStrictRead *bool
TBinaryStrictWrite *bool
// The wrapped protocol id to be used in THeader transport/protocol.
//
// THeaderProtocolIDPtr and THeaderProtocolIDPtrMust helper functions
// are provided to help filling this value.
THeaderProtocolID *THeaderProtocolID
// Used internally by deprecated constructors, to avoid overriding
// underlying TTransport/TProtocol's cfg by accidental propagations.
//
// For external users this is always false.
noPropagation bool
}
// GetMaxMessageSize returns the max message size an implementation should
// follow.
//
// It's nil-safe. DEFAULT_MAX_MESSAGE_SIZE will be returned if tc is nil.
func (tc *TConfiguration) GetMaxMessageSize() int32 {
if tc == nil || tc.MaxMessageSize <= 0 {
return DEFAULT_MAX_MESSAGE_SIZE
}
return tc.MaxMessageSize
}
// GetMaxFrameSize returns the max frame size an implementation should follow.
//
// It's nil-safe. DEFAULT_MAX_FRAME_SIZE will be returned if tc is nil.
//
// If the configured max message size is smaller than the configured max frame
// size, the smaller one will be returned instead.
func (tc *TConfiguration) GetMaxFrameSize() int32 {
if tc == nil {
return DEFAULT_MAX_FRAME_SIZE
}
maxFrameSize := tc.MaxFrameSize
if maxFrameSize <= 0 {
maxFrameSize = DEFAULT_MAX_FRAME_SIZE
}
if maxMessageSize := tc.GetMaxMessageSize(); maxMessageSize < maxFrameSize {
return maxMessageSize
}
return maxFrameSize
}
// GetConnectTimeout returns the connect timeout should be used by TSocket and
// TSSLSocket.
//
// It's nil-safe. If tc is nil, DEFAULT_CONNECT_TIMEOUT will be returned instead.
func (tc *TConfiguration) GetConnectTimeout() time.Duration {
if tc == nil || tc.ConnectTimeout < 0 {
return DEFAULT_CONNECT_TIMEOUT
}
return tc.ConnectTimeout
}
// GetSocketTimeout returns the socket timeout should be used by TSocket and
// TSSLSocket.
//
// It's nil-safe. If tc is nil, DEFAULT_SOCKET_TIMEOUT will be returned instead.
func (tc *TConfiguration) GetSocketTimeout() time.Duration {
if tc == nil || tc.SocketTimeout < 0 {
return DEFAULT_SOCKET_TIMEOUT
}
return tc.SocketTimeout
}
// GetTLSConfig returns the tls config should be used by TSSLSocket.
//
// It's nil-safe. If tc is nil, nil will be returned instead.
func (tc *TConfiguration) GetTLSConfig() *tls.Config {
if tc == nil {
return nil
}
return tc.TLSConfig
}
// GetTBinaryStrictRead returns the strict read configuration TBinaryProtocol
// should follow.
//
// It's nil-safe. DEFAULT_TBINARY_STRICT_READ will be returned if either tc or
// tc.TBinaryStrictRead is nil.
func (tc *TConfiguration) GetTBinaryStrictRead() bool {
if tc == nil || tc.TBinaryStrictRead == nil {
return DEFAULT_TBINARY_STRICT_READ
}
return *tc.TBinaryStrictRead
}
// GetTBinaryStrictWrite returns the strict read configuration TBinaryProtocol
// should follow.
//
// It's nil-safe. DEFAULT_TBINARY_STRICT_WRITE will be returned if either tc or
// tc.TBinaryStrictWrite is nil.
func (tc *TConfiguration) GetTBinaryStrictWrite() bool {
if tc == nil || tc.TBinaryStrictWrite == nil {
return DEFAULT_TBINARY_STRICT_WRITE
}
return *tc.TBinaryStrictWrite
}
// GetTHeaderProtocolID returns the THeaderProtocolID should be used by
// THeaderProtocol clients (for servers, they always use the same one as the
// client instead).
//
// It's nil-safe. If either tc or tc.THeaderProtocolID is nil,
// THeaderProtocolDefault will be returned instead.
// THeaderProtocolDefault will also be returned if configured value is invalid.
func (tc *TConfiguration) GetTHeaderProtocolID() THeaderProtocolID {
if tc == nil || tc.THeaderProtocolID == nil {
return THeaderProtocolDefault
}
protoID := *tc.THeaderProtocolID
if err := protoID.Validate(); err != nil {
return THeaderProtocolDefault
}
return protoID
}
// THeaderProtocolIDPtr validates and returns the pointer to id.
//
// If id is not a valid THeaderProtocolID, a pointer to THeaderProtocolDefault
// and the validation error will be returned.
func THeaderProtocolIDPtr(id THeaderProtocolID) (*THeaderProtocolID, error) {
err := id.Validate()
if err != nil {
id = THeaderProtocolDefault
}
return &id, err
}
// THeaderProtocolIDPtrMust validates and returns the pointer to id.
//
// It's similar to THeaderProtocolIDPtr, but it panics on validation errors
// instead of returning them.
func THeaderProtocolIDPtrMust(id THeaderProtocolID) *THeaderProtocolID {
ptr, err := THeaderProtocolIDPtr(id)
if err != nil {
panic(err)
}
return ptr
}
// TConfigurationSetter is an optional interface TProtocol, TTransport,
// TProtocolFactory, TTransportFactory, and other implementations can implement.
//
// It's intended to be called during intializations.
// The behavior of calling SetTConfiguration on a TTransport/TProtocol in the
// middle of a message is undefined:
// It may or may not change the behavior of the current processing message,
// and it may even cause the current message to fail.
//
// Note for implementations: SetTConfiguration might be called multiple times
// with the same value in quick successions due to the implementation of the
// propagation. Implementations should make SetTConfiguration as simple as
// possible (usually just overwrite the stored configuration and propagate it to
// the wrapped TTransports/TProtocols).
type TConfigurationSetter interface {
SetTConfiguration(*TConfiguration)
}
// PropagateTConfiguration propagates cfg to impl if impl implements
// TConfigurationSetter and cfg is non-nil, otherwise it does nothing.
//
// NOTE: nil cfg is not propagated. If you want to propagate a TConfiguration
// with everything being default value, use &TConfiguration{} explicitly instead.
func PropagateTConfiguration(impl interface{}, cfg *TConfiguration) {
if cfg == nil || cfg.noPropagation {
return
}
if setter, ok := impl.(TConfigurationSetter); ok {
setter.SetTConfiguration(cfg)
}
}
func checkSizeForProtocol(size int32, cfg *TConfiguration) error {
if size < 0 {
return NewTProtocolExceptionWithType(
NEGATIVE_SIZE,
fmt.Errorf("negative size: %d", size),
)
}
if size > cfg.GetMaxMessageSize() {
return NewTProtocolExceptionWithType(
SIZE_LIMIT,
fmt.Errorf("size exceeded max allowed: %d", size),
)
}
return nil
}
type tTransportFactoryConf struct {
delegate TTransportFactory
cfg *TConfiguration
}
func (f *tTransportFactoryConf) GetTransport(orig TTransport) (TTransport, error) {
trans, err := f.delegate.GetTransport(orig)
if err == nil {
PropagateTConfiguration(orig, f.cfg)
PropagateTConfiguration(trans, f.cfg)
}
return trans, err
}
func (f *tTransportFactoryConf) SetTConfiguration(cfg *TConfiguration) {
PropagateTConfiguration(f.delegate, f.cfg)
f.cfg = cfg
}
// TTransportFactoryConf wraps a TTransportFactory to propagate
// TConfiguration on the factory's GetTransport calls.
func TTransportFactoryConf(delegate TTransportFactory, conf *TConfiguration) TTransportFactory {
return &tTransportFactoryConf{
delegate: delegate,
cfg: conf,
}
}
type tProtocolFactoryConf struct {
delegate TProtocolFactory
cfg *TConfiguration
}
func (f *tProtocolFactoryConf) GetProtocol(trans TTransport) TProtocol {
proto := f.delegate.GetProtocol(trans)
PropagateTConfiguration(trans, f.cfg)
PropagateTConfiguration(proto, f.cfg)
return proto
}
func (f *tProtocolFactoryConf) SetTConfiguration(cfg *TConfiguration) {
PropagateTConfiguration(f.delegate, f.cfg)
f.cfg = cfg
}
// TProtocolFactoryConf wraps a TProtocolFactory to propagate
// TConfiguration on the factory's GetProtocol calls.
func TProtocolFactoryConf(delegate TProtocolFactory, conf *TConfiguration) TProtocolFactory {
return &tProtocolFactoryConf{
delegate: delegate,
cfg: conf,
}
}
var (
_ TConfigurationSetter = (*tTransportFactoryConf)(nil)
_ TConfigurationSetter = (*tProtocolFactoryConf)(nil)
)

View File

@ -19,12 +19,6 @@
package thrift package thrift
// A processor is a generic object which operates upon an input stream and import "context"
// writes to some output stream.
type TProcessor interface {
Process(in, out TProtocol) (bool, TException)
}
type TProcessorFunction interface { var defaultCtx = context.Background()
Process(seqId int32, in, out TProtocol) (bool, TException)
}

View File

@ -26,19 +26,91 @@ import (
// Generic Thrift exception // Generic Thrift exception
type TException interface { type TException interface {
error error
TExceptionType() TExceptionType
} }
// Prepends additional information to an error without losing the Thrift exception interface // Prepends additional information to an error without losing the Thrift exception interface
func PrependError(prepend string, err error) error { func PrependError(prepend string, err error) error {
if t, ok := err.(TTransportException); ok { msg := prepend + err.Error()
return NewTTransportException(t.TypeId(), prepend+t.Error())
} var te TException
if t, ok := err.(TProtocolException); ok { if errors.As(err, &te) {
return NewTProtocolExceptionWithType(t.TypeId(), errors.New(prepend+err.Error())) switch te.TExceptionType() {
} case TExceptionTypeTransport:
if t, ok := err.(TApplicationException); ok { if t, ok := err.(TTransportException); ok {
return NewTApplicationException(t.TypeId(), prepend+t.Error()) return prependTTransportException(prepend, t)
}
case TExceptionTypeProtocol:
if t, ok := err.(TProtocolException); ok {
return prependTProtocolException(prepend, t)
}
case TExceptionTypeApplication:
var t TApplicationException
if errors.As(err, &t) {
return NewTApplicationException(t.TypeId(), msg)
}
}
return wrappedTException{
err: err,
msg: msg,
tExceptionType: te.TExceptionType(),
}
} }
return errors.New(prepend + err.Error()) return errors.New(msg)
} }
// TExceptionType is an enum type to categorize different "subclasses" of TExceptions.
type TExceptionType byte
// TExceptionType values
const (
TExceptionTypeUnknown TExceptionType = iota
TExceptionTypeCompiled // TExceptions defined in thrift files and generated by thrift compiler
TExceptionTypeApplication // TApplicationExceptions
TExceptionTypeProtocol // TProtocolExceptions
TExceptionTypeTransport // TTransportExceptions
)
// WrapTException wraps an error into TException.
//
// If err is nil or already TException, it's returned as-is.
// Otherwise it will be wraped into TException with TExceptionType() returning
// TExceptionTypeUnknown, and Unwrap() returning the original error.
func WrapTException(err error) TException {
if err == nil {
return nil
}
if te, ok := err.(TException); ok {
return te
}
return wrappedTException{
err: err,
msg: err.Error(),
tExceptionType: TExceptionTypeUnknown,
}
}
type wrappedTException struct {
err error
msg string
tExceptionType TExceptionType
}
func (w wrappedTException) Error() string {
return w.msg
}
func (w wrappedTException) TExceptionType() TExceptionType {
return w.tExceptionType
}
func (w wrappedTException) Unwrap() error {
return w.err
}
var _ TException = wrappedTException{}

View File

@ -0,0 +1,110 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package thrift
import (
"context"
)
// See https://godoc.org/context#WithValue on why do we need the unexported typedefs.
type (
headerKey string
headerKeyList int
)
// Values for headerKeyList.
const (
headerKeyListRead headerKeyList = iota
headerKeyListWrite
)
// SetHeader sets a header in the context.
func SetHeader(ctx context.Context, key, value string) context.Context {
return context.WithValue(
ctx,
headerKey(key),
value,
)
}
// UnsetHeader unsets a previously set header in the context.
func UnsetHeader(ctx context.Context, key string) context.Context {
return context.WithValue(
ctx,
headerKey(key),
nil,
)
}
// GetHeader returns a value of the given header from the context.
func GetHeader(ctx context.Context, key string) (value string, ok bool) {
if v := ctx.Value(headerKey(key)); v != nil {
value, ok = v.(string)
}
return
}
// SetReadHeaderList sets the key list of read THeaders in the context.
func SetReadHeaderList(ctx context.Context, keys []string) context.Context {
return context.WithValue(
ctx,
headerKeyListRead,
keys,
)
}
// GetReadHeaderList returns the key list of read THeaders from the context.
func GetReadHeaderList(ctx context.Context) []string {
if v := ctx.Value(headerKeyListRead); v != nil {
if value, ok := v.([]string); ok {
return value
}
}
return nil
}
// SetWriteHeaderList sets the key list of THeaders to write in the context.
func SetWriteHeaderList(ctx context.Context, keys []string) context.Context {
return context.WithValue(
ctx,
headerKeyListWrite,
keys,
)
}
// GetWriteHeaderList returns the key list of THeaders to write from the context.
func GetWriteHeaderList(ctx context.Context) []string {
if v := ctx.Value(headerKeyListWrite); v != nil {
if value, ok := v.([]string); ok {
return value
}
}
return nil
}
// AddReadTHeaderToContext adds the whole THeader headers into context.
func AddReadTHeaderToContext(ctx context.Context, headers THeaderMap) context.Context {
keys := make([]string, 0, len(headers))
for key, value := range headers {
ctx = SetHeader(ctx, key, value)
keys = append(keys, key)
}
return SetReadHeaderList(ctx, keys)
}

View File

@ -0,0 +1,351 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package thrift
import (
"context"
"errors"
)
// THeaderProtocol is a thrift protocol that implements THeader:
// https://github.com/apache/thrift/blob/master/doc/specs/HeaderFormat.md
//
// It supports either binary or compact protocol as the wrapped protocol.
//
// Most of the THeader handlings are happening inside THeaderTransport.
type THeaderProtocol struct {
transport *THeaderTransport
// Will be initialized on first read/write.
protocol TProtocol
cfg *TConfiguration
}
// Deprecated: Use NewTHeaderProtocolConf instead.
func NewTHeaderProtocol(trans TTransport) *THeaderProtocol {
return newTHeaderProtocolConf(trans, &TConfiguration{
noPropagation: true,
})
}
// NewTHeaderProtocolConf creates a new THeaderProtocol from the underlying
// transport with given TConfiguration.
//
// The passed in transport will be wrapped with THeaderTransport.
//
// Note that THeaderTransport handles frame and zlib by itself,
// so the underlying transport should be a raw socket transports (TSocket or TSSLSocket),
// instead of rich transports like TZlibTransport or TFramedTransport.
func NewTHeaderProtocolConf(trans TTransport, conf *TConfiguration) *THeaderProtocol {
return newTHeaderProtocolConf(trans, conf)
}
func newTHeaderProtocolConf(trans TTransport, cfg *TConfiguration) *THeaderProtocol {
t := NewTHeaderTransportConf(trans, cfg)
p, _ := t.cfg.GetTHeaderProtocolID().GetProtocol(t)
PropagateTConfiguration(p, cfg)
return &THeaderProtocol{
transport: t,
protocol: p,
cfg: cfg,
}
}
type tHeaderProtocolFactory struct {
cfg *TConfiguration
}
func (f tHeaderProtocolFactory) GetProtocol(trans TTransport) TProtocol {
return newTHeaderProtocolConf(trans, f.cfg)
}
func (f *tHeaderProtocolFactory) SetTConfiguration(cfg *TConfiguration) {
f.cfg = cfg
}
// Deprecated: Use NewTHeaderProtocolFactoryConf instead.
func NewTHeaderProtocolFactory() TProtocolFactory {
return NewTHeaderProtocolFactoryConf(&TConfiguration{
noPropagation: true,
})
}
// NewTHeaderProtocolFactoryConf creates a factory for THeader with given
// TConfiguration.
func NewTHeaderProtocolFactoryConf(conf *TConfiguration) TProtocolFactory {
return tHeaderProtocolFactory{
cfg: conf,
}
}
// Transport returns the underlying transport.
//
// It's guaranteed to be of type *THeaderTransport.
func (p *THeaderProtocol) Transport() TTransport {
return p.transport
}
// GetReadHeaders returns the THeaderMap read from transport.
func (p *THeaderProtocol) GetReadHeaders() THeaderMap {
return p.transport.GetReadHeaders()
}
// SetWriteHeader sets a header for write.
func (p *THeaderProtocol) SetWriteHeader(key, value string) {
p.transport.SetWriteHeader(key, value)
}
// ClearWriteHeaders clears all write headers previously set.
func (p *THeaderProtocol) ClearWriteHeaders() {
p.transport.ClearWriteHeaders()
}
// AddTransform add a transform for writing.
func (p *THeaderProtocol) AddTransform(transform THeaderTransformID) error {
return p.transport.AddTransform(transform)
}
func (p *THeaderProtocol) Flush(ctx context.Context) error {
return p.transport.Flush(ctx)
}
func (p *THeaderProtocol) WriteMessageBegin(ctx context.Context, name string, typeID TMessageType, seqID int32) error {
newProto, err := p.transport.Protocol().GetProtocol(p.transport)
if err != nil {
return err
}
PropagateTConfiguration(newProto, p.cfg)
p.protocol = newProto
p.transport.SequenceID = seqID
return p.protocol.WriteMessageBegin(ctx, name, typeID, seqID)
}
func (p *THeaderProtocol) WriteMessageEnd(ctx context.Context) error {
if err := p.protocol.WriteMessageEnd(ctx); err != nil {
return err
}
return p.transport.Flush(ctx)
}
func (p *THeaderProtocol) WriteStructBegin(ctx context.Context, name string) error {
return p.protocol.WriteStructBegin(ctx, name)
}
func (p *THeaderProtocol) WriteStructEnd(ctx context.Context) error {
return p.protocol.WriteStructEnd(ctx)
}
func (p *THeaderProtocol) WriteFieldBegin(ctx context.Context, name string, typeID TType, id int16) error {
return p.protocol.WriteFieldBegin(ctx, name, typeID, id)
}
func (p *THeaderProtocol) WriteFieldEnd(ctx context.Context) error {
return p.protocol.WriteFieldEnd(ctx)
}
func (p *THeaderProtocol) WriteFieldStop(ctx context.Context) error {
return p.protocol.WriteFieldStop(ctx)
}
func (p *THeaderProtocol) WriteMapBegin(ctx context.Context, keyType TType, valueType TType, size int) error {
return p.protocol.WriteMapBegin(ctx, keyType, valueType, size)
}
func (p *THeaderProtocol) WriteMapEnd(ctx context.Context) error {
return p.protocol.WriteMapEnd(ctx)
}
func (p *THeaderProtocol) WriteListBegin(ctx context.Context, elemType TType, size int) error {
return p.protocol.WriteListBegin(ctx, elemType, size)
}
func (p *THeaderProtocol) WriteListEnd(ctx context.Context) error {
return p.protocol.WriteListEnd(ctx)
}
func (p *THeaderProtocol) WriteSetBegin(ctx context.Context, elemType TType, size int) error {
return p.protocol.WriteSetBegin(ctx, elemType, size)
}
func (p *THeaderProtocol) WriteSetEnd(ctx context.Context) error {
return p.protocol.WriteSetEnd(ctx)
}
func (p *THeaderProtocol) WriteBool(ctx context.Context, value bool) error {
return p.protocol.WriteBool(ctx, value)
}
func (p *THeaderProtocol) WriteByte(ctx context.Context, value int8) error {
return p.protocol.WriteByte(ctx, value)
}
func (p *THeaderProtocol) WriteI16(ctx context.Context, value int16) error {
return p.protocol.WriteI16(ctx, value)
}
func (p *THeaderProtocol) WriteI32(ctx context.Context, value int32) error {
return p.protocol.WriteI32(ctx, value)
}
func (p *THeaderProtocol) WriteI64(ctx context.Context, value int64) error {
return p.protocol.WriteI64(ctx, value)
}
func (p *THeaderProtocol) WriteDouble(ctx context.Context, value float64) error {
return p.protocol.WriteDouble(ctx, value)
}
func (p *THeaderProtocol) WriteString(ctx context.Context, value string) error {
return p.protocol.WriteString(ctx, value)
}
func (p *THeaderProtocol) WriteBinary(ctx context.Context, value []byte) error {
return p.protocol.WriteBinary(ctx, value)
}
// ReadFrame calls underlying THeaderTransport's ReadFrame function.
func (p *THeaderProtocol) ReadFrame(ctx context.Context) error {
return p.transport.ReadFrame(ctx)
}
func (p *THeaderProtocol) ReadMessageBegin(ctx context.Context) (name string, typeID TMessageType, seqID int32, err error) {
if err = p.transport.ReadFrame(ctx); err != nil {
return
}
var newProto TProtocol
newProto, err = p.transport.Protocol().GetProtocol(p.transport)
if err != nil {
var tAppExc TApplicationException
if !errors.As(err, &tAppExc) {
return
}
if e := p.protocol.WriteMessageBegin(ctx, "", EXCEPTION, seqID); e != nil {
return
}
if e := tAppExc.Write(ctx, p.protocol); e != nil {
return
}
if e := p.protocol.WriteMessageEnd(ctx); e != nil {
return
}
if e := p.transport.Flush(ctx); e != nil {
return
}
return
}
PropagateTConfiguration(newProto, p.cfg)
p.protocol = newProto
return p.protocol.ReadMessageBegin(ctx)
}
func (p *THeaderProtocol) ReadMessageEnd(ctx context.Context) error {
return p.protocol.ReadMessageEnd(ctx)
}
func (p *THeaderProtocol) ReadStructBegin(ctx context.Context) (name string, err error) {
return p.protocol.ReadStructBegin(ctx)
}
func (p *THeaderProtocol) ReadStructEnd(ctx context.Context) error {
return p.protocol.ReadStructEnd(ctx)
}
func (p *THeaderProtocol) ReadFieldBegin(ctx context.Context) (name string, typeID TType, id int16, err error) {
return p.protocol.ReadFieldBegin(ctx)
}
func (p *THeaderProtocol) ReadFieldEnd(ctx context.Context) error {
return p.protocol.ReadFieldEnd(ctx)
}
func (p *THeaderProtocol) ReadMapBegin(ctx context.Context) (keyType TType, valueType TType, size int, err error) {
return p.protocol.ReadMapBegin(ctx)
}
func (p *THeaderProtocol) ReadMapEnd(ctx context.Context) error {
return p.protocol.ReadMapEnd(ctx)
}
func (p *THeaderProtocol) ReadListBegin(ctx context.Context) (elemType TType, size int, err error) {
return p.protocol.ReadListBegin(ctx)
}
func (p *THeaderProtocol) ReadListEnd(ctx context.Context) error {
return p.protocol.ReadListEnd(ctx)
}
func (p *THeaderProtocol) ReadSetBegin(ctx context.Context) (elemType TType, size int, err error) {
return p.protocol.ReadSetBegin(ctx)
}
func (p *THeaderProtocol) ReadSetEnd(ctx context.Context) error {
return p.protocol.ReadSetEnd(ctx)
}
func (p *THeaderProtocol) ReadBool(ctx context.Context) (value bool, err error) {
return p.protocol.ReadBool(ctx)
}
func (p *THeaderProtocol) ReadByte(ctx context.Context) (value int8, err error) {
return p.protocol.ReadByte(ctx)
}
func (p *THeaderProtocol) ReadI16(ctx context.Context) (value int16, err error) {
return p.protocol.ReadI16(ctx)
}
func (p *THeaderProtocol) ReadI32(ctx context.Context) (value int32, err error) {
return p.protocol.ReadI32(ctx)
}
func (p *THeaderProtocol) ReadI64(ctx context.Context) (value int64, err error) {
return p.protocol.ReadI64(ctx)
}
func (p *THeaderProtocol) ReadDouble(ctx context.Context) (value float64, err error) {
return p.protocol.ReadDouble(ctx)
}
func (p *THeaderProtocol) ReadString(ctx context.Context) (value string, err error) {
return p.protocol.ReadString(ctx)
}
func (p *THeaderProtocol) ReadBinary(ctx context.Context) (value []byte, err error) {
return p.protocol.ReadBinary(ctx)
}
func (p *THeaderProtocol) Skip(ctx context.Context, fieldType TType) error {
return p.protocol.Skip(ctx, fieldType)
}
// SetTConfiguration implements TConfigurationSetter.
func (p *THeaderProtocol) SetTConfiguration(cfg *TConfiguration) {
PropagateTConfiguration(p.transport, cfg)
PropagateTConfiguration(p.protocol, cfg)
p.cfg = cfg
}
var (
_ TConfigurationSetter = (*tHeaderProtocolFactory)(nil)
_ TConfigurationSetter = (*THeaderProtocol)(nil)
)

View File

@ -0,0 +1,810 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package thrift
import (
"bufio"
"bytes"
"compress/zlib"
"context"
"encoding/binary"
"errors"
"fmt"
"io"
"io/ioutil"
)
// Size in bytes for 32-bit ints.
const size32 = 4
type headerMeta struct {
MagicFlags uint32
SequenceID int32
HeaderLength uint16
}
const headerMetaSize = 10
type clientType int
const (
clientUnknown clientType = iota
clientHeaders
clientFramedBinary
clientUnframedBinary
clientFramedCompact
clientUnframedCompact
)
// Constants defined in THeader format:
// https://github.com/apache/thrift/blob/master/doc/specs/HeaderFormat.md
const (
THeaderHeaderMagic uint32 = 0x0fff0000
THeaderHeaderMask uint32 = 0xffff0000
THeaderFlagsMask uint32 = 0x0000ffff
THeaderMaxFrameSize uint32 = 0x3fffffff
)
// THeaderMap is the type of the header map in THeader transport.
type THeaderMap map[string]string
// THeaderProtocolID is the wrapped protocol id used in THeader.
type THeaderProtocolID int32
// Supported THeaderProtocolID values.
const (
THeaderProtocolBinary THeaderProtocolID = 0x00
THeaderProtocolCompact THeaderProtocolID = 0x02
THeaderProtocolDefault = THeaderProtocolBinary
)
// Declared globally to avoid repetitive allocations, not really used.
var globalMemoryBuffer = NewTMemoryBuffer()
// Validate checks whether the THeaderProtocolID is a valid/supported one.
func (id THeaderProtocolID) Validate() error {
_, err := id.GetProtocol(globalMemoryBuffer)
return err
}
// GetProtocol gets the corresponding TProtocol from the wrapped protocol id.
func (id THeaderProtocolID) GetProtocol(trans TTransport) (TProtocol, error) {
switch id {
default:
return nil, NewTApplicationException(
INVALID_PROTOCOL,
fmt.Sprintf("THeader protocol id %d not supported", id),
)
case THeaderProtocolBinary:
return NewTBinaryProtocolTransport(trans), nil
case THeaderProtocolCompact:
return NewTCompactProtocol(trans), nil
}
}
// THeaderTransformID defines the numeric id of the transform used.
type THeaderTransformID int32
// THeaderTransformID values.
//
// Values not defined here are not currently supported, namely HMAC and Snappy.
const (
TransformNone THeaderTransformID = iota // 0, no special handling
TransformZlib // 1, zlib
)
var supportedTransformIDs = map[THeaderTransformID]bool{
TransformNone: true,
TransformZlib: true,
}
// TransformReader is an io.ReadCloser that handles transforms reading.
type TransformReader struct {
io.Reader
closers []io.Closer
}
var _ io.ReadCloser = (*TransformReader)(nil)
// NewTransformReaderWithCapacity initializes a TransformReader with expected
// closers capacity.
//
// If you don't know the closers capacity beforehand, just use
//
// &TransformReader{Reader: baseReader}
//
// instead would be sufficient.
func NewTransformReaderWithCapacity(baseReader io.Reader, capacity int) *TransformReader {
return &TransformReader{
Reader: baseReader,
closers: make([]io.Closer, 0, capacity),
}
}
// Close calls the underlying closers in appropriate order,
// stops at and returns the first error encountered.
func (tr *TransformReader) Close() error {
// Call closers in reversed order
for i := len(tr.closers) - 1; i >= 0; i-- {
if err := tr.closers[i].Close(); err != nil {
return err
}
}
return nil
}
// AddTransform adds a transform.
func (tr *TransformReader) AddTransform(id THeaderTransformID) error {
switch id {
default:
return NewTApplicationException(
INVALID_TRANSFORM,
fmt.Sprintf("THeaderTransformID %d not supported", id),
)
case TransformNone:
// no-op
case TransformZlib:
readCloser, err := zlib.NewReader(tr.Reader)
if err != nil {
return err
}
tr.Reader = readCloser
tr.closers = append(tr.closers, readCloser)
}
return nil
}
// TransformWriter is an io.WriteCloser that handles transforms writing.
type TransformWriter struct {
io.Writer
closers []io.Closer
}
var _ io.WriteCloser = (*TransformWriter)(nil)
// NewTransformWriter creates a new TransformWriter with base writer and transforms.
func NewTransformWriter(baseWriter io.Writer, transforms []THeaderTransformID) (io.WriteCloser, error) {
writer := &TransformWriter{
Writer: baseWriter,
closers: make([]io.Closer, 0, len(transforms)),
}
for _, id := range transforms {
if err := writer.AddTransform(id); err != nil {
return nil, err
}
}
return writer, nil
}
// Close calls the underlying closers in appropriate order,
// stops at and returns the first error encountered.
func (tw *TransformWriter) Close() error {
// Call closers in reversed order
for i := len(tw.closers) - 1; i >= 0; i-- {
if err := tw.closers[i].Close(); err != nil {
return err
}
}
return nil
}
// AddTransform adds a transform.
func (tw *TransformWriter) AddTransform(id THeaderTransformID) error {
switch id {
default:
return NewTApplicationException(
INVALID_TRANSFORM,
fmt.Sprintf("THeaderTransformID %d not supported", id),
)
case TransformNone:
// no-op
case TransformZlib:
writeCloser := zlib.NewWriter(tw.Writer)
tw.Writer = writeCloser
tw.closers = append(tw.closers, writeCloser)
}
return nil
}
// THeaderInfoType is the type id of the info headers.
type THeaderInfoType int32
// Supported THeaderInfoType values.
const (
_ THeaderInfoType = iota // Skip 0
InfoKeyValue // 1
// Rest of the info types are not supported.
)
// THeaderTransport is a Transport mode that implements THeader.
//
// Note that THeaderTransport handles frame and zlib by itself,
// so the underlying transport should be a raw socket transports (TSocket or TSSLSocket),
// instead of rich transports like TZlibTransport or TFramedTransport.
type THeaderTransport struct {
SequenceID int32
Flags uint32
transport TTransport
// THeaderMap for read and write
readHeaders THeaderMap
writeHeaders THeaderMap
// Reading related variables.
reader *bufio.Reader
// When frame is detected, we read the frame fully into frameBuffer.
frameBuffer bytes.Buffer
// When it's non-nil, Read should read from frameReader instead of
// reader, and EOF error indicates end of frame instead of end of all
// transport.
frameReader io.ReadCloser
// Writing related variables
writeBuffer bytes.Buffer
writeTransforms []THeaderTransformID
clientType clientType
protocolID THeaderProtocolID
cfg *TConfiguration
// buffer is used in the following scenarios to avoid repetitive
// allocations, while 4 is big enough for all those scenarios:
//
// * header padding (max size 4)
// * write the frame size (size 4)
buffer [4]byte
}
var _ TTransport = (*THeaderTransport)(nil)
// Deprecated: Use NewTHeaderTransportConf instead.
func NewTHeaderTransport(trans TTransport) *THeaderTransport {
return NewTHeaderTransportConf(trans, &TConfiguration{
noPropagation: true,
})
}
// NewTHeaderTransportConf creates THeaderTransport from the
// underlying transport, with given TConfiguration attached.
//
// If trans is already a *THeaderTransport, it will be returned as is,
// but with TConfiguration overridden by the value passed in.
//
// The protocol ID in TConfiguration is only useful for client transports.
// For servers,
// the protocol ID will be overridden again to the one set by the client,
// to ensure that servers always speak the same dialect as the client.
func NewTHeaderTransportConf(trans TTransport, conf *TConfiguration) *THeaderTransport {
if ht, ok := trans.(*THeaderTransport); ok {
ht.SetTConfiguration(conf)
return ht
}
PropagateTConfiguration(trans, conf)
return &THeaderTransport{
transport: trans,
reader: bufio.NewReader(trans),
writeHeaders: make(THeaderMap),
protocolID: conf.GetTHeaderProtocolID(),
cfg: conf,
}
}
// Open calls the underlying transport's Open function.
func (t *THeaderTransport) Open() error {
return t.transport.Open()
}
// IsOpen calls the underlying transport's IsOpen function.
func (t *THeaderTransport) IsOpen() bool {
return t.transport.IsOpen()
}
// ReadFrame tries to read the frame header, guess the client type, and handle
// unframed clients.
func (t *THeaderTransport) ReadFrame(ctx context.Context) error {
if !t.needReadFrame() {
// No need to read frame, skipping.
return nil
}
// Peek and handle the first 32 bits.
// They could either be the length field of a framed message,
// or the first bytes of an unframed message.
var buf []byte
var err error
// This is also usually the first read from a connection,
// so handle retries around socket timeouts.
_, deadlineSet := ctx.Deadline()
for {
buf, err = t.reader.Peek(size32)
if deadlineSet && isTimeoutError(err) && ctx.Err() == nil {
// This is I/O timeout and we still have time,
// continue trying
continue
}
// For anything else, do not retry
break
}
if err != nil {
return err
}
frameSize := binary.BigEndian.Uint32(buf)
if frameSize&VERSION_MASK == VERSION_1 {
t.clientType = clientUnframedBinary
return nil
}
if buf[0] == COMPACT_PROTOCOL_ID && buf[1]&COMPACT_VERSION_MASK == COMPACT_VERSION {
t.clientType = clientUnframedCompact
return nil
}
// At this point it should be a framed message,
// sanity check on frameSize then discard the peeked part.
if frameSize > THeaderMaxFrameSize || frameSize > uint32(t.cfg.GetMaxFrameSize()) {
return NewTProtocolExceptionWithType(
SIZE_LIMIT,
errors.New("frame too large"),
)
}
t.reader.Discard(size32)
// Read the frame fully into frameBuffer.
_, err = io.CopyN(&t.frameBuffer, t.reader, int64(frameSize))
if err != nil {
return err
}
t.frameReader = ioutil.NopCloser(&t.frameBuffer)
// Peek and handle the next 32 bits.
buf = t.frameBuffer.Bytes()[:size32]
version := binary.BigEndian.Uint32(buf)
if version&THeaderHeaderMask == THeaderHeaderMagic {
t.clientType = clientHeaders
return t.parseHeaders(ctx, frameSize)
}
if version&VERSION_MASK == VERSION_1 {
t.clientType = clientFramedBinary
return nil
}
if buf[0] == COMPACT_PROTOCOL_ID && buf[1]&COMPACT_VERSION_MASK == COMPACT_VERSION {
t.clientType = clientFramedCompact
return nil
}
if err := t.endOfFrame(); err != nil {
return err
}
return NewTProtocolExceptionWithType(
NOT_IMPLEMENTED,
errors.New("unsupported client transport type"),
)
}
// endOfFrame does end of frame handling.
//
// It closes frameReader, and also resets frame related states.
func (t *THeaderTransport) endOfFrame() error {
defer func() {
t.frameBuffer.Reset()
t.frameReader = nil
}()
return t.frameReader.Close()
}
func (t *THeaderTransport) parseHeaders(ctx context.Context, frameSize uint32) error {
if t.clientType != clientHeaders {
return nil
}
var err error
var meta headerMeta
if err = binary.Read(&t.frameBuffer, binary.BigEndian, &meta); err != nil {
return err
}
frameSize -= headerMetaSize
t.Flags = meta.MagicFlags & THeaderFlagsMask
t.SequenceID = meta.SequenceID
headerLength := int64(meta.HeaderLength) * 4
if int64(frameSize) < headerLength {
return NewTProtocolExceptionWithType(
SIZE_LIMIT,
errors.New("header size is larger than the whole frame"),
)
}
headerBuf := NewTMemoryBuffer()
_, err = io.CopyN(headerBuf, &t.frameBuffer, headerLength)
if err != nil {
return err
}
hp := NewTCompactProtocol(headerBuf)
hp.SetTConfiguration(t.cfg)
// At this point the header is already read into headerBuf,
// and t.frameBuffer starts from the actual payload.
protoID, err := hp.readVarint32()
if err != nil {
return err
}
t.protocolID = THeaderProtocolID(protoID)
var transformCount int32
transformCount, err = hp.readVarint32()
if err != nil {
return err
}
if transformCount > 0 {
reader := NewTransformReaderWithCapacity(
&t.frameBuffer,
int(transformCount),
)
t.frameReader = reader
transformIDs := make([]THeaderTransformID, transformCount)
for i := 0; i < int(transformCount); i++ {
id, err := hp.readVarint32()
if err != nil {
return err
}
transformIDs[i] = THeaderTransformID(id)
}
// The transform IDs on the wire was added based on the order of
// writing, so on the reading side we need to reverse the order.
for i := transformCount - 1; i >= 0; i-- {
id := transformIDs[i]
if err := reader.AddTransform(id); err != nil {
return err
}
}
}
// The info part does not use the transforms yet, so it's
// important to continue using headerBuf.
headers := make(THeaderMap)
for {
infoType, err := hp.readVarint32()
if errors.Is(err, io.EOF) {
break
}
if err != nil {
return err
}
if THeaderInfoType(infoType) == InfoKeyValue {
count, err := hp.readVarint32()
if err != nil {
return err
}
for i := 0; i < int(count); i++ {
key, err := hp.ReadString(ctx)
if err != nil {
return err
}
value, err := hp.ReadString(ctx)
if err != nil {
return err
}
headers[key] = value
}
} else {
// Skip reading info section on the first
// unsupported info type.
break
}
}
t.readHeaders = headers
return nil
}
func (t *THeaderTransport) needReadFrame() bool {
if t.clientType == clientUnknown {
// This is a new connection that's never read before.
return true
}
if t.isFramed() && t.frameReader == nil {
// We just finished the last frame.
return true
}
return false
}
func (t *THeaderTransport) Read(p []byte) (read int, err error) {
// Here using context.Background instead of a context passed in is safe.
// First is that there's no way to pass context into this function.
// Then, 99% of the case when calling this Read frame is already read
// into frameReader. ReadFrame here is more of preventing bugs that
// didn't call ReadFrame before calling Read.
err = t.ReadFrame(context.Background())
if err != nil {
return
}
if t.frameReader != nil {
read, err = t.frameReader.Read(p)
if err == nil && t.frameBuffer.Len() <= 0 {
// the last Read finished the frame, do endOfFrame
// handling here.
err = t.endOfFrame()
} else if err == io.EOF {
err = t.endOfFrame()
if err != nil {
return
}
if read == 0 {
// Try to read the next frame when we hit EOF
// (end of frame) immediately.
// When we got here, it means the last read
// finished the previous frame, but didn't
// do endOfFrame handling yet.
// We have to read the next frame here,
// as otherwise we would return 0 and nil,
// which is a case not handled well by most
// protocol implementations.
return t.Read(p)
}
}
return
}
return t.reader.Read(p)
}
// Write writes data to the write buffer.
//
// You need to call Flush to actually write them to the transport.
func (t *THeaderTransport) Write(p []byte) (int, error) {
return t.writeBuffer.Write(p)
}
// Flush writes the appropriate header and the write buffer to the underlying transport.
func (t *THeaderTransport) Flush(ctx context.Context) error {
if t.writeBuffer.Len() == 0 {
return nil
}
defer t.writeBuffer.Reset()
switch t.clientType {
default:
fallthrough
case clientUnknown:
t.clientType = clientHeaders
fallthrough
case clientHeaders:
headers := NewTMemoryBuffer()
hp := NewTCompactProtocol(headers)
hp.SetTConfiguration(t.cfg)
if _, err := hp.writeVarint32(int32(t.protocolID)); err != nil {
return NewTTransportExceptionFromError(err)
}
if _, err := hp.writeVarint32(int32(len(t.writeTransforms))); err != nil {
return NewTTransportExceptionFromError(err)
}
for _, transform := range t.writeTransforms {
if _, err := hp.writeVarint32(int32(transform)); err != nil {
return NewTTransportExceptionFromError(err)
}
}
if len(t.writeHeaders) > 0 {
if _, err := hp.writeVarint32(int32(InfoKeyValue)); err != nil {
return NewTTransportExceptionFromError(err)
}
if _, err := hp.writeVarint32(int32(len(t.writeHeaders))); err != nil {
return NewTTransportExceptionFromError(err)
}
for key, value := range t.writeHeaders {
if err := hp.WriteString(ctx, key); err != nil {
return NewTTransportExceptionFromError(err)
}
if err := hp.WriteString(ctx, value); err != nil {
return NewTTransportExceptionFromError(err)
}
}
}
padding := 4 - headers.Len()%4
if padding < 4 {
buf := t.buffer[:padding]
for i := range buf {
buf[i] = 0
}
if _, err := headers.Write(buf); err != nil {
return NewTTransportExceptionFromError(err)
}
}
var payload bytes.Buffer
meta := headerMeta{
MagicFlags: THeaderHeaderMagic + t.Flags&THeaderFlagsMask,
SequenceID: t.SequenceID,
HeaderLength: uint16(headers.Len() / 4),
}
if err := binary.Write(&payload, binary.BigEndian, meta); err != nil {
return NewTTransportExceptionFromError(err)
}
if _, err := io.Copy(&payload, headers); err != nil {
return NewTTransportExceptionFromError(err)
}
writer, err := NewTransformWriter(&payload, t.writeTransforms)
if err != nil {
return NewTTransportExceptionFromError(err)
}
if _, err := io.Copy(writer, &t.writeBuffer); err != nil {
return NewTTransportExceptionFromError(err)
}
if err := writer.Close(); err != nil {
return NewTTransportExceptionFromError(err)
}
// First write frame length
buf := t.buffer[:size32]
binary.BigEndian.PutUint32(buf, uint32(payload.Len()))
if _, err := t.transport.Write(buf); err != nil {
return NewTTransportExceptionFromError(err)
}
// Then write the payload
if _, err := io.Copy(t.transport, &payload); err != nil {
return NewTTransportExceptionFromError(err)
}
case clientFramedBinary, clientFramedCompact:
buf := t.buffer[:size32]
binary.BigEndian.PutUint32(buf, uint32(t.writeBuffer.Len()))
if _, err := t.transport.Write(buf); err != nil {
return NewTTransportExceptionFromError(err)
}
fallthrough
case clientUnframedBinary, clientUnframedCompact:
if _, err := io.Copy(t.transport, &t.writeBuffer); err != nil {
return NewTTransportExceptionFromError(err)
}
}
select {
default:
case <-ctx.Done():
return NewTTransportExceptionFromError(ctx.Err())
}
return t.transport.Flush(ctx)
}
// Close closes the transport, along with its underlying transport.
func (t *THeaderTransport) Close() error {
if err := t.Flush(context.Background()); err != nil {
return err
}
return t.transport.Close()
}
// RemainingBytes calls underlying transport's RemainingBytes.
//
// Even in framed cases, because of all the possible compression transforms
// involved, the remaining frame size is likely to be different from the actual
// remaining readable bytes, so we don't bother to keep tracking the remaining
// frame size by ourselves and just use the underlying transport's
// RemainingBytes directly.
func (t *THeaderTransport) RemainingBytes() uint64 {
return t.transport.RemainingBytes()
}
// GetReadHeaders returns the THeaderMap read from transport.
func (t *THeaderTransport) GetReadHeaders() THeaderMap {
return t.readHeaders
}
// SetWriteHeader sets a header for write.
func (t *THeaderTransport) SetWriteHeader(key, value string) {
t.writeHeaders[key] = value
}
// ClearWriteHeaders clears all write headers previously set.
func (t *THeaderTransport) ClearWriteHeaders() {
t.writeHeaders = make(THeaderMap)
}
// AddTransform add a transform for writing.
func (t *THeaderTransport) AddTransform(transform THeaderTransformID) error {
if !supportedTransformIDs[transform] {
return NewTProtocolExceptionWithType(
NOT_IMPLEMENTED,
fmt.Errorf("THeaderTransformID %d not supported", transform),
)
}
t.writeTransforms = append(t.writeTransforms, transform)
return nil
}
// Protocol returns the wrapped protocol id used in this THeaderTransport.
func (t *THeaderTransport) Protocol() THeaderProtocolID {
switch t.clientType {
default:
return t.protocolID
case clientFramedBinary, clientUnframedBinary:
return THeaderProtocolBinary
case clientFramedCompact, clientUnframedCompact:
return THeaderProtocolCompact
}
}
func (t *THeaderTransport) isFramed() bool {
switch t.clientType {
default:
return false
case clientHeaders, clientFramedBinary, clientFramedCompact:
return true
}
}
// SetTConfiguration implements TConfigurationSetter.
func (t *THeaderTransport) SetTConfiguration(cfg *TConfiguration) {
PropagateTConfiguration(t.transport, cfg)
t.cfg = cfg
}
// THeaderTransportFactory is a TTransportFactory implementation to create
// THeaderTransport.
//
// It also implements TConfigurationSetter.
type THeaderTransportFactory struct {
// The underlying factory, could be nil.
Factory TTransportFactory
cfg *TConfiguration
}
// Deprecated: Use NewTHeaderTransportFactoryConf instead.
func NewTHeaderTransportFactory(factory TTransportFactory) TTransportFactory {
return NewTHeaderTransportFactoryConf(factory, &TConfiguration{
noPropagation: true,
})
}
// NewTHeaderTransportFactoryConf creates a new *THeaderTransportFactory with
// the given *TConfiguration.
func NewTHeaderTransportFactoryConf(factory TTransportFactory, conf *TConfiguration) TTransportFactory {
return &THeaderTransportFactory{
Factory: factory,
cfg: conf,
}
}
// GetTransport implements TTransportFactory.
func (f *THeaderTransportFactory) GetTransport(trans TTransport) (TTransport, error) {
if f.Factory != nil {
t, err := f.Factory.GetTransport(trans)
if err != nil {
return nil, err
}
return NewTHeaderTransportConf(t, f.cfg), nil
}
return NewTHeaderTransportConf(trans, f.cfg), nil
}
// SetTConfiguration implements TConfigurationSetter.
func (f *THeaderTransportFactory) SetTConfiguration(cfg *TConfiguration) {
PropagateTConfiguration(f.Factory, f.cfg)
f.cfg = cfg
}
var (
_ TConfigurationSetter = (*THeaderTransportFactory)(nil)
_ TConfigurationSetter = (*THeaderTransport)(nil)
)

View File

@ -0,0 +1,59 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package thrift
import (
"log"
"os"
)
// Logger is a simple wrapper of a logging function.
//
// In reality the users might actually use different logging libraries, and they
// are not always compatible with each other.
//
// Logger is meant to be a simple common ground that it's easy to wrap whatever
// logging library they use into.
//
// See https://issues.apache.org/jira/browse/THRIFT-4985 for the design
// discussion behind it.
type Logger func(msg string)
// NopLogger is a Logger implementation that does nothing.
func NopLogger(msg string) {}
// StdLogger wraps stdlib log package into a Logger.
//
// If logger passed in is nil, it will fallback to use stderr and default flags.
func StdLogger(logger *log.Logger) Logger {
if logger == nil {
logger = log.New(os.Stderr, "", log.LstdFlags)
}
return func(msg string) {
logger.Print(msg)
}
}
func fallbackLogger(logger Logger) Logger {
if logger == nil {
return StdLogger(nil)
}
return logger
}

View File

@ -21,6 +21,7 @@ package thrift
import ( import (
"bytes" "bytes"
"context"
) )
// Memory buffer-based implementation of the TTransport interface. // Memory buffer-based implementation of the TTransport interface.
@ -33,14 +34,14 @@ type TMemoryBufferTransportFactory struct {
size int size int
} }
func (p *TMemoryBufferTransportFactory) GetTransport(trans TTransport) TTransport { func (p *TMemoryBufferTransportFactory) GetTransport(trans TTransport) (TTransport, error) {
if trans != nil { if trans != nil {
t, ok := trans.(*TMemoryBuffer) t, ok := trans.(*TMemoryBuffer)
if ok && t.size > 0 { if ok && t.size > 0 {
return NewTMemoryBufferLen(t.size) return NewTMemoryBufferLen(t.size), nil
} }
} }
return NewTMemoryBufferLen(p.size) return NewTMemoryBufferLen(p.size), nil
} }
func NewTMemoryBufferTransportFactory(size int) *TMemoryBufferTransportFactory { func NewTMemoryBufferTransportFactory(size int) *TMemoryBufferTransportFactory {
@ -70,7 +71,7 @@ func (p *TMemoryBuffer) Close() error {
} }
// Flushing a memory buffer is a no-op // Flushing a memory buffer is a no-op
func (p *TMemoryBuffer) Flush() error { func (p *TMemoryBuffer) Flush(ctx context.Context) error {
return nil return nil
} }

View File

@ -69,14 +69,14 @@ func NewNumericFromDouble(dValue float64) Numeric {
func NewNumericFromI64(iValue int64) Numeric { func NewNumericFromI64(iValue int64) Numeric {
dValue := float64(iValue) dValue := float64(iValue)
sValue := string(iValue) sValue := strconv.FormatInt(iValue, 10)
isNil := false isNil := false
return &numeric{iValue: iValue, dValue: dValue, sValue: sValue, isNil: isNil} return &numeric{iValue: iValue, dValue: dValue, sValue: sValue, isNil: isNil}
} }
func NewNumericFromI32(iValue int32) Numeric { func NewNumericFromI32(iValue int32) Numeric {
dValue := float64(iValue) dValue := float64(iValue)
sValue := string(iValue) sValue := strconv.FormatInt(int64(iValue), 10)
isNil := false isNil := false
return &numeric{iValue: int64(iValue), dValue: dValue, sValue: sValue, isNil: isNil} return &numeric{iValue: int64(iValue), dValue: dValue, sValue: sValue, isNil: isNil}
} }

View File

@ -0,0 +1,80 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package thrift
import "context"
// A processor is a generic object which operates upon an input stream and
// writes to some output stream.
type TProcessor interface {
Process(ctx context.Context, in, out TProtocol) (bool, TException)
// ProcessorMap returns a map of thrift method names to TProcessorFunctions.
ProcessorMap() map[string]TProcessorFunction
// AddToProcessorMap adds the given TProcessorFunction to the internal
// processor map at the given key.
//
// If one is already set at the given key, it will be replaced with the new
// TProcessorFunction.
AddToProcessorMap(string, TProcessorFunction)
}
type TProcessorFunction interface {
Process(ctx context.Context, seqId int32, in, out TProtocol) (bool, TException)
}
// The default processor factory just returns a singleton
// instance.
type TProcessorFactory interface {
GetProcessor(trans TTransport) TProcessor
}
type tProcessorFactory struct {
processor TProcessor
}
func NewTProcessorFactory(p TProcessor) TProcessorFactory {
return &tProcessorFactory{processor: p}
}
func (p *tProcessorFactory) GetProcessor(trans TTransport) TProcessor {
return p.processor
}
/**
* The default processor factory just returns a singleton
* instance.
*/
type TProcessorFunctionFactory interface {
GetProcessorFunction(trans TTransport) TProcessorFunction
}
type tProcessorFunctionFactory struct {
processor TProcessorFunction
}
func NewTProcessorFunctionFactory(p TProcessorFunction) TProcessorFunctionFactory {
return &tProcessorFunctionFactory{processor: p}
}
func (p *tProcessorFunctionFactory) GetProcessorFunction(trans TTransport) TProcessorFunction {
return p.processor
}

View File

@ -20,7 +20,9 @@
package thrift package thrift
import ( import (
"context"
"errors" "errors"
"fmt"
) )
const ( const (
@ -29,51 +31,51 @@ const (
) )
type TProtocol interface { type TProtocol interface {
WriteMessageBegin(name string, typeId TMessageType, seqid int32) error WriteMessageBegin(ctx context.Context, name string, typeId TMessageType, seqid int32) error
WriteMessageEnd() error WriteMessageEnd(ctx context.Context) error
WriteStructBegin(name string) error WriteStructBegin(ctx context.Context, name string) error
WriteStructEnd() error WriteStructEnd(ctx context.Context) error
WriteFieldBegin(name string, typeId TType, id int16) error WriteFieldBegin(ctx context.Context, name string, typeId TType, id int16) error
WriteFieldEnd() error WriteFieldEnd(ctx context.Context) error
WriteFieldStop() error WriteFieldStop(ctx context.Context) error
WriteMapBegin(keyType TType, valueType TType, size int) error WriteMapBegin(ctx context.Context, keyType TType, valueType TType, size int) error
WriteMapEnd() error WriteMapEnd(ctx context.Context) error
WriteListBegin(elemType TType, size int) error WriteListBegin(ctx context.Context, elemType TType, size int) error
WriteListEnd() error WriteListEnd(ctx context.Context) error
WriteSetBegin(elemType TType, size int) error WriteSetBegin(ctx context.Context, elemType TType, size int) error
WriteSetEnd() error WriteSetEnd(ctx context.Context) error
WriteBool(value bool) error WriteBool(ctx context.Context, value bool) error
WriteByte(value int8) error WriteByte(ctx context.Context, value int8) error
WriteI16(value int16) error WriteI16(ctx context.Context, value int16) error
WriteI32(value int32) error WriteI32(ctx context.Context, value int32) error
WriteI64(value int64) error WriteI64(ctx context.Context, value int64) error
WriteDouble(value float64) error WriteDouble(ctx context.Context, value float64) error
WriteString(value string) error WriteString(ctx context.Context, value string) error
WriteBinary(value []byte) error WriteBinary(ctx context.Context, value []byte) error
ReadMessageBegin() (name string, typeId TMessageType, seqid int32, err error) ReadMessageBegin(ctx context.Context) (name string, typeId TMessageType, seqid int32, err error)
ReadMessageEnd() error ReadMessageEnd(ctx context.Context) error
ReadStructBegin() (name string, err error) ReadStructBegin(ctx context.Context) (name string, err error)
ReadStructEnd() error ReadStructEnd(ctx context.Context) error
ReadFieldBegin() (name string, typeId TType, id int16, err error) ReadFieldBegin(ctx context.Context) (name string, typeId TType, id int16, err error)
ReadFieldEnd() error ReadFieldEnd(ctx context.Context) error
ReadMapBegin() (keyType TType, valueType TType, size int, err error) ReadMapBegin(ctx context.Context) (keyType TType, valueType TType, size int, err error)
ReadMapEnd() error ReadMapEnd(ctx context.Context) error
ReadListBegin() (elemType TType, size int, err error) ReadListBegin(ctx context.Context) (elemType TType, size int, err error)
ReadListEnd() error ReadListEnd(ctx context.Context) error
ReadSetBegin() (elemType TType, size int, err error) ReadSetBegin(ctx context.Context) (elemType TType, size int, err error)
ReadSetEnd() error ReadSetEnd(ctx context.Context) error
ReadBool() (value bool, err error) ReadBool(ctx context.Context) (value bool, err error)
ReadByte() (value int8, err error) ReadByte(ctx context.Context) (value int8, err error)
ReadI16() (value int16, err error) ReadI16(ctx context.Context) (value int16, err error)
ReadI32() (value int32, err error) ReadI32(ctx context.Context) (value int32, err error)
ReadI64() (value int64, err error) ReadI64(ctx context.Context) (value int64, err error)
ReadDouble() (value float64, err error) ReadDouble(ctx context.Context) (value float64, err error)
ReadString() (value string, err error) ReadString(ctx context.Context) (value string, err error)
ReadBinary() (value []byte, err error) ReadBinary(ctx context.Context) (value []byte, err error)
Skip(fieldType TType) (err error) Skip(ctx context.Context, fieldType TType) (err error)
Flush() (err error) Flush(ctx context.Context) (err error)
Transport() TTransport Transport() TTransport
} }
@ -82,94 +84,94 @@ type TProtocol interface {
const DEFAULT_RECURSION_DEPTH = 64 const DEFAULT_RECURSION_DEPTH = 64
// Skips over the next data element from the provided input TProtocol object. // Skips over the next data element from the provided input TProtocol object.
func SkipDefaultDepth(prot TProtocol, typeId TType) (err error) { func SkipDefaultDepth(ctx context.Context, prot TProtocol, typeId TType) (err error) {
return Skip(prot, typeId, DEFAULT_RECURSION_DEPTH) return Skip(ctx, prot, typeId, DEFAULT_RECURSION_DEPTH)
} }
// Skips over the next data element from the provided input TProtocol object. // Skips over the next data element from the provided input TProtocol object.
func Skip(self TProtocol, fieldType TType, maxDepth int) (err error) { func Skip(ctx context.Context, self TProtocol, fieldType TType, maxDepth int) (err error) {
if maxDepth <= 0 { if maxDepth <= 0 {
return NewTProtocolExceptionWithType( DEPTH_LIMIT, errors.New("Depth limit exceeded")) return NewTProtocolExceptionWithType(DEPTH_LIMIT, errors.New("Depth limit exceeded"))
} }
switch fieldType { switch fieldType {
case STOP:
return
case BOOL: case BOOL:
_, err = self.ReadBool() _, err = self.ReadBool(ctx)
return return
case BYTE: case BYTE:
_, err = self.ReadByte() _, err = self.ReadByte(ctx)
return return
case I16: case I16:
_, err = self.ReadI16() _, err = self.ReadI16(ctx)
return return
case I32: case I32:
_, err = self.ReadI32() _, err = self.ReadI32(ctx)
return return
case I64: case I64:
_, err = self.ReadI64() _, err = self.ReadI64(ctx)
return return
case DOUBLE: case DOUBLE:
_, err = self.ReadDouble() _, err = self.ReadDouble(ctx)
return return
case STRING: case STRING:
_, err = self.ReadString() _, err = self.ReadString(ctx)
return return
case STRUCT: case STRUCT:
if _, err = self.ReadStructBegin(); err != nil { if _, err = self.ReadStructBegin(ctx); err != nil {
return err return err
} }
for { for {
_, typeId, _, _ := self.ReadFieldBegin() _, typeId, _, _ := self.ReadFieldBegin(ctx)
if typeId == STOP { if typeId == STOP {
break break
} }
err := Skip(self, typeId, maxDepth-1) err := Skip(ctx, self, typeId, maxDepth-1)
if err != nil { if err != nil {
return err return err
} }
self.ReadFieldEnd() self.ReadFieldEnd(ctx)
} }
return self.ReadStructEnd() return self.ReadStructEnd(ctx)
case MAP: case MAP:
keyType, valueType, size, err := self.ReadMapBegin() keyType, valueType, size, err := self.ReadMapBegin(ctx)
if err != nil { if err != nil {
return err return err
} }
for i := 0; i < size; i++ { for i := 0; i < size; i++ {
err := Skip(self, keyType, maxDepth-1) err := Skip(ctx, self, keyType, maxDepth-1)
if err != nil { if err != nil {
return err return err
} }
self.Skip(valueType) self.Skip(ctx, valueType)
} }
return self.ReadMapEnd() return self.ReadMapEnd(ctx)
case SET: case SET:
elemType, size, err := self.ReadSetBegin() elemType, size, err := self.ReadSetBegin(ctx)
if err != nil { if err != nil {
return err return err
} }
for i := 0; i < size; i++ { for i := 0; i < size; i++ {
err := Skip(self, elemType, maxDepth-1) err := Skip(ctx, self, elemType, maxDepth-1)
if err != nil { if err != nil {
return err return err
} }
} }
return self.ReadSetEnd() return self.ReadSetEnd(ctx)
case LIST: case LIST:
elemType, size, err := self.ReadListBegin() elemType, size, err := self.ReadListBegin(ctx)
if err != nil { if err != nil {
return err return err
} }
for i := 0; i < size; i++ { for i := 0; i < size; i++ {
err := Skip(self, elemType, maxDepth-1) err := Skip(ctx, self, elemType, maxDepth-1)
if err != nil { if err != nil {
return err return err
} }
} }
return self.ReadListEnd() return self.ReadListEnd(ctx)
default:
return NewTProtocolExceptionWithType(INVALID_DATA, errors.New(fmt.Sprintf("Unknown data type %d", fieldType)))
} }
return nil return nil
} }

View File

@ -21,6 +21,7 @@ package thrift
import ( import (
"encoding/base64" "encoding/base64"
"errors"
) )
// Thrift Protocol exception // Thrift Protocol exception
@ -40,8 +41,15 @@ const (
) )
type tProtocolException struct { type tProtocolException struct {
typeId int typeId int
message string err error
msg string
}
var _ TProtocolException = (*tProtocolException)(nil)
func (tProtocolException) TExceptionType() TExceptionType {
return TExceptionTypeProtocol
} }
func (p *tProtocolException) TypeId() int { func (p *tProtocolException) TypeId() int {
@ -49,30 +57,48 @@ func (p *tProtocolException) TypeId() int {
} }
func (p *tProtocolException) String() string { func (p *tProtocolException) String() string {
return p.message return p.msg
} }
func (p *tProtocolException) Error() string { func (p *tProtocolException) Error() string {
return p.message return p.msg
}
func (p *tProtocolException) Unwrap() error {
return p.err
} }
func NewTProtocolException(err error) TProtocolException { func NewTProtocolException(err error) TProtocolException {
if err == nil { if err == nil {
return nil return nil
} }
if e,ok := err.(TProtocolException); ok {
if e, ok := err.(TProtocolException); ok {
return e return e
} }
if _, ok := err.(base64.CorruptInputError); ok {
return &tProtocolException{INVALID_DATA, err.Error()} if errors.As(err, new(base64.CorruptInputError)) {
return NewTProtocolExceptionWithType(INVALID_DATA, err)
} }
return &tProtocolException{UNKNOWN_PROTOCOL_EXCEPTION, err.Error()}
return NewTProtocolExceptionWithType(UNKNOWN_PROTOCOL_EXCEPTION, err)
} }
func NewTProtocolExceptionWithType(errType int, err error) TProtocolException { func NewTProtocolExceptionWithType(errType int, err error) TProtocolException {
if err == nil { if err == nil {
return nil return nil
} }
return &tProtocolException{errType, err.Error()} return &tProtocolException{
typeId: errType,
err: err,
msg: err.Error(),
}
} }
func prependTProtocolException(prepend string, err TProtocolException) TProtocolException {
return &tProtocolException{
typeId: err.TypeId(),
err: err,
msg: prepend + err.Error(),
}
}

View File

@ -0,0 +1,94 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package thrift
import (
"context"
)
// See https://godoc.org/context#WithValue on why do we need the unexported typedefs.
type responseHelperKey struct{}
// TResponseHelper defines a object with a set of helper functions that can be
// retrieved from the context object passed into server handler functions.
//
// Use GetResponseHelper to retrieve the injected TResponseHelper implementation
// from the context object.
//
// The zero value of TResponseHelper is valid with all helper functions being
// no-op.
type TResponseHelper struct {
// THeader related functions
*THeaderResponseHelper
}
// THeaderResponseHelper defines THeader related TResponseHelper functions.
//
// The zero value of *THeaderResponseHelper is valid with all helper functions
// being no-op.
type THeaderResponseHelper struct {
proto *THeaderProtocol
}
// NewTHeaderResponseHelper creates a new THeaderResponseHelper from the
// underlying TProtocol.
func NewTHeaderResponseHelper(proto TProtocol) *THeaderResponseHelper {
if hp, ok := proto.(*THeaderProtocol); ok {
return &THeaderResponseHelper{
proto: hp,
}
}
return nil
}
// SetHeader sets a response header.
//
// It's no-op if the underlying protocol/transport does not support THeader.
func (h *THeaderResponseHelper) SetHeader(key, value string) {
if h != nil && h.proto != nil {
h.proto.SetWriteHeader(key, value)
}
}
// ClearHeaders clears all the response headers previously set.
//
// It's no-op if the underlying protocol/transport does not support THeader.
func (h *THeaderResponseHelper) ClearHeaders() {
if h != nil && h.proto != nil {
h.proto.ClearWriteHeaders()
}
}
// GetResponseHelper retrieves the TResponseHelper implementation injected into
// the context object.
//
// If no helper was found in the context object, a nop helper with ok == false
// will be returned.
func GetResponseHelper(ctx context.Context) (helper TResponseHelper, ok bool) {
if v := ctx.Value(responseHelperKey{}); v != nil {
helper, ok = v.(TResponseHelper)
}
return
}
// SetResponseHelper injects TResponseHelper into the context object.
func SetResponseHelper(ctx context.Context, helper TResponseHelper) context.Context {
return context.WithValue(ctx, responseHelperKey{}, helper)
}

View File

@ -19,7 +19,10 @@
package thrift package thrift
import "io" import (
"errors"
"io"
)
type RichTransport struct { type RichTransport struct {
TTransport TTransport
@ -49,7 +52,7 @@ func (r *RichTransport) RemainingBytes() (num_bytes uint64) {
func readByte(r io.Reader) (c byte, err error) { func readByte(r io.Reader) (c byte, err error) {
v := [1]byte{0} v := [1]byte{0}
n, err := r.Read(v[0:1]) n, err := r.Read(v[0:1])
if n > 0 && (err == nil || err == io.EOF) { if n > 0 && (err == nil || errors.Is(err, io.EOF)) {
return v[0], nil return v[0], nil
} }
if n > 0 && err != nil { if n > 0 && err != nil {
@ -66,4 +69,3 @@ func writeByte(w io.Writer, c byte) error {
_, err := w.Write(v[0:1]) _, err := w.Write(v[0:1])
return err return err
} }

View File

@ -19,57 +19,118 @@
package thrift package thrift
import (
"context"
"sync"
)
type TSerializer struct { type TSerializer struct {
Transport *TMemoryBuffer Transport *TMemoryBuffer
Protocol TProtocol Protocol TProtocol
} }
type TStruct interface { type TStruct interface {
Write(p TProtocol) error Write(ctx context.Context, p TProtocol) error
Read(p TProtocol) error Read(ctx context.Context, p TProtocol) error
} }
func NewTSerializer() *TSerializer { func NewTSerializer() *TSerializer {
transport := NewTMemoryBufferLen(1024) transport := NewTMemoryBufferLen(1024)
protocol := NewTBinaryProtocolFactoryDefault().GetProtocol(transport) protocol := NewTBinaryProtocolTransport(transport)
return &TSerializer{ return &TSerializer{
transport, Transport: transport,
protocol} Protocol: protocol,
}
} }
func (t *TSerializer) WriteString(msg TStruct) (s string, err error) { func (t *TSerializer) WriteString(ctx context.Context, msg TStruct) (s string, err error) {
t.Transport.Reset() t.Transport.Reset()
if err = msg.Write(t.Protocol); err != nil { if err = msg.Write(ctx, t.Protocol); err != nil {
return return
} }
if err = t.Protocol.Flush(); err != nil { if err = t.Protocol.Flush(ctx); err != nil {
return return
} }
if err = t.Transport.Flush(); err != nil { if err = t.Transport.Flush(ctx); err != nil {
return return
} }
return t.Transport.String(), nil return t.Transport.String(), nil
} }
func (t *TSerializer) Write(msg TStruct) (b []byte, err error) { func (t *TSerializer) Write(ctx context.Context, msg TStruct) (b []byte, err error) {
t.Transport.Reset() t.Transport.Reset()
if err = msg.Write(t.Protocol); err != nil { if err = msg.Write(ctx, t.Protocol); err != nil {
return return
} }
if err = t.Protocol.Flush(); err != nil { if err = t.Protocol.Flush(ctx); err != nil {
return return
} }
if err = t.Transport.Flush(); err != nil { if err = t.Transport.Flush(ctx); err != nil {
return return
} }
b = append(b, t.Transport.Bytes()...) b = append(b, t.Transport.Bytes()...)
return return
} }
// TSerializerPool is the thread-safe version of TSerializer, it uses resource
// pool of TSerializer under the hood.
//
// It must be initialized with either NewTSerializerPool or
// NewTSerializerPoolSizeFactory.
type TSerializerPool struct {
pool sync.Pool
}
// NewTSerializerPool creates a new TSerializerPool.
//
// NewTSerializer can be used as the arg here.
func NewTSerializerPool(f func() *TSerializer) *TSerializerPool {
return &TSerializerPool{
pool: sync.Pool{
New: func() interface{} {
return f()
},
},
}
}
// NewTSerializerPoolSizeFactory creates a new TSerializerPool with the given
// size and protocol factory.
//
// Note that the size is not the limit. The TMemoryBuffer underneath can grow
// larger than that. It just dictates the initial size.
func NewTSerializerPoolSizeFactory(size int, factory TProtocolFactory) *TSerializerPool {
return &TSerializerPool{
pool: sync.Pool{
New: func() interface{} {
transport := NewTMemoryBufferLen(size)
protocol := factory.GetProtocol(transport)
return &TSerializer{
Transport: transport,
Protocol: protocol,
}
},
},
}
}
func (t *TSerializerPool) WriteString(ctx context.Context, msg TStruct) (string, error) {
s := t.pool.Get().(*TSerializer)
defer t.pool.Put(s)
return s.WriteString(ctx, msg)
}
func (t *TSerializerPool) Write(ctx context.Context, msg TStruct) ([]byte, error) {
s := t.pool.Get().(*TSerializer)
defer t.pool.Put(s)
return s.Write(ctx, msg)
}

View File

@ -0,0 +1,34 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package thrift
// Server transport. Object which provides client transports.
type TServerTransport interface {
Listen() error
Accept() (TTransport, error)
Close() error
// Optional method implementation. This signals to the server transport
// that it should break out of any accept() or listen() that it is currently
// blocked on. This method, if implemented, MUST be thread safe, as it may
// be called from a different thread context than the other TServerTransport
// methods.
Interrupt() error
}

View File

@ -22,8 +22,10 @@ package thrift
import ( import (
"bufio" "bufio"
"bytes" "bytes"
"context"
"encoding/base64" "encoding/base64"
"encoding/json" "encoding/json"
"errors"
"fmt" "fmt"
"io" "io"
"math" "math"
@ -33,12 +35,13 @@ import (
type _ParseContext int type _ParseContext int
const ( const (
_CONTEXT_IN_TOPLEVEL _ParseContext = 1 _CONTEXT_INVALID _ParseContext = iota
_CONTEXT_IN_LIST_FIRST _ParseContext = 2 _CONTEXT_IN_TOPLEVEL // 1
_CONTEXT_IN_LIST _ParseContext = 3 _CONTEXT_IN_LIST_FIRST // 2
_CONTEXT_IN_OBJECT_FIRST _ParseContext = 4 _CONTEXT_IN_LIST // 3
_CONTEXT_IN_OBJECT_NEXT_KEY _ParseContext = 5 _CONTEXT_IN_OBJECT_FIRST // 4
_CONTEXT_IN_OBJECT_NEXT_VALUE _ParseContext = 6 _CONTEXT_IN_OBJECT_NEXT_KEY // 5
_CONTEXT_IN_OBJECT_NEXT_VALUE // 6
) )
func (p _ParseContext) String() string { func (p _ParseContext) String() string {
@ -59,7 +62,33 @@ func (p _ParseContext) String() string {
return "UNKNOWN-PARSE-CONTEXT" return "UNKNOWN-PARSE-CONTEXT"
} }
// JSON protocol implementation for thrift. type jsonContextStack []_ParseContext
func (s *jsonContextStack) push(v _ParseContext) {
*s = append(*s, v)
}
func (s jsonContextStack) peek() (v _ParseContext, ok bool) {
l := len(s)
if l <= 0 {
return
}
return s[l-1], true
}
func (s *jsonContextStack) pop() (v _ParseContext, ok bool) {
l := len(*s)
if l <= 0 {
return
}
v = (*s)[l-1]
*s = (*s)[0 : l-1]
return v, true
}
var errEmptyJSONContextStack = NewTProtocolExceptionWithType(INVALID_DATA, errors.New("Unexpected empty json protocol context stack"))
// Simple JSON protocol implementation for thrift.
// //
// This protocol produces/consumes a simple output format // This protocol produces/consumes a simple output format
// suitable for parsing by scripting languages. It should not be // suitable for parsing by scripting languages. It should not be
@ -68,8 +97,8 @@ func (p _ParseContext) String() string {
type TSimpleJSONProtocol struct { type TSimpleJSONProtocol struct {
trans TTransport trans TTransport
parseContextStack []int parseContextStack jsonContextStack
dumpContext []int dumpContext jsonContextStack
writer *bufio.Writer writer *bufio.Writer
reader *bufio.Reader reader *bufio.Reader
@ -81,8 +110,8 @@ func NewTSimpleJSONProtocol(t TTransport) *TSimpleJSONProtocol {
writer: bufio.NewWriter(t), writer: bufio.NewWriter(t),
reader: bufio.NewReader(t), reader: bufio.NewReader(t),
} }
v.parseContextStack = append(v.parseContextStack, int(_CONTEXT_IN_TOPLEVEL)) v.parseContextStack.push(_CONTEXT_IN_TOPLEVEL)
v.dumpContext = append(v.dumpContext, int(_CONTEXT_IN_TOPLEVEL)) v.dumpContext.push(_CONTEXT_IN_TOPLEVEL)
return v return v
} }
@ -155,114 +184,113 @@ func mismatch(expected, actual string) error {
return fmt.Errorf("Expected '%s' but found '%s' while parsing JSON.", expected, actual) return fmt.Errorf("Expected '%s' but found '%s' while parsing JSON.", expected, actual)
} }
func (p *TSimpleJSONProtocol) WriteMessageBegin(name string, typeId TMessageType, seqId int32) error { func (p *TSimpleJSONProtocol) WriteMessageBegin(ctx context.Context, name string, typeId TMessageType, seqId int32) error {
p.resetContextStack() // THRIFT-3735 p.resetContextStack() // THRIFT-3735
if e := p.OutputListBegin(); e != nil { if e := p.OutputListBegin(); e != nil {
return e return e
} }
if e := p.WriteString(name); e != nil { if e := p.WriteString(ctx, name); e != nil {
return e return e
} }
if e := p.WriteByte(int8(typeId)); e != nil { if e := p.WriteByte(ctx, int8(typeId)); e != nil {
return e return e
} }
if e := p.WriteI32(seqId); e != nil { if e := p.WriteI32(ctx, seqId); e != nil {
return e return e
} }
return nil return nil
} }
func (p *TSimpleJSONProtocol) WriteMessageEnd() error { func (p *TSimpleJSONProtocol) WriteMessageEnd(ctx context.Context) error {
return p.OutputListEnd() return p.OutputListEnd()
} }
func (p *TSimpleJSONProtocol) WriteStructBegin(name string) error { func (p *TSimpleJSONProtocol) WriteStructBegin(ctx context.Context, name string) error {
if e := p.OutputObjectBegin(); e != nil { if e := p.OutputObjectBegin(); e != nil {
return e return e
} }
return nil return nil
} }
func (p *TSimpleJSONProtocol) WriteStructEnd() error { func (p *TSimpleJSONProtocol) WriteStructEnd(ctx context.Context) error {
return p.OutputObjectEnd() return p.OutputObjectEnd()
} }
func (p *TSimpleJSONProtocol) WriteFieldBegin(name string, typeId TType, id int16) error { func (p *TSimpleJSONProtocol) WriteFieldBegin(ctx context.Context, name string, typeId TType, id int16) error {
if e := p.WriteString(name); e != nil { if e := p.WriteString(ctx, name); e != nil {
return e return e
} }
return nil return nil
} }
func (p *TSimpleJSONProtocol) WriteFieldEnd() error { func (p *TSimpleJSONProtocol) WriteFieldEnd(ctx context.Context) error {
//return p.OutputListEnd()
return nil return nil
} }
func (p *TSimpleJSONProtocol) WriteFieldStop() error { return nil } func (p *TSimpleJSONProtocol) WriteFieldStop(ctx context.Context) error { return nil }
func (p *TSimpleJSONProtocol) WriteMapBegin(keyType TType, valueType TType, size int) error { func (p *TSimpleJSONProtocol) WriteMapBegin(ctx context.Context, keyType TType, valueType TType, size int) error {
if e := p.OutputListBegin(); e != nil { if e := p.OutputListBegin(); e != nil {
return e return e
} }
if e := p.WriteByte(int8(keyType)); e != nil { if e := p.WriteByte(ctx, int8(keyType)); e != nil {
return e return e
} }
if e := p.WriteByte(int8(valueType)); e != nil { if e := p.WriteByte(ctx, int8(valueType)); e != nil {
return e return e
} }
return p.WriteI32(int32(size)) return p.WriteI32(ctx, int32(size))
} }
func (p *TSimpleJSONProtocol) WriteMapEnd() error { func (p *TSimpleJSONProtocol) WriteMapEnd(ctx context.Context) error {
return p.OutputListEnd() return p.OutputListEnd()
} }
func (p *TSimpleJSONProtocol) WriteListBegin(elemType TType, size int) error { func (p *TSimpleJSONProtocol) WriteListBegin(ctx context.Context, elemType TType, size int) error {
return p.OutputElemListBegin(elemType, size) return p.OutputElemListBegin(elemType, size)
} }
func (p *TSimpleJSONProtocol) WriteListEnd() error { func (p *TSimpleJSONProtocol) WriteListEnd(ctx context.Context) error {
return p.OutputListEnd() return p.OutputListEnd()
} }
func (p *TSimpleJSONProtocol) WriteSetBegin(elemType TType, size int) error { func (p *TSimpleJSONProtocol) WriteSetBegin(ctx context.Context, elemType TType, size int) error {
return p.OutputElemListBegin(elemType, size) return p.OutputElemListBegin(elemType, size)
} }
func (p *TSimpleJSONProtocol) WriteSetEnd() error { func (p *TSimpleJSONProtocol) WriteSetEnd(ctx context.Context) error {
return p.OutputListEnd() return p.OutputListEnd()
} }
func (p *TSimpleJSONProtocol) WriteBool(b bool) error { func (p *TSimpleJSONProtocol) WriteBool(ctx context.Context, b bool) error {
return p.OutputBool(b) return p.OutputBool(b)
} }
func (p *TSimpleJSONProtocol) WriteByte(b int8) error { func (p *TSimpleJSONProtocol) WriteByte(ctx context.Context, b int8) error {
return p.WriteI32(int32(b)) return p.WriteI32(ctx, int32(b))
} }
func (p *TSimpleJSONProtocol) WriteI16(v int16) error { func (p *TSimpleJSONProtocol) WriteI16(ctx context.Context, v int16) error {
return p.WriteI32(int32(v)) return p.WriteI32(ctx, int32(v))
} }
func (p *TSimpleJSONProtocol) WriteI32(v int32) error { func (p *TSimpleJSONProtocol) WriteI32(ctx context.Context, v int32) error {
return p.OutputI64(int64(v)) return p.OutputI64(int64(v))
} }
func (p *TSimpleJSONProtocol) WriteI64(v int64) error { func (p *TSimpleJSONProtocol) WriteI64(ctx context.Context, v int64) error {
return p.OutputI64(int64(v)) return p.OutputI64(int64(v))
} }
func (p *TSimpleJSONProtocol) WriteDouble(v float64) error { func (p *TSimpleJSONProtocol) WriteDouble(ctx context.Context, v float64) error {
return p.OutputF64(v) return p.OutputF64(v)
} }
func (p *TSimpleJSONProtocol) WriteString(v string) error { func (p *TSimpleJSONProtocol) WriteString(ctx context.Context, v string) error {
return p.OutputString(v) return p.OutputString(v)
} }
func (p *TSimpleJSONProtocol) WriteBinary(v []byte) error { func (p *TSimpleJSONProtocol) WriteBinary(ctx context.Context, v []byte) error {
// JSON library only takes in a string, // JSON library only takes in a string,
// not an arbitrary byte array, to ensure bytes are transmitted // not an arbitrary byte array, to ensure bytes are transmitted
// efficiently we must convert this into a valid JSON string // efficiently we must convert this into a valid JSON string
@ -288,39 +316,39 @@ func (p *TSimpleJSONProtocol) WriteBinary(v []byte) error {
} }
// Reading methods. // Reading methods.
func (p *TSimpleJSONProtocol) ReadMessageBegin() (name string, typeId TMessageType, seqId int32, err error) { func (p *TSimpleJSONProtocol) ReadMessageBegin(ctx context.Context) (name string, typeId TMessageType, seqId int32, err error) {
p.resetContextStack() // THRIFT-3735 p.resetContextStack() // THRIFT-3735
if isNull, err := p.ParseListBegin(); isNull || err != nil { if isNull, err := p.ParseListBegin(); isNull || err != nil {
return name, typeId, seqId, err return name, typeId, seqId, err
} }
if name, err = p.ReadString(); err != nil { if name, err = p.ReadString(ctx); err != nil {
return name, typeId, seqId, err return name, typeId, seqId, err
} }
bTypeId, err := p.ReadByte() bTypeId, err := p.ReadByte(ctx)
typeId = TMessageType(bTypeId) typeId = TMessageType(bTypeId)
if err != nil { if err != nil {
return name, typeId, seqId, err return name, typeId, seqId, err
} }
if seqId, err = p.ReadI32(); err != nil { if seqId, err = p.ReadI32(ctx); err != nil {
return name, typeId, seqId, err return name, typeId, seqId, err
} }
return name, typeId, seqId, nil return name, typeId, seqId, nil
} }
func (p *TSimpleJSONProtocol) ReadMessageEnd() error { func (p *TSimpleJSONProtocol) ReadMessageEnd(ctx context.Context) error {
return p.ParseListEnd() return p.ParseListEnd()
} }
func (p *TSimpleJSONProtocol) ReadStructBegin() (name string, err error) { func (p *TSimpleJSONProtocol) ReadStructBegin(ctx context.Context) (name string, err error) {
_, err = p.ParseObjectStart() _, err = p.ParseObjectStart()
return "", err return "", err
} }
func (p *TSimpleJSONProtocol) ReadStructEnd() error { func (p *TSimpleJSONProtocol) ReadStructEnd(ctx context.Context) error {
return p.ParseObjectEnd() return p.ParseObjectEnd()
} }
func (p *TSimpleJSONProtocol) ReadFieldBegin() (string, TType, int16, error) { func (p *TSimpleJSONProtocol) ReadFieldBegin(ctx context.Context) (string, TType, int16, error) {
if err := p.ParsePreValue(); err != nil { if err := p.ParsePreValue(); err != nil {
return "", STOP, 0, err return "", STOP, 0, err
} }
@ -339,21 +367,6 @@ func (p *TSimpleJSONProtocol) ReadFieldBegin() (string, TType, int16, error) {
return name, STOP, 0, err return name, STOP, 0, err
} }
return name, STOP, -1, p.ParsePostValue() return name, STOP, -1, p.ParsePostValue()
/*
if err = p.ParsePostValue(); err != nil {
return name, STOP, 0, err
}
if isNull, err := p.ParseListBegin(); isNull || err != nil {
return name, STOP, 0, err
}
bType, err := p.ReadByte()
thetype := TType(bType)
if err != nil {
return name, thetype, 0, err
}
id, err := p.ReadI16()
return name, thetype, id, err
*/
} }
e := fmt.Errorf("Expected \"}\" or '\"', but found: '%s'", string(b)) e := fmt.Errorf("Expected \"}\" or '\"', but found: '%s'", string(b))
return "", STOP, 0, NewTProtocolExceptionWithType(INVALID_DATA, e) return "", STOP, 0, NewTProtocolExceptionWithType(INVALID_DATA, e)
@ -361,57 +374,56 @@ func (p *TSimpleJSONProtocol) ReadFieldBegin() (string, TType, int16, error) {
return "", STOP, 0, NewTProtocolException(io.EOF) return "", STOP, 0, NewTProtocolException(io.EOF)
} }
func (p *TSimpleJSONProtocol) ReadFieldEnd() error { func (p *TSimpleJSONProtocol) ReadFieldEnd(ctx context.Context) error {
return nil return nil
//return p.ParseListEnd()
} }
func (p *TSimpleJSONProtocol) ReadMapBegin() (keyType TType, valueType TType, size int, e error) { func (p *TSimpleJSONProtocol) ReadMapBegin(ctx context.Context) (keyType TType, valueType TType, size int, e error) {
if isNull, e := p.ParseListBegin(); isNull || e != nil { if isNull, e := p.ParseListBegin(); isNull || e != nil {
return VOID, VOID, 0, e return VOID, VOID, 0, e
} }
// read keyType // read keyType
bKeyType, e := p.ReadByte() bKeyType, e := p.ReadByte(ctx)
keyType = TType(bKeyType) keyType = TType(bKeyType)
if e != nil { if e != nil {
return keyType, valueType, size, e return keyType, valueType, size, e
} }
// read valueType // read valueType
bValueType, e := p.ReadByte() bValueType, e := p.ReadByte(ctx)
valueType = TType(bValueType) valueType = TType(bValueType)
if e != nil { if e != nil {
return keyType, valueType, size, e return keyType, valueType, size, e
} }
// read size // read size
iSize, err := p.ReadI64() iSize, err := p.ReadI64(ctx)
size = int(iSize) size = int(iSize)
return keyType, valueType, size, err return keyType, valueType, size, err
} }
func (p *TSimpleJSONProtocol) ReadMapEnd() error { func (p *TSimpleJSONProtocol) ReadMapEnd(ctx context.Context) error {
return p.ParseListEnd() return p.ParseListEnd()
} }
func (p *TSimpleJSONProtocol) ReadListBegin() (elemType TType, size int, e error) { func (p *TSimpleJSONProtocol) ReadListBegin(ctx context.Context) (elemType TType, size int, e error) {
return p.ParseElemListBegin() return p.ParseElemListBegin()
} }
func (p *TSimpleJSONProtocol) ReadListEnd() error { func (p *TSimpleJSONProtocol) ReadListEnd(ctx context.Context) error {
return p.ParseListEnd() return p.ParseListEnd()
} }
func (p *TSimpleJSONProtocol) ReadSetBegin() (elemType TType, size int, e error) { func (p *TSimpleJSONProtocol) ReadSetBegin(ctx context.Context) (elemType TType, size int, e error) {
return p.ParseElemListBegin() return p.ParseElemListBegin()
} }
func (p *TSimpleJSONProtocol) ReadSetEnd() error { func (p *TSimpleJSONProtocol) ReadSetEnd(ctx context.Context) error {
return p.ParseListEnd() return p.ParseListEnd()
} }
func (p *TSimpleJSONProtocol) ReadBool() (bool, error) { func (p *TSimpleJSONProtocol) ReadBool(ctx context.Context) (bool, error) {
var value bool var value bool
if err := p.ParsePreValue(); err != nil { if err := p.ParsePreValue(); err != nil {
@ -466,32 +478,32 @@ func (p *TSimpleJSONProtocol) ReadBool() (bool, error) {
return value, p.ParsePostValue() return value, p.ParsePostValue()
} }
func (p *TSimpleJSONProtocol) ReadByte() (int8, error) { func (p *TSimpleJSONProtocol) ReadByte(ctx context.Context) (int8, error) {
v, err := p.ReadI64() v, err := p.ReadI64(ctx)
return int8(v), err return int8(v), err
} }
func (p *TSimpleJSONProtocol) ReadI16() (int16, error) { func (p *TSimpleJSONProtocol) ReadI16(ctx context.Context) (int16, error) {
v, err := p.ReadI64() v, err := p.ReadI64(ctx)
return int16(v), err return int16(v), err
} }
func (p *TSimpleJSONProtocol) ReadI32() (int32, error) { func (p *TSimpleJSONProtocol) ReadI32(ctx context.Context) (int32, error) {
v, err := p.ReadI64() v, err := p.ReadI64(ctx)
return int32(v), err return int32(v), err
} }
func (p *TSimpleJSONProtocol) ReadI64() (int64, error) { func (p *TSimpleJSONProtocol) ReadI64(ctx context.Context) (int64, error) {
v, _, err := p.ParseI64() v, _, err := p.ParseI64()
return v, err return v, err
} }
func (p *TSimpleJSONProtocol) ReadDouble() (float64, error) { func (p *TSimpleJSONProtocol) ReadDouble(ctx context.Context) (float64, error) {
v, _, err := p.ParseF64() v, _, err := p.ParseF64()
return v, err return v, err
} }
func (p *TSimpleJSONProtocol) ReadString() (string, error) { func (p *TSimpleJSONProtocol) ReadString(ctx context.Context) (string, error) {
var v string var v string
if err := p.ParsePreValue(); err != nil { if err := p.ParsePreValue(); err != nil {
return v, err return v, err
@ -521,7 +533,7 @@ func (p *TSimpleJSONProtocol) ReadString() (string, error) {
return v, p.ParsePostValue() return v, p.ParsePostValue()
} }
func (p *TSimpleJSONProtocol) ReadBinary() ([]byte, error) { func (p *TSimpleJSONProtocol) ReadBinary(ctx context.Context) ([]byte, error) {
var v []byte var v []byte
if err := p.ParsePreValue(); err != nil { if err := p.ParsePreValue(); err != nil {
return nil, err return nil, err
@ -552,12 +564,12 @@ func (p *TSimpleJSONProtocol) ReadBinary() ([]byte, error) {
return v, p.ParsePostValue() return v, p.ParsePostValue()
} }
func (p *TSimpleJSONProtocol) Flush() (err error) { func (p *TSimpleJSONProtocol) Flush(ctx context.Context) (err error) {
return NewTProtocolException(p.writer.Flush()) return NewTProtocolException(p.writer.Flush())
} }
func (p *TSimpleJSONProtocol) Skip(fieldType TType) (err error) { func (p *TSimpleJSONProtocol) Skip(ctx context.Context, fieldType TType) (err error) {
return SkipDefaultDepth(p, fieldType) return SkipDefaultDepth(ctx, p, fieldType)
} }
func (p *TSimpleJSONProtocol) Transport() TTransport { func (p *TSimpleJSONProtocol) Transport() TTransport {
@ -565,41 +577,41 @@ func (p *TSimpleJSONProtocol) Transport() TTransport {
} }
func (p *TSimpleJSONProtocol) OutputPreValue() error { func (p *TSimpleJSONProtocol) OutputPreValue() error {
cxt := _ParseContext(p.dumpContext[len(p.dumpContext)-1]) cxt, ok := p.dumpContext.peek()
if !ok {
return errEmptyJSONContextStack
}
switch cxt { switch cxt {
case _CONTEXT_IN_LIST, _CONTEXT_IN_OBJECT_NEXT_KEY: case _CONTEXT_IN_LIST, _CONTEXT_IN_OBJECT_NEXT_KEY:
if _, e := p.write(JSON_COMMA); e != nil { if _, e := p.write(JSON_COMMA); e != nil {
return NewTProtocolException(e) return NewTProtocolException(e)
} }
break
case _CONTEXT_IN_OBJECT_NEXT_VALUE: case _CONTEXT_IN_OBJECT_NEXT_VALUE:
if _, e := p.write(JSON_COLON); e != nil { if _, e := p.write(JSON_COLON); e != nil {
return NewTProtocolException(e) return NewTProtocolException(e)
} }
break
} }
return nil return nil
} }
func (p *TSimpleJSONProtocol) OutputPostValue() error { func (p *TSimpleJSONProtocol) OutputPostValue() error {
cxt := _ParseContext(p.dumpContext[len(p.dumpContext)-1]) cxt, ok := p.dumpContext.peek()
if !ok {
return errEmptyJSONContextStack
}
switch cxt { switch cxt {
case _CONTEXT_IN_LIST_FIRST: case _CONTEXT_IN_LIST_FIRST:
p.dumpContext = p.dumpContext[:len(p.dumpContext)-1] p.dumpContext.pop()
p.dumpContext = append(p.dumpContext, int(_CONTEXT_IN_LIST)) p.dumpContext.push(_CONTEXT_IN_LIST)
break
case _CONTEXT_IN_OBJECT_FIRST: case _CONTEXT_IN_OBJECT_FIRST:
p.dumpContext = p.dumpContext[:len(p.dumpContext)-1] p.dumpContext.pop()
p.dumpContext = append(p.dumpContext, int(_CONTEXT_IN_OBJECT_NEXT_VALUE)) p.dumpContext.push(_CONTEXT_IN_OBJECT_NEXT_VALUE)
break
case _CONTEXT_IN_OBJECT_NEXT_KEY: case _CONTEXT_IN_OBJECT_NEXT_KEY:
p.dumpContext = p.dumpContext[:len(p.dumpContext)-1] p.dumpContext.pop()
p.dumpContext = append(p.dumpContext, int(_CONTEXT_IN_OBJECT_NEXT_VALUE)) p.dumpContext.push(_CONTEXT_IN_OBJECT_NEXT_VALUE)
break
case _CONTEXT_IN_OBJECT_NEXT_VALUE: case _CONTEXT_IN_OBJECT_NEXT_VALUE:
p.dumpContext = p.dumpContext[:len(p.dumpContext)-1] p.dumpContext.pop()
p.dumpContext = append(p.dumpContext, int(_CONTEXT_IN_OBJECT_NEXT_KEY)) p.dumpContext.push(_CONTEXT_IN_OBJECT_NEXT_KEY)
break
} }
return nil return nil
} }
@ -614,10 +626,13 @@ func (p *TSimpleJSONProtocol) OutputBool(value bool) error {
} else { } else {
v = string(JSON_FALSE) v = string(JSON_FALSE)
} }
switch _ParseContext(p.dumpContext[len(p.dumpContext)-1]) { cxt, ok := p.dumpContext.peek()
if !ok {
return errEmptyJSONContextStack
}
switch cxt {
case _CONTEXT_IN_OBJECT_FIRST, _CONTEXT_IN_OBJECT_NEXT_KEY: case _CONTEXT_IN_OBJECT_FIRST, _CONTEXT_IN_OBJECT_NEXT_KEY:
v = jsonQuote(v) v = jsonQuote(v)
default:
} }
if e := p.OutputStringData(v); e != nil { if e := p.OutputStringData(v); e != nil {
return e return e
@ -647,11 +662,14 @@ func (p *TSimpleJSONProtocol) OutputF64(value float64) error {
} else if math.IsInf(value, -1) { } else if math.IsInf(value, -1) {
v = string(JSON_QUOTE) + JSON_NEGATIVE_INFINITY + string(JSON_QUOTE) v = string(JSON_QUOTE) + JSON_NEGATIVE_INFINITY + string(JSON_QUOTE)
} else { } else {
cxt, ok := p.dumpContext.peek()
if !ok {
return errEmptyJSONContextStack
}
v = strconv.FormatFloat(value, 'g', -1, 64) v = strconv.FormatFloat(value, 'g', -1, 64)
switch _ParseContext(p.dumpContext[len(p.dumpContext)-1]) { switch cxt {
case _CONTEXT_IN_OBJECT_FIRST, _CONTEXT_IN_OBJECT_NEXT_KEY: case _CONTEXT_IN_OBJECT_FIRST, _CONTEXT_IN_OBJECT_NEXT_KEY:
v = string(JSON_QUOTE) + v + string(JSON_QUOTE) v = string(JSON_QUOTE) + v + string(JSON_QUOTE)
default:
} }
} }
if e := p.OutputStringData(v); e != nil { if e := p.OutputStringData(v); e != nil {
@ -664,11 +682,14 @@ func (p *TSimpleJSONProtocol) OutputI64(value int64) error {
if e := p.OutputPreValue(); e != nil { if e := p.OutputPreValue(); e != nil {
return e return e
} }
cxt, ok := p.dumpContext.peek()
if !ok {
return errEmptyJSONContextStack
}
v := strconv.FormatInt(value, 10) v := strconv.FormatInt(value, 10)
switch _ParseContext(p.dumpContext[len(p.dumpContext)-1]) { switch cxt {
case _CONTEXT_IN_OBJECT_FIRST, _CONTEXT_IN_OBJECT_NEXT_KEY: case _CONTEXT_IN_OBJECT_FIRST, _CONTEXT_IN_OBJECT_NEXT_KEY:
v = jsonQuote(v) v = jsonQuote(v)
default:
} }
if e := p.OutputStringData(v); e != nil { if e := p.OutputStringData(v); e != nil {
return e return e
@ -698,7 +719,7 @@ func (p *TSimpleJSONProtocol) OutputObjectBegin() error {
if _, e := p.write(JSON_LBRACE); e != nil { if _, e := p.write(JSON_LBRACE); e != nil {
return NewTProtocolException(e) return NewTProtocolException(e)
} }
p.dumpContext = append(p.dumpContext, int(_CONTEXT_IN_OBJECT_FIRST)) p.dumpContext.push(_CONTEXT_IN_OBJECT_FIRST)
return nil return nil
} }
@ -706,7 +727,10 @@ func (p *TSimpleJSONProtocol) OutputObjectEnd() error {
if _, e := p.write(JSON_RBRACE); e != nil { if _, e := p.write(JSON_RBRACE); e != nil {
return NewTProtocolException(e) return NewTProtocolException(e)
} }
p.dumpContext = p.dumpContext[:len(p.dumpContext)-1] _, ok := p.dumpContext.pop()
if !ok {
return errEmptyJSONContextStack
}
if e := p.OutputPostValue(); e != nil { if e := p.OutputPostValue(); e != nil {
return e return e
} }
@ -720,7 +744,7 @@ func (p *TSimpleJSONProtocol) OutputListBegin() error {
if _, e := p.write(JSON_LBRACKET); e != nil { if _, e := p.write(JSON_LBRACKET); e != nil {
return NewTProtocolException(e) return NewTProtocolException(e)
} }
p.dumpContext = append(p.dumpContext, int(_CONTEXT_IN_LIST_FIRST)) p.dumpContext.push(_CONTEXT_IN_LIST_FIRST)
return nil return nil
} }
@ -728,7 +752,10 @@ func (p *TSimpleJSONProtocol) OutputListEnd() error {
if _, e := p.write(JSON_RBRACKET); e != nil { if _, e := p.write(JSON_RBRACKET); e != nil {
return NewTProtocolException(e) return NewTProtocolException(e)
} }
p.dumpContext = p.dumpContext[:len(p.dumpContext)-1] _, ok := p.dumpContext.pop()
if !ok {
return errEmptyJSONContextStack
}
if e := p.OutputPostValue(); e != nil { if e := p.OutputPostValue(); e != nil {
return e return e
} }
@ -739,10 +766,10 @@ func (p *TSimpleJSONProtocol) OutputElemListBegin(elemType TType, size int) erro
if e := p.OutputListBegin(); e != nil { if e := p.OutputListBegin(); e != nil {
return e return e
} }
if e := p.WriteByte(int8(elemType)); e != nil { if e := p.OutputI64(int64(elemType)); e != nil {
return e return e
} }
if e := p.WriteI64(int64(size)); e != nil { if e := p.OutputI64(int64(size)); e != nil {
return e return e
} }
return nil return nil
@ -752,7 +779,10 @@ func (p *TSimpleJSONProtocol) ParsePreValue() error {
if e := p.readNonSignificantWhitespace(); e != nil { if e := p.readNonSignificantWhitespace(); e != nil {
return NewTProtocolException(e) return NewTProtocolException(e)
} }
cxt := _ParseContext(p.parseContextStack[len(p.parseContextStack)-1]) cxt, ok := p.parseContextStack.peek()
if !ok {
return errEmptyJSONContextStack
}
b, _ := p.reader.Peek(1) b, _ := p.reader.Peek(1)
switch cxt { switch cxt {
case _CONTEXT_IN_LIST: case _CONTEXT_IN_LIST:
@ -771,7 +801,6 @@ func (p *TSimpleJSONProtocol) ParsePreValue() error {
return NewTProtocolExceptionWithType(INVALID_DATA, e) return NewTProtocolExceptionWithType(INVALID_DATA, e)
} }
} }
break
case _CONTEXT_IN_OBJECT_NEXT_KEY: case _CONTEXT_IN_OBJECT_NEXT_KEY:
if len(b) > 0 { if len(b) > 0 {
switch b[0] { switch b[0] {
@ -788,7 +817,6 @@ func (p *TSimpleJSONProtocol) ParsePreValue() error {
return NewTProtocolExceptionWithType(INVALID_DATA, e) return NewTProtocolExceptionWithType(INVALID_DATA, e)
} }
} }
break
case _CONTEXT_IN_OBJECT_NEXT_VALUE: case _CONTEXT_IN_OBJECT_NEXT_VALUE:
if len(b) > 0 { if len(b) > 0 {
switch b[0] { switch b[0] {
@ -803,7 +831,6 @@ func (p *TSimpleJSONProtocol) ParsePreValue() error {
return NewTProtocolExceptionWithType(INVALID_DATA, e) return NewTProtocolExceptionWithType(INVALID_DATA, e)
} }
} }
break
} }
return nil return nil
} }
@ -812,20 +839,20 @@ func (p *TSimpleJSONProtocol) ParsePostValue() error {
if e := p.readNonSignificantWhitespace(); e != nil { if e := p.readNonSignificantWhitespace(); e != nil {
return NewTProtocolException(e) return NewTProtocolException(e)
} }
cxt := _ParseContext(p.parseContextStack[len(p.parseContextStack)-1]) cxt, ok := p.parseContextStack.peek()
if !ok {
return errEmptyJSONContextStack
}
switch cxt { switch cxt {
case _CONTEXT_IN_LIST_FIRST: case _CONTEXT_IN_LIST_FIRST:
p.parseContextStack = p.parseContextStack[:len(p.parseContextStack)-1] p.parseContextStack.pop()
p.parseContextStack = append(p.parseContextStack, int(_CONTEXT_IN_LIST)) p.parseContextStack.push(_CONTEXT_IN_LIST)
break
case _CONTEXT_IN_OBJECT_FIRST, _CONTEXT_IN_OBJECT_NEXT_KEY: case _CONTEXT_IN_OBJECT_FIRST, _CONTEXT_IN_OBJECT_NEXT_KEY:
p.parseContextStack = p.parseContextStack[:len(p.parseContextStack)-1] p.parseContextStack.pop()
p.parseContextStack = append(p.parseContextStack, int(_CONTEXT_IN_OBJECT_NEXT_VALUE)) p.parseContextStack.push(_CONTEXT_IN_OBJECT_NEXT_VALUE)
break
case _CONTEXT_IN_OBJECT_NEXT_VALUE: case _CONTEXT_IN_OBJECT_NEXT_VALUE:
p.parseContextStack = p.parseContextStack[:len(p.parseContextStack)-1] p.parseContextStack.pop()
p.parseContextStack = append(p.parseContextStack, int(_CONTEXT_IN_OBJECT_NEXT_KEY)) p.parseContextStack.push(_CONTEXT_IN_OBJECT_NEXT_KEY)
break
} }
return nil return nil
} }
@ -978,7 +1005,7 @@ func (p *TSimpleJSONProtocol) ParseObjectStart() (bool, error) {
} }
if len(b) > 0 && b[0] == JSON_LBRACE[0] { if len(b) > 0 && b[0] == JSON_LBRACE[0] {
p.reader.ReadByte() p.reader.ReadByte()
p.parseContextStack = append(p.parseContextStack, int(_CONTEXT_IN_OBJECT_FIRST)) p.parseContextStack.push(_CONTEXT_IN_OBJECT_FIRST)
return false, nil return false, nil
} else if p.safePeekContains(JSON_NULL) { } else if p.safePeekContains(JSON_NULL) {
return true, nil return true, nil
@ -991,7 +1018,7 @@ func (p *TSimpleJSONProtocol) ParseObjectEnd() error {
if isNull, err := p.readIfNull(); isNull || err != nil { if isNull, err := p.readIfNull(); isNull || err != nil {
return err return err
} }
cxt := _ParseContext(p.parseContextStack[len(p.parseContextStack)-1]) cxt, _ := p.parseContextStack.peek()
if (cxt != _CONTEXT_IN_OBJECT_FIRST) && (cxt != _CONTEXT_IN_OBJECT_NEXT_KEY) { if (cxt != _CONTEXT_IN_OBJECT_FIRST) && (cxt != _CONTEXT_IN_OBJECT_NEXT_KEY) {
e := fmt.Errorf("Expected to be in the Object Context, but not in Object Context (%d)", cxt) e := fmt.Errorf("Expected to be in the Object Context, but not in Object Context (%d)", cxt)
return NewTProtocolExceptionWithType(INVALID_DATA, e) return NewTProtocolExceptionWithType(INVALID_DATA, e)
@ -1009,7 +1036,7 @@ func (p *TSimpleJSONProtocol) ParseObjectEnd() error {
break break
} }
} }
p.parseContextStack = p.parseContextStack[:len(p.parseContextStack)-1] p.parseContextStack.pop()
return p.ParsePostValue() return p.ParsePostValue()
} }
@ -1023,7 +1050,7 @@ func (p *TSimpleJSONProtocol) ParseListBegin() (isNull bool, err error) {
return false, err return false, err
} }
if len(b) >= 1 && b[0] == JSON_LBRACKET[0] { if len(b) >= 1 && b[0] == JSON_LBRACKET[0] {
p.parseContextStack = append(p.parseContextStack, int(_CONTEXT_IN_LIST_FIRST)) p.parseContextStack.push(_CONTEXT_IN_LIST_FIRST)
p.reader.ReadByte() p.reader.ReadByte()
isNull = false isNull = false
} else if p.safePeekContains(JSON_NULL) { } else if p.safePeekContains(JSON_NULL) {
@ -1038,12 +1065,12 @@ func (p *TSimpleJSONProtocol) ParseElemListBegin() (elemType TType, size int, e
if isNull, e := p.ParseListBegin(); isNull || e != nil { if isNull, e := p.ParseListBegin(); isNull || e != nil {
return VOID, 0, e return VOID, 0, e
} }
bElemType, err := p.ReadByte() bElemType, _, err := p.ParseI64()
elemType = TType(bElemType) elemType = TType(bElemType)
if err != nil { if err != nil {
return elemType, size, err return elemType, size, err
} }
nSize, err2 := p.ReadI64() nSize, _, err2 := p.ParseI64()
size = int(nSize) size = int(nSize)
return elemType, size, err2 return elemType, size, err2
} }
@ -1052,7 +1079,7 @@ func (p *TSimpleJSONProtocol) ParseListEnd() error {
if isNull, err := p.readIfNull(); isNull || err != nil { if isNull, err := p.readIfNull(); isNull || err != nil {
return err return err
} }
cxt := _ParseContext(p.parseContextStack[len(p.parseContextStack)-1]) cxt, _ := p.parseContextStack.peek()
if cxt != _CONTEXT_IN_LIST { if cxt != _CONTEXT_IN_LIST {
e := fmt.Errorf("Expected to be in the List Context, but not in List Context (%d)", cxt) e := fmt.Errorf("Expected to be in the List Context, but not in List Context (%d)", cxt)
return NewTProtocolExceptionWithType(INVALID_DATA, e) return NewTProtocolExceptionWithType(INVALID_DATA, e)
@ -1064,14 +1091,16 @@ func (p *TSimpleJSONProtocol) ParseListEnd() error {
for _, char := range line { for _, char := range line {
switch char { switch char {
default: default:
e := fmt.Errorf("Expecting end of list \"]\", but found: \"%s\"", line) e := fmt.Errorf("Expecting end of list \"]\", but found: \"%v\"", line)
return NewTProtocolExceptionWithType(INVALID_DATA, e) return NewTProtocolExceptionWithType(INVALID_DATA, e)
case ' ', '\n', '\r', '\t', rune(JSON_RBRACKET[0]): case ' ', '\n', '\r', '\t', rune(JSON_RBRACKET[0]):
break break
} }
} }
p.parseContextStack = p.parseContextStack[:len(p.parseContextStack)-1] p.parseContextStack.pop()
if _ParseContext(p.parseContextStack[len(p.parseContextStack)-1]) == _CONTEXT_IN_TOPLEVEL { if cxt, ok := p.parseContextStack.peek(); !ok {
return errEmptyJSONContextStack
} else if cxt == _CONTEXT_IN_TOPLEVEL {
return nil return nil
} }
return p.ParsePostValue() return p.ParsePostValue()
@ -1315,7 +1344,7 @@ func (p *TSimpleJSONProtocol) readNumeric() (Numeric, error) {
func (p *TSimpleJSONProtocol) safePeekContains(b []byte) bool { func (p *TSimpleJSONProtocol) safePeekContains(b []byte) bool {
for i := 0; i < len(b); i++ { for i := 0; i < len(b); i++ {
a, _ := p.reader.Peek(i + 1) a, _ := p.reader.Peek(i + 1)
if len(a) == 0 || a[i] != b[i] { if len(a) < (i+1) || a[i] != b[i] {
return false return false
} }
} }
@ -1324,8 +1353,8 @@ func (p *TSimpleJSONProtocol) safePeekContains(b []byte) bool {
// Reset the context stack to its initial state. // Reset the context stack to its initial state.
func (p *TSimpleJSONProtocol) resetContextStack() { func (p *TSimpleJSONProtocol) resetContextStack() {
p.parseContextStack = []int{int(_CONTEXT_IN_TOPLEVEL)} p.parseContextStack = jsonContextStack{_CONTEXT_IN_TOPLEVEL}
p.dumpContext = []int{int(_CONTEXT_IN_TOPLEVEL)} p.dumpContext = jsonContextStack{_CONTEXT_IN_TOPLEVEL}
} }
func (p *TSimpleJSONProtocol) write(b []byte) (int, error) { func (p *TSimpleJSONProtocol) write(b []byte) (int, error) {
@ -1335,3 +1364,10 @@ func (p *TSimpleJSONProtocol) write(b []byte) (int, error) {
} }
return n, err return n, err
} }
// SetTConfiguration implements TConfigurationSetter for propagation.
func (p *TSimpleJSONProtocol) SetTConfiguration(conf *TConfiguration) {
PropagateTConfiguration(p.trans, conf)
}
var _ TConfigurationSetter = (*TSimpleJSONProtocol)(nil)

View File

@ -0,0 +1,332 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package thrift
import (
"errors"
"fmt"
"io"
"sync"
"sync/atomic"
"time"
)
// ErrAbandonRequest is a special error server handler implementations can
// return to indicate that the request has been abandoned.
//
// TSimpleServer will check for this error, and close the client connection
// instead of writing the response/error back to the client.
//
// It shall only be used when the server handler implementation know that the
// client already abandoned the request (by checking that the passed in context
// is already canceled, for example).
var ErrAbandonRequest = errors.New("request abandoned")
// ServerConnectivityCheckInterval defines the ticker interval used by
// connectivity check in thrift compiled TProcessorFunc implementations.
//
// It's defined as a variable instead of constant, so that thrift server
// implementations can change its value to control the behavior.
//
// If it's changed to <=0, the feature will be disabled.
var ServerConnectivityCheckInterval = time.Millisecond * 5
/*
* This is not a typical TSimpleServer as it is not blocked after accept a socket.
* It is more like a TThreadedServer that can handle different connections in different goroutines.
* This will work if golang user implements a conn-pool like thing in client side.
*/
type TSimpleServer struct {
closed int32
wg sync.WaitGroup
mu sync.Mutex
processorFactory TProcessorFactory
serverTransport TServerTransport
inputTransportFactory TTransportFactory
outputTransportFactory TTransportFactory
inputProtocolFactory TProtocolFactory
outputProtocolFactory TProtocolFactory
// Headers to auto forward in THeaderProtocol
forwardHeaders []string
logger Logger
}
func NewTSimpleServer2(processor TProcessor, serverTransport TServerTransport) *TSimpleServer {
return NewTSimpleServerFactory2(NewTProcessorFactory(processor), serverTransport)
}
func NewTSimpleServer4(processor TProcessor, serverTransport TServerTransport, transportFactory TTransportFactory, protocolFactory TProtocolFactory) *TSimpleServer {
return NewTSimpleServerFactory4(NewTProcessorFactory(processor),
serverTransport,
transportFactory,
protocolFactory,
)
}
func NewTSimpleServer6(processor TProcessor, serverTransport TServerTransport, inputTransportFactory TTransportFactory, outputTransportFactory TTransportFactory, inputProtocolFactory TProtocolFactory, outputProtocolFactory TProtocolFactory) *TSimpleServer {
return NewTSimpleServerFactory6(NewTProcessorFactory(processor),
serverTransport,
inputTransportFactory,
outputTransportFactory,
inputProtocolFactory,
outputProtocolFactory,
)
}
func NewTSimpleServerFactory2(processorFactory TProcessorFactory, serverTransport TServerTransport) *TSimpleServer {
return NewTSimpleServerFactory6(processorFactory,
serverTransport,
NewTTransportFactory(),
NewTTransportFactory(),
NewTBinaryProtocolFactoryDefault(),
NewTBinaryProtocolFactoryDefault(),
)
}
func NewTSimpleServerFactory4(processorFactory TProcessorFactory, serverTransport TServerTransport, transportFactory TTransportFactory, protocolFactory TProtocolFactory) *TSimpleServer {
return NewTSimpleServerFactory6(processorFactory,
serverTransport,
transportFactory,
transportFactory,
protocolFactory,
protocolFactory,
)
}
func NewTSimpleServerFactory6(processorFactory TProcessorFactory, serverTransport TServerTransport, inputTransportFactory TTransportFactory, outputTransportFactory TTransportFactory, inputProtocolFactory TProtocolFactory, outputProtocolFactory TProtocolFactory) *TSimpleServer {
return &TSimpleServer{
processorFactory: processorFactory,
serverTransport: serverTransport,
inputTransportFactory: inputTransportFactory,
outputTransportFactory: outputTransportFactory,
inputProtocolFactory: inputProtocolFactory,
outputProtocolFactory: outputProtocolFactory,
}
}
func (p *TSimpleServer) ProcessorFactory() TProcessorFactory {
return p.processorFactory
}
func (p *TSimpleServer) ServerTransport() TServerTransport {
return p.serverTransport
}
func (p *TSimpleServer) InputTransportFactory() TTransportFactory {
return p.inputTransportFactory
}
func (p *TSimpleServer) OutputTransportFactory() TTransportFactory {
return p.outputTransportFactory
}
func (p *TSimpleServer) InputProtocolFactory() TProtocolFactory {
return p.inputProtocolFactory
}
func (p *TSimpleServer) OutputProtocolFactory() TProtocolFactory {
return p.outputProtocolFactory
}
func (p *TSimpleServer) Listen() error {
return p.serverTransport.Listen()
}
// SetForwardHeaders sets the list of header keys that will be auto forwarded
// while using THeaderProtocol.
//
// "forward" means that when the server is also a client to other upstream
// thrift servers, the context object user gets in the processor functions will
// have both read and write headers set, with write headers being forwarded.
// Users can always override the write headers by calling SetWriteHeaderList
// before calling thrift client functions.
func (p *TSimpleServer) SetForwardHeaders(headers []string) {
size := len(headers)
if size == 0 {
p.forwardHeaders = nil
return
}
keys := make([]string, size)
copy(keys, headers)
p.forwardHeaders = keys
}
// SetLogger sets the logger used by this TSimpleServer.
//
// If no logger was set before Serve is called, a default logger using standard
// log library will be used.
func (p *TSimpleServer) SetLogger(logger Logger) {
p.logger = logger
}
func (p *TSimpleServer) innerAccept() (int32, error) {
client, err := p.serverTransport.Accept()
p.mu.Lock()
defer p.mu.Unlock()
closed := atomic.LoadInt32(&p.closed)
if closed != 0 {
return closed, nil
}
if err != nil {
return 0, err
}
if client != nil {
p.wg.Add(1)
go func() {
defer p.wg.Done()
if err := p.processRequests(client); err != nil {
p.logger(fmt.Sprintf("error processing request: %v", err))
}
}()
}
return 0, nil
}
func (p *TSimpleServer) AcceptLoop() error {
for {
closed, err := p.innerAccept()
if err != nil {
return err
}
if closed != 0 {
return nil
}
}
}
func (p *TSimpleServer) Serve() error {
p.logger = fallbackLogger(p.logger)
err := p.Listen()
if err != nil {
return err
}
p.AcceptLoop()
return nil
}
func (p *TSimpleServer) Stop() error {
p.mu.Lock()
defer p.mu.Unlock()
if atomic.LoadInt32(&p.closed) != 0 {
return nil
}
atomic.StoreInt32(&p.closed, 1)
p.serverTransport.Interrupt()
p.wg.Wait()
return nil
}
// If err is actually EOF, return nil, otherwise return err as-is.
func treatEOFErrorsAsNil(err error) error {
if err == nil {
return nil
}
if errors.Is(err, io.EOF) {
return nil
}
var te TTransportException
if errors.As(err, &te) && te.TypeId() == END_OF_FILE {
return nil
}
return err
}
func (p *TSimpleServer) processRequests(client TTransport) (err error) {
defer func() {
err = treatEOFErrorsAsNil(err)
}()
processor := p.processorFactory.GetProcessor(client)
inputTransport, err := p.inputTransportFactory.GetTransport(client)
if err != nil {
return err
}
inputProtocol := p.inputProtocolFactory.GetProtocol(inputTransport)
var outputTransport TTransport
var outputProtocol TProtocol
// for THeaderProtocol, we must use the same protocol instance for
// input and output so that the response is in the same dialect that
// the server detected the request was in.
headerProtocol, ok := inputProtocol.(*THeaderProtocol)
if ok {
outputProtocol = inputProtocol
} else {
oTrans, err := p.outputTransportFactory.GetTransport(client)
if err != nil {
return err
}
outputTransport = oTrans
outputProtocol = p.outputProtocolFactory.GetProtocol(outputTransport)
}
if inputTransport != nil {
defer inputTransport.Close()
}
if outputTransport != nil {
defer outputTransport.Close()
}
for {
if atomic.LoadInt32(&p.closed) != 0 {
return nil
}
ctx := SetResponseHelper(
defaultCtx,
TResponseHelper{
THeaderResponseHelper: NewTHeaderResponseHelper(outputProtocol),
},
)
if headerProtocol != nil {
// We need to call ReadFrame here, otherwise we won't
// get any headers on the AddReadTHeaderToContext call.
//
// ReadFrame is safe to be called multiple times so it
// won't break when it's called again later when we
// actually start to read the message.
if err := headerProtocol.ReadFrame(ctx); err != nil {
return err
}
ctx = AddReadTHeaderToContext(ctx, headerProtocol.GetReadHeaders())
ctx = SetWriteHeaderList(ctx, p.forwardHeaders)
}
ok, err := processor.Process(ctx, inputProtocol, outputProtocol)
if errors.Is(err, ErrAbandonRequest) {
return client.Close()
}
if errors.As(err, new(TTransportException)) && err != nil {
return err
}
var tae TApplicationException
if errors.As(err, &tae) && tae.TypeId() == UNKNOWN_METHOD {
continue
}
if !ok {
break
}
}
return nil
}

View File

@ -20,6 +20,7 @@
package thrift package thrift
import ( import (
"context"
"errors" "errors"
"io" "io"
) )
@ -30,15 +31,18 @@ type Flusher interface {
Flush() (err error) Flush() (err error)
} }
type ContextFlusher interface {
Flush(ctx context.Context) (err error)
}
type ReadSizeProvider interface { type ReadSizeProvider interface {
RemainingBytes() (num_bytes uint64) RemainingBytes() (num_bytes uint64)
} }
// Encapsulates the I/O layer // Encapsulates the I/O layer
type TTransport interface { type TTransport interface {
io.ReadWriteCloser io.ReadWriteCloser
Flusher ContextFlusher
ReadSizeProvider ReadSizeProvider
// Opens the transport for communication // Opens the transport for communication
@ -52,7 +56,6 @@ type stringWriter interface {
WriteString(s string) (n int, err error) WriteString(s string) (n int, err error)
} }
// This is "enchanced" transport with extra capabilities. You need to use one of these // This is "enchanced" transport with extra capabilities. You need to use one of these
// to construct protocol. // to construct protocol.
// Notably, TSocket does not implement this interface, and it is always a mistake to use // Notably, TSocket does not implement this interface, and it is always a mistake to use
@ -62,7 +65,6 @@ type TRichTransport interface {
io.ByteReader io.ByteReader
io.ByteWriter io.ByteWriter
stringWriter stringWriter
Flusher ContextFlusher
ReadSizeProvider ReadSizeProvider
} }

View File

@ -46,6 +46,13 @@ const (
type tTransportException struct { type tTransportException struct {
typeId int typeId int
err error err error
msg string
}
var _ TTransportException = (*tTransportException)(nil)
func (tTransportException) TExceptionType() TExceptionType {
return TExceptionTypeTransport
} }
func (p *tTransportException) TypeId() int { func (p *tTransportException) TypeId() int {
@ -53,15 +60,27 @@ func (p *tTransportException) TypeId() int {
} }
func (p *tTransportException) Error() string { func (p *tTransportException) Error() string {
return p.err.Error() return p.msg
} }
func (p *tTransportException) Err() error { func (p *tTransportException) Err() error {
return p.err return p.err
} }
func (p *tTransportException) Unwrap() error {
return p.err
}
func (p *tTransportException) Timeout() bool {
return p.typeId == TIMED_OUT
}
func NewTTransportException(t int, e string) TTransportException { func NewTTransportException(t int, e string) TTransportException {
return &tTransportException{typeId: t, err: errors.New(e)} return &tTransportException{
typeId: t,
err: errors.New(e),
msg: e,
}
} }
func NewTTransportExceptionFromError(e error) TTransportException { func NewTTransportExceptionFromError(e error) TTransportException {
@ -73,18 +92,40 @@ func NewTTransportExceptionFromError(e error) TTransportException {
return t return t
} }
switch v := e.(type) { te := &tTransportException{
case TTransportException: typeId: UNKNOWN_TRANSPORT_EXCEPTION,
return v err: e,
case timeoutable: msg: e.Error(),
if v.Timeout() {
return &tTransportException{typeId: TIMED_OUT, err: e}
}
} }
if e == io.EOF { if isTimeoutError(e) {
return &tTransportException{typeId: END_OF_FILE, err: e} te.typeId = TIMED_OUT
return te
} }
return &tTransportException{typeId: UNKNOWN_TRANSPORT_EXCEPTION, err: e} if errors.Is(e, io.EOF) {
te.typeId = END_OF_FILE
return te
}
return te
}
func prependTTransportException(prepend string, e TTransportException) TTransportException {
return &tTransportException{
typeId: e.TypeId(),
err: e,
msg: prepend + e.Error(),
}
}
// isTimeoutError returns true when err is an error caused by timeout.
//
// Note that this also includes TTransportException wrapped timeout errors.
func isTimeoutError(err error) bool {
var t timeoutable
if errors.As(err, &t) {
return t.Timeout()
}
return false
} }

View File

@ -24,14 +24,14 @@ package thrift
// a ServerTransport and then may want to mutate them (i.e. create // a ServerTransport and then may want to mutate them (i.e. create
// a BufferedTransport from the underlying base transport) // a BufferedTransport from the underlying base transport)
type TTransportFactory interface { type TTransportFactory interface {
GetTransport(trans TTransport) TTransport GetTransport(trans TTransport) (TTransport, error)
} }
type tTransportFactory struct{} type tTransportFactory struct{}
// Return a wrapped instance of the base Transport. // Return a wrapped instance of the base Transport.
func (p *tTransportFactory) GetTransport(trans TTransport) TTransport { func (p *tTransportFactory) GetTransport(trans TTransport) (TTransport, error) {
return trans return trans, nil
} }
func NewTTransportFactory() TTransportFactory { func NewTTransportFactory() TTransportFactory {

View File

@ -15,6 +15,7 @@
package utils package utils
import ( import (
"context"
"errors" "errors"
"fmt" "fmt"
"io" "io"
@ -124,15 +125,14 @@ func NewAgentClientUDP(hostPort string, maxPacketSize int) (*AgentClientUDP, err
} }
// EmitZipkinBatch implements EmitZipkinBatch() of Agent interface // EmitZipkinBatch implements EmitZipkinBatch() of Agent interface
func (a *AgentClientUDP) EmitZipkinBatch(spans []*zipkincore.Span) error { func (a *AgentClientUDP) EmitZipkinBatch(context.Context, []*zipkincore.Span) error {
return errors.New("Not implemented") return errors.New("Not implemented")
} }
// EmitBatch implements EmitBatch() of Agent interface // EmitBatch implements EmitBatch() of Agent interface
func (a *AgentClientUDP) EmitBatch(batch *jaeger.Batch) error { func (a *AgentClientUDP) EmitBatch(ctx context.Context, batch *jaeger.Batch) error {
a.thriftBuffer.Reset() a.thriftBuffer.Reset()
a.client.SeqId = 0 // we have no need for distinct SeqIds for our one-way UDP messages if err := a.client.EmitBatch(ctx, batch); err != nil {
if err := a.client.EmitBatch(batch); err != nil {
return err return err
} }
if a.thriftBuffer.Len() > a.maxPacketSize { if a.thriftBuffer.Len() > a.maxPacketSize {

2
vendor/modules.txt vendored
View File

@ -582,7 +582,7 @@ github.com/stretchr/testify/require
github.com/syndtr/gocapability/capability github.com/syndtr/gocapability/capability
# github.com/tchap/go-patricia v2.3.0+incompatible # github.com/tchap/go-patricia v2.3.0+incompatible
github.com/tchap/go-patricia/patricia github.com/tchap/go-patricia/patricia
# github.com/uber/jaeger-client-go v2.28.0+incompatible # github.com/uber/jaeger-client-go v2.29.1+incompatible
github.com/uber/jaeger-client-go/log github.com/uber/jaeger-client-go/log
github.com/uber/jaeger-client-go/thrift github.com/uber/jaeger-client-go/thrift
github.com/uber/jaeger-client-go/thrift-gen/agent github.com/uber/jaeger-client-go/thrift-gen/agent