Update the content interface to return info from update

Namespace keys used by client for uncompressed

Signed-off-by: Derek McGowan <derek@mcgstyle.net>
This commit is contained in:
Derek McGowan 2017-07-12 16:22:13 -07:00
parent 4f388e0e27
commit a78d0bdeac
No known key found for this signature in database
GPG Key ID: F58C5D0A4405ACDB
10 changed files with 318 additions and 181 deletions

View File

@ -13,6 +13,7 @@
InfoRequest InfoRequest
InfoResponse InfoResponse
UpdateRequest UpdateRequest
UpdateResponse
ListContentRequest ListContentRequest
ListContentResponse ListContentResponse
DeleteContentRequest DeleteContentRequest
@ -153,6 +154,14 @@ func (m *UpdateRequest) Reset() { *m = UpdateRequest{} }
func (*UpdateRequest) ProtoMessage() {} func (*UpdateRequest) ProtoMessage() {}
func (*UpdateRequest) Descriptor() ([]byte, []int) { return fileDescriptorContent, []int{3} } func (*UpdateRequest) Descriptor() ([]byte, []int) { return fileDescriptorContent, []int{3} }
type UpdateResponse struct {
Info Info `protobuf:"bytes,1,opt,name=info" json:"info"`
}
func (m *UpdateResponse) Reset() { *m = UpdateResponse{} }
func (*UpdateResponse) ProtoMessage() {}
func (*UpdateResponse) Descriptor() ([]byte, []int) { return fileDescriptorContent, []int{4} }
type ListContentRequest struct { type ListContentRequest struct {
// Filters contains one or more filters using the syntax defined in the // Filters contains one or more filters using the syntax defined in the
// containerd filter package. // containerd filter package.
@ -169,7 +178,7 @@ type ListContentRequest struct {
func (m *ListContentRequest) Reset() { *m = ListContentRequest{} } func (m *ListContentRequest) Reset() { *m = ListContentRequest{} }
func (*ListContentRequest) ProtoMessage() {} func (*ListContentRequest) ProtoMessage() {}
func (*ListContentRequest) Descriptor() ([]byte, []int) { return fileDescriptorContent, []int{4} } func (*ListContentRequest) Descriptor() ([]byte, []int) { return fileDescriptorContent, []int{5} }
type ListContentResponse struct { type ListContentResponse struct {
Info []Info `protobuf:"bytes,1,rep,name=info" json:"info"` Info []Info `protobuf:"bytes,1,rep,name=info" json:"info"`
@ -177,7 +186,7 @@ type ListContentResponse struct {
func (m *ListContentResponse) Reset() { *m = ListContentResponse{} } func (m *ListContentResponse) Reset() { *m = ListContentResponse{} }
func (*ListContentResponse) ProtoMessage() {} func (*ListContentResponse) ProtoMessage() {}
func (*ListContentResponse) Descriptor() ([]byte, []int) { return fileDescriptorContent, []int{5} } func (*ListContentResponse) Descriptor() ([]byte, []int) { return fileDescriptorContent, []int{6} }
type DeleteContentRequest struct { type DeleteContentRequest struct {
// Digest specifies which content to delete. // Digest specifies which content to delete.
@ -186,7 +195,7 @@ type DeleteContentRequest struct {
func (m *DeleteContentRequest) Reset() { *m = DeleteContentRequest{} } func (m *DeleteContentRequest) Reset() { *m = DeleteContentRequest{} }
func (*DeleteContentRequest) ProtoMessage() {} func (*DeleteContentRequest) ProtoMessage() {}
func (*DeleteContentRequest) Descriptor() ([]byte, []int) { return fileDescriptorContent, []int{6} } func (*DeleteContentRequest) Descriptor() ([]byte, []int) { return fileDescriptorContent, []int{7} }
// ReadContentRequest defines the fields that make up a request to read a portion of // ReadContentRequest defines the fields that make up a request to read a portion of
// data from a stored object. // data from a stored object.
@ -204,7 +213,7 @@ type ReadContentRequest struct {
func (m *ReadContentRequest) Reset() { *m = ReadContentRequest{} } func (m *ReadContentRequest) Reset() { *m = ReadContentRequest{} }
func (*ReadContentRequest) ProtoMessage() {} func (*ReadContentRequest) ProtoMessage() {}
func (*ReadContentRequest) Descriptor() ([]byte, []int) { return fileDescriptorContent, []int{7} } func (*ReadContentRequest) Descriptor() ([]byte, []int) { return fileDescriptorContent, []int{8} }
// ReadContentResponse carries byte data for a read request. // ReadContentResponse carries byte data for a read request.
type ReadContentResponse struct { type ReadContentResponse struct {
@ -214,7 +223,7 @@ type ReadContentResponse struct {
func (m *ReadContentResponse) Reset() { *m = ReadContentResponse{} } func (m *ReadContentResponse) Reset() { *m = ReadContentResponse{} }
func (*ReadContentResponse) ProtoMessage() {} func (*ReadContentResponse) ProtoMessage() {}
func (*ReadContentResponse) Descriptor() ([]byte, []int) { return fileDescriptorContent, []int{8} } func (*ReadContentResponse) Descriptor() ([]byte, []int) { return fileDescriptorContent, []int{9} }
type Status struct { type Status struct {
StartedAt time.Time `protobuf:"bytes,1,opt,name=started_at,json=startedAt,stdtime" json:"started_at"` StartedAt time.Time `protobuf:"bytes,1,opt,name=started_at,json=startedAt,stdtime" json:"started_at"`
@ -227,7 +236,7 @@ type Status struct {
func (m *Status) Reset() { *m = Status{} } func (m *Status) Reset() { *m = Status{} }
func (*Status) ProtoMessage() {} func (*Status) ProtoMessage() {}
func (*Status) Descriptor() ([]byte, []int) { return fileDescriptorContent, []int{9} } func (*Status) Descriptor() ([]byte, []int) { return fileDescriptorContent, []int{10} }
type StatusRequest struct { type StatusRequest struct {
Ref string `protobuf:"bytes,1,opt,name=ref,proto3" json:"ref,omitempty"` Ref string `protobuf:"bytes,1,opt,name=ref,proto3" json:"ref,omitempty"`
@ -235,7 +244,7 @@ type StatusRequest struct {
func (m *StatusRequest) Reset() { *m = StatusRequest{} } func (m *StatusRequest) Reset() { *m = StatusRequest{} }
func (*StatusRequest) ProtoMessage() {} func (*StatusRequest) ProtoMessage() {}
func (*StatusRequest) Descriptor() ([]byte, []int) { return fileDescriptorContent, []int{10} } func (*StatusRequest) Descriptor() ([]byte, []int) { return fileDescriptorContent, []int{11} }
type StatusResponse struct { type StatusResponse struct {
Status *Status `protobuf:"bytes,1,opt,name=status" json:"status,omitempty"` Status *Status `protobuf:"bytes,1,opt,name=status" json:"status,omitempty"`
@ -243,7 +252,7 @@ type StatusResponse struct {
func (m *StatusResponse) Reset() { *m = StatusResponse{} } func (m *StatusResponse) Reset() { *m = StatusResponse{} }
func (*StatusResponse) ProtoMessage() {} func (*StatusResponse) ProtoMessage() {}
func (*StatusResponse) Descriptor() ([]byte, []int) { return fileDescriptorContent, []int{11} } func (*StatusResponse) Descriptor() ([]byte, []int) { return fileDescriptorContent, []int{12} }
type ListStatusesRequest struct { type ListStatusesRequest struct {
Filters []string `protobuf:"bytes,1,rep,name=filters" json:"filters,omitempty"` Filters []string `protobuf:"bytes,1,rep,name=filters" json:"filters,omitempty"`
@ -251,7 +260,7 @@ type ListStatusesRequest struct {
func (m *ListStatusesRequest) Reset() { *m = ListStatusesRequest{} } func (m *ListStatusesRequest) Reset() { *m = ListStatusesRequest{} }
func (*ListStatusesRequest) ProtoMessage() {} func (*ListStatusesRequest) ProtoMessage() {}
func (*ListStatusesRequest) Descriptor() ([]byte, []int) { return fileDescriptorContent, []int{12} } func (*ListStatusesRequest) Descriptor() ([]byte, []int) { return fileDescriptorContent, []int{13} }
type ListStatusesResponse struct { type ListStatusesResponse struct {
Statuses []Status `protobuf:"bytes,1,rep,name=statuses" json:"statuses"` Statuses []Status `protobuf:"bytes,1,rep,name=statuses" json:"statuses"`
@ -259,7 +268,7 @@ type ListStatusesResponse struct {
func (m *ListStatusesResponse) Reset() { *m = ListStatusesResponse{} } func (m *ListStatusesResponse) Reset() { *m = ListStatusesResponse{} }
func (*ListStatusesResponse) ProtoMessage() {} func (*ListStatusesResponse) ProtoMessage() {}
func (*ListStatusesResponse) Descriptor() ([]byte, []int) { return fileDescriptorContent, []int{13} } func (*ListStatusesResponse) Descriptor() ([]byte, []int) { return fileDescriptorContent, []int{14} }
// WriteContentRequest writes data to the request ref at offset. // WriteContentRequest writes data to the request ref at offset.
type WriteContentRequest struct { type WriteContentRequest struct {
@ -316,7 +325,7 @@ type WriteContentRequest struct {
func (m *WriteContentRequest) Reset() { *m = WriteContentRequest{} } func (m *WriteContentRequest) Reset() { *m = WriteContentRequest{} }
func (*WriteContentRequest) ProtoMessage() {} func (*WriteContentRequest) ProtoMessage() {}
func (*WriteContentRequest) Descriptor() ([]byte, []int) { return fileDescriptorContent, []int{14} } func (*WriteContentRequest) Descriptor() ([]byte, []int) { return fileDescriptorContent, []int{15} }
// WriteContentResponse is returned on the culmination of a write call. // WriteContentResponse is returned on the culmination of a write call.
type WriteContentResponse struct { type WriteContentResponse struct {
@ -350,7 +359,7 @@ type WriteContentResponse struct {
func (m *WriteContentResponse) Reset() { *m = WriteContentResponse{} } func (m *WriteContentResponse) Reset() { *m = WriteContentResponse{} }
func (*WriteContentResponse) ProtoMessage() {} func (*WriteContentResponse) ProtoMessage() {}
func (*WriteContentResponse) Descriptor() ([]byte, []int) { return fileDescriptorContent, []int{15} } func (*WriteContentResponse) Descriptor() ([]byte, []int) { return fileDescriptorContent, []int{16} }
type AbortRequest struct { type AbortRequest struct {
Ref string `protobuf:"bytes,1,opt,name=ref,proto3" json:"ref,omitempty"` Ref string `protobuf:"bytes,1,opt,name=ref,proto3" json:"ref,omitempty"`
@ -358,13 +367,14 @@ type AbortRequest struct {
func (m *AbortRequest) Reset() { *m = AbortRequest{} } func (m *AbortRequest) Reset() { *m = AbortRequest{} }
func (*AbortRequest) ProtoMessage() {} func (*AbortRequest) ProtoMessage() {}
func (*AbortRequest) Descriptor() ([]byte, []int) { return fileDescriptorContent, []int{16} } func (*AbortRequest) Descriptor() ([]byte, []int) { return fileDescriptorContent, []int{17} }
func init() { func init() {
proto.RegisterType((*Info)(nil), "containerd.services.content.v1.Info") proto.RegisterType((*Info)(nil), "containerd.services.content.v1.Info")
proto.RegisterType((*InfoRequest)(nil), "containerd.services.content.v1.InfoRequest") proto.RegisterType((*InfoRequest)(nil), "containerd.services.content.v1.InfoRequest")
proto.RegisterType((*InfoResponse)(nil), "containerd.services.content.v1.InfoResponse") proto.RegisterType((*InfoResponse)(nil), "containerd.services.content.v1.InfoResponse")
proto.RegisterType((*UpdateRequest)(nil), "containerd.services.content.v1.UpdateRequest") proto.RegisterType((*UpdateRequest)(nil), "containerd.services.content.v1.UpdateRequest")
proto.RegisterType((*UpdateResponse)(nil), "containerd.services.content.v1.UpdateResponse")
proto.RegisterType((*ListContentRequest)(nil), "containerd.services.content.v1.ListContentRequest") proto.RegisterType((*ListContentRequest)(nil), "containerd.services.content.v1.ListContentRequest")
proto.RegisterType((*ListContentResponse)(nil), "containerd.services.content.v1.ListContentResponse") proto.RegisterType((*ListContentResponse)(nil), "containerd.services.content.v1.ListContentResponse")
proto.RegisterType((*DeleteContentRequest)(nil), "containerd.services.content.v1.DeleteContentRequest") proto.RegisterType((*DeleteContentRequest)(nil), "containerd.services.content.v1.DeleteContentRequest")
@ -402,7 +412,7 @@ type ContentClient interface {
// This call can be used to manage the mutable content labels. The // This call can be used to manage the mutable content labels. The
// immutable metadata such as digest, size, and committed at cannot // immutable metadata such as digest, size, and committed at cannot
// be updated. // be updated.
Update(ctx context.Context, in *UpdateRequest, opts ...grpc.CallOption) (*google_protobuf3.Empty, error) Update(ctx context.Context, in *UpdateRequest, opts ...grpc.CallOption) (*UpdateResponse, error)
// List streams the entire set of content as Info objects and closes the // List streams the entire set of content as Info objects and closes the
// stream. // stream.
// //
@ -464,8 +474,8 @@ func (c *contentClient) Info(ctx context.Context, in *InfoRequest, opts ...grpc.
return out, nil return out, nil
} }
func (c *contentClient) Update(ctx context.Context, in *UpdateRequest, opts ...grpc.CallOption) (*google_protobuf3.Empty, error) { func (c *contentClient) Update(ctx context.Context, in *UpdateRequest, opts ...grpc.CallOption) (*UpdateResponse, error) {
out := new(google_protobuf3.Empty) out := new(UpdateResponse)
err := grpc.Invoke(ctx, "/containerd.services.content.v1.Content/Update", in, out, c.cc, opts...) err := grpc.Invoke(ctx, "/containerd.services.content.v1.Content/Update", in, out, c.cc, opts...)
if err != nil { if err != nil {
return nil, err return nil, err
@ -617,7 +627,7 @@ type ContentServer interface {
// This call can be used to manage the mutable content labels. The // This call can be used to manage the mutable content labels. The
// immutable metadata such as digest, size, and committed at cannot // immutable metadata such as digest, size, and committed at cannot
// be updated. // be updated.
Update(context.Context, *UpdateRequest) (*google_protobuf3.Empty, error) Update(context.Context, *UpdateRequest) (*UpdateResponse, error)
// List streams the entire set of content as Info objects and closes the // List streams the entire set of content as Info objects and closes the
// stream. // stream.
// //
@ -1040,6 +1050,32 @@ func (m *UpdateRequest) MarshalTo(dAtA []byte) (int, error) {
return i, nil return i, nil
} }
func (m *UpdateResponse) 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 *UpdateResponse) MarshalTo(dAtA []byte) (int, error) {
var i int
_ = i
var l int
_ = l
dAtA[i] = 0xa
i++
i = encodeVarintContent(dAtA, i, uint64(m.Info.Size()))
n6, err := m.Info.MarshalTo(dAtA[i:])
if err != nil {
return 0, err
}
i += n6
return i, nil
}
func (m *ListContentRequest) Marshal() (dAtA []byte, err error) { func (m *ListContentRequest) Marshal() (dAtA []byte, err error) {
size := m.Size() size := m.Size()
dAtA = make([]byte, size) dAtA = make([]byte, size)
@ -1208,19 +1244,19 @@ func (m *Status) MarshalTo(dAtA []byte) (int, error) {
dAtA[i] = 0xa dAtA[i] = 0xa
i++ i++
i = encodeVarintContent(dAtA, i, uint64(github_com_gogo_protobuf_types.SizeOfStdTime(m.StartedAt))) i = encodeVarintContent(dAtA, i, uint64(github_com_gogo_protobuf_types.SizeOfStdTime(m.StartedAt)))
n6, err := github_com_gogo_protobuf_types.StdTimeMarshalTo(m.StartedAt, dAtA[i:]) n7, err := github_com_gogo_protobuf_types.StdTimeMarshalTo(m.StartedAt, dAtA[i:])
if err != nil {
return 0, err
}
i += n6
dAtA[i] = 0x12
i++
i = encodeVarintContent(dAtA, i, uint64(github_com_gogo_protobuf_types.SizeOfStdTime(m.UpdatedAt)))
n7, err := github_com_gogo_protobuf_types.StdTimeMarshalTo(m.UpdatedAt, dAtA[i:])
if err != nil { if err != nil {
return 0, err return 0, err
} }
i += n7 i += n7
dAtA[i] = 0x12
i++
i = encodeVarintContent(dAtA, i, uint64(github_com_gogo_protobuf_types.SizeOfStdTime(m.UpdatedAt)))
n8, err := github_com_gogo_protobuf_types.StdTimeMarshalTo(m.UpdatedAt, dAtA[i:])
if err != nil {
return 0, err
}
i += n8
if len(m.Ref) > 0 { if len(m.Ref) > 0 {
dAtA[i] = 0x1a dAtA[i] = 0x1a
i++ i++
@ -1289,11 +1325,11 @@ func (m *StatusResponse) MarshalTo(dAtA []byte) (int, error) {
dAtA[i] = 0xa dAtA[i] = 0xa
i++ i++
i = encodeVarintContent(dAtA, i, uint64(m.Status.Size())) i = encodeVarintContent(dAtA, i, uint64(m.Status.Size()))
n8, err := m.Status.MarshalTo(dAtA[i:]) n9, err := m.Status.MarshalTo(dAtA[i:])
if err != nil { if err != nil {
return 0, err return 0, err
} }
i += n8 i += n9
} }
return i, nil return i, nil
} }
@ -1435,19 +1471,19 @@ func (m *WriteContentResponse) MarshalTo(dAtA []byte) (int, error) {
dAtA[i] = 0x12 dAtA[i] = 0x12
i++ i++
i = encodeVarintContent(dAtA, i, uint64(github_com_gogo_protobuf_types.SizeOfStdTime(m.StartedAt))) i = encodeVarintContent(dAtA, i, uint64(github_com_gogo_protobuf_types.SizeOfStdTime(m.StartedAt)))
n9, err := github_com_gogo_protobuf_types.StdTimeMarshalTo(m.StartedAt, dAtA[i:]) n10, err := github_com_gogo_protobuf_types.StdTimeMarshalTo(m.StartedAt, dAtA[i:])
if err != nil {
return 0, err
}
i += n9
dAtA[i] = 0x1a
i++
i = encodeVarintContent(dAtA, i, uint64(github_com_gogo_protobuf_types.SizeOfStdTime(m.UpdatedAt)))
n10, err := github_com_gogo_protobuf_types.StdTimeMarshalTo(m.UpdatedAt, dAtA[i:])
if err != nil { if err != nil {
return 0, err return 0, err
} }
i += n10 i += n10
dAtA[i] = 0x1a
i++
i = encodeVarintContent(dAtA, i, uint64(github_com_gogo_protobuf_types.SizeOfStdTime(m.UpdatedAt)))
n11, err := github_com_gogo_protobuf_types.StdTimeMarshalTo(m.UpdatedAt, dAtA[i:])
if err != nil {
return 0, err
}
i += n11
if m.Offset != 0 { if m.Offset != 0 {
dAtA[i] = 0x20 dAtA[i] = 0x20
i++ i++
@ -1573,6 +1609,14 @@ func (m *UpdateRequest) Size() (n int) {
return n return n
} }
func (m *UpdateResponse) Size() (n int) {
var l int
_ = l
l = m.Info.Size()
n += 1 + l + sovContent(uint64(l))
return n
}
func (m *ListContentRequest) Size() (n int) { func (m *ListContentRequest) Size() (n int) {
var l int var l int
_ = l _ = l
@ -1832,6 +1876,16 @@ func (this *UpdateRequest) String() string {
}, "") }, "")
return s return s
} }
func (this *UpdateResponse) String() string {
if this == nil {
return "nil"
}
s := strings.Join([]string{`&UpdateResponse{`,
`Info:` + strings.Replace(strings.Replace(this.Info.String(), "Info", "Info", 1), `&`, ``, 1) + `,`,
`}`,
}, "")
return s
}
func (this *ListContentRequest) String() string { func (this *ListContentRequest) String() string {
if this == nil { if this == nil {
return "nil" return "nil"
@ -2534,6 +2588,86 @@ func (m *UpdateRequest) Unmarshal(dAtA []byte) error {
} }
return nil return nil
} }
func (m *UpdateResponse) 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 ErrIntOverflowContent
}
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: UpdateResponse: wiretype end group for non-group")
}
if fieldNum <= 0 {
return fmt.Errorf("proto: UpdateResponse: illegal tag %d (wire type %d)", fieldNum, wire)
}
switch fieldNum {
case 1:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Info", wireType)
}
var msglen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowContent
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
msglen |= (int(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
if msglen < 0 {
return ErrInvalidLengthContent
}
postIndex := iNdEx + msglen
if postIndex > l {
return io.ErrUnexpectedEOF
}
if err := m.Info.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
return err
}
iNdEx = postIndex
default:
iNdEx = preIndex
skippy, err := skipContent(dAtA[iNdEx:])
if err != nil {
return err
}
if skippy < 0 {
return ErrInvalidLengthContent
}
if (iNdEx + skippy) > l {
return io.ErrUnexpectedEOF
}
iNdEx += skippy
}
}
if iNdEx > l {
return io.ErrUnexpectedEOF
}
return nil
}
func (m *ListContentRequest) Unmarshal(dAtA []byte) error { func (m *ListContentRequest) Unmarshal(dAtA []byte) error {
l := len(dAtA) l := len(dAtA)
iNdEx := 0 iNdEx := 0
@ -4099,72 +4233,72 @@ func init() {
} }
var fileDescriptorContent = []byte{ var fileDescriptorContent = []byte{
// 1061 bytes of a gzipped FileDescriptorProto // 1067 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x57, 0xcf, 0x6f, 0x1a, 0xc7, 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x57, 0x4f, 0x6f, 0x1a, 0x47,
0x17, 0x67, 0x58, 0x58, 0x9b, 0x07, 0xc9, 0x97, 0xef, 0x40, 0x23, 0xb4, 0x55, 0x61, 0xb3, 0xaa, 0x14, 0xf7, 0xb0, 0xb0, 0x36, 0x0f, 0x92, 0xd2, 0x81, 0x46, 0x68, 0xab, 0xc2, 0x66, 0x55, 0x55,
0x2a, 0x94, 0xd4, 0x8b, 0x83, 0x7d, 0x68, 0x1b, 0xa9, 0x2a, 0x26, 0x4e, 0xe3, 0x2a, 0x4e, 0xaa, 0x28, 0xa9, 0x17, 0x07, 0xfb, 0xd0, 0x36, 0x52, 0x55, 0x4c, 0x9c, 0xc6, 0x55, 0x9c, 0x56, 0x1b,
0x0d, 0x69, 0xd4, 0x5c, 0xd2, 0x05, 0x06, 0xba, 0x32, 0xb0, 0x84, 0x19, 0x50, 0xdd, 0x53, 0x2f, 0xd2, 0xa8, 0xb9, 0xa4, 0x0b, 0x0c, 0x74, 0x65, 0x60, 0x09, 0x33, 0xa0, 0xba, 0xa7, 0x5e, 0x2a,
0x95, 0x2a, 0x2b, 0x87, 0xfe, 0x03, 0xbe, 0xb4, 0x55, 0xff, 0x88, 0xfe, 0x05, 0x3e, 0xf6, 0x58, 0x55, 0x56, 0x0e, 0xfd, 0x02, 0xbe, 0xb4, 0xfd, 0x14, 0x3d, 0xf4, 0xec, 0x63, 0x8f, 0x55, 0x0f,
0xf5, 0x90, 0x34, 0xfe, 0x2f, 0x7a, 0xa9, 0xaa, 0x9d, 0x99, 0x85, 0x05, 0xec, 0x2c, 0x60, 0xf7, 0x49, 0xe3, 0x6f, 0xd1, 0x4b, 0x55, 0xed, 0xcc, 0x2c, 0x2c, 0x60, 0x97, 0x05, 0x93, 0x13, 0x6f,
0xe4, 0x37, 0xc3, 0xfb, 0xbc, 0x79, 0xbf, 0x3e, 0xef, 0xad, 0xe1, 0x6e, 0xdb, 0x61, 0x5f, 0x0f, 0x66, 0xdf, 0xef, 0xfd, 0xff, 0x33, 0xc0, 0xdd, 0x96, 0xc3, 0xbe, 0x19, 0xd4, 0xcc, 0xba, 0xdb,
0xeb, 0x66, 0xc3, 0xed, 0x96, 0x1a, 0x6e, 0x8f, 0xd9, 0x4e, 0x8f, 0x0c, 0x9a, 0x41, 0xd1, 0xee, 0x29, 0xd6, 0xdd, 0x2e, 0xb3, 0x9d, 0x2e, 0xe9, 0x37, 0x82, 0xa4, 0xdd, 0x73, 0x8a, 0x94, 0xf4,
0x3b, 0x25, 0x4a, 0x06, 0x23, 0xa7, 0x41, 0x28, 0xbf, 0x27, 0x3d, 0x56, 0x1a, 0xdd, 0xf2, 0x45, 0x87, 0x4e, 0x9d, 0x50, 0x7e, 0x4f, 0xba, 0xac, 0x38, 0xbc, 0xe5, 0x93, 0x66, 0xaf, 0xef, 0x32,
0xb3, 0x3f, 0x70, 0x99, 0x8b, 0xf3, 0x13, 0x84, 0xe9, 0x6b, 0x9b, 0xbe, 0xca, 0xe8, 0x96, 0x96, 0x17, 0xe7, 0xc6, 0x08, 0xd3, 0xe7, 0x36, 0x7d, 0x96, 0xe1, 0x2d, 0x2d, 0xd3, 0x72, 0x5b, 0x2e,
0x6d, 0xbb, 0x6d, 0x97, 0xab, 0x96, 0x3c, 0x49, 0xa0, 0x34, 0xbd, 0xed, 0xba, 0xed, 0x0e, 0x29, 0x67, 0x2d, 0x7a, 0x94, 0x40, 0x69, 0x7a, 0xcb, 0x75, 0x5b, 0x6d, 0x52, 0xe4, 0xa7, 0xda, 0xa0,
0xf1, 0x53, 0x7d, 0xd8, 0x2a, 0xb5, 0x1c, 0xd2, 0x69, 0x3e, 0xeb, 0xda, 0xf4, 0x40, 0x6a, 0x14, 0x59, 0x6c, 0x3a, 0xa4, 0xdd, 0x78, 0xda, 0xb1, 0xe9, 0xa1, 0xe4, 0xc8, 0x4f, 0x73, 0x30, 0xa7,
0x66, 0x35, 0x98, 0xd3, 0x25, 0x94, 0xd9, 0xdd, 0xbe, 0x54, 0x78, 0x7b, 0x56, 0x81, 0x74, 0xfb, 0x43, 0x28, 0xb3, 0x3b, 0x3d, 0xc9, 0xf0, 0xf6, 0x34, 0x03, 0xe9, 0xf4, 0xd8, 0x91, 0xf8, 0x68,
0xec, 0x50, 0xfc, 0x68, 0xfc, 0x1d, 0x85, 0xd8, 0x5e, 0xaf, 0xe5, 0xe2, 0xcf, 0x40, 0x6d, 0x3a, 0xfc, 0x13, 0x81, 0xe8, 0x7e, 0xb7, 0xe9, 0xe2, 0xcf, 0x40, 0x6d, 0x38, 0x2d, 0x42, 0x59, 0x16,
0x6d, 0x42, 0x59, 0x0e, 0xe9, 0xa8, 0x98, 0xd8, 0x29, 0x9f, 0xbc, 0x2c, 0x44, 0xfe, 0x7c, 0x59, 0xe9, 0xa8, 0x10, 0xdf, 0x2d, 0x9d, 0xbe, 0xc8, 0xaf, 0xfd, 0xf5, 0x22, 0x7f, 0x23, 0xe0, 0xbe,
0xb8, 0x11, 0x08, 0xdf, 0xed, 0x93, 0xde, 0x38, 0x0a, 0x5a, 0x6a, 0xbb, 0x1b, 0x02, 0x62, 0xde, 0xdb, 0x23, 0xdd, 0x91, 0x17, 0xb4, 0xd8, 0x72, 0x37, 0x05, 0xc4, 0xbc, 0xc3, 0x7f, 0x2c, 0x29,
0xe1, 0x7f, 0x2c, 0x69, 0x01, 0x63, 0x88, 0x51, 0xe7, 0x5b, 0x92, 0x8b, 0xea, 0xa8, 0xa8, 0x58, 0x01, 0x63, 0x88, 0x52, 0xe7, 0x3b, 0x92, 0x8d, 0xe8, 0xa8, 0xa0, 0x58, 0x9c, 0xc6, 0x9f, 0x42,
0x5c, 0xc6, 0x9f, 0x42, 0xaa, 0xe1, 0x76, 0xbb, 0x0e, 0x63, 0xa4, 0xf9, 0xcc, 0x66, 0x39, 0x45, 0xb2, 0xee, 0x76, 0x3a, 0x0e, 0x63, 0xa4, 0xf1, 0xd4, 0x66, 0x59, 0x45, 0x47, 0x85, 0x44, 0x49,
0x47, 0xc5, 0x64, 0x59, 0x33, 0x85, 0x73, 0xa6, 0xef, 0x9c, 0x59, 0xf3, 0xbd, 0xdf, 0x59, 0xf7, 0x33, 0x85, 0x71, 0xa6, 0x6f, 0x9c, 0x59, 0xf5, 0xad, 0xdf, 0xdd, 0xf0, 0x2c, 0xf8, 0xe9, 0x65,
0x3c, 0xf8, 0xf1, 0x55, 0x01, 0x59, 0xc9, 0x31, 0xb2, 0xc2, 0x70, 0x15, 0x60, 0xd8, 0x6f, 0xda, 0x1e, 0x59, 0x89, 0x11, 0xb2, 0xcc, 0x70, 0x05, 0x60, 0xd0, 0x6b, 0xd8, 0x52, 0x4c, 0x74, 0x01,
0xd2, 0x4c, 0x6c, 0x09, 0x33, 0x09, 0x89, 0xab, 0x30, 0x7c, 0x0f, 0xd4, 0x8e, 0x5d, 0x27, 0x1d, 0x31, 0x71, 0x89, 0x2b, 0x33, 0x7c, 0x0f, 0xd4, 0xb6, 0x5d, 0x23, 0x6d, 0x9a, 0x8d, 0xe9, 0x4a,
0x9a, 0x8b, 0xeb, 0x4a, 0x31, 0x59, 0xde, 0x34, 0xdf, 0x5c, 0x1d, 0xd3, 0xcb, 0x91, 0x79, 0x9f, 0x21, 0x51, 0xda, 0x32, 0xff, 0x3f, 0x3b, 0xa6, 0x17, 0x23, 0xf3, 0x3e, 0x87, 0xec, 0x75, 0x59,
0x43, 0x76, 0x7b, 0x6c, 0x70, 0x68, 0x49, 0xbc, 0xf6, 0x21, 0x24, 0x03, 0xd7, 0x38, 0x0d, 0xca, 0xff, 0xc8, 0x92, 0x78, 0xed, 0x43, 0x48, 0x04, 0xae, 0x71, 0x0a, 0x94, 0x43, 0x72, 0x24, 0x62,
0x01, 0x39, 0x14, 0x39, 0xb4, 0x3c, 0x11, 0x67, 0x21, 0x3e, 0xb2, 0x3b, 0x43, 0x91, 0x8d, 0x84, 0x68, 0x79, 0x24, 0xce, 0x40, 0x6c, 0x68, 0xb7, 0x07, 0x22, 0x1a, 0x71, 0x4b, 0x1c, 0x3e, 0x8a,
0x25, 0x0e, 0x1f, 0x45, 0x3f, 0x40, 0xc6, 0x97, 0x90, 0xf4, 0xcc, 0x5a, 0xe4, 0xf9, 0xd0, 0xcb, 0x7c, 0x80, 0x8c, 0xaf, 0x20, 0xe1, 0x89, 0xb5, 0xc8, 0xb3, 0x81, 0x17, 0xb5, 0x15, 0x66, 0xc0,
0xda, 0x25, 0x56, 0xc0, 0x78, 0x00, 0x29, 0x61, 0x9a, 0xf6, 0xdd, 0x1e, 0x25, 0xf8, 0x63, 0x88, 0x78, 0x00, 0x49, 0x21, 0x9a, 0xf6, 0xdc, 0x2e, 0x25, 0xf8, 0x63, 0x88, 0x3a, 0xdd, 0xa6, 0xcb,
0x39, 0xbd, 0x96, 0xcb, 0x2d, 0x27, 0xcb, 0xef, 0x2e, 0x12, 0xed, 0x4e, 0xcc, 0x7b, 0xdf, 0xe2, 0x25, 0x27, 0x4a, 0xef, 0x86, 0xf1, 0x76, 0x37, 0xea, 0xe9, 0xb7, 0x38, 0xce, 0x78, 0x8e, 0xe0,
0x38, 0xe3, 0x05, 0x82, 0x2b, 0x8f, 0x79, 0xf6, 0x7c, 0x6f, 0x2f, 0x68, 0x11, 0xdf, 0x86, 0xa4, 0xca, 0x23, 0x1e, 0x3d, 0xdf, 0xda, 0x4b, 0x4a, 0xc4, 0xb7, 0x21, 0x21, 0xd2, 0xc1, 0x6b, 0x99,
0x28, 0x07, 0xef, 0x65, 0x9e, 0x9c, 0xb3, 0xea, 0x78, 0xd7, 0x6b, 0xf7, 0x7d, 0x9b, 0x1e, 0x58, 0x07, 0xe7, 0xbc, 0x3c, 0xde, 0xf5, 0xca, 0xfd, 0xc0, 0xa6, 0x87, 0x96, 0xcc, 0xba, 0x47, 0x1b,
0xb2, 0xea, 0x9e, 0x6c, 0x98, 0x80, 0xef, 0x3b, 0x94, 0x55, 0x85, 0x7d, 0xdf, 0xa5, 0x1c, 0xac, 0x5f, 0xc0, 0x55, 0xdf, 0x9a, 0x15, 0x39, 0x68, 0x02, 0xbe, 0xef, 0x50, 0x56, 0x11, 0x2c, 0xbe,
0xb5, 0x9c, 0x0e, 0x23, 0x03, 0x9a, 0x43, 0xba, 0x52, 0x4c, 0x58, 0xfe, 0xd1, 0x78, 0x0c, 0x99, 0x93, 0x59, 0x58, 0x6f, 0x3a, 0x6d, 0x46, 0xfa, 0x34, 0x8b, 0x74, 0xa5, 0x10, 0xb7, 0xfc, 0xa3,
0x29, 0xfd, 0xb9, 0xac, 0x28, 0x2b, 0x65, 0xa5, 0x0e, 0xd9, 0x3b, 0xa4, 0x43, 0x18, 0x99, 0x71, 0xf1, 0x08, 0xd2, 0x13, 0xfc, 0x33, 0x66, 0x28, 0x4b, 0x99, 0x51, 0x83, 0xcc, 0x1d, 0xd2, 0x26,
0xe4, 0x32, 0x2b, 0xf9, 0x02, 0x01, 0xb6, 0x88, 0xdd, 0xfc, 0xef, 0x9e, 0xc0, 0xd7, 0x40, 0x75, 0x8c, 0x4c, 0x19, 0xb2, 0xca, 0xda, 0x78, 0x8e, 0x00, 0x5b, 0xc4, 0x6e, 0xbc, 0x3e, 0x15, 0xf8,
0x5b, 0x2d, 0x4a, 0x98, 0x24, 0xac, 0x3c, 0x8d, 0x69, 0xac, 0x4c, 0x68, 0x6c, 0x54, 0x20, 0x33, 0x1a, 0xa8, 0x6e, 0xb3, 0x49, 0x09, 0x93, 0x23, 0x40, 0x9e, 0x46, 0x83, 0x41, 0x19, 0x0f, 0x06,
0xe5, 0x8d, 0xcc, 0xe4, 0xc4, 0x04, 0x9a, 0x35, 0xd1, 0xb4, 0x99, 0xcd, 0x0d, 0xa7, 0x2c, 0x2e, 0xa3, 0x0c, 0xe9, 0x09, 0x6b, 0x64, 0x24, 0xc7, 0x22, 0xd0, 0xb4, 0x88, 0x86, 0xcd, 0x6c, 0x2e,
0x1b, 0x3f, 0x45, 0x41, 0x7d, 0xc4, 0x6c, 0x36, 0xa4, 0x1e, 0x97, 0x29, 0xb3, 0x07, 0x92, 0xcb, 0x38, 0x69, 0x71, 0xda, 0xf8, 0x39, 0x02, 0xea, 0x43, 0x66, 0xb3, 0x01, 0xf5, 0xa6, 0x03, 0x65,
0x68, 0x19, 0x2e, 0x4b, 0xdc, 0xdc, 0x40, 0x88, 0xae, 0x36, 0x10, 0xd2, 0xa0, 0x0c, 0x48, 0x8b, 0x76, 0x5f, 0x4e, 0x07, 0xb4, 0xc8, 0x74, 0x90, 0xb8, 0x99, 0x11, 0x13, 0x59, 0x6e, 0xc4, 0xa4,
0x87, 0x9a, 0xb0, 0x3c, 0x31, 0x10, 0x52, 0x6c, 0x2a, 0xa4, 0x2c, 0xc4, 0x99, 0xcb, 0xec, 0x4e, 0x40, 0xe9, 0x93, 0x26, 0x77, 0x35, 0x6e, 0x79, 0x64, 0xc0, 0xa5, 0xe8, 0x84, 0x4b, 0x19, 0x88,
0x2e, 0xce, 0xaf, 0xc5, 0x01, 0x3f, 0x80, 0x75, 0xf2, 0x4d, 0x9f, 0x34, 0x18, 0x69, 0xe6, 0xd4, 0x31, 0x97, 0xd9, 0xed, 0x6c, 0x8c, 0x5f, 0x8b, 0x03, 0x7e, 0x00, 0x1b, 0xe4, 0xdb, 0x1e, 0xa9,
0x95, 0x2b, 0x32, 0xb6, 0x61, 0x5c, 0x87, 0x2b, 0x22, 0x47, 0x7e, 0xc1, 0xa5, 0x83, 0x68, 0xec, 0x33, 0xd2, 0xc8, 0xaa, 0x4b, 0x67, 0x64, 0x24, 0xc3, 0xb8, 0x0e, 0x57, 0x44, 0x8c, 0xfc, 0x84,
0xa0, 0xf1, 0x39, 0x5c, 0xf5, 0x55, 0xc6, 0xfd, 0xac, 0x52, 0x7e, 0x23, 0x53, 0xf9, 0x5e, 0x58, 0x4b, 0x03, 0xd1, 0xc8, 0x40, 0xaf, 0xad, 0x7c, 0x96, 0x51, 0x3d, 0xab, 0x94, 0xdf, 0xc8, 0x50,
0x47, 0x4b, 0xbc, 0x44, 0x19, 0x25, 0x41, 0x13, 0x71, 0x4b, 0x68, 0x38, 0xaf, 0xbe, 0x82, 0xec, 0xbe, 0x37, 0xaf, 0xa2, 0x25, 0x5e, 0xa2, 0x8c, 0xa2, 0x68, 0x13, 0x71, 0x4b, 0xe8, 0xfc, 0xbe,
0x34, 0x40, 0x3a, 0x72, 0x0f, 0xd6, 0xa9, 0xbc, 0x93, 0xe4, 0x5a, 0xd0, 0x15, 0x49, 0xaf, 0x31, 0xfa, 0x1a, 0x32, 0x93, 0x00, 0x69, 0xc8, 0x3d, 0xd8, 0xa0, 0xf2, 0x4e, 0x36, 0x57, 0x48, 0x53,
0xda, 0xf8, 0x07, 0x41, 0xe6, 0xc9, 0xc0, 0x99, 0xa3, 0x58, 0x15, 0x54, 0xbb, 0xc1, 0x1c, 0xb7, 0x64, 0x7b, 0x8d, 0xd0, 0xc6, 0xbf, 0x08, 0xd2, 0x8f, 0xfb, 0xce, 0x4c, 0x8b, 0x55, 0x40, 0xb5,
0xc7, 0x43, 0xbd, 0x5a, 0xbe, 0x19, 0x66, 0x9f, 0x1b, 0xa9, 0x70, 0x88, 0x25, 0xa1, 0x7e, 0x4e, 0xeb, 0xcc, 0x71, 0xbb, 0xdc, 0xd5, 0xab, 0xa5, 0x9b, 0xf3, 0xe4, 0x73, 0x21, 0x65, 0x0e, 0xb1,
0xa3, 0x93, 0xa2, 0x8f, 0x8b, 0xab, 0x9c, 0x57, 0xdc, 0xd8, 0xc5, 0x8b, 0x1b, 0x68, 0xad, 0xf8, 0x24, 0xd4, 0x8f, 0x69, 0x64, 0x9c, 0xf4, 0x51, 0x72, 0x95, 0x8b, 0x92, 0x1b, 0xbd, 0x7c, 0x72,
0x99, 0x6c, 0x51, 0x03, 0x6c, 0x79, 0x15, 0x85, 0xec, 0x74, 0x02, 0x64, 0x8e, 0x2f, 0x25, 0x03, 0x03, 0xa5, 0x15, 0x3b, 0xb7, 0x5b, 0xd4, 0x40, 0xb7, 0xbc, 0x8c, 0x40, 0x66, 0x32, 0x00, 0x32,
0xd3, 0x04, 0x8c, 0x5e, 0x06, 0x01, 0x95, 0xd5, 0x08, 0xb8, 0x1c, 0xdd, 0x26, 0xe3, 0x4f, 0xbd, 0xc6, 0x2b, 0x89, 0xc0, 0x64, 0x03, 0x46, 0x56, 0xd1, 0x80, 0xca, 0x72, 0x0d, 0xb8, 0x58, 0xbb,
0xf0, 0x84, 0xd5, 0x21, 0x55, 0xa9, 0xbb, 0x03, 0x76, 0x2e, 0xd3, 0x6e, 0x7c, 0x8f, 0x20, 0x19, 0x8d, 0xc7, 0x9f, 0x7a, 0xe9, 0x09, 0xab, 0x43, 0xb2, 0x5c, 0x73, 0xfb, 0xec, 0xc2, 0x4e, 0xbb,
0xc8, 0x1e, 0x7e, 0x07, 0x62, 0x8f, 0x6a, 0x95, 0x5a, 0x3a, 0xa2, 0x65, 0x8e, 0x8e, 0xf5, 0xff, 0xf1, 0x03, 0x82, 0x44, 0x20, 0x7a, 0xf8, 0x1d, 0x88, 0x3e, 0xac, 0x96, 0xab, 0xa9, 0x35, 0x2d,
0x05, 0x7e, 0xf2, 0xba, 0x18, 0x17, 0x20, 0xfe, 0xc4, 0xda, 0xab, 0xed, 0xa6, 0x91, 0x96, 0x3d, 0x7d, 0x7c, 0xa2, 0xbf, 0x11, 0xf8, 0xe4, 0x55, 0x31, 0xce, 0x43, 0xec, 0xb1, 0xb5, 0x5f, 0xdd,
0x3a, 0xd6, 0xd3, 0x81, 0xdf, 0xb9, 0x88, 0xaf, 0x83, 0x5a, 0x7d, 0xb8, 0xbf, 0xbf, 0x57, 0x4b, 0x4b, 0x21, 0x2d, 0x73, 0x7c, 0xa2, 0xa7, 0x02, 0xdf, 0x39, 0x89, 0xaf, 0x83, 0x5a, 0xf9, 0xfc,
0x47, 0xb5, 0xb7, 0x8e, 0x8e, 0xf5, 0xff, 0x07, 0x34, 0xaa, 0xfc, 0x53, 0x47, 0xcb, 0xfc, 0xf0, 0xe0, 0x60, 0xbf, 0x9a, 0x8a, 0x68, 0x6f, 0x1d, 0x9f, 0xe8, 0x6f, 0x06, 0x38, 0x2a, 0xfc, 0xf1,
0x73, 0x3e, 0xf2, 0xdb, 0x2f, 0xf9, 0xe0, 0xbb, 0xe5, 0x5f, 0xd7, 0x60, 0x4d, 0xb6, 0x01, 0xb6, 0xa4, 0xa5, 0x7f, 0xfc, 0x25, 0xb7, 0xf6, 0xdb, 0xaf, 0xb9, 0xa0, 0xde, 0xd2, 0xef, 0xeb, 0xb0,
0xe5, 0x77, 0xdb, 0xcd, 0x45, 0xb6, 0x96, 0x0c, 0x4d, 0x7b, 0x7f, 0x31, 0x65, 0xd9, 0x61, 0x0f, 0x2e, 0xcb, 0x00, 0xdb, 0xf2, 0x25, 0x78, 0x33, 0xcc, 0xd6, 0x92, 0xae, 0x69, 0xef, 0x87, 0x63,
0x41, 0x15, 0x3b, 0x1f, 0x6f, 0x84, 0xe1, 0xa6, 0xbe, 0x0d, 0xb4, 0x6b, 0x73, 0xc5, 0xdf, 0xf5, 0x96, 0x15, 0xd6, 0x02, 0x55, 0xec, 0x6d, 0xbc, 0x39, 0x0f, 0x37, 0xf1, 0xda, 0xd0, 0xcc, 0xb0,
0x3e, 0x39, 0xf1, 0x73, 0x88, 0x79, 0xe3, 0x02, 0x97, 0xc3, 0xcc, 0xcd, 0x2f, 0x77, 0x6d, 0x6b, 0xec, 0x52, 0xd1, 0x33, 0x88, 0x7a, 0x63, 0x04, 0x97, 0xe6, 0xe1, 0x66, 0x97, 0xbe, 0xb6, 0xbd,
0x29, 0x8c, 0x88, 0x60, 0x13, 0xe1, 0x2f, 0x40, 0x15, 0x2b, 0x1a, 0x6f, 0x87, 0x19, 0x38, 0x6b, 0x10, 0x46, 0x28, 0xdc, 0x42, 0xf8, 0x4b, 0x50, 0xc5, 0xea, 0xc6, 0x3b, 0xf3, 0x04, 0x9c, 0xb7,
0x95, 0xbf, 0x29, 0x14, 0x6f, 0x0f, 0x86, 0x87, 0x32, 0xbf, 0xbb, 0xc3, 0x43, 0x39, 0x63, 0xc3, 0xe2, 0xb5, 0x6b, 0x33, 0xf5, 0xbd, 0xe7, 0xbd, 0xd3, 0x3d, 0x57, 0xbc, 0xfd, 0x38, 0xdf, 0x95,
0x6e, 0x22, 0xdc, 0x1e, 0xaf, 0xcd, 0x8d, 0x05, 0xe7, 0xba, 0x7c, 0xcf, 0x5c, 0x54, 0x5d, 0xd6, 0xd9, 0x9d, 0x3e, 0xdf, 0x95, 0x73, 0x36, 0xef, 0x16, 0xf2, 0xd2, 0x24, 0xd7, 0xe9, 0x66, 0xc8,
0xfd, 0x10, 0x52, 0xc1, 0xa9, 0x8e, 0x17, 0x4a, 0xfd, 0xcc, 0xd2, 0xd0, 0xb6, 0x97, 0x03, 0xc9, 0x79, 0x1f, 0x36, 0x4d, 0x53, 0xeb, 0xe5, 0x08, 0x92, 0xc1, 0x69, 0x8f, 0x43, 0x85, 0x7e, 0x6a,
0xa7, 0x47, 0x10, 0x17, 0x14, 0xd9, 0x5a, 0x68, 0x9a, 0xcd, 0x24, 0x76, 0x7b, 0x39, 0x90, 0x78, 0x99, 0x68, 0x3b, 0x8b, 0x81, 0xa4, 0xea, 0x21, 0xc4, 0x44, 0xeb, 0x6c, 0x87, 0x9a, 0x72, 0x53,
0xb3, 0x88, 0x36, 0x11, 0xde, 0x87, 0x38, 0x9f, 0x01, 0x38, 0x94, 0x21, 0xc1, 0x51, 0x71, 0x5e, 0x81, 0xdd, 0x59, 0x0c, 0x24, 0x74, 0x16, 0xd0, 0x16, 0xc2, 0x07, 0x10, 0xe3, 0xb3, 0x01, 0xcf,
0x77, 0xec, 0x3c, 0x3d, 0x79, 0x9d, 0x8f, 0xfc, 0xf1, 0x3a, 0x1f, 0xf9, 0xee, 0x34, 0x8f, 0x4e, 0xed, 0x9c, 0xe0, 0x08, 0xb9, 0xa8, 0x3a, 0x76, 0x9f, 0x9c, 0xbe, 0xca, 0xad, 0xfd, 0xf9, 0x2a,
0x4e, 0xf3, 0xe8, 0xf7, 0xd3, 0x3c, 0xfa, 0xeb, 0x34, 0x8f, 0x9e, 0x7e, 0xb2, 0xea, 0x7f, 0x93, 0xb7, 0xf6, 0xfd, 0x59, 0x0e, 0x9d, 0x9e, 0xe5, 0xd0, 0x1f, 0x67, 0x39, 0xf4, 0xf7, 0x59, 0x0e,
0xb7, 0xa5, 0x58, 0x57, 0xf9, 0x5b, 0x5b, 0xff, 0x06, 0x00, 0x00, 0xff, 0xff, 0xed, 0xa1, 0x30, 0x3d, 0xf9, 0x64, 0xd9, 0xff, 0xad, 0xb7, 0x25, 0x59, 0x53, 0xb9, 0xae, 0xed, 0xff, 0x02, 0x00,
0xea, 0x98, 0x0e, 0x00, 0x00, 0x00, 0xff, 0xff, 0x63, 0x60, 0xb3, 0x49, 0x02, 0x0f, 0x00, 0x00,
} }

View File

@ -22,7 +22,7 @@ service Content {
// This call can be used to manage the mutable content labels. The // This call can be used to manage the mutable content labels. The
// immutable metadata such as digest, size, and committed at cannot // immutable metadata such as digest, size, and committed at cannot
// be updated. // be updated.
rpc Update(UpdateRequest) returns (google.protobuf.Empty); rpc Update(UpdateRequest) returns (UpdateResponse);
// List streams the entire set of content as Info objects and closes the // List streams the entire set of content as Info objects and closes the
// stream. // stream.
@ -111,6 +111,10 @@ message UpdateRequest {
google.protobuf.FieldMask update_mask = 2; google.protobuf.FieldMask update_mask = 2;
} }
message UpdateResponse {
Info info = 1 [(gogoproto.nullable) = false];
}
message ListContentRequest { message ListContentRequest {
// Filters contains one or more filters using the syntax defined in the // Filters contains one or more filters using the syntax defined in the
// containerd filter package. // containerd filter package.

46
cmd/dist/labels.go vendored
View File

@ -4,6 +4,7 @@ import (
"fmt" "fmt"
"strings" "strings"
"github.com/containerd/containerd/content"
digest "github.com/opencontainers/go-digest" digest "github.com/opencontainers/go-digest"
"github.com/urfave/cli" "github.com/urfave/cli"
) )
@ -16,8 +17,7 @@ var labelCommand = cli.Command{
Flags: []cli.Flag{}, Flags: []cli.Flag{},
Action: func(context *cli.Context) error { Action: func(context *cli.Context) error {
var ( var (
object = context.Args().First() object, labels = objectWithLabelArgs(context)
labelArgs = context.Args().Tail()
) )
ctx, cancel := appContext(context) ctx, cancel := appContext(context)
defer cancel() defer cancel()
@ -32,32 +32,36 @@ var labelCommand = cli.Command{
return err return err
} }
info, err := cs.Info(ctx, dgst) info := content.Info{
if err != nil { Digest: dgst,
return err Labels: map[string]string{},
}
if info.Labels == nil {
info.Labels = map[string]string{}
} }
var paths []string var paths []string
for _, arg := range labelArgs { for k, v := range labels {
var k, v string
if idx := strings.IndexByte(arg, '='); idx > 0 {
k = arg[:idx]
v = arg[idx+1:]
} else {
k = arg
}
paths = append(paths, fmt.Sprintf("labels.%s", k)) paths = append(paths, fmt.Sprintf("labels.%s", k))
if v == "" { if v != "" {
delete(info.Labels, k)
} else {
info.Labels[k] = v info.Labels[k] = v
} }
} }
return cs.Update(ctx, info, paths...) // Nothing updated, do no clear
if len(paths) == 0 {
info, err = cs.Info(ctx, info.Digest)
} else {
info, err = cs.Update(ctx, info, paths...)
}
if err != nil {
return err
}
var labelStrings []string
for k, v := range info.Labels {
labelStrings = append(labelStrings, fmt.Sprintf("%s=%s", k, v))
}
fmt.Println(strings.Join(labelStrings, ","))
return nil
}, },
} }

View File

@ -60,7 +60,7 @@ type Manager interface {
// fields will be updated. // fields will be updated.
// Mutable fields: // Mutable fields:
// labels.* // labels.*
Update(ctx context.Context, info Info, fieldpaths ...string) error Update(ctx context.Context, info Info, fieldpaths ...string) (Info, error)
// Walk will call fn for each item in the content store which // Walk will call fn for each item in the content store which
// match the provided filters. If no filters are given all // match the provided filters. If no filters are given all

View File

@ -93,9 +93,9 @@ func (cs *store) Delete(ctx context.Context, dgst digest.Digest) error {
return nil return nil
} }
func (cs *store) Update(ctx context.Context, info Info, fieldpaths ...string) error { func (cs *store) Update(ctx context.Context, info Info, fieldpaths ...string) (Info, error) {
// TODO: Support persisting and updating mutable content data // TODO: Support persisting and updating mutable content data
return errors.Wrapf(errdefs.ErrFailedPrecondition, "update not supported on immutable content store") return Info{}, errors.Wrapf(errdefs.ErrFailedPrecondition, "update not supported on immutable content store")
} }
func (cs *store) Walk(ctx context.Context, fn WalkFunc, filters ...string) error { func (cs *store) Walk(ctx context.Context, fn WalkFunc, filters ...string) error {

View File

@ -57,12 +57,12 @@ func (i *image) Unpack(ctx context.Context, snapshotterName string) error {
if err != nil { if err != nil {
return err return err
} }
if info.Labels["uncompressed"] != layer.Diff.Digest.String() { if info.Labels["containerd.io/uncompressed"] != layer.Diff.Digest.String() {
if info.Labels == nil { if info.Labels == nil {
info.Labels = map[string]string{} info.Labels = map[string]string{}
} }
info.Labels["uncompressed"] = layer.Diff.Digest.String() info.Labels["containerd.io/uncompressed"] = layer.Diff.Digest.String()
if err := cs.Update(ctx, info, "labels.uncompressed"); err != nil { if _, err := cs.Update(ctx, info, "labels.containerd.io/uncompressed"); err != nil {
return err return err
} }
} }

View File

@ -70,6 +70,25 @@ func adaptContainer(o interface{}) filters.Adaptor {
}) })
} }
func adaptContentInfo(info content.Info) filters.Adaptor {
return filters.AdapterFunc(func(fieldpath []string) (string, bool) {
if len(fieldpath) == 0 {
return "", false
}
switch fieldpath[0] {
case "digest":
return info.Digest.String(), true
case "size":
// TODO: support size based filtering
case "labels":
return checkMap(fieldpath[1:], info.Labels)
}
return "", false
})
}
func adaptContentStatus(status content.Status) filters.Adaptor { func adaptContentStatus(status content.Status) filters.Adaptor {
return filters.AdapterFunc(func(fieldpath []string) (string, bool) { return filters.AdapterFunc(func(fieldpath []string) (string, bool) {
if len(fieldpath) == 0 { if len(fieldpath) == 0 {

View File

@ -52,21 +52,20 @@ func (cs *contentStore) Info(ctx context.Context, dgst digest.Digest) (content.I
return info, nil return info, nil
} }
func (cs *contentStore) Update(ctx context.Context, info content.Info, fieldpaths ...string) error { func (cs *contentStore) Update(ctx context.Context, info content.Info, fieldpaths ...string) (content.Info, error) {
ns, err := namespaces.NamespaceRequired(ctx) ns, err := namespaces.NamespaceRequired(ctx)
if err != nil { if err != nil {
return err return content.Info{}, err
}
if err := update(ctx, cs.db, func(tx *bolt.Tx) error {
bkt := getBlobBucket(tx, ns, info.Digest)
if bkt == nil {
return errors.Wrapf(errdefs.ErrNotFound, "content digest %v", info.Digest)
} }
updated := content.Info{ updated := content.Info{
Digest: info.Digest, Digest: info.Digest,
} }
if err := update(ctx, cs.db, func(tx *bolt.Tx) error {
bkt := getBlobBucket(tx, ns, info.Digest)
if bkt == nil {
return errors.Wrapf(errdefs.ErrNotFound, "content digest %v", info.Digest)
}
if err := readInfo(&updated, bkt); err != nil { if err := readInfo(&updated, bkt); err != nil {
return errors.Wrapf(err, "info %q", info.Digest) return errors.Wrapf(err, "info %q", info.Digest)
@ -92,16 +91,16 @@ func (cs *contentStore) Update(ctx context.Context, info content.Info, fieldpath
} }
} }
} else { } else {
info.CommittedAt = updated.CommittedAt // Set mutable fields
updated = info updated.Labels = info.Labels
} }
updated.UpdatedAt = time.Now().UTC() updated.UpdatedAt = time.Now().UTC()
return writeInfo(&updated, bkt) return writeInfo(&updated, bkt)
}); err != nil { }); err != nil {
return err return content.Info{}, err
} }
return nil return updated, nil
} }
func (cs *contentStore) Walk(ctx context.Context, fn content.WalkFunc, fs ...string) error { func (cs *contentStore) Walk(ctx context.Context, fn content.WalkFunc, fs ...string) error {
@ -110,17 +109,9 @@ func (cs *contentStore) Walk(ctx context.Context, fn content.WalkFunc, fs ...str
return err return err
} }
var filter filters.Filter = filters.Always filter, err := filters.ParseAll(fs...)
if len(fs) > 0 {
fa := make([]filters.Filter, 0, len(fs))
for _, s := range fs {
f, err := filters.Parse(s)
if err != nil { if err != nil {
return errors.Wrapf(errdefs.ErrInvalidArgument, "bad filter %q", s) return err
}
fa = append(fa, f)
}
filter = filters.Filter(filters.Any(fa))
} }
// TODO: Batch results to keep from reading all info into memory // TODO: Batch results to keep from reading all info into memory
@ -481,22 +472,3 @@ func writeInfo(info *content.Info, bkt *bolt.Bucket) error {
return nil return nil
} }
func adaptContentInfo(info content.Info) filters.Adaptor {
return filters.AdapterFunc(func(fieldpath []string) (string, bool) {
if len(fieldpath) == 0 {
return "", false
}
switch fieldpath[0] {
case "digest":
return info.Digest.String(), true
case "size":
// TODO: support size based filtering
case "labels":
return checkMap(fieldpath[1:], info.Labels)
}
return "", false
})
}

View File

@ -83,16 +83,19 @@ func (s *Service) Info(ctx context.Context, req *api.InfoRequest) (*api.InfoResp
}, nil }, nil
} }
func (s *Service) Update(ctx context.Context, req *api.UpdateRequest) (*empty.Empty, error) { func (s *Service) Update(ctx context.Context, req *api.UpdateRequest) (*api.UpdateResponse, error) {
if err := req.Info.Digest.Validate(); err != nil { if err := req.Info.Digest.Validate(); err != nil {
return nil, grpc.Errorf(codes.InvalidArgument, "%q failed validation", req.Info.Digest) return nil, grpc.Errorf(codes.InvalidArgument, "%q failed validation", req.Info.Digest)
} }
if err := s.store.Update(ctx, infoFromGRPC(req.Info), req.UpdateMask.GetPaths()...); err != nil { info, err := s.store.Update(ctx, infoFromGRPC(req.Info), req.UpdateMask.GetPaths()...)
if err != nil {
return nil, errdefs.ToGRPC(err) return nil, errdefs.ToGRPC(err)
} }
return &empty.Empty{}, nil return &api.UpdateResponse{
Info: infoToGRPC(info),
}, nil
} }
func (s *Service) List(req *api.ListContentRequest, session api.Content_ListServer) error { func (s *Service) List(req *api.ListContentRequest, session api.Content_ListServer) error {

View File

@ -108,16 +108,17 @@ func (rs *remoteStore) Status(ctx context.Context, ref string) (content.Status,
}, nil }, nil
} }
func (rs *remoteStore) Update(ctx context.Context, info content.Info, fieldpaths ...string) error { func (rs *remoteStore) Update(ctx context.Context, info content.Info, fieldpaths ...string) (content.Info, error) {
if _, err := rs.client.Update(ctx, &contentapi.UpdateRequest{ resp, err := rs.client.Update(ctx, &contentapi.UpdateRequest{
Info: infoToGRPC(info), Info: infoToGRPC(info),
UpdateMask: &protobuftypes.FieldMask{ UpdateMask: &protobuftypes.FieldMask{
Paths: fieldpaths, Paths: fieldpaths,
}, },
}); err != nil { })
return errdefs.FromGRPC(err) if err != nil {
return content.Info{}, errdefs.FromGRPC(err)
} }
return nil return infoFromGRPC(resp.Info), nil
} }
func (rs *remoteStore) ListStatuses(ctx context.Context, filters ...string) ([]content.Status, error) { func (rs *remoteStore) ListStatuses(ctx context.Context, filters ...string) ([]content.Status, error) {