diff --git a/api/grpc/server/server.go b/api/grpc/server/server.go index b38433f..004c8de 100644 --- a/api/grpc/server/server.go +++ b/api/grpc/server/server.go @@ -32,7 +32,7 @@ func (s *apiServer) CreateContainer(ctx context.Context, c *types.CreateContaine if c.BundlePath == "" { return nil, errors.New("empty bundle path") } - e := supervisor.NewEvent(supervisor.StartContainerEventType) + e := supervisor.NewTask(supervisor.StartContainerTaskType) e.ID = c.Id e.BundlePath = c.BundlePath e.Stdin = c.Stdin @@ -45,7 +45,7 @@ func (s *apiServer) CreateContainer(ctx context.Context, c *types.CreateContaine Name: c.Checkpoint, } } - s.sv.SendEvent(e) + s.sv.SendTask(e) if err := <-e.Err; err != nil { return nil, err } @@ -60,11 +60,11 @@ func (s *apiServer) CreateContainer(ctx context.Context, c *types.CreateContaine } func (s *apiServer) Signal(ctx context.Context, r *types.SignalRequest) (*types.SignalResponse, error) { - e := supervisor.NewEvent(supervisor.SignalEventType) + e := supervisor.NewTask(supervisor.SignalTaskType) e.ID = r.Id e.Pid = r.Pid e.Signal = syscall.Signal(int(r.Signal)) - s.sv.SendEvent(e) + s.sv.SendTask(e) if err := <-e.Err; err != nil { return nil, err } @@ -89,7 +89,7 @@ func (s *apiServer) AddProcess(ctx context.Context, r *types.AddProcessRequest) if r.Pid == "" { return nil, fmt.Errorf("process id cannot be empty") } - e := supervisor.NewEvent(supervisor.AddProcessEventType) + e := supervisor.NewTask(supervisor.AddProcessTaskType) e.ID = r.Id e.Pid = r.Pid e.ProcessSpec = process @@ -97,7 +97,7 @@ func (s *apiServer) AddProcess(ctx context.Context, r *types.AddProcessRequest) e.Stdout = r.Stdout e.Stderr = r.Stderr e.StartResponse = make(chan supervisor.StartResponse, 1) - s.sv.SendEvent(e) + s.sv.SendTask(e) if err := <-e.Err; err != nil { return nil, err } @@ -106,7 +106,7 @@ func (s *apiServer) AddProcess(ctx context.Context, r *types.AddProcessRequest) } func (s *apiServer) CreateCheckpoint(ctx context.Context, r *types.CreateCheckpointRequest) (*types.CreateCheckpointResponse, error) { - e := supervisor.NewEvent(supervisor.CreateCheckpointEventType) + e := supervisor.NewTask(supervisor.CreateCheckpointTaskType) e.ID = r.Id e.Checkpoint = &runtime.Checkpoint{ Name: r.Checkpoint.Name, @@ -115,7 +115,7 @@ func (s *apiServer) CreateCheckpoint(ctx context.Context, r *types.CreateCheckpo UnixSockets: r.Checkpoint.UnixSockets, Shell: r.Checkpoint.Shell, } - s.sv.SendEvent(e) + s.sv.SendTask(e) if err := <-e.Err; err != nil { return nil, err } @@ -126,12 +126,12 @@ func (s *apiServer) DeleteCheckpoint(ctx context.Context, r *types.DeleteCheckpo if r.Name == "" { return nil, errors.New("checkpoint name cannot be empty") } - e := supervisor.NewEvent(supervisor.DeleteCheckpointEventType) + e := supervisor.NewTask(supervisor.DeleteCheckpointTaskType) e.ID = r.Id e.Checkpoint = &runtime.Checkpoint{ Name: r.Name, } - s.sv.SendEvent(e) + s.sv.SendTask(e) if err := <-e.Err; err != nil { return nil, err } @@ -139,8 +139,8 @@ func (s *apiServer) DeleteCheckpoint(ctx context.Context, r *types.DeleteCheckpo } func (s *apiServer) ListCheckpoint(ctx context.Context, r *types.ListCheckpointRequest) (*types.ListCheckpointResponse, error) { - e := supervisor.NewEvent(supervisor.GetContainerEventType) - s.sv.SendEvent(e) + e := supervisor.NewTask(supervisor.GetContainerTaskType) + s.sv.SendTask(e) if err := <-e.Err; err != nil { return nil, err } @@ -173,9 +173,9 @@ func (s *apiServer) ListCheckpoint(ctx context.Context, r *types.ListCheckpointR } func (s *apiServer) State(ctx context.Context, r *types.StateRequest) (*types.StateResponse, error) { - e := supervisor.NewEvent(supervisor.GetContainerEventType) + e := supervisor.NewTask(supervisor.GetContainerTaskType) e.ID = r.Id - s.sv.SendEvent(e) + s.sv.SendTask(e) if err := <-e.Err; err != nil { return nil, err } @@ -245,10 +245,10 @@ func toUint32(its []int) []uint32 { } func (s *apiServer) UpdateContainer(ctx context.Context, r *types.UpdateContainerRequest) (*types.UpdateContainerResponse, error) { - e := supervisor.NewEvent(supervisor.UpdateContainerEventType) + e := supervisor.NewTask(supervisor.UpdateContainerTaskType) e.ID = r.Id e.State = runtime.State(r.Status) - s.sv.SendEvent(e) + s.sv.SendTask(e) if err := <-e.Err; err != nil { return nil, err } @@ -256,13 +256,13 @@ func (s *apiServer) UpdateContainer(ctx context.Context, r *types.UpdateContaine } func (s *apiServer) UpdateProcess(ctx context.Context, r *types.UpdateProcessRequest) (*types.UpdateProcessResponse, error) { - e := supervisor.NewEvent(supervisor.UpdateProcessEventType) + e := supervisor.NewTask(supervisor.UpdateProcessTaskType) e.ID = r.Id e.Pid = r.Pid e.Height = int(r.Height) e.Width = int(r.Width) e.CloseStdin = r.CloseStdin - s.sv.SendEvent(e) + s.sv.SendTask(e) if err := <-e.Err; err != nil { return nil, err } @@ -272,37 +272,25 @@ func (s *apiServer) UpdateProcess(ctx context.Context, r *types.UpdateProcessReq func (s *apiServer) Events(r *types.EventsRequest, stream types.API_EventsServer) error { events := s.sv.Events() defer s.sv.Unsubscribe(events) - for evt := range events { - var ev *types.Event - switch evt.Type { - case supervisor.ExitEventType, supervisor.ExecExitEventType: - ev = &types.Event{ - Type: "exit", - Id: evt.ID, - Pid: evt.Pid, - Status: uint32(evt.Status), - } - case supervisor.OOMEventType: - ev = &types.Event{ - Type: "oom", - Id: evt.ID, - } + for e := range events { + if err := stream.Send(&types.Event{ + Id: e.ID, + Type: e.Type, + Timestamp: uint64(e.Timestamp.Unix()), + Pid: e.Pid, + Status: uint32(e.Status), + }); err != nil { + return err } - if ev != nil { - if err := stream.Send(ev); err != nil { - return err - } - } - } return nil } func (s *apiServer) Stats(ctx context.Context, r *types.StatsRequest) (*types.StatsResponse, error) { - e := supervisor.NewEvent(supervisor.StatsEventType) + e := supervisor.NewTask(supervisor.StatsTaskType) e.ID = r.Id e.Stat = make(chan *runtime.Stat, 1) - s.sv.SendEvent(e) + s.sv.SendTask(e) if err := <-e.Err; err != nil { return nil, err } diff --git a/api/grpc/types/api.pb.go b/api/grpc/types/api.pb.go index ff143bc..a5c9a34 100644 --- a/api/grpc/types/api.pb.go +++ b/api/grpc/types/api.pb.go @@ -389,15 +389,11 @@ func (*EventsRequest) ProtoMessage() {} func (*EventsRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{24} } type Event struct { - Type string `protobuf:"bytes,1,opt,name=type" json:"type,omitempty"` - Id string `protobuf:"bytes,2,opt,name=id" json:"id,omitempty"` - Status uint32 `protobuf:"varint,3,opt,name=status" json:"status,omitempty"` - BundlePath string `protobuf:"bytes,4,opt,name=bundlePath" json:"bundlePath,omitempty"` - Pid string `protobuf:"bytes,5,opt,name=pid" json:"pid,omitempty"` - Signal uint32 `protobuf:"varint,7,opt,name=signal" json:"signal,omitempty"` - Process *Process `protobuf:"bytes,8,opt,name=process" json:"process,omitempty"` - Containers []*Container `protobuf:"bytes,9,rep,name=containers" json:"containers,omitempty"` - Checkpoint *Checkpoint `protobuf:"bytes,10,opt,name=checkpoint" json:"checkpoint,omitempty"` + Type string `protobuf:"bytes,1,opt,name=type" json:"type,omitempty"` + Id string `protobuf:"bytes,2,opt,name=id" json:"id,omitempty"` + Status uint32 `protobuf:"varint,3,opt,name=status" json:"status,omitempty"` + Pid string `protobuf:"bytes,4,opt,name=pid" json:"pid,omitempty"` + Timestamp uint64 `protobuf:"varint,5,opt,name=timestamp" json:"timestamp,omitempty"` } func (m *Event) Reset() { *m = Event{} } @@ -405,27 +401,6 @@ func (m *Event) String() string { return proto.CompactTextString(m) } func (*Event) ProtoMessage() {} func (*Event) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{25} } -func (m *Event) GetProcess() *Process { - if m != nil { - return m.Process - } - return nil -} - -func (m *Event) GetContainers() []*Container { - if m != nil { - return m.Containers - } - return nil -} - -func (m *Event) GetCheckpoint() *Checkpoint { - if m != nil { - return m.Checkpoint - } - return nil -} - type NetworkStats struct { Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` RxBytes uint64 `protobuf:"varint,2,opt,name=rx_bytes" json:"rx_bytes,omitempty"` @@ -1118,102 +1093,100 @@ var _API_serviceDesc = grpc.ServiceDesc{ } var fileDescriptor0 = []byte{ - // 1542 bytes of a gzipped FileDescriptorProto + // 1517 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xb4, 0x58, 0xd9, 0x6e, 0x1c, 0x45, 0x17, 0xf6, 0xec, 0x33, 0x67, 0x16, 0xdb, 0xed, 0x6d, 0x3c, 0xf9, 0xf3, 0xc7, 0x74, 0x02, 0x89, - 0x50, 0x64, 0x05, 0x87, 0x25, 0x04, 0x09, 0x08, 0x4e, 0x44, 0x40, 0x09, 0x58, 0xb1, 0x8d, 0xc4, - 0x0d, 0xa3, 0x9e, 0xee, 0x62, 0xa6, 0x71, 0x6f, 0x74, 0x55, 0x7b, 0x79, 0x85, 0x70, 0xcf, 0x5b, - 0x20, 0x71, 0xc5, 0x03, 0xf0, 0x04, 0x3c, 0x07, 0x4f, 0xc1, 0xa9, 0xa5, 0x6b, 0xba, 0x7b, 0x16, - 0x93, 0x0b, 0x6e, 0x46, 0xaa, 0xaa, 0xb3, 0x7c, 0xe7, 0x3b, 0x4b, 0x57, 0x0d, 0xb4, 0xac, 0xc8, - 0xdd, 0x8f, 0xe2, 0x90, 0x85, 0x46, 0x8d, 0x5d, 0x45, 0x84, 0x9a, 0x23, 0xd8, 0x3c, 0x8d, 0x1c, - 0x8b, 0x91, 0xa3, 0x38, 0xb4, 0x09, 0xa5, 0xaf, 0xc8, 0xcf, 0x09, 0xa1, 0xcc, 0x00, 0x28, 0xbb, - 0x4e, 0xbf, 0xb4, 0x57, 0xba, 0xd7, 0x32, 0xda, 0x50, 0x89, 0x70, 0x51, 0x16, 0x0b, 0x3c, 0xb1, - 0xbd, 0x90, 0x92, 0x63, 0xe6, 0xb8, 0x41, 0xbf, 0x82, 0x7b, 0x4d, 0xa3, 0x0b, 0xb5, 0x0b, 0xd7, - 0x61, 0x93, 0x7e, 0x15, 0x97, 0x5d, 0xa3, 0x07, 0xf5, 0x09, 0x71, 0xc7, 0x13, 0xd6, 0xaf, 0xf1, - 0xb5, 0xb9, 0x03, 0x5b, 0x05, 0x1f, 0x34, 0x0a, 0x03, 0x4a, 0xcc, 0x5f, 0x4a, 0xb0, 0x7d, 0x18, - 0x13, 0x3c, 0x39, 0x0c, 0x03, 0x66, 0xb9, 0x01, 0x89, 0xe7, 0xf9, 0xc7, 0xc5, 0x28, 0x09, 0x1c, - 0x8f, 0x1c, 0x59, 0xe8, 0x63, 0x0a, 0x63, 0x42, 0xec, 0xb3, 0x28, 0x74, 0x03, 0x26, 0x60, 0xb4, - 0x38, 0x0c, 0x2a, 0x50, 0x55, 0xc5, 0x12, 0x61, 0xe0, 0x32, 0x4c, 0x24, 0x8c, 0x74, 0x4d, 0xe2, - 0xb8, 0x5f, 0x4f, 0xd7, 0x9e, 0x35, 0x22, 0x1e, 0xed, 0x37, 0xf6, 0x2a, 0xf7, 0x5a, 0xe6, 0xa7, - 0xb0, 0x33, 0x03, 0x46, 0x02, 0x35, 0x6e, 0x43, 0xcb, 0x4e, 0x37, 0x05, 0xa8, 0xf6, 0xc1, 0xda, - 0xbe, 0x20, 0x70, 0x5f, 0x0b, 0x9b, 0x8f, 0xa0, 0x7b, 0xec, 0x8e, 0x03, 0xcb, 0xbb, 0x96, 0x43, - 0x8e, 0x44, 0x48, 0x0a, 0xe0, 0x5d, 0x73, 0x0d, 0x7a, 0xa9, 0xa6, 0x62, 0xe6, 0xf7, 0x12, 0xac, - 0x3f, 0x71, 0x9c, 0x25, 0x49, 0x59, 0x83, 0x26, 0x23, 0xb1, 0xef, 0x72, 0x2b, 0x65, 0x91, 0x85, - 0x5d, 0xa8, 0x26, 0x14, 0xf1, 0x55, 0x04, 0xbe, 0xb6, 0xc2, 0x77, 0x8a, 0x5b, 0x46, 0x07, 0xaa, - 0x56, 0x3c, 0xa6, 0x48, 0x4c, 0x45, 0x62, 0x21, 0xc1, 0x39, 0xb2, 0xa2, 0x16, 0xf6, 0x85, 0xa3, - 0x28, 0x51, 0x28, 0x1b, 0x79, 0x3a, 0x9b, 0x05, 0x3a, 0x5b, 0x05, 0x3a, 0x81, 0xaf, 0x31, 0xfc, - 0xaa, 0xf0, 0x85, 0x36, 0x12, 0x85, 0xb2, 0xcb, 0x17, 0x63, 0x15, 0x76, 0xd7, 0xd8, 0x86, 0x9e, - 0xe5, 0x38, 0x2e, 0x73, 0x43, 0x04, 0xfd, 0xa5, 0xeb, 0x50, 0x84, 0x5a, 0xc1, 0xf0, 0x37, 0xc1, - 0xc8, 0xc6, 0xaa, 0x28, 0x78, 0xa1, 0xd3, 0xa1, 0xf3, 0x3c, 0x8f, 0x87, 0xb7, 0x73, 0x85, 0x50, - 0x16, 0xb1, 0xaf, 0xa7, 0xb9, 0xd1, 0x07, 0xe6, 0x00, 0xfa, 0xb3, 0xd6, 0x94, 0xa7, 0x87, 0xb0, - 0xf3, 0x94, 0x78, 0xe4, 0x3a, 0x4f, 0x48, 0x62, 0x60, 0xf9, 0x44, 0xe6, 0x90, 0x1b, 0x9c, 0x55, - 0x52, 0x06, 0x6f, 0xc3, 0xd6, 0x0b, 0x97, 0xb2, 0xa5, 0xe6, 0xcc, 0xef, 0x01, 0xa6, 0x02, 0xda, - 0xb8, 0x76, 0x45, 0x2e, 0x5d, 0xa6, 0x12, 0x8b, 0x24, 0x32, 0x3b, 0x52, 0xbd, 0xb6, 0x01, 0xed, - 0x24, 0x70, 0x2f, 0x8f, 0x43, 0xfb, 0x8c, 0x30, 0x2a, 0x4a, 0x5d, 0x34, 0x20, 0x9d, 0x10, 0xcf, - 0x13, 0x95, 0xde, 0x34, 0x3f, 0x87, 0xed, 0xa2, 0x7f, 0x55, 0xc8, 0xef, 0x40, 0x7b, 0xca, 0x16, - 0x45, 0x6f, 0x95, 0x45, 0x74, 0x75, 0x8e, 0x19, 0xb2, 0x35, 0x0f, 0xf8, 0x1e, 0xf4, 0x74, 0xd1, - 0x0b, 0x21, 0x59, 0x0a, 0x16, 0x4b, 0xa8, 0x92, 0xf8, 0xad, 0x04, 0x0d, 0x95, 0xce, 0xb4, 0xa4, - 0xfe, 0xc3, 0xa2, 0x5d, 0x87, 0x16, 0xbd, 0xa2, 0x8c, 0xf8, 0x47, 0xaa, 0x74, 0xbb, 0x6f, 0x5a, - 0xba, 0xaf, 0x4b, 0xd0, 0xd2, 0x21, 0x2d, 0xce, 0x79, 0x61, 0x10, 0xc9, 0xa1, 0xf3, 0x16, 0xb4, - 0x22, 0x19, 0x2a, 0x91, 0x50, 0xdb, 0x07, 0x3d, 0x15, 0x45, 0x4a, 0xc1, 0x94, 0x9e, 0x5a, 0x61, - 0xf0, 0xd4, 0x45, 0x34, 0xe8, 0x24, 0xe2, 0xdd, 0xd0, 0x10, 0xdd, 0x70, 0x17, 0x1a, 0x2f, 0x2d, - 0x7b, 0x82, 0x50, 0xf8, 0x81, 0x1d, 0x29, 0x56, 0xc5, 0x58, 0xf5, 0x89, 0x1f, 0xc6, 0x57, 0x02, - 0x4d, 0xd5, 0xfc, 0x0e, 0xe7, 0x8d, 0xcc, 0x91, 0x4a, 0xee, 0x1d, 0x6c, 0x85, 0x34, 0x8a, 0x34, - 0xb7, 0x33, 0x63, 0xca, 0xb8, 0x05, 0x0d, 0x5f, 0xda, 0x57, 0xdd, 0x92, 0xc2, 0x55, 0x5e, 0xcd, - 0x27, 0xb0, 0x2d, 0xc7, 0xf5, 0xd2, 0xa1, 0x3c, 0x33, 0xd0, 0x64, 0x84, 0x82, 0x14, 0x73, 0x17, - 0x76, 0x66, 0x4c, 0xa8, 0xde, 0x58, 0x85, 0xee, 0xb3, 0x73, 0x82, 0xc5, 0xa7, 0x8c, 0x9a, 0x7f, - 0x95, 0xa0, 0x26, 0x76, 0x78, 0xb8, 0x1c, 0x89, 0x72, 0x20, 0x9d, 0xcd, 0xb3, 0xdf, 0x2d, 0x24, - 0xa2, 0x9a, 0x05, 0x54, 0x2b, 0x4c, 0x58, 0x59, 0x10, 0x18, 0xb4, 0xca, 0x92, 0x28, 0x89, 0xd9, - 0x1c, 0xe5, 0xb9, 0x6b, 0x2d, 0xe0, 0x2e, 0x3f, 0x6c, 0x60, 0xd1, 0xb0, 0xf9, 0xa3, 0x04, 0x9d, - 0x6f, 0x08, 0xbb, 0x08, 0xe3, 0x33, 0x9e, 0x21, 0x5a, 0xe8, 0x6e, 0xec, 0x82, 0xf8, 0x72, 0x38, - 0xba, 0x62, 0x58, 0x31, 0x22, 0x95, 0x3c, 0x1e, 0xdc, 0x39, 0xb2, 0x64, 0x4f, 0x57, 0xc4, 0x1e, - 0x96, 0xf5, 0xab, 0xcb, 0x21, 0x16, 0x69, 0x18, 0xcb, 0x36, 0x17, 0x62, 0xb8, 0xe5, 0xc4, 0x61, - 0x14, 0x11, 0x19, 0x69, 0x95, 0x1b, 0x3b, 0x49, 0x8d, 0xd5, 0x53, 0x29, 0xdc, 0x89, 0x94, 0xb1, - 0x46, 0x6a, 0xec, 0x44, 0x1b, 0x6b, 0x66, 0xc4, 0x52, 0x63, 0x2d, 0x51, 0x52, 0x3e, 0x34, 0x0f, - 0xa3, 0xe4, 0x94, 0x5a, 0x63, 0xc2, 0x07, 0x0d, 0x0b, 0x99, 0xe5, 0x0d, 0x13, 0xbe, 0x14, 0xd0, - 0xab, 0xc6, 0x26, 0x74, 0x22, 0x12, 0x63, 0x51, 0xaa, 0xdd, 0x32, 0x12, 0x55, 0x35, 0x6e, 0xc0, - 0x86, 0x58, 0x0e, 0xdd, 0x60, 0x78, 0x46, 0xe2, 0x80, 0x78, 0x7e, 0xe8, 0x10, 0x15, 0xc7, 0x2e, - 0xac, 0xeb, 0x43, 0xde, 0xea, 0xe2, 0x48, 0xc4, 0x63, 0x9e, 0x40, 0xef, 0x64, 0x82, 0xb7, 0x11, - 0xe6, 0xb9, 0xc1, 0xf8, 0xa9, 0xc5, 0x2c, 0x63, 0x15, 0xf3, 0x44, 0x62, 0x37, 0x74, 0xa8, 0x72, - 0x88, 0xda, 0x4c, 0x8a, 0x10, 0x67, 0x98, 0x1e, 0x49, 0xd2, 0xf0, 0x73, 0x32, 0x3d, 0x62, 0xae, - 0xaf, 0x1c, 0x9a, 0x3f, 0x88, 0x20, 0x24, 0xf1, 0x26, 0x7e, 0xb8, 0x35, 0x58, 0xf9, 0xe1, 0x5e, - 0x4d, 0xf3, 0x95, 0x06, 0xba, 0x0f, 0xab, 0x4c, 0xa3, 0x18, 0x62, 0xd5, 0x5a, 0xaa, 0x31, 0xb6, - 0x94, 0x64, 0x1e, 0xa3, 0xf9, 0x19, 0xc0, 0x4b, 0xd1, 0x87, 0x02, 0x31, 0x8e, 0x9a, 0x2c, 0x41, - 0x48, 0xb4, 0x6f, 0x5d, 0x6a, 0x76, 0xf8, 0x16, 0xc6, 0xf4, 0xa3, 0xe5, 0x7a, 0xb6, 0xba, 0xa7, - 0x54, 0xcd, 0xbf, 0x4b, 0xd0, 0x96, 0x16, 0x24, 0x48, 0x34, 0x61, 0x63, 0xef, 0xa5, 0x26, 0xf6, - 0x52, 0x8b, 0xf9, 0x8f, 0x59, 0xc6, 0x27, 0x96, 0x21, 0xbd, 0xb0, 0x22, 0xe5, 0xa5, 0xb2, 0x48, - 0xec, 0x2e, 0x74, 0x64, 0x36, 0x94, 0x60, 0x75, 0x91, 0xe0, 0x7d, 0x3e, 0x2e, 0x11, 0x89, 0x98, - 0xae, 0xed, 0x83, 0x9b, 0x39, 0x09, 0x81, 0x71, 0x5f, 0xfc, 0x3e, 0x0b, 0x58, 0x7c, 0x35, 0xb8, - 0x0f, 0x30, 0x5d, 0xf1, 0xb6, 0x3b, 0x23, 0x57, 0xaa, 0xb2, 0x31, 0x92, 0x73, 0xcb, 0x4b, 0x54, - 0xe4, 0x8f, 0xcb, 0x8f, 0x4a, 0xe6, 0xd7, 0xb0, 0xfa, 0x85, 0x77, 0xe6, 0x86, 0x19, 0x15, 0x94, - 0xf2, 0xad, 0x9f, 0xc2, 0x58, 0xc5, 0xcb, 0x97, 0x6e, 0x80, 0x4b, 0x49, 0x17, 0xf6, 0x7d, 0x18, - 0x4d, 0x6f, 0x74, 0xd2, 0x9e, 0xac, 0x97, 0x3f, 0x2b, 0x00, 0x53, 0x63, 0xc6, 0x63, 0x18, 0xb8, - 0xe1, 0x10, 0x4b, 0xea, 0xdc, 0xb5, 0x89, 0x6c, 0x81, 0x61, 0x4c, 0xec, 0x24, 0xa6, 0xee, 0x39, - 0x51, 0xf3, 0x6f, 0x5b, 0xc5, 0x52, 0xc4, 0xf0, 0x01, 0x6c, 0x4d, 0x75, 0x9d, 0x8c, 0x5a, 0x79, - 0xa9, 0xda, 0x43, 0xd8, 0x40, 0x35, 0x1c, 0x5c, 0x49, 0x4e, 0xa9, 0xb2, 0x54, 0xe9, 0x63, 0xd8, - 0xcd, 0xe0, 0xe4, 0x95, 0x9a, 0x51, 0xad, 0x2e, 0x55, 0xfd, 0x10, 0xb6, 0x51, 0xf5, 0xc2, 0x72, - 0x59, 0x51, 0xaf, 0xf6, 0x2f, 0x70, 0xfa, 0x24, 0x1e, 0xe7, 0x70, 0xd6, 0x97, 0x2a, 0xbd, 0x07, - 0xeb, 0xa8, 0x54, 0xf0, 0xd3, 0xb8, 0x4e, 0x85, 0x12, 0x9b, 0xe1, 0x54, 0xc9, 0xa8, 0x34, 0x97, - 0xa9, 0xe0, 0xe7, 0xa5, 0xf3, 0x3c, 0x19, 0x13, 0xe6, 0x8d, 0x74, 0xf5, 0xbf, 0x69, 0x03, 0xbd, - 0x2e, 0x43, 0xfb, 0x70, 0x1c, 0x87, 0x49, 0x94, 0xeb, 0x72, 0x59, 0xc3, 0x33, 0x5d, 0x2e, 0x65, - 0xee, 0x41, 0x47, 0x7e, 0x3d, 0x95, 0x98, 0x6c, 0x2e, 0x63, 0xb6, 0xd4, 0xf9, 0x1d, 0x69, 0xc4, - 0x31, 0x2b, 0xc1, 0x7c, 0x7b, 0x65, 0xca, 0xef, 0x13, 0xe8, 0x4e, 0x64, 0x20, 0x4a, 0x52, 0xa6, - 0xf2, 0x4e, 0xea, 0x79, 0x0a, 0x70, 0x3f, 0x1b, 0xb0, 0x6c, 0xa2, 0xe7, 0xb0, 0x3e, 0xb3, 0x99, - 0xef, 0x25, 0x33, 0xdb, 0x4b, 0xed, 0x83, 0x0d, 0x65, 0x36, 0xab, 0x25, 0x1a, 0xec, 0x52, 0x5e, - 0x03, 0xf4, 0xc5, 0xd9, 0x78, 0x17, 0xba, 0x81, 0xfc, 0xf8, 0x68, 0x46, 0x2a, 0x19, 0x03, 0xb9, - 0x0f, 0x13, 0xb2, 0x62, 0x0b, 0x9c, 0x73, 0x59, 0xc9, 0x72, 0x8c, 0x79, 0xe1, 0x95, 0x81, 0x62, - 0x7e, 0xa4, 0xd2, 0xa0, 0x2e, 0x89, 0xf3, 0x9e, 0x27, 0x07, 0xbf, 0xd6, 0xa1, 0xf2, 0xe4, 0xe8, - 0x2b, 0xe3, 0x15, 0xac, 0x16, 0x1e, 0x55, 0x46, 0x3a, 0x5e, 0xe6, 0xbf, 0xfc, 0x06, 0xff, 0x5f, - 0x74, 0xac, 0x2e, 0x10, 0x2b, 0xdc, 0x66, 0xe1, 0x76, 0xa1, 0x6d, 0xce, 0xbf, 0xb8, 0x68, 0x9b, - 0x8b, 0x2e, 0x25, 0x2b, 0xc6, 0x47, 0x50, 0x97, 0x4f, 0x30, 0x63, 0x53, 0xc9, 0xe6, 0xde, 0x72, - 0x83, 0xad, 0xc2, 0xae, 0x56, 0x7c, 0x01, 0xdd, 0xdc, 0xe3, 0xd6, 0xb8, 0x91, 0xf3, 0x95, 0x7f, - 0xc1, 0x0d, 0xfe, 0x37, 0xff, 0x50, 0x5b, 0x3b, 0x04, 0x98, 0x3e, 0x85, 0x8c, 0xbe, 0x92, 0x9e, - 0x79, 0x09, 0x0e, 0x76, 0xe7, 0x9c, 0x68, 0x23, 0xa7, 0xb0, 0x56, 0x7c, 0xeb, 0x18, 0x05, 0x56, - 0x8b, 0x2f, 0x93, 0xc1, 0xad, 0x85, 0xe7, 0x59, 0xb3, 0xc5, 0x17, 0x8f, 0x36, 0xbb, 0xe0, 0xfd, - 0xa4, 0xcd, 0x2e, 0x7c, 0x2a, 0xad, 0x18, 0xdf, 0x42, 0x2f, 0xff, 0x58, 0x31, 0x52, 0x92, 0xe6, - 0xbe, 0xa1, 0x06, 0x37, 0x17, 0x9c, 0x6a, 0x83, 0xef, 0x43, 0x4d, 0x3e, 0x4b, 0xd2, 0x8a, 0xcf, - 0xbe, 0x64, 0x06, 0x9b, 0xf9, 0x4d, 0xad, 0xf5, 0x00, 0xea, 0xf2, 0x5e, 0xaa, 0x0b, 0x20, 0x77, - 0x4d, 0x1d, 0x74, 0xb2, 0xbb, 0xe6, 0xca, 0x83, 0x52, 0xea, 0x87, 0xe6, 0xfc, 0xd0, 0x79, 0x7e, - 0x32, 0xc9, 0x19, 0xd5, 0xc5, 0xdf, 0x2f, 0x0f, 0xff, 0x09, 0x00, 0x00, 0xff, 0xff, 0x7e, 0x37, - 0x3f, 0x0d, 0x8b, 0x11, 0x00, 0x00, + 0x50, 0x64, 0x05, 0x87, 0x25, 0x04, 0x09, 0x08, 0x4e, 0x44, 0x40, 0x09, 0x98, 0xd8, 0x46, 0xe2, + 0x86, 0x51, 0x4f, 0x77, 0x31, 0xd3, 0xb8, 0x37, 0xba, 0xaa, 0xbd, 0xbc, 0x42, 0xb8, 0xe7, 0x2d, + 0x90, 0xb8, 0xe2, 0x01, 0x78, 0x1c, 0x9e, 0x82, 0xd3, 0xb5, 0x4d, 0x77, 0xcf, 0x62, 0x72, 0xc1, + 0xcd, 0x48, 0x55, 0x75, 0xce, 0x77, 0xbe, 0xb3, 0x55, 0xf5, 0x19, 0x68, 0x59, 0x91, 0xbb, 0x1f, + 0xc5, 0x21, 0x0b, 0x8d, 0x1a, 0xbb, 0x8a, 0x08, 0x35, 0x47, 0xb0, 0x79, 0x1a, 0x39, 0x16, 0x23, + 0x47, 0x71, 0x68, 0x13, 0x4a, 0x5f, 0x91, 0x5f, 0x12, 0x42, 0x99, 0x01, 0x50, 0x76, 0x9d, 0x7e, + 0x69, 0xaf, 0x74, 0xaf, 0x65, 0xb4, 0xa1, 0x12, 0xe1, 0xa2, 0xcc, 0x17, 0x78, 0x62, 0x7b, 0x21, + 0x25, 0xc7, 0xcc, 0x71, 0x83, 0x7e, 0x05, 0xf7, 0x9a, 0x46, 0x17, 0x6a, 0x17, 0xae, 0xc3, 0x26, + 0xfd, 0x2a, 0x2e, 0xbb, 0x46, 0x0f, 0xea, 0x13, 0xe2, 0x8e, 0x27, 0xac, 0x5f, 0x4b, 0xd7, 0xe6, + 0x0e, 0x6c, 0x15, 0x6c, 0xd0, 0x28, 0x0c, 0x28, 0x31, 0x7f, 0x2d, 0xc1, 0xf6, 0x61, 0x4c, 0xf0, + 0xe4, 0x30, 0x0c, 0x98, 0xe5, 0x06, 0x24, 0x9e, 0x67, 0x1f, 0x17, 0xa3, 0x24, 0x70, 0x3c, 0x72, + 0x64, 0xa1, 0x8d, 0x29, 0x8d, 0x09, 0xb1, 0xcf, 0xa2, 0xd0, 0x0d, 0x18, 0xa7, 0xd1, 0x4a, 0x69, + 0x50, 0xce, 0xaa, 0xca, 0x97, 0x48, 0x03, 0x97, 0x61, 0x22, 0x68, 0xa8, 0x35, 0x89, 0xe3, 0x7e, + 0x5d, 0xad, 0x3d, 0x6b, 0x44, 0x3c, 0xda, 0x6f, 0xec, 0x55, 0xee, 0xb5, 0xcc, 0x4f, 0x61, 0x67, + 0x86, 0x8c, 0x20, 0x6a, 0xdc, 0x86, 0x96, 0xad, 0x36, 0x39, 0xa9, 0xf6, 0xc1, 0xda, 0x3e, 0x0f, + 0xe0, 0xbe, 0x16, 0x36, 0x1f, 0x41, 0xf7, 0xd8, 0x1d, 0x07, 0x96, 0x77, 0x6d, 0x0c, 0x53, 0x26, + 0x5c, 0x92, 0x13, 0xef, 0x9a, 0x6b, 0xd0, 0x53, 0x9a, 0x32, 0x32, 0x7f, 0x94, 0x60, 0xfd, 0x89, + 0xe3, 0x2c, 0x49, 0xca, 0x1a, 0x34, 0x19, 0x89, 0x7d, 0x37, 0x45, 0x29, 0xf3, 0x2c, 0xec, 0x42, + 0x35, 0xa1, 0xc8, 0xaf, 0xc2, 0xf9, 0xb5, 0x25, 0xbf, 0x53, 0xdc, 0x32, 0x3a, 0x50, 0xb5, 0xe2, + 0x31, 0xc5, 0xc0, 0x54, 0x04, 0x17, 0x12, 0x9c, 0x63, 0x54, 0xe4, 0xc2, 0xbe, 0x70, 0x64, 0x48, + 0x24, 0xcb, 0x46, 0x3e, 0x9c, 0xcd, 0x42, 0x38, 0x5b, 0x85, 0x70, 0x42, 0xba, 0x46, 0xf7, 0xab, + 0xdc, 0x16, 0x62, 0x24, 0x92, 0x65, 0x37, 0x5d, 0x8c, 0xa5, 0xdb, 0x5d, 0x63, 0x1b, 0x7a, 0x96, + 0xe3, 0xb8, 0xcc, 0x0d, 0x91, 0xf4, 0x97, 0xae, 0x43, 0x91, 0x6a, 0x05, 0xdd, 0xdf, 0x04, 0x23, + 0xeb, 0xab, 0x0c, 0xc1, 0x0b, 0x9d, 0x0e, 0x9d, 0xe7, 0x79, 0x71, 0x78, 0x3b, 0x57, 0x08, 0x65, + 0xee, 0xfb, 0xba, 0xca, 0x8d, 0x3e, 0x30, 0x07, 0xd0, 0x9f, 0x45, 0x93, 0x96, 0x1e, 0xc2, 0xce, + 0x53, 0xe2, 0x91, 0xeb, 0x2c, 0x61, 0x10, 0x03, 0xcb, 0x27, 0x22, 0x87, 0x29, 0xe0, 0xac, 0x92, + 0x04, 0xbc, 0x0d, 0x5b, 0x2f, 0x5c, 0xca, 0x96, 0xc2, 0x99, 0x3f, 0x00, 0x4c, 0x05, 0x34, 0xb8, + 0x36, 0x45, 0x2e, 0x5d, 0x26, 0x13, 0x8b, 0x41, 0x64, 0x76, 0x24, 0x7b, 0x6d, 0x03, 0xda, 0x49, + 0xe0, 0x5e, 0x1e, 0x87, 0xf6, 0x19, 0x61, 0x94, 0x97, 0x3a, 0x6f, 0x40, 0x3a, 0x21, 0x9e, 0xc7, + 0x2b, 0xbd, 0x69, 0x7e, 0x0e, 0xdb, 0x45, 0xfb, 0xb2, 0x90, 0xdf, 0x81, 0xf6, 0x34, 0x5a, 0x14, + 0xad, 0x55, 0x16, 0x85, 0xab, 0x73, 0xcc, 0x30, 0x5a, 0xf3, 0x88, 0xef, 0x41, 0x4f, 0x17, 0x3d, + 0x17, 0x12, 0xa5, 0x60, 0xb1, 0x84, 0x4a, 0x89, 0xdf, 0x4b, 0xd0, 0x90, 0xe9, 0x54, 0x25, 0xf5, + 0x1f, 0x16, 0xed, 0x3a, 0xb4, 0xe8, 0x15, 0x65, 0xc4, 0x3f, 0x92, 0xa5, 0xdb, 0x7d, 0xd3, 0xd2, + 0x7d, 0x5d, 0x82, 0x96, 0x76, 0x69, 0x71, 0xce, 0x0b, 0x17, 0x91, 0xb8, 0x74, 0xde, 0x82, 0x56, + 0x24, 0x5c, 0x25, 0x82, 0x6a, 0xfb, 0xa0, 0x27, 0xbd, 0x50, 0x21, 0x98, 0x86, 0xa7, 0x56, 0xb8, + 0x78, 0xea, 0xdc, 0x1b, 0x34, 0x12, 0xa5, 0xdd, 0xd0, 0xe0, 0xdd, 0x70, 0x17, 0x1a, 0x2f, 0x2d, + 0x7b, 0x82, 0x54, 0xd2, 0x03, 0x3b, 0x92, 0x51, 0xe5, 0xd7, 0xaa, 0x4f, 0xfc, 0x30, 0xbe, 0xe2, + 0x6c, 0xaa, 0xe6, 0xf7, 0x78, 0xdf, 0x88, 0x1c, 0xc9, 0xe4, 0xde, 0xc1, 0x56, 0x50, 0x5e, 0xa8, + 0xdc, 0xce, 0x5c, 0x53, 0xc6, 0x2d, 0x68, 0xf8, 0x02, 0x5f, 0x76, 0x8b, 0xa2, 0x2b, 0xad, 0x9a, + 0x4f, 0x60, 0x5b, 0x5c, 0xd7, 0x4b, 0x2f, 0xe5, 0x99, 0x0b, 0x4d, 0x78, 0xc8, 0x83, 0x62, 0xee, + 0xc2, 0xce, 0x0c, 0x84, 0xec, 0x8d, 0x55, 0xe8, 0x3e, 0x3b, 0x27, 0x58, 0x7c, 0x12, 0xd4, 0xfc, + 0x0e, 0x6a, 0x7c, 0x23, 0xf5, 0x36, 0x25, 0x22, 0xf1, 0x85, 0xad, 0x79, 0xf0, 0x5d, 0x65, 0xbb, + 0xaa, 0xd2, 0xcf, 0x5c, 0x1f, 0x91, 0x2c, 0x3f, 0xe2, 0x01, 0xae, 0x9a, 0x7f, 0x96, 0xa0, 0xf3, + 0x0d, 0x61, 0x17, 0x61, 0x7c, 0x96, 0x46, 0x88, 0x16, 0xba, 0x0b, 0xab, 0x30, 0xbe, 0x1c, 0x8e, + 0xae, 0x18, 0x66, 0x8c, 0x87, 0x32, 0x4d, 0x2c, 0xee, 0x1c, 0x59, 0xa2, 0xa7, 0x2a, 0x7c, 0x0f, + 0x71, 0x5f, 0x5d, 0x0e, 0xb1, 0x48, 0xc2, 0x58, 0xb4, 0x19, 0x17, 0xc3, 0x2d, 0x27, 0x0e, 0xa3, + 0x88, 0x38, 0xc2, 0x56, 0x0a, 0x76, 0xa2, 0xc0, 0xea, 0x4a, 0x0a, 0x77, 0x22, 0x09, 0xd6, 0x50, + 0x60, 0x27, 0x1a, 0xac, 0x99, 0x11, 0x53, 0x60, 0x2d, 0x4e, 0xdc, 0x87, 0xe6, 0x61, 0x94, 0x9c, + 0x52, 0x6b, 0x4c, 0xd2, 0x46, 0x67, 0x21, 0xb3, 0xbc, 0x61, 0x92, 0x2e, 0x39, 0xf5, 0xaa, 0xb1, + 0x09, 0x9d, 0x88, 0xc4, 0x58, 0x14, 0x72, 0xb7, 0x8c, 0x49, 0xae, 0x1a, 0x37, 0x60, 0x83, 0x2f, + 0x87, 0x6e, 0x30, 0x3c, 0x23, 0x71, 0x40, 0x3c, 0x3f, 0x74, 0x88, 0xf4, 0x63, 0x17, 0xd6, 0xf5, + 0x61, 0xda, 0x6a, 0xfc, 0x88, 0xfb, 0x63, 0x9e, 0x40, 0xef, 0x64, 0x82, 0x5f, 0x03, 0xcc, 0x73, + 0x83, 0xf1, 0x53, 0x8b, 0x59, 0xc6, 0x2a, 0x34, 0x10, 0xdf, 0x0d, 0x1d, 0x2a, 0x0d, 0xa2, 0x36, + 0x13, 0x22, 0xc4, 0x19, 0xaa, 0x23, 0x11, 0x34, 0xbc, 0xce, 0xa7, 0x47, 0x69, 0x0a, 0x84, 0x41, + 0xf3, 0x47, 0xee, 0x84, 0x08, 0xbc, 0x89, 0x0f, 0xa7, 0x26, 0x2b, 0x1e, 0xce, 0x55, 0x55, 0x91, + 0xca, 0xd1, 0x7d, 0x58, 0x65, 0x9a, 0xc5, 0x10, 0xab, 0xc6, 0x92, 0x85, 0xb9, 0x25, 0x25, 0xf3, + 0x1c, 0xcd, 0xcf, 0x00, 0x5e, 0xf2, 0x3e, 0xe0, 0x8c, 0xb1, 0xd5, 0xb3, 0x01, 0xc2, 0x40, 0xfb, + 0xd6, 0xa5, 0x8e, 0x4e, 0xba, 0x85, 0x3e, 0xfd, 0x64, 0xb9, 0x9e, 0x2d, 0xbf, 0x13, 0xaa, 0xe6, + 0xdf, 0x25, 0x68, 0x0b, 0x04, 0x41, 0x12, 0x21, 0x6c, 0xac, 0x7d, 0x05, 0xb1, 0xa7, 0x10, 0xf3, + 0x8f, 0x49, 0xc6, 0x26, 0xbe, 0x39, 0xf4, 0xc2, 0x8a, 0xa4, 0x95, 0xca, 0x22, 0xb1, 0xbb, 0xd0, + 0x11, 0xd9, 0x90, 0x82, 0xd5, 0x45, 0x82, 0xf7, 0xd3, 0xeb, 0x0a, 0x99, 0xf0, 0xdb, 0xad, 0x7d, + 0x70, 0x33, 0x27, 0xc1, 0x39, 0xee, 0xf3, 0xdf, 0x67, 0x01, 0x8b, 0xaf, 0x06, 0xf7, 0x01, 0xa6, + 0xab, 0xb4, 0x17, 0xce, 0xc8, 0x95, 0xac, 0x6c, 0xf4, 0xe4, 0xdc, 0xf2, 0x12, 0xe9, 0xf9, 0xe3, + 0xf2, 0xa3, 0x92, 0xf9, 0x35, 0xac, 0x7e, 0xe1, 0x9d, 0xb9, 0x61, 0x46, 0x05, 0xa5, 0x7c, 0xeb, + 0xe7, 0x30, 0x96, 0xfe, 0xa6, 0x4b, 0x37, 0xc0, 0xa5, 0x08, 0x17, 0x36, 0x5e, 0x18, 0x4d, 0xbf, + 0xa8, 0x04, 0x9e, 0xa8, 0x97, 0xbf, 0x2a, 0x00, 0x53, 0x30, 0xe3, 0x31, 0x0c, 0xdc, 0x70, 0x88, + 0x25, 0x75, 0xee, 0xda, 0x44, 0xb4, 0xc0, 0x30, 0x26, 0x76, 0x12, 0x53, 0xf7, 0x9c, 0xc8, 0xfb, + 0x67, 0x5b, 0xfa, 0x52, 0xe4, 0xf0, 0x01, 0x6c, 0x4d, 0x75, 0x9d, 0x8c, 0x5a, 0x79, 0xa9, 0xda, + 0x43, 0xd8, 0x40, 0x35, 0xbc, 0x38, 0x92, 0x9c, 0x52, 0x65, 0xa9, 0xd2, 0xc7, 0xb0, 0x9b, 0xe1, + 0x99, 0x56, 0x6a, 0x46, 0xb5, 0xba, 0x54, 0xf5, 0x43, 0xd8, 0x46, 0xd5, 0x0b, 0xcb, 0x65, 0x45, + 0xbd, 0xda, 0xbf, 0xe0, 0xe9, 0x93, 0x78, 0x9c, 0xe3, 0x59, 0x5f, 0xaa, 0xf4, 0x1e, 0xac, 0xa3, + 0x52, 0xc1, 0x4e, 0xe3, 0x3a, 0x15, 0x4a, 0x6c, 0x86, 0xb7, 0x4a, 0x46, 0xa5, 0xb9, 0x4c, 0x05, + 0xaf, 0xf7, 0xce, 0xf3, 0x64, 0x4c, 0x98, 0x37, 0xd2, 0xd5, 0xff, 0xa6, 0x0d, 0xf4, 0xba, 0x0c, + 0xed, 0xc3, 0x71, 0x1c, 0x26, 0x51, 0xae, 0xcb, 0x45, 0x0d, 0xcf, 0x74, 0xb9, 0x90, 0xb9, 0x07, + 0x1d, 0xf1, 0x7a, 0x49, 0x31, 0xd1, 0x5c, 0xc6, 0x6c, 0xa9, 0xa7, 0xdf, 0x28, 0xa3, 0x94, 0xb3, + 0x14, 0xcc, 0xb7, 0x57, 0xa6, 0xfc, 0x3e, 0x81, 0xee, 0x44, 0x38, 0x22, 0x25, 0x45, 0x2a, 0xef, + 0x28, 0xcb, 0x53, 0x82, 0xfb, 0x59, 0x87, 0x45, 0x13, 0x3d, 0x87, 0xf5, 0x99, 0xcd, 0x7c, 0x2f, + 0x99, 0xd9, 0x5e, 0x6a, 0x1f, 0x6c, 0x48, 0xd8, 0xac, 0x16, 0x6f, 0xb0, 0x4b, 0xf1, 0x0c, 0xeb, + 0x0f, 0x57, 0xe3, 0x5d, 0xe8, 0x06, 0xe2, 0xf1, 0xd1, 0x11, 0xa9, 0x64, 0x00, 0x72, 0x0f, 0x13, + 0x46, 0xc5, 0xe6, 0x3c, 0xe7, 0x46, 0x25, 0x1b, 0xe3, 0xdc, 0x33, 0x27, 0xd2, 0x20, 0x3f, 0xd2, + 0xe6, 0x8d, 0x07, 0x07, 0xbf, 0xd5, 0xa1, 0xf2, 0xe4, 0xe8, 0x2b, 0xe3, 0x15, 0xac, 0x16, 0x86, + 0x1a, 0x43, 0x5d, 0x2f, 0xf3, 0x27, 0xaf, 0xc1, 0xff, 0x17, 0x1d, 0xcb, 0x07, 0x7c, 0x25, 0xc5, + 0x2c, 0xbc, 0xee, 0x1a, 0x73, 0xfe, 0x87, 0x83, 0xc6, 0x5c, 0xf4, 0x51, 0xb0, 0x62, 0x7c, 0x04, + 0x75, 0x31, 0x02, 0x19, 0x9b, 0x52, 0x36, 0x37, 0x4b, 0x0d, 0xb6, 0x0a, 0xbb, 0x5a, 0xf1, 0x05, + 0x74, 0x73, 0xc3, 0xa5, 0x71, 0x23, 0x67, 0x2b, 0x3f, 0x41, 0x0d, 0xfe, 0x37, 0xff, 0x50, 0xa3, + 0x1d, 0x02, 0x4c, 0x47, 0x11, 0xa3, 0x2f, 0xa5, 0x67, 0x26, 0xb1, 0xc1, 0xee, 0x9c, 0x13, 0x0d, + 0x72, 0x0a, 0x6b, 0xc5, 0x59, 0xc3, 0x28, 0x44, 0xb5, 0x38, 0x19, 0x0c, 0x6e, 0x2d, 0x3c, 0xcf, + 0xc2, 0x16, 0x27, 0x0e, 0x0d, 0xbb, 0x60, 0x7e, 0xd1, 0xb0, 0x0b, 0x47, 0x95, 0x15, 0xe3, 0x5b, + 0xe8, 0xe5, 0x87, 0x05, 0x43, 0x05, 0x69, 0xee, 0x0c, 0x33, 0xb8, 0xb9, 0xe0, 0x54, 0x03, 0xbe, + 0x0f, 0x35, 0x31, 0x16, 0xa8, 0x8a, 0xcf, 0x4e, 0x12, 0x83, 0xcd, 0xfc, 0xa6, 0xd6, 0x7a, 0x00, + 0x75, 0xf1, 0x5d, 0xa8, 0x0b, 0x20, 0xf7, 0x99, 0x38, 0xe8, 0x64, 0x77, 0xcd, 0x95, 0x07, 0x25, + 0x65, 0x87, 0xe6, 0xec, 0xd0, 0x79, 0x76, 0x32, 0xc9, 0x19, 0xd5, 0xf9, 0xdf, 0x1f, 0x0f, 0xff, + 0x09, 0x00, 0x00, 0xff, 0xff, 0x25, 0xa3, 0x4c, 0x3f, 0x0b, 0x11, 0x00, 0x00, } diff --git a/api/grpc/types/api.proto b/api/grpc/types/api.proto index a9fecb4..475be91 100644 --- a/api/grpc/types/api.proto +++ b/api/grpc/types/api.proto @@ -163,12 +163,8 @@ message Event { string type = 1; string id = 2; uint32 status = 3; - string bundlePath = 4; - string pid = 5; - uint32 signal = 7; - Process process = 8; - repeated Container containers = 9; - Checkpoint checkpoint = 10; + string pid = 4; + uint64 timestamp = 5; } message NetworkStats { diff --git a/containerd/main.go b/containerd/main.go index 62407be..177661d 100644 --- a/containerd/main.go +++ b/containerd/main.go @@ -39,11 +39,6 @@ var daemonFlags = []cli.Flag{ Value: "/run/containerd", Usage: "runtime state directory", }, - cli.IntFlag{ - Name: "c,concurrency", - Value: 10, - Usage: "set the concurrency level for tasks", - }, cli.DurationFlag{ Name: "metrics-interval", Value: 120 * time.Second, @@ -86,7 +81,7 @@ func main() { if err := daemon( context.String("listen"), context.String("state-dir"), - context.Int("concurrency"), + 10, context.Bool("oom-notify"), ); err != nil { logrus.Fatal(err) @@ -171,8 +166,7 @@ func daemon(address, stateDir string, concurrency int, oom bool) error { // setup a standard reaper so that we don't leave any zombies if we are still alive // this is just good practice because we are spawning new processes go reapProcesses() - tasks := make(chan *supervisor.StartTask, concurrency*100) - sv, err := supervisor.New(stateDir, tasks, oom) + sv, err := supervisor.New(stateDir, oom) if err != nil { return err } diff --git a/supervisor/add_process.go b/supervisor/add_process.go index 2a7951b..6801a21 100644 --- a/supervisor/add_process.go +++ b/supervisor/add_process.go @@ -6,13 +6,13 @@ import ( "github.com/docker/containerd/runtime" ) -type AddProcessEvent struct { +type AddProcessTask struct { s *Supervisor } // TODO: add this to worker for concurrent starts??? maybe not because of races where the container // could be stopped and removed... -func (h *AddProcessEvent) Handle(e *Event) error { +func (h *AddProcessTask) Handle(e *Task) error { start := time.Now() ci, ok := h.s.containers[e.ID] if !ok { @@ -27,5 +27,11 @@ func (h *AddProcessEvent) Handle(e *Event) error { } ExecProcessTimer.UpdateSince(start) e.StartResponse <- StartResponse{} + h.s.notifySubscribers(Event{ + Timestamp: time.Now(), + Type: "start-process", + Pid: e.Pid, + ID: e.ID, + }) return nil } diff --git a/supervisor/checkpoint.go b/supervisor/checkpoint.go index a5ae540..53311eb 100644 --- a/supervisor/checkpoint.go +++ b/supervisor/checkpoint.go @@ -1,10 +1,10 @@ package supervisor -type CreateCheckpointEvent struct { +type CreateCheckpointTask struct { s *Supervisor } -func (h *CreateCheckpointEvent) Handle(e *Event) error { +func (h *CreateCheckpointTask) Handle(e *Task) error { i, ok := h.s.containers[e.ID] if !ok { return ErrContainerNotFound @@ -12,11 +12,11 @@ func (h *CreateCheckpointEvent) Handle(e *Event) error { return i.container.Checkpoint(*e.Checkpoint) } -type DeleteCheckpointEvent struct { +type DeleteCheckpointTask struct { s *Supervisor } -func (h *DeleteCheckpointEvent) Handle(e *Event) error { +func (h *DeleteCheckpointTask) Handle(e *Task) error { i, ok := h.s.containers[e.ID] if !ok { return ErrContainerNotFound diff --git a/supervisor/create.go b/supervisor/create.go index d8178e8..a65dea8 100644 --- a/supervisor/create.go +++ b/supervisor/create.go @@ -6,11 +6,11 @@ import ( "github.com/docker/containerd/runtime" ) -type StartEvent struct { +type StartTask struct { s *Supervisor } -func (h *StartEvent) Handle(e *Event) error { +func (h *StartTask) Handle(e *Task) error { start := time.Now() container, err := runtime.New(h.s.stateDir, e.ID, e.BundlePath, e.Labels) if err != nil { @@ -20,7 +20,7 @@ func (h *StartEvent) Handle(e *Event) error { container: container, } ContainersCounter.Inc(1) - task := &StartTask{ + task := &startTask{ Err: e.Err, Container: container, StartResponse: e.StartResponse, diff --git a/supervisor/delete.go b/supervisor/delete.go index efccb56..1a11060 100644 --- a/supervisor/delete.go +++ b/supervisor/delete.go @@ -7,21 +7,22 @@ import ( "github.com/docker/containerd/runtime" ) -type DeleteEvent struct { +type DeleteTask struct { s *Supervisor } -func (h *DeleteEvent) Handle(e *Event) error { +func (h *DeleteTask) Handle(e *Task) error { if i, ok := h.s.containers[e.ID]; ok { start := time.Now() if err := h.deleteContainer(i.container); err != nil { logrus.WithField("error", err).Error("containerd: deleting container") } - h.s.notifySubscribers(&Event{ - Type: ExitEventType, - ID: e.ID, - Status: e.Status, - Pid: e.Pid, + h.s.notifySubscribers(Event{ + Type: "exit", + Timestamp: time.Now(), + ID: e.ID, + Status: e.Status, + Pid: e.Pid, }) ContainersCounter.Dec(1) ContainerDeleteTimer.UpdateSince(start) @@ -29,7 +30,7 @@ func (h *DeleteEvent) Handle(e *Event) error { return nil } -func (h *DeleteEvent) deleteContainer(container runtime.Container) error { +func (h *DeleteTask) deleteContainer(container runtime.Container) error { delete(h.s.containers, container.ID()) return container.Delete() } diff --git a/supervisor/errors.go b/supervisor/errors.go index 9645ef1..7c8cf53 100644 --- a/supervisor/errors.go +++ b/supervisor/errors.go @@ -4,13 +4,13 @@ import "errors" var ( // External errors - ErrEventChanNil = errors.New("containerd: event channel is nil") + ErrTaskChanNil = errors.New("containerd: task channel is nil") ErrBundleNotFound = errors.New("containerd: bundle not found") ErrContainerNotFound = errors.New("containerd: container not found") ErrContainerExists = errors.New("containerd: container already exists") ErrProcessNotFound = errors.New("containerd: processs not found for container") ErrUnknownContainerStatus = errors.New("containerd: unknown container status ") - ErrUnknownEvent = errors.New("containerd: unknown event type") + ErrUnknownTask = errors.New("containerd: unknown task type") // Internal errors errShutdown = errors.New("containerd: supervisor is shutdown") diff --git a/supervisor/exit.go b/supervisor/exit.go index 14ececa..d0673ec 100644 --- a/supervisor/exit.go +++ b/supervisor/exit.go @@ -7,11 +7,11 @@ import ( "github.com/docker/containerd/runtime" ) -type ExitEvent struct { +type ExitTask struct { s *Supervisor } -func (h *ExitEvent) Handle(e *Event) error { +func (h *ExitTask) Handle(e *Task) error { start := time.Now() proc := e.Process status, err := proc.ExitStatus() @@ -23,37 +23,43 @@ func (h *ExitEvent) Handle(e *Event) error { // if the process is the the init process of the container then // fire a separate event for this process if proc.ID() != runtime.InitProcessID { - ne := NewEvent(ExecExitEventType) + ne := NewTask(ExecExitTaskType) ne.ID = proc.Container().ID() ne.Pid = proc.ID() ne.Status = status ne.Process = proc - h.s.SendEvent(ne) + h.s.SendTask(ne) return nil } container := proc.Container() - ne := NewEvent(DeleteEventType) + ne := NewTask(DeleteTaskType) ne.ID = container.ID() ne.Status = status ne.Pid = proc.ID() - h.s.SendEvent(ne) + h.s.SendTask(ne) ExitProcessTimer.UpdateSince(start) return nil } -type ExecExitEvent struct { +type ExecExitTask struct { s *Supervisor } -func (h *ExecExitEvent) Handle(e *Event) error { +func (h *ExecExitTask) Handle(e *Task) error { container := e.Process.Container() // exec process: we remove this process without notifying the main event loop if err := container.RemoveProcess(e.Pid); err != nil { logrus.WithField("error", err).Error("containerd: find container for pid") } - h.s.notifySubscribers(e) + h.s.notifySubscribers(Event{ + Timestamp: time.Now(), + ID: e.ID, + Type: "exit", + Pid: e.Pid, + Status: e.Status, + }) return nil } diff --git a/supervisor/get_containers.go b/supervisor/get_containers.go index aba3400..64acc3f 100644 --- a/supervisor/get_containers.go +++ b/supervisor/get_containers.go @@ -1,10 +1,10 @@ package supervisor -type GetContainersEvent struct { +type GetContainersTask struct { s *Supervisor } -func (h *GetContainersEvent) Handle(e *Event) error { +func (h *GetContainersTask) Handle(e *Task) error { if e.ID != "" { ci := h.s.containers[e.ID] if ci == nil { diff --git a/supervisor/metrics.go b/supervisor/metrics.go index 38e48a7..2ba772a 100644 --- a/supervisor/metrics.go +++ b/supervisor/metrics.go @@ -9,7 +9,7 @@ var ( ContainerStatsTimer = metrics.NewTimer() ContainersCounter = metrics.NewCounter() EventSubscriberCounter = metrics.NewCounter() - EventsCounter = metrics.NewCounter() + TasksCounter = metrics.NewCounter() ExecProcessTimer = metrics.NewTimer() ExitProcessTimer = metrics.NewTimer() EpollFdCounter = metrics.NewCounter() @@ -23,7 +23,7 @@ func Metrics() map[string]interface{} { "container-stats-time": ContainerStatsTimer, "containers": ContainersCounter, "event-subscribers": EventSubscriberCounter, - "events": EventsCounter, + "tasks": TasksCounter, "exec-process-time": ExecProcessTimer, "exit-process-time": ExitProcessTimer, "epoll-fds": EpollFdCounter, diff --git a/supervisor/signal.go b/supervisor/signal.go index b5a7e4c..c88a916 100644 --- a/supervisor/signal.go +++ b/supervisor/signal.go @@ -1,10 +1,10 @@ package supervisor -type SignalEvent struct { +type SignalTask struct { s *Supervisor } -func (h *SignalEvent) Handle(e *Event) error { +func (h *SignalTask) Handle(e *Task) error { i, ok := h.s.containers[e.ID] if !ok { return ErrContainerNotFound diff --git a/supervisor/stats.go b/supervisor/stats.go index 7ca44a0..6cbbfed 100644 --- a/supervisor/stats.go +++ b/supervisor/stats.go @@ -2,11 +2,11 @@ package supervisor import "time" -type StatsEvent struct { +type StatsTask struct { s *Supervisor } -func (h *StatsEvent) Handle(e *Event) error { +func (h *StatsTask) Handle(e *Task) error { start := time.Now() i, ok := h.s.containers[e.ID] if !ok { diff --git a/supervisor/supervisor.go b/supervisor/supervisor.go index b3b83bd..f61f66f 100644 --- a/supervisor/supervisor.go +++ b/supervisor/supervisor.go @@ -5,6 +5,7 @@ import ( "os" "sort" "sync" + "time" "github.com/Sirupsen/logrus" "github.com/docker/containerd/chanotify" @@ -17,7 +18,8 @@ const ( ) // New returns an initialized Process supervisor. -func New(stateDir string, tasks chan *StartTask, oom bool) (*Supervisor, error) { +func New(stateDir string, oom bool) (*Supervisor, error) { + tasks := make(chan *startTask, 10) if err := os.MkdirAll(stateDir, 0755); err != nil { return nil, err } @@ -34,7 +36,7 @@ func New(stateDir string, tasks chan *StartTask, oom bool) (*Supervisor, error) containers: make(map[string]*containerInfo), tasks: tasks, machine: machine, - subscribers: make(map[chan *Event]struct{}), + subscribers: make(map[chan Event]struct{}), el: eventloop.NewChanLoop(defaultBufferSize), monitor: monitor, } @@ -42,26 +44,26 @@ func New(stateDir string, tasks chan *StartTask, oom bool) (*Supervisor, error) s.notifier = chanotify.New() go func() { for id := range s.notifier.Chan() { - e := NewEvent(OOMEventType) + e := NewTask(OOMTaskType) e.ID = id.(string) - s.SendEvent(e) + s.SendTask(e) } }() } // register default event handlers - s.handlers = map[EventType]Handler{ - ExecExitEventType: &ExecExitEvent{s}, - ExitEventType: &ExitEvent{s}, - StartContainerEventType: &StartEvent{s}, - DeleteEventType: &DeleteEvent{s}, - GetContainerEventType: &GetContainersEvent{s}, - SignalEventType: &SignalEvent{s}, - AddProcessEventType: &AddProcessEvent{s}, - UpdateContainerEventType: &UpdateEvent{s}, - CreateCheckpointEventType: &CreateCheckpointEvent{s}, - DeleteCheckpointEventType: &DeleteCheckpointEvent{s}, - StatsEventType: &StatsEvent{s}, - UpdateProcessEventType: &UpdateProcessEvent{s}, + s.handlers = map[TaskType]Handler{ + ExecExitTaskType: &ExecExitTask{s}, + ExitTaskType: &ExitTask{s}, + StartContainerTaskType: &StartTask{s}, + DeleteTaskType: &DeleteTask{s}, + GetContainerTaskType: &GetContainersTask{s}, + SignalTaskType: &SignalTask{s}, + AddProcessTaskType: &AddProcessTask{s}, + UpdateContainerTaskType: &UpdateTask{s}, + CreateCheckpointTaskType: &CreateCheckpointTask{s}, + DeleteCheckpointTaskType: &DeleteCheckpointTask{s}, + StatsTaskType: &StatsTask{s}, + UpdateProcessTaskType: &UpdateProcessTask{s}, } go s.exitHandler() if err := s.restore(); err != nil { @@ -78,13 +80,13 @@ type Supervisor struct { // stateDir is the directory on the system to store container runtime state information. stateDir string containers map[string]*containerInfo - handlers map[EventType]Handler - events chan *Event - tasks chan *StartTask + handlers map[TaskType]Handler + events chan *Task + tasks chan *startTask // we need a lock around the subscribers map only because additions and deletions from // the map are via the API so we cannot really control the concurrency subscriberLock sync.RWMutex - subscribers map[chan *Event]struct{} + subscribers map[chan Event]struct{} machine Machine notifier *chanotify.Notifier el eventloop.EventLoop @@ -105,19 +107,27 @@ func (s *Supervisor) Close() error { return nil } +type Event struct { + ID string `json:"id"` + Type string `json:"type"` + Timestamp time.Time `json:"timestamp"` + Pid string `json:"pid,omitempty"` + Status int `json:"status,omitempty"` +} + // Events returns an event channel that external consumers can use to receive updates // on container events -func (s *Supervisor) Events() chan *Event { +func (s *Supervisor) Events() chan Event { s.subscriberLock.Lock() defer s.subscriberLock.Unlock() - c := make(chan *Event, defaultBufferSize) + c := make(chan Event, defaultBufferSize) EventSubscriberCounter.Inc(1) s.subscribers[c] = struct{}{} return c } // Unsubscribe removes the provided channel from receiving any more events -func (s *Supervisor) Unsubscribe(sub chan *Event) { +func (s *Supervisor) Unsubscribe(sub chan Event) { s.subscriberLock.Lock() defer s.subscriberLock.Unlock() delete(s.subscribers, sub) @@ -127,7 +137,7 @@ func (s *Supervisor) Unsubscribe(sub chan *Event) { // notifySubscribers will send the provided event to the external subscribers // of the events channel -func (s *Supervisor) notifySubscribers(e *Event) { +func (s *Supervisor) notifySubscribers(e Event) { s.subscriberLock.RLock() defer s.subscriberLock.RUnlock() for sub := range s.subscribers { @@ -159,17 +169,17 @@ func (s *Supervisor) Machine() Machine { return s.machine } -// SendEvent sends the provided event the the supervisors main event loop -func (s *Supervisor) SendEvent(evt *Event) { - EventsCounter.Inc(1) - s.el.Send(&commonEvent{data: evt, sv: s}) +// SendTask sends the provided event the the supervisors main event loop +func (s *Supervisor) SendTask(evt *Task) { + TasksCounter.Inc(1) + s.el.Send(&commonTask{data: evt, sv: s}) } func (s *Supervisor) exitHandler() { for p := range s.monitor.Exits() { - e := NewEvent(ExitEventType) + e := NewTask(ExitTaskType) e.Process = p - s.SendEvent(e) + s.SendTask(e) } } @@ -215,9 +225,9 @@ func (s *Supervisor) restore() error { // exit events sort.Sort(&processSorter{exitedProcesses}) for _, p := range exitedProcesses { - e := NewEvent(ExitEventType) + e := NewTask(ExitTaskType) e.Process = p - s.SendEvent(e) + s.SendTask(e) } } } diff --git a/supervisor/event.go b/supervisor/task.go similarity index 53% rename from supervisor/event.go rename to supervisor/task.go index 1397ee5..2844e77 100644 --- a/supervisor/event.go +++ b/supervisor/task.go @@ -8,26 +8,26 @@ import ( "github.com/opencontainers/specs" ) -type EventType string +type TaskType string const ( - ExecExitEventType EventType = "execExit" - ExitEventType EventType = "exit" - StartContainerEventType EventType = "startContainer" - DeleteEventType EventType = "deleteContainerEvent" - GetContainerEventType EventType = "getContainer" - SignalEventType EventType = "signal" - AddProcessEventType EventType = "addProcess" - UpdateContainerEventType EventType = "updateContainer" - UpdateProcessEventType EventType = "updateProcess" - CreateCheckpointEventType EventType = "createCheckpoint" - DeleteCheckpointEventType EventType = "deleteCheckpoint" - StatsEventType EventType = "events" - OOMEventType EventType = "oom" + ExecExitTaskType TaskType = "execExit" + ExitTaskType TaskType = "exit" + StartContainerTaskType TaskType = "startContainer" + DeleteTaskType TaskType = "deleteContainerEvent" + GetContainerTaskType TaskType = "getContainer" + SignalTaskType TaskType = "signal" + AddProcessTaskType TaskType = "addProcess" + UpdateContainerTaskType TaskType = "updateContainer" + UpdateProcessTaskType TaskType = "updateProcess" + CreateCheckpointTaskType TaskType = "createCheckpoint" + DeleteCheckpointTaskType TaskType = "deleteCheckpoint" + StatsTaskType TaskType = "events" + OOMTaskType TaskType = "oom" ) -func NewEvent(t EventType) *Event { - return &Event{ +func NewTask(t TaskType) *Task { + return &Task{ Type: t, Timestamp: time.Now(), Err: make(chan error, 1), @@ -38,8 +38,8 @@ type StartResponse struct { Container runtime.Container } -type Event struct { - Type EventType +type Task struct { + Type TaskType Timestamp time.Time ID string BundlePath string @@ -66,18 +66,18 @@ type Event struct { } type Handler interface { - Handle(*Event) error + Handle(*Task) error } -type commonEvent struct { - data *Event +type commonTask struct { + data *Task sv *Supervisor } -func (e *commonEvent) Handle() { +func (e *commonTask) Handle() { h, ok := e.sv.handlers[e.data.Type] if !ok { - e.data.Err <- ErrUnknownEvent + e.data.Err <- ErrUnknownTask return } err := h.Handle(e.data) diff --git a/supervisor/update.go b/supervisor/update.go index 5a95f02..f4a178e 100644 --- a/supervisor/update.go +++ b/supervisor/update.go @@ -1,12 +1,16 @@ package supervisor -import "github.com/docker/containerd/runtime" +import ( + "time" -type UpdateEvent struct { + "github.com/docker/containerd/runtime" +) + +type UpdateTask struct { s *Supervisor } -func (h *UpdateEvent) Handle(e *Event) error { +func (h *UpdateTask) Handle(e *Task) error { i, ok := h.s.containers[e.ID] if !ok { return ErrContainerNotFound @@ -18,10 +22,20 @@ func (h *UpdateEvent) Handle(e *Event) error { if err := container.Resume(); err != nil { return ErrUnknownContainerStatus } + h.s.notifySubscribers(Event{ + ID: e.ID, + Type: "resume", + Timestamp: time.Now(), + }) case runtime.Paused: if err := container.Pause(); err != nil { return ErrUnknownContainerStatus } + h.s.notifySubscribers(Event{ + ID: e.ID, + Type: "pause", + Timestamp: time.Now(), + }) default: return ErrUnknownContainerStatus } @@ -29,11 +43,11 @@ func (h *UpdateEvent) Handle(e *Event) error { return nil } -type UpdateProcessEvent struct { +type UpdateProcessTask struct { s *Supervisor } -func (h *UpdateProcessEvent) Handle(e *Event) error { +func (h *UpdateProcessTask) Handle(e *Task) error { i, ok := h.s.containers[e.ID] if !ok { return ErrContainerNotFound diff --git a/supervisor/worker.go b/supervisor/worker.go index 4eba0ab..a481c73 100644 --- a/supervisor/worker.go +++ b/supervisor/worker.go @@ -12,7 +12,7 @@ type Worker interface { Start() } -type StartTask struct { +type startTask struct { Container runtime.Container Checkpoint string Stdin string @@ -40,9 +40,9 @@ func (w *worker) Start() { started := time.Now() process, err := t.Container.Start(t.Checkpoint, runtime.NewStdio(t.Stdin, t.Stdout, t.Stderr)) if err != nil { - evt := NewEvent(DeleteEventType) + evt := NewTask(DeleteTaskType) evt.ID = t.Container.ID() - w.s.SendEvent(evt) + w.s.SendTask(evt) t.Err <- err continue } @@ -64,5 +64,10 @@ func (w *worker) Start() { t.StartResponse <- StartResponse{ Container: t.Container, } + w.s.notifySubscribers(Event{ + Timestamp: time.Now(), + ID: t.Container.ID(), + Type: "start-container", + }) } }