From 62b7d04d0176cc4fbfad97e55dc0a9bb1f0c070b Mon Sep 17 00:00:00 2001 From: Tonis Tiigi Date: Tue, 13 Jun 2017 14:42:51 -0700 Subject: [PATCH 1/5] control: base of status reporting Signed-off-by: Tonis Tiigi --- api/services/control/control.pb.go | 1708 +++++++++++++++++++++++++++- api/services/control/control.proto | 36 +- client/graph.go | 49 + control/control.go | 6 +- control/control_standalone.go | 2 +- solver/load.go | 82 +- solver/run.go | 102 ++ util/progress/multireader.go | 67 ++ util/progress/progress.go | 56 +- util/progress/progress_test.go | 14 +- 10 files changed, 2042 insertions(+), 80 deletions(-) create mode 100644 client/graph.go create mode 100644 solver/run.go create mode 100644 util/progress/multireader.go diff --git a/api/services/control/control.pb.go b/api/services/control/control.pb.go index c73fdc3c..13724498 100644 --- a/api/services/control/control.pb.go +++ b/api/services/control/control.pb.go @@ -14,7 +14,11 @@ UsageRecord SolveRequest SolveResponse + StatusRequest + StatusResponse + Vertex VertexStatus + VertexLog */ package control @@ -130,26 +134,214 @@ func (m *SolveRequest) GetDefinition() [][]byte { } type SolveResponse struct { - Vertex []*VertexStatus `protobuf:"bytes,1,rep,name=vertex" json:"vertex,omitempty"` + Vtx []*Vertex `protobuf:"bytes,1,rep,name=vtx" json:"vtx,omitempty"` } func (m *SolveResponse) Reset() { *m = SolveResponse{} } func (*SolveResponse) ProtoMessage() {} func (*SolveResponse) Descriptor() ([]byte, []int) { return fileDescriptorControl, []int{4} } -func (m *SolveResponse) GetVertex() []*VertexStatus { +func (m *SolveResponse) GetVtx() []*Vertex { if m != nil { - return m.Vertex + return m.Vtx } return nil } +type StatusRequest struct { + Ref string `protobuf:"bytes,1,opt,name=Ref,proto3" json:"Ref,omitempty"` +} + +func (m *StatusRequest) Reset() { *m = StatusRequest{} } +func (*StatusRequest) ProtoMessage() {} +func (*StatusRequest) Descriptor() ([]byte, []int) { return fileDescriptorControl, []int{5} } + +func (m *StatusRequest) GetRef() string { + if m != nil { + return m.Ref + } + return "" +} + +type StatusResponse struct { + Vtx []*Vertex `protobuf:"bytes,1,rep,name=vtx" json:"vtx,omitempty"` + Status []*VertexStatus `protobuf:"bytes,2,rep,name=status" json:"status,omitempty"` + Log []*VertexLog `protobuf:"bytes,3,rep,name=log" json:"log,omitempty"` +} + +func (m *StatusResponse) Reset() { *m = StatusResponse{} } +func (*StatusResponse) ProtoMessage() {} +func (*StatusResponse) Descriptor() ([]byte, []int) { return fileDescriptorControl, []int{6} } + +func (m *StatusResponse) GetVtx() []*Vertex { + if m != nil { + return m.Vtx + } + return nil +} + +func (m *StatusResponse) GetStatus() []*VertexStatus { + if m != nil { + return m.Status + } + return nil +} + +func (m *StatusResponse) GetLog() []*VertexLog { + if m != nil { + return m.Log + } + return nil +} + +type Vertex struct { + ID string `protobuf:"bytes,1,opt,name=ID,proto3" json:"ID,omitempty"` + Inputs []string `protobuf:"bytes,2,rep,name=inputs" json:"inputs,omitempty"` + Name string `protobuf:"bytes,3,opt,name=name,proto3" json:"name,omitempty"` + Status []*VertexStatus `protobuf:"bytes,4,rep,name=status" json:"status,omitempty"` + Cached bool `protobuf:"varint,5,opt,name=cached,proto3" json:"cached,omitempty"` + Started int64 `protobuf:"varint,6,opt,name=started,proto3" json:"started,omitempty"` + Completed int64 `protobuf:"varint,7,opt,name=completed,proto3" json:"completed,omitempty"` +} + +func (m *Vertex) Reset() { *m = Vertex{} } +func (*Vertex) ProtoMessage() {} +func (*Vertex) Descriptor() ([]byte, []int) { return fileDescriptorControl, []int{7} } + +func (m *Vertex) GetID() string { + if m != nil { + return m.ID + } + return "" +} + +func (m *Vertex) GetInputs() []string { + if m != nil { + return m.Inputs + } + return nil +} + +func (m *Vertex) GetName() string { + if m != nil { + return m.Name + } + return "" +} + +func (m *Vertex) GetStatus() []*VertexStatus { + if m != nil { + return m.Status + } + return nil +} + +func (m *Vertex) GetCached() bool { + if m != nil { + return m.Cached + } + return false +} + +func (m *Vertex) GetStarted() int64 { + if m != nil { + return m.Started + } + return 0 +} + +func (m *Vertex) GetCompleted() int64 { + if m != nil { + return m.Completed + } + return 0 +} + type VertexStatus struct { + ID string `protobuf:"bytes,1,opt,name=ID,proto3" json:"ID,omitempty"` + Vertex string `protobuf:"bytes,2,opt,name=vertex,proto3" json:"vertex,omitempty"` + Name string `protobuf:"bytes,3,opt,name=name,proto3" json:"name,omitempty"` + Current int64 `protobuf:"varint,4,opt,name=current,proto3" json:"current,omitempty"` + Total int64 `protobuf:"varint,5,opt,name=total,proto3" json:"total,omitempty"` } func (m *VertexStatus) Reset() { *m = VertexStatus{} } func (*VertexStatus) ProtoMessage() {} -func (*VertexStatus) Descriptor() ([]byte, []int) { return fileDescriptorControl, []int{5} } +func (*VertexStatus) Descriptor() ([]byte, []int) { return fileDescriptorControl, []int{8} } + +func (m *VertexStatus) GetID() string { + if m != nil { + return m.ID + } + return "" +} + +func (m *VertexStatus) GetVertex() string { + if m != nil { + return m.Vertex + } + return "" +} + +func (m *VertexStatus) GetName() string { + if m != nil { + return m.Name + } + return "" +} + +func (m *VertexStatus) GetCurrent() int64 { + if m != nil { + return m.Current + } + return 0 +} + +func (m *VertexStatus) GetTotal() int64 { + if m != nil { + return m.Total + } + return 0 +} + +type VertexLog struct { + Inc int64 `protobuf:"varint,1,opt,name=inc,proto3" json:"inc,omitempty"` + Timestamp int64 `protobuf:"varint,2,opt,name=timestamp,proto3" json:"timestamp,omitempty"` + Stream int64 `protobuf:"varint,3,opt,name=stream,proto3" json:"stream,omitempty"` + Msg []byte `protobuf:"bytes,4,opt,name=msg,proto3" json:"msg,omitempty"` +} + +func (m *VertexLog) Reset() { *m = VertexLog{} } +func (*VertexLog) ProtoMessage() {} +func (*VertexLog) Descriptor() ([]byte, []int) { return fileDescriptorControl, []int{9} } + +func (m *VertexLog) GetInc() int64 { + if m != nil { + return m.Inc + } + return 0 +} + +func (m *VertexLog) GetTimestamp() int64 { + if m != nil { + return m.Timestamp + } + return 0 +} + +func (m *VertexLog) GetStream() int64 { + if m != nil { + return m.Stream + } + return 0 +} + +func (m *VertexLog) GetMsg() []byte { + if m != nil { + return m.Msg + } + return nil +} func init() { proto.RegisterType((*DiskUsageRequest)(nil), "control.DiskUsageRequest") @@ -157,7 +349,11 @@ func init() { proto.RegisterType((*UsageRecord)(nil), "control.UsageRecord") proto.RegisterType((*SolveRequest)(nil), "control.SolveRequest") proto.RegisterType((*SolveResponse)(nil), "control.SolveResponse") + proto.RegisterType((*StatusRequest)(nil), "control.StatusRequest") + proto.RegisterType((*StatusResponse)(nil), "control.StatusResponse") + proto.RegisterType((*Vertex)(nil), "control.Vertex") proto.RegisterType((*VertexStatus)(nil), "control.VertexStatus") + proto.RegisterType((*VertexLog)(nil), "control.VertexLog") } func (this *DiskUsageRequest) Equal(that interface{}) bool { if that == nil { @@ -323,16 +519,155 @@ func (this *SolveResponse) Equal(that interface{}) bool { } else if this == nil { return false } - if len(this.Vertex) != len(that1.Vertex) { + if len(this.Vtx) != len(that1.Vtx) { return false } - for i := range this.Vertex { - if !this.Vertex[i].Equal(that1.Vertex[i]) { + for i := range this.Vtx { + if !this.Vtx[i].Equal(that1.Vtx[i]) { return false } } return true } +func (this *StatusRequest) Equal(that interface{}) bool { + if that == nil { + if this == nil { + return true + } + return false + } + + that1, ok := that.(*StatusRequest) + if !ok { + that2, ok := that.(StatusRequest) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + if this == nil { + return true + } + return false + } else if this == nil { + return false + } + if this.Ref != that1.Ref { + return false + } + return true +} +func (this *StatusResponse) Equal(that interface{}) bool { + if that == nil { + if this == nil { + return true + } + return false + } + + that1, ok := that.(*StatusResponse) + if !ok { + that2, ok := that.(StatusResponse) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + if this == nil { + return true + } + return false + } else if this == nil { + return false + } + if len(this.Vtx) != len(that1.Vtx) { + return false + } + for i := range this.Vtx { + if !this.Vtx[i].Equal(that1.Vtx[i]) { + return false + } + } + if len(this.Status) != len(that1.Status) { + return false + } + for i := range this.Status { + if !this.Status[i].Equal(that1.Status[i]) { + return false + } + } + if len(this.Log) != len(that1.Log) { + return false + } + for i := range this.Log { + if !this.Log[i].Equal(that1.Log[i]) { + return false + } + } + return true +} +func (this *Vertex) Equal(that interface{}) bool { + if that == nil { + if this == nil { + return true + } + return false + } + + that1, ok := that.(*Vertex) + if !ok { + that2, ok := that.(Vertex) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + if this == nil { + return true + } + return false + } else if this == nil { + return false + } + if this.ID != that1.ID { + return false + } + if len(this.Inputs) != len(that1.Inputs) { + return false + } + for i := range this.Inputs { + if this.Inputs[i] != that1.Inputs[i] { + return false + } + } + if this.Name != that1.Name { + return false + } + if len(this.Status) != len(that1.Status) { + return false + } + for i := range this.Status { + if !this.Status[i].Equal(that1.Status[i]) { + return false + } + } + if this.Cached != that1.Cached { + return false + } + if this.Started != that1.Started { + return false + } + if this.Completed != that1.Completed { + return false + } + return true +} func (this *VertexStatus) Equal(that interface{}) bool { if that == nil { if this == nil { @@ -358,6 +693,60 @@ func (this *VertexStatus) Equal(that interface{}) bool { } else if this == nil { return false } + if this.ID != that1.ID { + return false + } + if this.Vertex != that1.Vertex { + return false + } + if this.Name != that1.Name { + return false + } + if this.Current != that1.Current { + return false + } + if this.Total != that1.Total { + return false + } + return true +} +func (this *VertexLog) Equal(that interface{}) bool { + if that == nil { + if this == nil { + return true + } + return false + } + + that1, ok := that.(*VertexLog) + if !ok { + that2, ok := that.(VertexLog) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + if this == nil { + return true + } + return false + } else if this == nil { + return false + } + if this.Inc != that1.Inc { + return false + } + if this.Timestamp != that1.Timestamp { + return false + } + if this.Stream != that1.Stream { + return false + } + if !bytes.Equal(this.Msg, that1.Msg) { + return false + } return true } func (this *DiskUsageRequest) GoString() string { @@ -411,18 +800,82 @@ func (this *SolveResponse) GoString() string { } s := make([]string, 0, 5) s = append(s, "&control.SolveResponse{") - if this.Vertex != nil { - s = append(s, "Vertex: "+fmt.Sprintf("%#v", this.Vertex)+",\n") + if this.Vtx != nil { + s = append(s, "Vtx: "+fmt.Sprintf("%#v", this.Vtx)+",\n") } s = append(s, "}") return strings.Join(s, "") } +func (this *StatusRequest) GoString() string { + if this == nil { + return "nil" + } + s := make([]string, 0, 5) + s = append(s, "&control.StatusRequest{") + s = append(s, "Ref: "+fmt.Sprintf("%#v", this.Ref)+",\n") + s = append(s, "}") + return strings.Join(s, "") +} +func (this *StatusResponse) GoString() string { + if this == nil { + return "nil" + } + s := make([]string, 0, 7) + s = append(s, "&control.StatusResponse{") + if this.Vtx != nil { + s = append(s, "Vtx: "+fmt.Sprintf("%#v", this.Vtx)+",\n") + } + if this.Status != nil { + s = append(s, "Status: "+fmt.Sprintf("%#v", this.Status)+",\n") + } + if this.Log != nil { + s = append(s, "Log: "+fmt.Sprintf("%#v", this.Log)+",\n") + } + s = append(s, "}") + return strings.Join(s, "") +} +func (this *Vertex) GoString() string { + if this == nil { + return "nil" + } + s := make([]string, 0, 11) + s = append(s, "&control.Vertex{") + s = append(s, "ID: "+fmt.Sprintf("%#v", this.ID)+",\n") + s = append(s, "Inputs: "+fmt.Sprintf("%#v", this.Inputs)+",\n") + s = append(s, "Name: "+fmt.Sprintf("%#v", this.Name)+",\n") + if this.Status != nil { + s = append(s, "Status: "+fmt.Sprintf("%#v", this.Status)+",\n") + } + s = append(s, "Cached: "+fmt.Sprintf("%#v", this.Cached)+",\n") + s = append(s, "Started: "+fmt.Sprintf("%#v", this.Started)+",\n") + s = append(s, "Completed: "+fmt.Sprintf("%#v", this.Completed)+",\n") + s = append(s, "}") + return strings.Join(s, "") +} func (this *VertexStatus) GoString() string { if this == nil { return "nil" } - s := make([]string, 0, 4) + s := make([]string, 0, 9) s = append(s, "&control.VertexStatus{") + s = append(s, "ID: "+fmt.Sprintf("%#v", this.ID)+",\n") + s = append(s, "Vertex: "+fmt.Sprintf("%#v", this.Vertex)+",\n") + s = append(s, "Name: "+fmt.Sprintf("%#v", this.Name)+",\n") + s = append(s, "Current: "+fmt.Sprintf("%#v", this.Current)+",\n") + s = append(s, "Total: "+fmt.Sprintf("%#v", this.Total)+",\n") + s = append(s, "}") + return strings.Join(s, "") +} +func (this *VertexLog) GoString() string { + if this == nil { + return "nil" + } + s := make([]string, 0, 8) + s = append(s, "&control.VertexLog{") + s = append(s, "Inc: "+fmt.Sprintf("%#v", this.Inc)+",\n") + s = append(s, "Timestamp: "+fmt.Sprintf("%#v", this.Timestamp)+",\n") + s = append(s, "Stream: "+fmt.Sprintf("%#v", this.Stream)+",\n") + s = append(s, "Msg: "+fmt.Sprintf("%#v", this.Msg)+",\n") s = append(s, "}") return strings.Join(s, "") } @@ -448,6 +901,7 @@ const _ = grpc.SupportPackageIsVersion4 type ControlClient interface { DiskUsage(ctx context.Context, in *DiskUsageRequest, opts ...grpc.CallOption) (*DiskUsageResponse, error) Solve(ctx context.Context, in *SolveRequest, opts ...grpc.CallOption) (*SolveResponse, error) + Status(ctx context.Context, in *StatusRequest, opts ...grpc.CallOption) (Control_StatusClient, error) } type controlClient struct { @@ -476,11 +930,44 @@ func (c *controlClient) Solve(ctx context.Context, in *SolveRequest, opts ...grp return out, nil } +func (c *controlClient) Status(ctx context.Context, in *StatusRequest, opts ...grpc.CallOption) (Control_StatusClient, error) { + stream, err := grpc.NewClientStream(ctx, &_Control_serviceDesc.Streams[0], c.cc, "/control.Control/Status", opts...) + if err != nil { + return nil, err + } + x := &controlStatusClient{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 Control_StatusClient interface { + Recv() (*StatusResponse, error) + grpc.ClientStream +} + +type controlStatusClient struct { + grpc.ClientStream +} + +func (x *controlStatusClient) Recv() (*StatusResponse, error) { + m := new(StatusResponse) + if err := x.ClientStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + // Server API for Control service type ControlServer interface { DiskUsage(context.Context, *DiskUsageRequest) (*DiskUsageResponse, error) Solve(context.Context, *SolveRequest) (*SolveResponse, error) + Status(*StatusRequest, Control_StatusServer) error } func RegisterControlServer(s *grpc.Server, srv ControlServer) { @@ -523,6 +1010,27 @@ func _Control_Solve_Handler(srv interface{}, ctx context.Context, dec func(inter return interceptor(ctx, in, info, handler) } +func _Control_Status_Handler(srv interface{}, stream grpc.ServerStream) error { + m := new(StatusRequest) + if err := stream.RecvMsg(m); err != nil { + return err + } + return srv.(ControlServer).Status(m, &controlStatusServer{stream}) +} + +type Control_StatusServer interface { + Send(*StatusResponse) error + grpc.ServerStream +} + +type controlStatusServer struct { + grpc.ServerStream +} + +func (x *controlStatusServer) Send(m *StatusResponse) error { + return x.ServerStream.SendMsg(m) +} + var _Control_serviceDesc = grpc.ServiceDesc{ ServiceName: "control.Control", HandlerType: (*ControlServer)(nil), @@ -536,7 +1044,13 @@ var _Control_serviceDesc = grpc.ServiceDesc{ Handler: _Control_Solve_Handler, }, }, - Streams: []grpc.StreamDesc{}, + Streams: []grpc.StreamDesc{ + { + StreamName: "Status", + Handler: _Control_Status_Handler, + ServerStreams: true, + }, + }, Metadata: "control.proto", } @@ -684,8 +1198,8 @@ func (m *SolveResponse) MarshalTo(dAtA []byte) (int, error) { _ = i var l int _ = l - if len(m.Vertex) > 0 { - for _, msg := range m.Vertex { + if len(m.Vtx) > 0 { + for _, msg := range m.Vtx { dAtA[i] = 0xa i++ i = encodeVarintControl(dAtA, i, uint64(msg.Size())) @@ -699,6 +1213,161 @@ func (m *SolveResponse) MarshalTo(dAtA []byte) (int, error) { return i, nil } +func (m *StatusRequest) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalTo(dAtA) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *StatusRequest) MarshalTo(dAtA []byte) (int, error) { + var i int + _ = i + var l int + _ = l + if len(m.Ref) > 0 { + dAtA[i] = 0xa + i++ + i = encodeVarintControl(dAtA, i, uint64(len(m.Ref))) + i += copy(dAtA[i:], m.Ref) + } + return i, nil +} + +func (m *StatusResponse) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalTo(dAtA) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *StatusResponse) MarshalTo(dAtA []byte) (int, error) { + var i int + _ = i + var l int + _ = l + if len(m.Vtx) > 0 { + for _, msg := range m.Vtx { + dAtA[i] = 0xa + i++ + i = encodeVarintControl(dAtA, i, uint64(msg.Size())) + n, err := msg.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n + } + } + if len(m.Status) > 0 { + for _, msg := range m.Status { + dAtA[i] = 0x12 + i++ + i = encodeVarintControl(dAtA, i, uint64(msg.Size())) + n, err := msg.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n + } + } + if len(m.Log) > 0 { + for _, msg := range m.Log { + dAtA[i] = 0x1a + i++ + i = encodeVarintControl(dAtA, i, uint64(msg.Size())) + n, err := msg.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n + } + } + return i, nil +} + +func (m *Vertex) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalTo(dAtA) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *Vertex) MarshalTo(dAtA []byte) (int, error) { + var i int + _ = i + var l int + _ = l + if len(m.ID) > 0 { + dAtA[i] = 0xa + i++ + i = encodeVarintControl(dAtA, i, uint64(len(m.ID))) + i += copy(dAtA[i:], m.ID) + } + if len(m.Inputs) > 0 { + for _, s := range m.Inputs { + dAtA[i] = 0x12 + i++ + l = len(s) + for l >= 1<<7 { + dAtA[i] = uint8(uint64(l)&0x7f | 0x80) + l >>= 7 + i++ + } + dAtA[i] = uint8(l) + i++ + i += copy(dAtA[i:], s) + } + } + if len(m.Name) > 0 { + dAtA[i] = 0x1a + i++ + i = encodeVarintControl(dAtA, i, uint64(len(m.Name))) + i += copy(dAtA[i:], m.Name) + } + if len(m.Status) > 0 { + for _, msg := range m.Status { + dAtA[i] = 0x22 + i++ + i = encodeVarintControl(dAtA, i, uint64(msg.Size())) + n, err := msg.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n + } + } + if m.Cached { + dAtA[i] = 0x28 + i++ + if m.Cached { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i++ + } + if m.Started != 0 { + dAtA[i] = 0x30 + i++ + i = encodeVarintControl(dAtA, i, uint64(m.Started)) + } + if m.Completed != 0 { + dAtA[i] = 0x38 + i++ + i = encodeVarintControl(dAtA, i, uint64(m.Completed)) + } + return i, nil +} + func (m *VertexStatus) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) @@ -714,6 +1383,73 @@ func (m *VertexStatus) MarshalTo(dAtA []byte) (int, error) { _ = i var l int _ = l + if len(m.ID) > 0 { + dAtA[i] = 0xa + i++ + i = encodeVarintControl(dAtA, i, uint64(len(m.ID))) + i += copy(dAtA[i:], m.ID) + } + if len(m.Vertex) > 0 { + dAtA[i] = 0x12 + i++ + i = encodeVarintControl(dAtA, i, uint64(len(m.Vertex))) + i += copy(dAtA[i:], m.Vertex) + } + if len(m.Name) > 0 { + dAtA[i] = 0x1a + i++ + i = encodeVarintControl(dAtA, i, uint64(len(m.Name))) + i += copy(dAtA[i:], m.Name) + } + if m.Current != 0 { + dAtA[i] = 0x20 + i++ + i = encodeVarintControl(dAtA, i, uint64(m.Current)) + } + if m.Total != 0 { + dAtA[i] = 0x28 + i++ + i = encodeVarintControl(dAtA, i, uint64(m.Total)) + } + return i, nil +} + +func (m *VertexLog) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalTo(dAtA) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *VertexLog) MarshalTo(dAtA []byte) (int, error) { + var i int + _ = i + var l int + _ = l + if m.Inc != 0 { + dAtA[i] = 0x8 + i++ + i = encodeVarintControl(dAtA, i, uint64(m.Inc)) + } + if m.Timestamp != 0 { + dAtA[i] = 0x10 + i++ + i = encodeVarintControl(dAtA, i, uint64(m.Timestamp)) + } + if m.Stream != 0 { + dAtA[i] = 0x18 + i++ + i = encodeVarintControl(dAtA, i, uint64(m.Stream)) + } + if len(m.Msg) > 0 { + dAtA[i] = 0x22 + i++ + i = encodeVarintControl(dAtA, i, uint64(len(m.Msg))) + i += copy(dAtA[i:], m.Msg) + } return i, nil } @@ -800,8 +1536,8 @@ func (m *SolveRequest) Size() (n int) { func (m *SolveResponse) Size() (n int) { var l int _ = l - if len(m.Vertex) > 0 { - for _, e := range m.Vertex { + if len(m.Vtx) > 0 { + for _, e := range m.Vtx { l = e.Size() n += 1 + l + sovControl(uint64(l)) } @@ -809,9 +1545,115 @@ func (m *SolveResponse) Size() (n int) { return n } +func (m *StatusRequest) Size() (n int) { + var l int + _ = l + l = len(m.Ref) + if l > 0 { + n += 1 + l + sovControl(uint64(l)) + } + return n +} + +func (m *StatusResponse) Size() (n int) { + var l int + _ = l + if len(m.Vtx) > 0 { + for _, e := range m.Vtx { + l = e.Size() + n += 1 + l + sovControl(uint64(l)) + } + } + if len(m.Status) > 0 { + for _, e := range m.Status { + l = e.Size() + n += 1 + l + sovControl(uint64(l)) + } + } + if len(m.Log) > 0 { + for _, e := range m.Log { + l = e.Size() + n += 1 + l + sovControl(uint64(l)) + } + } + return n +} + +func (m *Vertex) Size() (n int) { + var l int + _ = l + l = len(m.ID) + if l > 0 { + n += 1 + l + sovControl(uint64(l)) + } + if len(m.Inputs) > 0 { + for _, s := range m.Inputs { + l = len(s) + n += 1 + l + sovControl(uint64(l)) + } + } + l = len(m.Name) + if l > 0 { + n += 1 + l + sovControl(uint64(l)) + } + if len(m.Status) > 0 { + for _, e := range m.Status { + l = e.Size() + n += 1 + l + sovControl(uint64(l)) + } + } + if m.Cached { + n += 2 + } + if m.Started != 0 { + n += 1 + sovControl(uint64(m.Started)) + } + if m.Completed != 0 { + n += 1 + sovControl(uint64(m.Completed)) + } + return n +} + func (m *VertexStatus) Size() (n int) { var l int _ = l + l = len(m.ID) + if l > 0 { + n += 1 + l + sovControl(uint64(l)) + } + l = len(m.Vertex) + if l > 0 { + n += 1 + l + sovControl(uint64(l)) + } + l = len(m.Name) + if l > 0 { + n += 1 + l + sovControl(uint64(l)) + } + if m.Current != 0 { + n += 1 + sovControl(uint64(m.Current)) + } + if m.Total != 0 { + n += 1 + sovControl(uint64(m.Total)) + } + return n +} + +func (m *VertexLog) Size() (n int) { + var l int + _ = l + if m.Inc != 0 { + n += 1 + sovControl(uint64(m.Inc)) + } + if m.Timestamp != 0 { + n += 1 + sovControl(uint64(m.Timestamp)) + } + if m.Stream != 0 { + n += 1 + sovControl(uint64(m.Stream)) + } + l = len(m.Msg) + if l > 0 { + n += 1 + l + sovControl(uint64(l)) + } return n } @@ -876,7 +1718,45 @@ func (this *SolveResponse) String() string { return "nil" } s := strings.Join([]string{`&SolveResponse{`, - `Vertex:` + strings.Replace(fmt.Sprintf("%v", this.Vertex), "VertexStatus", "VertexStatus", 1) + `,`, + `Vtx:` + strings.Replace(fmt.Sprintf("%v", this.Vtx), "Vertex", "Vertex", 1) + `,`, + `}`, + }, "") + return s +} +func (this *StatusRequest) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&StatusRequest{`, + `Ref:` + fmt.Sprintf("%v", this.Ref) + `,`, + `}`, + }, "") + return s +} +func (this *StatusResponse) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&StatusResponse{`, + `Vtx:` + strings.Replace(fmt.Sprintf("%v", this.Vtx), "Vertex", "Vertex", 1) + `,`, + `Status:` + strings.Replace(fmt.Sprintf("%v", this.Status), "VertexStatus", "VertexStatus", 1) + `,`, + `Log:` + strings.Replace(fmt.Sprintf("%v", this.Log), "VertexLog", "VertexLog", 1) + `,`, + `}`, + }, "") + return s +} +func (this *Vertex) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&Vertex{`, + `ID:` + fmt.Sprintf("%v", this.ID) + `,`, + `Inputs:` + fmt.Sprintf("%v", this.Inputs) + `,`, + `Name:` + fmt.Sprintf("%v", this.Name) + `,`, + `Status:` + strings.Replace(fmt.Sprintf("%v", this.Status), "VertexStatus", "VertexStatus", 1) + `,`, + `Cached:` + fmt.Sprintf("%v", this.Cached) + `,`, + `Started:` + fmt.Sprintf("%v", this.Started) + `,`, + `Completed:` + fmt.Sprintf("%v", this.Completed) + `,`, `}`, }, "") return s @@ -886,6 +1766,24 @@ func (this *VertexStatus) String() string { return "nil" } s := strings.Join([]string{`&VertexStatus{`, + `ID:` + fmt.Sprintf("%v", this.ID) + `,`, + `Vertex:` + fmt.Sprintf("%v", this.Vertex) + `,`, + `Name:` + fmt.Sprintf("%v", this.Name) + `,`, + `Current:` + fmt.Sprintf("%v", this.Current) + `,`, + `Total:` + fmt.Sprintf("%v", this.Total) + `,`, + `}`, + }, "") + return s +} +func (this *VertexLog) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&VertexLog{`, + `Inc:` + fmt.Sprintf("%v", this.Inc) + `,`, + `Timestamp:` + fmt.Sprintf("%v", this.Timestamp) + `,`, + `Stream:` + fmt.Sprintf("%v", this.Stream) + `,`, + `Msg:` + fmt.Sprintf("%v", this.Msg) + `,`, `}`, }, "") return s @@ -1306,7 +2204,7 @@ func (m *SolveResponse) Unmarshal(dAtA []byte) error { switch fieldNum { case 1: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Vertex", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field Vtx", wireType) } var msglen int for shift := uint(0); ; shift += 7 { @@ -1330,8 +2228,8 @@ func (m *SolveResponse) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - m.Vertex = append(m.Vertex, &VertexStatus{}) - if err := m.Vertex[len(m.Vertex)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + m.Vtx = append(m.Vtx, &Vertex{}) + if err := m.Vtx[len(m.Vtx)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err } iNdEx = postIndex @@ -1356,6 +2254,454 @@ func (m *SolveResponse) Unmarshal(dAtA []byte) error { } return nil } +func (m *StatusRequest) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowControl + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: StatusRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: StatusRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Ref", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowControl + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthControl + } + postIndex := iNdEx + intStringLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Ref = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipControl(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthControl + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *StatusResponse) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowControl + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: StatusResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: StatusResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Vtx", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowControl + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthControl + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Vtx = append(m.Vtx, &Vertex{}) + if err := m.Vtx[len(m.Vtx)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Status", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowControl + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthControl + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Status = append(m.Status, &VertexStatus{}) + if err := m.Status[len(m.Status)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Log", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowControl + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthControl + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Log = append(m.Log, &VertexLog{}) + if err := m.Log[len(m.Log)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipControl(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthControl + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *Vertex) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowControl + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: Vertex: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: Vertex: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ID", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowControl + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthControl + } + postIndex := iNdEx + intStringLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ID = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Inputs", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowControl + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthControl + } + postIndex := iNdEx + intStringLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Inputs = append(m.Inputs, string(dAtA[iNdEx:postIndex])) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Name", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowControl + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthControl + } + postIndex := iNdEx + intStringLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Name = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Status", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowControl + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthControl + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Status = append(m.Status, &VertexStatus{}) + if err := m.Status[len(m.Status)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 5: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Cached", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowControl + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + m.Cached = bool(v != 0) + case 6: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Started", wireType) + } + m.Started = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowControl + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Started |= (int64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + case 7: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Completed", wireType) + } + m.Completed = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowControl + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Completed |= (int64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipControl(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthControl + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} func (m *VertexStatus) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 @@ -1385,6 +2731,269 @@ func (m *VertexStatus) Unmarshal(dAtA []byte) error { return fmt.Errorf("proto: VertexStatus: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ID", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowControl + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthControl + } + postIndex := iNdEx + intStringLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ID = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Vertex", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowControl + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthControl + } + postIndex := iNdEx + intStringLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Vertex = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Name", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowControl + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthControl + } + postIndex := iNdEx + intStringLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Name = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 4: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Current", wireType) + } + m.Current = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowControl + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Current |= (int64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + case 5: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Total", wireType) + } + m.Total = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowControl + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Total |= (int64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipControl(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthControl + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *VertexLog) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowControl + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: VertexLog: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: VertexLog: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Inc", wireType) + } + m.Inc = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowControl + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Inc |= (int64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Timestamp", wireType) + } + m.Timestamp = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowControl + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Timestamp |= (int64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + case 3: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Stream", wireType) + } + m.Stream = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowControl + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Stream |= (int64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Msg", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowControl + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthControl + } + postIndex := iNdEx + byteLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Msg = append(m.Msg[:0], dAtA[iNdEx:postIndex]...) + if m.Msg == nil { + m.Msg = []byte{} + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipControl(dAtA[iNdEx:]) @@ -1514,27 +3123,42 @@ var ( func init() { proto.RegisterFile("control.proto", fileDescriptorControl) } var fileDescriptorControl = []byte{ - // 349 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x6c, 0x92, 0xbb, 0x4e, 0x02, 0x41, - 0x14, 0x86, 0x77, 0x76, 0xb9, 0xc8, 0xe1, 0x12, 0x9c, 0xa0, 0x19, 0x29, 0x26, 0x9b, 0xad, 0xb6, - 0x40, 0x0a, 0x4c, 0x2c, 0x8d, 0xe2, 0x36, 0x14, 0x36, 0x43, 0xb0, 0x5f, 0x70, 0x30, 0x1b, 0xc9, - 0x0e, 0xee, 0x0c, 0xc4, 0x58, 0xd9, 0xd8, 0xfb, 0x18, 0x3e, 0x8a, 0x25, 0xa5, 0xa5, 0x8c, 0x8d, - 0x25, 0x8f, 0x60, 0x58, 0x06, 0xdc, 0x10, 0xbb, 0x73, 0xbe, 0x73, 0x99, 0xff, 0x3f, 0x19, 0xa8, - 0x8e, 0x44, 0xac, 0x12, 0x31, 0x69, 0x4f, 0x13, 0xa1, 0x04, 0x2e, 0x9a, 0xd4, 0xc3, 0x50, 0x0f, - 0x22, 0xf9, 0x30, 0x90, 0xe1, 0x3d, 0x67, 0xfc, 0x71, 0xc6, 0xa5, 0xf2, 0xae, 0xe0, 0x30, 0xc3, - 0xe4, 0x54, 0xc4, 0x92, 0xe3, 0x16, 0x14, 0x12, 0x3e, 0x12, 0xc9, 0x1d, 0x41, 0xae, 0xe3, 0x97, - 0x3b, 0x8d, 0xf6, 0x76, 0xa3, 0xe9, 0x5b, 0xd7, 0x98, 0xe9, 0xf1, 0x42, 0x28, 0x67, 0x30, 0xae, - 0x81, 0xdd, 0x0b, 0x08, 0x72, 0x91, 0x5f, 0x62, 0x76, 0x2f, 0xc0, 0x04, 0x8a, 0x37, 0x33, 0x15, - 0x0e, 0x27, 0x9c, 0xd8, 0x2e, 0xf2, 0x0f, 0xd8, 0x36, 0xc5, 0x0d, 0xc8, 0xf7, 0xe2, 0x81, 0xe4, - 0xc4, 0x49, 0xf9, 0x26, 0xc1, 0x18, 0x72, 0xfd, 0xe8, 0x99, 0x93, 0x9c, 0x8b, 0x7c, 0x87, 0xa5, - 0xb1, 0x77, 0x09, 0x95, 0xbe, 0x98, 0xcc, 0xb7, 0xaa, 0x71, 0x1d, 0x1c, 0xc6, 0xc7, 0xe6, 0x91, - 0x75, 0x88, 0x29, 0x40, 0xc0, 0xc7, 0x51, 0x1c, 0xa9, 0x48, 0xc4, 0xc4, 0x76, 0x1d, 0xbf, 0xc2, - 0x32, 0xc4, 0xbb, 0x80, 0xaa, 0xd9, 0x60, 0x3c, 0x9e, 0x42, 0x61, 0xce, 0x13, 0xc5, 0x9f, 0x8c, - 0xc7, 0xa3, 0x9d, 0xc7, 0xdb, 0x14, 0xf7, 0x55, 0xa8, 0x66, 0x92, 0x99, 0x26, 0xaf, 0x06, 0x95, - 0x2c, 0xef, 0xbc, 0x22, 0x28, 0x5e, 0x6f, 0x06, 0x70, 0x17, 0x4a, 0xbb, 0x1b, 0xe2, 0x93, 0xdd, - 0x9e, 0xfd, 0x5b, 0x37, 0x9b, 0xff, 0x95, 0x8c, 0x9c, 0x73, 0xc8, 0xa7, 0xfa, 0xf0, 0x9f, 0x8e, - 0xac, 0xe3, 0xe6, 0xf1, 0x3e, 0xde, 0xcc, 0x75, 0x5b, 0x8b, 0x25, 0xb5, 0x3e, 0x97, 0xd4, 0x5a, - 0x2d, 0x29, 0x7a, 0xd1, 0x14, 0xbd, 0x6b, 0x8a, 0x3e, 0x34, 0x45, 0x0b, 0x4d, 0xd1, 0x97, 0xa6, - 0xe8, 0x47, 0x53, 0x6b, 0xa5, 0x29, 0x7a, 0xfb, 0xa6, 0xd6, 0xb0, 0x90, 0xfe, 0x88, 0xb3, 0xdf, - 0x00, 0x00, 0x00, 0xff, 0xff, 0x80, 0xe3, 0xfa, 0x6f, 0x22, 0x02, 0x00, 0x00, + // 577 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x8c, 0x54, 0xbf, 0x6f, 0xd3, 0x4e, + 0x14, 0xcf, 0xe5, 0x1a, 0xe7, 0xeb, 0x97, 0xa4, 0xdf, 0x72, 0x2a, 0xc1, 0x44, 0xe8, 0x94, 0x5a, + 0x0c, 0x19, 0x4a, 0x85, 0x82, 0xc4, 0xc2, 0x02, 0x25, 0x4b, 0x24, 0x58, 0x2e, 0x2a, 0xbb, 0xeb, + 0x5c, 0x83, 0x85, 0xed, 0x0b, 0xbe, 0x4b, 0x54, 0x75, 0x62, 0x64, 0xe4, 0xcf, 0xe0, 0xef, 0x80, + 0x85, 0xb1, 0x23, 0x23, 0x31, 0x0b, 0x63, 0xff, 0x04, 0x74, 0xe7, 0x73, 0x62, 0xa5, 0x41, 0xea, + 0xf6, 0x3e, 0x9f, 0xf7, 0xfc, 0xde, 0xe7, 0xfd, 0x38, 0x43, 0x27, 0x14, 0xa9, 0xca, 0x44, 0x7c, + 0x32, 0xcf, 0x84, 0x12, 0xa4, 0x69, 0xa1, 0x4f, 0xe0, 0x60, 0x14, 0xc9, 0x0f, 0x67, 0x32, 0x98, + 0x71, 0xc6, 0x3f, 0x2e, 0xb8, 0x54, 0xfe, 0x2b, 0xb8, 0x57, 0xe1, 0xe4, 0x5c, 0xa4, 0x92, 0x93, + 0x63, 0x70, 0x32, 0x1e, 0x8a, 0x6c, 0xea, 0xa1, 0x3e, 0x1e, 0xb4, 0x86, 0x87, 0x27, 0x65, 0x46, + 0x1b, 0xa7, 0x7d, 0xcc, 0xc6, 0xf8, 0x01, 0xb4, 0x2a, 0x34, 0xd9, 0x87, 0xfa, 0x78, 0xe4, 0xa1, + 0x3e, 0x1a, 0xb8, 0xac, 0x3e, 0x1e, 0x11, 0x0f, 0x9a, 0x6f, 0x17, 0x2a, 0x38, 0x8f, 0xb9, 0x57, + 0xef, 0xa3, 0xc1, 0x7f, 0xac, 0x84, 0xe4, 0x10, 0x1a, 0xe3, 0xf4, 0x4c, 0x72, 0x0f, 0x1b, 0xbe, + 0x00, 0x84, 0xc0, 0xde, 0x24, 0xba, 0xe2, 0xde, 0x5e, 0x1f, 0x0d, 0x30, 0x33, 0xb6, 0xff, 0x12, + 0xda, 0x13, 0x11, 0x2f, 0x4b, 0xd5, 0xe4, 0x00, 0x30, 0xe3, 0x17, 0xb6, 0x88, 0x36, 0x09, 0x05, + 0x18, 0xf1, 0x8b, 0x28, 0x8d, 0x54, 0x24, 0x52, 0xaf, 0xde, 0xc7, 0x83, 0x36, 0xab, 0x30, 0xfe, + 0x10, 0x3a, 0x36, 0x83, 0xed, 0xf1, 0x08, 0xf0, 0x52, 0x5d, 0xda, 0x06, 0xff, 0x5f, 0x37, 0xf8, + 0x8e, 0x67, 0x8a, 0x5f, 0x32, 0xed, 0xf3, 0x8f, 0xa0, 0x33, 0x51, 0x81, 0x5a, 0xc8, 0x7f, 0x96, + 0xf5, 0x3f, 0x23, 0xd8, 0x2f, 0x63, 0xee, 0x9c, 0x98, 0x3c, 0x01, 0x47, 0x9a, 0x8f, 0x8c, 0xd0, + 0xd6, 0xf0, 0xfe, 0x56, 0x94, 0xcd, 0x68, 0x83, 0xc8, 0x63, 0xc0, 0xb1, 0x98, 0x79, 0xd8, 0xc4, + 0x92, 0xad, 0xd8, 0x37, 0x62, 0xc6, 0xb4, 0xdb, 0xff, 0x8e, 0xc0, 0x29, 0xa8, 0x5b, 0x2b, 0xe8, + 0x82, 0x13, 0xa5, 0xf3, 0x85, 0x2a, 0xea, 0xb9, 0xcc, 0x22, 0x3d, 0xea, 0x34, 0x48, 0x8a, 0xf9, + 0xbb, 0xcc, 0xd8, 0x15, 0x6d, 0x7b, 0x77, 0xd1, 0xd6, 0x05, 0x27, 0x0c, 0xc2, 0xf7, 0x7c, 0xea, + 0x35, 0xcc, 0x12, 0x2d, 0xd2, 0x5b, 0x97, 0x2a, 0xc8, 0x14, 0x9f, 0x7a, 0x8e, 0x59, 0x64, 0x09, + 0xc9, 0x23, 0x70, 0x43, 0x91, 0xcc, 0x63, 0xae, 0x7d, 0x4d, 0xe3, 0xdb, 0x10, 0xfe, 0x15, 0xb4, + 0xab, 0x75, 0x76, 0xb5, 0xb2, 0x34, 0x7e, 0x73, 0x4c, 0x2e, 0xb3, 0x68, 0x67, 0x2b, 0x1e, 0x34, + 0xc3, 0x45, 0x96, 0xf1, 0x54, 0xd9, 0x63, 0x2a, 0xa1, 0xbe, 0x3c, 0x25, 0x54, 0x10, 0x1b, 0xd1, + 0x98, 0x15, 0xc0, 0xe7, 0xe0, 0xae, 0x67, 0xaa, 0x77, 0x1d, 0xa5, 0xa1, 0xa9, 0x8c, 0x99, 0x36, + 0xb5, 0x70, 0x15, 0x25, 0x5c, 0xaa, 0x20, 0x99, 0x9b, 0xea, 0x98, 0x6d, 0x08, 0x2d, 0x4c, 0xaa, + 0x8c, 0x07, 0x89, 0x91, 0x80, 0x99, 0x45, 0x3a, 0x4f, 0x22, 0x67, 0x46, 0x40, 0x9b, 0x69, 0x73, + 0xf8, 0x0d, 0x41, 0xf3, 0x75, 0x31, 0x53, 0x72, 0x0a, 0xee, 0xfa, 0xf9, 0x91, 0x87, 0xeb, 0x51, + 0x6f, 0x3f, 0xd3, 0x5e, 0x6f, 0x97, 0xcb, 0x1e, 0xdc, 0x73, 0x68, 0x98, 0xd3, 0x26, 0x9b, 0x55, + 0x55, 0x1f, 0x4b, 0xaf, 0xbb, 0x4d, 0xdb, 0xef, 0x5e, 0x80, 0x63, 0x87, 0x5c, 0x89, 0xa8, 0xde, + 0x7b, 0xef, 0xc1, 0x2d, 0xbe, 0xf8, 0xf4, 0x29, 0x3a, 0x3d, 0xbe, 0x5e, 0xd1, 0xda, 0xcf, 0x15, + 0xad, 0xdd, 0xac, 0x28, 0xfa, 0x94, 0x53, 0xf4, 0x35, 0xa7, 0xe8, 0x47, 0x4e, 0xd1, 0x75, 0x4e, + 0xd1, 0xaf, 0x9c, 0xa2, 0x3f, 0x39, 0xad, 0xdd, 0xe4, 0x14, 0x7d, 0xf9, 0x4d, 0x6b, 0xe7, 0x8e, + 0xf9, 0x13, 0x3d, 0xfb, 0x1b, 0x00, 0x00, 0xff, 0xff, 0xc4, 0xe0, 0x91, 0xb1, 0x9a, 0x04, 0x00, + 0x00, } diff --git a/api/services/control/control.proto b/api/services/control/control.proto index 57c47818..ffd8de8d 100644 --- a/api/services/control/control.proto +++ b/api/services/control/control.proto @@ -5,7 +5,7 @@ package control; service Control { rpc DiskUsage(DiskUsageRequest) returns (DiskUsageResponse); rpc Solve(SolveRequest) returns (SolveResponse); - // rpc Status() returns (); + rpc Status(StatusRequest) returns (stream StatusResponse); } message DiskUsageRequest { @@ -28,8 +28,40 @@ message SolveRequest { } message SolveResponse { - repeated VertexStatus vertex = 1; + repeated Vertex vtx = 1; +} + +message StatusRequest { + string Ref = 1; +} + +message StatusResponse { + repeated Vertex vtx = 1; + repeated VertexStatus status = 2; + repeated VertexLog log = 3; +} + +message Vertex { + string ID = 1; + repeated string inputs = 2; + string name = 3; + repeated VertexStatus status = 4; + bool cached = 5; + int64 started = 6; // relative, add abolute google.protobuf.Timestamp as well? + int64 completed = 7; } message VertexStatus { + string ID = 1; + string vertex = 2; + string name = 3; + int64 current = 4; + int64 total = 5; +} + +message VertexLog { + int64 inc = 1; + int64 timestamp = 2; + int64 stream = 3; + bytes msg = 4; } diff --git a/client/graph.go b/client/graph.go new file mode 100644 index 00000000..ceace229 --- /dev/null +++ b/client/graph.go @@ -0,0 +1,49 @@ +package client + +import ( + "time" + + digest "github.com/opencontainers/go-digest" +) + +type Vertex struct { + ID digest.Digest + Inputs []digest.Digest + Name string + Started time.Time + Completed time.Time + Cached bool + Error string +} + +type VertexStatus struct { + ID digest.Digest + Vertex digest.Digest + Name string + Total int + Current int + Timestamp time.Time +} + +type VertexLog struct { + Vertex digest.Digest + Stream int + Data []byte + Timestamp time.Time +} + +type SolveStatus struct { + Vertexes []*Vertex + Statuses []*VertexStatus + Logs []*VertexLog +} + +// +// type VertexEvent struct { +// ID digest.Digest +// Vertex digest.Digest +// Name string +// Total int +// Current int +// Timestamp int64 +// } diff --git a/control/control.go b/control/control.go index 7e957a05..68f70b42 100644 --- a/control/control.go +++ b/control/control.go @@ -64,8 +64,12 @@ func (c *Controller) Solve(ctx context.Context, req *controlapi.SolveRequest) (* if err != nil { return nil, errors.Wrap(err, "failed to load") } - if err := c.solver.Solve(ctx, v); err != nil { + if err := c.solver.Solve(ctx, req.Ref, v); err != nil { return nil, err } return &controlapi.SolveResponse{}, nil } + +func (c *Controller) Status(*controlapi.StatusRequest, controlapi.Control_StatusServer) error { + return errors.Errorf("not implemented") +} diff --git a/control/control_standalone.go b/control/control_standalone.go index cb0c9fae..a1ff0891 100644 --- a/control/control_standalone.go +++ b/control/control_standalone.go @@ -3,7 +3,6 @@ package control import ( - "context" "io" "io/ioutil" "os" @@ -18,6 +17,7 @@ import ( ocispec "github.com/opencontainers/image-spec/specs-go/v1" "github.com/pkg/errors" "github.com/tonistiigi/buildkit_poc/worker/runcworker" + "golang.org/x/net/context" ) func NewStandalone(root string) (*Controller, error) { diff --git a/solver/load.go b/solver/load.go index 391fc5f4..f8d4b0c5 100644 --- a/solver/load.go +++ b/solver/load.go @@ -3,15 +3,19 @@ package solver import ( "context" "os" + "strings" "sync" + "time" "golang.org/x/sync/errgroup" digest "github.com/opencontainers/go-digest" "github.com/pkg/errors" "github.com/tonistiigi/buildkit_poc/cache" + "github.com/tonistiigi/buildkit_poc/client" "github.com/tonistiigi/buildkit_poc/solver/pb" "github.com/tonistiigi/buildkit_poc/source" + "github.com/tonistiigi/buildkit_poc/util/progress" "github.com/tonistiigi/buildkit_poc/worker" ) @@ -22,6 +26,7 @@ type opVertex struct { refs []cache.ImmutableRef err error dgst digest.Digest + vtx client.Vertex } func Load(ops [][]byte) (*opVertex, error) { @@ -63,17 +68,25 @@ func loadReqursive(dgst digest.Digest, op *pb.Op, inputs map[digest.Digest]*pb.O return v, nil } vtx := &opVertex{op: op, dgst: dgst} + inputDigests := make([]digest.Digest, 0, len(op.Inputs)) for _, in := range op.Inputs { - op, ok := inputs[digest.Digest(in.Digest)] + dgst := digest.Digest(in.Digest) + inputDigests = append(inputDigests, dgst) + op, ok := inputs[dgst] if !ok { return nil, errors.Errorf("failed to find %s", in) } - sub, err := loadReqursive(digest.Digest(in.Digest), op, inputs, cache) + sub, err := loadReqursive(dgst, op, inputs, cache) if err != nil { return nil, err } vtx.inputs = append(vtx.inputs, sub) } + vtx.vtx = client.Vertex{ + Inputs: inputDigests, + Name: vtx.name(), + ID: dgst, + } cache[dgst] = vtx return vtx, nil } @@ -89,19 +102,44 @@ func (g *opVertex) inputRequiresExport(i int) bool { } type Solver struct { - opt Opt + opt Opt + jobs jobs } func New(opt Opt) *Solver { return &Solver{opt: opt} } -func (s *Solver) Solve(ctx context.Context, g *opVertex) error { - err := g.solve(ctx, s.opt) // TODO: separate exporting +func (s *Solver) Solve(ctx context.Context, id string, g *opVertex) error { + // ctx, cancel := context.WithCancel(ctx) + // defer cancel() + + pr, ctx, closeProgressWriter := progress.NewContext(ctx) + + _, err := s.jobs.new(id, g, pr) + if err != nil { + return err + } + + err = g.solve(ctx, s.opt) // TODO: separate exporting + closeProgressWriter() + if err != nil { + return err + } + g.release(ctx) + // TODO: export final vertex state return err } +func (s *Solver) Status(ctx context.Context, id string, statusChan chan *client.SolveStatus) error { + j, err := s.jobs.get(id) + if err != nil { + return nil + } + return j.pipe(ctx, statusChan) +} + func (g *opVertex) release(ctx context.Context) (retErr error) { for _, i := range g.inputs { if err := i.release(ctx); err != nil { @@ -150,8 +188,7 @@ func (g *opVertex) solve(ctx context.Context, opt Opt) (retErr error) { for _, in := range g.inputs { eg.Go(func() error { - err := in.solve(ctx, opt) - if err != nil { + if err := in.solve(ctx, opt); err != nil { return err } return nil @@ -163,6 +200,12 @@ func (g *opVertex) solve(ctx context.Context, opt Opt) (retErr error) { } } + pw, _, ctx := progress.FromContext(ctx, g.dgst.String()) + defer pw.Done() + + g.notifyStarted(pw) + defer g.notifyComplete(pw) + switch op := g.op.Op.(type) { case *pb.Op_Source: id, err := source.FromString(op.Source.Identifier) @@ -232,3 +275,28 @@ func (g *opVertex) solve(ctx context.Context, opt Opt) (retErr error) { } return nil } + +func (g *opVertex) notifyStarted(pw progress.ProgressWriter) { + g.vtx.Started = time.Now() + pw.Write(g.vtx) +} + +func (g *opVertex) notifyComplete(pw progress.ProgressWriter) { + g.vtx.Completed = time.Now() + pw.Write(g.vtx) +} + +func (g *opVertex) name() string { + switch op := g.op.Op.(type) { + case *pb.Op_Source: + return op.Source.Identifier + case *pb.Op_Exec: + name := strings.Join(op.Exec.Meta.Args, " ") + if len(name) > 22 { // TODO: const + name = name[:20] + "..." + } + return name + default: + return "unknown" + } +} diff --git a/solver/run.go b/solver/run.go new file mode 100644 index 00000000..066d1ae7 --- /dev/null +++ b/solver/run.go @@ -0,0 +1,102 @@ +package solver + +import ( + "context" + "sync" + + digest "github.com/opencontainers/go-digest" + "github.com/pkg/errors" + "github.com/tonistiigi/buildkit_poc/client" + "github.com/tonistiigi/buildkit_poc/util/progress" +) + +type jobs struct { + mu sync.RWMutex + refs map[string]*job +} + +func (j *jobs) new(id string, g *opVertex, pr progress.ProgressReader) (*job, error) { + j.mu.Lock() + defer j.mu.Unlock() + + if j.refs == nil { + j.refs = make(map[string]*job) + } + if _, ok := j.refs[id]; ok { + return nil, errors.Errorf("id %s exists", id) + } + nj := &job{g: g, pr: progress.NewMultiReader(pr)} + j.refs[id] = nj + + go func() { + j.mu.Lock() + defer j.mu.Unlock() + delete(j.refs, id) + }() + + return j.refs[id], nil +} + +func (j *jobs) get(id string) (*job, error) { + j.mu.RLock() + defer j.mu.RUnlock() + nj, ok := j.refs[id] + if !ok { + return nil, errors.Errorf("no such job %s", id) + } + return nj, nil +} + +type job struct { + mu sync.Mutex + g *opVertex + pr *progress.MultiReader +} + +func (j *job) pipe(ctx context.Context, ch chan *client.SolveStatus) error { + pr := j.pr.Reader(ctx) + for v := range flatten(j.g) { + ss := &client.SolveStatus{ + Vertexes: []*client.Vertex{&v.vtx}, + } + select { + case <-ctx.Done(): + return ctx.Err() + case ch <- ss: + } + } + for { + p, err := pr.Read(ctx) // add cancelling + if err != nil { + return err + } + switch v := p.Sys.(type) { + case *client.Vertex: + ss := &client.SolveStatus{Vertexes: []*client.Vertex{v}} + select { + case <-ctx.Done(): + return ctx.Err() + case ch <- ss: + } + } + } + + return nil +} + +func flatten(op *opVertex) chan *opVertex { + cache := make(map[digest.Digest]struct{}) + ch := make(chan *opVertex, 32) + go sendVertex(ch, op, cache) + return ch +} + +func sendVertex(ch chan *opVertex, op *opVertex, cache map[digest.Digest]struct{}) { + for _, v := range op.inputs { + sendVertex(ch, v, cache) + } + if _, ok := cache[op.dgst]; !ok { + ch <- op + cache[op.dgst] = struct{}{} + } +} diff --git a/util/progress/multireader.go b/util/progress/multireader.go new file mode 100644 index 00000000..69779e23 --- /dev/null +++ b/util/progress/multireader.go @@ -0,0 +1,67 @@ +package progress + +import ( + "context" + "sync" +) + +type MultiReader struct { + mu sync.Mutex + main ProgressReader + initialized bool + done chan struct{} + writers map[*progressWriter]struct{} +} + +func NewMultiReader(pr ProgressReader) *MultiReader { + mr := &MultiReader{ + main: pr, + done: make(chan struct{}), + } + return mr +} + +func (mr *MultiReader) Reader(ctx context.Context) ProgressReader { + mr.mu.Lock() + defer mr.mu.Unlock() + + pr, ctx, _ := NewContext(ctx) + pw, _, _ := FromContext(ctx, "") + + w := pw.(*progressWriter) + mr.writers[w] = struct{}{} + + go func() { + select { + case <-ctx.Done(): + case <-mr.done: + } + mr.mu.Lock() + defer mr.mu.Unlock() + delete(mr.writers, w) + }() + + if !mr.initialized { + go mr.handle() + mr.initialized = true + } + + return pr +} + +func (mr *MultiReader) handle() error { + for { + p, err := mr.main.Read(context.TODO()) + if err != nil { + return err + } + if p == nil { + return nil + } + mr.mu.Lock() + for w := range mr.writers { + w.write(*p) + } + mr.mu.Unlock() + } +} diff --git a/util/progress/progress.go b/util/progress/progress.go index 4a48479d..4874577a 100644 --- a/util/progress/progress.go +++ b/util/progress/progress.go @@ -20,7 +20,7 @@ func FromContext(ctx context.Context, name string) (ProgressWriter, bool, contex } pw = newWriter(pw, name) ctx = context.WithValue(ctx, contextKey, pw) - return pw, false, ctx + return pw, true, ctx } func NewContext(ctx context.Context) (ProgressReader, context.Context, func()) { @@ -30,7 +30,7 @@ func NewContext(ctx context.Context) (ProgressReader, context.Context, func()) { } type ProgressWriter interface { - Write(Progress) error + Write(interface{}) error Done() error } @@ -39,17 +39,17 @@ type ProgressReader interface { } type Progress struct { - ID string - - // Progress contains a Message or... - Message string - - // ...progress of an action - Action string - Current int - Total int + ID string Timestamp time.Time Done bool + Sys interface{} +} + +type Status struct { + // ...progress of an action + Action string + Current int + Total int } type progressReader struct { @@ -95,7 +95,7 @@ func (pr *progressReader) Read(ctx context.Context) (*Progress, error) { default: } open := false - for _, sh := range pr.handles { // could be more efficient but unlikely that this array will be very big, maybe random ordering? + for _, sh := range pr.handles { // could be more efficient but unlikely that this array will be very big, maybe random ordering? at least remove the completed handlers. p, ok := sh.next() if ok { pr.mu.Unlock() @@ -148,7 +148,11 @@ func pipe() (*progressReader, *progressWriter, func()) { func newWriter(pw *progressWriter, name string) *progressWriter { if pw.id != "" { - name = pw.id + "." + name + if name == "" { + name = pw.id + } else { + name = pw.id + "." + name + } } pw = &progressWriter{ id: name, @@ -163,20 +167,27 @@ type progressWriter struct { lastP atomic.Value done bool reader *progressReader + + byKey map[string]atomic.Value + items []atomic.Value } -func (pw *progressWriter) Write(p Progress) error { +func (pw *progressWriter) Write(s interface{}) error { if pw.done { return errors.Errorf("writing to closed progresswriter %s", pw.id) } + var p Progress p.ID = pw.id - if p.Timestamp.IsZero() { - p.Timestamp = time.Now() - } - pw.lastP.Store(&p) + p.Timestamp = time.Now() + p.Sys = s + return pw.write(p) +} + +func (pw *progressWriter) write(p Progress) error { if p.Done { pw.done = true } + pw.lastP.Store(&p) pw.reader.cond.Broadcast() return nil } @@ -184,21 +195,24 @@ func (pw *progressWriter) Write(p Progress) error { func (pw *progressWriter) Done() error { var p Progress lastP := pw.lastP.Load().(*Progress) + p.ID = pw.id + p.Timestamp = time.Now() if lastP != nil { p = *lastP if p.Done { return nil } } else { - p = Progress{} + p.Sys = lastP.Sys } p.Done = true - return pw.Write(p) + pw.done = true + return pw.write(p) } type noOpWriter struct{} -func (pw *noOpWriter) Write(p Progress) error { +func (pw *noOpWriter) Write(p interface{}) error { return nil } diff --git a/util/progress/progress_test.go b/util/progress/progress_test.go index ab3ac5be..c5ef2a23 100644 --- a/util/progress/progress_test.go +++ b/util/progress/progress_test.go @@ -30,7 +30,8 @@ func TestProgress(t *testing.T) { err = eg.Wait() assert.NoError(t, err) - assert.Equal(t, 6, len(trace.items)) + assert.True(t, len(trace.items) > 5) + assert.True(t, len(trace.items) <= 7) assert.Equal(t, trace.items[len(trace.items)-1].Done, true) } @@ -51,7 +52,7 @@ func TestProgressNested(t *testing.T) { assert.NoError(t, err) assert.True(t, len(trace.items) > 9) // usually 14 - assert.True(t, len(trace.items) <= 14) + assert.True(t, len(trace.items) <= 15) streams := 0 for _, t := range trace.items { if t.Done { @@ -66,7 +67,7 @@ func calc(ctx context.Context, total int, name string) (int, error) { defer pw.Done() sum := 0 - pw.Write(Progress{Action: "starting", Total: total}) + pw.Write(Status{Action: "starting", Total: total}) for i := 1; i <= total; i++ { select { case <-ctx.Done(): @@ -74,12 +75,13 @@ func calc(ctx context.Context, total int, name string) (int, error) { case <-time.After(10 * time.Millisecond): } if i == total { - pw.Write(Progress{Action: "done", Total: total, Current: total, Done: true}) + pw.Write(Status{Action: "done", Total: total, Current: total}) } else { - pw.Write(Progress{Action: "calculating", Total: total, Current: i}) + pw.Write(Status{Action: "calculating", Total: total, Current: i}) } sum += i } + pw.Done() return sum, nil } @@ -90,7 +92,7 @@ func reduceCalc(ctx context.Context, total int) (int, error) { pw, _, ctx := FromContext(ctx, "reduce") defer pw.Done() - pw.Write(Progress{Action: "starting"}) + pw.Write(Status{Action: "starting"}) // sync step sum, err := calc(ctx, total, "synccalc") From 12a84368df4e74f797020a00f0328bcdd96d8806 Mon Sep 17 00:00:00 2001 From: Tonis Tiigi Date: Tue, 13 Jun 2017 17:15:55 -0700 Subject: [PATCH 2/5] solver: vertex progress reporting Signed-off-by: Tonis Tiigi --- api/services/control/control.pb.go | 265 +++++++++++------------------ api/services/control/control.proto | 13 +- client/graph.go | 4 +- client/solve.go | 42 ++++- control/control.go | 56 +++++- solver/jobs.go | 132 ++++++++++++++ solver/load.go | 232 ------------------------- solver/run.go | 102 ----------- solver/solver.go | 242 ++++++++++++++++++++++++++ util/progress/multireader.go | 25 +-- util/progress/progress.go | 2 +- 11 files changed, 585 insertions(+), 530 deletions(-) create mode 100644 solver/jobs.go delete mode 100644 solver/run.go create mode 100644 solver/solver.go diff --git a/api/services/control/control.pb.go b/api/services/control/control.pb.go index 13724498..3ae18914 100644 --- a/api/services/control/control.pb.go +++ b/api/services/control/control.pb.go @@ -164,44 +164,43 @@ func (m *StatusRequest) GetRef() string { } type StatusResponse struct { - Vtx []*Vertex `protobuf:"bytes,1,rep,name=vtx" json:"vtx,omitempty"` - Status []*VertexStatus `protobuf:"bytes,2,rep,name=status" json:"status,omitempty"` - Log []*VertexLog `protobuf:"bytes,3,rep,name=log" json:"log,omitempty"` + Vertexes []*Vertex `protobuf:"bytes,1,rep,name=vertexes" json:"vertexes,omitempty"` + Statuses []*VertexStatus `protobuf:"bytes,2,rep,name=statuses" json:"statuses,omitempty"` + Logs []*VertexLog `protobuf:"bytes,3,rep,name=logs" json:"logs,omitempty"` } func (m *StatusResponse) Reset() { *m = StatusResponse{} } func (*StatusResponse) ProtoMessage() {} func (*StatusResponse) Descriptor() ([]byte, []int) { return fileDescriptorControl, []int{6} } -func (m *StatusResponse) GetVtx() []*Vertex { +func (m *StatusResponse) GetVertexes() []*Vertex { if m != nil { - return m.Vtx + return m.Vertexes } return nil } -func (m *StatusResponse) GetStatus() []*VertexStatus { +func (m *StatusResponse) GetStatuses() []*VertexStatus { if m != nil { - return m.Status + return m.Statuses } return nil } -func (m *StatusResponse) GetLog() []*VertexLog { +func (m *StatusResponse) GetLogs() []*VertexLog { if m != nil { - return m.Log + return m.Logs } return nil } type Vertex struct { - ID string `protobuf:"bytes,1,opt,name=ID,proto3" json:"ID,omitempty"` - Inputs []string `protobuf:"bytes,2,rep,name=inputs" json:"inputs,omitempty"` - Name string `protobuf:"bytes,3,opt,name=name,proto3" json:"name,omitempty"` - Status []*VertexStatus `protobuf:"bytes,4,rep,name=status" json:"status,omitempty"` - Cached bool `protobuf:"varint,5,opt,name=cached,proto3" json:"cached,omitempty"` - Started int64 `protobuf:"varint,6,opt,name=started,proto3" json:"started,omitempty"` - Completed int64 `protobuf:"varint,7,opt,name=completed,proto3" json:"completed,omitempty"` + ID string `protobuf:"bytes,1,opt,name=ID,proto3" json:"ID,omitempty"` + Inputs []string `protobuf:"bytes,2,rep,name=inputs" json:"inputs,omitempty"` + Name string `protobuf:"bytes,3,opt,name=name,proto3" json:"name,omitempty"` + Cached bool `protobuf:"varint,4,opt,name=cached,proto3" json:"cached,omitempty"` + Started int64 `protobuf:"varint,5,opt,name=started,proto3" json:"started,omitempty"` + Completed int64 `protobuf:"varint,6,opt,name=completed,proto3" json:"completed,omitempty"` } func (m *Vertex) Reset() { *m = Vertex{} } @@ -229,13 +228,6 @@ func (m *Vertex) GetName() string { return "" } -func (m *Vertex) GetStatus() []*VertexStatus { - if m != nil { - return m.Status - } - return nil -} - func (m *Vertex) GetCached() bool { if m != nil { return m.Cached @@ -584,27 +576,27 @@ func (this *StatusResponse) Equal(that interface{}) bool { } else if this == nil { return false } - if len(this.Vtx) != len(that1.Vtx) { + if len(this.Vertexes) != len(that1.Vertexes) { return false } - for i := range this.Vtx { - if !this.Vtx[i].Equal(that1.Vtx[i]) { + for i := range this.Vertexes { + if !this.Vertexes[i].Equal(that1.Vertexes[i]) { return false } } - if len(this.Status) != len(that1.Status) { + if len(this.Statuses) != len(that1.Statuses) { return false } - for i := range this.Status { - if !this.Status[i].Equal(that1.Status[i]) { + for i := range this.Statuses { + if !this.Statuses[i].Equal(that1.Statuses[i]) { return false } } - if len(this.Log) != len(that1.Log) { + if len(this.Logs) != len(that1.Logs) { return false } - for i := range this.Log { - if !this.Log[i].Equal(that1.Log[i]) { + for i := range this.Logs { + if !this.Logs[i].Equal(that1.Logs[i]) { return false } } @@ -649,14 +641,6 @@ func (this *Vertex) Equal(that interface{}) bool { if this.Name != that1.Name { return false } - if len(this.Status) != len(that1.Status) { - return false - } - for i := range this.Status { - if !this.Status[i].Equal(that1.Status[i]) { - return false - } - } if this.Cached != that1.Cached { return false } @@ -822,14 +806,14 @@ func (this *StatusResponse) GoString() string { } s := make([]string, 0, 7) s = append(s, "&control.StatusResponse{") - if this.Vtx != nil { - s = append(s, "Vtx: "+fmt.Sprintf("%#v", this.Vtx)+",\n") + if this.Vertexes != nil { + s = append(s, "Vertexes: "+fmt.Sprintf("%#v", this.Vertexes)+",\n") } - if this.Status != nil { - s = append(s, "Status: "+fmt.Sprintf("%#v", this.Status)+",\n") + if this.Statuses != nil { + s = append(s, "Statuses: "+fmt.Sprintf("%#v", this.Statuses)+",\n") } - if this.Log != nil { - s = append(s, "Log: "+fmt.Sprintf("%#v", this.Log)+",\n") + if this.Logs != nil { + s = append(s, "Logs: "+fmt.Sprintf("%#v", this.Logs)+",\n") } s = append(s, "}") return strings.Join(s, "") @@ -838,14 +822,11 @@ func (this *Vertex) GoString() string { if this == nil { return "nil" } - s := make([]string, 0, 11) + s := make([]string, 0, 10) s = append(s, "&control.Vertex{") s = append(s, "ID: "+fmt.Sprintf("%#v", this.ID)+",\n") s = append(s, "Inputs: "+fmt.Sprintf("%#v", this.Inputs)+",\n") s = append(s, "Name: "+fmt.Sprintf("%#v", this.Name)+",\n") - if this.Status != nil { - s = append(s, "Status: "+fmt.Sprintf("%#v", this.Status)+",\n") - } s = append(s, "Cached: "+fmt.Sprintf("%#v", this.Cached)+",\n") s = append(s, "Started: "+fmt.Sprintf("%#v", this.Started)+",\n") s = append(s, "Completed: "+fmt.Sprintf("%#v", this.Completed)+",\n") @@ -1252,8 +1233,8 @@ func (m *StatusResponse) MarshalTo(dAtA []byte) (int, error) { _ = i var l int _ = l - if len(m.Vtx) > 0 { - for _, msg := range m.Vtx { + if len(m.Vertexes) > 0 { + for _, msg := range m.Vertexes { dAtA[i] = 0xa i++ i = encodeVarintControl(dAtA, i, uint64(msg.Size())) @@ -1264,8 +1245,8 @@ func (m *StatusResponse) MarshalTo(dAtA []byte) (int, error) { i += n } } - if len(m.Status) > 0 { - for _, msg := range m.Status { + if len(m.Statuses) > 0 { + for _, msg := range m.Statuses { dAtA[i] = 0x12 i++ i = encodeVarintControl(dAtA, i, uint64(msg.Size())) @@ -1276,8 +1257,8 @@ func (m *StatusResponse) MarshalTo(dAtA []byte) (int, error) { i += n } } - if len(m.Log) > 0 { - for _, msg := range m.Log { + if len(m.Logs) > 0 { + for _, msg := range m.Logs { dAtA[i] = 0x1a i++ i = encodeVarintControl(dAtA, i, uint64(msg.Size())) @@ -1333,20 +1314,8 @@ func (m *Vertex) MarshalTo(dAtA []byte) (int, error) { i = encodeVarintControl(dAtA, i, uint64(len(m.Name))) i += copy(dAtA[i:], m.Name) } - if len(m.Status) > 0 { - for _, msg := range m.Status { - dAtA[i] = 0x22 - i++ - i = encodeVarintControl(dAtA, i, uint64(msg.Size())) - n, err := msg.MarshalTo(dAtA[i:]) - if err != nil { - return 0, err - } - i += n - } - } if m.Cached { - dAtA[i] = 0x28 + dAtA[i] = 0x20 i++ if m.Cached { dAtA[i] = 1 @@ -1356,12 +1325,12 @@ func (m *Vertex) MarshalTo(dAtA []byte) (int, error) { i++ } if m.Started != 0 { - dAtA[i] = 0x30 + dAtA[i] = 0x28 i++ i = encodeVarintControl(dAtA, i, uint64(m.Started)) } if m.Completed != 0 { - dAtA[i] = 0x38 + dAtA[i] = 0x30 i++ i = encodeVarintControl(dAtA, i, uint64(m.Completed)) } @@ -1558,20 +1527,20 @@ func (m *StatusRequest) Size() (n int) { func (m *StatusResponse) Size() (n int) { var l int _ = l - if len(m.Vtx) > 0 { - for _, e := range m.Vtx { + if len(m.Vertexes) > 0 { + for _, e := range m.Vertexes { l = e.Size() n += 1 + l + sovControl(uint64(l)) } } - if len(m.Status) > 0 { - for _, e := range m.Status { + if len(m.Statuses) > 0 { + for _, e := range m.Statuses { l = e.Size() n += 1 + l + sovControl(uint64(l)) } } - if len(m.Log) > 0 { - for _, e := range m.Log { + if len(m.Logs) > 0 { + for _, e := range m.Logs { l = e.Size() n += 1 + l + sovControl(uint64(l)) } @@ -1596,12 +1565,6 @@ func (m *Vertex) Size() (n int) { if l > 0 { n += 1 + l + sovControl(uint64(l)) } - if len(m.Status) > 0 { - for _, e := range m.Status { - l = e.Size() - n += 1 + l + sovControl(uint64(l)) - } - } if m.Cached { n += 2 } @@ -1738,9 +1701,9 @@ func (this *StatusResponse) String() string { return "nil" } s := strings.Join([]string{`&StatusResponse{`, - `Vtx:` + strings.Replace(fmt.Sprintf("%v", this.Vtx), "Vertex", "Vertex", 1) + `,`, - `Status:` + strings.Replace(fmt.Sprintf("%v", this.Status), "VertexStatus", "VertexStatus", 1) + `,`, - `Log:` + strings.Replace(fmt.Sprintf("%v", this.Log), "VertexLog", "VertexLog", 1) + `,`, + `Vertexes:` + strings.Replace(fmt.Sprintf("%v", this.Vertexes), "Vertex", "Vertex", 1) + `,`, + `Statuses:` + strings.Replace(fmt.Sprintf("%v", this.Statuses), "VertexStatus", "VertexStatus", 1) + `,`, + `Logs:` + strings.Replace(fmt.Sprintf("%v", this.Logs), "VertexLog", "VertexLog", 1) + `,`, `}`, }, "") return s @@ -1753,7 +1716,6 @@ func (this *Vertex) String() string { `ID:` + fmt.Sprintf("%v", this.ID) + `,`, `Inputs:` + fmt.Sprintf("%v", this.Inputs) + `,`, `Name:` + fmt.Sprintf("%v", this.Name) + `,`, - `Status:` + strings.Replace(fmt.Sprintf("%v", this.Status), "VertexStatus", "VertexStatus", 1) + `,`, `Cached:` + fmt.Sprintf("%v", this.Cached) + `,`, `Started:` + fmt.Sprintf("%v", this.Started) + `,`, `Completed:` + fmt.Sprintf("%v", this.Completed) + `,`, @@ -2364,7 +2326,7 @@ func (m *StatusResponse) Unmarshal(dAtA []byte) error { switch fieldNum { case 1: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Vtx", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field Vertexes", wireType) } var msglen int for shift := uint(0); ; shift += 7 { @@ -2388,14 +2350,14 @@ func (m *StatusResponse) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - m.Vtx = append(m.Vtx, &Vertex{}) - if err := m.Vtx[len(m.Vtx)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + m.Vertexes = append(m.Vertexes, &Vertex{}) + if err := m.Vertexes[len(m.Vertexes)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err } iNdEx = postIndex case 2: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Status", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field Statuses", wireType) } var msglen int for shift := uint(0); ; shift += 7 { @@ -2419,14 +2381,14 @@ func (m *StatusResponse) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - m.Status = append(m.Status, &VertexStatus{}) - if err := m.Status[len(m.Status)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + m.Statuses = append(m.Statuses, &VertexStatus{}) + if err := m.Statuses[len(m.Statuses)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err } iNdEx = postIndex case 3: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Log", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field Logs", wireType) } var msglen int for shift := uint(0); ; shift += 7 { @@ -2450,8 +2412,8 @@ func (m *StatusResponse) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - m.Log = append(m.Log, &VertexLog{}) - if err := m.Log[len(m.Log)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + m.Logs = append(m.Logs, &VertexLog{}) + if err := m.Logs[len(m.Logs)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err } iNdEx = postIndex @@ -2593,37 +2555,6 @@ func (m *Vertex) Unmarshal(dAtA []byte) error { m.Name = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex case 4: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Status", wireType) - } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowControl - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - msglen |= (int(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return ErrInvalidLengthControl - } - postIndex := iNdEx + msglen - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.Status = append(m.Status, &VertexStatus{}) - if err := m.Status[len(m.Status)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - case 5: if wireType != 0 { return fmt.Errorf("proto: wrong wireType = %d for field Cached", wireType) } @@ -2643,7 +2574,7 @@ func (m *Vertex) Unmarshal(dAtA []byte) error { } } m.Cached = bool(v != 0) - case 6: + case 5: if wireType != 0 { return fmt.Errorf("proto: wrong wireType = %d for field Started", wireType) } @@ -2662,7 +2593,7 @@ func (m *Vertex) Unmarshal(dAtA []byte) error { break } } - case 7: + case 6: if wireType != 0 { return fmt.Errorf("proto: wrong wireType = %d for field Completed", wireType) } @@ -3123,42 +3054,42 @@ var ( func init() { proto.RegisterFile("control.proto", fileDescriptorControl) } var fileDescriptorControl = []byte{ - // 577 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x8c, 0x54, 0xbf, 0x6f, 0xd3, 0x4e, - 0x14, 0xcf, 0xe5, 0x1a, 0xe7, 0xeb, 0x97, 0xa4, 0xdf, 0x72, 0x2a, 0xc1, 0x44, 0xe8, 0x94, 0x5a, - 0x0c, 0x19, 0x4a, 0x85, 0x82, 0xc4, 0xc2, 0x02, 0x25, 0x4b, 0x24, 0x58, 0x2e, 0x2a, 0xbb, 0xeb, - 0x5c, 0x83, 0x85, 0xed, 0x0b, 0xbe, 0x4b, 0x54, 0x75, 0x62, 0x64, 0xe4, 0xcf, 0xe0, 0xef, 0x80, - 0x85, 0xb1, 0x23, 0x23, 0x31, 0x0b, 0x63, 0xff, 0x04, 0x74, 0xe7, 0x73, 0x62, 0xa5, 0x41, 0xea, - 0xf6, 0x3e, 0x9f, 0xf7, 0xfc, 0xde, 0xe7, 0xfd, 0x38, 0x43, 0x27, 0x14, 0xa9, 0xca, 0x44, 0x7c, - 0x32, 0xcf, 0x84, 0x12, 0xa4, 0x69, 0xa1, 0x4f, 0xe0, 0x60, 0x14, 0xc9, 0x0f, 0x67, 0x32, 0x98, - 0x71, 0xc6, 0x3f, 0x2e, 0xb8, 0x54, 0xfe, 0x2b, 0xb8, 0x57, 0xe1, 0xe4, 0x5c, 0xa4, 0x92, 0x93, - 0x63, 0x70, 0x32, 0x1e, 0x8a, 0x6c, 0xea, 0xa1, 0x3e, 0x1e, 0xb4, 0x86, 0x87, 0x27, 0x65, 0x46, - 0x1b, 0xa7, 0x7d, 0xcc, 0xc6, 0xf8, 0x01, 0xb4, 0x2a, 0x34, 0xd9, 0x87, 0xfa, 0x78, 0xe4, 0xa1, - 0x3e, 0x1a, 0xb8, 0xac, 0x3e, 0x1e, 0x11, 0x0f, 0x9a, 0x6f, 0x17, 0x2a, 0x38, 0x8f, 0xb9, 0x57, - 0xef, 0xa3, 0xc1, 0x7f, 0xac, 0x84, 0xe4, 0x10, 0x1a, 0xe3, 0xf4, 0x4c, 0x72, 0x0f, 0x1b, 0xbe, - 0x00, 0x84, 0xc0, 0xde, 0x24, 0xba, 0xe2, 0xde, 0x5e, 0x1f, 0x0d, 0x30, 0x33, 0xb6, 0xff, 0x12, - 0xda, 0x13, 0x11, 0x2f, 0x4b, 0xd5, 0xe4, 0x00, 0x30, 0xe3, 0x17, 0xb6, 0x88, 0x36, 0x09, 0x05, - 0x18, 0xf1, 0x8b, 0x28, 0x8d, 0x54, 0x24, 0x52, 0xaf, 0xde, 0xc7, 0x83, 0x36, 0xab, 0x30, 0xfe, - 0x10, 0x3a, 0x36, 0x83, 0xed, 0xf1, 0x08, 0xf0, 0x52, 0x5d, 0xda, 0x06, 0xff, 0x5f, 0x37, 0xf8, - 0x8e, 0x67, 0x8a, 0x5f, 0x32, 0xed, 0xf3, 0x8f, 0xa0, 0x33, 0x51, 0x81, 0x5a, 0xc8, 0x7f, 0x96, - 0xf5, 0x3f, 0x23, 0xd8, 0x2f, 0x63, 0xee, 0x9c, 0x98, 0x3c, 0x01, 0x47, 0x9a, 0x8f, 0x8c, 0xd0, - 0xd6, 0xf0, 0xfe, 0x56, 0x94, 0xcd, 0x68, 0x83, 0xc8, 0x63, 0xc0, 0xb1, 0x98, 0x79, 0xd8, 0xc4, - 0x92, 0xad, 0xd8, 0x37, 0x62, 0xc6, 0xb4, 0xdb, 0xff, 0x8e, 0xc0, 0x29, 0xa8, 0x5b, 0x2b, 0xe8, - 0x82, 0x13, 0xa5, 0xf3, 0x85, 0x2a, 0xea, 0xb9, 0xcc, 0x22, 0x3d, 0xea, 0x34, 0x48, 0x8a, 0xf9, - 0xbb, 0xcc, 0xd8, 0x15, 0x6d, 0x7b, 0x77, 0xd1, 0xd6, 0x05, 0x27, 0x0c, 0xc2, 0xf7, 0x7c, 0xea, - 0x35, 0xcc, 0x12, 0x2d, 0xd2, 0x5b, 0x97, 0x2a, 0xc8, 0x14, 0x9f, 0x7a, 0x8e, 0x59, 0x64, 0x09, - 0xc9, 0x23, 0x70, 0x43, 0x91, 0xcc, 0x63, 0xae, 0x7d, 0x4d, 0xe3, 0xdb, 0x10, 0xfe, 0x15, 0xb4, - 0xab, 0x75, 0x76, 0xb5, 0xb2, 0x34, 0x7e, 0x73, 0x4c, 0x2e, 0xb3, 0x68, 0x67, 0x2b, 0x1e, 0x34, - 0xc3, 0x45, 0x96, 0xf1, 0x54, 0xd9, 0x63, 0x2a, 0xa1, 0xbe, 0x3c, 0x25, 0x54, 0x10, 0x1b, 0xd1, - 0x98, 0x15, 0xc0, 0xe7, 0xe0, 0xae, 0x67, 0xaa, 0x77, 0x1d, 0xa5, 0xa1, 0xa9, 0x8c, 0x99, 0x36, - 0xb5, 0x70, 0x15, 0x25, 0x5c, 0xaa, 0x20, 0x99, 0x9b, 0xea, 0x98, 0x6d, 0x08, 0x2d, 0x4c, 0xaa, - 0x8c, 0x07, 0x89, 0x91, 0x80, 0x99, 0x45, 0x3a, 0x4f, 0x22, 0x67, 0x46, 0x40, 0x9b, 0x69, 0x73, - 0xf8, 0x0d, 0x41, 0xf3, 0x75, 0x31, 0x53, 0x72, 0x0a, 0xee, 0xfa, 0xf9, 0x91, 0x87, 0xeb, 0x51, - 0x6f, 0x3f, 0xd3, 0x5e, 0x6f, 0x97, 0xcb, 0x1e, 0xdc, 0x73, 0x68, 0x98, 0xd3, 0x26, 0x9b, 0x55, - 0x55, 0x1f, 0x4b, 0xaf, 0xbb, 0x4d, 0xdb, 0xef, 0x5e, 0x80, 0x63, 0x87, 0x5c, 0x89, 0xa8, 0xde, - 0x7b, 0xef, 0xc1, 0x2d, 0xbe, 0xf8, 0xf4, 0x29, 0x3a, 0x3d, 0xbe, 0x5e, 0xd1, 0xda, 0xcf, 0x15, - 0xad, 0xdd, 0xac, 0x28, 0xfa, 0x94, 0x53, 0xf4, 0x35, 0xa7, 0xe8, 0x47, 0x4e, 0xd1, 0x75, 0x4e, - 0xd1, 0xaf, 0x9c, 0xa2, 0x3f, 0x39, 0xad, 0xdd, 0xe4, 0x14, 0x7d, 0xf9, 0x4d, 0x6b, 0xe7, 0x8e, - 0xf9, 0x13, 0x3d, 0xfb, 0x1b, 0x00, 0x00, 0xff, 0xff, 0xc4, 0xe0, 0x91, 0xb1, 0x9a, 0x04, 0x00, - 0x00, + // 581 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x74, 0x54, 0x31, 0x6f, 0xd3, 0x40, + 0x14, 0xce, 0xc5, 0x89, 0x13, 0xbf, 0x24, 0xa5, 0x9c, 0x4a, 0x31, 0x11, 0x3a, 0xa5, 0x1e, 0x50, + 0x24, 0xaa, 0x0a, 0x82, 0xc4, 0xc2, 0x02, 0x25, 0x4b, 0x24, 0x58, 0x2e, 0x2a, 0xbb, 0xeb, 0x5c, + 0x83, 0x85, 0xed, 0x0b, 0xbe, 0x4b, 0x54, 0x75, 0xe2, 0x27, 0x30, 0x30, 0xf0, 0x13, 0xf8, 0x1d, + 0x4c, 0x8c, 0x1d, 0x19, 0x89, 0x59, 0x18, 0xfb, 0x13, 0xd0, 0x9d, 0xcf, 0x8e, 0x95, 0xa6, 0xdb, + 0xfb, 0xbe, 0xf7, 0xf9, 0xbd, 0xef, 0xee, 0xbd, 0x33, 0xf4, 0x02, 0x9e, 0xc8, 0x94, 0x47, 0x27, + 0x8b, 0x94, 0x4b, 0x8e, 0x5b, 0x06, 0x7a, 0x18, 0xf6, 0xc7, 0xa1, 0xf8, 0x74, 0x26, 0xfc, 0x39, + 0xa3, 0xec, 0xf3, 0x92, 0x09, 0xe9, 0xbd, 0x81, 0xfb, 0x15, 0x4e, 0x2c, 0x78, 0x22, 0x18, 0x3e, + 0x06, 0x3b, 0x65, 0x01, 0x4f, 0x67, 0x2e, 0x1a, 0x58, 0xc3, 0xce, 0xe8, 0xe0, 0xa4, 0xa8, 0x68, + 0x74, 0x2a, 0x47, 0x8d, 0xc6, 0xf3, 0xa1, 0x53, 0xa1, 0xf1, 0x1e, 0xd4, 0x27, 0x63, 0x17, 0x0d, + 0xd0, 0xd0, 0xa1, 0xf5, 0xc9, 0x18, 0xbb, 0xd0, 0x7a, 0xbf, 0x94, 0xfe, 0x79, 0xc4, 0xdc, 0xfa, + 0x00, 0x0d, 0xdb, 0xb4, 0x80, 0xf8, 0x00, 0x9a, 0x93, 0xe4, 0x4c, 0x30, 0xd7, 0xd2, 0x7c, 0x0e, + 0x30, 0x86, 0xc6, 0x34, 0xbc, 0x62, 0x6e, 0x63, 0x80, 0x86, 0x16, 0xd5, 0xb1, 0xf7, 0x1a, 0xba, + 0x53, 0x1e, 0xad, 0x0a, 0xd7, 0x78, 0x1f, 0x2c, 0xca, 0x2e, 0x4c, 0x13, 0x15, 0x62, 0x02, 0x30, + 0x66, 0x17, 0x61, 0x12, 0xca, 0x90, 0x27, 0x6e, 0x7d, 0x60, 0x0d, 0xbb, 0xb4, 0xc2, 0x78, 0x23, + 0xe8, 0x99, 0x0a, 0xe6, 0x8c, 0x47, 0x60, 0xad, 0xe4, 0xa5, 0x39, 0xe0, 0xbd, 0xf2, 0x80, 0x1f, + 0x58, 0x2a, 0xd9, 0x25, 0x55, 0x39, 0xef, 0x08, 0x7a, 0x53, 0xe9, 0xcb, 0xa5, 0xb8, 0xb3, 0xad, + 0xf7, 0x1d, 0xc1, 0x5e, 0xa1, 0x31, 0x85, 0x9f, 0x42, 0x7b, 0xa5, 0x8b, 0x30, 0x71, 0x57, 0xf5, + 0x52, 0x80, 0x9f, 0x43, 0x5b, 0xe8, 0xcf, 0x99, 0xd0, 0xa6, 0x3b, 0xa3, 0x07, 0x5b, 0x62, 0x53, + 0xbd, 0x94, 0xe1, 0x27, 0xd0, 0x88, 0xf8, 0x5c, 0xb8, 0x96, 0x96, 0xe3, 0x2d, 0xf9, 0x3b, 0x3e, + 0xa7, 0x3a, 0xef, 0x7d, 0x43, 0x60, 0xe7, 0xdc, 0xad, 0x91, 0x1c, 0x82, 0x1d, 0x26, 0x8b, 0xa5, + 0xcc, 0x7b, 0x3a, 0xd4, 0x20, 0x75, 0xf5, 0x89, 0x1f, 0xe7, 0xf3, 0x70, 0xa8, 0x8e, 0x95, 0x36, + 0xf0, 0x83, 0x8f, 0x6c, 0xa6, 0x07, 0xd2, 0xa6, 0x06, 0xa9, 0xb1, 0x0a, 0xe9, 0xa7, 0x92, 0xcd, + 0xdc, 0xa6, 0x9e, 0x54, 0x01, 0xf1, 0x63, 0x70, 0x02, 0x1e, 0x2f, 0x22, 0xa6, 0x72, 0xb6, 0xce, + 0x6d, 0x08, 0xef, 0x0a, 0xba, 0xd5, 0x83, 0xed, 0xf2, 0x96, 0xdf, 0x8e, 0xde, 0x16, 0x87, 0x1a, + 0xb4, 0xd3, 0x9b, 0x0b, 0xad, 0x60, 0x99, 0xa6, 0x2c, 0x91, 0x66, 0x5b, 0x0a, 0xa8, 0x56, 0x4b, + 0x72, 0xe9, 0x47, 0xc6, 0x5b, 0x0e, 0x3c, 0x06, 0x4e, 0x79, 0x4b, 0x6a, 0x98, 0x61, 0x12, 0xe8, + 0xce, 0x16, 0x55, 0xa1, 0x32, 0x2e, 0xc3, 0x98, 0x09, 0xe9, 0xc7, 0x0b, 0xdd, 0xdd, 0xa2, 0x1b, + 0x42, 0x19, 0x13, 0x32, 0x65, 0x7e, 0xac, 0x2d, 0x58, 0xd4, 0x20, 0x55, 0x27, 0x16, 0x73, 0x6d, + 0xa0, 0x4b, 0x55, 0x38, 0xfa, 0x89, 0xa0, 0xf5, 0x36, 0x9f, 0x0a, 0x3e, 0x05, 0xa7, 0x7c, 0x5f, + 0xf8, 0x51, 0x39, 0xac, 0xed, 0x77, 0xd8, 0xef, 0xef, 0x4a, 0x99, 0x8d, 0x7a, 0x09, 0x4d, 0xbd, + 0xbb, 0x78, 0xb3, 0x1b, 0xd5, 0xd7, 0xd0, 0x3f, 0xdc, 0xa6, 0xcd, 0x77, 0xaf, 0xc0, 0x36, 0x97, + 0x5c, 0x51, 0x54, 0x17, 0xba, 0xff, 0xf0, 0x16, 0x9f, 0x7f, 0xfa, 0x0c, 0x9d, 0x1e, 0x5f, 0xaf, + 0x49, 0xed, 0xf7, 0x9a, 0xd4, 0x6e, 0xd6, 0x04, 0x7d, 0xc9, 0x08, 0xfa, 0x91, 0x11, 0xf4, 0x2b, + 0x23, 0xe8, 0x3a, 0x23, 0xe8, 0x4f, 0x46, 0xd0, 0xbf, 0x8c, 0xd4, 0x6e, 0x32, 0x82, 0xbe, 0xfe, + 0x25, 0xb5, 0x73, 0x5b, 0xff, 0x6a, 0x5e, 0xfc, 0x0f, 0x00, 0x00, 0xff, 0xff, 0x03, 0x50, 0xff, + 0x6a, 0x7b, 0x04, 0x00, 0x00, } diff --git a/api/services/control/control.proto b/api/services/control/control.proto index ffd8de8d..5164f4b7 100644 --- a/api/services/control/control.proto +++ b/api/services/control/control.proto @@ -36,19 +36,18 @@ message StatusRequest { } message StatusResponse { - repeated Vertex vtx = 1; - repeated VertexStatus status = 2; - repeated VertexLog log = 3; + repeated Vertex vertexes = 1; + repeated VertexStatus statuses = 2; + repeated VertexLog logs = 3; } message Vertex { string ID = 1; repeated string inputs = 2; string name = 3; - repeated VertexStatus status = 4; - bool cached = 5; - int64 started = 6; // relative, add abolute google.protobuf.Timestamp as well? - int64 completed = 7; + bool cached = 4; + int64 started = 5; // relative, add abolute google.protobuf.Timestamp as well? + int64 completed = 6; } message VertexStatus { diff --git a/client/graph.go b/client/graph.go index ceace229..8ac76f75 100644 --- a/client/graph.go +++ b/client/graph.go @@ -10,8 +10,8 @@ type Vertex struct { ID digest.Digest Inputs []digest.Digest Name string - Started time.Time - Completed time.Time + Started *time.Time + Completed *time.Time Cached bool Error string } diff --git a/client/solve.go b/client/solve.go index daaeedb2..db98b5c4 100644 --- a/client/solve.go +++ b/client/solve.go @@ -6,9 +6,11 @@ import ( "encoding/hex" "io" + "github.com/Sirupsen/logrus" "github.com/pkg/errors" controlapi "github.com/tonistiigi/buildkit_poc/api/services/control" "github.com/tonistiigi/buildkit_poc/client/llb" + "golang.org/x/sync/errgroup" ) func (c *Client) Solve(ctx context.Context, r io.Reader) error { @@ -21,14 +23,40 @@ func (c *Client) Solve(ctx context.Context, r io.Reader) error { return errors.New("invalid empty definition") } - _, err = c.controlClient().Solve(ctx, &controlapi.SolveRequest{ - Ref: generateID(), - Definition: def, + ref := generateID() + eg, ctx := errgroup.WithContext(ctx) + + eg.Go(func() error { + _, err = c.controlClient().Solve(ctx, &controlapi.SolveRequest{ + Ref: ref, + Definition: def, + }) + if err != nil { + return errors.Wrap(err, "failed to solve") + } + return nil }) - if err != nil { - return errors.Wrap(err, "failed to solve") - } - return nil + + eg.Go(func() error { + stream, err := c.controlClient().Status(ctx, &controlapi.StatusRequest{ + Ref: ref, + }) + if err != nil { + return errors.Wrap(err, "failed to get status") + } + for { + resp, err := stream.Recv() + if err != nil { + if err == io.EOF { + return nil + } + return errors.Wrap(err, "failed to receive status") + } + logrus.Debugf("status: %+v", resp) + } + }) + + return eg.Wait() } func generateID() string { diff --git a/control/control.go b/control/control.go index 68f70b42..4403fa70 100644 --- a/control/control.go +++ b/control/control.go @@ -1,14 +1,19 @@ package control import ( + "time" + "github.com/containerd/containerd/snapshot" + digest "github.com/opencontainers/go-digest" "github.com/pkg/errors" controlapi "github.com/tonistiigi/buildkit_poc/api/services/control" "github.com/tonistiigi/buildkit_poc/cache" + "github.com/tonistiigi/buildkit_poc/client" "github.com/tonistiigi/buildkit_poc/solver" "github.com/tonistiigi/buildkit_poc/source" "github.com/tonistiigi/buildkit_poc/worker" "golang.org/x/net/context" + "golang.org/x/sync/errgroup" "google.golang.org/grpc" ) @@ -70,6 +75,53 @@ func (c *Controller) Solve(ctx context.Context, req *controlapi.SolveRequest) (* return &controlapi.SolveResponse{}, nil } -func (c *Controller) Status(*controlapi.StatusRequest, controlapi.Control_StatusServer) error { - return errors.Errorf("not implemented") +func (c *Controller) Status(req *controlapi.StatusRequest, stream controlapi.Control_StatusServer) error { + ch := make(chan *client.SolveStatus, 8) + + eg, ctx := errgroup.WithContext(stream.Context()) + eg.Go(func() error { + return c.solver.Status(ctx, req.Ref, ch) + }) + + eg.Go(func() error { + for { + select { + case <-ctx.Done(): + return ctx.Err() + case ss, ok := <-ch: + if !ok { + return nil + } + sr := controlapi.StatusResponse{} + for _, v := range ss.Vertexes { + sr.Vertexes = append(sr.Vertexes, &controlapi.Vertex{ + ID: v.ID.String(), + Inputs: digestToString(v.Inputs), + Name: v.Name, + Started: marshalTimeStamp(v.Started), + Completed: marshalTimeStamp(v.Completed), + }) + } + if err := stream.SendMsg(&sr); err != nil { + return err + } + } + } + }) + + return eg.Wait() +} + +func digestToString(dgsts []digest.Digest) (out []string) { // TODO: make proto use digest + for _, dgst := range dgsts { + out = append(out, dgst.String()) + } + return +} + +func marshalTimeStamp(tm *time.Time) int64 { + if tm == nil { + return 0 + } + return tm.UnixNano() } diff --git a/solver/jobs.go b/solver/jobs.go new file mode 100644 index 00000000..12d25309 --- /dev/null +++ b/solver/jobs.go @@ -0,0 +1,132 @@ +package solver + +import ( + "context" + "sync" + "time" + + digest "github.com/opencontainers/go-digest" + "github.com/pkg/errors" + "github.com/tonistiigi/buildkit_poc/client" + "github.com/tonistiigi/buildkit_poc/util/progress" +) + +type jobList struct { + mu sync.RWMutex + refs map[string]*job + updateCond *sync.Cond +} + +func newJobList() *jobList { + jl := &jobList{ + refs: make(map[string]*job), + } + jl.updateCond = sync.NewCond(jl.mu.RLocker()) + return jl +} + +func (jl *jobList) new(ctx context.Context, id string, g *opVertex, pr progress.ProgressReader) (*job, error) { + jl.mu.Lock() + defer jl.mu.Unlock() + + if _, ok := jl.refs[id]; ok { + return nil, errors.Errorf("id %s exists", id) + } + j := &job{g: g, pr: progress.NewMultiReader(pr)} + jl.refs[id] = j + jl.updateCond.Broadcast() + go func() { + <-ctx.Done() + jl.mu.Lock() + defer jl.mu.Unlock() + delete(jl.refs, id) + }() + + return jl.refs[id], nil +} + +func (jl *jobList) get(id string) (*job, error) { + ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second) + defer cancel() + + go func() { + <-ctx.Done() + jl.updateCond.Broadcast() + }() + + jl.mu.RLock() + defer jl.mu.RUnlock() + for { + select { + case <-ctx.Done(): + return nil, errors.Errorf("no such job %s", id) + default: + } + j, ok := jl.refs[id] + if !ok { + jl.updateCond.Wait() + continue + } + return j, nil + } +} + +type job struct { + mu sync.Mutex + g *opVertex + pr *progress.MultiReader +} + +func (j *job) pipe(ctx context.Context, ch chan *client.SolveStatus) error { + pr := j.pr.Reader(ctx) + for v := range walk(j.g) { + ss := &client.SolveStatus{ + Vertexes: []*client.Vertex{&v.vtx}, + } + select { + case <-ctx.Done(): + return ctx.Err() + case ch <- ss: + } + } + for { + p, err := pr.Read(ctx) // add cancelling + if err != nil { + return err + } + if p == nil { + return nil + } + switch v := p.Sys.(type) { + case client.Vertex: + ss := &client.SolveStatus{Vertexes: []*client.Vertex{&v}} + select { + case <-ctx.Done(): + return ctx.Err() + case ch <- ss: + } + } + } +} + +func walk(op *opVertex) chan *opVertex { + cache := make(map[digest.Digest]struct{}) + ch := make(chan *opVertex, 32) + + var send func(op *opVertex) + send = func(op *opVertex) { + for _, v := range op.inputs { + send(v) + } + if _, ok := cache[op.dgst]; !ok { + ch <- op + cache[op.dgst] = struct{}{} + } + } + + go func() { + send(op) + close(ch) + }() + return ch +} diff --git a/solver/load.go b/solver/load.go index f8d4b0c5..a624661f 100644 --- a/solver/load.go +++ b/solver/load.go @@ -1,34 +1,12 @@ package solver import ( - "context" - "os" - "strings" - "sync" - "time" - - "golang.org/x/sync/errgroup" - digest "github.com/opencontainers/go-digest" "github.com/pkg/errors" - "github.com/tonistiigi/buildkit_poc/cache" "github.com/tonistiigi/buildkit_poc/client" "github.com/tonistiigi/buildkit_poc/solver/pb" - "github.com/tonistiigi/buildkit_poc/source" - "github.com/tonistiigi/buildkit_poc/util/progress" - "github.com/tonistiigi/buildkit_poc/worker" ) -type opVertex struct { - mu sync.Mutex - op *pb.Op - inputs []*opVertex - refs []cache.ImmutableRef - err error - dgst digest.Digest - vtx client.Vertex -} - func Load(ops [][]byte) (*opVertex, error) { if len(ops) == 0 { return nil, errors.New("invalid empty definition") @@ -90,213 +68,3 @@ func loadReqursive(dgst digest.Digest, op *pb.Op, inputs map[digest.Digest]*pb.O cache[dgst] = vtx return vtx, nil } - -type Opt struct { - SourceManager *source.Manager - CacheManager cache.Manager // TODO: this shouldn't be needed before instruction cache - Worker worker.Worker -} - -func (g *opVertex) inputRequiresExport(i int) bool { - return true // TODO -} - -type Solver struct { - opt Opt - jobs jobs -} - -func New(opt Opt) *Solver { - return &Solver{opt: opt} -} - -func (s *Solver) Solve(ctx context.Context, id string, g *opVertex) error { - // ctx, cancel := context.WithCancel(ctx) - // defer cancel() - - pr, ctx, closeProgressWriter := progress.NewContext(ctx) - - _, err := s.jobs.new(id, g, pr) - if err != nil { - return err - } - - err = g.solve(ctx, s.opt) // TODO: separate exporting - closeProgressWriter() - if err != nil { - return err - } - - g.release(ctx) - // TODO: export final vertex state - return err -} - -func (s *Solver) Status(ctx context.Context, id string, statusChan chan *client.SolveStatus) error { - j, err := s.jobs.get(id) - if err != nil { - return nil - } - return j.pipe(ctx, statusChan) -} - -func (g *opVertex) release(ctx context.Context) (retErr error) { - for _, i := range g.inputs { - if err := i.release(ctx); err != nil { - retErr = err - } - } - for _, ref := range g.refs { - if ref != nil { - if err := ref.Release(ctx); err != nil { - retErr = err - } - } - } - return retErr -} - -func (g *opVertex) getInputRef(i int) cache.ImmutableRef { - input := g.op.Inputs[i] - for _, v := range g.inputs { - if v.dgst == digest.Digest(input.Digest) { - return v.refs[input.Index] - } - } - return nil -} - -func (g *opVertex) solve(ctx context.Context, opt Opt) (retErr error) { - g.mu.Lock() - defer g.mu.Unlock() - - if g.err != nil { - return g.err - } - if len(g.refs) > 0 { - return nil - } - - defer func() { - if retErr != nil { - g.err = retErr - } - }() - - if len(g.inputs) > 0 { - eg, ctx := errgroup.WithContext(ctx) - - for _, in := range g.inputs { - eg.Go(func() error { - if err := in.solve(ctx, opt); err != nil { - return err - } - return nil - }) - } - err := eg.Wait() - if err != nil { - return err - } - } - - pw, _, ctx := progress.FromContext(ctx, g.dgst.String()) - defer pw.Done() - - g.notifyStarted(pw) - defer g.notifyComplete(pw) - - switch op := g.op.Op.(type) { - case *pb.Op_Source: - id, err := source.FromString(op.Source.Identifier) - if err != nil { - return err - } - ref, err := opt.SourceManager.Pull(ctx, id) - if err != nil { - return err - } - g.refs = []cache.ImmutableRef{ref} - case *pb.Op_Exec: - - mounts := make(map[string]cache.Mountable) - - var outputs []cache.MutableRef - - defer func() { - for _, o := range outputs { - if o != nil { - s, err := o.Freeze() // TODO: log error - if err == nil { - s.Release(ctx) - } - } - } - }() - - for _, m := range op.Exec.Mounts { - var mountable cache.Mountable - ref := g.getInputRef(int(m.Input)) - mountable = ref - if m.Output != -1 { - active, err := opt.CacheManager.New(ctx, ref) // TODO: should be method - if err != nil { - return err - } - outputs = append(outputs, active) - mountable = active - } - mounts[m.Dest] = mountable - } - - meta := worker.Meta{ - Args: op.Exec.Meta.Args, - Env: op.Exec.Meta.Env, - Cwd: op.Exec.Meta.Cwd, - } - - if err := opt.Worker.Exec(ctx, meta, mounts, os.Stderr, os.Stderr); err != nil { - return errors.Wrapf(err, "worker failed running %v", meta.Args) - } - - g.refs = []cache.ImmutableRef{} - - for i, o := range outputs { - ref, err := o.ReleaseAndCommit(ctx) - if err != nil { - return errors.Wrapf(err, "error committing %s", ref.ID()) - } - g.refs = append(g.refs, ref) - outputs[i] = nil - } - - default: - return errors.Errorf("invalid op type") - } - return nil -} - -func (g *opVertex) notifyStarted(pw progress.ProgressWriter) { - g.vtx.Started = time.Now() - pw.Write(g.vtx) -} - -func (g *opVertex) notifyComplete(pw progress.ProgressWriter) { - g.vtx.Completed = time.Now() - pw.Write(g.vtx) -} - -func (g *opVertex) name() string { - switch op := g.op.Op.(type) { - case *pb.Op_Source: - return op.Source.Identifier - case *pb.Op_Exec: - name := strings.Join(op.Exec.Meta.Args, " ") - if len(name) > 22 { // TODO: const - name = name[:20] + "..." - } - return name - default: - return "unknown" - } -} diff --git a/solver/run.go b/solver/run.go deleted file mode 100644 index 066d1ae7..00000000 --- a/solver/run.go +++ /dev/null @@ -1,102 +0,0 @@ -package solver - -import ( - "context" - "sync" - - digest "github.com/opencontainers/go-digest" - "github.com/pkg/errors" - "github.com/tonistiigi/buildkit_poc/client" - "github.com/tonistiigi/buildkit_poc/util/progress" -) - -type jobs struct { - mu sync.RWMutex - refs map[string]*job -} - -func (j *jobs) new(id string, g *opVertex, pr progress.ProgressReader) (*job, error) { - j.mu.Lock() - defer j.mu.Unlock() - - if j.refs == nil { - j.refs = make(map[string]*job) - } - if _, ok := j.refs[id]; ok { - return nil, errors.Errorf("id %s exists", id) - } - nj := &job{g: g, pr: progress.NewMultiReader(pr)} - j.refs[id] = nj - - go func() { - j.mu.Lock() - defer j.mu.Unlock() - delete(j.refs, id) - }() - - return j.refs[id], nil -} - -func (j *jobs) get(id string) (*job, error) { - j.mu.RLock() - defer j.mu.RUnlock() - nj, ok := j.refs[id] - if !ok { - return nil, errors.Errorf("no such job %s", id) - } - return nj, nil -} - -type job struct { - mu sync.Mutex - g *opVertex - pr *progress.MultiReader -} - -func (j *job) pipe(ctx context.Context, ch chan *client.SolveStatus) error { - pr := j.pr.Reader(ctx) - for v := range flatten(j.g) { - ss := &client.SolveStatus{ - Vertexes: []*client.Vertex{&v.vtx}, - } - select { - case <-ctx.Done(): - return ctx.Err() - case ch <- ss: - } - } - for { - p, err := pr.Read(ctx) // add cancelling - if err != nil { - return err - } - switch v := p.Sys.(type) { - case *client.Vertex: - ss := &client.SolveStatus{Vertexes: []*client.Vertex{v}} - select { - case <-ctx.Done(): - return ctx.Err() - case ch <- ss: - } - } - } - - return nil -} - -func flatten(op *opVertex) chan *opVertex { - cache := make(map[digest.Digest]struct{}) - ch := make(chan *opVertex, 32) - go sendVertex(ch, op, cache) - return ch -} - -func sendVertex(ch chan *opVertex, op *opVertex, cache map[digest.Digest]struct{}) { - for _, v := range op.inputs { - sendVertex(ch, v, cache) - } - if _, ok := cache[op.dgst]; !ok { - ch <- op - cache[op.dgst] = struct{}{} - } -} diff --git a/solver/solver.go b/solver/solver.go new file mode 100644 index 00000000..c2a7ffd8 --- /dev/null +++ b/solver/solver.go @@ -0,0 +1,242 @@ +package solver + +import ( + "os" + "strings" + "sync" + "time" + + digest "github.com/opencontainers/go-digest" + "github.com/pkg/errors" + "github.com/tonistiigi/buildkit_poc/cache" + "github.com/tonistiigi/buildkit_poc/client" + "github.com/tonistiigi/buildkit_poc/solver/pb" + "github.com/tonistiigi/buildkit_poc/source" + "github.com/tonistiigi/buildkit_poc/util/progress" + "github.com/tonistiigi/buildkit_poc/worker" + "golang.org/x/net/context" + "golang.org/x/sync/errgroup" +) + +type Opt struct { + SourceManager *source.Manager + CacheManager cache.Manager // TODO: this shouldn't be needed before instruction cache + Worker worker.Worker +} + +type Solver struct { + opt Opt + jobs *jobList +} + +func New(opt Opt) *Solver { + return &Solver{opt: opt, jobs: newJobList()} +} + +func (s *Solver) Solve(ctx context.Context, id string, g *opVertex) error { + ctx, cancel := context.WithCancel(ctx) + defer cancel() + + pr, ctx, closeProgressWriter := progress.NewContext(ctx) + + _, err := s.jobs.new(ctx, id, g, pr) + if err != nil { + return err + } + + err = g.solve(ctx, s.opt) // TODO: separate exporting + closeProgressWriter() + if err != nil { + return err + } + + g.release(ctx) + // TODO: export final vertex state + return err +} + +func (s *Solver) Status(ctx context.Context, id string, statusChan chan *client.SolveStatus) error { + j, err := s.jobs.get(id) + if err != nil { + return err + } + defer close(statusChan) + return j.pipe(ctx, statusChan) +} + +type opVertex struct { + mu sync.Mutex + op *pb.Op + inputs []*opVertex + refs []cache.ImmutableRef + err error + dgst digest.Digest + vtx client.Vertex +} + +func (g *opVertex) inputRequiresExport(i int) bool { + return true // TODO +} + +func (g *opVertex) release(ctx context.Context) (retErr error) { + for _, i := range g.inputs { + if err := i.release(ctx); err != nil { + retErr = err + } + } + for _, ref := range g.refs { + if ref != nil { + if err := ref.Release(ctx); err != nil { + retErr = err + } + } + } + return retErr +} + +func (g *opVertex) getInputRef(i int) cache.ImmutableRef { + input := g.op.Inputs[i] + for _, v := range g.inputs { + if v.dgst == digest.Digest(input.Digest) { + return v.refs[input.Index] + } + } + return nil +} + +func (g *opVertex) solve(ctx context.Context, opt Opt) (retErr error) { + g.mu.Lock() + defer g.mu.Unlock() + + if g.err != nil { + return g.err + } + if len(g.refs) > 0 { + return nil + } + + defer func() { + if retErr != nil { + g.err = retErr + } + }() + + if len(g.inputs) > 0 { + eg, ctx := errgroup.WithContext(ctx) + + for _, in := range g.inputs { + eg.Go(func() error { + if err := in.solve(ctx, opt); err != nil { + return err + } + return nil + }) + } + err := eg.Wait() + if err != nil { + return err + } + } + + pw, _, ctx := progress.FromContext(ctx, g.dgst.String()) + defer pw.Done() + + g.notifyStarted(pw) + defer g.notifyComplete(pw) + + switch op := g.op.Op.(type) { + case *pb.Op_Source: + id, err := source.FromString(op.Source.Identifier) + if err != nil { + return err + } + ref, err := opt.SourceManager.Pull(ctx, id) + if err != nil { + return err + } + g.refs = []cache.ImmutableRef{ref} + case *pb.Op_Exec: + + mounts := make(map[string]cache.Mountable) + + var outputs []cache.MutableRef + + defer func() { + for _, o := range outputs { + if o != nil { + s, err := o.Freeze() // TODO: log error + if err == nil { + s.Release(ctx) + } + } + } + }() + + for _, m := range op.Exec.Mounts { + var mountable cache.Mountable + ref := g.getInputRef(int(m.Input)) + mountable = ref + if m.Output != -1 { + active, err := opt.CacheManager.New(ctx, ref) // TODO: should be method + if err != nil { + return err + } + outputs = append(outputs, active) + mountable = active + } + mounts[m.Dest] = mountable + } + + meta := worker.Meta{ + Args: op.Exec.Meta.Args, + Env: op.Exec.Meta.Env, + Cwd: op.Exec.Meta.Cwd, + } + + if err := opt.Worker.Exec(ctx, meta, mounts, os.Stderr, os.Stderr); err != nil { + return errors.Wrapf(err, "worker failed running %v", meta.Args) + } + + g.refs = []cache.ImmutableRef{} + + for i, o := range outputs { + ref, err := o.ReleaseAndCommit(ctx) + if err != nil { + return errors.Wrapf(err, "error committing %s", ref.ID()) + } + g.refs = append(g.refs, ref) + outputs[i] = nil + } + + default: + return errors.Errorf("invalid op type") + } + return nil +} + +func (g *opVertex) notifyStarted(pw progress.ProgressWriter) { + now := time.Now() + g.vtx.Started = &now + pw.Write(g.vtx) +} + +func (g *opVertex) notifyComplete(pw progress.ProgressWriter) { + now := time.Now() + g.vtx.Completed = &now + pw.Write(g.vtx) +} + +func (g *opVertex) name() string { + switch op := g.op.Op.(type) { + case *pb.Op_Source: + return op.Source.Identifier + case *pb.Op_Exec: + name := strings.Join(op.Exec.Meta.Args, " ") + if len(name) > 22 { // TODO: const + name = name[:20] + "..." + } + return name + default: + return "unknown" + } +} diff --git a/util/progress/multireader.go b/util/progress/multireader.go index 69779e23..4af71b56 100644 --- a/util/progress/multireader.go +++ b/util/progress/multireader.go @@ -10,13 +10,14 @@ type MultiReader struct { main ProgressReader initialized bool done chan struct{} - writers map[*progressWriter]struct{} + writers map[*progressWriter]func() } func NewMultiReader(pr ProgressReader) *MultiReader { mr := &MultiReader{ - main: pr, - done: make(chan struct{}), + main: pr, + writers: make(map[*progressWriter]func()), + done: make(chan struct{}), } return mr } @@ -25,11 +26,11 @@ func (mr *MultiReader) Reader(ctx context.Context) ProgressReader { mr.mu.Lock() defer mr.mu.Unlock() - pr, ctx, _ := NewContext(ctx) + pr, ctx, closeWriter := NewContext(ctx) pw, _, _ := FromContext(ctx, "") w := pw.(*progressWriter) - mr.writers[w] = struct{}{} + mr.writers[w] = closeWriter go func() { select { @@ -55,13 +56,17 @@ func (mr *MultiReader) handle() error { if err != nil { return err } + mr.mu.Lock() + for w, c := range mr.writers { + if p == nil { + c() + } else { + w.write(*p) + } + } + mr.mu.Unlock() if p == nil { return nil } - mr.mu.Lock() - for w := range mr.writers { - w.write(*p) - } - mr.mu.Unlock() } } diff --git a/util/progress/progress.go b/util/progress/progress.go index 4874577a..8600c270 100644 --- a/util/progress/progress.go +++ b/util/progress/progress.go @@ -31,7 +31,7 @@ func NewContext(ctx context.Context) (ProgressReader, context.Context, func()) { type ProgressWriter interface { Write(interface{}) error - Done() error + Done() error // Close } type ProgressReader interface { From 177aac40180443e74b3de3f8a1057f55468768f1 Mon Sep 17 00:00:00 2001 From: Tonis Tiigi Date: Tue, 13 Jun 2017 17:40:15 -0700 Subject: [PATCH 3/5] api: fix types in protobuf Signed-off-by: Tonis Tiigi --- api/services/control/control.pb.go | 1069 +++++++--------------------- api/services/control/control.proto | 24 +- api/services/control/generate.go | 4 +- client/graph.go | 4 +- control/control.go | 25 +- solver/load.go | 2 +- 6 files changed, 289 insertions(+), 839 deletions(-) diff --git a/api/services/control/control.pb.go b/api/services/control/control.pb.go index 3ae18914..5a0e7d45 100644 --- a/api/services/control/control.pb.go +++ b/api/services/control/control.pb.go @@ -3,7 +3,7 @@ // DO NOT EDIT! /* - Package control is a generated protocol buffer package. + Package moby_buildkit_v1 is a generated protocol buffer package. It is generated from these files: control.proto @@ -20,28 +20,31 @@ VertexStatus VertexLog */ -package control +package moby_buildkit_v1 import proto "github.com/gogo/protobuf/proto" import fmt "fmt" import math "math" +import _ "github.com/gogo/protobuf/gogoproto" +import _ "github.com/golang/protobuf/ptypes/timestamp" -import bytes "bytes" - -import strings "strings" -import reflect "reflect" +import github_com_opencontainers_go_digest "github.com/opencontainers/go-digest" +import time "time" import ( context "golang.org/x/net/context" grpc "google.golang.org/grpc" ) +import github_com_gogo_protobuf_types "github.com/gogo/protobuf/types" + import io "io" // Reference imports to suppress errors if they are not otherwise used. var _ = proto.Marshal var _ = fmt.Errorf var _ = math.Inf +var _ = time.Kitchen // This is a compile-time assertion to ensure that this generated file // is compatible with the proto package it is being compiled against. @@ -53,6 +56,7 @@ type DiskUsageRequest struct { } func (m *DiskUsageRequest) Reset() { *m = DiskUsageRequest{} } +func (m *DiskUsageRequest) String() string { return proto.CompactTextString(m) } func (*DiskUsageRequest) ProtoMessage() {} func (*DiskUsageRequest) Descriptor() ([]byte, []int) { return fileDescriptorControl, []int{0} } @@ -61,6 +65,7 @@ type DiskUsageResponse struct { } func (m *DiskUsageResponse) Reset() { *m = DiskUsageResponse{} } +func (m *DiskUsageResponse) String() string { return proto.CompactTextString(m) } func (*DiskUsageResponse) ProtoMessage() {} func (*DiskUsageResponse) Descriptor() ([]byte, []int) { return fileDescriptorControl, []int{1} } @@ -79,6 +84,7 @@ type UsageRecord struct { } func (m *UsageRecord) Reset() { *m = UsageRecord{} } +func (m *UsageRecord) String() string { return proto.CompactTextString(m) } func (*UsageRecord) ProtoMessage() {} func (*UsageRecord) Descriptor() ([]byte, []int) { return fileDescriptorControl, []int{2} } @@ -116,6 +122,7 @@ type SolveRequest struct { } func (m *SolveRequest) Reset() { *m = SolveRequest{} } +func (m *SolveRequest) String() string { return proto.CompactTextString(m) } func (*SolveRequest) ProtoMessage() {} func (*SolveRequest) Descriptor() ([]byte, []int) { return fileDescriptorControl, []int{3} } @@ -138,6 +145,7 @@ type SolveResponse struct { } func (m *SolveResponse) Reset() { *m = SolveResponse{} } +func (m *SolveResponse) String() string { return proto.CompactTextString(m) } func (*SolveResponse) ProtoMessage() {} func (*SolveResponse) Descriptor() ([]byte, []int) { return fileDescriptorControl, []int{4} } @@ -153,6 +161,7 @@ type StatusRequest struct { } func (m *StatusRequest) Reset() { *m = StatusRequest{} } +func (m *StatusRequest) String() string { return proto.CompactTextString(m) } func (*StatusRequest) ProtoMessage() {} func (*StatusRequest) Descriptor() ([]byte, []int) { return fileDescriptorControl, []int{5} } @@ -170,6 +179,7 @@ type StatusResponse struct { } func (m *StatusResponse) Reset() { *m = StatusResponse{} } +func (m *StatusResponse) String() string { return proto.CompactTextString(m) } func (*StatusResponse) ProtoMessage() {} func (*StatusResponse) Descriptor() ([]byte, []int) { return fileDescriptorControl, []int{6} } @@ -195,32 +205,19 @@ func (m *StatusResponse) GetLogs() []*VertexLog { } type Vertex struct { - ID string `protobuf:"bytes,1,opt,name=ID,proto3" json:"ID,omitempty"` - Inputs []string `protobuf:"bytes,2,rep,name=inputs" json:"inputs,omitempty"` - Name string `protobuf:"bytes,3,opt,name=name,proto3" json:"name,omitempty"` - Cached bool `protobuf:"varint,4,opt,name=cached,proto3" json:"cached,omitempty"` - Started int64 `protobuf:"varint,5,opt,name=started,proto3" json:"started,omitempty"` - Completed int64 `protobuf:"varint,6,opt,name=completed,proto3" json:"completed,omitempty"` + Digest github_com_opencontainers_go_digest.Digest `protobuf:"bytes,1,opt,name=digest,proto3,customtype=github.com/opencontainers/go-digest.Digest" json:"digest"` + Inputs []github_com_opencontainers_go_digest.Digest `protobuf:"bytes,2,rep,name=inputs,customtype=github.com/opencontainers/go-digest.Digest" json:"inputs"` + Name string `protobuf:"bytes,3,opt,name=name,proto3" json:"name,omitempty"` + Cached bool `protobuf:"varint,4,opt,name=cached,proto3" json:"cached,omitempty"` + Started *time.Time `protobuf:"bytes,5,opt,name=started,stdtime" json:"started,omitempty"` + Completed *time.Time `protobuf:"bytes,6,opt,name=completed,stdtime" json:"completed,omitempty"` } func (m *Vertex) Reset() { *m = Vertex{} } +func (m *Vertex) String() string { return proto.CompactTextString(m) } func (*Vertex) ProtoMessage() {} func (*Vertex) Descriptor() ([]byte, []int) { return fileDescriptorControl, []int{7} } -func (m *Vertex) GetID() string { - if m != nil { - return m.ID - } - return "" -} - -func (m *Vertex) GetInputs() []string { - if m != nil { - return m.Inputs - } - return nil -} - func (m *Vertex) GetName() string { if m != nil { return m.Name @@ -235,29 +232,31 @@ func (m *Vertex) GetCached() bool { return false } -func (m *Vertex) GetStarted() int64 { +func (m *Vertex) GetStarted() *time.Time { if m != nil { return m.Started } - return 0 + return nil } -func (m *Vertex) GetCompleted() int64 { +func (m *Vertex) GetCompleted() *time.Time { if m != nil { return m.Completed } - return 0 + return nil } type VertexStatus struct { - ID string `protobuf:"bytes,1,opt,name=ID,proto3" json:"ID,omitempty"` - Vertex string `protobuf:"bytes,2,opt,name=vertex,proto3" json:"vertex,omitempty"` - Name string `protobuf:"bytes,3,opt,name=name,proto3" json:"name,omitempty"` - Current int64 `protobuf:"varint,4,opt,name=current,proto3" json:"current,omitempty"` - Total int64 `protobuf:"varint,5,opt,name=total,proto3" json:"total,omitempty"` + ID string `protobuf:"bytes,1,opt,name=ID,proto3" json:"ID,omitempty"` + Vertex github_com_opencontainers_go_digest.Digest `protobuf:"bytes,2,opt,name=vertex,proto3,customtype=github.com/opencontainers/go-digest.Digest" json:"vertex"` + Name string `protobuf:"bytes,3,opt,name=name,proto3" json:"name,omitempty"` + Current int64 `protobuf:"varint,4,opt,name=current,proto3" json:"current,omitempty"` + Total int64 `protobuf:"varint,5,opt,name=total,proto3" json:"total,omitempty"` + Timestamp time.Time `protobuf:"bytes,6,opt,name=timestamp,stdtime" json:"timestamp"` } func (m *VertexStatus) Reset() { *m = VertexStatus{} } +func (m *VertexStatus) String() string { return proto.CompactTextString(m) } func (*VertexStatus) ProtoMessage() {} func (*VertexStatus) Descriptor() ([]byte, []int) { return fileDescriptorControl, []int{8} } @@ -268,13 +267,6 @@ func (m *VertexStatus) GetID() string { return "" } -func (m *VertexStatus) GetVertex() string { - if m != nil { - return m.Vertex - } - return "" -} - func (m *VertexStatus) GetName() string { if m != nil { return m.Name @@ -296,29 +288,30 @@ func (m *VertexStatus) GetTotal() int64 { return 0 } -type VertexLog struct { - Inc int64 `protobuf:"varint,1,opt,name=inc,proto3" json:"inc,omitempty"` - Timestamp int64 `protobuf:"varint,2,opt,name=timestamp,proto3" json:"timestamp,omitempty"` - Stream int64 `protobuf:"varint,3,opt,name=stream,proto3" json:"stream,omitempty"` - Msg []byte `protobuf:"bytes,4,opt,name=msg,proto3" json:"msg,omitempty"` -} - -func (m *VertexLog) Reset() { *m = VertexLog{} } -func (*VertexLog) ProtoMessage() {} -func (*VertexLog) Descriptor() ([]byte, []int) { return fileDescriptorControl, []int{9} } - -func (m *VertexLog) GetInc() int64 { - if m != nil { - return m.Inc - } - return 0 -} - -func (m *VertexLog) GetTimestamp() int64 { +func (m *VertexStatus) GetTimestamp() time.Time { if m != nil { return m.Timestamp } - return 0 + return time.Time{} +} + +type VertexLog struct { + Vertex github_com_opencontainers_go_digest.Digest `protobuf:"bytes,1,opt,name=vertex,proto3,customtype=github.com/opencontainers/go-digest.Digest" json:"vertex"` + Timestamp time.Time `protobuf:"bytes,2,opt,name=timestamp,stdtime" json:"timestamp"` + Stream int64 `protobuf:"varint,3,opt,name=stream,proto3" json:"stream,omitempty"` + Msg []byte `protobuf:"bytes,4,opt,name=msg,proto3" json:"msg,omitempty"` +} + +func (m *VertexLog) Reset() { *m = VertexLog{} } +func (m *VertexLog) String() string { return proto.CompactTextString(m) } +func (*VertexLog) ProtoMessage() {} +func (*VertexLog) Descriptor() ([]byte, []int) { return fileDescriptorControl, []int{9} } + +func (m *VertexLog) GetTimestamp() time.Time { + if m != nil { + return m.Timestamp + } + return time.Time{} } func (m *VertexLog) GetStream() int64 { @@ -336,537 +329,16 @@ func (m *VertexLog) GetMsg() []byte { } func init() { - proto.RegisterType((*DiskUsageRequest)(nil), "control.DiskUsageRequest") - proto.RegisterType((*DiskUsageResponse)(nil), "control.DiskUsageResponse") - proto.RegisterType((*UsageRecord)(nil), "control.UsageRecord") - proto.RegisterType((*SolveRequest)(nil), "control.SolveRequest") - proto.RegisterType((*SolveResponse)(nil), "control.SolveResponse") - proto.RegisterType((*StatusRequest)(nil), "control.StatusRequest") - proto.RegisterType((*StatusResponse)(nil), "control.StatusResponse") - proto.RegisterType((*Vertex)(nil), "control.Vertex") - proto.RegisterType((*VertexStatus)(nil), "control.VertexStatus") - proto.RegisterType((*VertexLog)(nil), "control.VertexLog") -} -func (this *DiskUsageRequest) Equal(that interface{}) bool { - if that == nil { - if this == nil { - return true - } - return false - } - - that1, ok := that.(*DiskUsageRequest) - if !ok { - that2, ok := that.(DiskUsageRequest) - if ok { - that1 = &that2 - } else { - return false - } - } - if that1 == nil { - if this == nil { - return true - } - return false - } else if this == nil { - return false - } - return true -} -func (this *DiskUsageResponse) Equal(that interface{}) bool { - if that == nil { - if this == nil { - return true - } - return false - } - - that1, ok := that.(*DiskUsageResponse) - if !ok { - that2, ok := that.(DiskUsageResponse) - if ok { - that1 = &that2 - } else { - return false - } - } - if that1 == nil { - if this == nil { - return true - } - return false - } else if this == nil { - return false - } - if len(this.Record) != len(that1.Record) { - return false - } - for i := range this.Record { - if !this.Record[i].Equal(that1.Record[i]) { - return false - } - } - return true -} -func (this *UsageRecord) Equal(that interface{}) bool { - if that == nil { - if this == nil { - return true - } - return false - } - - that1, ok := that.(*UsageRecord) - if !ok { - that2, ok := that.(UsageRecord) - if ok { - that1 = &that2 - } else { - return false - } - } - if that1 == nil { - if this == nil { - return true - } - return false - } else if this == nil { - return false - } - if this.ID != that1.ID { - return false - } - if this.Mutable != that1.Mutable { - return false - } - if this.InUse != that1.InUse { - return false - } - if this.Size_ != that1.Size_ { - return false - } - return true -} -func (this *SolveRequest) Equal(that interface{}) bool { - if that == nil { - if this == nil { - return true - } - return false - } - - that1, ok := that.(*SolveRequest) - if !ok { - that2, ok := that.(SolveRequest) - if ok { - that1 = &that2 - } else { - return false - } - } - if that1 == nil { - if this == nil { - return true - } - return false - } else if this == nil { - return false - } - if this.Ref != that1.Ref { - return false - } - if len(this.Definition) != len(that1.Definition) { - return false - } - for i := range this.Definition { - if !bytes.Equal(this.Definition[i], that1.Definition[i]) { - return false - } - } - return true -} -func (this *SolveResponse) Equal(that interface{}) bool { - if that == nil { - if this == nil { - return true - } - return false - } - - that1, ok := that.(*SolveResponse) - if !ok { - that2, ok := that.(SolveResponse) - if ok { - that1 = &that2 - } else { - return false - } - } - if that1 == nil { - if this == nil { - return true - } - return false - } else if this == nil { - return false - } - if len(this.Vtx) != len(that1.Vtx) { - return false - } - for i := range this.Vtx { - if !this.Vtx[i].Equal(that1.Vtx[i]) { - return false - } - } - return true -} -func (this *StatusRequest) Equal(that interface{}) bool { - if that == nil { - if this == nil { - return true - } - return false - } - - that1, ok := that.(*StatusRequest) - if !ok { - that2, ok := that.(StatusRequest) - if ok { - that1 = &that2 - } else { - return false - } - } - if that1 == nil { - if this == nil { - return true - } - return false - } else if this == nil { - return false - } - if this.Ref != that1.Ref { - return false - } - return true -} -func (this *StatusResponse) Equal(that interface{}) bool { - if that == nil { - if this == nil { - return true - } - return false - } - - that1, ok := that.(*StatusResponse) - if !ok { - that2, ok := that.(StatusResponse) - if ok { - that1 = &that2 - } else { - return false - } - } - if that1 == nil { - if this == nil { - return true - } - return false - } else if this == nil { - return false - } - if len(this.Vertexes) != len(that1.Vertexes) { - return false - } - for i := range this.Vertexes { - if !this.Vertexes[i].Equal(that1.Vertexes[i]) { - return false - } - } - if len(this.Statuses) != len(that1.Statuses) { - return false - } - for i := range this.Statuses { - if !this.Statuses[i].Equal(that1.Statuses[i]) { - return false - } - } - if len(this.Logs) != len(that1.Logs) { - return false - } - for i := range this.Logs { - if !this.Logs[i].Equal(that1.Logs[i]) { - return false - } - } - return true -} -func (this *Vertex) Equal(that interface{}) bool { - if that == nil { - if this == nil { - return true - } - return false - } - - that1, ok := that.(*Vertex) - if !ok { - that2, ok := that.(Vertex) - if ok { - that1 = &that2 - } else { - return false - } - } - if that1 == nil { - if this == nil { - return true - } - return false - } else if this == nil { - return false - } - if this.ID != that1.ID { - return false - } - if len(this.Inputs) != len(that1.Inputs) { - return false - } - for i := range this.Inputs { - if this.Inputs[i] != that1.Inputs[i] { - return false - } - } - if this.Name != that1.Name { - return false - } - if this.Cached != that1.Cached { - return false - } - if this.Started != that1.Started { - return false - } - if this.Completed != that1.Completed { - return false - } - return true -} -func (this *VertexStatus) Equal(that interface{}) bool { - if that == nil { - if this == nil { - return true - } - return false - } - - that1, ok := that.(*VertexStatus) - if !ok { - that2, ok := that.(VertexStatus) - if ok { - that1 = &that2 - } else { - return false - } - } - if that1 == nil { - if this == nil { - return true - } - return false - } else if this == nil { - return false - } - if this.ID != that1.ID { - return false - } - if this.Vertex != that1.Vertex { - return false - } - if this.Name != that1.Name { - return false - } - if this.Current != that1.Current { - return false - } - if this.Total != that1.Total { - return false - } - return true -} -func (this *VertexLog) Equal(that interface{}) bool { - if that == nil { - if this == nil { - return true - } - return false - } - - that1, ok := that.(*VertexLog) - if !ok { - that2, ok := that.(VertexLog) - if ok { - that1 = &that2 - } else { - return false - } - } - if that1 == nil { - if this == nil { - return true - } - return false - } else if this == nil { - return false - } - if this.Inc != that1.Inc { - return false - } - if this.Timestamp != that1.Timestamp { - return false - } - if this.Stream != that1.Stream { - return false - } - if !bytes.Equal(this.Msg, that1.Msg) { - return false - } - return true -} -func (this *DiskUsageRequest) GoString() string { - if this == nil { - return "nil" - } - s := make([]string, 0, 4) - s = append(s, "&control.DiskUsageRequest{") - s = append(s, "}") - return strings.Join(s, "") -} -func (this *DiskUsageResponse) GoString() string { - if this == nil { - return "nil" - } - s := make([]string, 0, 5) - s = append(s, "&control.DiskUsageResponse{") - if this.Record != nil { - s = append(s, "Record: "+fmt.Sprintf("%#v", this.Record)+",\n") - } - s = append(s, "}") - return strings.Join(s, "") -} -func (this *UsageRecord) GoString() string { - if this == nil { - return "nil" - } - s := make([]string, 0, 8) - s = append(s, "&control.UsageRecord{") - s = append(s, "ID: "+fmt.Sprintf("%#v", this.ID)+",\n") - s = append(s, "Mutable: "+fmt.Sprintf("%#v", this.Mutable)+",\n") - s = append(s, "InUse: "+fmt.Sprintf("%#v", this.InUse)+",\n") - s = append(s, "Size_: "+fmt.Sprintf("%#v", this.Size_)+",\n") - s = append(s, "}") - return strings.Join(s, "") -} -func (this *SolveRequest) GoString() string { - if this == nil { - return "nil" - } - s := make([]string, 0, 6) - s = append(s, "&control.SolveRequest{") - s = append(s, "Ref: "+fmt.Sprintf("%#v", this.Ref)+",\n") - s = append(s, "Definition: "+fmt.Sprintf("%#v", this.Definition)+",\n") - s = append(s, "}") - return strings.Join(s, "") -} -func (this *SolveResponse) GoString() string { - if this == nil { - return "nil" - } - s := make([]string, 0, 5) - s = append(s, "&control.SolveResponse{") - if this.Vtx != nil { - s = append(s, "Vtx: "+fmt.Sprintf("%#v", this.Vtx)+",\n") - } - s = append(s, "}") - return strings.Join(s, "") -} -func (this *StatusRequest) GoString() string { - if this == nil { - return "nil" - } - s := make([]string, 0, 5) - s = append(s, "&control.StatusRequest{") - s = append(s, "Ref: "+fmt.Sprintf("%#v", this.Ref)+",\n") - s = append(s, "}") - return strings.Join(s, "") -} -func (this *StatusResponse) GoString() string { - if this == nil { - return "nil" - } - s := make([]string, 0, 7) - s = append(s, "&control.StatusResponse{") - if this.Vertexes != nil { - s = append(s, "Vertexes: "+fmt.Sprintf("%#v", this.Vertexes)+",\n") - } - if this.Statuses != nil { - s = append(s, "Statuses: "+fmt.Sprintf("%#v", this.Statuses)+",\n") - } - if this.Logs != nil { - s = append(s, "Logs: "+fmt.Sprintf("%#v", this.Logs)+",\n") - } - s = append(s, "}") - return strings.Join(s, "") -} -func (this *Vertex) GoString() string { - if this == nil { - return "nil" - } - s := make([]string, 0, 10) - s = append(s, "&control.Vertex{") - s = append(s, "ID: "+fmt.Sprintf("%#v", this.ID)+",\n") - s = append(s, "Inputs: "+fmt.Sprintf("%#v", this.Inputs)+",\n") - s = append(s, "Name: "+fmt.Sprintf("%#v", this.Name)+",\n") - s = append(s, "Cached: "+fmt.Sprintf("%#v", this.Cached)+",\n") - s = append(s, "Started: "+fmt.Sprintf("%#v", this.Started)+",\n") - s = append(s, "Completed: "+fmt.Sprintf("%#v", this.Completed)+",\n") - s = append(s, "}") - return strings.Join(s, "") -} -func (this *VertexStatus) GoString() string { - if this == nil { - return "nil" - } - s := make([]string, 0, 9) - s = append(s, "&control.VertexStatus{") - s = append(s, "ID: "+fmt.Sprintf("%#v", this.ID)+",\n") - s = append(s, "Vertex: "+fmt.Sprintf("%#v", this.Vertex)+",\n") - s = append(s, "Name: "+fmt.Sprintf("%#v", this.Name)+",\n") - s = append(s, "Current: "+fmt.Sprintf("%#v", this.Current)+",\n") - s = append(s, "Total: "+fmt.Sprintf("%#v", this.Total)+",\n") - s = append(s, "}") - return strings.Join(s, "") -} -func (this *VertexLog) GoString() string { - if this == nil { - return "nil" - } - s := make([]string, 0, 8) - s = append(s, "&control.VertexLog{") - s = append(s, "Inc: "+fmt.Sprintf("%#v", this.Inc)+",\n") - s = append(s, "Timestamp: "+fmt.Sprintf("%#v", this.Timestamp)+",\n") - s = append(s, "Stream: "+fmt.Sprintf("%#v", this.Stream)+",\n") - s = append(s, "Msg: "+fmt.Sprintf("%#v", this.Msg)+",\n") - s = append(s, "}") - return strings.Join(s, "") -} -func valueToGoStringControl(v interface{}, typ string) string { - rv := reflect.ValueOf(v) - if rv.IsNil() { - return "nil" - } - pv := reflect.Indirect(rv).Interface() - return fmt.Sprintf("func(v %v) *%v { return &v } ( %#v )", typ, typ, pv) + proto.RegisterType((*DiskUsageRequest)(nil), "moby.buildkit.v1.DiskUsageRequest") + proto.RegisterType((*DiskUsageResponse)(nil), "moby.buildkit.v1.DiskUsageResponse") + proto.RegisterType((*UsageRecord)(nil), "moby.buildkit.v1.UsageRecord") + proto.RegisterType((*SolveRequest)(nil), "moby.buildkit.v1.SolveRequest") + proto.RegisterType((*SolveResponse)(nil), "moby.buildkit.v1.SolveResponse") + proto.RegisterType((*StatusRequest)(nil), "moby.buildkit.v1.StatusRequest") + proto.RegisterType((*StatusResponse)(nil), "moby.buildkit.v1.StatusResponse") + proto.RegisterType((*Vertex)(nil), "moby.buildkit.v1.Vertex") + proto.RegisterType((*VertexStatus)(nil), "moby.buildkit.v1.VertexStatus") + proto.RegisterType((*VertexLog)(nil), "moby.buildkit.v1.VertexLog") } // Reference imports to suppress errors if they are not otherwise used. @@ -895,7 +367,7 @@ func NewControlClient(cc *grpc.ClientConn) ControlClient { func (c *controlClient) DiskUsage(ctx context.Context, in *DiskUsageRequest, opts ...grpc.CallOption) (*DiskUsageResponse, error) { out := new(DiskUsageResponse) - err := grpc.Invoke(ctx, "/control.Control/DiskUsage", in, out, c.cc, opts...) + err := grpc.Invoke(ctx, "/moby.buildkit.v1.Control/DiskUsage", in, out, c.cc, opts...) if err != nil { return nil, err } @@ -904,7 +376,7 @@ func (c *controlClient) DiskUsage(ctx context.Context, in *DiskUsageRequest, opt func (c *controlClient) Solve(ctx context.Context, in *SolveRequest, opts ...grpc.CallOption) (*SolveResponse, error) { out := new(SolveResponse) - err := grpc.Invoke(ctx, "/control.Control/Solve", in, out, c.cc, opts...) + err := grpc.Invoke(ctx, "/moby.buildkit.v1.Control/Solve", in, out, c.cc, opts...) if err != nil { return nil, err } @@ -912,7 +384,7 @@ func (c *controlClient) Solve(ctx context.Context, in *SolveRequest, opts ...grp } func (c *controlClient) Status(ctx context.Context, in *StatusRequest, opts ...grpc.CallOption) (Control_StatusClient, error) { - stream, err := grpc.NewClientStream(ctx, &_Control_serviceDesc.Streams[0], c.cc, "/control.Control/Status", opts...) + stream, err := grpc.NewClientStream(ctx, &_Control_serviceDesc.Streams[0], c.cc, "/moby.buildkit.v1.Control/Status", opts...) if err != nil { return nil, err } @@ -965,7 +437,7 @@ func _Control_DiskUsage_Handler(srv interface{}, ctx context.Context, dec func(i } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: "/control.Control/DiskUsage", + FullMethod: "/moby.buildkit.v1.Control/DiskUsage", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(ControlServer).DiskUsage(ctx, req.(*DiskUsageRequest)) @@ -983,7 +455,7 @@ func _Control_Solve_Handler(srv interface{}, ctx context.Context, dec func(inter } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: "/control.Control/Solve", + FullMethod: "/moby.buildkit.v1.Control/Solve", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(ControlServer).Solve(ctx, req.(*SolveRequest)) @@ -1013,7 +485,7 @@ func (x *controlStatusServer) Send(m *StatusResponse) error { } var _Control_serviceDesc = grpc.ServiceDesc{ - ServiceName: "control.Control", + ServiceName: "moby.buildkit.v1.Control", HandlerType: (*ControlServer)(nil), Methods: []grpc.MethodDesc{ { @@ -1287,11 +759,11 @@ func (m *Vertex) MarshalTo(dAtA []byte) (int, error) { _ = i var l int _ = l - if len(m.ID) > 0 { + if len(m.Digest) > 0 { dAtA[i] = 0xa i++ - i = encodeVarintControl(dAtA, i, uint64(len(m.ID))) - i += copy(dAtA[i:], m.ID) + i = encodeVarintControl(dAtA, i, uint64(len(m.Digest))) + i += copy(dAtA[i:], m.Digest) } if len(m.Inputs) > 0 { for _, s := range m.Inputs { @@ -1324,15 +796,25 @@ func (m *Vertex) MarshalTo(dAtA []byte) (int, error) { } i++ } - if m.Started != 0 { - dAtA[i] = 0x28 + if m.Started != nil { + dAtA[i] = 0x2a i++ - i = encodeVarintControl(dAtA, i, uint64(m.Started)) + i = encodeVarintControl(dAtA, i, uint64(github_com_gogo_protobuf_types.SizeOfStdTime(*m.Started))) + n1, err := github_com_gogo_protobuf_types.StdTimeMarshalTo(*m.Started, dAtA[i:]) + if err != nil { + return 0, err + } + i += n1 } - if m.Completed != 0 { - dAtA[i] = 0x30 + if m.Completed != nil { + dAtA[i] = 0x32 i++ - i = encodeVarintControl(dAtA, i, uint64(m.Completed)) + i = encodeVarintControl(dAtA, i, uint64(github_com_gogo_protobuf_types.SizeOfStdTime(*m.Completed))) + n2, err := github_com_gogo_protobuf_types.StdTimeMarshalTo(*m.Completed, dAtA[i:]) + if err != nil { + return 0, err + } + i += n2 } return i, nil } @@ -1380,6 +862,14 @@ func (m *VertexStatus) MarshalTo(dAtA []byte) (int, error) { i++ i = encodeVarintControl(dAtA, i, uint64(m.Total)) } + dAtA[i] = 0x32 + i++ + i = encodeVarintControl(dAtA, i, uint64(github_com_gogo_protobuf_types.SizeOfStdTime(m.Timestamp))) + n3, err := github_com_gogo_protobuf_types.StdTimeMarshalTo(m.Timestamp, dAtA[i:]) + if err != nil { + return 0, err + } + i += n3 return i, nil } @@ -1398,16 +888,20 @@ func (m *VertexLog) MarshalTo(dAtA []byte) (int, error) { _ = i var l int _ = l - if m.Inc != 0 { - dAtA[i] = 0x8 + if len(m.Vertex) > 0 { + dAtA[i] = 0xa i++ - i = encodeVarintControl(dAtA, i, uint64(m.Inc)) + i = encodeVarintControl(dAtA, i, uint64(len(m.Vertex))) + i += copy(dAtA[i:], m.Vertex) } - if m.Timestamp != 0 { - dAtA[i] = 0x10 - i++ - i = encodeVarintControl(dAtA, i, uint64(m.Timestamp)) + dAtA[i] = 0x12 + i++ + i = encodeVarintControl(dAtA, i, uint64(github_com_gogo_protobuf_types.SizeOfStdTime(m.Timestamp))) + n4, err := github_com_gogo_protobuf_types.StdTimeMarshalTo(m.Timestamp, dAtA[i:]) + if err != nil { + return 0, err } + i += n4 if m.Stream != 0 { dAtA[i] = 0x18 i++ @@ -1551,7 +1045,7 @@ func (m *StatusResponse) Size() (n int) { func (m *Vertex) Size() (n int) { var l int _ = l - l = len(m.ID) + l = len(m.Digest) if l > 0 { n += 1 + l + sovControl(uint64(l)) } @@ -1568,11 +1062,13 @@ func (m *Vertex) Size() (n int) { if m.Cached { n += 2 } - if m.Started != 0 { - n += 1 + sovControl(uint64(m.Started)) + if m.Started != nil { + l = github_com_gogo_protobuf_types.SizeOfStdTime(*m.Started) + n += 1 + l + sovControl(uint64(l)) } - if m.Completed != 0 { - n += 1 + sovControl(uint64(m.Completed)) + if m.Completed != nil { + l = github_com_gogo_protobuf_types.SizeOfStdTime(*m.Completed) + n += 1 + l + sovControl(uint64(l)) } return n } @@ -1598,18 +1094,20 @@ func (m *VertexStatus) Size() (n int) { if m.Total != 0 { n += 1 + sovControl(uint64(m.Total)) } + l = github_com_gogo_protobuf_types.SizeOfStdTime(m.Timestamp) + n += 1 + l + sovControl(uint64(l)) return n } func (m *VertexLog) Size() (n int) { var l int _ = l - if m.Inc != 0 { - n += 1 + sovControl(uint64(m.Inc)) - } - if m.Timestamp != 0 { - n += 1 + sovControl(uint64(m.Timestamp)) + l = len(m.Vertex) + if l > 0 { + n += 1 + l + sovControl(uint64(l)) } + l = github_com_gogo_protobuf_types.SizeOfStdTime(m.Timestamp) + n += 1 + l + sovControl(uint64(l)) if m.Stream != 0 { n += 1 + sovControl(uint64(m.Stream)) } @@ -1633,131 +1131,6 @@ func sovControl(x uint64) (n int) { func sozControl(x uint64) (n int) { return sovControl(uint64((x << 1) ^ uint64((int64(x) >> 63)))) } -func (this *DiskUsageRequest) String() string { - if this == nil { - return "nil" - } - s := strings.Join([]string{`&DiskUsageRequest{`, - `}`, - }, "") - return s -} -func (this *DiskUsageResponse) String() string { - if this == nil { - return "nil" - } - s := strings.Join([]string{`&DiskUsageResponse{`, - `Record:` + strings.Replace(fmt.Sprintf("%v", this.Record), "UsageRecord", "UsageRecord", 1) + `,`, - `}`, - }, "") - return s -} -func (this *UsageRecord) String() string { - if this == nil { - return "nil" - } - s := strings.Join([]string{`&UsageRecord{`, - `ID:` + fmt.Sprintf("%v", this.ID) + `,`, - `Mutable:` + fmt.Sprintf("%v", this.Mutable) + `,`, - `InUse:` + fmt.Sprintf("%v", this.InUse) + `,`, - `Size_:` + fmt.Sprintf("%v", this.Size_) + `,`, - `}`, - }, "") - return s -} -func (this *SolveRequest) String() string { - if this == nil { - return "nil" - } - s := strings.Join([]string{`&SolveRequest{`, - `Ref:` + fmt.Sprintf("%v", this.Ref) + `,`, - `Definition:` + fmt.Sprintf("%v", this.Definition) + `,`, - `}`, - }, "") - return s -} -func (this *SolveResponse) String() string { - if this == nil { - return "nil" - } - s := strings.Join([]string{`&SolveResponse{`, - `Vtx:` + strings.Replace(fmt.Sprintf("%v", this.Vtx), "Vertex", "Vertex", 1) + `,`, - `}`, - }, "") - return s -} -func (this *StatusRequest) String() string { - if this == nil { - return "nil" - } - s := strings.Join([]string{`&StatusRequest{`, - `Ref:` + fmt.Sprintf("%v", this.Ref) + `,`, - `}`, - }, "") - return s -} -func (this *StatusResponse) String() string { - if this == nil { - return "nil" - } - s := strings.Join([]string{`&StatusResponse{`, - `Vertexes:` + strings.Replace(fmt.Sprintf("%v", this.Vertexes), "Vertex", "Vertex", 1) + `,`, - `Statuses:` + strings.Replace(fmt.Sprintf("%v", this.Statuses), "VertexStatus", "VertexStatus", 1) + `,`, - `Logs:` + strings.Replace(fmt.Sprintf("%v", this.Logs), "VertexLog", "VertexLog", 1) + `,`, - `}`, - }, "") - return s -} -func (this *Vertex) String() string { - if this == nil { - return "nil" - } - s := strings.Join([]string{`&Vertex{`, - `ID:` + fmt.Sprintf("%v", this.ID) + `,`, - `Inputs:` + fmt.Sprintf("%v", this.Inputs) + `,`, - `Name:` + fmt.Sprintf("%v", this.Name) + `,`, - `Cached:` + fmt.Sprintf("%v", this.Cached) + `,`, - `Started:` + fmt.Sprintf("%v", this.Started) + `,`, - `Completed:` + fmt.Sprintf("%v", this.Completed) + `,`, - `}`, - }, "") - return s -} -func (this *VertexStatus) String() string { - if this == nil { - return "nil" - } - s := strings.Join([]string{`&VertexStatus{`, - `ID:` + fmt.Sprintf("%v", this.ID) + `,`, - `Vertex:` + fmt.Sprintf("%v", this.Vertex) + `,`, - `Name:` + fmt.Sprintf("%v", this.Name) + `,`, - `Current:` + fmt.Sprintf("%v", this.Current) + `,`, - `Total:` + fmt.Sprintf("%v", this.Total) + `,`, - `}`, - }, "") - return s -} -func (this *VertexLog) String() string { - if this == nil { - return "nil" - } - s := strings.Join([]string{`&VertexLog{`, - `Inc:` + fmt.Sprintf("%v", this.Inc) + `,`, - `Timestamp:` + fmt.Sprintf("%v", this.Timestamp) + `,`, - `Stream:` + fmt.Sprintf("%v", this.Stream) + `,`, - `Msg:` + fmt.Sprintf("%v", this.Msg) + `,`, - `}`, - }, "") - return s -} -func valueToStringControl(v interface{}) string { - rv := reflect.ValueOf(v) - if rv.IsNil() { - return "nil" - } - pv := reflect.Indirect(rv).Interface() - return fmt.Sprintf("*%v", pv) -} func (m *DiskUsageRequest) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 @@ -2469,7 +1842,7 @@ func (m *Vertex) Unmarshal(dAtA []byte) error { switch fieldNum { case 1: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ID", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field Digest", wireType) } var stringLen uint64 for shift := uint(0); ; shift += 7 { @@ -2494,7 +1867,7 @@ func (m *Vertex) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - m.ID = string(dAtA[iNdEx:postIndex]) + m.Digest = github_com_opencontainers_go_digest.Digest(dAtA[iNdEx:postIndex]) iNdEx = postIndex case 2: if wireType != 2 { @@ -2523,7 +1896,7 @@ func (m *Vertex) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - m.Inputs = append(m.Inputs, string(dAtA[iNdEx:postIndex])) + m.Inputs = append(m.Inputs, github_com_opencontainers_go_digest.Digest(dAtA[iNdEx:postIndex])) iNdEx = postIndex case 3: if wireType != 2 { @@ -2575,10 +1948,10 @@ func (m *Vertex) Unmarshal(dAtA []byte) error { } m.Cached = bool(v != 0) case 5: - if wireType != 0 { + if wireType != 2 { return fmt.Errorf("proto: wrong wireType = %d for field Started", wireType) } - m.Started = 0 + var msglen int for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflowControl @@ -2588,16 +1961,30 @@ func (m *Vertex) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - m.Started |= (int64(b) & 0x7F) << shift + msglen |= (int(b) & 0x7F) << shift if b < 0x80 { break } } + if msglen < 0 { + return ErrInvalidLengthControl + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Started == nil { + m.Started = new(time.Time) + } + if err := github_com_gogo_protobuf_types.StdTimeUnmarshal(m.Started, dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex case 6: - if wireType != 0 { + if wireType != 2 { return fmt.Errorf("proto: wrong wireType = %d for field Completed", wireType) } - m.Completed = 0 + var msglen int for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflowControl @@ -2607,11 +1994,25 @@ func (m *Vertex) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - m.Completed |= (int64(b) & 0x7F) << shift + msglen |= (int(b) & 0x7F) << shift if b < 0x80 { break } } + if msglen < 0 { + return ErrInvalidLengthControl + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Completed == nil { + m.Completed = new(time.Time) + } + if err := github_com_gogo_protobuf_types.StdTimeUnmarshal(m.Completed, dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipControl(dAtA[iNdEx:]) @@ -2718,7 +2119,7 @@ func (m *VertexStatus) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - m.Vertex = string(dAtA[iNdEx:postIndex]) + m.Vertex = github_com_opencontainers_go_digest.Digest(dAtA[iNdEx:postIndex]) iNdEx = postIndex case 3: if wireType != 2 { @@ -2787,6 +2188,36 @@ func (m *VertexStatus) Unmarshal(dAtA []byte) error { break } } + case 6: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Timestamp", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowControl + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthControl + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := github_com_gogo_protobuf_types.StdTimeUnmarshal(&m.Timestamp, dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipControl(dAtA[iNdEx:]) @@ -2838,10 +2269,10 @@ func (m *VertexLog) Unmarshal(dAtA []byte) error { } switch fieldNum { case 1: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field Inc", wireType) + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Vertex", wireType) } - m.Inc = 0 + var stringLen uint64 for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflowControl @@ -2851,16 +2282,26 @@ func (m *VertexLog) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - m.Inc |= (int64(b) & 0x7F) << shift + stringLen |= (uint64(b) & 0x7F) << shift if b < 0x80 { break } } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthControl + } + postIndex := iNdEx + intStringLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Vertex = github_com_opencontainers_go_digest.Digest(dAtA[iNdEx:postIndex]) + iNdEx = postIndex case 2: - if wireType != 0 { + if wireType != 2 { return fmt.Errorf("proto: wrong wireType = %d for field Timestamp", wireType) } - m.Timestamp = 0 + var msglen int for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflowControl @@ -2870,11 +2311,22 @@ func (m *VertexLog) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - m.Timestamp |= (int64(b) & 0x7F) << shift + msglen |= (int(b) & 0x7F) << shift if b < 0x80 { break } } + if msglen < 0 { + return ErrInvalidLengthControl + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := github_com_gogo_protobuf_types.StdTimeUnmarshal(&m.Timestamp, dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex case 3: if wireType != 0 { return fmt.Errorf("proto: wrong wireType = %d for field Stream", wireType) @@ -3054,42 +2506,49 @@ var ( func init() { proto.RegisterFile("control.proto", fileDescriptorControl) } var fileDescriptorControl = []byte{ - // 581 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x74, 0x54, 0x31, 0x6f, 0xd3, 0x40, - 0x14, 0xce, 0xc5, 0x89, 0x13, 0xbf, 0x24, 0xa5, 0x9c, 0x4a, 0x31, 0x11, 0x3a, 0xa5, 0x1e, 0x50, - 0x24, 0xaa, 0x0a, 0x82, 0xc4, 0xc2, 0x02, 0x25, 0x4b, 0x24, 0x58, 0x2e, 0x2a, 0xbb, 0xeb, 0x5c, - 0x83, 0x85, 0xed, 0x0b, 0xbe, 0x4b, 0x54, 0x75, 0xe2, 0x27, 0x30, 0x30, 0xf0, 0x13, 0xf8, 0x1d, - 0x4c, 0x8c, 0x1d, 0x19, 0x89, 0x59, 0x18, 0xfb, 0x13, 0xd0, 0x9d, 0xcf, 0x8e, 0x95, 0xa6, 0xdb, - 0xfb, 0xbe, 0xf7, 0xf9, 0xbd, 0xef, 0xee, 0xbd, 0x33, 0xf4, 0x02, 0x9e, 0xc8, 0x94, 0x47, 0x27, - 0x8b, 0x94, 0x4b, 0x8e, 0x5b, 0x06, 0x7a, 0x18, 0xf6, 0xc7, 0xa1, 0xf8, 0x74, 0x26, 0xfc, 0x39, - 0xa3, 0xec, 0xf3, 0x92, 0x09, 0xe9, 0xbd, 0x81, 0xfb, 0x15, 0x4e, 0x2c, 0x78, 0x22, 0x18, 0x3e, - 0x06, 0x3b, 0x65, 0x01, 0x4f, 0x67, 0x2e, 0x1a, 0x58, 0xc3, 0xce, 0xe8, 0xe0, 0xa4, 0xa8, 0x68, - 0x74, 0x2a, 0x47, 0x8d, 0xc6, 0xf3, 0xa1, 0x53, 0xa1, 0xf1, 0x1e, 0xd4, 0x27, 0x63, 0x17, 0x0d, - 0xd0, 0xd0, 0xa1, 0xf5, 0xc9, 0x18, 0xbb, 0xd0, 0x7a, 0xbf, 0x94, 0xfe, 0x79, 0xc4, 0xdc, 0xfa, - 0x00, 0x0d, 0xdb, 0xb4, 0x80, 0xf8, 0x00, 0x9a, 0x93, 0xe4, 0x4c, 0x30, 0xd7, 0xd2, 0x7c, 0x0e, - 0x30, 0x86, 0xc6, 0x34, 0xbc, 0x62, 0x6e, 0x63, 0x80, 0x86, 0x16, 0xd5, 0xb1, 0xf7, 0x1a, 0xba, - 0x53, 0x1e, 0xad, 0x0a, 0xd7, 0x78, 0x1f, 0x2c, 0xca, 0x2e, 0x4c, 0x13, 0x15, 0x62, 0x02, 0x30, - 0x66, 0x17, 0x61, 0x12, 0xca, 0x90, 0x27, 0x6e, 0x7d, 0x60, 0x0d, 0xbb, 0xb4, 0xc2, 0x78, 0x23, - 0xe8, 0x99, 0x0a, 0xe6, 0x8c, 0x47, 0x60, 0xad, 0xe4, 0xa5, 0x39, 0xe0, 0xbd, 0xf2, 0x80, 0x1f, - 0x58, 0x2a, 0xd9, 0x25, 0x55, 0x39, 0xef, 0x08, 0x7a, 0x53, 0xe9, 0xcb, 0xa5, 0xb8, 0xb3, 0xad, - 0xf7, 0x1d, 0xc1, 0x5e, 0xa1, 0x31, 0x85, 0x9f, 0x42, 0x7b, 0xa5, 0x8b, 0x30, 0x71, 0x57, 0xf5, - 0x52, 0x80, 0x9f, 0x43, 0x5b, 0xe8, 0xcf, 0x99, 0xd0, 0xa6, 0x3b, 0xa3, 0x07, 0x5b, 0x62, 0x53, - 0xbd, 0x94, 0xe1, 0x27, 0xd0, 0x88, 0xf8, 0x5c, 0xb8, 0x96, 0x96, 0xe3, 0x2d, 0xf9, 0x3b, 0x3e, - 0xa7, 0x3a, 0xef, 0x7d, 0x43, 0x60, 0xe7, 0xdc, 0xad, 0x91, 0x1c, 0x82, 0x1d, 0x26, 0x8b, 0xa5, - 0xcc, 0x7b, 0x3a, 0xd4, 0x20, 0x75, 0xf5, 0x89, 0x1f, 0xe7, 0xf3, 0x70, 0xa8, 0x8e, 0x95, 0x36, - 0xf0, 0x83, 0x8f, 0x6c, 0xa6, 0x07, 0xd2, 0xa6, 0x06, 0xa9, 0xb1, 0x0a, 0xe9, 0xa7, 0x92, 0xcd, - 0xdc, 0xa6, 0x9e, 0x54, 0x01, 0xf1, 0x63, 0x70, 0x02, 0x1e, 0x2f, 0x22, 0xa6, 0x72, 0xb6, 0xce, - 0x6d, 0x08, 0xef, 0x0a, 0xba, 0xd5, 0x83, 0xed, 0xf2, 0x96, 0xdf, 0x8e, 0xde, 0x16, 0x87, 0x1a, - 0xb4, 0xd3, 0x9b, 0x0b, 0xad, 0x60, 0x99, 0xa6, 0x2c, 0x91, 0x66, 0x5b, 0x0a, 0xa8, 0x56, 0x4b, - 0x72, 0xe9, 0x47, 0xc6, 0x5b, 0x0e, 0x3c, 0x06, 0x4e, 0x79, 0x4b, 0x6a, 0x98, 0x61, 0x12, 0xe8, - 0xce, 0x16, 0x55, 0xa1, 0x32, 0x2e, 0xc3, 0x98, 0x09, 0xe9, 0xc7, 0x0b, 0xdd, 0xdd, 0xa2, 0x1b, - 0x42, 0x19, 0x13, 0x32, 0x65, 0x7e, 0xac, 0x2d, 0x58, 0xd4, 0x20, 0x55, 0x27, 0x16, 0x73, 0x6d, - 0xa0, 0x4b, 0x55, 0x38, 0xfa, 0x89, 0xa0, 0xf5, 0x36, 0x9f, 0x0a, 0x3e, 0x05, 0xa7, 0x7c, 0x5f, - 0xf8, 0x51, 0x39, 0xac, 0xed, 0x77, 0xd8, 0xef, 0xef, 0x4a, 0x99, 0x8d, 0x7a, 0x09, 0x4d, 0xbd, - 0xbb, 0x78, 0xb3, 0x1b, 0xd5, 0xd7, 0xd0, 0x3f, 0xdc, 0xa6, 0xcd, 0x77, 0xaf, 0xc0, 0x36, 0x97, - 0x5c, 0x51, 0x54, 0x17, 0xba, 0xff, 0xf0, 0x16, 0x9f, 0x7f, 0xfa, 0x0c, 0x9d, 0x1e, 0x5f, 0xaf, - 0x49, 0xed, 0xf7, 0x9a, 0xd4, 0x6e, 0xd6, 0x04, 0x7d, 0xc9, 0x08, 0xfa, 0x91, 0x11, 0xf4, 0x2b, - 0x23, 0xe8, 0x3a, 0x23, 0xe8, 0x4f, 0x46, 0xd0, 0xbf, 0x8c, 0xd4, 0x6e, 0x32, 0x82, 0xbe, 0xfe, - 0x25, 0xb5, 0x73, 0x5b, 0xff, 0x6a, 0x5e, 0xfc, 0x0f, 0x00, 0x00, 0xff, 0xff, 0x03, 0x50, 0xff, - 0x6a, 0x7b, 0x04, 0x00, 0x00, + // 689 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xa4, 0x54, 0xc1, 0x6e, 0xd3, 0x4c, + 0x10, 0xfe, 0x37, 0x4e, 0x9d, 0x64, 0x92, 0x56, 0xfd, 0x57, 0x08, 0x59, 0x41, 0x24, 0xc6, 0x5c, + 0xa2, 0x4a, 0x75, 0x20, 0xc0, 0xa5, 0x48, 0x08, 0x85, 0x1c, 0x68, 0x45, 0x2f, 0xdb, 0x96, 0xbb, + 0xe3, 0x6c, 0x5d, 0xab, 0xb6, 0x37, 0x78, 0xd7, 0x51, 0xe1, 0x29, 0x78, 0x17, 0x9e, 0x01, 0xa9, + 0x47, 0xce, 0x1c, 0x0a, 0xea, 0x23, 0x70, 0xe2, 0x88, 0xbc, 0xbb, 0x76, 0x4d, 0xdb, 0x40, 0x55, + 0x4e, 0xd9, 0xd9, 0x7c, 0xf3, 0xed, 0x7c, 0xe3, 0xf9, 0x06, 0x56, 0x7d, 0x96, 0x88, 0x94, 0x45, + 0xee, 0x3c, 0x65, 0x82, 0xe1, 0xf5, 0x98, 0x4d, 0xdf, 0xbb, 0xd3, 0x2c, 0x8c, 0x66, 0xc7, 0xa1, + 0x70, 0x17, 0x8f, 0xbb, 0x9b, 0x41, 0x28, 0x8e, 0xb2, 0xa9, 0xeb, 0xb3, 0x78, 0x18, 0xb0, 0x80, + 0x0d, 0x25, 0x70, 0x9a, 0x1d, 0xca, 0x48, 0x06, 0xf2, 0xa4, 0x08, 0xba, 0xfd, 0x80, 0xb1, 0x20, + 0xa2, 0x17, 0x28, 0x11, 0xc6, 0x94, 0x0b, 0x2f, 0x9e, 0x2b, 0x80, 0x83, 0x61, 0x7d, 0x12, 0xf2, + 0xe3, 0x03, 0xee, 0x05, 0x94, 0xd0, 0x77, 0x19, 0xe5, 0xc2, 0xd9, 0x81, 0xff, 0x2b, 0x77, 0x7c, + 0xce, 0x12, 0x4e, 0xf1, 0x33, 0x30, 0x53, 0xea, 0xb3, 0x74, 0x66, 0x21, 0xdb, 0x18, 0xb4, 0x47, + 0xf7, 0xdd, 0xcb, 0xb5, 0xb9, 0x3a, 0x21, 0x07, 0x11, 0x0d, 0x76, 0x3c, 0x68, 0x57, 0xae, 0xf1, + 0x1a, 0xd4, 0xb6, 0x27, 0x16, 0xb2, 0xd1, 0xa0, 0x45, 0x6a, 0xdb, 0x13, 0x6c, 0x41, 0x63, 0x37, + 0x13, 0xde, 0x34, 0xa2, 0x56, 0xcd, 0x46, 0x83, 0x26, 0x29, 0x42, 0x7c, 0x07, 0x56, 0xb6, 0x93, + 0x03, 0x4e, 0x2d, 0x43, 0xde, 0xab, 0x00, 0x63, 0xa8, 0xef, 0x85, 0x1f, 0xa8, 0x55, 0xb7, 0xd1, + 0xc0, 0x20, 0xf2, 0xec, 0xbc, 0x84, 0xce, 0x1e, 0x8b, 0x16, 0x45, 0xf9, 0x78, 0x1d, 0x0c, 0x42, + 0x0f, 0xf5, 0x23, 0xf9, 0x11, 0xf7, 0x00, 0x26, 0xf4, 0x30, 0x4c, 0x42, 0x11, 0xb2, 0xc4, 0xaa, + 0xd9, 0xc6, 0xa0, 0x43, 0x2a, 0x37, 0xce, 0x73, 0x58, 0xd5, 0x0c, 0x5a, 0xec, 0x06, 0x18, 0x0b, + 0x71, 0xa2, 0x95, 0x5a, 0x57, 0x95, 0xbe, 0xa5, 0xa9, 0xa0, 0x27, 0x24, 0x07, 0x39, 0x0f, 0x60, + 0x75, 0x4f, 0x78, 0x22, 0xe3, 0x4b, 0xdf, 0x77, 0x3e, 0x21, 0x58, 0x2b, 0x30, 0xfa, 0x85, 0xa7, + 0xd0, 0x5c, 0x48, 0x12, 0xca, 0xff, 0xfa, 0x4c, 0x89, 0xc4, 0x5b, 0xd0, 0xe4, 0x92, 0x87, 0x72, + 0x29, 0xa3, 0x3d, 0xea, 0x2d, 0xcb, 0xd2, 0xef, 0x95, 0x78, 0x3c, 0x84, 0x7a, 0xc4, 0x02, 0x6e, + 0x19, 0x32, 0xef, 0xde, 0xb2, 0xbc, 0x37, 0x2c, 0x20, 0x12, 0xe8, 0x9c, 0xd6, 0xc0, 0x54, 0x77, + 0x78, 0x07, 0xcc, 0x59, 0x18, 0x50, 0x2e, 0x94, 0xaa, 0xf1, 0xe8, 0xf4, 0xac, 0xff, 0xdf, 0xd7, + 0xb3, 0xfe, 0x46, 0x65, 0x1a, 0xd9, 0x9c, 0x26, 0xf9, 0xf4, 0x7a, 0x61, 0x42, 0x53, 0x3e, 0x0c, + 0xd8, 0xa6, 0x4a, 0x71, 0x27, 0xf2, 0x87, 0x68, 0x86, 0x9c, 0x2b, 0x4c, 0xe6, 0x99, 0x50, 0x0a, + 0x6e, 0xc9, 0xa5, 0x18, 0xf2, 0x71, 0x48, 0xbc, 0x58, 0xcd, 0x48, 0x8b, 0xc8, 0x33, 0xbe, 0x0b, + 0xa6, 0xef, 0xf9, 0x47, 0x74, 0x26, 0x87, 0xa4, 0x49, 0x74, 0x84, 0xb7, 0xa0, 0xc1, 0x85, 0x97, + 0x0a, 0x3a, 0xb3, 0x56, 0x6c, 0x34, 0x68, 0x8f, 0xba, 0xae, 0x32, 0x87, 0x5b, 0x98, 0xc3, 0xdd, + 0x2f, 0xcc, 0x31, 0xae, 0x7f, 0xfc, 0xd6, 0x47, 0xa4, 0x48, 0xc0, 0x2f, 0xa0, 0xe5, 0xb3, 0x78, + 0x1e, 0xd1, 0x3c, 0xdb, 0xbc, 0x61, 0xf6, 0x45, 0x8a, 0xf3, 0x03, 0x41, 0xa7, 0xfa, 0x59, 0xae, + 0xf8, 0x60, 0x07, 0x4c, 0xf5, 0x91, 0xa5, 0x0d, 0x6e, 0xd9, 0x14, 0xc5, 0x70, 0x6d, 0x53, 0x2c, + 0x68, 0xf8, 0x59, 0x9a, 0xd2, 0x44, 0x68, 0xeb, 0x14, 0x61, 0xee, 0x33, 0xc1, 0x84, 0x17, 0xc9, + 0xa6, 0x18, 0x44, 0x05, 0x78, 0x0c, 0xad, 0x72, 0x53, 0xdc, 0x40, 0x70, 0x33, 0x2f, 0x57, 0x89, + 0x2e, 0xd3, 0x9c, 0xcf, 0x08, 0x5a, 0xe5, 0x4c, 0x55, 0x14, 0xa2, 0x7f, 0x56, 0xf8, 0x5b, 0x75, + 0xb5, 0x5b, 0x55, 0x97, 0x8f, 0x09, 0x17, 0x29, 0xf5, 0x62, 0xd9, 0x27, 0x83, 0xe8, 0x28, 0x77, + 0x6f, 0xcc, 0x03, 0xd9, 0xa5, 0x0e, 0xc9, 0x8f, 0xa3, 0x9f, 0x08, 0x1a, 0xaf, 0xd4, 0x5a, 0xc6, + 0xfb, 0xd0, 0x2a, 0x57, 0x23, 0x76, 0xae, 0x7a, 0xe8, 0xf2, 0x2e, 0xed, 0x3e, 0xfc, 0x23, 0x46, + 0x2f, 0x83, 0xd7, 0xb0, 0x22, 0xf7, 0x0f, 0xbe, 0xc6, 0xcd, 0xd5, 0xd5, 0xd6, 0xed, 0x2f, 0xfd, + 0x5f, 0x33, 0xed, 0x82, 0xa9, 0x27, 0xec, 0x3a, 0x68, 0x75, 0x4d, 0x75, 0xed, 0xe5, 0x00, 0x45, + 0xf6, 0x08, 0x8d, 0x3b, 0xa7, 0xe7, 0x3d, 0xf4, 0xe5, 0xbc, 0x87, 0xbe, 0x9f, 0xf7, 0xd0, 0xd4, + 0x94, 0xbd, 0x7d, 0xf2, 0x2b, 0x00, 0x00, 0xff, 0xff, 0x08, 0xd7, 0xbb, 0xa9, 0xa5, 0x06, 0x00, + 0x00, } diff --git a/api/services/control/control.proto b/api/services/control/control.proto index 5164f4b7..71e38655 100644 --- a/api/services/control/control.proto +++ b/api/services/control/control.proto @@ -1,6 +1,13 @@ syntax = "proto3"; -package control; +package moby.buildkit.v1; + +import "github.com/gogo/protobuf/gogoproto/gogo.proto"; +import "google/protobuf/timestamp.proto"; + +option (gogoproto.sizer_all) = true; +option (gogoproto.marshaler_all) = true; +option (gogoproto.unmarshaler_all) = true; service Control { rpc DiskUsage(DiskUsageRequest) returns (DiskUsageResponse); @@ -42,25 +49,26 @@ message StatusResponse { } message Vertex { - string ID = 1; - repeated string inputs = 2; + string digest = 1 [(gogoproto.customtype) = "github.com/opencontainers/go-digest.Digest", (gogoproto.nullable) = false]; + repeated string inputs = 2 [(gogoproto.customtype) = "github.com/opencontainers/go-digest.Digest", (gogoproto.nullable) = false]; string name = 3; bool cached = 4; - int64 started = 5; // relative, add abolute google.protobuf.Timestamp as well? - int64 completed = 6; + google.protobuf.Timestamp started = 5 [(gogoproto.stdtime) = true ]; + google.protobuf.Timestamp completed = 6 [(gogoproto.stdtime) = true ]; } message VertexStatus { string ID = 1; - string vertex = 2; + string vertex = 2 [(gogoproto.customtype) = "github.com/opencontainers/go-digest.Digest", (gogoproto.nullable) = false]; string name = 3; int64 current = 4; int64 total = 5; + google.protobuf.Timestamp timestamp = 6 [(gogoproto.stdtime) = true, (gogoproto.nullable) = false]; } message VertexLog { - int64 inc = 1; - int64 timestamp = 2; + string vertex = 1 [(gogoproto.customtype) = "github.com/opencontainers/go-digest.Digest", (gogoproto.nullable) = false]; + google.protobuf.Timestamp timestamp = 2 [(gogoproto.stdtime) = true, (gogoproto.nullable) = false]; int64 stream = 3; bytes msg = 4; } diff --git a/api/services/control/generate.go b/api/services/control/generate.go index be8fc140..301dad1a 100644 --- a/api/services/control/generate.go +++ b/api/services/control/generate.go @@ -1,3 +1,3 @@ -package control +package moby_buildkit_v1 -//go:generate protoc --gogoslick_out=plugins=grpc:. control.proto +//go:generate protoc -I=. -I=../../../vendor/ --gogo_out=plugins=grpc:. control.proto diff --git a/client/graph.go b/client/graph.go index 8ac76f75..0325ed40 100644 --- a/client/graph.go +++ b/client/graph.go @@ -7,7 +7,7 @@ import ( ) type Vertex struct { - ID digest.Digest + Digest digest.Digest Inputs []digest.Digest Name string Started *time.Time @@ -17,7 +17,7 @@ type Vertex struct { } type VertexStatus struct { - ID digest.Digest + ID string Vertex digest.Digest Name string Total int diff --git a/control/control.go b/control/control.go index 4403fa70..b6947e61 100644 --- a/control/control.go +++ b/control/control.go @@ -1,10 +1,7 @@ package control import ( - "time" - "github.com/containerd/containerd/snapshot" - digest "github.com/opencontainers/go-digest" "github.com/pkg/errors" controlapi "github.com/tonistiigi/buildkit_poc/api/services/control" "github.com/tonistiigi/buildkit_poc/cache" @@ -95,11 +92,11 @@ func (c *Controller) Status(req *controlapi.StatusRequest, stream controlapi.Con sr := controlapi.StatusResponse{} for _, v := range ss.Vertexes { sr.Vertexes = append(sr.Vertexes, &controlapi.Vertex{ - ID: v.ID.String(), - Inputs: digestToString(v.Inputs), + Digest: v.Digest, + Inputs: v.Inputs, Name: v.Name, - Started: marshalTimeStamp(v.Started), - Completed: marshalTimeStamp(v.Completed), + Started: v.Started, + Completed: v.Completed, }) } if err := stream.SendMsg(&sr); err != nil { @@ -111,17 +108,3 @@ func (c *Controller) Status(req *controlapi.StatusRequest, stream controlapi.Con return eg.Wait() } - -func digestToString(dgsts []digest.Digest) (out []string) { // TODO: make proto use digest - for _, dgst := range dgsts { - out = append(out, dgst.String()) - } - return -} - -func marshalTimeStamp(tm *time.Time) int64 { - if tm == nil { - return 0 - } - return tm.UnixNano() -} diff --git a/solver/load.go b/solver/load.go index a624661f..65b32a36 100644 --- a/solver/load.go +++ b/solver/load.go @@ -63,7 +63,7 @@ func loadReqursive(dgst digest.Digest, op *pb.Op, inputs map[digest.Digest]*pb.O vtx.vtx = client.Vertex{ Inputs: inputDigests, Name: vtx.name(), - ID: dgst, + Digest: dgst, } cache[dgst] = vtx return vtx, nil From dd9490fb85e0b08daaf0f2bc9146616dcf80c0c9 Mon Sep 17 00:00:00 2001 From: Tonis Tiigi Date: Tue, 13 Jun 2017 23:26:27 -0700 Subject: [PATCH 4/5] control: unbreak standalone Signed-off-by: Tonis Tiigi --- control/control_standalone.go | 49 ++++++++++++++++++++++++++++++++--- 1 file changed, 46 insertions(+), 3 deletions(-) diff --git a/control/control_standalone.go b/control/control_standalone.go index a1ff0891..e0e9efe2 100644 --- a/control/control_standalone.go +++ b/control/control_standalone.go @@ -3,6 +3,7 @@ package control import ( + "context" "io" "io/ioutil" "os" @@ -12,12 +13,14 @@ import ( "github.com/containerd/containerd/archive/compression" "github.com/containerd/containerd/content" "github.com/containerd/containerd/mount" + "github.com/containerd/containerd/namespaces" + ctdsnapshot "github.com/containerd/containerd/snapshot" "github.com/containerd/containerd/snapshot/overlay" digest "github.com/opencontainers/go-digest" ocispec "github.com/opencontainers/image-spec/specs-go/v1" "github.com/pkg/errors" "github.com/tonistiigi/buildkit_poc/worker/runcworker" - "golang.org/x/net/context" + netcontext "golang.org/x/net/context" // TODO: fix ) func NewStandalone(root string) (*Controller, error) { @@ -61,7 +64,7 @@ func newPullDeps(root string) (*pullDeps, error) { a := &localApplier{root: root, content: c} return &pullDeps{ - Snapshotter: s, + Snapshotter: &nsSnapshotter{s}, ContentStore: c, Applier: a, }, nil @@ -73,7 +76,7 @@ type localApplier struct { content content.Store } -func (a *localApplier) Apply(ctx context.Context, desc ocispec.Descriptor, mounts []mount.Mount) (ocispec.Descriptor, error) { +func (a *localApplier) Apply(ctx netcontext.Context, desc ocispec.Descriptor, mounts []mount.Mount) (ocispec.Descriptor, error) { dir, err := ioutil.TempDir(a.root, "extract-") if err != nil { return ocispec.Descriptor{}, errors.Wrap(err, "failed to create temporary directory") @@ -136,3 +139,43 @@ type nopCloser struct { func (n *nopCloser) Close() error { return nil } + +// this should be supported by containerd. currently packages are unusable without wrapping +const dummyNs = "buildkit" + +type nsSnapshotter struct { + ctdsnapshot.Snapshotter +} + +func (s *nsSnapshotter) Stat(ctx context.Context, key string) (ctdsnapshot.Info, error) { + ctx = namespaces.WithNamespace(ctx, dummyNs) + return s.Snapshotter.Stat(ctx, key) +} +func (s *nsSnapshotter) Usage(ctx context.Context, key string) (ctdsnapshot.Usage, error) { + ctx = namespaces.WithNamespace(ctx, dummyNs) + return s.Snapshotter.Usage(ctx, key) +} +func (s *nsSnapshotter) Mounts(ctx context.Context, key string) ([]mount.Mount, error) { + ctx = namespaces.WithNamespace(ctx, dummyNs) + return s.Snapshotter.Mounts(ctx, key) +} +func (s *nsSnapshotter) Prepare(ctx context.Context, key, parent string) ([]mount.Mount, error) { + ctx = namespaces.WithNamespace(ctx, dummyNs) + return s.Snapshotter.Prepare(ctx, key, parent) +} +func (s *nsSnapshotter) View(ctx context.Context, key, parent string) ([]mount.Mount, error) { + ctx = namespaces.WithNamespace(ctx, dummyNs) + return s.Snapshotter.View(ctx, key, parent) +} +func (s *nsSnapshotter) Commit(ctx context.Context, name, key string) error { + ctx = namespaces.WithNamespace(ctx, dummyNs) + return s.Snapshotter.Commit(ctx, name, key) +} +func (s *nsSnapshotter) Remove(ctx context.Context, key string) error { + ctx = namespaces.WithNamespace(ctx, dummyNs) + return s.Snapshotter.Remove(ctx, key) +} +func (s *nsSnapshotter) Walk(ctx context.Context, fn func(context.Context, ctdsnapshot.Info) error) error { + ctx = namespaces.WithNamespace(ctx, dummyNs) + return s.Snapshotter.Walk(ctx, fn) +} From 7c062a85785b26457077b493a6bd4cdc99e48fb4 Mon Sep 17 00:00:00 2001 From: Tonis Tiigi Date: Tue, 13 Jun 2017 23:28:14 -0700 Subject: [PATCH 5/5] vendor: include proto timestamps Signed-off-by: Tonis Tiigi --- .../protobuf/ptypes/timestamp/timestamp.pb.go | 162 ++++++++++++++++++ .../protobuf/ptypes/timestamp/timestamp.proto | 133 ++++++++++++++ 2 files changed, 295 insertions(+) create mode 100644 vendor/github.com/golang/protobuf/ptypes/timestamp/timestamp.pb.go create mode 100644 vendor/github.com/golang/protobuf/ptypes/timestamp/timestamp.proto diff --git a/vendor/github.com/golang/protobuf/ptypes/timestamp/timestamp.pb.go b/vendor/github.com/golang/protobuf/ptypes/timestamp/timestamp.pb.go new file mode 100644 index 00000000..3b76261e --- /dev/null +++ b/vendor/github.com/golang/protobuf/ptypes/timestamp/timestamp.pb.go @@ -0,0 +1,162 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// source: github.com/golang/protobuf/ptypes/timestamp/timestamp.proto + +/* +Package timestamp is a generated protocol buffer package. + +It is generated from these files: + github.com/golang/protobuf/ptypes/timestamp/timestamp.proto + +It has these top-level messages: + Timestamp +*/ +package timestamp + +import proto "github.com/golang/protobuf/proto" +import fmt "fmt" +import math "math" + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package + +// A Timestamp represents a point in time independent of any time zone +// or calendar, represented as seconds and fractions of seconds at +// nanosecond resolution in UTC Epoch time. It is encoded using the +// Proleptic Gregorian Calendar which extends the Gregorian calendar +// backwards to year one. It is encoded assuming all minutes are 60 +// seconds long, i.e. leap seconds are "smeared" so that no leap second +// table is needed for interpretation. Range is from +// 0001-01-01T00:00:00Z to 9999-12-31T23:59:59.999999999Z. +// By restricting to that range, we ensure that we can convert to +// and from RFC 3339 date strings. +// See [https://www.ietf.org/rfc/rfc3339.txt](https://www.ietf.org/rfc/rfc3339.txt). +// +// # Examples +// +// Example 1: Compute Timestamp from POSIX `time()`. +// +// Timestamp timestamp; +// timestamp.set_seconds(time(NULL)); +// timestamp.set_nanos(0); +// +// Example 2: Compute Timestamp from POSIX `gettimeofday()`. +// +// struct timeval tv; +// gettimeofday(&tv, NULL); +// +// Timestamp timestamp; +// timestamp.set_seconds(tv.tv_sec); +// timestamp.set_nanos(tv.tv_usec * 1000); +// +// Example 3: Compute Timestamp from Win32 `GetSystemTimeAsFileTime()`. +// +// FILETIME ft; +// GetSystemTimeAsFileTime(&ft); +// UINT64 ticks = (((UINT64)ft.dwHighDateTime) << 32) | ft.dwLowDateTime; +// +// // A Windows tick is 100 nanoseconds. Windows epoch 1601-01-01T00:00:00Z +// // is 11644473600 seconds before Unix epoch 1970-01-01T00:00:00Z. +// Timestamp timestamp; +// timestamp.set_seconds((INT64) ((ticks / 10000000) - 11644473600LL)); +// timestamp.set_nanos((INT32) ((ticks % 10000000) * 100)); +// +// Example 4: Compute Timestamp from Java `System.currentTimeMillis()`. +// +// long millis = System.currentTimeMillis(); +// +// Timestamp timestamp = Timestamp.newBuilder().setSeconds(millis / 1000) +// .setNanos((int) ((millis % 1000) * 1000000)).build(); +// +// +// Example 5: Compute Timestamp from current time in Python. +// +// timestamp = Timestamp() +// timestamp.GetCurrentTime() +// +// # JSON Mapping +// +// In JSON format, the Timestamp type is encoded as a string in the +// [RFC 3339](https://www.ietf.org/rfc/rfc3339.txt) format. That is, the +// format is "{year}-{month}-{day}T{hour}:{min}:{sec}[.{frac_sec}]Z" +// where {year} is always expressed using four digits while {month}, {day}, +// {hour}, {min}, and {sec} are zero-padded to two digits each. The fractional +// seconds, which can go up to 9 digits (i.e. up to 1 nanosecond resolution), +// are optional. The "Z" suffix indicates the timezone ("UTC"); the timezone +// is required, though only UTC (as indicated by "Z") is presently supported. +// +// For example, "2017-01-15T01:30:15.01Z" encodes 15.01 seconds past +// 01:30 UTC on January 15, 2017. +// +// In JavaScript, one can convert a Date object to this format using the +// standard [toISOString()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toISOString] +// method. In Python, a standard `datetime.datetime` object can be converted +// to this format using [`strftime`](https://docs.python.org/2/library/time.html#time.strftime) +// with the time format spec '%Y-%m-%dT%H:%M:%S.%fZ'. Likewise, in Java, one +// can use the Joda Time's [`ISODateTimeFormat.dateTime()`]( +// http://joda-time.sourceforge.net/apidocs/org/joda/time/format/ISODateTimeFormat.html#dateTime()) +// to obtain a formatter capable of generating timestamps in this format. +// +// +type Timestamp struct { + // Represents seconds of UTC time since Unix epoch + // 1970-01-01T00:00:00Z. Must be from 0001-01-01T00:00:00Z to + // 9999-12-31T23:59:59Z inclusive. + Seconds int64 `protobuf:"varint,1,opt,name=seconds" json:"seconds,omitempty"` + // Non-negative fractions of a second at nanosecond resolution. Negative + // second values with fractions must still have non-negative nanos values + // that count forward in time. Must be from 0 to 999,999,999 + // inclusive. + Nanos int32 `protobuf:"varint,2,opt,name=nanos" json:"nanos,omitempty"` +} + +func (m *Timestamp) Reset() { *m = Timestamp{} } +func (m *Timestamp) String() string { return proto.CompactTextString(m) } +func (*Timestamp) ProtoMessage() {} +func (*Timestamp) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} } +func (*Timestamp) XXX_WellKnownType() string { return "Timestamp" } + +func (m *Timestamp) GetSeconds() int64 { + if m != nil { + return m.Seconds + } + return 0 +} + +func (m *Timestamp) GetNanos() int32 { + if m != nil { + return m.Nanos + } + return 0 +} + +func init() { + proto.RegisterType((*Timestamp)(nil), "google.protobuf.Timestamp") +} + +func init() { + proto.RegisterFile("github.com/golang/protobuf/ptypes/timestamp/timestamp.proto", fileDescriptor0) +} + +var fileDescriptor0 = []byte{ + // 190 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xb2, 0x4e, 0xcf, 0x2c, 0xc9, + 0x28, 0x4d, 0xd2, 0x4b, 0xce, 0xcf, 0xd5, 0x4f, 0xcf, 0xcf, 0x49, 0xcc, 0x4b, 0xd7, 0x2f, 0x28, + 0xca, 0x2f, 0xc9, 0x4f, 0x2a, 0x4d, 0xd3, 0x2f, 0x28, 0xa9, 0x2c, 0x48, 0x2d, 0xd6, 0x2f, 0xc9, + 0xcc, 0x4d, 0x2d, 0x2e, 0x49, 0xcc, 0x2d, 0x40, 0xb0, 0xf4, 0xc0, 0x6a, 0x84, 0xf8, 0xd3, 0xf3, + 0xf3, 0xd3, 0x73, 0x52, 0xf5, 0x60, 0x3a, 0x94, 0xac, 0xb9, 0x38, 0x43, 0x60, 0x6a, 0x84, 0x24, + 0xb8, 0xd8, 0x8b, 0x53, 0x93, 0xf3, 0xf3, 0x52, 0x8a, 0x25, 0x18, 0x15, 0x18, 0x35, 0x98, 0x83, + 0x60, 0x5c, 0x21, 0x11, 0x2e, 0xd6, 0xbc, 0xc4, 0xbc, 0xfc, 0x62, 0x09, 0x26, 0x05, 0x46, 0x0d, + 0xd6, 0x20, 0x08, 0xc7, 0xa9, 0x8e, 0x4b, 0x38, 0x39, 0x3f, 0x57, 0x0f, 0xcd, 0x4c, 0x27, 0x3e, + 0xb8, 0x89, 0x01, 0x20, 0xa1, 0x00, 0xc6, 0x28, 0x6d, 0x12, 0xdc, 0xfc, 0x83, 0x91, 0x71, 0x11, + 0x13, 0xb3, 0x7b, 0x80, 0xd3, 0x2a, 0x26, 0x39, 0x77, 0x88, 0xc9, 0x01, 0x50, 0xb5, 0x7a, 0xe1, + 0xa9, 0x39, 0x39, 0xde, 0x79, 0xf9, 0xe5, 0x79, 0x21, 0x20, 0x3d, 0x49, 0x6c, 0x60, 0x43, 0x8c, + 0x01, 0x01, 0x00, 0x00, 0xff, 0xff, 0x6b, 0x59, 0x0a, 0x4d, 0x13, 0x01, 0x00, 0x00, +} diff --git a/vendor/github.com/golang/protobuf/ptypes/timestamp/timestamp.proto b/vendor/github.com/golang/protobuf/ptypes/timestamp/timestamp.proto new file mode 100644 index 00000000..b7cbd175 --- /dev/null +++ b/vendor/github.com/golang/protobuf/ptypes/timestamp/timestamp.proto @@ -0,0 +1,133 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +syntax = "proto3"; + +package google.protobuf; + +option csharp_namespace = "Google.Protobuf.WellKnownTypes"; +option cc_enable_arenas = true; +option go_package = "github.com/golang/protobuf/ptypes/timestamp"; +option java_package = "com.google.protobuf"; +option java_outer_classname = "TimestampProto"; +option java_multiple_files = true; +option objc_class_prefix = "GPB"; + +// A Timestamp represents a point in time independent of any time zone +// or calendar, represented as seconds and fractions of seconds at +// nanosecond resolution in UTC Epoch time. It is encoded using the +// Proleptic Gregorian Calendar which extends the Gregorian calendar +// backwards to year one. It is encoded assuming all minutes are 60 +// seconds long, i.e. leap seconds are "smeared" so that no leap second +// table is needed for interpretation. Range is from +// 0001-01-01T00:00:00Z to 9999-12-31T23:59:59.999999999Z. +// By restricting to that range, we ensure that we can convert to +// and from RFC 3339 date strings. +// See [https://www.ietf.org/rfc/rfc3339.txt](https://www.ietf.org/rfc/rfc3339.txt). +// +// # Examples +// +// Example 1: Compute Timestamp from POSIX `time()`. +// +// Timestamp timestamp; +// timestamp.set_seconds(time(NULL)); +// timestamp.set_nanos(0); +// +// Example 2: Compute Timestamp from POSIX `gettimeofday()`. +// +// struct timeval tv; +// gettimeofday(&tv, NULL); +// +// Timestamp timestamp; +// timestamp.set_seconds(tv.tv_sec); +// timestamp.set_nanos(tv.tv_usec * 1000); +// +// Example 3: Compute Timestamp from Win32 `GetSystemTimeAsFileTime()`. +// +// FILETIME ft; +// GetSystemTimeAsFileTime(&ft); +// UINT64 ticks = (((UINT64)ft.dwHighDateTime) << 32) | ft.dwLowDateTime; +// +// // A Windows tick is 100 nanoseconds. Windows epoch 1601-01-01T00:00:00Z +// // is 11644473600 seconds before Unix epoch 1970-01-01T00:00:00Z. +// Timestamp timestamp; +// timestamp.set_seconds((INT64) ((ticks / 10000000) - 11644473600LL)); +// timestamp.set_nanos((INT32) ((ticks % 10000000) * 100)); +// +// Example 4: Compute Timestamp from Java `System.currentTimeMillis()`. +// +// long millis = System.currentTimeMillis(); +// +// Timestamp timestamp = Timestamp.newBuilder().setSeconds(millis / 1000) +// .setNanos((int) ((millis % 1000) * 1000000)).build(); +// +// +// Example 5: Compute Timestamp from current time in Python. +// +// timestamp = Timestamp() +// timestamp.GetCurrentTime() +// +// # JSON Mapping +// +// In JSON format, the Timestamp type is encoded as a string in the +// [RFC 3339](https://www.ietf.org/rfc/rfc3339.txt) format. That is, the +// format is "{year}-{month}-{day}T{hour}:{min}:{sec}[.{frac_sec}]Z" +// where {year} is always expressed using four digits while {month}, {day}, +// {hour}, {min}, and {sec} are zero-padded to two digits each. The fractional +// seconds, which can go up to 9 digits (i.e. up to 1 nanosecond resolution), +// are optional. The "Z" suffix indicates the timezone ("UTC"); the timezone +// is required, though only UTC (as indicated by "Z") is presently supported. +// +// For example, "2017-01-15T01:30:15.01Z" encodes 15.01 seconds past +// 01:30 UTC on January 15, 2017. +// +// In JavaScript, one can convert a Date object to this format using the +// standard [toISOString()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toISOString] +// method. In Python, a standard `datetime.datetime` object can be converted +// to this format using [`strftime`](https://docs.python.org/2/library/time.html#time.strftime) +// with the time format spec '%Y-%m-%dT%H:%M:%S.%fZ'. Likewise, in Java, one +// can use the Joda Time's [`ISODateTimeFormat.dateTime()`]( +// http://joda-time.sourceforge.net/apidocs/org/joda/time/format/ISODateTimeFormat.html#dateTime()) +// to obtain a formatter capable of generating timestamps in this format. +// +// +message Timestamp { + + // Represents seconds of UTC time since Unix epoch + // 1970-01-01T00:00:00Z. Must be from 0001-01-01T00:00:00Z to + // 9999-12-31T23:59:59Z inclusive. + int64 seconds = 1; + + // Non-negative fractions of a second at nanosecond resolution. Negative + // second values with fractions must still have non-negative nanos values + // that count forward in time. Must be from 0 to 999,999,999 + // inclusive. + int32 nanos = 2; +}