From 31e382f482f10243fc854a07dfb5ff623337227a Mon Sep 17 00:00:00 2001 From: Matthew Topol Date: Fri, 11 Sep 2020 18:33:05 -0400 Subject: [PATCH 1/8] go flight implementation --- format/Flight.proto | 2 + go/arrow/flight/Flight.pb.go | 1473 ++++++++++++++++++++++++++++ go/arrow/flight/Flight_grpc.pb.go | 877 +++++++++++++++++ go/arrow/flight/client.go | 56 ++ go/arrow/flight/client_auth.go | 71 ++ go/arrow/flight/flight_test.go | 148 +++ go/arrow/flight/gen.go | 3 + go/arrow/flight/server.go | 102 ++ go/arrow/flight/server_auth.go | 112 +++ go/arrow/go.mod | 8 + go/arrow/go.sum | 93 ++ go/arrow/ipc/flight_data_reader.go | 141 +++ go/arrow/ipc/flight_data_writer.go | 132 +++ 13 files changed, 3218 insertions(+) create mode 100644 go/arrow/flight/Flight.pb.go create mode 100644 go/arrow/flight/Flight_grpc.pb.go create mode 100644 go/arrow/flight/client.go create mode 100644 go/arrow/flight/client_auth.go create mode 100644 go/arrow/flight/flight_test.go create mode 100644 go/arrow/flight/gen.go create mode 100644 go/arrow/flight/server.go create mode 100644 go/arrow/flight/server_auth.go create mode 100644 go/arrow/ipc/flight_data_reader.go create mode 100644 go/arrow/ipc/flight_data_writer.go diff --git a/format/Flight.proto b/format/Flight.proto index 71ae7ca9d56..7b0f591a237 100644 --- a/format/Flight.proto +++ b/format/Flight.proto @@ -19,6 +19,8 @@ syntax = "proto3"; option java_package = "org.apache.arrow.flight.impl"; +option go_package = "github.com/apache/arrow/go/flight;flight"; + package arrow.flight.protocol; /* diff --git a/go/arrow/flight/Flight.pb.go b/go/arrow/flight/Flight.pb.go new file mode 100644 index 00000000000..75c6c2c3c05 --- /dev/null +++ b/go/arrow/flight/Flight.pb.go @@ -0,0 +1,1473 @@ +// +// 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. + +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.25.0 +// protoc v3.9.1 +// source: Flight.proto + +package flight + +import ( + proto "github.com/golang/protobuf/proto" + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +// This is a compile-time assertion that a sufficiently up-to-date version +// of the legacy proto package is being used. +const _ = proto.ProtoPackageIsVersion4 + +// +// Describes what type of descriptor is defined. +type FlightDescriptor_DescriptorType int32 + +const ( + // Protobuf pattern, not used. + FlightDescriptor_UNKNOWN FlightDescriptor_DescriptorType = 0 + // + // A named path that identifies a dataset. A path is composed of a string + // or list of strings describing a particular dataset. This is conceptually + // similar to a path inside a filesystem. + FlightDescriptor_PATH FlightDescriptor_DescriptorType = 1 + // + // An opaque command to generate a dataset. + FlightDescriptor_CMD FlightDescriptor_DescriptorType = 2 +) + +// Enum value maps for FlightDescriptor_DescriptorType. +var ( + FlightDescriptor_DescriptorType_name = map[int32]string{ + 0: "UNKNOWN", + 1: "PATH", + 2: "CMD", + } + FlightDescriptor_DescriptorType_value = map[string]int32{ + "UNKNOWN": 0, + "PATH": 1, + "CMD": 2, + } +) + +func (x FlightDescriptor_DescriptorType) Enum() *FlightDescriptor_DescriptorType { + p := new(FlightDescriptor_DescriptorType) + *p = x + return p +} + +func (x FlightDescriptor_DescriptorType) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (FlightDescriptor_DescriptorType) Descriptor() protoreflect.EnumDescriptor { + return file_Flight_proto_enumTypes[0].Descriptor() +} + +func (FlightDescriptor_DescriptorType) Type() protoreflect.EnumType { + return &file_Flight_proto_enumTypes[0] +} + +func (x FlightDescriptor_DescriptorType) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use FlightDescriptor_DescriptorType.Descriptor instead. +func (FlightDescriptor_DescriptorType) EnumDescriptor() ([]byte, []int) { + return file_Flight_proto_rawDescGZIP(), []int{9, 0} +} + +// +// The request that a client provides to a server on handshake. +type HandshakeRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // + // A defined protocol version + ProtocolVersion uint64 `protobuf:"varint,1,opt,name=protocol_version,json=protocolVersion,proto3" json:"protocol_version,omitempty"` + // + // Arbitrary auth/handshake info. + Payload []byte `protobuf:"bytes,2,opt,name=payload,proto3" json:"payload,omitempty"` +} + +func (x *HandshakeRequest) Reset() { + *x = HandshakeRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_Flight_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *HandshakeRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*HandshakeRequest) ProtoMessage() {} + +func (x *HandshakeRequest) ProtoReflect() protoreflect.Message { + mi := &file_Flight_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use HandshakeRequest.ProtoReflect.Descriptor instead. +func (*HandshakeRequest) Descriptor() ([]byte, []int) { + return file_Flight_proto_rawDescGZIP(), []int{0} +} + +func (x *HandshakeRequest) GetProtocolVersion() uint64 { + if x != nil { + return x.ProtocolVersion + } + return 0 +} + +func (x *HandshakeRequest) GetPayload() []byte { + if x != nil { + return x.Payload + } + return nil +} + +type HandshakeResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // + // A defined protocol version + ProtocolVersion uint64 `protobuf:"varint,1,opt,name=protocol_version,json=protocolVersion,proto3" json:"protocol_version,omitempty"` + // + // Arbitrary auth/handshake info. + Payload []byte `protobuf:"bytes,2,opt,name=payload,proto3" json:"payload,omitempty"` +} + +func (x *HandshakeResponse) Reset() { + *x = HandshakeResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_Flight_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *HandshakeResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*HandshakeResponse) ProtoMessage() {} + +func (x *HandshakeResponse) ProtoReflect() protoreflect.Message { + mi := &file_Flight_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use HandshakeResponse.ProtoReflect.Descriptor instead. +func (*HandshakeResponse) Descriptor() ([]byte, []int) { + return file_Flight_proto_rawDescGZIP(), []int{1} +} + +func (x *HandshakeResponse) GetProtocolVersion() uint64 { + if x != nil { + return x.ProtocolVersion + } + return 0 +} + +func (x *HandshakeResponse) GetPayload() []byte { + if x != nil { + return x.Payload + } + return nil +} + +// +// A message for doing simple auth. +type BasicAuth struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Username string `protobuf:"bytes,2,opt,name=username,proto3" json:"username,omitempty"` + Password string `protobuf:"bytes,3,opt,name=password,proto3" json:"password,omitempty"` +} + +func (x *BasicAuth) Reset() { + *x = BasicAuth{} + if protoimpl.UnsafeEnabled { + mi := &file_Flight_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *BasicAuth) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*BasicAuth) ProtoMessage() {} + +func (x *BasicAuth) ProtoReflect() protoreflect.Message { + mi := &file_Flight_proto_msgTypes[2] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use BasicAuth.ProtoReflect.Descriptor instead. +func (*BasicAuth) Descriptor() ([]byte, []int) { + return file_Flight_proto_rawDescGZIP(), []int{2} +} + +func (x *BasicAuth) GetUsername() string { + if x != nil { + return x.Username + } + return "" +} + +func (x *BasicAuth) GetPassword() string { + if x != nil { + return x.Password + } + return "" +} + +type Empty struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *Empty) Reset() { + *x = Empty{} + if protoimpl.UnsafeEnabled { + mi := &file_Flight_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Empty) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Empty) ProtoMessage() {} + +func (x *Empty) ProtoReflect() protoreflect.Message { + mi := &file_Flight_proto_msgTypes[3] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Empty.ProtoReflect.Descriptor instead. +func (*Empty) Descriptor() ([]byte, []int) { + return file_Flight_proto_rawDescGZIP(), []int{3} +} + +// +// Describes an available action, including both the name used for execution +// along with a short description of the purpose of the action. +type ActionType struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Type string `protobuf:"bytes,1,opt,name=type,proto3" json:"type,omitempty"` + Description string `protobuf:"bytes,2,opt,name=description,proto3" json:"description,omitempty"` +} + +func (x *ActionType) Reset() { + *x = ActionType{} + if protoimpl.UnsafeEnabled { + mi := &file_Flight_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ActionType) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ActionType) ProtoMessage() {} + +func (x *ActionType) ProtoReflect() protoreflect.Message { + mi := &file_Flight_proto_msgTypes[4] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ActionType.ProtoReflect.Descriptor instead. +func (*ActionType) Descriptor() ([]byte, []int) { + return file_Flight_proto_rawDescGZIP(), []int{4} +} + +func (x *ActionType) GetType() string { + if x != nil { + return x.Type + } + return "" +} + +func (x *ActionType) GetDescription() string { + if x != nil { + return x.Description + } + return "" +} + +// +// A service specific expression that can be used to return a limited set +// of available Arrow Flight streams. +type Criteria struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Expression []byte `protobuf:"bytes,1,opt,name=expression,proto3" json:"expression,omitempty"` +} + +func (x *Criteria) Reset() { + *x = Criteria{} + if protoimpl.UnsafeEnabled { + mi := &file_Flight_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Criteria) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Criteria) ProtoMessage() {} + +func (x *Criteria) ProtoReflect() protoreflect.Message { + mi := &file_Flight_proto_msgTypes[5] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Criteria.ProtoReflect.Descriptor instead. +func (*Criteria) Descriptor() ([]byte, []int) { + return file_Flight_proto_rawDescGZIP(), []int{5} +} + +func (x *Criteria) GetExpression() []byte { + if x != nil { + return x.Expression + } + return nil +} + +// +// An opaque action specific for the service. +type Action struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Type string `protobuf:"bytes,1,opt,name=type,proto3" json:"type,omitempty"` + Body []byte `protobuf:"bytes,2,opt,name=body,proto3" json:"body,omitempty"` +} + +func (x *Action) Reset() { + *x = Action{} + if protoimpl.UnsafeEnabled { + mi := &file_Flight_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Action) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Action) ProtoMessage() {} + +func (x *Action) ProtoReflect() protoreflect.Message { + mi := &file_Flight_proto_msgTypes[6] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Action.ProtoReflect.Descriptor instead. +func (*Action) Descriptor() ([]byte, []int) { + return file_Flight_proto_rawDescGZIP(), []int{6} +} + +func (x *Action) GetType() string { + if x != nil { + return x.Type + } + return "" +} + +func (x *Action) GetBody() []byte { + if x != nil { + return x.Body + } + return nil +} + +// +// An opaque result returned after executing an action. +type Result struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Body []byte `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"` +} + +func (x *Result) Reset() { + *x = Result{} + if protoimpl.UnsafeEnabled { + mi := &file_Flight_proto_msgTypes[7] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Result) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Result) ProtoMessage() {} + +func (x *Result) ProtoReflect() protoreflect.Message { + mi := &file_Flight_proto_msgTypes[7] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Result.ProtoReflect.Descriptor instead. +func (*Result) Descriptor() ([]byte, []int) { + return file_Flight_proto_rawDescGZIP(), []int{7} +} + +func (x *Result) GetBody() []byte { + if x != nil { + return x.Body + } + return nil +} + +// +// Wrap the result of a getSchema call +type SchemaResult struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // schema of the dataset as described in Schema.fbs::Schema. + Schema []byte `protobuf:"bytes,1,opt,name=schema,proto3" json:"schema,omitempty"` +} + +func (x *SchemaResult) Reset() { + *x = SchemaResult{} + if protoimpl.UnsafeEnabled { + mi := &file_Flight_proto_msgTypes[8] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *SchemaResult) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SchemaResult) ProtoMessage() {} + +func (x *SchemaResult) ProtoReflect() protoreflect.Message { + mi := &file_Flight_proto_msgTypes[8] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SchemaResult.ProtoReflect.Descriptor instead. +func (*SchemaResult) Descriptor() ([]byte, []int) { + return file_Flight_proto_rawDescGZIP(), []int{8} +} + +func (x *SchemaResult) GetSchema() []byte { + if x != nil { + return x.Schema + } + return nil +} + +// +// The name or tag for a Flight. May be used as a way to retrieve or generate +// a flight or be used to expose a set of previously defined flights. +type FlightDescriptor struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Type FlightDescriptor_DescriptorType `protobuf:"varint,1,opt,name=type,proto3,enum=arrow.flight.protocol.FlightDescriptor_DescriptorType" json:"type,omitempty"` + // + // Opaque value used to express a command. Should only be defined when + // type = CMD. + Cmd []byte `protobuf:"bytes,2,opt,name=cmd,proto3" json:"cmd,omitempty"` + // + // List of strings identifying a particular dataset. Should only be defined + // when type = PATH. + Path []string `protobuf:"bytes,3,rep,name=path,proto3" json:"path,omitempty"` +} + +func (x *FlightDescriptor) Reset() { + *x = FlightDescriptor{} + if protoimpl.UnsafeEnabled { + mi := &file_Flight_proto_msgTypes[9] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *FlightDescriptor) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*FlightDescriptor) ProtoMessage() {} + +func (x *FlightDescriptor) ProtoReflect() protoreflect.Message { + mi := &file_Flight_proto_msgTypes[9] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use FlightDescriptor.ProtoReflect.Descriptor instead. +func (*FlightDescriptor) Descriptor() ([]byte, []int) { + return file_Flight_proto_rawDescGZIP(), []int{9} +} + +func (x *FlightDescriptor) GetType() FlightDescriptor_DescriptorType { + if x != nil { + return x.Type + } + return FlightDescriptor_UNKNOWN +} + +func (x *FlightDescriptor) GetCmd() []byte { + if x != nil { + return x.Cmd + } + return nil +} + +func (x *FlightDescriptor) GetPath() []string { + if x != nil { + return x.Path + } + return nil +} + +// +// The access coordinates for retrieval of a dataset. With a FlightInfo, a +// consumer is able to determine how to retrieve a dataset. +type FlightInfo struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // schema of the dataset as described in Schema.fbs::Schema. + Schema []byte `protobuf:"bytes,1,opt,name=schema,proto3" json:"schema,omitempty"` + // + // The descriptor associated with this info. + FlightDescriptor *FlightDescriptor `protobuf:"bytes,2,opt,name=flight_descriptor,json=flightDescriptor,proto3" json:"flight_descriptor,omitempty"` + // + // A list of endpoints associated with the flight. To consume the whole + // flight, all endpoints must be consumed. + Endpoint []*FlightEndpoint `protobuf:"bytes,3,rep,name=endpoint,proto3" json:"endpoint,omitempty"` + // Set these to -1 if unknown. + TotalRecords int64 `protobuf:"varint,4,opt,name=total_records,json=totalRecords,proto3" json:"total_records,omitempty"` + TotalBytes int64 `protobuf:"varint,5,opt,name=total_bytes,json=totalBytes,proto3" json:"total_bytes,omitempty"` +} + +func (x *FlightInfo) Reset() { + *x = FlightInfo{} + if protoimpl.UnsafeEnabled { + mi := &file_Flight_proto_msgTypes[10] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *FlightInfo) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*FlightInfo) ProtoMessage() {} + +func (x *FlightInfo) ProtoReflect() protoreflect.Message { + mi := &file_Flight_proto_msgTypes[10] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use FlightInfo.ProtoReflect.Descriptor instead. +func (*FlightInfo) Descriptor() ([]byte, []int) { + return file_Flight_proto_rawDescGZIP(), []int{10} +} + +func (x *FlightInfo) GetSchema() []byte { + if x != nil { + return x.Schema + } + return nil +} + +func (x *FlightInfo) GetFlightDescriptor() *FlightDescriptor { + if x != nil { + return x.FlightDescriptor + } + return nil +} + +func (x *FlightInfo) GetEndpoint() []*FlightEndpoint { + if x != nil { + return x.Endpoint + } + return nil +} + +func (x *FlightInfo) GetTotalRecords() int64 { + if x != nil { + return x.TotalRecords + } + return 0 +} + +func (x *FlightInfo) GetTotalBytes() int64 { + if x != nil { + return x.TotalBytes + } + return 0 +} + +// +// A particular stream or split associated with a flight. +type FlightEndpoint struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // + // Token used to retrieve this stream. + Ticket *Ticket `protobuf:"bytes,1,opt,name=ticket,proto3" json:"ticket,omitempty"` + // + // A list of URIs where this ticket can be redeemed. If the list is + // empty, the expectation is that the ticket can only be redeemed on the + // current service where the ticket was generated. + Location []*Location `protobuf:"bytes,2,rep,name=location,proto3" json:"location,omitempty"` +} + +func (x *FlightEndpoint) Reset() { + *x = FlightEndpoint{} + if protoimpl.UnsafeEnabled { + mi := &file_Flight_proto_msgTypes[11] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *FlightEndpoint) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*FlightEndpoint) ProtoMessage() {} + +func (x *FlightEndpoint) ProtoReflect() protoreflect.Message { + mi := &file_Flight_proto_msgTypes[11] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use FlightEndpoint.ProtoReflect.Descriptor instead. +func (*FlightEndpoint) Descriptor() ([]byte, []int) { + return file_Flight_proto_rawDescGZIP(), []int{11} +} + +func (x *FlightEndpoint) GetTicket() *Ticket { + if x != nil { + return x.Ticket + } + return nil +} + +func (x *FlightEndpoint) GetLocation() []*Location { + if x != nil { + return x.Location + } + return nil +} + +// +// A location where a Flight service will accept retrieval of a particular +// stream given a ticket. +type Location struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Uri string `protobuf:"bytes,1,opt,name=uri,proto3" json:"uri,omitempty"` +} + +func (x *Location) Reset() { + *x = Location{} + if protoimpl.UnsafeEnabled { + mi := &file_Flight_proto_msgTypes[12] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Location) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Location) ProtoMessage() {} + +func (x *Location) ProtoReflect() protoreflect.Message { + mi := &file_Flight_proto_msgTypes[12] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Location.ProtoReflect.Descriptor instead. +func (*Location) Descriptor() ([]byte, []int) { + return file_Flight_proto_rawDescGZIP(), []int{12} +} + +func (x *Location) GetUri() string { + if x != nil { + return x.Uri + } + return "" +} + +// +// An opaque identifier that the service can use to retrieve a particular +// portion of a stream. +type Ticket struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Ticket []byte `protobuf:"bytes,1,opt,name=ticket,proto3" json:"ticket,omitempty"` +} + +func (x *Ticket) Reset() { + *x = Ticket{} + if protoimpl.UnsafeEnabled { + mi := &file_Flight_proto_msgTypes[13] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Ticket) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Ticket) ProtoMessage() {} + +func (x *Ticket) ProtoReflect() protoreflect.Message { + mi := &file_Flight_proto_msgTypes[13] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Ticket.ProtoReflect.Descriptor instead. +func (*Ticket) Descriptor() ([]byte, []int) { + return file_Flight_proto_rawDescGZIP(), []int{13} +} + +func (x *Ticket) GetTicket() []byte { + if x != nil { + return x.Ticket + } + return nil +} + +// +// A batch of Arrow data as part of a stream of batches. +type FlightData struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // + // The descriptor of the data. This is only relevant when a client is + // starting a new DoPut stream. + FlightDescriptor *FlightDescriptor `protobuf:"bytes,1,opt,name=flight_descriptor,json=flightDescriptor,proto3" json:"flight_descriptor,omitempty"` + // + // Header for message data as described in Message.fbs::Message. + DataHeader []byte `protobuf:"bytes,2,opt,name=data_header,json=dataHeader,proto3" json:"data_header,omitempty"` + // + // Application-defined metadata. + AppMetadata []byte `protobuf:"bytes,3,opt,name=app_metadata,json=appMetadata,proto3" json:"app_metadata,omitempty"` + // + // The actual batch of Arrow data. Preferably handled with minimal-copies + // coming last in the definition to help with sidecar patterns (it is + // expected that some implementations will fetch this field off the wire + // with specialized code to avoid extra memory copies). + DataBody []byte `protobuf:"bytes,1000,opt,name=data_body,json=dataBody,proto3" json:"data_body,omitempty"` +} + +func (x *FlightData) Reset() { + *x = FlightData{} + if protoimpl.UnsafeEnabled { + mi := &file_Flight_proto_msgTypes[14] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *FlightData) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*FlightData) ProtoMessage() {} + +func (x *FlightData) ProtoReflect() protoreflect.Message { + mi := &file_Flight_proto_msgTypes[14] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use FlightData.ProtoReflect.Descriptor instead. +func (*FlightData) Descriptor() ([]byte, []int) { + return file_Flight_proto_rawDescGZIP(), []int{14} +} + +func (x *FlightData) GetFlightDescriptor() *FlightDescriptor { + if x != nil { + return x.FlightDescriptor + } + return nil +} + +func (x *FlightData) GetDataHeader() []byte { + if x != nil { + return x.DataHeader + } + return nil +} + +func (x *FlightData) GetAppMetadata() []byte { + if x != nil { + return x.AppMetadata + } + return nil +} + +func (x *FlightData) GetDataBody() []byte { + if x != nil { + return x.DataBody + } + return nil +} + +//* +// The response message associated with the submission of a DoPut. +type PutResult struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + AppMetadata []byte `protobuf:"bytes,1,opt,name=app_metadata,json=appMetadata,proto3" json:"app_metadata,omitempty"` +} + +func (x *PutResult) Reset() { + *x = PutResult{} + if protoimpl.UnsafeEnabled { + mi := &file_Flight_proto_msgTypes[15] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *PutResult) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PutResult) ProtoMessage() {} + +func (x *PutResult) ProtoReflect() protoreflect.Message { + mi := &file_Flight_proto_msgTypes[15] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use PutResult.ProtoReflect.Descriptor instead. +func (*PutResult) Descriptor() ([]byte, []int) { + return file_Flight_proto_rawDescGZIP(), []int{15} +} + +func (x *PutResult) GetAppMetadata() []byte { + if x != nil { + return x.AppMetadata + } + return nil +} + +var File_Flight_proto protoreflect.FileDescriptor + +var file_Flight_proto_rawDesc = []byte{ + 0x0a, 0x0c, 0x46, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x15, + 0x61, 0x72, 0x72, 0x6f, 0x77, 0x2e, 0x66, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x22, 0x57, 0x0a, 0x10, 0x48, 0x61, 0x6e, 0x64, 0x73, 0x68, 0x61, + 0x6b, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x29, 0x0a, 0x10, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x04, 0x52, 0x0f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x56, 0x65, 0x72, + 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x22, 0x58, + 0x0a, 0x11, 0x48, 0x61, 0x6e, 0x64, 0x73, 0x68, 0x61, 0x6b, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x29, 0x0a, 0x10, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x5f, + 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0f, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x18, + 0x0a, 0x07, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, + 0x07, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x22, 0x43, 0x0a, 0x09, 0x42, 0x61, 0x73, 0x69, + 0x63, 0x41, 0x75, 0x74, 0x68, 0x12, 0x1a, 0x0a, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, + 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, + 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x22, 0x07, 0x0a, + 0x05, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x42, 0x0a, 0x0a, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, + 0x54, 0x79, 0x70, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, + 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, + 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x2a, 0x0a, 0x08, 0x43, 0x72, + 0x69, 0x74, 0x65, 0x72, 0x69, 0x61, 0x12, 0x1e, 0x0a, 0x0a, 0x65, 0x78, 0x70, 0x72, 0x65, 0x73, + 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0a, 0x65, 0x78, 0x70, 0x72, + 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x30, 0x0a, 0x06, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, + 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, + 0x74, 0x79, 0x70, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x0c, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x22, 0x1c, 0x0a, 0x06, 0x52, 0x65, 0x73, 0x75, + 0x6c, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, + 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x22, 0x26, 0x0a, 0x0c, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, + 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x22, 0xb6, + 0x01, 0x0a, 0x10, 0x46, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, + 0x74, 0x6f, 0x72, 0x12, 0x4a, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x0e, 0x32, 0x36, 0x2e, 0x61, 0x72, 0x72, 0x6f, 0x77, 0x2e, 0x66, 0x6c, 0x69, 0x67, 0x68, 0x74, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2e, 0x46, 0x6c, 0x69, 0x67, 0x68, 0x74, + 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x2e, 0x44, 0x65, 0x73, 0x63, 0x72, + 0x69, 0x70, 0x74, 0x6f, 0x72, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, + 0x10, 0x0a, 0x03, 0x63, 0x6d, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x03, 0x63, 0x6d, + 0x64, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, + 0x04, 0x70, 0x61, 0x74, 0x68, 0x22, 0x30, 0x0a, 0x0e, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, + 0x74, 0x6f, 0x72, 0x54, 0x79, 0x70, 0x65, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, + 0x57, 0x4e, 0x10, 0x00, 0x12, 0x08, 0x0a, 0x04, 0x50, 0x41, 0x54, 0x48, 0x10, 0x01, 0x12, 0x07, + 0x0a, 0x03, 0x43, 0x4d, 0x44, 0x10, 0x02, 0x22, 0x83, 0x02, 0x0a, 0x0a, 0x46, 0x6c, 0x69, 0x67, + 0x68, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x12, 0x54, + 0x0a, 0x11, 0x66, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x5f, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, + 0x74, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x61, 0x72, 0x72, 0x6f, + 0x77, 0x2e, 0x66, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, + 0x6c, 0x2e, 0x46, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, + 0x6f, 0x72, 0x52, 0x10, 0x66, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, + 0x70, 0x74, 0x6f, 0x72, 0x12, 0x41, 0x0a, 0x08, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, + 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x61, 0x72, 0x72, 0x6f, 0x77, 0x2e, 0x66, + 0x6c, 0x69, 0x67, 0x68, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2e, 0x46, + 0x6c, 0x69, 0x67, 0x68, 0x74, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x08, 0x65, + 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x23, 0x0a, 0x0d, 0x74, 0x6f, 0x74, 0x61, 0x6c, + 0x5f, 0x72, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, + 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x73, 0x12, 0x1f, 0x0a, 0x0b, + 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, + 0x03, 0x52, 0x0a, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x42, 0x79, 0x74, 0x65, 0x73, 0x22, 0x84, 0x01, + 0x0a, 0x0e, 0x46, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, + 0x12, 0x35, 0x0a, 0x06, 0x74, 0x69, 0x63, 0x6b, 0x65, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x1d, 0x2e, 0x61, 0x72, 0x72, 0x6f, 0x77, 0x2e, 0x66, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2e, 0x54, 0x69, 0x63, 0x6b, 0x65, 0x74, 0x52, + 0x06, 0x74, 0x69, 0x63, 0x6b, 0x65, 0x74, 0x12, 0x3b, 0x0a, 0x08, 0x6c, 0x6f, 0x63, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x61, 0x72, 0x72, 0x6f, + 0x77, 0x2e, 0x66, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, + 0x6c, 0x2e, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x08, 0x6c, 0x6f, 0x63, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x1c, 0x0a, 0x08, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x12, 0x10, 0x0a, 0x03, 0x75, 0x72, 0x69, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, + 0x72, 0x69, 0x22, 0x20, 0x0a, 0x06, 0x54, 0x69, 0x63, 0x6b, 0x65, 0x74, 0x12, 0x16, 0x0a, 0x06, + 0x74, 0x69, 0x63, 0x6b, 0x65, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x74, 0x69, + 0x63, 0x6b, 0x65, 0x74, 0x22, 0xc4, 0x01, 0x0a, 0x0a, 0x46, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x44, + 0x61, 0x74, 0x61, 0x12, 0x54, 0x0a, 0x11, 0x66, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x5f, 0x64, 0x65, + 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, + 0x2e, 0x61, 0x72, 0x72, 0x6f, 0x77, 0x2e, 0x66, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2e, 0x46, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x44, 0x65, 0x73, + 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x52, 0x10, 0x66, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x44, + 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x12, 0x1f, 0x0a, 0x0b, 0x64, 0x61, 0x74, + 0x61, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0a, + 0x64, 0x61, 0x74, 0x61, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x21, 0x0a, 0x0c, 0x61, 0x70, + 0x70, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, + 0x52, 0x0b, 0x61, 0x70, 0x70, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x1c, 0x0a, + 0x09, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x62, 0x6f, 0x64, 0x79, 0x18, 0xe8, 0x07, 0x20, 0x01, 0x28, + 0x0c, 0x52, 0x08, 0x64, 0x61, 0x74, 0x61, 0x42, 0x6f, 0x64, 0x79, 0x22, 0x2e, 0x0a, 0x09, 0x50, + 0x75, 0x74, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x12, 0x21, 0x0a, 0x0c, 0x61, 0x70, 0x70, 0x5f, + 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, + 0x61, 0x70, 0x70, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x32, 0xa7, 0x06, 0x0a, 0x0d, + 0x46, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x64, 0x0a, + 0x09, 0x48, 0x61, 0x6e, 0x64, 0x73, 0x68, 0x61, 0x6b, 0x65, 0x12, 0x27, 0x2e, 0x61, 0x72, 0x72, + 0x6f, 0x77, 0x2e, 0x66, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, + 0x6f, 0x6c, 0x2e, 0x48, 0x61, 0x6e, 0x64, 0x73, 0x68, 0x61, 0x6b, 0x65, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x28, 0x2e, 0x61, 0x72, 0x72, 0x6f, 0x77, 0x2e, 0x66, 0x6c, 0x69, 0x67, + 0x68, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2e, 0x48, 0x61, 0x6e, 0x64, + 0x73, 0x68, 0x61, 0x6b, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x28, + 0x01, 0x30, 0x01, 0x12, 0x55, 0x0a, 0x0b, 0x4c, 0x69, 0x73, 0x74, 0x46, 0x6c, 0x69, 0x67, 0x68, + 0x74, 0x73, 0x12, 0x1f, 0x2e, 0x61, 0x72, 0x72, 0x6f, 0x77, 0x2e, 0x66, 0x6c, 0x69, 0x67, 0x68, + 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2e, 0x43, 0x72, 0x69, 0x74, 0x65, + 0x72, 0x69, 0x61, 0x1a, 0x21, 0x2e, 0x61, 0x72, 0x72, 0x6f, 0x77, 0x2e, 0x66, 0x6c, 0x69, 0x67, + 0x68, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2e, 0x46, 0x6c, 0x69, 0x67, + 0x68, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x22, 0x00, 0x30, 0x01, 0x12, 0x5d, 0x0a, 0x0d, 0x47, 0x65, + 0x74, 0x46, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x27, 0x2e, 0x61, 0x72, + 0x72, 0x6f, 0x77, 0x2e, 0x66, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x63, 0x6f, 0x6c, 0x2e, 0x46, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, + 0x70, 0x74, 0x6f, 0x72, 0x1a, 0x21, 0x2e, 0x61, 0x72, 0x72, 0x6f, 0x77, 0x2e, 0x66, 0x6c, 0x69, + 0x67, 0x68, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2e, 0x46, 0x6c, 0x69, + 0x67, 0x68, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x22, 0x00, 0x12, 0x5b, 0x0a, 0x09, 0x47, 0x65, 0x74, + 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x12, 0x27, 0x2e, 0x61, 0x72, 0x72, 0x6f, 0x77, 0x2e, 0x66, + 0x6c, 0x69, 0x67, 0x68, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2e, 0x46, + 0x6c, 0x69, 0x67, 0x68, 0x74, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x1a, + 0x23, 0x2e, 0x61, 0x72, 0x72, 0x6f, 0x77, 0x2e, 0x66, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2e, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x52, 0x65, + 0x73, 0x75, 0x6c, 0x74, 0x22, 0x00, 0x12, 0x4d, 0x0a, 0x05, 0x44, 0x6f, 0x47, 0x65, 0x74, 0x12, + 0x1d, 0x2e, 0x61, 0x72, 0x72, 0x6f, 0x77, 0x2e, 0x66, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2e, 0x54, 0x69, 0x63, 0x6b, 0x65, 0x74, 0x1a, 0x21, + 0x2e, 0x61, 0x72, 0x72, 0x6f, 0x77, 0x2e, 0x66, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2e, 0x46, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x44, 0x61, 0x74, + 0x61, 0x22, 0x00, 0x30, 0x01, 0x12, 0x52, 0x0a, 0x05, 0x44, 0x6f, 0x50, 0x75, 0x74, 0x12, 0x21, + 0x2e, 0x61, 0x72, 0x72, 0x6f, 0x77, 0x2e, 0x66, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2e, 0x46, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x44, 0x61, 0x74, + 0x61, 0x1a, 0x20, 0x2e, 0x61, 0x72, 0x72, 0x6f, 0x77, 0x2e, 0x66, 0x6c, 0x69, 0x67, 0x68, 0x74, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2e, 0x50, 0x75, 0x74, 0x52, 0x65, 0x73, + 0x75, 0x6c, 0x74, 0x22, 0x00, 0x28, 0x01, 0x30, 0x01, 0x12, 0x58, 0x0a, 0x0a, 0x44, 0x6f, 0x45, + 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x21, 0x2e, 0x61, 0x72, 0x72, 0x6f, 0x77, 0x2e, + 0x66, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2e, + 0x46, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x44, 0x61, 0x74, 0x61, 0x1a, 0x21, 0x2e, 0x61, 0x72, 0x72, + 0x6f, 0x77, 0x2e, 0x66, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, + 0x6f, 0x6c, 0x2e, 0x46, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x44, 0x61, 0x74, 0x61, 0x22, 0x00, 0x28, + 0x01, 0x30, 0x01, 0x12, 0x4c, 0x0a, 0x08, 0x44, 0x6f, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, + 0x1d, 0x2e, 0x61, 0x72, 0x72, 0x6f, 0x77, 0x2e, 0x66, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2e, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x1a, 0x1d, + 0x2e, 0x61, 0x72, 0x72, 0x6f, 0x77, 0x2e, 0x66, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2e, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x22, 0x00, 0x30, + 0x01, 0x12, 0x52, 0x0a, 0x0b, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, + 0x12, 0x1c, 0x2e, 0x61, 0x72, 0x72, 0x6f, 0x77, 0x2e, 0x66, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x21, + 0x2e, 0x61, 0x72, 0x72, 0x6f, 0x77, 0x2e, 0x66, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2e, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x79, 0x70, + 0x65, 0x22, 0x00, 0x30, 0x01, 0x42, 0x48, 0x0a, 0x1c, 0x6f, 0x72, 0x67, 0x2e, 0x61, 0x70, 0x61, + 0x63, 0x68, 0x65, 0x2e, 0x61, 0x72, 0x72, 0x6f, 0x77, 0x2e, 0x66, 0x6c, 0x69, 0x67, 0x68, 0x74, + 0x2e, 0x69, 0x6d, 0x70, 0x6c, 0x5a, 0x28, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, + 0x6d, 0x2f, 0x61, 0x70, 0x61, 0x63, 0x68, 0x65, 0x2f, 0x61, 0x72, 0x72, 0x6f, 0x77, 0x2f, 0x67, + 0x6f, 0x2f, 0x66, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x3b, 0x66, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x62, + 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_Flight_proto_rawDescOnce sync.Once + file_Flight_proto_rawDescData = file_Flight_proto_rawDesc +) + +func file_Flight_proto_rawDescGZIP() []byte { + file_Flight_proto_rawDescOnce.Do(func() { + file_Flight_proto_rawDescData = protoimpl.X.CompressGZIP(file_Flight_proto_rawDescData) + }) + return file_Flight_proto_rawDescData +} + +var file_Flight_proto_enumTypes = make([]protoimpl.EnumInfo, 1) +var file_Flight_proto_msgTypes = make([]protoimpl.MessageInfo, 16) +var file_Flight_proto_goTypes = []interface{}{ + (FlightDescriptor_DescriptorType)(0), // 0: arrow.flight.protocol.FlightDescriptor.DescriptorType + (*HandshakeRequest)(nil), // 1: arrow.flight.protocol.HandshakeRequest + (*HandshakeResponse)(nil), // 2: arrow.flight.protocol.HandshakeResponse + (*BasicAuth)(nil), // 3: arrow.flight.protocol.BasicAuth + (*Empty)(nil), // 4: arrow.flight.protocol.Empty + (*ActionType)(nil), // 5: arrow.flight.protocol.ActionType + (*Criteria)(nil), // 6: arrow.flight.protocol.Criteria + (*Action)(nil), // 7: arrow.flight.protocol.Action + (*Result)(nil), // 8: arrow.flight.protocol.Result + (*SchemaResult)(nil), // 9: arrow.flight.protocol.SchemaResult + (*FlightDescriptor)(nil), // 10: arrow.flight.protocol.FlightDescriptor + (*FlightInfo)(nil), // 11: arrow.flight.protocol.FlightInfo + (*FlightEndpoint)(nil), // 12: arrow.flight.protocol.FlightEndpoint + (*Location)(nil), // 13: arrow.flight.protocol.Location + (*Ticket)(nil), // 14: arrow.flight.protocol.Ticket + (*FlightData)(nil), // 15: arrow.flight.protocol.FlightData + (*PutResult)(nil), // 16: arrow.flight.protocol.PutResult +} +var file_Flight_proto_depIdxs = []int32{ + 0, // 0: arrow.flight.protocol.FlightDescriptor.type:type_name -> arrow.flight.protocol.FlightDescriptor.DescriptorType + 10, // 1: arrow.flight.protocol.FlightInfo.flight_descriptor:type_name -> arrow.flight.protocol.FlightDescriptor + 12, // 2: arrow.flight.protocol.FlightInfo.endpoint:type_name -> arrow.flight.protocol.FlightEndpoint + 14, // 3: arrow.flight.protocol.FlightEndpoint.ticket:type_name -> arrow.flight.protocol.Ticket + 13, // 4: arrow.flight.protocol.FlightEndpoint.location:type_name -> arrow.flight.protocol.Location + 10, // 5: arrow.flight.protocol.FlightData.flight_descriptor:type_name -> arrow.flight.protocol.FlightDescriptor + 1, // 6: arrow.flight.protocol.FlightService.Handshake:input_type -> arrow.flight.protocol.HandshakeRequest + 6, // 7: arrow.flight.protocol.FlightService.ListFlights:input_type -> arrow.flight.protocol.Criteria + 10, // 8: arrow.flight.protocol.FlightService.GetFlightInfo:input_type -> arrow.flight.protocol.FlightDescriptor + 10, // 9: arrow.flight.protocol.FlightService.GetSchema:input_type -> arrow.flight.protocol.FlightDescriptor + 14, // 10: arrow.flight.protocol.FlightService.DoGet:input_type -> arrow.flight.protocol.Ticket + 15, // 11: arrow.flight.protocol.FlightService.DoPut:input_type -> arrow.flight.protocol.FlightData + 15, // 12: arrow.flight.protocol.FlightService.DoExchange:input_type -> arrow.flight.protocol.FlightData + 7, // 13: arrow.flight.protocol.FlightService.DoAction:input_type -> arrow.flight.protocol.Action + 4, // 14: arrow.flight.protocol.FlightService.ListActions:input_type -> arrow.flight.protocol.Empty + 2, // 15: arrow.flight.protocol.FlightService.Handshake:output_type -> arrow.flight.protocol.HandshakeResponse + 11, // 16: arrow.flight.protocol.FlightService.ListFlights:output_type -> arrow.flight.protocol.FlightInfo + 11, // 17: arrow.flight.protocol.FlightService.GetFlightInfo:output_type -> arrow.flight.protocol.FlightInfo + 9, // 18: arrow.flight.protocol.FlightService.GetSchema:output_type -> arrow.flight.protocol.SchemaResult + 15, // 19: arrow.flight.protocol.FlightService.DoGet:output_type -> arrow.flight.protocol.FlightData + 16, // 20: arrow.flight.protocol.FlightService.DoPut:output_type -> arrow.flight.protocol.PutResult + 15, // 21: arrow.flight.protocol.FlightService.DoExchange:output_type -> arrow.flight.protocol.FlightData + 8, // 22: arrow.flight.protocol.FlightService.DoAction:output_type -> arrow.flight.protocol.Result + 5, // 23: arrow.flight.protocol.FlightService.ListActions:output_type -> arrow.flight.protocol.ActionType + 15, // [15:24] is the sub-list for method output_type + 6, // [6:15] is the sub-list for method input_type + 6, // [6:6] is the sub-list for extension type_name + 6, // [6:6] is the sub-list for extension extendee + 0, // [0:6] is the sub-list for field type_name +} + +func init() { file_Flight_proto_init() } +func file_Flight_proto_init() { + if File_Flight_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_Flight_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*HandshakeRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_Flight_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*HandshakeResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_Flight_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*BasicAuth); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_Flight_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Empty); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_Flight_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ActionType); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_Flight_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Criteria); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_Flight_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Action); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_Flight_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Result); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_Flight_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*SchemaResult); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_Flight_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*FlightDescriptor); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_Flight_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*FlightInfo); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_Flight_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*FlightEndpoint); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_Flight_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Location); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_Flight_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Ticket); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_Flight_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*FlightData); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_Flight_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*PutResult); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_Flight_proto_rawDesc, + NumEnums: 1, + NumMessages: 16, + NumExtensions: 0, + NumServices: 1, + }, + GoTypes: file_Flight_proto_goTypes, + DependencyIndexes: file_Flight_proto_depIdxs, + EnumInfos: file_Flight_proto_enumTypes, + MessageInfos: file_Flight_proto_msgTypes, + }.Build() + File_Flight_proto = out.File + file_Flight_proto_rawDesc = nil + file_Flight_proto_goTypes = nil + file_Flight_proto_depIdxs = nil +} diff --git a/go/arrow/flight/Flight_grpc.pb.go b/go/arrow/flight/Flight_grpc.pb.go new file mode 100644 index 00000000000..c2b98d5613e --- /dev/null +++ b/go/arrow/flight/Flight_grpc.pb.go @@ -0,0 +1,877 @@ +// Code generated by protoc-gen-go-grpc. DO NOT EDIT. + +package flight + +import ( + context "context" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" +) + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +const _ = grpc.SupportPackageIsVersion7 + +// FlightServiceClient is the client API for FlightService service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. +type FlightServiceClient interface { + // + // Handshake between client and server. Depending on the server, the + // handshake may be required to determine the token that should be used for + // future operations. Both request and response are streams to allow multiple + // round-trips depending on auth mechanism. + Handshake(ctx context.Context, opts ...grpc.CallOption) (FlightService_HandshakeClient, error) + // + // Get a list of available streams given a particular criteria. Most flight + // services will expose one or more streams that are readily available for + // retrieval. This api allows listing the streams available for + // consumption. A user can also provide a criteria. The criteria can limit + // the subset of streams that can be listed via this interface. Each flight + // service allows its own definition of how to consume criteria. + ListFlights(ctx context.Context, in *Criteria, opts ...grpc.CallOption) (FlightService_ListFlightsClient, error) + // + // For a given FlightDescriptor, get information about how the flight can be + // consumed. This is a useful interface if the consumer of the interface + // already can identify the specific flight to consume. This interface can + // also allow a consumer to generate a flight stream through a specified + // descriptor. For example, a flight descriptor might be something that + // includes a SQL statement or a Pickled Python operation that will be + // executed. In those cases, the descriptor will not be previously available + // within the list of available streams provided by ListFlights but will be + // available for consumption for the duration defined by the specific flight + // service. + GetFlightInfo(ctx context.Context, in *FlightDescriptor, opts ...grpc.CallOption) (*FlightInfo, error) + // + // For a given FlightDescriptor, get the Schema as described in Schema.fbs::Schema + // This is used when a consumer needs the Schema of flight stream. Similar to + // GetFlightInfo this interface may generate a new flight that was not previously + // available in ListFlights. + GetSchema(ctx context.Context, in *FlightDescriptor, opts ...grpc.CallOption) (*SchemaResult, error) + // + // Retrieve a single stream associated with a particular descriptor + // associated with the referenced ticket. A Flight can be composed of one or + // more streams where each stream can be retrieved using a separate opaque + // ticket that the flight service uses for managing a collection of streams. + DoGet(ctx context.Context, in *Ticket, opts ...grpc.CallOption) (FlightService_DoGetClient, error) + // + // Push a stream to the flight service associated with a particular + // flight stream. This allows a client of a flight service to upload a stream + // of data. Depending on the particular flight service, a client consumer + // could be allowed to upload a single stream per descriptor or an unlimited + // number. In the latter, the service might implement a 'seal' action that + // can be applied to a descriptor once all streams are uploaded. + DoPut(ctx context.Context, opts ...grpc.CallOption) (FlightService_DoPutClient, error) + // + // Open a bidirectional data channel for a given descriptor. This + // allows clients to send and receive arbitrary Arrow data and + // application-specific metadata in a single logical stream. In + // contrast to DoGet/DoPut, this is more suited for clients + // offloading computation (rather than storage) to a Flight service. + DoExchange(ctx context.Context, opts ...grpc.CallOption) (FlightService_DoExchangeClient, error) + // + // Flight services can support an arbitrary number of simple actions in + // addition to the possible ListFlights, GetFlightInfo, DoGet, DoPut + // operations that are potentially available. DoAction allows a flight client + // to do a specific action against a flight service. An action includes + // opaque request and response objects that are specific to the type action + // being undertaken. + DoAction(ctx context.Context, in *Action, opts ...grpc.CallOption) (FlightService_DoActionClient, error) + // + // A flight service exposes all of the available action types that it has + // along with descriptions. This allows different flight consumers to + // understand the capabilities of the flight service. + ListActions(ctx context.Context, in *Empty, opts ...grpc.CallOption) (FlightService_ListActionsClient, error) +} + +type flightServiceClient struct { + cc grpc.ClientConnInterface +} + +func NewFlightServiceClient(cc grpc.ClientConnInterface) FlightServiceClient { + return &flightServiceClient{cc} +} + +var flightServiceHandshakeStreamDesc = &grpc.StreamDesc{ + StreamName: "Handshake", + ServerStreams: true, + ClientStreams: true, +} + +func (c *flightServiceClient) Handshake(ctx context.Context, opts ...grpc.CallOption) (FlightService_HandshakeClient, error) { + stream, err := c.cc.NewStream(ctx, flightServiceHandshakeStreamDesc, "/arrow.flight.protocol.FlightService/Handshake", opts...) + if err != nil { + return nil, err + } + x := &flightServiceHandshakeClient{stream} + return x, nil +} + +type FlightService_HandshakeClient interface { + Send(*HandshakeRequest) error + Recv() (*HandshakeResponse, error) + grpc.ClientStream +} + +type flightServiceHandshakeClient struct { + grpc.ClientStream +} + +func (x *flightServiceHandshakeClient) Send(m *HandshakeRequest) error { + return x.ClientStream.SendMsg(m) +} + +func (x *flightServiceHandshakeClient) Recv() (*HandshakeResponse, error) { + m := new(HandshakeResponse) + if err := x.ClientStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + +var flightServiceListFlightsStreamDesc = &grpc.StreamDesc{ + StreamName: "ListFlights", + ServerStreams: true, +} + +func (c *flightServiceClient) ListFlights(ctx context.Context, in *Criteria, opts ...grpc.CallOption) (FlightService_ListFlightsClient, error) { + stream, err := c.cc.NewStream(ctx, flightServiceListFlightsStreamDesc, "/arrow.flight.protocol.FlightService/ListFlights", opts...) + if err != nil { + return nil, err + } + x := &flightServiceListFlightsClient{stream} + if err := x.ClientStream.SendMsg(in); err != nil { + return nil, err + } + if err := x.ClientStream.CloseSend(); err != nil { + return nil, err + } + return x, nil +} + +type FlightService_ListFlightsClient interface { + Recv() (*FlightInfo, error) + grpc.ClientStream +} + +type flightServiceListFlightsClient struct { + grpc.ClientStream +} + +func (x *flightServiceListFlightsClient) Recv() (*FlightInfo, error) { + m := new(FlightInfo) + if err := x.ClientStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + +var flightServiceGetFlightInfoStreamDesc = &grpc.StreamDesc{ + StreamName: "GetFlightInfo", +} + +func (c *flightServiceClient) GetFlightInfo(ctx context.Context, in *FlightDescriptor, opts ...grpc.CallOption) (*FlightInfo, error) { + out := new(FlightInfo) + err := c.cc.Invoke(ctx, "/arrow.flight.protocol.FlightService/GetFlightInfo", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +var flightServiceGetSchemaStreamDesc = &grpc.StreamDesc{ + StreamName: "GetSchema", +} + +func (c *flightServiceClient) GetSchema(ctx context.Context, in *FlightDescriptor, opts ...grpc.CallOption) (*SchemaResult, error) { + out := new(SchemaResult) + err := c.cc.Invoke(ctx, "/arrow.flight.protocol.FlightService/GetSchema", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +var flightServiceDoGetStreamDesc = &grpc.StreamDesc{ + StreamName: "DoGet", + ServerStreams: true, +} + +func (c *flightServiceClient) DoGet(ctx context.Context, in *Ticket, opts ...grpc.CallOption) (FlightService_DoGetClient, error) { + stream, err := c.cc.NewStream(ctx, flightServiceDoGetStreamDesc, "/arrow.flight.protocol.FlightService/DoGet", opts...) + if err != nil { + return nil, err + } + x := &flightServiceDoGetClient{stream} + if err := x.ClientStream.SendMsg(in); err != nil { + return nil, err + } + if err := x.ClientStream.CloseSend(); err != nil { + return nil, err + } + return x, nil +} + +type FlightService_DoGetClient interface { + Recv() (*FlightData, error) + grpc.ClientStream +} + +type flightServiceDoGetClient struct { + grpc.ClientStream +} + +func (x *flightServiceDoGetClient) Recv() (*FlightData, error) { + m := new(FlightData) + if err := x.ClientStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + +var flightServiceDoPutStreamDesc = &grpc.StreamDesc{ + StreamName: "DoPut", + ServerStreams: true, + ClientStreams: true, +} + +func (c *flightServiceClient) DoPut(ctx context.Context, opts ...grpc.CallOption) (FlightService_DoPutClient, error) { + stream, err := c.cc.NewStream(ctx, flightServiceDoPutStreamDesc, "/arrow.flight.protocol.FlightService/DoPut", opts...) + if err != nil { + return nil, err + } + x := &flightServiceDoPutClient{stream} + return x, nil +} + +type FlightService_DoPutClient interface { + Send(*FlightData) error + Recv() (*PutResult, error) + grpc.ClientStream +} + +type flightServiceDoPutClient struct { + grpc.ClientStream +} + +func (x *flightServiceDoPutClient) Send(m *FlightData) error { + return x.ClientStream.SendMsg(m) +} + +func (x *flightServiceDoPutClient) Recv() (*PutResult, error) { + m := new(PutResult) + if err := x.ClientStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + +var flightServiceDoExchangeStreamDesc = &grpc.StreamDesc{ + StreamName: "DoExchange", + ServerStreams: true, + ClientStreams: true, +} + +func (c *flightServiceClient) DoExchange(ctx context.Context, opts ...grpc.CallOption) (FlightService_DoExchangeClient, error) { + stream, err := c.cc.NewStream(ctx, flightServiceDoExchangeStreamDesc, "/arrow.flight.protocol.FlightService/DoExchange", opts...) + if err != nil { + return nil, err + } + x := &flightServiceDoExchangeClient{stream} + return x, nil +} + +type FlightService_DoExchangeClient interface { + Send(*FlightData) error + Recv() (*FlightData, error) + grpc.ClientStream +} + +type flightServiceDoExchangeClient struct { + grpc.ClientStream +} + +func (x *flightServiceDoExchangeClient) Send(m *FlightData) error { + return x.ClientStream.SendMsg(m) +} + +func (x *flightServiceDoExchangeClient) Recv() (*FlightData, error) { + m := new(FlightData) + if err := x.ClientStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + +var flightServiceDoActionStreamDesc = &grpc.StreamDesc{ + StreamName: "DoAction", + ServerStreams: true, +} + +func (c *flightServiceClient) DoAction(ctx context.Context, in *Action, opts ...grpc.CallOption) (FlightService_DoActionClient, error) { + stream, err := c.cc.NewStream(ctx, flightServiceDoActionStreamDesc, "/arrow.flight.protocol.FlightService/DoAction", opts...) + if err != nil { + return nil, err + } + x := &flightServiceDoActionClient{stream} + if err := x.ClientStream.SendMsg(in); err != nil { + return nil, err + } + if err := x.ClientStream.CloseSend(); err != nil { + return nil, err + } + return x, nil +} + +type FlightService_DoActionClient interface { + Recv() (*Result, error) + grpc.ClientStream +} + +type flightServiceDoActionClient struct { + grpc.ClientStream +} + +func (x *flightServiceDoActionClient) Recv() (*Result, error) { + m := new(Result) + if err := x.ClientStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + +var flightServiceListActionsStreamDesc = &grpc.StreamDesc{ + StreamName: "ListActions", + ServerStreams: true, +} + +func (c *flightServiceClient) ListActions(ctx context.Context, in *Empty, opts ...grpc.CallOption) (FlightService_ListActionsClient, error) { + stream, err := c.cc.NewStream(ctx, flightServiceListActionsStreamDesc, "/arrow.flight.protocol.FlightService/ListActions", opts...) + if err != nil { + return nil, err + } + x := &flightServiceListActionsClient{stream} + if err := x.ClientStream.SendMsg(in); err != nil { + return nil, err + } + if err := x.ClientStream.CloseSend(); err != nil { + return nil, err + } + return x, nil +} + +type FlightService_ListActionsClient interface { + Recv() (*ActionType, error) + grpc.ClientStream +} + +type flightServiceListActionsClient struct { + grpc.ClientStream +} + +func (x *flightServiceListActionsClient) Recv() (*ActionType, error) { + m := new(ActionType) + if err := x.ClientStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + +// FlightServiceService is the service API for FlightService service. +// Fields should be assigned to their respective handler implementations only before +// RegisterFlightServiceService is called. Any unassigned fields will result in the +// handler for that method returning an Unimplemented error. +type FlightServiceService struct { + // + // Handshake between client and server. Depending on the server, the + // handshake may be required to determine the token that should be used for + // future operations. Both request and response are streams to allow multiple + // round-trips depending on auth mechanism. + Handshake func(FlightService_HandshakeServer) error + // + // Get a list of available streams given a particular criteria. Most flight + // services will expose one or more streams that are readily available for + // retrieval. This api allows listing the streams available for + // consumption. A user can also provide a criteria. The criteria can limit + // the subset of streams that can be listed via this interface. Each flight + // service allows its own definition of how to consume criteria. + ListFlights func(*Criteria, FlightService_ListFlightsServer) error + // + // For a given FlightDescriptor, get information about how the flight can be + // consumed. This is a useful interface if the consumer of the interface + // already can identify the specific flight to consume. This interface can + // also allow a consumer to generate a flight stream through a specified + // descriptor. For example, a flight descriptor might be something that + // includes a SQL statement or a Pickled Python operation that will be + // executed. In those cases, the descriptor will not be previously available + // within the list of available streams provided by ListFlights but will be + // available for consumption for the duration defined by the specific flight + // service. + GetFlightInfo func(context.Context, *FlightDescriptor) (*FlightInfo, error) + // + // For a given FlightDescriptor, get the Schema as described in Schema.fbs::Schema + // This is used when a consumer needs the Schema of flight stream. Similar to + // GetFlightInfo this interface may generate a new flight that was not previously + // available in ListFlights. + GetSchema func(context.Context, *FlightDescriptor) (*SchemaResult, error) + // + // Retrieve a single stream associated with a particular descriptor + // associated with the referenced ticket. A Flight can be composed of one or + // more streams where each stream can be retrieved using a separate opaque + // ticket that the flight service uses for managing a collection of streams. + DoGet func(*Ticket, FlightService_DoGetServer) error + // + // Push a stream to the flight service associated with a particular + // flight stream. This allows a client of a flight service to upload a stream + // of data. Depending on the particular flight service, a client consumer + // could be allowed to upload a single stream per descriptor or an unlimited + // number. In the latter, the service might implement a 'seal' action that + // can be applied to a descriptor once all streams are uploaded. + DoPut func(FlightService_DoPutServer) error + // + // Open a bidirectional data channel for a given descriptor. This + // allows clients to send and receive arbitrary Arrow data and + // application-specific metadata in a single logical stream. In + // contrast to DoGet/DoPut, this is more suited for clients + // offloading computation (rather than storage) to a Flight service. + DoExchange func(FlightService_DoExchangeServer) error + // + // Flight services can support an arbitrary number of simple actions in + // addition to the possible ListFlights, GetFlightInfo, DoGet, DoPut + // operations that are potentially available. DoAction allows a flight client + // to do a specific action against a flight service. An action includes + // opaque request and response objects that are specific to the type action + // being undertaken. + DoAction func(*Action, FlightService_DoActionServer) error + // + // A flight service exposes all of the available action types that it has + // along with descriptions. This allows different flight consumers to + // understand the capabilities of the flight service. + ListActions func(*Empty, FlightService_ListActionsServer) error +} + +func (s *FlightServiceService) handshake(_ interface{}, stream grpc.ServerStream) error { + return s.Handshake(&flightServiceHandshakeServer{stream}) +} +func (s *FlightServiceService) listFlights(_ interface{}, stream grpc.ServerStream) error { + m := new(Criteria) + if err := stream.RecvMsg(m); err != nil { + return err + } + return s.ListFlights(m, &flightServiceListFlightsServer{stream}) +} +func (s *FlightServiceService) getFlightInfo(_ interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(FlightDescriptor) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return s.GetFlightInfo(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: s, + FullMethod: "/arrow.flight.protocol.FlightService/GetFlightInfo", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return s.GetFlightInfo(ctx, req.(*FlightDescriptor)) + } + return interceptor(ctx, in, info, handler) +} +func (s *FlightServiceService) getSchema(_ interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(FlightDescriptor) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return s.GetSchema(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: s, + FullMethod: "/arrow.flight.protocol.FlightService/GetSchema", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return s.GetSchema(ctx, req.(*FlightDescriptor)) + } + return interceptor(ctx, in, info, handler) +} +func (s *FlightServiceService) doGet(_ interface{}, stream grpc.ServerStream) error { + m := new(Ticket) + if err := stream.RecvMsg(m); err != nil { + return err + } + return s.DoGet(m, &flightServiceDoGetServer{stream}) +} +func (s *FlightServiceService) doPut(_ interface{}, stream grpc.ServerStream) error { + return s.DoPut(&flightServiceDoPutServer{stream}) +} +func (s *FlightServiceService) doExchange(_ interface{}, stream grpc.ServerStream) error { + return s.DoExchange(&flightServiceDoExchangeServer{stream}) +} +func (s *FlightServiceService) doAction(_ interface{}, stream grpc.ServerStream) error { + m := new(Action) + if err := stream.RecvMsg(m); err != nil { + return err + } + return s.DoAction(m, &flightServiceDoActionServer{stream}) +} +func (s *FlightServiceService) listActions(_ interface{}, stream grpc.ServerStream) error { + m := new(Empty) + if err := stream.RecvMsg(m); err != nil { + return err + } + return s.ListActions(m, &flightServiceListActionsServer{stream}) +} + +type FlightService_HandshakeServer interface { + Send(*HandshakeResponse) error + Recv() (*HandshakeRequest, error) + grpc.ServerStream +} + +type flightServiceHandshakeServer struct { + grpc.ServerStream +} + +func (x *flightServiceHandshakeServer) Send(m *HandshakeResponse) error { + return x.ServerStream.SendMsg(m) +} + +func (x *flightServiceHandshakeServer) Recv() (*HandshakeRequest, error) { + m := new(HandshakeRequest) + if err := x.ServerStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + +type FlightService_ListFlightsServer interface { + Send(*FlightInfo) error + grpc.ServerStream +} + +type flightServiceListFlightsServer struct { + grpc.ServerStream +} + +func (x *flightServiceListFlightsServer) Send(m *FlightInfo) error { + return x.ServerStream.SendMsg(m) +} + +type FlightService_DoGetServer interface { + Send(*FlightData) error + grpc.ServerStream +} + +type flightServiceDoGetServer struct { + grpc.ServerStream +} + +func (x *flightServiceDoGetServer) Send(m *FlightData) error { + return x.ServerStream.SendMsg(m) +} + +type FlightService_DoPutServer interface { + Send(*PutResult) error + Recv() (*FlightData, error) + grpc.ServerStream +} + +type flightServiceDoPutServer struct { + grpc.ServerStream +} + +func (x *flightServiceDoPutServer) Send(m *PutResult) error { + return x.ServerStream.SendMsg(m) +} + +func (x *flightServiceDoPutServer) Recv() (*FlightData, error) { + m := new(FlightData) + if err := x.ServerStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + +type FlightService_DoExchangeServer interface { + Send(*FlightData) error + Recv() (*FlightData, error) + grpc.ServerStream +} + +type flightServiceDoExchangeServer struct { + grpc.ServerStream +} + +func (x *flightServiceDoExchangeServer) Send(m *FlightData) error { + return x.ServerStream.SendMsg(m) +} + +func (x *flightServiceDoExchangeServer) Recv() (*FlightData, error) { + m := new(FlightData) + if err := x.ServerStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + +type FlightService_DoActionServer interface { + Send(*Result) error + grpc.ServerStream +} + +type flightServiceDoActionServer struct { + grpc.ServerStream +} + +func (x *flightServiceDoActionServer) Send(m *Result) error { + return x.ServerStream.SendMsg(m) +} + +type FlightService_ListActionsServer interface { + Send(*ActionType) error + grpc.ServerStream +} + +type flightServiceListActionsServer struct { + grpc.ServerStream +} + +func (x *flightServiceListActionsServer) Send(m *ActionType) error { + return x.ServerStream.SendMsg(m) +} + +// RegisterFlightServiceService registers a service implementation with a gRPC server. +func RegisterFlightServiceService(s grpc.ServiceRegistrar, srv *FlightServiceService) { + srvCopy := *srv + if srvCopy.Handshake == nil { + srvCopy.Handshake = func(FlightService_HandshakeServer) error { + return status.Errorf(codes.Unimplemented, "method Handshake not implemented") + } + } + if srvCopy.ListFlights == nil { + srvCopy.ListFlights = func(*Criteria, FlightService_ListFlightsServer) error { + return status.Errorf(codes.Unimplemented, "method ListFlights not implemented") + } + } + if srvCopy.GetFlightInfo == nil { + srvCopy.GetFlightInfo = func(context.Context, *FlightDescriptor) (*FlightInfo, error) { + return nil, status.Errorf(codes.Unimplemented, "method GetFlightInfo not implemented") + } + } + if srvCopy.GetSchema == nil { + srvCopy.GetSchema = func(context.Context, *FlightDescriptor) (*SchemaResult, error) { + return nil, status.Errorf(codes.Unimplemented, "method GetSchema not implemented") + } + } + if srvCopy.DoGet == nil { + srvCopy.DoGet = func(*Ticket, FlightService_DoGetServer) error { + return status.Errorf(codes.Unimplemented, "method DoGet not implemented") + } + } + if srvCopy.DoPut == nil { + srvCopy.DoPut = func(FlightService_DoPutServer) error { + return status.Errorf(codes.Unimplemented, "method DoPut not implemented") + } + } + if srvCopy.DoExchange == nil { + srvCopy.DoExchange = func(FlightService_DoExchangeServer) error { + return status.Errorf(codes.Unimplemented, "method DoExchange not implemented") + } + } + if srvCopy.DoAction == nil { + srvCopy.DoAction = func(*Action, FlightService_DoActionServer) error { + return status.Errorf(codes.Unimplemented, "method DoAction not implemented") + } + } + if srvCopy.ListActions == nil { + srvCopy.ListActions = func(*Empty, FlightService_ListActionsServer) error { + return status.Errorf(codes.Unimplemented, "method ListActions not implemented") + } + } + sd := grpc.ServiceDesc{ + ServiceName: "arrow.flight.protocol.FlightService", + Methods: []grpc.MethodDesc{ + { + MethodName: "GetFlightInfo", + Handler: srvCopy.getFlightInfo, + }, + { + MethodName: "GetSchema", + Handler: srvCopy.getSchema, + }, + }, + Streams: []grpc.StreamDesc{ + { + StreamName: "Handshake", + Handler: srvCopy.handshake, + ServerStreams: true, + ClientStreams: true, + }, + { + StreamName: "ListFlights", + Handler: srvCopy.listFlights, + ServerStreams: true, + }, + { + StreamName: "DoGet", + Handler: srvCopy.doGet, + ServerStreams: true, + }, + { + StreamName: "DoPut", + Handler: srvCopy.doPut, + ServerStreams: true, + ClientStreams: true, + }, + { + StreamName: "DoExchange", + Handler: srvCopy.doExchange, + ServerStreams: true, + ClientStreams: true, + }, + { + StreamName: "DoAction", + Handler: srvCopy.doAction, + ServerStreams: true, + }, + { + StreamName: "ListActions", + Handler: srvCopy.listActions, + ServerStreams: true, + }, + }, + Metadata: "Flight.proto", + } + + s.RegisterService(&sd, nil) +} + +// NewFlightServiceService creates a new FlightServiceService containing the +// implemented methods of the FlightService service in s. Any unimplemented +// methods will result in the gRPC server returning an UNIMPLEMENTED status to the client. +// This includes situations where the method handler is misspelled or has the wrong +// signature. For this reason, this function should be used with great care and +// is not recommended to be used by most users. +func NewFlightServiceService(s interface{}) *FlightServiceService { + ns := &FlightServiceService{} + if h, ok := s.(interface { + Handshake(FlightService_HandshakeServer) error + }); ok { + ns.Handshake = h.Handshake + } + if h, ok := s.(interface { + ListFlights(*Criteria, FlightService_ListFlightsServer) error + }); ok { + ns.ListFlights = h.ListFlights + } + if h, ok := s.(interface { + GetFlightInfo(context.Context, *FlightDescriptor) (*FlightInfo, error) + }); ok { + ns.GetFlightInfo = h.GetFlightInfo + } + if h, ok := s.(interface { + GetSchema(context.Context, *FlightDescriptor) (*SchemaResult, error) + }); ok { + ns.GetSchema = h.GetSchema + } + if h, ok := s.(interface { + DoGet(*Ticket, FlightService_DoGetServer) error + }); ok { + ns.DoGet = h.DoGet + } + if h, ok := s.(interface { + DoPut(FlightService_DoPutServer) error + }); ok { + ns.DoPut = h.DoPut + } + if h, ok := s.(interface { + DoExchange(FlightService_DoExchangeServer) error + }); ok { + ns.DoExchange = h.DoExchange + } + if h, ok := s.(interface { + DoAction(*Action, FlightService_DoActionServer) error + }); ok { + ns.DoAction = h.DoAction + } + if h, ok := s.(interface { + ListActions(*Empty, FlightService_ListActionsServer) error + }); ok { + ns.ListActions = h.ListActions + } + return ns +} + +// UnstableFlightServiceService is the service API for FlightService service. +// New methods may be added to this interface if they are added to the service +// definition, which is not a backward-compatible change. For this reason, +// use of this type is not recommended. +type UnstableFlightServiceService interface { + // + // Handshake between client and server. Depending on the server, the + // handshake may be required to determine the token that should be used for + // future operations. Both request and response are streams to allow multiple + // round-trips depending on auth mechanism. + Handshake(FlightService_HandshakeServer) error + // + // Get a list of available streams given a particular criteria. Most flight + // services will expose one or more streams that are readily available for + // retrieval. This api allows listing the streams available for + // consumption. A user can also provide a criteria. The criteria can limit + // the subset of streams that can be listed via this interface. Each flight + // service allows its own definition of how to consume criteria. + ListFlights(*Criteria, FlightService_ListFlightsServer) error + // + // For a given FlightDescriptor, get information about how the flight can be + // consumed. This is a useful interface if the consumer of the interface + // already can identify the specific flight to consume. This interface can + // also allow a consumer to generate a flight stream through a specified + // descriptor. For example, a flight descriptor might be something that + // includes a SQL statement or a Pickled Python operation that will be + // executed. In those cases, the descriptor will not be previously available + // within the list of available streams provided by ListFlights but will be + // available for consumption for the duration defined by the specific flight + // service. + GetFlightInfo(context.Context, *FlightDescriptor) (*FlightInfo, error) + // + // For a given FlightDescriptor, get the Schema as described in Schema.fbs::Schema + // This is used when a consumer needs the Schema of flight stream. Similar to + // GetFlightInfo this interface may generate a new flight that was not previously + // available in ListFlights. + GetSchema(context.Context, *FlightDescriptor) (*SchemaResult, error) + // + // Retrieve a single stream associated with a particular descriptor + // associated with the referenced ticket. A Flight can be composed of one or + // more streams where each stream can be retrieved using a separate opaque + // ticket that the flight service uses for managing a collection of streams. + DoGet(*Ticket, FlightService_DoGetServer) error + // + // Push a stream to the flight service associated with a particular + // flight stream. This allows a client of a flight service to upload a stream + // of data. Depending on the particular flight service, a client consumer + // could be allowed to upload a single stream per descriptor or an unlimited + // number. In the latter, the service might implement a 'seal' action that + // can be applied to a descriptor once all streams are uploaded. + DoPut(FlightService_DoPutServer) error + // + // Open a bidirectional data channel for a given descriptor. This + // allows clients to send and receive arbitrary Arrow data and + // application-specific metadata in a single logical stream. In + // contrast to DoGet/DoPut, this is more suited for clients + // offloading computation (rather than storage) to a Flight service. + DoExchange(FlightService_DoExchangeServer) error + // + // Flight services can support an arbitrary number of simple actions in + // addition to the possible ListFlights, GetFlightInfo, DoGet, DoPut + // operations that are potentially available. DoAction allows a flight client + // to do a specific action against a flight service. An action includes + // opaque request and response objects that are specific to the type action + // being undertaken. + DoAction(*Action, FlightService_DoActionServer) error + // + // A flight service exposes all of the available action types that it has + // along with descriptions. This allows different flight consumers to + // understand the capabilities of the flight service. + ListActions(*Empty, FlightService_ListActionsServer) error +} diff --git a/go/arrow/flight/client.go b/go/arrow/flight/client.go new file mode 100644 index 00000000000..d2962cd22b2 --- /dev/null +++ b/go/arrow/flight/client.go @@ -0,0 +1,56 @@ +package flight + +import ( + context "context" + + "google.golang.org/grpc" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" +) + +type FlightClient interface { + Authenticate(context.Context, ...grpc.CallOption) error + Close() error + FlightServiceClient +} + +type client struct { + conn *grpc.ClientConn + authHandler ClientAuthHandler + + FlightServiceClient +} + +func NewFlightClient(addr string, auth ClientAuthHandler, opts ...grpc.DialOption) (*client, error) { + if auth != nil { + opts = append([]grpc.DialOption{ + grpc.WithChainStreamInterceptor(createClientAuthStreamInterceptor(auth)), + grpc.WithChainUnaryInterceptor(createClientAuthUnaryInterceptor(auth)), + }, opts...) + } + + conn, err := grpc.Dial(addr, opts...) + if err != nil { + return nil, err + } + + return &client{conn: conn, FlightServiceClient: NewFlightServiceClient(conn), authHandler: auth}, nil +} + +func (c *client) Authenticate(ctx context.Context, opts ...grpc.CallOption) error { + if c.authHandler == nil { + return status.Error(codes.NotFound, "cannot authenticate without an auth-handler") + } + + stream, err := c.FlightServiceClient.Handshake(ctx, opts...) + if err != nil { + return err + } + + return c.authHandler.Authenticate(&clientAuthConn{stream}) +} + +func (c *client) Close() error { + c.FlightServiceClient = nil + return c.conn.Close() +} diff --git a/go/arrow/flight/client_auth.go b/go/arrow/flight/client_auth.go new file mode 100644 index 00000000000..f06ac5f1abc --- /dev/null +++ b/go/arrow/flight/client_auth.go @@ -0,0 +1,71 @@ +package flight + +import ( + context "context" + "strings" + + "google.golang.org/grpc" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/metadata" + "google.golang.org/grpc/status" +) + +type ClientAuthHandler interface { + Authenticate(AuthConn) error + GetToken() (string, error) +} + +type clientAuthConn struct { + stream FlightService_HandshakeClient +} + +func (a *clientAuthConn) Read() ([]byte, error) { + in, err := a.stream.Recv() + if err != nil { + return nil, err + } + + return in.Payload, nil +} + +func (a *clientAuthConn) Send(b []byte) error { + return a.stream.Send(&HandshakeRequest{Payload: b}) +} + +func createClientAuthUnaryInterceptor(auth ClientAuthHandler) grpc.UnaryClientInterceptor { + if auth == nil { + return func(ctx context.Context, method string, req, reply interface{}, cc *grpc.ClientConn, invoker grpc.UnaryInvoker, opts ...grpc.CallOption) error { + return invoker(ctx, method, req, reply, cc, opts...) + } + } + + return func(ctx context.Context, method string, req, reply interface{}, cc *grpc.ClientConn, invoker grpc.UnaryInvoker, opts ...grpc.CallOption) error { + tok, err := auth.GetToken() + if err != nil { + return status.Errorf(codes.Unauthenticated, "error retrieving token: %s", err) + } + + return invoker(metadata.NewOutgoingContext(ctx, metadata.Pairs(grpcAuthHeader, tok)), method, req, reply, cc, opts...) + } +} + +func createClientAuthStreamInterceptor(auth ClientAuthHandler) grpc.StreamClientInterceptor { + if auth == nil { + return func(ctx context.Context, desc *grpc.StreamDesc, cc *grpc.ClientConn, method string, streamer grpc.Streamer, opts ...grpc.CallOption) (grpc.ClientStream, error) { + return streamer(ctx, desc, cc, method, opts...) + } + } + + return func(ctx context.Context, desc *grpc.StreamDesc, cc *grpc.ClientConn, method string, streamer grpc.Streamer, opts ...grpc.CallOption) (grpc.ClientStream, error) { + if strings.HasSuffix(method, "/Handshake") { + return streamer(ctx, desc, cc, method, opts...) + } + + tok, err := auth.GetToken() + if err != nil { + return nil, status.Errorf(codes.Unauthenticated, "error retrieving token: %s", err) + } + + return streamer(metadata.NewOutgoingContext(ctx, metadata.Pairs(grpcAuthHeader, tok)), desc, cc, method, opts...) + } +} diff --git a/go/arrow/flight/flight_test.go b/go/arrow/flight/flight_test.go new file mode 100644 index 00000000000..ad3512562c6 --- /dev/null +++ b/go/arrow/flight/flight_test.go @@ -0,0 +1,148 @@ +// 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 flight_test + +import ( + context "context" + "errors" + "io" + "log" + "testing" + + "github.com/apache/arrow/go/arrow/flight" + "github.com/apache/arrow/go/arrow/internal/arrdata" + "github.com/apache/arrow/go/arrow/ipc" + "google.golang.org/grpc" + "google.golang.org/grpc/metadata" +) + +type flightServer struct{} + +func (f *flightServer) ListFlights(c *flight.Criteria, fs flight.FlightService_ListFlightsServer) error { + ctx := fs.Context() + md, ok := metadata.FromIncomingContext(ctx) + log.Println(md, ok) + return nil +} + +func (f *flightServer) DoGet(_ *flight.Ticket, fs flight.FlightService_DoGetServer) error { + recs := arrdata.Records["primitives"] + + w := ipc.NewFlightDataWriter(fs, ipc.WithSchema(recs[0].Schema())) + for _, r := range recs { + w.Write(r) + } + + return nil +} + +type servAuth struct{} + +func (a *servAuth) Authenticate(c flight.AuthConn) error { + in, err := c.Read() + if err == io.EOF { + return nil + } + + if err != nil { + return err + } + + log.Println(string(in)) + return c.Send([]byte("baz")) +} + +func (a *servAuth) IsValid(token string) error { + if token == "baz" { + return nil + } + return errors.New("novalid") +} + +type clientAuth struct{} + +func (a *clientAuth) Authenticate(c flight.AuthConn) error { + if err := c.Send([]byte("foobar")); err != nil { + return err + } + + in, err := c.Read() + log.Println(in) + return err +} + +func (a *clientAuth) GetToken() (string, error) { + return "baz", nil +} + +func TestServer(t *testing.T) { + f := &flightServer{} + service := &flight.FlightServiceService{ + ListFlights: f.ListFlights, + DoGet: f.DoGet, + } + + s := flight.NewFlightServer(&servAuth{}) + s.Init("localhost:0") + s.RegisterFlightService(service) + + log.Println(s.Addr()) + + go s.Serve() + defer s.Shutdown() + + client, err := flight.NewFlightClient(s.Addr().String(), &clientAuth{}, grpc.WithInsecure()) + if err != nil { + t.Error(err) + } + defer client.Close() + + err = client.Authenticate(context.Background()) + if err != nil { + t.Error(err) + } + + fistream, err := client.ListFlights(context.Background(), &flight.Criteria{}) + if err != nil { + t.Error(err) + } + + fi, err := fistream.Recv() + log.Println(fi, err) + + fdata, err := client.DoGet(context.Background(), &flight.Ticket{}) + if err != nil { + t.Error(err) + } + + r, err := ipc.NewFlightDataReader(fdata) + if err != nil { + t.Error(err) + } + + for { + rec, err := r.Read() + if err != nil { + if err == io.EOF { + break + } + t.Error(err) + } + + log.Println(rec) + } +} diff --git a/go/arrow/flight/gen.go b/go/arrow/flight/gen.go new file mode 100644 index 00000000000..d04844eeedf --- /dev/null +++ b/go/arrow/flight/gen.go @@ -0,0 +1,3 @@ +package flight // import "github.com/apache/arrow/go/arrow/flight" + +//go:generate protoc -I../../../format --go_out=. --go-grpc_out=. --go_opt=paths=source_relative --go-grpc_opt=paths=source_relative Flight.proto diff --git a/go/arrow/flight/server.go b/go/arrow/flight/server.go new file mode 100644 index 00000000000..c4666f6c0fa --- /dev/null +++ b/go/arrow/flight/server.go @@ -0,0 +1,102 @@ +package flight + +import ( + "net" + "os" + "os/signal" + + "google.golang.org/grpc" +) + +// Server is an interface for hiding some of the grpc specifics to make +// it slightly easier to manage a flight service, slightly modeled after +// the C++ implementation +type Server interface { + // Init takes in the address to bind to and creates the listener + Init(addr string) error + // Addr will return the address that was bound to for the service to listen on + Addr() net.Addr + // SetShutdownOnSignals sets notifications on the given signals to call GracefulStop + // on the grpc service if any of those signals are received + SetShutdownOnSignals(sig ...os.Signal) + // Serve blocks until accepting a connection fails with a fatal error. It will return + // a non-nil error unless it stopped due to calling Shutdown or receiving one of the + // signals set in SetShutdownOnSignals + Serve() error + // Shutdown will call GracefulStop on the grpc server so that it stops accepting connections + // and will wait until current methods complete + Shutdown() + // RegisterFlightService sets up the handler for the Flight Endpoints as per + // normal Grpc setups + RegisterFlightService(*FlightServiceService) +} + +type server struct { + lis net.Listener + sigChannel <-chan os.Signal + done chan bool + + authHandler ServerAuthHandler + server *grpc.Server +} + +// NewFlightServer takes in an auth handler for managing the handshake authentication +// and any grpc Server options desired, such as TLS certs and so on which will just +// be passed through to the underlying grpc server. +// +// Alternatively, a grpc server can be created normally without this helper as the +// grpc server generated code is still being exported. This only exists to allow +// the utility of the helpers +func NewFlightServer(auth ServerAuthHandler, opt ...grpc.ServerOption) Server { + if auth != nil { + opt = append([]grpc.ServerOption{ + grpc.ChainStreamInterceptor(createServerAuthStreamInterceptor(auth)), + grpc.ChainUnaryInterceptor(createServerAuthUnaryInterceptor(auth)), + }, opt...) + } + + return &server{ + authHandler: auth, + server: grpc.NewServer(opt...), + } +} + +func (s *server) Init(addr string) (err error) { + s.lis, err = net.Listen("tcp", addr) + return +} + +func (s *server) Addr() net.Addr { + return s.lis.Addr() +} + +func (s *server) SetShutdownOnSignals(sig ...os.Signal) { + c := make(chan os.Signal, 1) + signal.Notify(c, sig...) + s.sigChannel = c +} + +func (s *server) Serve() error { + s.done = make(chan bool) + go func() { + select { + case sig := <-s.sigChannel: + s.server.GracefulStop() + case <-s.done: + } + }() + err := s.server.Serve(s.lis) + close(s.done) + return err +} + +func (s *server) RegisterFlightService(svc *FlightServiceService) { + if svc.Handshake == nil { + svc.Handshake = s.handshake + } + RegisterFlightServiceService(s.server, svc) +} + +func (s *server) Shutdown() { + s.server.GracefulStop() +} diff --git a/go/arrow/flight/server_auth.go b/go/arrow/flight/server_auth.go new file mode 100644 index 00000000000..12594814504 --- /dev/null +++ b/go/arrow/flight/server_auth.go @@ -0,0 +1,112 @@ +package flight + +import ( + "context" + "strings" + + "google.golang.org/grpc" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/metadata" + "google.golang.org/grpc/status" +) + +const grpcAuthHeader = "auth-token-bin" + +// AuthConn wraps the stream from grpc for handshakes to simplify handling +// handshake request and response from the flight.proto forwarding just the +// payloads and errors instead of having to deal with the handshake request +// and response protos directly +type AuthConn interface { + Read() ([]byte, error) + Send([]byte) error +} + +type serverAuthConn struct { + stream FlightService_HandshakeServer +} + +func (a *serverAuthConn) Read() ([]byte, error) { + in, err := a.stream.Recv() + if err != nil { + return nil, err + } + + return in.Payload, nil +} + +func (a *serverAuthConn) Send(b []byte) error { + return a.stream.Send(&HandshakeResponse{Payload: b}) +} + +// ServerAuthHandler defines an interface for the server to perform the handshake. +// The token is expected to be sent as part of the context metadata in subsequent +// requests with a key of "auth-token-bin" which will then call IsValid to validate +// +// TODO: implement returning identifying information with the token +type ServerAuthHandler interface { + Authenticate(AuthConn) error + IsValid(token string) error +} + +func createServerAuthUnaryInterceptor(auth ServerAuthHandler) grpc.UnaryServerInterceptor { + if auth == nil { + return func(ctx context.Context, req interface{}, _ *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) { + return handler(ctx, req) + } + } + + return func(ctx context.Context, req interface{}, _ *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) { + var authTok string + md, ok := metadata.FromIncomingContext(ctx) + if ok { + vals := md.Get(grpcAuthHeader) + if len(vals) > 0 { + authTok = vals[0] + } + } + + if err := auth.IsValid(authTok); err != nil { + return nil, status.Errorf(codes.PermissionDenied, "auth-error: %s", err) + } + + return handler(ctx, req) + } +} + +func createServerAuthStreamInterceptor(auth ServerAuthHandler) grpc.StreamServerInterceptor { + if auth == nil { + return func(srv interface{}, stream grpc.ServerStream, info *grpc.StreamServerInfo, handler grpc.StreamHandler) error { + return handler(srv, stream) + } + } + + return func(srv interface{}, stream grpc.ServerStream, info *grpc.StreamServerInfo, handler grpc.StreamHandler) error { + if strings.HasSuffix(info.FullMethod, "/Handshake") { + return handler(srv, stream) + } + + var authTok string + md, ok := metadata.FromIncomingContext(stream.Context()) + if ok { + vals := md.Get(grpcAuthHeader) + if len(vals) > 0 { + authTok = vals[0] + } + } + + if err := auth.IsValid(authTok); err != nil { + return status.Errorf(codes.Unauthenticated, "auth-error: %s", err) + } + + return handler(srv, stream) + } +} + +// our implementation of handshake using the authhandler +func (s *server) handshake(stream FlightService_HandshakeServer) error { + if s.authHandler == nil { + return nil + } + + return s.authHandler.Authenticate(&serverAuthConn{stream}) +} diff --git a/go/arrow/go.mod b/go/arrow/go.mod index a83f7cc2fdb..f5a30780fd8 100644 --- a/go/arrow/go.mod +++ b/go/arrow/go.mod @@ -20,8 +20,16 @@ go 1.12 require ( github.com/davecgh/go-spew v1.1.0 // indirect + github.com/golang/protobuf v1.4.2 github.com/google/flatbuffers v1.11.0 github.com/pmezard/go-difflib v1.0.0 // indirect github.com/stretchr/testify v1.2.0 + golang.org/x/net v0.0.0-20200904194848-62affa334b73 // indirect + golang.org/x/sys v0.0.0-20200909081042-eff7692f9009 // indirect + golang.org/x/text v0.3.3 // indirect golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 + google.golang.org/genproto v0.0.0-20200910191746-8ad3c7ee2cd1 // indirect + google.golang.org/grpc v1.32.0 + google.golang.org/grpc/cmd/protoc-gen-go-grpc v0.0.0-20200910201057-6591123024b3 // indirect + google.golang.org/protobuf v1.25.0 ) diff --git a/go/arrow/go.sum b/go/arrow/go.sum index 25e38a1bb4a..15cf9f5f467 100644 --- a/go/arrow/go.sum +++ b/go/arrow/go.sum @@ -1,10 +1,103 @@ +cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= +github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= +github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= +github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= +github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.1 h1:ZFgWrT+bLgsYPirOnRfKLYJLvssAegOj/hgyMFdJZe0= +github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= +github.com/golang/protobuf v1.4.2 h1:+Z5KGCizgyZCbGh1KZqA0fcLLkwbsjIzS4aV2v7wJX0= +github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/google/flatbuffers v1.11.0 h1:O7CEyB8Cb3/DmtxODGtLHcEvpr81Jm5qLg/hsHnxA2A= github.com/google/flatbuffers v1.11.0/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8= +github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/stretchr/testify v1.2.0 h1:LThGCOvhuJic9Gyd1VBCkhyUXmO8vKaBFvBsJ2k03rg= github.com/stretchr/testify v1.2.0/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190311183353-d8887717615a h1:oWX7TPOiFAMXLq8o0ikBYfCJVlRHBcsciT5bXOrH628= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20200904194848-62affa334b73 h1:MXfv8rhZWmFeqX3GNZRsd6vOLoaCHjYEX3qkRo3YBUA= +golang.org/x/net v0.0.0-20200904194848-62affa334b73/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a h1:1BGLXjeY4akVXGgbC9HugT3Jv3hCI0z56oJR5vAMgBU= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200909081042-eff7692f9009 h1:W0lCpv29Hv0UaM1LXb9QlBHLNP8UFfcKjblhVCWftOM= +golang.org/x/sys v0.0.0-20200909081042-eff7692f9009/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013 h1:+kGHl1aib/qcwaRi1CbqBZ1rk19r85MNUf8HaBghugY= +google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= +google.golang.org/genproto v0.0.0-20200910191746-8ad3c7ee2cd1 h1:Oi/dETbxPPblvoi4hgkzJun62A4dwuBsTM0UcZYpN3U= +google.golang.org/genproto v0.0.0-20200910191746-8ad3c7ee2cd1/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= +google.golang.org/grpc v1.27.0 h1:rRYRFMVgRv6E0D70Skyfsr28tDXIuuPZyWGMPdMcnXg= +google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.32.0 h1:zWTV+LMdc3kaiJMSTOFz2UgSBgx8RNQoTGiZu3fR9S0= +google.golang.org/grpc v1.32.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc/cmd/protoc-gen-go-grpc v0.0.0-20200910201057-6591123024b3 h1:MZjUhWVLZHiPPNKvwdt31HZVHrASfgk1ScV3vVTKbDo= +google.golang.org/grpc/cmd/protoc-gen-go-grpc v0.0.0-20200910201057-6591123024b3/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= +google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= +google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= +google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= +google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c= +google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= +honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/go/arrow/ipc/flight_data_reader.go b/go/arrow/ipc/flight_data_reader.go new file mode 100644 index 00000000000..fb52416d1c7 --- /dev/null +++ b/go/arrow/ipc/flight_data_reader.go @@ -0,0 +1,141 @@ +// 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 ipc + +import ( + "bytes" + "io" + + "github.com/apache/arrow/go/arrow" + "github.com/apache/arrow/go/arrow/array" + "github.com/apache/arrow/go/arrow/flight" + "github.com/apache/arrow/go/arrow/internal/flatbuf" + "github.com/apache/arrow/go/arrow/memory" + "golang.org/x/xerrors" +) + +type FlightDataStreamReader interface { + Recv() (*flight.FlightData, error) +} + +type FlightDataReader struct { + r FlightDataStreamReader + schema *arrow.Schema + + rec array.Record + err error + + types dictTypeMap + memo dictMemo + + mem memory.Allocator + + done bool +} + +func NewFlightDataReader(r FlightDataStreamReader, opts ...Option) (*FlightDataReader, error) { + cfg := newConfig(opts...) + + rr := &FlightDataReader{ + r: r, + mem: cfg.alloc, + } + + msg, err := rr.nextMessage() + if err != nil { + return nil, xerrors.Errorf("arrow/ipc: could not read message schema: %w", err) + } + + if msg.Type() != MessageSchema { + return nil, xerrors.Errorf("arrow/ipc: invalid message type (got=%v, want=%v)", msg.Type(), MessageSchema) + } + + var schemaFB flatbuf.Schema + initFB(&schemaFB, msg.msg.Header) + + rr.types, err = dictTypesFromFB(&schemaFB) + if err != nil { + return nil, xerrors.Errorf("arrow/ipc: could not read dictionary types from message schema: %w", err) + } + + for range rr.types { + panic("not implemented") // ReadNextDictionary + } + + rr.schema, err = schemaFromFB(&schemaFB, &rr.memo) + if err != nil { + return nil, xerrors.Errorf("arrow/ipc: could not decode schema from message schema: %w", err) + } + + if cfg.schema != nil && !cfg.schema.Equal(rr.schema) { + return nil, errInconsistentSchema + } + + return rr, nil +} + +func (f *FlightDataReader) nextMessage() (*Message, error) { + fd, err := f.r.Recv() + if err != nil { + return nil, err + } + + return NewMessage(memory.NewBufferBytes(fd.DataHeader), memory.NewBufferBytes(fd.DataBody)), nil +} + +func (f *FlightDataReader) next() bool { + var msg *Message + msg, f.err = f.nextMessage() + if f.err != nil { + f.done = true + if f.err == io.EOF { + f.err = nil + } + return false + } + + if got, want := msg.Type(), MessageRecordBatch; got != want { + f.err = xerrors.Errorf("arrow/ipc: invalid message type (got=%v, want=%v)", got, want) + return false + } + + f.rec = newRecord(f.schema, msg.meta, bytes.NewReader(msg.body.Bytes())) + return true +} + +func (f *FlightDataReader) Record() array.Record { + return f.rec +} + +func (f *FlightDataReader) Read() (array.Record, error) { + if f.rec != nil { + f.rec.Release() + f.rec = nil + } + + if !f.next() { + if f.done { + return nil, io.EOF + } + return nil, f.err + } + + return f.rec, nil +} + +func (f *FlightDataReader) Err() error { return f.err } +func (f *FlightDataReader) Schema() *arrow.Schema { return f.schema } diff --git a/go/arrow/ipc/flight_data_writer.go b/go/arrow/ipc/flight_data_writer.go new file mode 100644 index 00000000000..a12ba53f282 --- /dev/null +++ b/go/arrow/ipc/flight_data_writer.go @@ -0,0 +1,132 @@ +// 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 ipc + +import ( + "bytes" + + "github.com/apache/arrow/go/arrow" + "github.com/apache/arrow/go/arrow/array" + "github.com/apache/arrow/go/arrow/bitutil" + "github.com/apache/arrow/go/arrow/flight" + "github.com/apache/arrow/go/arrow/memory" + "golang.org/x/xerrors" +) + +type FlightDataStreamWriter interface { + Send(*flight.FlightData) error +} + +type FlightDataWriter struct { + w FlightDataStreamWriter + fd flight.FlightData + buf bytes.Buffer + + mem memory.Allocator + started bool + schema *arrow.Schema +} + +func NewFlightDataWriter(w FlightDataStreamWriter, opts ...Option) *FlightDataWriter { + cfg := newConfig(opts...) + return &FlightDataWriter{ + w: w, + mem: cfg.alloc, + schema: cfg.schema, + } +} + +func (w *FlightDataWriter) start() error { + w.started = true + + ps := payloadsFromSchema(w.schema, w.mem, nil) + defer ps.Release() + + for i := range ps { + if err := w.writePayload(&ps[i]); err != nil { + return err + } + } + + return nil +} + +func (w *FlightDataWriter) Close() (err error) { + if !w.started { + err = w.start() + } + + return err +} + +func (w *FlightDataWriter) Write(rec array.Record) error { + if !w.started { + err := w.start() + if err != nil { + return err + } + } + + schema := rec.Schema() + if schema == nil || !schema.Equal(w.schema) { + return errInconsistentSchema + } + + const allow64b = true + var ( + data = payload{} + enc = newRecordEncoder(w.mem, 0, kMaxNestingDepth, allow64b) + ) + defer data.Release() + + if err := enc.Encode(&data, rec); err != nil { + return xerrors.Errorf("arrow/ipc: could not encode record to payload: %w", err) + } + + return w.writePayload(&data) +} + +func (w *FlightDataWriter) writePayload(data *payload) (err error) { + w.fd.DataHeader = data.meta.Bytes() + tmp := &w.buf + tmp.Reset() + + for _, bufs := range data.body { + if bufs == nil { + continue + } + + size := int64(bufs.Len()) + padding := bitutil.CeilByte64(size) - size + if size > 0 { + _, err = tmp.Write(bufs.Bytes()) + if err != nil { + return xerrors.Errorf("arrow/ipc: could not write payload message body: %w", err) + } + } + + if padding > 0 { + _, err = tmp.Write(paddingBytes[:padding]) + if err != nil { + return xerrors.Errorf("arrow/ipc: could not write payload message padding: %w", err) + } + } + } + + w.fd.DataBody = tmp.Bytes() + return w.w.Send(&w.fd) +} From b8e00dbb5a918f87dd524fcaa31d2ec5b381c3a2 Mon Sep 17 00:00:00 2001 From: Matthew Topol Date: Sat, 12 Sep 2020 14:35:43 -0400 Subject: [PATCH 2/8] remove unused var --- go/arrow/flight/server.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go/arrow/flight/server.go b/go/arrow/flight/server.go index c4666f6c0fa..e25fd69dd4f 100644 --- a/go/arrow/flight/server.go +++ b/go/arrow/flight/server.go @@ -80,7 +80,7 @@ func (s *server) Serve() error { s.done = make(chan bool) go func() { select { - case sig := <-s.sigChannel: + case <-s.sigChannel: s.server.GracefulStop() case <-s.done: } From 741543ef9890b6b2b369c96ca16caac941b6e742 Mon Sep 17 00:00:00 2001 From: Matthew Topol Date: Sat, 12 Sep 2020 14:56:40 -0400 Subject: [PATCH 3/8] update deps and add more comments / docs --- go/arrow/flight/client.go | 21 +++++++++++++++++++-- go/arrow/flight/client_auth.go | 4 ++++ go/arrow/go.mod | 2 +- go/arrow/go.sum | 5 +++-- 4 files changed, 27 insertions(+), 5 deletions(-) diff --git a/go/arrow/flight/client.go b/go/arrow/flight/client.go index d2962cd22b2..d9940482434 100644 --- a/go/arrow/flight/client.go +++ b/go/arrow/flight/client.go @@ -8,9 +8,18 @@ import ( "google.golang.org/grpc/status" ) -type FlightClient interface { +// Client is an interface wrapped around the generated FlightServiceClient which is +// generated by grpc protobuf definitions. This interface provides a useful hiding +// of the authentication handshake via calling Authenticate and using the +// ClientAuthHandler rather than manually having to implement the grpc communication +// and sending of the auth token. +type Client interface { + // Authenticate uses the ClientAuthHandler that was used when creating the client + // in order to use the Handshake endpoints of the service. Authenticate(context.Context, ...grpc.CallOption) error Close() error + // join the interface from the FlightServiceClient instead of re-defining all + // the endpoints here. FlightServiceClient } @@ -21,7 +30,15 @@ type client struct { FlightServiceClient } -func NewFlightClient(addr string, auth ClientAuthHandler, opts ...grpc.DialOption) (*client, error) { +// NewFlightClient takes in the address of the grpc server and an auth handler for the +// application-level handshake. If using TLS or other grpc configurations they can still +// be passed via the grpc.DialOption list just as if connecting manually without this +// helper function. +// +// Alternatively, a grpc client can be constructed as normal without this helper as the +// grpc generated client code is still exported. This exists to add utility and helpers +// around the authentication and passing the token with requests. +func NewFlightClient(addr string, auth ClientAuthHandler, opts ...grpc.DialOption) (Client, error) { if auth != nil { opts = append([]grpc.DialOption{ grpc.WithChainStreamInterceptor(createClientAuthStreamInterceptor(auth)), diff --git a/go/arrow/flight/client_auth.go b/go/arrow/flight/client_auth.go index f06ac5f1abc..8889db77c32 100644 --- a/go/arrow/flight/client_auth.go +++ b/go/arrow/flight/client_auth.go @@ -10,6 +10,10 @@ import ( "google.golang.org/grpc/status" ) +// ClientAuthHandler defines an interface for the Flight client to perform +// the authentication handshake. The token that is retrieved from GetToken +// will be sent as part of the context metadata in subsequent requests after +// authentication is performed using the key "auth-token-bin". type ClientAuthHandler interface { Authenticate(AuthConn) error GetToken() (string, error) diff --git a/go/arrow/go.mod b/go/arrow/go.mod index f5a30780fd8..ca760281449 100644 --- a/go/arrow/go.mod +++ b/go/arrow/go.mod @@ -28,7 +28,7 @@ require ( golang.org/x/sys v0.0.0-20200909081042-eff7692f9009 // indirect golang.org/x/text v0.3.3 // indirect golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 - google.golang.org/genproto v0.0.0-20200910191746-8ad3c7ee2cd1 // indirect + google.golang.org/genproto v0.0.0-20200911024640-645f7a48b24f // indirect google.golang.org/grpc v1.32.0 google.golang.org/grpc/cmd/protoc-gen-go-grpc v0.0.0-20200910201057-6591123024b3 // indirect google.golang.org/protobuf v1.25.0 diff --git a/go/arrow/go.sum b/go/arrow/go.sum index 15cf9f5f467..f56e738d4c3 100644 --- a/go/arrow/go.sum +++ b/go/arrow/go.sum @@ -29,6 +29,7 @@ github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5a github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.0 h1:/QaMHBdZ26BB3SSst0Iwl10Epc+xhTquomWX0oZEB6w= github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= @@ -77,8 +78,8 @@ google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoA google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013 h1:+kGHl1aib/qcwaRi1CbqBZ1rk19r85MNUf8HaBghugY= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto v0.0.0-20200910191746-8ad3c7ee2cd1 h1:Oi/dETbxPPblvoi4hgkzJun62A4dwuBsTM0UcZYpN3U= -google.golang.org/genproto v0.0.0-20200910191746-8ad3c7ee2cd1/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200911024640-645f7a48b24f h1:Yv4xsIx7HZOoyUGSJ2ksDyWE2qIBXROsZKt2ny3hCGM= +google.golang.org/genproto v0.0.0-20200911024640-645f7a48b24f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= From aa679ae7534bb9d40c0594756e74831ebe2e7da4 Mon Sep 17 00:00:00 2001 From: Matthew Topol Date: Sat, 12 Sep 2020 14:59:39 -0400 Subject: [PATCH 4/8] add apache license to each of the new files --- go/arrow/flight/client.go | 16 ++++++++++++++++ go/arrow/flight/client_auth.go | 16 ++++++++++++++++ go/arrow/flight/gen.go | 16 ++++++++++++++++ go/arrow/flight/server.go | 16 ++++++++++++++++ go/arrow/flight/server_auth.go | 16 ++++++++++++++++ 5 files changed, 80 insertions(+) diff --git a/go/arrow/flight/client.go b/go/arrow/flight/client.go index d9940482434..2367fddb9a9 100644 --- a/go/arrow/flight/client.go +++ b/go/arrow/flight/client.go @@ -1,3 +1,19 @@ +// 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 flight import ( diff --git a/go/arrow/flight/client_auth.go b/go/arrow/flight/client_auth.go index 8889db77c32..d66c260e42c 100644 --- a/go/arrow/flight/client_auth.go +++ b/go/arrow/flight/client_auth.go @@ -1,3 +1,19 @@ +// 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 flight import ( diff --git a/go/arrow/flight/gen.go b/go/arrow/flight/gen.go index d04844eeedf..8a4b8744098 100644 --- a/go/arrow/flight/gen.go +++ b/go/arrow/flight/gen.go @@ -1,3 +1,19 @@ +// 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 flight // import "github.com/apache/arrow/go/arrow/flight" //go:generate protoc -I../../../format --go_out=. --go-grpc_out=. --go_opt=paths=source_relative --go-grpc_opt=paths=source_relative Flight.proto diff --git a/go/arrow/flight/server.go b/go/arrow/flight/server.go index e25fd69dd4f..90492a7b3a3 100644 --- a/go/arrow/flight/server.go +++ b/go/arrow/flight/server.go @@ -1,3 +1,19 @@ +// 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 flight import ( diff --git a/go/arrow/flight/server_auth.go b/go/arrow/flight/server_auth.go index 12594814504..ecde537dc74 100644 --- a/go/arrow/flight/server_auth.go +++ b/go/arrow/flight/server_auth.go @@ -1,3 +1,19 @@ +// 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 flight import ( From dbac2fde94d7ec9d7c1d5ccd531da933bdbe2437 Mon Sep 17 00:00:00 2001 From: Matthew Topol Date: Sat, 12 Sep 2020 15:35:21 -0400 Subject: [PATCH 5/8] more documentation comments --- go/arrow/ipc/flight_data_reader.go | 69 ++++++++++++++++++++++++++++-- go/arrow/ipc/flight_data_writer.go | 9 ++++ 2 files changed, 75 insertions(+), 3 deletions(-) diff --git a/go/arrow/ipc/flight_data_reader.go b/go/arrow/ipc/flight_data_reader.go index fb52416d1c7..7684f4e3d13 100644 --- a/go/arrow/ipc/flight_data_reader.go +++ b/go/arrow/ipc/flight_data_reader.go @@ -19,25 +19,31 @@ package ipc import ( "bytes" "io" + "sync/atomic" "github.com/apache/arrow/go/arrow" "github.com/apache/arrow/go/arrow/array" + "github.com/apache/arrow/go/arrow/arrio" "github.com/apache/arrow/go/arrow/flight" + "github.com/apache/arrow/go/arrow/internal/debug" "github.com/apache/arrow/go/arrow/internal/flatbuf" "github.com/apache/arrow/go/arrow/memory" "golang.org/x/xerrors" ) +// FlightDataStreamReader wraps a grpc stream for receiving FlightData objects type FlightDataStreamReader interface { Recv() (*flight.FlightData, error) } +// FlightDataReader reads records from a stream of messages type FlightDataReader struct { r FlightDataStreamReader schema *arrow.Schema - rec array.Record - err error + refCount int64 + rec array.Record + err error types dictTypeMap memo dictMemo @@ -47,6 +53,10 @@ type FlightDataReader struct { done bool } +// NewFlightDataReader returns a reader that will produce records from a flight data stream +// +// implementation is generally based on the ipc.Reader, expecting the first message to be the +// schema with the subsequent messages being the record batches. func NewFlightDataReader(r FlightDataStreamReader, opts ...Option) (*FlightDataReader, error) { cfg := newConfig(opts...) @@ -64,6 +74,7 @@ func NewFlightDataReader(r FlightDataStreamReader, opts ...Option) (*FlightDataR return nil, xerrors.Errorf("arrow/ipc: invalid message type (got=%v, want=%v)", msg.Type(), MessageSchema) } + // FIXME(sbinet) refactor msg-header handling (a la ipc.Reader.readSchema) var schemaFB flatbuf.Schema initFB(&schemaFB, msg.msg.Header) @@ -72,6 +83,7 @@ func NewFlightDataReader(r FlightDataStreamReader, opts ...Option) (*FlightDataR return nil, xerrors.Errorf("arrow/ipc: could not read dictionary types from message schema: %w", err) } + // TODO(sbinet): see ipc.Reader.readSchema for range rr.types { panic("not implemented") // ReadNextDictionary } @@ -117,10 +129,29 @@ func (f *FlightDataReader) next() bool { return true } +// Record returns the current record that has been extracted from the stream. +// It is valid until the next call to Next or Read func (f *FlightDataReader) Record() array.Record { return f.rec } +// Next returns whether a record was able to be extracted from the stream or not. +func (f *FlightDataReader) Next() bool { + if f.rec != nil { + f.rec.Release() + f.rec = nil + } + + if f.err != nil || f.done { + return false + } + + return f.next() +} + +// Read reads the current record from the flight stream and an error, if any. +// When we reach the end of the flight stream it will return (nil, io.EOF). +// Also calls release on the previous existing record if any. func (f *FlightDataReader) Read() (array.Record, error) { if f.rec != nil { f.rec.Release() @@ -137,5 +168,37 @@ func (f *FlightDataReader) Read() (array.Record, error) { return f.rec, nil } -func (f *FlightDataReader) Err() error { return f.err } +// Retain increases the refcount by 1. +// Retain can be called by multiple goroutines simultaneously. +func (f *FlightDataReader) Retain() { + atomic.AddInt64(&f.refCount, 1) +} + +// Release decreases the refcount by 1. +// When the refcount is 0 the memory is freed. +// Release may be called simultaneously from multiple goroutines. +func (f *FlightDataReader) Release() { + debug.Assert(atomic.LoadInt64(&f.refCount) > 0, "too many releases") + + if atomic.AddInt64(&f.refCount, -1) == 0 { + if f.rec != nil { + f.rec.Release() + f.rec = nil + } + if f.r != nil { + f.r = nil + } + } +} + +// Err returns the last error encounted during the iteration of the stream. +func (f *FlightDataReader) Err() error { return f.err } + +// Schema returns the schema of the underlying records as described by the +// first message received. func (f *FlightDataReader) Schema() *arrow.Schema { return f.schema } + +var ( + _ array.RecordReader = (*FlightDataReader)(nil) + _ arrio.Reader = (*FlightDataReader)(nil) +) diff --git a/go/arrow/ipc/flight_data_writer.go b/go/arrow/ipc/flight_data_writer.go index a12ba53f282..e6661f9cfa4 100644 --- a/go/arrow/ipc/flight_data_writer.go +++ b/go/arrow/ipc/flight_data_writer.go @@ -21,16 +21,19 @@ import ( "github.com/apache/arrow/go/arrow" "github.com/apache/arrow/go/arrow/array" + "github.com/apache/arrow/go/arrow/arrio" "github.com/apache/arrow/go/arrow/bitutil" "github.com/apache/arrow/go/arrow/flight" "github.com/apache/arrow/go/arrow/memory" "golang.org/x/xerrors" ) +// FlightDataStreamWriter wraps a grpc stream for sending FlightData type FlightDataStreamWriter interface { Send(*flight.FlightData) error } +// FlightDataWriter is a stream writer for writing with Flight RPC type FlightDataWriter struct { w FlightDataStreamWriter fd flight.FlightData @@ -41,6 +44,7 @@ type FlightDataWriter struct { schema *arrow.Schema } +// NewFlightDataWriter returns a writer for writing array Records to a flight data stream. func NewFlightDataWriter(w FlightDataStreamWriter, opts ...Option) *FlightDataWriter { cfg := newConfig(opts...) return &FlightDataWriter{ @@ -73,6 +77,7 @@ func (w *FlightDataWriter) Close() (err error) { return err } +// Write the provided record to the underlying stream func (w *FlightDataWriter) Write(rec array.Record) error { if !w.started { err := w.start() @@ -130,3 +135,7 @@ func (w *FlightDataWriter) writePayload(data *payload) (err error) { w.fd.DataBody = tmp.Bytes() return w.w.Send(&w.fd) } + +var ( + _ arrio.Writer = (*FlightDataWriter)(nil) +) From a559d98b0f0a5c81ddf42d000bdd8c8020045e26 Mon Sep 17 00:00:00 2001 From: Matthew Topol Date: Sat, 12 Sep 2020 23:23:53 -0400 Subject: [PATCH 6/8] example for docs, more tests --- go/arrow/flight/example_flight_server_test.go | 70 +++++++ go/arrow/flight/flight_test.go | 182 ++++++++++++++++-- go/arrow/ipc/flight_data_reader.go | 6 + go/arrow/ipc/flight_data_writer.go | 9 + 4 files changed, 249 insertions(+), 18 deletions(-) create mode 100644 go/arrow/flight/example_flight_server_test.go diff --git a/go/arrow/flight/example_flight_server_test.go b/go/arrow/flight/example_flight_server_test.go new file mode 100644 index 00000000000..fad7f541780 --- /dev/null +++ b/go/arrow/flight/example_flight_server_test.go @@ -0,0 +1,70 @@ +package flight_test + +import ( + "context" + "fmt" + "io" + "log" + + "github.com/apache/arrow/go/arrow/flight" + "google.golang.org/grpc" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" +) + +type serverAuth struct{} + +func (sa *serverAuth) Authenticate(c flight.AuthConn) error { + in, err := c.Read() + if err == io.EOF { + return status.Error(codes.Unauthenticated, "no auth info provided") + } + + if err != nil { + return status.Error(codes.FailedPrecondition, "error reading auth handshake") + } + + // do something with in.... + fmt.Println(string(in)) + + // send auth token back + return c.Send([]byte("foobar")) +} + +func (sa *serverAuth) IsValid(token string) error { + if token == "foobar" { + return nil + } + return status.Error(codes.PermissionDenied, "invalid auth token") +} + +func Example_server() { + server := flight.NewFlightServer(&serverAuth{}) + server.Init("localhost:0") + server.RegisterFlightService(&flight.FlightServiceService{}) + + go server.Serve() + defer server.Shutdown() + + conn, err := grpc.Dial(server.Addr().String(), grpc.WithInsecure()) + if err != nil { + log.Fatal(err) + } + defer conn.Close() + + client := flight.NewFlightServiceClient(conn) + stream, err := client.Handshake(context.Background()) + if err != nil { + log.Fatal(err) + } + + // ignore error handling here for brevity + stream.Send(&flight.HandshakeRequest{Payload: []byte("baz")}) + + resp, _ := stream.Recv() + fmt.Println(string(resp.Payload)) + + // Output: + // baz + // foobar +} diff --git a/go/arrow/flight/flight_test.go b/go/arrow/flight/flight_test.go index ad3512562c6..daf73b960f0 100644 --- a/go/arrow/flight/flight_test.go +++ b/go/arrow/flight/flight_test.go @@ -20,27 +20,72 @@ import ( context "context" "errors" "io" - "log" "testing" + "github.com/apache/arrow/go/arrow/array" "github.com/apache/arrow/go/arrow/flight" "github.com/apache/arrow/go/arrow/internal/arrdata" "github.com/apache/arrow/go/arrow/ipc" + "github.com/apache/arrow/go/arrow/memory" "google.golang.org/grpc" - "google.golang.org/grpc/metadata" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" ) -type flightServer struct{} +type flightServer struct { + mem memory.Allocator +} + +func (f *flightServer) getmem() memory.Allocator { + if f.mem == nil { + f.mem = memory.NewGoAllocator() + } + + return f.mem +} func (f *flightServer) ListFlights(c *flight.Criteria, fs flight.FlightService_ListFlightsServer) error { - ctx := fs.Context() - md, ok := metadata.FromIncomingContext(ctx) - log.Println(md, ok) + expr := string(c.GetExpression()) + for _, name := range arrdata.RecordNames { + if expr != "" && expr != name { + continue + } + + recs := arrdata.Records[name] + totalRows := int64(0) + for _, r := range recs { + totalRows += r.NumRows() + } + + fs.Send(&flight.FlightInfo{ + Schema: ipc.FlightInfoSchemaBytes(recs[0].Schema(), f.getmem()), + FlightDescriptor: &flight.FlightDescriptor{ + Type: flight.FlightDescriptor_PATH, + Path: []string{name}, + }, + TotalRecords: totalRows, + TotalBytes: -1, + }) + } + return nil } -func (f *flightServer) DoGet(_ *flight.Ticket, fs flight.FlightService_DoGetServer) error { - recs := arrdata.Records["primitives"] +func (f *flightServer) GetSchema(_ context.Context, in *flight.FlightDescriptor) (*flight.SchemaResult, error) { + if in == nil { + return nil, status.Error(codes.InvalidArgument, "invalid flight descriptor") + } + + recs, ok := arrdata.Records[in.Path[0]] + if !ok { + return nil, status.Error(codes.NotFound, "flight not found") + } + + return &flight.SchemaResult{Schema: ipc.FlightInfoSchemaBytes(recs[0].Schema(), f.getmem())}, nil +} + +func (f *flightServer) DoGet(tkt *flight.Ticket, fs flight.FlightService_DoGetServer) error { + recs := arrdata.Records[string(tkt.GetTicket())] w := ipc.NewFlightDataWriter(fs, ipc.WithSchema(recs[0].Schema())) for _, r := range recs { @@ -53,7 +98,7 @@ func (f *flightServer) DoGet(_ *flight.Ticket, fs flight.FlightService_DoGetServ type servAuth struct{} func (a *servAuth) Authenticate(c flight.AuthConn) error { - in, err := c.Read() + _, err := c.Read() if err == io.EOF { return nil } @@ -62,7 +107,6 @@ func (a *servAuth) Authenticate(c flight.AuthConn) error { return err } - log.Println(string(in)) return c.Send([]byte("baz")) } @@ -80,8 +124,7 @@ func (a *clientAuth) Authenticate(c flight.AuthConn) error { return err } - in, err := c.Read() - log.Println(in) + _, err := c.Read() return err } @@ -89,6 +132,98 @@ func (a *clientAuth) GetToken() (string, error) { return "baz", nil } +func TestListFlights(t *testing.T) { + s := flight.NewFlightServer(nil) + s.Init("localhost:0") + f := &flightServer{} + s.RegisterFlightService(&flight.FlightServiceService{ + ListFlights: f.ListFlights, + }) + + go s.Serve() + defer s.Shutdown() + + client, err := flight.NewFlightClient(s.Addr().String(), nil, grpc.WithInsecure()) + if err != nil { + t.Error(err) + } + defer client.Close() + + flightStream, err := client.ListFlights(context.Background(), &flight.Criteria{}) + if err != nil { + t.Error(err) + } + + for { + info, err := flightStream.Recv() + if err == io.EOF { + break + } else if err != nil { + t.Error(err) + } + + fname := info.GetFlightDescriptor().GetPath()[0] + recs, ok := arrdata.Records[fname] + if !ok { + t.Fatalf("got unknown flight info: %s", fname) + } + + sc, err := ipc.SchemaFromFlightInfo(info.GetSchema()) + if err != nil { + t.Fatal(err) + } + + if !recs[0].Schema().Equal(sc) { + t.Fatalf("flight info schema transfer failed: \ngot = %#v\nwant = %#v\n", sc, recs[0].Schema()) + } + + var total int64 = 0 + for _, r := range recs { + total += r.NumRows() + } + + if info.TotalRecords != total { + t.Fatalf("got wrong number of total records: got = %d, wanted = %d", info.TotalRecords, total) + } + } +} + +func TestGetSchema(t *testing.T) { + s := flight.NewFlightServer(nil) + s.Init("localhost:0") + f := &flightServer{} + s.RegisterFlightService(&flight.FlightServiceService{ + GetSchema: f.GetSchema, + }) + + go s.Serve() + defer s.Shutdown() + + client, err := flight.NewFlightClient(s.Addr().String(), nil, grpc.WithInsecure()) + if err != nil { + t.Error(err) + } + defer client.Close() + + for name, testrecs := range arrdata.Records { + t.Run("flight get schema: "+name, func(t *testing.T) { + res, err := client.GetSchema(context.Background(), &flight.FlightDescriptor{Path: []string{name}}) + if err != nil { + t.Fatal(err) + } + + schema, err := ipc.SchemaFromFlightInfo(res.GetSchema()) + if err != nil { + t.Fatal(err) + } + + if !testrecs[0].Schema().Equal(schema) { + t.Fatalf("schema not match: \ngot = %#v\nwant = %#v\n", schema, testrecs[0].Schema()) + } + }) + } +} + func TestServer(t *testing.T) { f := &flightServer{} service := &flight.FlightServiceService{ @@ -100,8 +235,6 @@ func TestServer(t *testing.T) { s.Init("localhost:0") s.RegisterFlightService(service) - log.Println(s.Addr()) - go s.Serve() defer s.Shutdown() @@ -116,15 +249,17 @@ func TestServer(t *testing.T) { t.Error(err) } - fistream, err := client.ListFlights(context.Background(), &flight.Criteria{}) + fistream, err := client.ListFlights(context.Background(), &flight.Criteria{Expression: []byte("decimal128")}) if err != nil { t.Error(err) } fi, err := fistream.Recv() - log.Println(fi, err) + if err != nil { + t.Fatal(err) + } - fdata, err := client.DoGet(context.Background(), &flight.Ticket{}) + fdata, err := client.DoGet(context.Background(), &flight.Ticket{Ticket: []byte("decimal128")}) if err != nil { t.Error(err) } @@ -134,6 +269,9 @@ func TestServer(t *testing.T) { t.Error(err) } + expected := arrdata.Records["decimal128"] + idx := 0 + var numRows int64 = 0 for { rec, err := r.Read() if err != nil { @@ -143,6 +281,14 @@ func TestServer(t *testing.T) { t.Error(err) } - log.Println(rec) + numRows += rec.NumRows() + if !array.RecordEqual(expected[idx], rec) { + t.Errorf("flight data stream records don't match: \ngot = %#v\nwant = %#v", rec, expected[idx]) + } + idx++ + } + + if numRows != fi.TotalRecords { + t.Fatalf("got %d, want %d", numRows, fi.TotalRecords) } } diff --git a/go/arrow/ipc/flight_data_reader.go b/go/arrow/ipc/flight_data_reader.go index 7684f4e3d13..462286f7ca6 100644 --- a/go/arrow/ipc/flight_data_reader.go +++ b/go/arrow/ipc/flight_data_reader.go @@ -198,6 +198,12 @@ func (f *FlightDataReader) Err() error { return f.err } // first message received. func (f *FlightDataReader) Schema() *arrow.Schema { return f.schema } +func SchemaFromFlightInfo(b []byte) (*arrow.Schema, error) { + fb := flatbuf.GetRootAsSchema(b, 0) + dict := newMemo() + return schemaFromFB(fb, &dict) +} + var ( _ array.RecordReader = (*FlightDataReader)(nil) _ arrio.Reader = (*FlightDataReader)(nil) diff --git a/go/arrow/ipc/flight_data_writer.go b/go/arrow/ipc/flight_data_writer.go index e6661f9cfa4..7a5bc27bb6e 100644 --- a/go/arrow/ipc/flight_data_writer.go +++ b/go/arrow/ipc/flight_data_writer.go @@ -25,6 +25,7 @@ import ( "github.com/apache/arrow/go/arrow/bitutil" "github.com/apache/arrow/go/arrow/flight" "github.com/apache/arrow/go/arrow/memory" + flatbuffers "github.com/google/flatbuffers/go" "golang.org/x/xerrors" ) @@ -136,6 +137,14 @@ func (w *FlightDataWriter) writePayload(data *payload) (err error) { return w.w.Send(&w.fd) } +func FlightInfoSchemaBytes(schema *arrow.Schema, mem memory.Allocator) []byte { + dict := newMemo() + b := flatbuffers.NewBuilder(1024) + offset := schemaToFB(b, schema, &dict) + b.Finish(offset) + return b.FinishedBytes() +} + var ( _ arrio.Writer = (*FlightDataWriter)(nil) ) From 8e48e761ffa95149a846d6ca9825ee8b4626c66a Mon Sep 17 00:00:00 2001 From: Matthew Topol Date: Thu, 24 Sep 2020 10:43:28 -0400 Subject: [PATCH 7/8] remove extraneous named import --- go/arrow/flight/client.go | 2 +- go/arrow/flight/client_auth.go | 2 +- go/arrow/flight/flight_test.go | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go/arrow/flight/client.go b/go/arrow/flight/client.go index 2367fddb9a9..3b490a5be59 100644 --- a/go/arrow/flight/client.go +++ b/go/arrow/flight/client.go @@ -17,7 +17,7 @@ package flight import ( - context "context" + "context" "google.golang.org/grpc" "google.golang.org/grpc/codes" diff --git a/go/arrow/flight/client_auth.go b/go/arrow/flight/client_auth.go index d66c260e42c..c95606b6bfe 100644 --- a/go/arrow/flight/client_auth.go +++ b/go/arrow/flight/client_auth.go @@ -17,7 +17,7 @@ package flight import ( - context "context" + "context" "strings" "google.golang.org/grpc" diff --git a/go/arrow/flight/flight_test.go b/go/arrow/flight/flight_test.go index daf73b960f0..428ff69685a 100644 --- a/go/arrow/flight/flight_test.go +++ b/go/arrow/flight/flight_test.go @@ -17,7 +17,7 @@ package flight_test import ( - context "context" + "context" "errors" "io" "testing" From 981de9ddf84df7cf49d14d899d71040239b4ee6e Mon Sep 17 00:00:00 2001 From: Matthew Topol Date: Thu, 24 Sep 2020 19:14:50 -0400 Subject: [PATCH 8/8] add interface{} return from IsValid to pass identifying information from server auth --- go/arrow/flight/example_flight_server_test.go | 6 ++-- go/arrow/flight/flight_test.go | 19 +++++++++--- go/arrow/flight/server_auth.go | 29 +++++++++++++++---- 3 files changed, 41 insertions(+), 13 deletions(-) diff --git a/go/arrow/flight/example_flight_server_test.go b/go/arrow/flight/example_flight_server_test.go index fad7f541780..3fc1050fb0d 100644 --- a/go/arrow/flight/example_flight_server_test.go +++ b/go/arrow/flight/example_flight_server_test.go @@ -31,11 +31,11 @@ func (sa *serverAuth) Authenticate(c flight.AuthConn) error { return c.Send([]byte("foobar")) } -func (sa *serverAuth) IsValid(token string) error { +func (sa *serverAuth) IsValid(token string) (interface{}, error) { if token == "foobar" { - return nil + return "foo", nil } - return status.Error(codes.PermissionDenied, "invalid auth token") + return "", status.Error(codes.PermissionDenied, "invalid auth token") } func Example_server() { diff --git a/go/arrow/flight/flight_test.go b/go/arrow/flight/flight_test.go index 428ff69685a..ed57bbc3192 100644 --- a/go/arrow/flight/flight_test.go +++ b/go/arrow/flight/flight_test.go @@ -46,6 +46,13 @@ func (f *flightServer) getmem() memory.Allocator { func (f *flightServer) ListFlights(c *flight.Criteria, fs flight.FlightService_ListFlightsServer) error { expr := string(c.GetExpression()) + + auth := "" + authVal := flight.AuthFromContext(fs.Context()) + if authVal != nil { + auth = authVal.(string) + } + for _, name := range arrdata.RecordNames { if expr != "" && expr != name { continue @@ -61,7 +68,7 @@ func (f *flightServer) ListFlights(c *flight.Criteria, fs flight.FlightService_L Schema: ipc.FlightInfoSchemaBytes(recs[0].Schema(), f.getmem()), FlightDescriptor: &flight.FlightDescriptor{ Type: flight.FlightDescriptor_PATH, - Path: []string{name}, + Path: []string{name, auth}, }, TotalRecords: totalRows, TotalBytes: -1, @@ -110,11 +117,11 @@ func (a *servAuth) Authenticate(c flight.AuthConn) error { return c.Send([]byte("baz")) } -func (a *servAuth) IsValid(token string) error { +func (a *servAuth) IsValid(token string) (interface{}, error) { if token == "baz" { - return nil + return "bar", nil } - return errors.New("novalid") + return "", errors.New("novalid") } type clientAuth struct{} @@ -259,6 +266,10 @@ func TestServer(t *testing.T) { t.Fatal(err) } + if len(fi.FlightDescriptor.GetPath()) != 2 || fi.FlightDescriptor.GetPath()[1] != "bar" { + t.Fatalf("path should have auth info: want %s got %s", "bar", fi.FlightDescriptor.GetPath()[1]) + } + fdata, err := client.DoGet(context.Background(), &flight.Ticket{Ticket: []byte("decimal128")}) if err != nil { t.Error(err) diff --git a/go/arrow/flight/server_auth.go b/go/arrow/flight/server_auth.go index ecde537dc74..99e6f8e3c1e 100644 --- a/go/arrow/flight/server_auth.go +++ b/go/arrow/flight/server_auth.go @@ -57,11 +57,25 @@ func (a *serverAuthConn) Send(b []byte) error { // ServerAuthHandler defines an interface for the server to perform the handshake. // The token is expected to be sent as part of the context metadata in subsequent // requests with a key of "auth-token-bin" which will then call IsValid to validate -// -// TODO: implement returning identifying information with the token type ServerAuthHandler interface { Authenticate(AuthConn) error - IsValid(token string) error + IsValid(token string) (interface{}, error) +} + +type authCtxKey struct{} + +type authWrappedStream struct { + grpc.ServerStream + ctx context.Context +} + +func (a *authWrappedStream) Context() context.Context { return a.ctx } + +// AuthFromContext will return back whatever object was returned from `IsValid` for a +// given request context allowing handlers to retrieve identifying information +// for the current request for use. +func AuthFromContext(ctx context.Context) interface{} { + return ctx.Value(authCtxKey{}) } func createServerAuthUnaryInterceptor(auth ServerAuthHandler) grpc.UnaryServerInterceptor { @@ -81,11 +95,12 @@ func createServerAuthUnaryInterceptor(auth ServerAuthHandler) grpc.UnaryServerIn } } - if err := auth.IsValid(authTok); err != nil { + peerIdentity, err := auth.IsValid(authTok) + if err != nil { return nil, status.Errorf(codes.PermissionDenied, "auth-error: %s", err) } - return handler(ctx, req) + return handler(context.WithValue(ctx, authCtxKey{}, peerIdentity), req) } } @@ -110,10 +125,12 @@ func createServerAuthStreamInterceptor(auth ServerAuthHandler) grpc.StreamServer } } - if err := auth.IsValid(authTok); err != nil { + peerIdentity, err := auth.IsValid(authTok) + if err != nil { return status.Errorf(codes.Unauthenticated, "auth-error: %s", err) } + stream = &authWrappedStream{ServerStream: stream, ctx: context.WithValue(stream.Context(), authCtxKey{}, peerIdentity)} return handler(srv, stream) } }