storagenode/piecestore: delete several pieces in a single request

This is part of the deletion performance improvement.
See https://storjlabs.atlassian.net/browse/V3-3349

Change-Id: Idcd83a302f2bd5cc3299e1a4195a7e177f452599
This commit is contained in:
Fadila 2019-12-18 16:33:12 +01:00 committed by Kaloyan Raev
parent 7df3c9efc3
commit 115b8b0fc8
7 changed files with 404 additions and 62 deletions

View File

@ -49,7 +49,7 @@ func (x PieceHeader_FormatVersion) String() string {
}
func (PieceHeader_FormatVersion) EnumDescriptor() ([]byte, []int) {
return fileDescriptor_23ff32dd550c2439, []int{12, 0}
return fileDescriptor_23ff32dd550c2439, []int{14, 0}
}
// Expected order of messages from uplink:
@ -550,6 +550,67 @@ func (m *PieceDeletePieceResponse) XXX_DiscardUnknown() {
var xxx_messageInfo_PieceDeletePieceResponse proto.InternalMessageInfo
type DeletePiecesRequest struct {
PieceIds []PieceID `protobuf:"bytes,1,rep,name=piece_ids,json=pieceIds,proto3,customtype=PieceID" json:"piece_ids"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *DeletePiecesRequest) Reset() { *m = DeletePiecesRequest{} }
func (m *DeletePiecesRequest) String() string { return proto.CompactTextString(m) }
func (*DeletePiecesRequest) ProtoMessage() {}
func (*DeletePiecesRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_23ff32dd550c2439, []int{8}
}
func (m *DeletePiecesRequest) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_DeletePiecesRequest.Unmarshal(m, b)
}
func (m *DeletePiecesRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_DeletePiecesRequest.Marshal(b, m, deterministic)
}
func (m *DeletePiecesRequest) XXX_Merge(src proto.Message) {
xxx_messageInfo_DeletePiecesRequest.Merge(m, src)
}
func (m *DeletePiecesRequest) XXX_Size() int {
return xxx_messageInfo_DeletePiecesRequest.Size(m)
}
func (m *DeletePiecesRequest) XXX_DiscardUnknown() {
xxx_messageInfo_DeletePiecesRequest.DiscardUnknown(m)
}
var xxx_messageInfo_DeletePiecesRequest proto.InternalMessageInfo
type DeletePiecesResponse struct {
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *DeletePiecesResponse) Reset() { *m = DeletePiecesResponse{} }
func (m *DeletePiecesResponse) String() string { return proto.CompactTextString(m) }
func (*DeletePiecesResponse) ProtoMessage() {}
func (*DeletePiecesResponse) Descriptor() ([]byte, []int) {
return fileDescriptor_23ff32dd550c2439, []int{9}
}
func (m *DeletePiecesResponse) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_DeletePiecesResponse.Unmarshal(m, b)
}
func (m *DeletePiecesResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_DeletePiecesResponse.Marshal(b, m, deterministic)
}
func (m *DeletePiecesResponse) XXX_Merge(src proto.Message) {
xxx_messageInfo_DeletePiecesResponse.Merge(m, src)
}
func (m *DeletePiecesResponse) XXX_Size() int {
return xxx_messageInfo_DeletePiecesResponse.Size(m)
}
func (m *DeletePiecesResponse) XXX_DiscardUnknown() {
xxx_messageInfo_DeletePiecesResponse.DiscardUnknown(m)
}
var xxx_messageInfo_DeletePiecesResponse proto.InternalMessageInfo
type RetainRequest struct {
CreationDate time.Time `protobuf:"bytes,1,opt,name=creation_date,json=creationDate,proto3,stdtime" json:"creation_date"`
Filter []byte `protobuf:"bytes,2,opt,name=filter,proto3" json:"filter,omitempty"`
@ -562,7 +623,7 @@ func (m *RetainRequest) Reset() { *m = RetainRequest{} }
func (m *RetainRequest) String() string { return proto.CompactTextString(m) }
func (*RetainRequest) ProtoMessage() {}
func (*RetainRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_23ff32dd550c2439, []int{8}
return fileDescriptor_23ff32dd550c2439, []int{10}
}
func (m *RetainRequest) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_RetainRequest.Unmarshal(m, b)
@ -606,7 +667,7 @@ func (m *RetainResponse) Reset() { *m = RetainResponse{} }
func (m *RetainResponse) String() string { return proto.CompactTextString(m) }
func (*RetainResponse) ProtoMessage() {}
func (*RetainResponse) Descriptor() ([]byte, []int) {
return fileDescriptor_23ff32dd550c2439, []int{9}
return fileDescriptor_23ff32dd550c2439, []int{11}
}
func (m *RetainResponse) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_RetainResponse.Unmarshal(m, b)
@ -636,7 +697,7 @@ func (m *RestoreTrashRequest) Reset() { *m = RestoreTrashRequest{} }
func (m *RestoreTrashRequest) String() string { return proto.CompactTextString(m) }
func (*RestoreTrashRequest) ProtoMessage() {}
func (*RestoreTrashRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_23ff32dd550c2439, []int{10}
return fileDescriptor_23ff32dd550c2439, []int{12}
}
func (m *RestoreTrashRequest) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_RestoreTrashRequest.Unmarshal(m, b)
@ -666,7 +727,7 @@ func (m *RestoreTrashResponse) Reset() { *m = RestoreTrashResponse{} }
func (m *RestoreTrashResponse) String() string { return proto.CompactTextString(m) }
func (*RestoreTrashResponse) ProtoMessage() {}
func (*RestoreTrashResponse) Descriptor() ([]byte, []int) {
return fileDescriptor_23ff32dd550c2439, []int{11}
return fileDescriptor_23ff32dd550c2439, []int{13}
}
func (m *RestoreTrashResponse) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_RestoreTrashResponse.Unmarshal(m, b)
@ -711,7 +772,7 @@ func (m *PieceHeader) Reset() { *m = PieceHeader{} }
func (m *PieceHeader) String() string { return proto.CompactTextString(m) }
func (*PieceHeader) ProtoMessage() {}
func (*PieceHeader) Descriptor() ([]byte, []int) {
return fileDescriptor_23ff32dd550c2439, []int{12}
return fileDescriptor_23ff32dd550c2439, []int{14}
}
func (m *PieceHeader) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_PieceHeader.Unmarshal(m, b)
@ -779,6 +840,8 @@ func init() {
proto.RegisterType((*PieceDeleteResponse)(nil), "piecestore.PieceDeleteResponse")
proto.RegisterType((*PieceDeletePieceRequest)(nil), "piecestore.PieceDeletePieceRequest")
proto.RegisterType((*PieceDeletePieceResponse)(nil), "piecestore.PieceDeletePieceResponse")
proto.RegisterType((*DeletePiecesRequest)(nil), "piecestore.DeletePiecesRequest")
proto.RegisterType((*DeletePiecesResponse)(nil), "piecestore.DeletePiecesResponse")
proto.RegisterType((*RetainRequest)(nil), "piecestore.RetainRequest")
proto.RegisterType((*RetainResponse)(nil), "piecestore.RetainResponse")
proto.RegisterType((*RestoreTrashRequest)(nil), "piecestore.RestoreTrashRequest")
@ -789,54 +852,57 @@ func init() {
func init() { proto.RegisterFile("piecestore2.proto", fileDescriptor_23ff32dd550c2439) }
var fileDescriptor_23ff32dd550c2439 = []byte{
// 747 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x54, 0x4b, 0x4f, 0x13, 0x51,
0x14, 0x66, 0xfa, 0x02, 0x4e, 0xa7, 0x08, 0x97, 0x87, 0x75, 0xa2, 0x16, 0x07, 0x50, 0x62, 0xe2,
0x80, 0x65, 0xa5, 0x41, 0x8c, 0xb5, 0x12, 0x49, 0x40, 0xc8, 0xe5, 0x11, 0xe3, 0xa6, 0x19, 0x98,
0xdb, 0x76, 0x62, 0x3b, 0xb7, 0xce, 0xdc, 0x6a, 0xc2, 0x2f, 0x70, 0xe9, 0x6f, 0x72, 0xe5, 0x6f,
0x30, 0x06, 0x17, 0xfe, 0x03, 0xb7, 0x6e, 0xcc, 0x7d, 0x4c, 0x3b, 0xd3, 0x67, 0x30, 0x71, 0xd5,
0xde, 0x73, 0xbe, 0xf3, 0x98, 0xef, 0x7c, 0xe7, 0xc0, 0x5c, 0xcb, 0x25, 0x17, 0x24, 0x60, 0xd4,
0x27, 0x45, 0xab, 0xe5, 0x53, 0x46, 0x11, 0x74, 0x4d, 0x06, 0xd4, 0x68, 0x8d, 0x4a, 0xbb, 0x51,
0xa8, 0x51, 0x5a, 0x6b, 0x90, 0x0d, 0xf1, 0x3a, 0x6f, 0x57, 0x37, 0x98, 0xdb, 0x24, 0x01, 0xb3,
0x9b, 0x2d, 0x05, 0xd0, 0xa9, 0xef, 0x10, 0x3f, 0x90, 0x2f, 0xf3, 0x8f, 0x06, 0xe8, 0x88, 0x67,
0x3a, 0x6d, 0x35, 0xa8, 0xed, 0x60, 0xf2, 0xa1, 0x4d, 0x02, 0x86, 0xd6, 0x21, 0xdd, 0x70, 0x9b,
0x2e, 0xcb, 0x6b, 0xcb, 0xda, 0x7a, 0xb6, 0x88, 0x2c, 0x15, 0x74, 0xc8, 0x7f, 0xf6, 0xb9, 0x07,
0x4b, 0x00, 0x5a, 0x81, 0xb4, 0xf0, 0xe5, 0x13, 0x02, 0x99, 0x8b, 0x21, 0xb1, 0xf4, 0xa1, 0xa7,
0x90, 0xbe, 0xa8, 0xb7, 0xbd, 0xf7, 0xf9, 0xa4, 0x00, 0xad, 0x5a, 0xdd, 0xe6, 0xad, 0xfe, 0xea,
0xd6, 0x4b, 0x8e, 0xc5, 0x32, 0x04, 0xad, 0x41, 0xca, 0xa1, 0x1e, 0xc9, 0xa7, 0x44, 0xe8, 0x5c,
0x98, 0x5f, 0x84, 0xbd, 0xb6, 0x83, 0x3a, 0x16, 0x6e, 0x63, 0x0b, 0xd2, 0x22, 0x0c, 0x2d, 0x41,
0x86, 0x56, 0xab, 0x01, 0x91, 0xbd, 0x27, 0xb1, 0x7a, 0x21, 0x04, 0x29, 0xc7, 0x66, 0xb6, 0xe8,
0x53, 0xc7, 0xe2, 0xbf, 0xb9, 0x0d, 0xf3, 0xb1, 0xf2, 0x41, 0x8b, 0x7a, 0x01, 0xe9, 0x94, 0xd4,
0x46, 0x96, 0x34, 0x7f, 0x69, 0xb0, 0x20, 0x6c, 0x65, 0xfa, 0xc9, 0xfb, 0x8f, 0xec, 0x6d, 0xc7,
0xd9, 0xbb, 0xdf, 0xc7, 0x5e, 0x4f, 0xfd, 0x18, 0x7f, 0xc6, 0xce, 0x38, 0x62, 0xee, 0x00, 0x08,
0x64, 0x25, 0x70, 0x2f, 0x89, 0x68, 0x24, 0x89, 0xa7, 0x85, 0xe5, 0xd8, 0xbd, 0x24, 0xe6, 0x0f,
0x0d, 0x16, 0x7b, 0xaa, 0x28, 0x9a, 0x9e, 0x85, 0x7d, 0xc9, 0xcf, 0x7c, 0x30, 0xa2, 0x2f, 0x19,
0xd1, 0x37, 0xd8, 0xba, 0x1d, 0xd4, 0xd5, 0xa7, 0x0f, 0x62, 0x99, 0xbb, 0xbb, 0x64, 0x26, 0xc7,
0x90, 0xf9, 0x6f, 0x12, 0xd8, 0x51, 0xfa, 0x2f, 0x93, 0x06, 0x61, 0xe4, 0xda, 0x13, 0x34, 0x17,
0x95, 0x84, 0xc2, 0x78, 0xf9, 0xa5, 0xe6, 0x2b, 0xb8, 0x19, 0x31, 0x8b, 0xbf, 0x61, 0xee, 0x87,
0x30, 0x25, 0x88, 0xaa, 0xb8, 0x8e, 0x48, 0xaf, 0x97, 0x6e, 0x7c, 0xbb, 0x2a, 0x4c, 0x7c, 0xbf,
0x2a, 0x4c, 0x0a, 0xdc, 0x5e, 0x19, 0x4f, 0x0a, 0xc0, 0x9e, 0x63, 0x1a, 0x90, 0xef, 0x4f, 0xa3,
0x4a, 0xf8, 0x90, 0xc3, 0x84, 0xd9, 0xae, 0x17, 0x26, 0xde, 0x83, 0xdc, 0x85, 0x4f, 0x6c, 0xe6,
0x52, 0xaf, 0xe2, 0xd8, 0x2c, 0xd4, 0xaf, 0x61, 0xc9, 0x93, 0x60, 0x85, 0x27, 0xc1, 0x3a, 0x09,
0x4f, 0x42, 0x69, 0x8a, 0x57, 0xfe, 0xf2, 0xb3, 0xa0, 0x61, 0x3d, 0x0c, 0x2d, 0xdb, 0x8c, 0x70,
0x06, 0xab, 0x6e, 0x83, 0x29, 0x61, 0xea, 0x58, 0xbd, 0xcc, 0x59, 0x98, 0x09, 0x6b, 0xaa, 0x2e,
0x16, 0x61, 0x1e, 0xcb, 0x99, 0x9f, 0xf8, 0x7c, 0x68, 0xb2, 0x17, 0x73, 0x09, 0x16, 0xe2, 0x66,
0x05, 0xff, 0x9a, 0x80, 0xac, 0x9c, 0x30, 0xb1, 0xb9, 0xb6, 0xf7, 0x61, 0xa6, 0x4a, 0xfd, 0xa6,
0xcd, 0x2a, 0x1f, 0x89, 0x1f, 0xb8, 0xd4, 0x13, 0x4d, 0xcf, 0x14, 0xd7, 0xfa, 0xc4, 0x24, 0x03,
0xac, 0x5d, 0x81, 0x3e, 0x93, 0x60, 0x9c, 0xab, 0x46, 0x9f, 0x7c, 0xc0, 0x1d, 0x49, 0xe9, 0x4a,
0x3f, 0x51, 0x56, 0xf8, 0x2d, 0x54, 0x3a, 0xba, 0x26, 0x2b, 0xdc, 0x89, 0x6e, 0xc3, 0x74, 0xe0,
0xd6, 0x3c, 0x9b, 0xb5, 0x7d, 0x79, 0x8f, 0x74, 0xdc, 0x35, 0xa0, 0x27, 0x90, 0x15, 0x2a, 0xa9,
0x48, 0xe5, 0xa4, 0x87, 0x29, 0xa7, 0x94, 0xe2, 0xe9, 0x31, 0xd0, 0x8e, 0xc5, 0x7c, 0x04, 0xb9,
0xd8, 0x77, 0xa1, 0x1c, 0x4c, 0xef, 0x1e, 0xe2, 0x83, 0x17, 0x27, 0x95, 0xb3, 0xcd, 0xd9, 0x89,
0xe8, 0xf3, 0xf1, 0xac, 0x56, 0xfc, 0x9d, 0x04, 0x38, 0xea, 0xd0, 0x83, 0x0e, 0x20, 0x23, 0x0f,
0x18, 0xba, 0x3b, 0xfa, 0xb0, 0x1a, 0x85, 0xa1, 0x7e, 0x35, 0x9e, 0x89, 0x75, 0x0d, 0x9d, 0xc2,
0x54, 0xb8, 0xb8, 0x68, 0x79, 0xdc, 0xad, 0x31, 0xee, 0x8d, 0xdd, 0x7a, 0x9e, 0x74, 0x53, 0x43,
0x6f, 0x20, 0x23, 0x55, 0x3c, 0xa0, 0xcb, 0xd8, 0xf2, 0x0d, 0xe8, 0xb2, 0x67, 0xb9, 0x92, 0x9f,
0x13, 0x1a, 0x7a, 0x0b, 0xd9, 0xc8, 0x56, 0xa0, 0x95, 0x21, 0x41, 0xd1, 0xd5, 0x33, 0x56, 0x47,
0x83, 0xd4, 0x5d, 0x7b, 0x0e, 0x19, 0x29, 0x72, 0x74, 0x2b, 0x8a, 0x8f, 0x2d, 0x9b, 0x61, 0x0c,
0x72, 0xa9, 0x04, 0xc7, 0xa0, 0x47, 0xc5, 0x8f, 0x0a, 0x71, 0x6c, 0xdf, 0xb6, 0x18, 0xcb, 0xc3,
0x01, 0x21, 0x87, 0xa5, 0xd4, 0xbb, 0x44, 0xeb, 0xfc, 0x3c, 0x23, 0xe4, 0xba, 0xf5, 0x37, 0x00,
0x00, 0xff, 0xff, 0xfb, 0xe1, 0x1b, 0xbe, 0x12, 0x08, 0x00, 0x00,
// 793 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x54, 0xcb, 0x6e, 0xd3, 0x4c,
0x14, 0x8e, 0x73, 0x6b, 0x72, 0xe2, 0xf4, 0x6f, 0xa7, 0x97, 0x3f, 0x58, 0x40, 0x82, 0xdb, 0x42,
0x85, 0xc0, 0x2d, 0xe9, 0x0a, 0x54, 0x8a, 0x48, 0x43, 0x45, 0xa5, 0x96, 0x96, 0xe9, 0x65, 0x81,
0x84, 0x22, 0xb7, 0x99, 0x24, 0x16, 0x89, 0x27, 0xd8, 0x0e, 0x48, 0x7d, 0x02, 0x96, 0x3c, 0x13,
0x2b, 0xc4, 0x23, 0x20, 0x54, 0x16, 0x3c, 0x06, 0x1b, 0x34, 0x17, 0x27, 0x76, 0xe3, 0x24, 0x2a,
0x12, 0xab, 0x64, 0xce, 0x7c, 0xe7, 0x3b, 0x9f, 0xcf, 0x7c, 0xe7, 0xc0, 0x6c, 0xd7, 0x22, 0xe7,
0xc4, 0xf5, 0xa8, 0x43, 0xca, 0x46, 0xd7, 0xa1, 0x1e, 0x45, 0x30, 0x08, 0x69, 0xd0, 0xa4, 0x4d,
0x2a, 0xe2, 0x5a, 0xb1, 0x49, 0x69, 0xb3, 0x4d, 0xd6, 0xf8, 0xe9, 0xac, 0xd7, 0x58, 0xf3, 0xac,
0x0e, 0x71, 0x3d, 0xb3, 0xd3, 0x95, 0x00, 0x95, 0x3a, 0x75, 0xe2, 0xb8, 0xe2, 0xa4, 0xff, 0x56,
0x00, 0x1d, 0x32, 0xa6, 0x93, 0x6e, 0x9b, 0x9a, 0x75, 0x4c, 0xde, 0xf7, 0x88, 0xeb, 0xa1, 0x55,
0x48, 0xb5, 0xad, 0x8e, 0xe5, 0x15, 0x94, 0x92, 0xb2, 0x9a, 0x2b, 0x23, 0x43, 0x26, 0x1d, 0xb0,
0x9f, 0x3d, 0x76, 0x83, 0x05, 0x00, 0x2d, 0x41, 0x8a, 0xdf, 0x15, 0xe2, 0x1c, 0x99, 0x0f, 0x21,
0xb1, 0xb8, 0x43, 0x4f, 0x20, 0x75, 0xde, 0xea, 0xd9, 0xef, 0x0a, 0x09, 0x0e, 0x5a, 0x36, 0x06,
0xe2, 0x8d, 0xe1, 0xea, 0xc6, 0x36, 0xc3, 0x62, 0x91, 0x82, 0x56, 0x20, 0x59, 0xa7, 0x36, 0x29,
0x24, 0x79, 0xea, 0xac, 0xcf, 0xcf, 0xd3, 0x5e, 0x9a, 0x6e, 0x0b, 0xf3, 0x6b, 0x6d, 0x03, 0x52,
0x3c, 0x0d, 0x2d, 0x42, 0x9a, 0x36, 0x1a, 0x2e, 0x11, 0xda, 0x13, 0x58, 0x9e, 0x10, 0x82, 0x64,
0xdd, 0xf4, 0x4c, 0xae, 0x53, 0xc5, 0xfc, 0xbf, 0xbe, 0x09, 0x73, 0xa1, 0xf2, 0x6e, 0x97, 0xda,
0x2e, 0xe9, 0x97, 0x54, 0xc6, 0x96, 0xd4, 0x7f, 0x29, 0x30, 0xcf, 0x63, 0x55, 0xfa, 0xd1, 0xfe,
0x87, 0xdd, 0xdb, 0x0c, 0x77, 0xef, 0xee, 0x50, 0xf7, 0xae, 0xd4, 0x0f, 0xf5, 0x4f, 0xdb, 0x9a,
0xd4, 0x98, 0x5b, 0x00, 0x1c, 0x59, 0x73, 0xad, 0x0b, 0xc2, 0x85, 0x24, 0x70, 0x96, 0x47, 0x8e,
0xac, 0x0b, 0xa2, 0xff, 0x50, 0x60, 0xe1, 0x4a, 0x15, 0xd9, 0xa6, 0xa7, 0xbe, 0x2e, 0xf1, 0x99,
0xf7, 0xc6, 0xe8, 0x12, 0x19, 0x43, 0x0f, 0xdb, 0x32, 0xdd, 0x96, 0xfc, 0xf4, 0xa8, 0x2e, 0xb3,
0xeb, 0x41, 0x33, 0x13, 0x13, 0x9a, 0xf9, 0x77, 0x16, 0xd8, 0x92, 0xfe, 0xaf, 0x92, 0x36, 0xf1,
0xc8, 0xb5, 0x5f, 0x50, 0x5f, 0x90, 0x16, 0xf2, 0xf3, 0xc5, 0x97, 0xea, 0x2f, 0xe0, 0xff, 0x40,
0x98, 0xff, 0xf5, 0xb9, 0xef, 0x43, 0x86, 0x37, 0xaa, 0x66, 0xd5, 0x39, 0xbd, 0x5a, 0xf9, 0xef,
0xeb, 0x65, 0x31, 0xf6, 0xfd, 0xb2, 0x38, 0xc5, 0x71, 0xbb, 0x55, 0x3c, 0xc5, 0x01, 0xbb, 0x75,
0x5d, 0x83, 0xc2, 0x30, 0x8d, 0x2c, 0xb1, 0x0d, 0x73, 0x81, 0xb0, 0xeb, 0xd3, 0x3f, 0x80, 0xac,
0x4f, 0xef, 0x16, 0x94, 0x52, 0x22, 0x8a, 0x3f, 0x23, 0xf9, 0x5d, 0x7d, 0x11, 0xe6, 0xc3, 0x24,
0x92, 0xdc, 0x81, 0x3c, 0x26, 0x9e, 0x69, 0xd9, 0x3e, 0xed, 0x2e, 0xe4, 0xcf, 0x1d, 0x62, 0x7a,
0x16, 0xb5, 0x6b, 0x75, 0xd3, 0xf3, 0x87, 0x43, 0x33, 0xc4, 0xbe, 0x31, 0xfc, 0x7d, 0x63, 0x1c,
0xfb, 0xfb, 0xa6, 0x92, 0x61, 0x65, 0x3f, 0xff, 0x2c, 0x2a, 0x58, 0xf5, 0x53, 0xab, 0xa6, 0x47,
0xd8, 0xf3, 0x34, 0xac, 0xb6, 0x27, 0x5d, 0xaf, 0x62, 0x79, 0xd2, 0x67, 0x60, 0xda, 0xaf, 0x29,
0x55, 0x2c, 0xc0, 0x1c, 0x16, 0x86, 0x3a, 0x76, 0x98, 0x23, 0x84, 0x16, 0x26, 0x3a, 0x1c, 0x96,
0xf0, 0x2f, 0x71, 0xc8, 0x09, 0xfb, 0x10, 0x93, 0x0d, 0xce, 0x1e, 0x4c, 0x37, 0xa8, 0xd3, 0x31,
0xbd, 0xda, 0x07, 0xe2, 0xb8, 0x16, 0xb5, 0xb9, 0xe8, 0xe9, 0xf2, 0xca, 0x90, 0x53, 0x45, 0x82,
0xb1, 0xc3, 0xd1, 0xa7, 0x02, 0x8c, 0xf3, 0x8d, 0xe0, 0x91, 0xb9, 0xa7, 0xef, 0x57, 0x55, 0x9a,
0x33, 0xd8, 0x15, 0xb6, 0x68, 0xa5, 0x49, 0xaf, 0xd9, 0x15, 0x76, 0x89, 0x6e, 0x42, 0xd6, 0xb5,
0x9a, 0xb6, 0xe9, 0xf5, 0x1c, 0xb1, 0xec, 0x54, 0x3c, 0x08, 0xa0, 0xc7, 0x90, 0xe3, 0x16, 0xac,
0x09, 0x5b, 0xa6, 0x46, 0xd9, 0xb2, 0x92, 0x64, 0xf4, 0x18, 0x68, 0x3f, 0xa2, 0x3f, 0x84, 0x7c,
0xe8, 0xbb, 0x50, 0x1e, 0xb2, 0x3b, 0x07, 0x78, 0xff, 0xf9, 0x71, 0xed, 0x74, 0x7d, 0x26, 0x16,
0x3c, 0x3e, 0x9a, 0x51, 0xca, 0xdf, 0x92, 0x00, 0x87, 0xfd, 0xf6, 0xa0, 0x7d, 0x48, 0x8b, 0xed,
0x88, 0x6e, 0x8f, 0xdf, 0xda, 0x5a, 0x71, 0xe4, 0xbd, 0x7c, 0x9e, 0xd8, 0xaa, 0x82, 0x4e, 0x20,
0xe3, 0x6f, 0x05, 0x54, 0x9a, 0xb4, 0xc8, 0xb4, 0x3b, 0x13, 0x57, 0x0a, 0x23, 0x5d, 0x57, 0xd0,
0x2b, 0x48, 0x0b, 0x1b, 0x47, 0xa8, 0x0c, 0x4d, 0x76, 0x84, 0xca, 0x2b, 0x93, 0x9b, 0xf8, 0x14,
0x57, 0xd0, 0x5b, 0xc8, 0x05, 0xc6, 0x02, 0x2d, 0x8d, 0x48, 0x0a, 0xce, 0xb5, 0xb6, 0x3c, 0x1e,
0x14, 0xa4, 0x7f, 0x0d, 0x6a, 0x70, 0xea, 0x50, 0x48, 0x54, 0xc4, 0x50, 0x6b, 0xa5, 0xd1, 0x00,
0xb9, 0x8c, 0x9f, 0x41, 0x5a, 0x0c, 0x0f, 0xba, 0x11, 0xc4, 0x86, 0x86, 0x58, 0xd3, 0xa2, 0xae,
0x24, 0xc1, 0x11, 0xa8, 0xc1, 0xa1, 0x0a, 0x6b, 0x8a, 0x98, 0xc2, 0xb0, 0xa6, 0xc8, 0x79, 0x8c,
0x55, 0x92, 0x6f, 0xe2, 0xdd, 0xb3, 0xb3, 0x34, 0x1f, 0x83, 0x8d, 0x3f, 0x01, 0x00, 0x00, 0xff,
0xff, 0x87, 0xd0, 0x1d, 0xa6, 0xc7, 0x08, 0x00, 0x00,
}
type DRPCPiecestoreClient interface {
@ -847,6 +913,8 @@ type DRPCPiecestoreClient interface {
Delete(ctx context.Context, in *PieceDeleteRequest) (*PieceDeleteResponse, error)
// DeletePiece deletes a piece from a satellite request
DeletePiece(ctx context.Context, in *PieceDeletePieceRequest) (*PieceDeletePieceResponse, error)
// DeletePieces deletes a set of pieces on satellite request
DeletePieces(ctx context.Context, in *DeletePiecesRequest) (*DeletePiecesResponse, error)
Retain(ctx context.Context, in *RetainRequest) (*RetainResponse, error)
RestoreTrash(ctx context.Context, in *RestoreTrashRequest) (*RestoreTrashResponse, error)
}
@ -944,6 +1012,15 @@ func (c *drpcPiecestoreClient) DeletePiece(ctx context.Context, in *PieceDeleteP
return out, nil
}
func (c *drpcPiecestoreClient) DeletePieces(ctx context.Context, in *DeletePiecesRequest) (*DeletePiecesResponse, error) {
out := new(DeletePiecesResponse)
err := c.cc.Invoke(ctx, "/piecestore.Piecestore/DeletePieces", in, out)
if err != nil {
return nil, err
}
return out, nil
}
func (c *drpcPiecestoreClient) Retain(ctx context.Context, in *RetainRequest) (*RetainResponse, error) {
out := new(RetainResponse)
err := c.cc.Invoke(ctx, "/piecestore.Piecestore/Retain", in, out)
@ -968,13 +1045,15 @@ type DRPCPiecestoreServer interface {
Delete(context.Context, *PieceDeleteRequest) (*PieceDeleteResponse, error)
// DeletePiece deletes a piece from a satellite request
DeletePiece(context.Context, *PieceDeletePieceRequest) (*PieceDeletePieceResponse, error)
// DeletePieces deletes a set of pieces on satellite request
DeletePieces(context.Context, *DeletePiecesRequest) (*DeletePiecesResponse, error)
Retain(context.Context, *RetainRequest) (*RetainResponse, error)
RestoreTrash(context.Context, *RestoreTrashRequest) (*RestoreTrashResponse, error)
}
type DRPCPiecestoreDescription struct{}
func (DRPCPiecestoreDescription) NumMethods() int { return 6 }
func (DRPCPiecestoreDescription) NumMethods() int { return 7 }
func (DRPCPiecestoreDescription) Method(n int) (string, drpc.Handler, interface{}, bool) {
switch n {
@ -1013,6 +1092,15 @@ func (DRPCPiecestoreDescription) Method(n int) (string, drpc.Handler, interface{
)
}, DRPCPiecestoreServer.DeletePiece, true
case 4:
return "/piecestore.Piecestore/DeletePieces",
func(srv interface{}, ctx context.Context, in1, in2 interface{}) (drpc.Message, error) {
return srv.(DRPCPiecestoreServer).
DeletePieces(
ctx,
in1.(*DeletePiecesRequest),
)
}, DRPCPiecestoreServer.DeletePieces, true
case 5:
return "/piecestore.Piecestore/Retain",
func(srv interface{}, ctx context.Context, in1, in2 interface{}) (drpc.Message, error) {
return srv.(DRPCPiecestoreServer).
@ -1021,7 +1109,7 @@ func (DRPCPiecestoreDescription) Method(n int) (string, drpc.Handler, interface{
in1.(*RetainRequest),
)
}, DRPCPiecestoreServer.Retain, true
case 5:
case 6:
return "/piecestore.Piecestore/RestoreTrash",
func(srv interface{}, ctx context.Context, in1, in2 interface{}) (drpc.Message, error) {
return srv.(DRPCPiecestoreServer).
@ -1118,6 +1206,22 @@ func (x *drpcPiecestoreDeletePieceStream) SendAndClose(m *PieceDeletePieceRespon
return x.CloseSend()
}
type DRPCPiecestore_DeletePiecesStream interface {
drpc.Stream
SendAndClose(*DeletePiecesResponse) error
}
type drpcPiecestoreDeletePiecesStream struct {
drpc.Stream
}
func (x *drpcPiecestoreDeletePiecesStream) SendAndClose(m *DeletePiecesResponse) error {
if err := x.MsgSend(m); err != nil {
return err
}
return x.CloseSend()
}
type DRPCPiecestore_RetainStream interface {
drpc.Stream
SendAndClose(*RetainResponse) error
@ -1167,6 +1271,8 @@ type PiecestoreClient interface {
Delete(ctx context.Context, in *PieceDeleteRequest, opts ...grpc.CallOption) (*PieceDeleteResponse, error)
// DeletePiece deletes a piece from a satellite request
DeletePiece(ctx context.Context, in *PieceDeletePieceRequest, opts ...grpc.CallOption) (*PieceDeletePieceResponse, error)
// DeletePieces deletes a set of pieces on satellite request
DeletePieces(ctx context.Context, in *DeletePiecesRequest, opts ...grpc.CallOption) (*DeletePiecesResponse, error)
Retain(ctx context.Context, in *RetainRequest, opts ...grpc.CallOption) (*RetainResponse, error)
RestoreTrash(ctx context.Context, in *RestoreTrashRequest, opts ...grpc.CallOption) (*RestoreTrashResponse, error)
}
@ -1254,6 +1360,7 @@ func (c *piecestoreClient) Delete(ctx context.Context, in *PieceDeleteRequest, o
return out, nil
}
// Deprecated: Do not use.
func (c *piecestoreClient) DeletePiece(ctx context.Context, in *PieceDeletePieceRequest, opts ...grpc.CallOption) (*PieceDeletePieceResponse, error) {
out := new(PieceDeletePieceResponse)
err := c.cc.Invoke(ctx, "/piecestore.Piecestore/DeletePiece", in, out, opts...)
@ -1263,6 +1370,15 @@ func (c *piecestoreClient) DeletePiece(ctx context.Context, in *PieceDeletePiece
return out, nil
}
func (c *piecestoreClient) DeletePieces(ctx context.Context, in *DeletePiecesRequest, opts ...grpc.CallOption) (*DeletePiecesResponse, error) {
out := new(DeletePiecesResponse)
err := c.cc.Invoke(ctx, "/piecestore.Piecestore/DeletePieces", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *piecestoreClient) Retain(ctx context.Context, in *RetainRequest, opts ...grpc.CallOption) (*RetainResponse, error) {
out := new(RetainResponse)
err := c.cc.Invoke(ctx, "/piecestore.Piecestore/Retain", in, out, opts...)
@ -1288,6 +1404,8 @@ type PiecestoreServer interface {
Delete(context.Context, *PieceDeleteRequest) (*PieceDeleteResponse, error)
// DeletePiece deletes a piece from a satellite request
DeletePiece(context.Context, *PieceDeletePieceRequest) (*PieceDeletePieceResponse, error)
// DeletePieces deletes a set of pieces on satellite request
DeletePieces(context.Context, *DeletePiecesRequest) (*DeletePiecesResponse, error)
Retain(context.Context, *RetainRequest) (*RetainResponse, error)
RestoreTrash(context.Context, *RestoreTrashRequest) (*RestoreTrashResponse, error)
}
@ -1384,6 +1502,24 @@ func _Piecestore_DeletePiece_Handler(srv interface{}, ctx context.Context, dec f
return interceptor(ctx, in, info, handler)
}
func _Piecestore_DeletePieces_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(DeletePiecesRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(PiecestoreServer).DeletePieces(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/piecestore.Piecestore/DeletePieces",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(PiecestoreServer).DeletePieces(ctx, req.(*DeletePiecesRequest))
}
return interceptor(ctx, in, info, handler)
}
func _Piecestore_Retain_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(RetainRequest)
if err := dec(in); err != nil {
@ -1432,6 +1568,10 @@ var _Piecestore_serviceDesc = grpc.ServiceDesc{
MethodName: "DeletePiece",
Handler: _Piecestore_DeletePiece_Handler,
},
{
MethodName: "DeletePieces",
Handler: _Piecestore_DeletePieces_Handler,
},
{
MethodName: "Retain",
Handler: _Piecestore_Retain_Handler,

View File

@ -17,7 +17,11 @@ service Piecestore {
option deprecated = true;
}
// DeletePiece deletes a piece from a satellite request
rpc DeletePiece(PieceDeletePieceRequest) returns (PieceDeletePieceResponse);
rpc DeletePiece(PieceDeletePieceRequest) returns (PieceDeletePieceResponse) {
option deprecated = true;
}
// DeletePieces deletes a set of pieces on satellite request
rpc DeletePieces(DeletePiecesRequest) returns (DeletePiecesResponse);
rpc Retain(RetainRequest) returns (RetainResponse);
rpc RestoreTrash(RestoreTrashRequest) returns (RestoreTrashResponse) {}
}
@ -97,6 +101,13 @@ message PieceDeletePieceRequest {
message PieceDeletePieceResponse {
}
message DeletePiecesRequest {
repeated bytes piece_ids = 1 [(gogoproto.customtype) = "PieceID", (gogoproto.nullable) = false];
}
message DeletePiecesResponse {
}
message RetainRequest {
google.protobuf.Timestamp creation_date = 1 [(gogoproto.stdtime) = true, (gogoproto.nullable) = false];
bytes filter = 2;

View File

@ -176,9 +176,15 @@ func (mock *piecestoreMock) Download(server pb.Piecestore_DownloadServer) error
func (mock *piecestoreMock) Delete(ctx context.Context, delete *pb.PieceDeleteRequest) (_ *pb.PieceDeleteResponse, err error) {
return nil, nil
}
func (mock *piecestoreMock) DeletePiece(ctx context.Context, delete *pb.PieceDeletePieceRequest) (_ *pb.PieceDeletePieceResponse, err error) {
return nil, nil
}
func (mock *piecestoreMock) DeletePieces(ctx context.Context, delete *pb.DeletePiecesRequest) (_ *pb.DeletePiecesResponse, err error) {
return nil, nil
}
func (mock *piecestoreMock) Retain(ctx context.Context, retain *pb.RetainRequest) (_ *pb.RetainResponse, err error) {
return nil, nil
}

View File

@ -5593,6 +5593,30 @@
{
"name": "PieceDeletePieceResponse"
},
{
"name": "DeletePiecesRequest",
"fields": [
{
"id": 1,
"name": "piece_ids",
"type": "bytes",
"is_repeated": true,
"options": [
{
"name": "(gogoproto.customtype)",
"value": "PieceID"
},
{
"name": "(gogoproto.nullable)",
"value": "false"
}
]
}
]
},
{
"name": "DeletePiecesResponse"
},
{
"name": "RetainRequest",
"fields": [
@ -5705,7 +5729,18 @@
{
"name": "DeletePiece",
"in_type": "PieceDeletePieceRequest",
"out_type": "PieceDeletePieceResponse"
"out_type": "PieceDeletePieceResponse",
"options": [
{
"name": "deprecated",
"value": "true"
}
]
},
{
"name": "DeletePieces",
"in_type": "DeletePiecesRequest",
"out_type": "DeletePiecesResponse"
},
{
"name": "Retain",

View File

@ -139,7 +139,7 @@ var monLiveRequests = mon.TaskNamed("live-request")
// Delete handles deleting a piece on piece store requested by uplink.
//
// DEPRECATED in favor of DeletePiece.
// DEPRECATED in favor of DeletePieces.
func (endpoint *Endpoint) Delete(ctx context.Context, delete *pb.PieceDeleteRequest) (_ *pb.PieceDeleteResponse, err error) {
defer monLiveRequests(&ctx)(&err)
defer mon.Task()(&ctx)(&err)
@ -173,9 +173,47 @@ func (endpoint *Endpoint) Delete(ctx context.Context, delete *pb.PieceDeleteRequ
return &pb.PieceDeleteResponse{}, nil
}
// DeletePieces delete a list of pieces on satellite request.
func (endpoint *Endpoint) DeletePieces(
ctx context.Context, req *pb.DeletePiecesRequest,
) (_ *pb.DeletePiecesResponse, err error) {
defer mon.Task()(&ctx, req.PieceIds)(&err)
peer, err := identity.PeerIdentityFromContext(ctx)
if err != nil {
return nil, rpcstatus.Error(rpcstatus.Unauthenticated, Error.Wrap(err).Error())
}
err = endpoint.trust.VerifySatelliteID(ctx, peer.ID)
if err != nil {
return nil, rpcstatus.Error(rpcstatus.PermissionDenied,
Error.New("%s", "delete pieces called with untrusted ID").Error(),
)
}
for _, pieceID := range req.PieceIds {
err = endpoint.store.Delete(ctx, peer.ID, pieceID)
if err != nil {
// If a piece cannot be deleted, we just log the error.
// No error is returned to the caller.
endpoint.log.Error("delete failed",
zap.Stringer("Satellite ID", peer.ID),
zap.Stringer("Piece ID", pieceID),
zap.Error(Error.Wrap(err)),
)
} else {
endpoint.log.Info("deleted",
zap.Stringer("Satellite ID", peer.ID),
zap.Stringer("Piece ID", pieceID),
)
}
}
return &pb.DeletePiecesResponse{}, nil
}
// DeletePiece handles deleting a piece on piece store requested by satellite.
//
// It doesn't return an error if the piece isn't found by any reason.
// DEPRECATED in favor of DeletePieces.
func (endpoint *Endpoint) DeletePiece(
ctx context.Context, req *pb.PieceDeletePieceRequest,
) (_ *pb.PieceDeletePieceResponse, err error) {
@ -201,17 +239,22 @@ func (endpoint *Endpoint) DeletePiece(
return nil, rpcstatus.Error(rpcstatus.NotFound, "piece not found")
}
endpoint.log.Error("delete piece failed",
endpoint.log.Error("delete failed",
zap.Error(Error.Wrap(err)),
zap.Stringer("Satellite ID", peer.ID),
zap.Stringer("Piece ID", req.PieceId),
)
return nil, rpcstatus.Error(rpcstatus.Internal,
Error.New("%s", "delete piece failed").Error(),
Error.New("%s", "delete failed").Error(),
)
}
endpoint.log.Info("deleted",
zap.Stringer("Satellite ID", peer.ID),
zap.Stringer("Piece ID", req.PieceId),
)
return &pb.PieceDeletePieceResponse{}, nil
}

View File

@ -362,6 +362,96 @@ func TestDelete(t *testing.T) {
})
}
func TestDeletePieces(t *testing.T) {
testplanet.Run(t, testplanet.Config{
SatelliteCount: 1, StorageNodeCount: 1, UplinkCount: 1,
}, func(t *testing.T, ctx *testcontext.Context, planet *testplanet.Planet) {
var (
planetSat = planet.Satellites[0]
planetSN = planet.StorageNodes[0]
)
var client *piecestore.Client
{
dossier, err := planetSat.Overlay.DB.Get(ctx.Context, planetSN.ID())
require.NoError(t, err)
client, err = piecestore.Dial(
ctx.Context, planetSat.Dialer, &dossier.Node, zaptest.NewLogger(t), piecestore.Config{},
)
require.NoError(t, err)
}
t.Run("Ok", func(t *testing.T) {
pieceIDs := []storj.PieceID{{1}, {2}, {3}, {4}}
dataArray := make([][]byte, len(pieceIDs))
for i, pieceID := range pieceIDs {
dataArray[i], _, _ = uploadPiece(t, ctx, pieceID, planetSN, planet.Uplinks[0], planetSat)
}
err := client.DeletePieces(ctx.Context, pieceIDs...)
require.NoError(t, err)
for i, pieceID := range pieceIDs {
_, err = downloadPiece(t, ctx, pieceID, int64(len(dataArray[i])), planetSN, planet.Uplinks[0], planetSat)
require.Error(t, err)
}
require.Condition(t, func() bool {
return strings.Contains(err.Error(), "file does not exist") ||
strings.Contains(err.Error(), "The system cannot find the path specified")
}, "unexpected error message")
})
t.Run("Ok: one piece to delete is missing", func(t *testing.T) {
missingPieceID := storj.PieceID{12}
pieceIDs := []storj.PieceID{{1}, {2}, {3}, {4}}
dataArray := make([][]byte, len(pieceIDs))
for i, pieceID := range pieceIDs {
dataArray[i], _, _ = uploadPiece(t, ctx, pieceID, planetSN, planet.Uplinks[0], planetSat)
}
err := client.DeletePieces(ctx.Context, append(pieceIDs, missingPieceID)...)
require.NoError(t, err)
for i, pieceID := range pieceIDs {
_, err = downloadPiece(t, ctx, pieceID, int64(len(dataArray[i])), planetSN, planet.Uplinks[0], planetSat)
require.Error(t, err)
}
require.Condition(t, func() bool {
return strings.Contains(err.Error(), "file does not exist") ||
strings.Contains(err.Error(), "The system cannot find the path specified")
}, "unexpected error message")
})
t.Run("Ok: no piece deleted", func(t *testing.T) {
pieceID := storj.PieceID{10}
data, _, _ := uploadPiece(t, ctx, pieceID, planetSN, planet.Uplinks[0], planetSat)
err := client.DeletePieces(ctx.Context)
require.NoError(t, err)
downloaded, err := downloadPiece(t, ctx, pieceID, int64(len(data)), planetSN, planet.Uplinks[0], planetSat)
require.NoError(t, err)
require.Equal(t, data, downloaded)
})
t.Run("error: permission denied", func(t *testing.T) {
pieceID := storj.PieceID{11}
data, _, _ := uploadPiece(t, ctx, pieceID, planetSN, planet.Uplinks[0], planetSat)
client, err := planet.Uplinks[0].DialPiecestore(ctx, planetSN)
require.NoError(t, err)
err = client.DeletePieces(ctx.Context, pieceID)
require.Error(t, err)
require.Equal(t, rpcstatus.PermissionDenied, rpcstatus.Code(err))
downloaded, err := downloadPiece(t, ctx, pieceID, int64(len(data)), planetSN, planet.Uplinks[0], planetSat)
require.NoError(t, err)
require.Equal(t, data, downloaded)
})
})
}
func TestDeletePiece(t *testing.T) {
testplanet.Run(t, testplanet.Config{
SatelliteCount: 1, StorageNodeCount: 1, UplinkCount: 1,

View File

@ -62,6 +62,8 @@ func Dial(ctx context.Context, dialer rpc.Dialer, target *pb.Node, log *zap.Logg
}
// Delete uses delete order limit to delete a piece on piece store.
//
// DEPRECATED in favor of DeletePieces.
func (client *Client) Delete(ctx context.Context, limit *pb.OrderLimit, privateKey storj.PiecePrivateKey) (err error) {
defer mon.Task()(&ctx)(&err)
_, err = client.client.Delete(ctx, &pb.PieceDeleteRequest{
@ -71,6 +73,8 @@ func (client *Client) Delete(ctx context.Context, limit *pb.OrderLimit, privateK
}
// DeletePiece deletes a piece.
//
// DEPRECATED in favor of DeletePieces.
func (client *Client) DeletePiece(ctx context.Context, id storj.PieceID) (err error) {
defer mon.Task()(&ctx, id.String())(&err)
_, err = client.client.DeletePiece(ctx, &pb.PieceDeletePieceRequest{
@ -79,6 +83,19 @@ func (client *Client) DeletePiece(ctx context.Context, id storj.PieceID) (err er
return Error.Wrap(err)
}
// DeletePieces deletes a set of pieces.
func (client *Client) DeletePieces(ctx context.Context, ids ...storj.PieceID) (err error) {
defer mon.Task()(&ctx)(&err)
if len(ids) == 0 {
// Avoid RPC calls if no pieces to delete.
return nil
}
_, err = client.client.DeletePieces(ctx, &pb.DeletePiecesRequest{
PieceIds: ids,
})
return Error.Wrap(err)
}
// Retain uses a bloom filter to tell the piece store which pieces to keep.
func (client *Client) Retain(ctx context.Context, req *pb.RetainRequest) (err error) {
defer mon.Task()(&ctx)(&err)