storage/: remove reverse-key-listing feature

We don't use reverse listing in any of our code, outside of tests, and
it is only exposed through libuplink in the
lib/uplink.(*Project).ListBuckets() API. We also don't know of any users
who might have a need for reverse listing through ListBuckets().

Since one of our prospective pointerdb backends can not support
backwards iteration, and because of the above considerations, we are
going to remove the reverse listing feature.

Change-Id: I8d2a1f33d01ee70b79918d584b8c671f57eef2a0
This commit is contained in:
paul cannon 2019-09-25 16:30:41 -05:00 committed by Michal Niewrzal
parent 28a70200d7
commit 0c025fa937
30 changed files with 326 additions and 1081 deletions

View File

@ -91,7 +91,7 @@ func TestDownloadWithSomeNodesOffline(t *testing.T) {
// get a remote segment from pointerdb
pdb := satellite.Metainfo.Service
listResponse, _, err := pdb.List(ctx, "", "", "", true, 0, 0)
listResponse, _, err := pdb.List(ctx, "", "", true, 0, 0)
require.NoError(t, err)
var path string
@ -195,7 +195,7 @@ func TestDownloadFromUnresponsiveNode(t *testing.T) {
// get a remote segment from pointerdb
pdb := planet.Satellites[0].Metainfo.Service
listResponse, _, err := pdb.List(ctx, "", "", "", true, 0, 0)
listResponse, _, err := pdb.List(ctx, "", "", true, 0, 0)
require.NoError(t, err)
var path string

View File

@ -1310,7 +1310,7 @@ type ListSegmentsRequestOld struct {
Bucket []byte `protobuf:"bytes,1,opt,name=bucket,proto3" json:"bucket,omitempty"`
Prefix []byte `protobuf:"bytes,2,opt,name=prefix,proto3" json:"prefix,omitempty"`
StartAfter []byte `protobuf:"bytes,3,opt,name=start_after,json=startAfter,proto3" json:"start_after,omitempty"`
EndBefore []byte `protobuf:"bytes,4,opt,name=end_before,json=endBefore,proto3" json:"end_before,omitempty"`
EndBefore []byte `protobuf:"bytes,4,opt,name=end_before,json=endBefore,proto3" json:"end_before,omitempty"` // Deprecated: Do not use.
Recursive bool `protobuf:"varint,5,opt,name=recursive,proto3" json:"recursive,omitempty"`
Limit int32 `protobuf:"varint,6,opt,name=limit,proto3" json:"limit,omitempty"`
MetaFlags uint32 `protobuf:"fixed32,7,opt,name=meta_flags,json=metaFlags,proto3" json:"meta_flags,omitempty"`
@ -1371,6 +1371,7 @@ func (m *ListSegmentsRequestOld) GetStartAfter() []byte {
return nil
}
// Deprecated: Do not use.
func (m *ListSegmentsRequestOld) GetEndBefore() []byte {
if m != nil {
return m.EndBefore
@ -5133,239 +5134,239 @@ func init() {
func init() { proto.RegisterFile("metainfo.proto", fileDescriptor_631e2f30a93cd64e) }
var fileDescriptor_631e2f30a93cd64e = []byte{
// 3709 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xd4, 0x5b, 0x4b, 0x6c, 0x1c, 0x59,
0xd5, 0x76, 0xbf, 0xbb, 0x4f, 0xb7, 0xdd, 0xdd, 0xd7, 0x8e, 0xdd, 0x29, 0xc7, 0x71, 0x52, 0x49,
0x66, 0xfc, 0xeb, 0x9f, 0x71, 0x46, 0x9e, 0xff, 0x47, 0x83, 0x92, 0x61, 0xb0, 0xd3, 0x9e, 0x74,
0x4f, 0x62, 0xc7, 0x53, 0x4e, 0x26, 0x21, 0x0c, 0xb4, 0xca, 0x5d, 0xd7, 0x76, 0x91, 0xee, 0xae,
0xa6, 0xaa, 0x7a, 0xc6, 0x19, 0x56, 0x48, 0x23, 0x21, 0x04, 0x42, 0x23, 0xd6, 0x88, 0xd5, 0xec,
0x58, 0xc1, 0x0e, 0x09, 0xd8, 0x02, 0x12, 0x1a, 0xa4, 0x11, 0x62, 0xc1, 0x62, 0x60, 0xc5, 0x0e,
0x36, 0xec, 0x40, 0x48, 0xe8, 0xbe, 0xea, 0x5d, 0xfd, 0xf0, 0x23, 0x61, 0x76, 0x55, 0xe7, 0x9e,
0x7b, 0xea, 0xde, 0xf3, 0xf8, 0xce, 0xa9, 0x73, 0xab, 0x60, 0xa6, 0x8b, 0x6d, 0x55, 0xef, 0xed,
0x1b, 0xab, 0x7d, 0xd3, 0xb0, 0x0d, 0x94, 0x17, 0xf7, 0x52, 0x05, 0xf7, 0xda, 0xe6, 0xd3, 0xbe,
0xad, 0x1b, 0x3d, 0x36, 0x26, 0xc1, 0x81, 0x71, 0xc0, 0xf9, 0xa4, 0xe5, 0x03, 0xc3, 0x38, 0xe8,
0xe0, 0xeb, 0xf4, 0x6e, 0x6f, 0xb0, 0x7f, 0xdd, 0xd6, 0xbb, 0xd8, 0xb2, 0xd5, 0x6e, 0x5f, 0x30,
0xf7, 0x0c, 0x0d, 0xf3, 0xeb, 0x72, 0xdf, 0xd0, 0x7b, 0x36, 0x36, 0xb5, 0x3d, 0x4e, 0x28, 0x19,
0xa6, 0x86, 0x4d, 0x8b, 0xdd, 0xc9, 0x2b, 0x30, 0xad, 0xe0, 0x6f, 0x0e, 0xb0, 0x65, 0x37, 0xb0,
0xaa, 0x61, 0x13, 0x2d, 0x40, 0x4e, 0xed, 0xeb, 0xad, 0x27, 0xf8, 0x69, 0x2d, 0x71, 0x29, 0xb1,
0x52, 0x52, 0xb2, 0x6a, 0x5f, 0xbf, 0x83, 0x9f, 0xca, 0x3f, 0x49, 0x41, 0x76, 0x63, 0xd0, 0x7e,
0x82, 0x6d, 0x84, 0x20, 0xdd, 0x53, 0xbb, 0x98, 0x33, 0xd0, 0x6b, 0xf4, 0x1a, 0x14, 0xfb, 0xaa,
0x7d, 0xd8, 0x6a, 0xeb, 0xfd, 0x43, 0x6c, 0xd6, 0x92, 0x97, 0x12, 0x2b, 0x33, 0x6b, 0x0b, 0xab,
0x9e, 0x8d, 0xdc, 0xa2, 0x23, 0xbb, 0x03, 0xdd, 0xc6, 0x0a, 0x10, 0x5e, 0x46, 0x40, 0xb7, 0x00,
0xda, 0x26, 0x56, 0x6d, 0xac, 0xb5, 0x54, 0xbb, 0x96, 0xba, 0x94, 0x58, 0x29, 0xae, 0x49, 0xab,
0x6c, 0x8f, 0xab, 0x62, 0x8f, 0xab, 0xf7, 0xc5, 0x1e, 0x37, 0xf2, 0xbf, 0xf9, 0x6c, 0x79, 0xea,
0xa3, 0x3f, 0x2f, 0x27, 0x94, 0x02, 0x9f, 0xb7, 0x6e, 0xa3, 0x57, 0x60, 0x4e, 0xc3, 0xfb, 0xea,
0xa0, 0x63, 0xb7, 0x2c, 0x7c, 0xd0, 0xc5, 0x3d, 0xbb, 0x65, 0xe9, 0x1f, 0xe0, 0x5a, 0xfa, 0x52,
0x62, 0x25, 0xa5, 0x20, 0x3e, 0xb6, 0xcb, 0x86, 0x76, 0xf5, 0x0f, 0x30, 0x7a, 0x08, 0xe7, 0xc5,
0x0c, 0x13, 0x6b, 0x83, 0x9e, 0xa6, 0xf6, 0xda, 0x4f, 0x5b, 0x56, 0xfb, 0x10, 0x77, 0x71, 0x2d,
0x43, 0x57, 0xb1, 0xb8, 0xea, 0x2a, 0x4f, 0x71, 0x78, 0x76, 0x29, 0x8b, 0xb2, 0xc0, 0x67, 0x07,
0x07, 0x90, 0x06, 0x4b, 0x42, 0xb0, 0xbb, 0xfb, 0x56, 0x5f, 0x35, 0xd5, 0x2e, 0xb6, 0xb1, 0x69,
0xd5, 0xb2, 0x54, 0xf8, 0x25, 0xaf, 0x6e, 0x36, 0x9d, 0xcb, 0x1d, 0x87, 0x4f, 0x59, 0xe4, 0x62,
0xa2, 0x06, 0xd1, 0x12, 0x40, 0x5f, 0x35, 0xed, 0x1e, 0x36, 0x5b, 0xba, 0x56, 0xcb, 0x51, 0x4b,
0x14, 0x38, 0xa5, 0xa9, 0xc9, 0x3a, 0xcc, 0x30, 0x63, 0xdd, 0xd5, 0x2d, 0xbb, 0x69, 0xe3, 0x6e,
0xa4, 0xd1, 0xfc, 0xaa, 0x4f, 0x1e, 0x4b, 0xf5, 0xf2, 0xc7, 0x29, 0x98, 0x65, 0xcf, 0xba, 0x45,
0x69, 0xdc, 0x9f, 0xd0, 0x75, 0xc8, 0x1e, 0x52, 0x9f, 0xaa, 0x95, 0xa9, 0xe0, 0x85, 0x55, 0xc7,
0xdf, 0x7d, 0x2e, 0xa7, 0x70, 0xb6, 0x53, 0x76, 0xab, 0x38, 0x8f, 0x48, 0x1d, 0xcf, 0x23, 0xd2,
0x67, 0xe9, 0x11, 0x99, 0xd3, 0xf7, 0x88, 0x6c, 0xd0, 0x23, 0xbe, 0x0c, 0x73, 0x7e, 0x2b, 0x59,
0x7d, 0xa3, 0x67, 0x61, 0xb4, 0x02, 0xd9, 0x3d, 0x4a, 0xa7, 0x7a, 0x2f, 0xae, 0x55, 0x5c, 0x33,
0x31, 0x7e, 0x85, 0x8f, 0xcb, 0x0f, 0xa1, 0xc2, 0x28, 0xb7, 0xb1, 0x7d, 0x9a, 0x46, 0x96, 0x5f,
0x87, 0xaa, 0x47, 0xf0, 0xc4, 0xeb, 0x7a, 0x2c, 0xfc, 0xaf, 0x8e, 0x3b, 0xf8, 0x74, 0xfd, 0x4f,
0x9e, 0x17, 0x5a, 0x13, 0xb2, 0xd9, 0xea, 0xe4, 0x8f, 0x12, 0x62, 0xcd, 0x24, 0xc0, 0x8e, 0xfd,
0xc8, 0x79, 0xc8, 0xb6, 0x07, 0xa6, 0x65, 0x98, 0x02, 0x6c, 0xd9, 0x1d, 0x9a, 0x83, 0x4c, 0x47,
0xef, 0xea, 0x2c, 0x26, 0x33, 0x0a, 0xbb, 0x41, 0x17, 0xa0, 0xa0, 0xe9, 0x26, 0x6e, 0x13, 0xc3,
0x53, 0x3f, 0xce, 0x28, 0x2e, 0x41, 0x7e, 0x04, 0xc8, 0xbb, 0x22, 0xae, 0xc6, 0x55, 0xc8, 0xe8,
0x36, 0xee, 0x5a, 0xb5, 0xc4, 0xa5, 0xd4, 0x4a, 0x71, 0xad, 0x16, 0xd4, 0xa2, 0xc0, 0x07, 0x85,
0xb1, 0x11, 0x25, 0x74, 0x0d, 0x13, 0xd3, 0x07, 0xe7, 0x15, 0x7a, 0x2d, 0x7f, 0x3b, 0x01, 0x8b,
0x8c, 0x7b, 0x17, 0xdb, 0xeb, 0xb6, 0x6d, 0xea, 0x7b, 0x03, 0xf2, 0xc8, 0x53, 0x8d, 0x74, 0xbf,
0xfb, 0x26, 0x83, 0xee, 0x7b, 0x11, 0x2e, 0x44, 0x2f, 0x81, 0x1b, 0xe4, 0xc3, 0x04, 0xcc, 0xae,
0x6b, 0x9a, 0x89, 0x2d, 0x0b, 0x6b, 0xf7, 0x48, 0x8a, 0xbb, 0x4b, 0x75, 0xb6, 0x22, 0x34, 0xc9,
0xbc, 0x08, 0xad, 0xf2, 0xf4, 0xe7, 0xb2, 0x08, 0xed, 0xde, 0x82, 0x39, 0xcb, 0x36, 0x4c, 0xf5,
0x00, 0xb7, 0x48, 0xfe, 0x6c, 0xa9, 0x4c, 0x1a, 0x87, 0xc5, 0xea, 0x2a, 0x4d, 0xaa, 0xdb, 0x86,
0x86, 0xf9, 0x63, 0x14, 0xc4, 0xd9, 0x3d, 0x34, 0xf9, 0xf7, 0x49, 0x98, 0xe7, 0x98, 0xf2, 0xd0,
0xd4, 0x1d, 0x67, 0xbc, 0xd7, 0xd1, 0x8e, 0xe5, 0x1c, 0x9e, 0x08, 0x28, 0x09, 0x7f, 0x27, 0xda,
0x23, 0x38, 0xc7, 0x75, 0x44, 0xaf, 0x51, 0x0d, 0x72, 0x1c, 0xe5, 0x38, 0xc0, 0x89, 0x5b, 0x74,
0x03, 0xc0, 0x45, 0xb3, 0x71, 0x60, 0xcc, 0xc3, 0x8e, 0x6e, 0x80, 0xd4, 0x55, 0x8f, 0x04, 0x6a,
0x61, 0xcd, 0x0f, 0xa5, 0x19, 0xfa, 0xa4, 0x85, 0xae, 0x7a, 0xb4, 0x29, 0x18, 0xbc, 0x78, 0x5a,
0x07, 0xc0, 0x47, 0x7d, 0xdd, 0x54, 0xa9, 0xbf, 0x66, 0x27, 0xc8, 0x2e, 0x9e, 0x79, 0xf2, 0xa7,
0x09, 0x58, 0xf0, 0x6b, 0x94, 0x59, 0x9c, 0xa8, 0xb4, 0x01, 0x15, 0x55, 0xd8, 0xbc, 0x45, 0xad,
0x28, 0xfc, 0x7c, 0xc9, 0x55, 0x6e, 0x84, 0x57, 0x28, 0x65, 0x67, 0x1a, 0xbd, 0xb7, 0xd0, 0xab,
0x30, 0x6d, 0x1a, 0x86, 0xdd, 0xea, 0xeb, 0xb8, 0x8d, 0x1d, 0x07, 0xdc, 0x28, 0x93, 0x25, 0xfd,
0xe9, 0xb3, 0xe5, 0xdc, 0x0e, 0xa1, 0x37, 0xeb, 0x4a, 0x91, 0x70, 0xb1, 0x1b, 0x8d, 0x26, 0x27,
0x53, 0x7f, 0x4f, 0xb5, 0x31, 0xad, 0x97, 0x52, 0x74, 0xca, 0x02, 0x9f, 0x52, 0xa6, 0x5c, 0x3b,
0x6c, 0xfc, 0x0e, 0x7e, 0xaa, 0x40, 0xdf, 0xb9, 0x96, 0xff, 0xe5, 0x6e, 0xea, 0x96, 0xd1, 0x25,
0x2b, 0x7a, 0xee, 0x7e, 0xf2, 0x12, 0xe4, 0xb8, 0x53, 0x70, 0x27, 0x41, 0x1e, 0x27, 0xd9, 0x61,
0x57, 0x8a, 0x60, 0x41, 0x37, 0xa0, 0x6c, 0x98, 0xfa, 0x81, 0xde, 0x53, 0x3b, 0x42, 0xf1, 0x19,
0xaa, 0xf8, 0xa8, 0x00, 0x9b, 0x11, 0xac, 0x4c, 0xd9, 0x72, 0x03, 0x6a, 0x81, 0xcd, 0xbb, 0x26,
0xf5, 0x2c, 0x23, 0x31, 0x72, 0x19, 0xf2, 0x0f, 0x13, 0x70, 0x9e, 0x8b, 0xaa, 0x1b, 0xef, 0xf7,
0x3a, 0x86, 0xaa, 0x3d, 0x77, 0x4d, 0xca, 0x9f, 0x24, 0x40, 0x0a, 0x2d, 0xea, 0x2c, 0x9c, 0xd6,
0xa3, 0xab, 0xe4, 0x68, 0x93, 0x1d, 0xdf, 0x5b, 0x7f, 0x90, 0x80, 0x73, 0x7c, 0x43, 0xcd, 0xde,
0xbe, 0xf1, 0xfc, 0x35, 0xfc, 0xa6, 0x03, 0xb2, 0x6c, 0x3d, 0x91, 0xee, 0x33, 0x5a, 0x25, 0x24,
0x8b, 0x8b, 0x30, 0xf4, 0xd5, 0x0e, 0xcf, 0x71, 0x6b, 0x3f, 0x4e, 0x38, 0xc1, 0xe1, 0x2f, 0x39,
0x4e, 0xd7, 0x75, 0x02, 0xce, 0x90, 0x1c, 0xdf, 0x19, 0xbe, 0x9f, 0x84, 0x79, 0x52, 0x34, 0xf0,
0x45, 0x5a, 0x67, 0xa1, 0xb2, 0x79, 0xc8, 0xf6, 0x4d, 0xbc, 0xaf, 0x1f, 0x71, 0xa5, 0xf1, 0x3b,
0xb4, 0x0c, 0x45, 0xcb, 0x56, 0x4d, 0xbb, 0xa5, 0xee, 0x13, 0x0b, 0x53, 0x17, 0x56, 0x80, 0x92,
0xd6, 0x09, 0x85, 0x14, 0x11, 0xb8, 0xa7, 0xb5, 0xf6, 0xf0, 0x3e, 0xa9, 0x61, 0xd2, 0xac, 0x88,
0xc0, 0x3d, 0x6d, 0x83, 0x12, 0x48, 0x01, 0x65, 0x62, 0x52, 0x62, 0xe9, 0xef, 0xb1, 0xec, 0x95,
0x57, 0x5c, 0x82, 0x5b, 0x74, 0x65, 0xbd, 0x45, 0xd7, 0x12, 0x00, 0xd9, 0x45, 0x6b, 0xbf, 0xa3,
0x1e, 0x58, 0xf4, 0x45, 0x2b, 0xa7, 0x14, 0x08, 0xe5, 0x4d, 0x42, 0xa0, 0xe9, 0xc9, 0xaf, 0x0e,
0xd7, 0x5c, 0x37, 0xfd, 0xb5, 0xd7, 0x0b, 0xae, 0x3a, 0x62, 0x66, 0xac, 0x8e, 0xa8, 0xc4, 0x24,
0x0c, 0x69, 0xf1, 0x32, 0x47, 0x7d, 0x2a, 0xe1, 0xf1, 0xa9, 0xc9, 0xd0, 0x60, 0x11, 0x0a, 0xba,
0xd5, 0xe2, 0x5a, 0x4e, 0xd1, 0x47, 0xe4, 0x75, 0x6b, 0x87, 0xde, 0xcb, 0xdf, 0xa3, 0x4e, 0x18,
0x51, 0xea, 0x1d, 0xcb, 0xca, 0xcb, 0x50, 0x64, 0x76, 0x6d, 0x79, 0x8a, 0x3e, 0x60, 0xa4, 0xed,
0x31, 0x4a, 0xbf, 0x45, 0x82, 0xf1, 0x51, 0x45, 0xdf, 0xbd, 0x8e, 0x26, 0x6f, 0x02, 0xda, 0x31,
0x8d, 0x6f, 0xe0, 0xb6, 0x17, 0x9a, 0x26, 0x5e, 0xa3, 0xfc, 0x1a, 0xcc, 0xfa, 0xc4, 0xf0, 0xea,
0xf9, 0x32, 0x94, 0xfa, 0x8c, 0xdc, 0xb2, 0xd4, 0x8e, 0x70, 0xd3, 0x22, 0xa7, 0xed, 0xaa, 0x1d,
0x5b, 0xfe, 0x6e, 0x0e, 0xb2, 0xf7, 0xf6, 0xc8, 0x6d, 0xac, 0x3b, 0x5f, 0x83, 0x19, 0xb7, 0x82,
0xf2, 0x60, 0xc1, 0xb4, 0x43, 0xdd, 0xe1, 0xa0, 0xf0, 0x1e, 0x36, 0x2d, 0xb7, 0xb8, 0x17, 0xb7,
0x64, 0x3b, 0x96, 0xad, 0xda, 0x03, 0x8b, 0xba, 0xf4, 0x8c, 0x77, 0x3b, 0xec, 0xd1, 0xab, 0xbb,
0x74, 0x58, 0xe1, 0x6c, 0xe8, 0x65, 0x28, 0x58, 0xb6, 0x89, 0xd5, 0x2e, 0x51, 0x68, 0x86, 0x06,
0x77, 0x85, 0x07, 0x77, 0x7e, 0x97, 0x0e, 0x34, 0xeb, 0x4a, 0x9e, 0xb1, 0x34, 0xb5, 0x40, 0x1f,
0x20, 0x7b, 0xbc, 0x16, 0xcc, 0x3a, 0x79, 0x26, 0x79, 0x3a, 0x91, 0x91, 0x9b, 0x40, 0x46, 0x9e,
0x4d, 0x5b, 0x27, 0x25, 0x38, 0xab, 0xfc, 0x30, 0x95, 0x91, 0x9f, 0x64, 0x1d, 0x7c, 0xde, 0xba,
0x8d, 0x6e, 0x43, 0xcd, 0xd5, 0x36, 0xd1, 0x93, 0xa6, 0xda, 0x6a, 0xab, 0x67, 0xf4, 0xda, 0xb8,
0x56, 0xa0, 0xaa, 0x98, 0xe6, 0xaa, 0xc8, 0x6c, 0x13, 0xa2, 0x32, 0xef, 0xb0, 0x6f, 0x71, 0x6e,
0x4a, 0x47, 0x2f, 0x03, 0x0a, 0x0b, 0xaa, 0x01, 0x35, 0x5d, 0x35, 0x34, 0x07, 0xbd, 0x04, 0x68,
0x5f, 0x3f, 0x0a, 0xd6, 0xc8, 0x45, 0x0a, 0xef, 0x15, 0x3a, 0xe2, 0x2d, 0x8e, 0x1b, 0x50, 0x0d,
0x37, 0x19, 0x4a, 0xa3, 0xab, 0xf3, 0x8a, 0x19, 0xec, 0x2e, 0x3c, 0x80, 0x73, 0xd1, 0x5d, 0x85,
0xe9, 0x31, 0xbb, 0x0a, 0x73, 0x38, 0xa6, 0x9d, 0x60, 0x1b, 0xb6, 0xda, 0x61, 0xdb, 0x98, 0xa1,
0xdb, 0x28, 0x50, 0x0a, 0x5d, 0xff, 0x32, 0x14, 0xf5, 0x5e, 0x47, 0xef, 0x61, 0x36, 0x5e, 0xa6,
0xe3, 0xc0, 0x48, 0x82, 0xc1, 0xc4, 0x5d, 0xc3, 0xe6, 0x0c, 0x15, 0xc6, 0xc0, 0x48, 0x84, 0x41,
0x7e, 0x1b, 0xb2, 0xcc, 0x6b, 0x51, 0x11, 0x72, 0xcd, 0xed, 0x77, 0xd6, 0xef, 0x36, 0xeb, 0x95,
0x29, 0x34, 0x0d, 0x85, 0x07, 0x3b, 0x77, 0xef, 0xad, 0xd7, 0x9b, 0xdb, 0xb7, 0x2b, 0x09, 0x34,
0x03, 0x70, 0xeb, 0xde, 0xd6, 0x56, 0xf3, 0xfe, 0x7d, 0x72, 0x9f, 0x24, 0xc3, 0xfc, 0x7e, 0xb3,
0x5e, 0x49, 0xa1, 0x12, 0xe4, 0xeb, 0x9b, 0x77, 0x37, 0xe9, 0x60, 0x5a, 0xfe, 0x30, 0x05, 0x88,
0x05, 0xc4, 0x06, 0x3e, 0xd0, 0x7b, 0x27, 0x79, 0x2d, 0x3f, 0x9b, 0x40, 0xf6, 0x3b, 0x78, 0xfa,
0x78, 0x0e, 0x1e, 0xe9, 0x3a, 0xb9, 0x53, 0x75, 0x9d, 0xfc, 0x49, 0x5c, 0x47, 0xfe, 0x55, 0x12,
0x66, 0x7d, 0x66, 0xe0, 0x68, 0x7a, 0x66, 0x6a, 0xf5, 0xc1, 0x5d, 0x7a, 0x24, 0xdc, 0x45, 0x2a,
0x30, 0x73, 0xaa, 0x0a, 0xcc, 0x9e, 0x48, 0x81, 0x7f, 0x4b, 0x08, 0x05, 0xfa, 0xde, 0x0e, 0x27,
0x77, 0x64, 0x9f, 0x62, 0x12, 0x23, 0x15, 0x33, 0x0c, 0x3a, 0x93, 0x27, 0x87, 0xce, 0x54, 0x0c,
0x74, 0xca, 0xf3, 0x30, 0xe7, 0xdf, 0x2e, 0x6f, 0xea, 0xfc, 0x28, 0x01, 0x15, 0x36, 0x70, 0x92,
0x96, 0xe3, 0x59, 0xb9, 0x9d, 0xfc, 0x3a, 0x54, 0x3d, 0xab, 0x73, 0xfb, 0x96, 0x06, 0x25, 0x86,
0xfb, 0x96, 0x8c, 0x59, 0xe1, 0xe3, 0xf2, 0x4f, 0x93, 0x62, 0xfe, 0x49, 0x7b, 0x88, 0x91, 0xdb,
0xfb, 0x1f, 0xa8, 0x78, 0xb6, 0xe7, 0x2d, 0xa7, 0xcb, 0xee, 0x06, 0x59, 0x5d, 0xed, 0x63, 0xe5,
0x0d, 0xc9, 0x54, 0x80, 0xf5, 0x16, 0xeb, 0x4c, 0xfa, 0x4a, 0xe8, 0x74, 0x6c, 0x09, 0x9d, 0xf1,
0x96, 0xd0, 0x4d, 0x28, 0xb3, 0x2d, 0xb7, 0xf4, 0x5e, 0xbb, 0x33, 0xd0, 0xb0, 0x1b, 0x1f, 0x01,
0xdd, 0x88, 0x6e, 0x64, 0x93, 0xf3, 0x29, 0x33, 0x6c, 0xa2, 0xb8, 0x97, 0x1f, 0x09, 0x80, 0x1f,
0xb3, 0xc9, 0xe9, 0x17, 0x3b, 0xac, 0xc9, 0xf9, 0xeb, 0x14, 0xcc, 0xf8, 0xb9, 0x23, 0x1c, 0x24,
0x31, 0xc2, 0x41, 0x92, 0x71, 0x75, 0x5b, 0x6a, 0xbc, 0xba, 0xcd, 0x5f, 0x88, 0xa5, 0x4f, 0xa1,
0x10, 0xcb, 0x9c, 0x42, 0x21, 0x96, 0x3d, 0xfd, 0x42, 0x2c, 0x77, 0x72, 0x34, 0xc9, 0xc7, 0xa1,
0xc9, 0xff, 0xc1, 0x7c, 0xb4, 0x37, 0x21, 0x09, 0xf2, 0xce, 0xf4, 0x04, 0x7b, 0xe7, 0x11, 0xf7,
0xf2, 0xc7, 0x09, 0xa8, 0x79, 0x92, 0xd6, 0x09, 0xcf, 0x12, 0xce, 0x0c, 0x73, 0xde, 0x82, 0xf3,
0x11, 0xab, 0xe4, 0x71, 0x30, 0x19, 0xdc, 0xcb, 0xdf, 0x12, 0xb2, 0xde, 0xd4, 0x7b, 0xba, 0x75,
0x78, 0xc2, 0x2d, 0x4f, 0xf8, 0xf0, 0x0b, 0x20, 0x45, 0x3d, 0x9c, 0x23, 0xff, 0xdf, 0x93, 0x50,
0xdc, 0x55, 0x6d, 0x31, 0xef, 0xec, 0x4a, 0x87, 0x13, 0xb5, 0xc7, 0x9b, 0x30, 0x4d, 0xc3, 0x8e,
0x24, 0x7f, 0x4d, 0xb5, 0xf1, 0x44, 0xd1, 0x56, 0x12, 0x53, 0xeb, 0xaa, 0x8d, 0xd1, 0x16, 0x94,
0xdd, 0xa6, 0x37, 0x13, 0x36, 0x49, 0xd8, 0xcd, 0xb8, 0x93, 0xa9, 0xb8, 0xeb, 0x30, 0x6b, 0xa9,
0x36, 0xee, 0x74, 0x74, 0x5a, 0x80, 0x1f, 0xf4, 0x54, 0x7b, 0x60, 0xf2, 0xf7, 0x1f, 0x05, 0x39,
0x43, 0xbb, 0x62, 0x44, 0xfe, 0x4b, 0x12, 0x72, 0xfc, 0xfd, 0x64, 0xd2, 0xaa, 0xe1, 0xff, 0x21,
0xdf, 0x37, 0x2c, 0xdd, 0x16, 0x00, 0x58, 0x5c, 0x3b, 0xef, 0xfa, 0x0a, 0x97, 0xb9, 0xc3, 0x19,
0x14, 0x87, 0x15, 0xbd, 0x0e, 0xb3, 0xae, 0xe9, 0x9e, 0xe0, 0xa7, 0x1c, 0x19, 0x52, 0x51, 0xc8,
0xe0, 0x46, 0xf9, 0x1d, 0xfc, 0x94, 0x81, 0xc2, 0x15, 0x98, 0xf6, 0x4d, 0xe7, 0xdd, 0x9e, 0x92,
0x97, 0x13, 0xad, 0xc2, 0x2c, 0x79, 0xfb, 0xf0, 0x1c, 0x60, 0xd0, 0xd8, 0x67, 0x07, 0x17, 0x55,
0x32, 0xe4, 0x9c, 0x5c, 0xd4, 0xc9, 0x3b, 0xdc, 0x9a, 0x53, 0xcf, 0x61, 0xad, 0xc5, 0xdf, 0x6f,
0xe8, 0x0c, 0x76, 0x9c, 0xea, 0x2e, 0xb8, 0x49, 0xc7, 0xe8, 0x9c, 0x17, 0x21, 0x4b, 0x4f, 0x0d,
0xac, 0x5a, 0x8e, 0x66, 0x9f, 0xb2, 0xbb, 0x79, 0xda, 0x47, 0x53, 0xf8, 0xb0, 0xdc, 0x80, 0x0c,
0x25, 0xa0, 0x45, 0x28, 0xb0, 0x73, 0x86, 0xde, 0xa0, 0x4b, 0xf5, 0x9b, 0x51, 0xf2, 0x94, 0xb0,
0x3d, 0xe8, 0x22, 0x19, 0xd2, 0x3d, 0x43, 0x13, 0xf5, 0xd6, 0x0c, 0xd7, 0x43, 0x76, 0xdb, 0xd0,
0x70, 0xb3, 0xae, 0xd0, 0x31, 0xb9, 0x01, 0xe5, 0x80, 0x5e, 0xc9, 0xeb, 0x56, 0x5f, 0x35, 0x6d,
0x22, 0x72, 0x8f, 0xf7, 0xce, 0x33, 0x0a, 0x6d, 0xab, 0x6c, 0x53, 0x0a, 0x49, 0xcd, 0x7a, 0x4f,
0xc3, 0x47, 0xe2, 0x48, 0x91, 0xde, 0xc8, 0x7f, 0x48, 0xc0, 0x2c, 0x17, 0x75, 0xb2, 0x57, 0xa6,
0x67, 0xe3, 0x33, 0x2f, 0x40, 0xb9, 0xab, 0x1e, 0xb5, 0xe8, 0x11, 0x03, 0x6b, 0x80, 0xf2, 0xfe,
0xe9, 0x74, 0x57, 0x3d, 0x72, 0xfb, 0x9d, 0xf2, 0xef, 0x12, 0x30, 0xe7, 0xdf, 0x16, 0x47, 0xc8,
0x57, 0x00, 0xc4, 0xeb, 0xb9, 0xb3, 0xce, 0x2a, 0x5f, 0x67, 0x41, 0xf4, 0x94, 0xeb, 0x4a, 0x81,
0x33, 0x35, 0xa3, 0x7b, 0xae, 0xc9, 0xd3, 0xe8, 0xb9, 0x4e, 0xd0, 0x80, 0xff, 0x63, 0xd2, 0xd9,
0xce, 0x09, 0x5f, 0x08, 0x26, 0xdf, 0x7f, 0x4c, 0x98, 0x26, 0x8f, 0x1b, 0xa6, 0xa9, 0xf1, 0xc3,
0x34, 0x1d, 0x17, 0xa6, 0xb7, 0x61, 0x7a, 0xd0, 0xef, 0x18, 0xaa, 0xd6, 0x32, 0xb1, 0x35, 0xe8,
0xd8, 0xfc, 0xec, 0x49, 0x0e, 0xbb, 0x10, 0x51, 0xea, 0x83, 0x3e, 0x3f, 0x82, 0x19, 0x74, 0x6c,
0xa5, 0x34, 0xf0, 0xdc, 0xc9, 0xdf, 0x71, 0xbb, 0xed, 0x21, 0xd6, 0xe1, 0x61, 0xfa, 0x22, 0xe4,
0xe8, 0x29, 0xb1, 0x73, 0x54, 0x18, 0x8c, 0xd4, 0x2c, 0x19, 0x6e, 0x6a, 0xe8, 0x1a, 0xa4, 0x0f,
0x55, 0xeb, 0x90, 0x7f, 0xd8, 0x54, 0x15, 0xc7, 0x63, 0xf4, 0x71, 0x0d, 0xd5, 0x3a, 0x54, 0xe8,
0xb0, 0xfc, 0xef, 0x24, 0x94, 0x48, 0xc2, 0x13, 0x26, 0x40, 0x6b, 0xc1, 0x80, 0x2a, 0xae, 0x9d,
0xf3, 0xec, 0xcf, 0xcd, 0x8d, 0x9e, 0xa8, 0x0a, 0x80, 0x40, 0x32, 0x1e, 0x04, 0x52, 0x1e, 0x10,
0x08, 0x1f, 0x7e, 0x66, 0xc6, 0x38, 0xfc, 0x7c, 0x1b, 0xce, 0x39, 0x27, 0x80, 0x9e, 0x78, 0x24,
0xa5, 0xfd, 0x18, 0xc1, 0x31, 0x2b, 0xe6, 0xba, 0x34, 0x2b, 0x9c, 0x4e, 0x73, 0xc7, 0x4e, 0xa7,
0x31, 0xf9, 0x2f, 0x1f, 0x9b, 0xff, 0xea, 0xce, 0x11, 0x97, 0xff, 0x1d, 0x14, 0xfd, 0x2f, 0x54,
0xad, 0x41, 0xbb, 0x8d, 0x2d, 0x6b, 0x7f, 0xd0, 0x69, 0x71, 0xa4, 0x67, 0xde, 0x50, 0x71, 0x07,
0x76, 0x18, 0xc4, 0xff, 0x36, 0xe9, 0xf8, 0xd3, 0x96, 0xfa, 0x04, 0xb3, 0x2c, 0xf1, 0x5f, 0x8e,
0xa9, 0xcf, 0x22, 0x0f, 0xc7, 0xe6, 0xd5, 0x4c, 0x6c, 0x5e, 0x65, 0x6d, 0xff, 0x90, 0x2a, 0x79,
0x7d, 0xf8, 0x33, 0xf7, 0xe0, 0xf7, 0x34, 0xca, 0xf5, 0x67, 0xa2, 0x69, 0xf9, 0x53, 0xf7, 0x60,
0x38, 0xaa, 0x7a, 0xff, 0x7c, 0xe6, 0xa6, 0x5f, 0xba, 0x9b, 0x3a, 0x95, 0xd7, 0x88, 0xc9, 0xb5,
0x70, 0x13, 0x72, 0x2c, 0x0d, 0x88, 0xcd, 0xc7, 0xe4, 0x01, 0x47, 0xdd, 0x24, 0x0f, 0x88, 0x29,
0xa1, 0x14, 0xe0, 0xe5, 0x7a, 0xb6, 0x29, 0x60, 0x09, 0x16, 0x23, 0x15, 0xc9, 0x5d, 0xfe, 0x93,
0x04, 0x20, 0x3e, 0x7e, 0xa2, 0x7e, 0xd1, 0x84, 0xbe, 0xbe, 0x01, 0x65, 0xd6, 0x11, 0x6a, 0x8d,
0xef, 0xf2, 0x33, 0x6c, 0x86, 0x53, 0x9c, 0x3a, 0x6d, 0xa1, 0x94, 0xa7, 0x2d, 0x24, 0x3f, 0x76,
0x4a, 0x4f, 0x5f, 0x33, 0xe7, 0xba, 0xbf, 0x99, 0x13, 0x7e, 0xcc, 0x38, 0xdd, 0x1c, 0xb7, 0x42,
0x76, 0xba, 0x39, 0xde, 0xa0, 0x4d, 0x8c, 0x1f, 0xb4, 0xbf, 0x48, 0x38, 0x1f, 0x1b, 0x04, 0x3e,
0x31, 0xf9, 0x3c, 0xa8, 0x5e, 0xfe, 0x79, 0xca, 0xfd, 0xc4, 0x21, 0xf0, 0x31, 0xca, 0xe7, 0x13,
0x70, 0xe2, 0x73, 0x49, 0x3a, 0xfe, 0x1d, 0xed, 0x32, 0x94, 0x22, 0xbe, 0x5c, 0x2b, 0x5a, 0x9e,
0x03, 0xb9, 0x98, 0x34, 0x98, 0x3d, 0x6e, 0x1a, 0xcc, 0x45, 0xa4, 0xc1, 0x97, 0x21, 0xdd, 0xc3,
0x47, 0xe2, 0x64, 0x73, 0x88, 0x15, 0x29, 0x9b, 0xfc, 0x3e, 0x94, 0x36, 0x54, 0xbb, 0x7d, 0x78,
0x6c, 0x7f, 0xfb, 0x02, 0xe4, 0x4d, 0x36, 0x20, 0xa2, 0x49, 0xf2, 0x7c, 0xff, 0xe9, 0x11, 0x4d,
0xc3, 0xc9, 0xe1, 0x95, 0xff, 0x0a, 0x50, 0x09, 0x0e, 0xa3, 0x3a, 0x4c, 0xf3, 0x63, 0x7c, 0xd6,
0x6a, 0xe4, 0x41, 0xb4, 0x14, 0xfc, 0xa2, 0xd4, 0xf7, 0x15, 0x78, 0x63, 0x4a, 0x29, 0xed, 0x79,
0xc8, 0xe8, 0x06, 0xf0, 0x93, 0xff, 0xd6, 0x01, 0x76, 0x3f, 0x39, 0x0f, 0x88, 0x70, 0xbb, 0xfd,
0x8d, 0x29, 0xa5, 0xb0, 0x27, 0x68, 0x9e, 0x25, 0x68, 0x14, 0x1b, 0x39, 0xa2, 0x86, 0x96, 0xe0,
0x4b, 0x41, 0xee, 0x12, 0x18, 0x19, 0x7d, 0xc9, 0xf9, 0x1e, 0xa1, 0xa3, 0x5b, 0xb6, 0xd3, 0xf3,
0x89, 0xf8, 0x30, 0xd6, 0x95, 0xc0, 0x17, 0x4d, 0x88, 0xe8, 0x6b, 0x30, 0xcf, 0xe7, 0x5b, 0xd8,
0x6e, 0xa9, 0xee, 0x77, 0x09, 0xbc, 0xfd, 0x73, 0x2d, 0x28, 0x2a, 0xf2, 0x53, 0x8a, 0xc6, 0x94,
0x32, 0xb7, 0x17, 0x31, 0x8c, 0xd6, 0xa1, 0xc4, 0xbb, 0xe5, 0x7b, 0xa4, 0x48, 0xe0, 0x6d, 0xa0,
0x0b, 0xc1, 0xd6, 0xb1, 0xf7, 0x75, 0xbd, 0x31, 0xa5, 0x14, 0x0d, 0x97, 0x4a, 0xf4, 0xc4, 0x45,
0xb4, 0x69, 0x31, 0xcb, 0x0b, 0xe9, 0xa5, 0xa0, 0x0c, 0xdf, 0xcb, 0x24, 0xd1, 0x93, 0xe1, 0x21,
0x13, 0x53, 0x71, 0x29, 0xc4, 0x54, 0xf9, 0xa0, 0xa9, 0x82, 0x07, 0x33, 0xc4, 0x54, 0x86, 0xa0,
0x11, 0x25, 0xf3, 0xc9, 0x54, 0xc9, 0x85, 0xa0, 0x92, 0x43, 0x07, 0x1f, 0x44, 0xc9, 0x86, 0x43,
0x44, 0xf7, 0x61, 0xd6, 0xab, 0x05, 0x61, 0x70, 0xa0, 0x72, 0xe4, 0x48, 0x65, 0x04, 0xad, 0x5e,
0x35, 0x82, 0x63, 0xe8, 0x21, 0xcc, 0x71, 0xa9, 0xfb, 0x34, 0xc5, 0x0a, 0xb1, 0x45, 0x2a, 0xf6,
0x4a, 0x50, 0x6c, 0x44, 0x41, 0xd3, 0x98, 0x52, 0x90, 0x11, 0x1a, 0x24, 0x1a, 0x17, 0x00, 0xc3,
0xac, 0x56, 0x0a, 0x6a, 0x3c, 0xa2, 0xcb, 0x42, 0x34, 0x6e, 0x79, 0xc8, 0xe8, 0x36, 0xcc, 0x08,
0x29, 0xdc, 0x70, 0xec, 0x0c, 0xff, 0x62, 0x48, 0x4c, 0xd0, 0x72, 0xe2, 0xe9, 0xdc, 0x74, 0xf7,
0x61, 0x56, 0x08, 0xea, 0xaa, 0x4f, 0x30, 0x87, 0x49, 0x7a, 0x8a, 0x1f, 0x55, 0x1e, 0x85, 0xde,
0x55, 0x88, 0xf6, 0xac, 0xe0, 0x18, 0xd1, 0x9e, 0x6f, 0x93, 0x42, 0x7b, 0xe5, 0xa0, 0xf6, 0x62,
0x2b, 0x73, 0xa2, 0x3d, 0x2b, 0x34, 0x88, 0x1e, 0xc3, 0x39, 0x21, 0xd8, 0x6f, 0x97, 0x0a, 0x95,
0x7c, 0x35, 0x24, 0x39, 0xda, 0x30, 0x62, 0xcf, 0x3e, 0xcb, 0xac, 0xbb, 0xd0, 0x4f, 0x3d, 0xb1,
0x1a, 0x0c, 0xa7, 0x70, 0x4d, 0x45, 0xc2, 0xc9, 0x72, 0xa9, 0x68, 0x0b, 0x2a, 0x42, 0x84, 0xc6,
0x73, 0x68, 0x0d, 0x05, 0x0f, 0xb0, 0xa2, 0x6b, 0x84, 0xc6, 0x94, 0x52, 0xb6, 0xfc, 0x23, 0x1b,
0x05, 0xc8, 0xf1, 0x51, 0xf9, 0x2d, 0x98, 0xe6, 0x38, 0xcb, 0x53, 0xf2, 0x17, 0xa1, 0x60, 0xf2,
0x6b, 0x01, 0xd9, 0x8b, 0x21, 0xc8, 0x66, 0xe3, 0x14, 0xb3, 0x5d, 0x6e, 0xf9, 0x9f, 0x00, 0xd5,
0x10, 0x03, 0xda, 0x8c, 0x46, 0xed, 0x8b, 0x71, 0xa8, 0xcd, 0xa6, 0x86, 0x60, 0xfb, 0x66, 0x04,
0x6c, 0x2f, 0x46, 0xc2, 0xb6, 0x23, 0xc0, 0x83, 0xdb, 0x9b, 0xd1, 0xb8, 0x7d, 0x31, 0x0e, 0xb7,
0x83, 0x8b, 0xe0, 0xa6, 0x7c, 0x23, 0x0a, 0xb8, 0x2f, 0x44, 0x03, 0xb7, 0x23, 0xc2, 0x8b, 0xdc,
0x5f, 0x1f, 0x81, 0xdc, 0x2f, 0x8c, 0x42, 0x6e, 0x47, 0x6a, 0x34, 0x74, 0x6f, 0x44, 0x42, 0xf7,
0x52, 0x0c, 0x74, 0x3b, 0xc2, 0x7c, 0xd8, 0xbd, 0x19, 0x8d, 0xdd, 0x17, 0xe3, 0xb0, 0xdb, 0xd5,
0x95, 0x0f, 0xbc, 0x6f, 0x46, 0x80, 0xf7, 0x62, 0x24, 0x78, 0xbb, 0x06, 0x73, 0xd1, 0xfb, 0x8d,
0x28, 0xf4, 0xbe, 0x10, 0x8d, 0xde, 0xae, 0xa6, 0x3d, 0xf0, 0xfd, 0x60, 0x18, 0x7c, 0x5f, 0x19,
0x0a, 0xdf, 0x8e, 0xbc, 0x08, 0xfc, 0x7e, 0x34, 0x14, 0xbf, 0xaf, 0x0e, 0xc7, 0x6f, 0x47, 0x70,
0x14, 0x80, 0x6f, 0x46, 0x03, 0xf8, 0xc5, 0x38, 0x00, 0x77, 0xd5, 0xee, 0x43, 0xf0, 0x46, 0x0c,
0x82, 0x2f, 0xc7, 0x22, 0xb8, 0x23, 0x28, 0x00, 0xe1, 0x0f, 0x86, 0x41, 0xf8, 0x95, 0xa1, 0x10,
0xee, 0x6a, 0x30, 0x8c, 0xe1, 0x8f, 0x86, 0x62, 0xf8, 0xd5, 0xe1, 0x18, 0xee, 0x6a, 0x30, 0x02,
0xc4, 0xbf, 0x3a, 0x1c, 0xc4, 0xaf, 0x8d, 0x00, 0x71, 0x47, 0x76, 0x24, 0x8a, 0x6f, 0x44, 0xa2,
0xf8, 0x52, 0x0c, 0x8a, 0xbb, 0x91, 0xe5, 0x85, 0xf1, 0xed, 0x58, 0x18, 0xbf, 0x3c, 0x04, 0xc6,
0x1d, 0x59, 0x21, 0x1c, 0x07, 0xc8, 0x8b, 0xe1, 0xb5, 0x7f, 0x54, 0x21, 0xbf, 0xc5, 0x65, 0xa0,
0x2d, 0x28, 0x31, 0xd8, 0xe4, 0xff, 0xcb, 0x0e, 0x2f, 0x91, 0xa5, 0x11, 0x58, 0x8c, 0xea, 0x50,
0xb8, 0x8d, 0x6d, 0x2e, 0x6b, 0x48, 0xad, 0x2c, 0x0d, 0x03, 0x64, 0xb2, 0x28, 0xa6, 0xcb, 0xb8,
0x45, 0xf9, 0xb2, 0xa9, 0x34, 0x02, 0x9b, 0x51, 0x03, 0x8a, 0x44, 0xa9, 0x6c, 0xcc, 0x42, 0xc3,
0xca, 0x67, 0x69, 0x28, 0x44, 0x23, 0x0c, 0x73, 0xbb, 0x62, 0x7b, 0x5e, 0x30, 0x1d, 0xaf, 0x8c,
0x96, 0xc6, 0xc4, 0x6c, 0xf4, 0x16, 0x14, 0xa9, 0xb7, 0xf2, 0x6f, 0x75, 0x87, 0xd6, 0xd3, 0xd2,
0x70, 0xc8, 0xa6, 0x06, 0xa6, 0x51, 0xca, 0x85, 0x0d, 0x2f, 0xac, 0xa5, 0x11, 0xd8, 0xcd, 0x0d,
0xcc, 0x65, 0x0d, 0xa9, 0xb0, 0xa5, 0x61, 0x00, 0x2e, 0x2c, 0xc2, 0x06, 0x7c, 0x16, 0x09, 0xd5,
0xda, 0xd2, 0x50, 0x28, 0x47, 0xef, 0x42, 0xd5, 0x13, 0xd8, 0x7c, 0x5d, 0x63, 0xd4, 0xdc, 0xd2,
0x38, 0xc0, 0x8e, 0x5a, 0x80, 0xbc, 0xa1, 0xcd, 0xc5, 0x8f, 0x53, 0x7b, 0x4b, 0x63, 0x01, 0x3c,
0xb1, 0x0e, 0x7d, 0xae, 0x38, 0xce, 0x1e, 0x5e, 0x84, 0x4b, 0x23, 0x20, 0x1e, 0xed, 0xc0, 0x34,
0xb3, 0x97, 0x90, 0x37, 0xa2, 0x1a, 0x97, 0x46, 0x61, 0x3d, 0xd1, 0xaf, 0x8b, 0xc8, 0x42, 0xea,
0x18, 0x55, 0xb9, 0x34, 0x0e, 0xec, 0x13, 0xfd, 0x7a, 0xd4, 0x2e, 0xc4, 0x8f, 0x53, 0x9d, 0x4b,
0x63, 0xc1, 0x3f, 0xda, 0x83, 0x59, 0xaf, 0xde, 0xc5, 0x13, 0xc6, 0xaa, 0xd2, 0xa5, 0xf1, 0xd2,
0x00, 0xba, 0x03, 0x25, 0xef, 0x3f, 0x12, 0x68, 0x68, 0xbd, 0x2e, 0x0d, 0xcf, 0x03, 0xe8, 0x1d,
0x28, 0x0b, 0xd0, 0x16, 0x8b, 0x1d, 0x59, 0xb8, 0x4b, 0xa3, 0x73, 0x02, 0x7a, 0x0d, 0x32, 0xb4,
0xe0, 0x46, 0xf3, 0xd1, 0x5d, 0x15, 0x69, 0x21, 0xa6, 0x74, 0x47, 0x0f, 0xa1, 0xc2, 0x40, 0x9e,
0x8b, 0xbe, 0xd7, 0xd1, 0x22, 0x96, 0x14, 0xf8, 0x83, 0x34, 0x62, 0x49, 0xa1, 0x3f, 0x22, 0xbf,
0x02, 0x15, 0x9f, 0xb3, 0x12, 0xda, 0xe5, 0xe1, 0xfe, 0x4a, 0x24, 0xcb, 0x23, 0x5c, 0x96, 0x88,
0xd9, 0x85, 0x19, 0xcf, 0x4f, 0x57, 0x84, 0x12, 0x76, 0x74, 0xff, 0xef, 0x61, 0xd2, 0xa5, 0x18,
0x06, 0x57, 0x68, 0x0b, 0x50, 0xc0, 0x34, 0x84, 0x7a, 0x65, 0x94, 0x75, 0x88, 0xf0, 0xab, 0x23,
0x0d, 0xc4, 0x15, 0xe2, 0x73, 0xd3, 0x68, 0x85, 0x04, 0xff, 0xfe, 0x8a, 0x50, 0x48, 0xf8, 0x6f,
0xac, 0x77, 0xa0, 0xec, 0xf5, 0xd1, 0x80, 0x0d, 0xa3, 0xff, 0x91, 0xf2, 0xda, 0x30, 0xee, 0xb7,
0xa1, 0x77, 0xa1, 0xea, 0xcf, 0x61, 0x84, 0xe8, 0x5b, 0x50, 0xf4, 0x9f, 0x39, 0x7e, 0x78, 0x88,
0xf9, 0x61, 0x86, 0xe4, 0x41, 0xcf, 0x9f, 0x2e, 0xde, 0xc0, 0x0a, 0xff, 0x47, 0xe3, 0x0d, 0xac,
0x88, 0xdf, 0x63, 0x36, 0xd2, 0x8f, 0x93, 0xfd, 0xbd, 0xbd, 0x2c, 0x3d, 0x97, 0x7d, 0xf5, 0x3f,
0x01, 0x00, 0x00, 0xff, 0xff, 0x48, 0x9e, 0xe0, 0x05, 0xd0, 0x44, 0x00, 0x00,
// 3712 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xd4, 0x5b, 0x5d, 0x6c, 0x1c, 0x57,
0xf5, 0xf7, 0xec, 0xf7, 0x9e, 0x5d, 0x7b, 0xd7, 0xd7, 0x8e, 0xbd, 0x19, 0xc7, 0x71, 0x32, 0x49,
0x5a, 0xff, 0xf5, 0x6f, 0x9d, 0xca, 0x05, 0x54, 0x94, 0x94, 0x62, 0x67, 0xdd, 0x78, 0x9b, 0xd8,
0x71, 0xc7, 0x49, 0x13, 0x42, 0x61, 0x35, 0xde, 0xb9, 0xb6, 0x87, 0xec, 0xee, 0x2c, 0x33, 0xb3,
0xad, 0x53, 0x9e, 0x90, 0x2a, 0x21, 0x84, 0x84, 0x2a, 0x9e, 0x11, 0x4f, 0x7d, 0xe3, 0x09, 0xde,
0x90, 0x80, 0x57, 0x40, 0x42, 0x45, 0xaa, 0x10, 0x0f, 0x3c, 0x14, 0x9e, 0x78, 0x83, 0x17, 0xde,
0x40, 0x48, 0xe8, 0x7e, 0xcd, 0xf7, 0xec, 0x87, 0x3f, 0x12, 0xfa, 0x36, 0x73, 0xee, 0xb9, 0x67,
0xee, 0x3d, 0x1f, 0xbf, 0x73, 0xe6, 0xdc, 0x19, 0x98, 0xea, 0x60, 0x47, 0x33, 0xba, 0xfb, 0xe6,
0x4a, 0xcf, 0x32, 0x1d, 0x13, 0x15, 0xc4, 0xbd, 0x5c, 0xc5, 0xdd, 0x96, 0xf5, 0xb4, 0xe7, 0x18,
0x66, 0x97, 0x8d, 0xc9, 0x70, 0x60, 0x1e, 0x70, 0x3e, 0x79, 0xe9, 0xc0, 0x34, 0x0f, 0xda, 0xf8,
0x3a, 0xbd, 0xdb, 0xeb, 0xef, 0x5f, 0x77, 0x8c, 0x0e, 0xb6, 0x1d, 0xad, 0xd3, 0x13, 0xcc, 0x5d,
0x53, 0xc7, 0xfc, 0xba, 0xd2, 0x33, 0x8d, 0xae, 0x83, 0x2d, 0x7d, 0x8f, 0x13, 0xca, 0xa6, 0xa5,
0x63, 0xcb, 0x66, 0x77, 0xca, 0x32, 0x4c, 0xaa, 0xf8, 0xdb, 0x7d, 0x6c, 0x3b, 0x9b, 0x58, 0xd3,
0xb1, 0x85, 0xe6, 0x21, 0xaf, 0xf5, 0x8c, 0xe6, 0x13, 0xfc, 0xb4, 0x26, 0x5d, 0x92, 0x96, 0xcb,
0x6a, 0x4e, 0xeb, 0x19, 0x77, 0xf0, 0x53, 0xe5, 0xa7, 0x69, 0xc8, 0xad, 0xf7, 0x5b, 0x4f, 0xb0,
0x83, 0x10, 0x64, 0xba, 0x5a, 0x07, 0x73, 0x06, 0x7a, 0x8d, 0x5e, 0x83, 0x52, 0x4f, 0x73, 0x0e,
0x9b, 0x2d, 0xa3, 0x77, 0x88, 0xad, 0x5a, 0xea, 0x92, 0xb4, 0x3c, 0xb5, 0x3a, 0xbf, 0xe2, 0xdb,
0xc8, 0x2d, 0x3a, 0xb2, 0xdb, 0x37, 0x1c, 0xac, 0x02, 0xe1, 0x65, 0x04, 0x74, 0x0b, 0xa0, 0x65,
0x61, 0xcd, 0xc1, 0x7a, 0x53, 0x73, 0x6a, 0xe9, 0x4b, 0xd2, 0x72, 0x69, 0x55, 0x5e, 0x61, 0x7b,
0x5c, 0x11, 0x7b, 0x5c, 0xb9, 0x2f, 0xf6, 0xb8, 0x5e, 0xf8, 0xed, 0x67, 0x4b, 0x13, 0x1f, 0xfd,
0x65, 0x49, 0x52, 0x8b, 0x7c, 0xde, 0x9a, 0x83, 0x5e, 0x81, 0x59, 0x1d, 0xef, 0x6b, 0xfd, 0xb6,
0xd3, 0xb4, 0xf1, 0x41, 0x07, 0x77, 0x9d, 0xa6, 0x6d, 0x7c, 0x80, 0x6b, 0x99, 0x4b, 0xd2, 0x72,
0x5a, 0x45, 0x7c, 0x6c, 0x97, 0x0d, 0xed, 0x1a, 0x1f, 0x60, 0xf4, 0x10, 0xce, 0x8b, 0x19, 0x16,
0xd6, 0xfb, 0x5d, 0x5d, 0xeb, 0xb6, 0x9e, 0x36, 0xed, 0xd6, 0x21, 0xee, 0xe0, 0x5a, 0x96, 0xae,
0x62, 0x61, 0xc5, 0x53, 0x9e, 0xea, 0xf2, 0xec, 0x52, 0x16, 0x75, 0x9e, 0xcf, 0x0e, 0x0f, 0x20,
0x1d, 0x16, 0x85, 0x60, 0x6f, 0xf7, 0xcd, 0x9e, 0x66, 0x69, 0x1d, 0xec, 0x60, 0xcb, 0xae, 0xe5,
0xa8, 0xf0, 0x4b, 0x7e, 0xdd, 0x6c, 0xb8, 0x97, 0x3b, 0x2e, 0x9f, 0xba, 0xc0, 0xc5, 0xc4, 0x0d,
0xa2, 0x45, 0x80, 0x9e, 0x66, 0x39, 0x5d, 0x6c, 0x35, 0x0d, 0xbd, 0x96, 0xa7, 0x96, 0x28, 0x72,
0x4a, 0x43, 0x57, 0x0c, 0x98, 0x62, 0xc6, 0xba, 0x6b, 0xd8, 0x4e, 0xc3, 0xc1, 0x9d, 0x58, 0xa3,
0x05, 0x55, 0x9f, 0x3a, 0x96, 0xea, 0x95, 0x8f, 0xd3, 0x30, 0xc3, 0x9e, 0x75, 0x8b, 0xd2, 0xb8,
0x3f, 0xa1, 0xeb, 0x90, 0x3b, 0xa4, 0x3e, 0x55, 0xab, 0x50, 0xc1, 0xf3, 0x2b, 0xae, 0xbf, 0x07,
0x5c, 0x4e, 0xe5, 0x6c, 0xa7, 0xec, 0x56, 0x49, 0x1e, 0x91, 0x3e, 0x9e, 0x47, 0x64, 0xce, 0xd2,
0x23, 0xb2, 0xa7, 0xef, 0x11, 0xb9, 0xb0, 0x47, 0x7c, 0x15, 0x66, 0x83, 0x56, 0xb2, 0x7b, 0x66,
0xd7, 0xc6, 0x68, 0x19, 0x72, 0x7b, 0x94, 0x4e, 0xf5, 0x5e, 0x5a, 0xad, 0x7a, 0x66, 0x62, 0xfc,
0x2a, 0x1f, 0x57, 0x1e, 0x42, 0x95, 0x51, 0x6e, 0x63, 0xe7, 0x34, 0x8d, 0xac, 0xbc, 0x0e, 0xd3,
0x3e, 0xc1, 0x63, 0xaf, 0xeb, 0xb1, 0xf0, 0xbf, 0x3a, 0x6e, 0xe3, 0xd3, 0xf5, 0x3f, 0x65, 0x4e,
0x68, 0x4d, 0xc8, 0x66, 0xab, 0x53, 0x3e, 0x92, 0xc4, 0x9a, 0x49, 0x80, 0x1d, 0xfb, 0x91, 0x73,
0x90, 0x6b, 0xf5, 0x2d, 0xdb, 0xb4, 0x04, 0xd8, 0xb2, 0x3b, 0x34, 0x0b, 0xd9, 0xb6, 0xd1, 0x31,
0x58, 0x4c, 0x66, 0x55, 0x76, 0x83, 0x2e, 0x40, 0x51, 0x37, 0x2c, 0xdc, 0x22, 0x86, 0xa7, 0x7e,
0x9c, 0x55, 0x3d, 0x82, 0xf2, 0x08, 0x90, 0x7f, 0x45, 0x5c, 0x8d, 0x2b, 0x90, 0x35, 0x1c, 0xdc,
0xb1, 0x6b, 0xd2, 0xa5, 0xf4, 0x72, 0x69, 0xb5, 0x16, 0xd6, 0xa2, 0xc0, 0x07, 0x95, 0xb1, 0x11,
0x25, 0x74, 0x4c, 0x0b, 0xd3, 0x07, 0x17, 0x54, 0x7a, 0xad, 0x7c, 0x57, 0x82, 0x05, 0xc6, 0xbd,
0x8b, 0x9d, 0x35, 0xc7, 0xb1, 0x8c, 0xbd, 0x3e, 0x79, 0xe4, 0xa9, 0x46, 0x7a, 0xd0, 0x7d, 0x53,
0x61, 0xf7, 0xbd, 0x08, 0x17, 0xe2, 0x97, 0xc0, 0x0d, 0xf2, 0xa1, 0x04, 0x33, 0x6b, 0xba, 0x6e,
0x61, 0xdb, 0xc6, 0xfa, 0x3d, 0x92, 0xe2, 0xee, 0x52, 0x9d, 0x2d, 0x0b, 0x4d, 0x32, 0x2f, 0x42,
0x2b, 0x3c, 0xfd, 0x79, 0x2c, 0x42, 0xbb, 0xb7, 0x60, 0xd6, 0x76, 0x4c, 0x4b, 0x3b, 0xc0, 0x4d,
0x92, 0x3f, 0x9b, 0x1a, 0x93, 0xc6, 0x61, 0x71, 0x7a, 0x85, 0x26, 0xd5, 0x6d, 0x53, 0xc7, 0xfc,
0x31, 0x2a, 0xe2, 0xec, 0x3e, 0x9a, 0xf2, 0x87, 0x14, 0xcc, 0x71, 0x4c, 0x79, 0x68, 0x19, 0xae,
0x33, 0xde, 0x6b, 0xeb, 0xc7, 0x72, 0x0e, 0x5f, 0x04, 0x94, 0x85, 0xbf, 0x13, 0xed, 0x11, 0x9c,
0xe3, 0x3a, 0xa2, 0xd7, 0xa8, 0x06, 0x79, 0x8e, 0x72, 0x1c, 0xe0, 0xc4, 0x2d, 0xba, 0x01, 0xe0,
0xa1, 0xd9, 0x28, 0x30, 0xe6, 0x63, 0x47, 0x37, 0x40, 0xee, 0x68, 0x47, 0x02, 0xb5, 0xb0, 0x1e,
0x84, 0xd2, 0x2c, 0x7d, 0xd2, 0x7c, 0x47, 0x3b, 0xda, 0x10, 0x0c, 0x7e, 0x3c, 0xad, 0x03, 0xe0,
0xa3, 0x9e, 0x61, 0x69, 0xd4, 0x5f, 0x73, 0x63, 0x64, 0x17, 0xdf, 0x3c, 0xe5, 0x53, 0x09, 0xe6,
0x83, 0x1a, 0x65, 0x16, 0x27, 0x2a, 0xdd, 0x84, 0xaa, 0x26, 0x6c, 0xde, 0xa4, 0x56, 0x14, 0x7e,
0xbe, 0xe8, 0x29, 0x37, 0xc6, 0x2b, 0xd4, 0x8a, 0x3b, 0x8d, 0xde, 0xdb, 0xe8, 0x55, 0x98, 0xb4,
0x4c, 0xd3, 0x69, 0xf6, 0x0c, 0xdc, 0xc2, 0xae, 0x03, 0xae, 0x57, 0xc8, 0x92, 0xfe, 0xfc, 0xd9,
0x52, 0x7e, 0x87, 0xd0, 0x1b, 0x75, 0xb5, 0x44, 0xb8, 0xd8, 0x8d, 0x4e, 0x93, 0x93, 0x65, 0xbc,
0xa7, 0x39, 0x98, 0xd6, 0x4b, 0x69, 0x3a, 0x65, 0x9e, 0x4f, 0xa9, 0x50, 0xae, 0x1d, 0x36, 0x7e,
0x07, 0x3f, 0x55, 0xa1, 0xe7, 0x5e, 0x2b, 0xff, 0xf6, 0x36, 0x75, 0xcb, 0xec, 0x90, 0x15, 0x3d,
0x77, 0x3f, 0x79, 0x09, 0xf2, 0xdc, 0x29, 0xb8, 0x93, 0x20, 0x9f, 0x93, 0xec, 0xb0, 0x2b, 0x55,
0xb0, 0xa0, 0x1b, 0x50, 0x31, 0x2d, 0xe3, 0xc0, 0xe8, 0x6a, 0x6d, 0xa1, 0xf8, 0x2c, 0x55, 0x7c,
0x5c, 0x80, 0x4d, 0x09, 0x56, 0xa6, 0x6c, 0x65, 0x13, 0x6a, 0xa1, 0xcd, 0x7b, 0x26, 0xf5, 0x2d,
0x43, 0x1a, 0xba, 0x0c, 0xe5, 0x47, 0x12, 0x9c, 0xe7, 0xa2, 0xea, 0xe6, 0xfb, 0xdd, 0xb6, 0xa9,
0xe9, 0xcf, 0x5d, 0x93, 0xca, 0x27, 0x12, 0xc8, 0x91, 0x45, 0x9d, 0x85, 0xd3, 0xfa, 0x74, 0x95,
0x1a, 0x6e, 0xb2, 0xe3, 0x7b, 0xeb, 0x0f, 0x25, 0x38, 0xc7, 0x37, 0xd4, 0xe8, 0xee, 0x9b, 0xcf,
0x5f, 0xc3, 0x6f, 0xba, 0x20, 0xcb, 0xd6, 0x13, 0xeb, 0x3e, 0xc3, 0x55, 0x42, 0xb2, 0xb8, 0x08,
0xc3, 0x40, 0xed, 0xf0, 0x1c, 0xb7, 0xf6, 0x13, 0xc9, 0x0d, 0x8e, 0x60, 0xc9, 0x71, 0xba, 0xae,
0x13, 0x72, 0x86, 0xd4, 0xe8, 0xce, 0xf0, 0x51, 0x0a, 0xe6, 0x48, 0xd1, 0xc0, 0x17, 0x69, 0x9f,
0x85, 0xca, 0xe6, 0x20, 0xd7, 0xb3, 0xf0, 0xbe, 0x71, 0xc4, 0x95, 0xc6, 0xef, 0xd0, 0x12, 0x94,
0x6c, 0x47, 0xb3, 0x9c, 0xa6, 0xb6, 0x4f, 0x2c, 0x4c, 0x5d, 0x58, 0x05, 0x4a, 0x5a, 0x23, 0x14,
0x74, 0x19, 0x00, 0x77, 0xf5, 0xe6, 0x1e, 0xde, 0x27, 0x35, 0x4c, 0x86, 0xee, 0x2a, 0x55, 0x93,
0xd4, 0x22, 0xee, 0xea, 0xeb, 0x94, 0x48, 0x8a, 0x28, 0x0b, 0x93, 0x32, 0xcb, 0x78, 0x8f, 0x65,
0xb0, 0x82, 0xea, 0x11, 0xbc, 0xc2, 0x2b, 0xe7, 0x2f, 0xbc, 0x16, 0x01, 0xc8, 0x4e, 0x9a, 0xfb,
0x6d, 0xed, 0xc0, 0xa6, 0x2f, 0x5b, 0x79, 0xb5, 0x48, 0x28, 0x6f, 0x12, 0x02, 0x4d, 0x51, 0x41,
0x95, 0x78, 0x26, 0xbb, 0x19, 0xac, 0xbf, 0x5e, 0xf0, 0x54, 0x92, 0x30, 0x63, 0x65, 0x48, 0x35,
0x26, 0x63, 0xc8, 0x88, 0x17, 0x3a, 0xea, 0x57, 0x92, 0xcf, 0xaf, 0xc6, 0x43, 0x84, 0x05, 0x28,
0x1a, 0x76, 0x93, 0x6b, 0x3a, 0x4d, 0x1f, 0x51, 0x30, 0xec, 0x1d, 0x7a, 0xaf, 0xfc, 0x80, 0x3a,
0x62, 0x4c, 0xb9, 0x77, 0x2c, 0x4b, 0x2f, 0x41, 0x89, 0xd9, 0xb6, 0xe9, 0x2b, 0xfc, 0x80, 0x91,
0xb6, 0x47, 0x28, 0xff, 0x16, 0x08, 0xce, 0xc7, 0x15, 0x7e, 0xf7, 0xda, 0xba, 0xb2, 0x01, 0x68,
0xc7, 0x32, 0xbf, 0x85, 0x5b, 0x7e, 0x78, 0x1a, 0x7b, 0x8d, 0xca, 0x6b, 0x30, 0x13, 0x10, 0xc3,
0x2b, 0xe8, 0xcb, 0x50, 0xee, 0x31, 0x72, 0xd3, 0xd6, 0xda, 0xc2, 0x55, 0x4b, 0x9c, 0xb6, 0xab,
0xb5, 0x1d, 0xe5, 0xfb, 0x79, 0xc8, 0xdd, 0xdb, 0x23, 0xb7, 0x89, 0x2e, 0x7d, 0x0d, 0xa6, 0xbc,
0x2a, 0xca, 0x87, 0x07, 0x93, 0x2e, 0x75, 0x87, 0x03, 0xc3, 0x7b, 0xd8, 0xb2, 0xbd, 0x02, 0x5f,
0xdc, 0x92, 0xed, 0xd8, 0x8e, 0xe6, 0xf4, 0x6d, 0xea, 0xd6, 0x53, 0xfe, 0xed, 0xb0, 0x47, 0xaf,
0xec, 0xd2, 0x61, 0x95, 0xb3, 0xa1, 0x97, 0xa1, 0x68, 0x3b, 0x16, 0xd6, 0x3a, 0x44, 0xa1, 0x59,
0x1a, 0x0a, 0x55, 0x1e, 0xe0, 0x85, 0x5d, 0x3a, 0xd0, 0xa8, 0xab, 0x05, 0xc6, 0xd2, 0xd0, 0x43,
0xbd, 0x80, 0xdc, 0xf1, 0xda, 0x30, 0x6b, 0xe4, 0x99, 0xe4, 0xe9, 0x44, 0x46, 0x7e, 0x0c, 0x19,
0x05, 0x36, 0x6d, 0x8d, 0x94, 0xe1, 0xac, 0xfa, 0xc3, 0x54, 0x46, 0x61, 0x9c, 0x75, 0xf0, 0x79,
0x6b, 0x0e, 0xba, 0x0d, 0x35, 0x4f, 0xdb, 0x44, 0x4f, 0xba, 0xe6, 0x68, 0xcd, 0xae, 0xd9, 0x6d,
0xe1, 0x5a, 0x91, 0xaa, 0x62, 0x92, 0xab, 0x22, 0xbb, 0x4d, 0x88, 0xea, 0x9c, 0xcb, 0xbe, 0xc5,
0xb9, 0x29, 0x1d, 0xbd, 0x0c, 0x28, 0x2a, 0xa8, 0x06, 0xd4, 0x74, 0xd3, 0x91, 0x39, 0xe8, 0x25,
0x40, 0xfb, 0xc6, 0x51, 0xb8, 0x4e, 0x2e, 0x51, 0x88, 0xaf, 0xd2, 0x11, 0x7f, 0x81, 0xbc, 0x09,
0xd3, 0xd1, 0x46, 0x43, 0x79, 0x78, 0x85, 0x5e, 0xb5, 0xc2, 0x1d, 0x86, 0x07, 0x70, 0x2e, 0xbe,
0xb3, 0x30, 0x39, 0x62, 0x67, 0x61, 0x16, 0x27, 0xb4, 0x14, 0x1c, 0xd3, 0xd1, 0xda, 0x6c, 0x1b,
0x53, 0x74, 0x1b, 0x45, 0x4a, 0xa1, 0xeb, 0x5f, 0x82, 0x92, 0xd1, 0x6d, 0x1b, 0x5d, 0xcc, 0xc6,
0x2b, 0x74, 0x1c, 0x18, 0x49, 0x30, 0x58, 0xb8, 0x63, 0x3a, 0x9c, 0xa1, 0xca, 0x18, 0x18, 0x89,
0x30, 0x28, 0x6f, 0x43, 0x8e, 0x79, 0x2d, 0x2a, 0x41, 0xbe, 0xb1, 0xfd, 0xce, 0xda, 0xdd, 0x46,
0xbd, 0x3a, 0x81, 0x26, 0xa1, 0xf8, 0x60, 0xe7, 0xee, 0xbd, 0xb5, 0x7a, 0x63, 0xfb, 0x76, 0x55,
0x42, 0x53, 0x00, 0xb7, 0xee, 0x6d, 0x6d, 0x35, 0xee, 0xdf, 0x27, 0xf7, 0x29, 0x32, 0xcc, 0xef,
0x37, 0xea, 0xd5, 0x34, 0x2a, 0x43, 0xa1, 0xbe, 0x71, 0x77, 0x83, 0x0e, 0x66, 0x94, 0x0f, 0xd3,
0x80, 0x58, 0x40, 0xac, 0xe3, 0x03, 0xa3, 0x7b, 0x92, 0x57, 0xf3, 0xb3, 0x09, 0xe4, 0xa0, 0x83,
0x67, 0x8e, 0xe7, 0xe0, 0xb1, 0xae, 0x93, 0x3f, 0x55, 0xd7, 0x29, 0x9c, 0xc4, 0x75, 0x94, 0x5f,
0xa7, 0x60, 0x26, 0x60, 0x06, 0x8e, 0xa6, 0x67, 0xa6, 0xd6, 0x00, 0xdc, 0x65, 0x86, 0xc2, 0x5d,
0xac, 0x02, 0xb3, 0xa7, 0xaa, 0xc0, 0xdc, 0x89, 0x14, 0xf8, 0x77, 0x49, 0x28, 0x30, 0xf0, 0x86,
0x38, 0xbe, 0x23, 0x07, 0x14, 0x23, 0x0d, 0x55, 0xcc, 0x20, 0xe8, 0x4c, 0x9d, 0x1c, 0x3a, 0xd3,
0x09, 0xd0, 0xa9, 0xcc, 0xc1, 0x6c, 0x70, 0xbb, 0xbc, 0xb1, 0xf3, 0x63, 0x09, 0xaa, 0x6c, 0xe0,
0x24, 0x6d, 0xc7, 0xb3, 0x72, 0x3b, 0xe5, 0x75, 0x98, 0xf6, 0xad, 0xce, 0xeb, 0x5d, 0x9a, 0x94,
0x18, 0xed, 0x5d, 0x32, 0x66, 0x95, 0x8f, 0x2b, 0x3f, 0x4b, 0x89, 0xf9, 0x27, 0xed, 0x23, 0xc6,
0x6e, 0xef, 0xff, 0xa0, 0xea, 0xdb, 0x9e, 0xbf, 0xa4, 0xae, 0x78, 0x1b, 0x64, 0xb5, 0x75, 0x80,
0x95, 0x37, 0x25, 0xd3, 0x21, 0xd6, 0x5b, 0xac, 0x3b, 0x19, 0x28, 0xa1, 0x33, 0x89, 0x25, 0x74,
0xd6, 0x5f, 0x42, 0x37, 0xa0, 0xc2, 0xb6, 0xdc, 0x34, 0xba, 0xad, 0x76, 0x5f, 0xc7, 0x5e, 0x7c,
0x84, 0x74, 0x23, 0x3a, 0x92, 0x0d, 0xce, 0xa7, 0x4e, 0xb1, 0x89, 0xe2, 0x5e, 0x79, 0x24, 0x00,
0x7e, 0xc4, 0x46, 0x67, 0x50, 0xec, 0xa0, 0x46, 0xe7, 0x6f, 0xd2, 0x30, 0x15, 0xe4, 0x8e, 0x71,
0x10, 0x69, 0x88, 0x83, 0xa4, 0x92, 0xea, 0xb6, 0xf4, 0x68, 0x75, 0x5b, 0xb0, 0x10, 0xcb, 0x9c,
0x42, 0x21, 0x96, 0x3d, 0x85, 0x42, 0x2c, 0x77, 0xfa, 0x85, 0x58, 0xfe, 0xe4, 0x68, 0x52, 0x48,
0x42, 0x93, 0x2f, 0xc0, 0x5c, 0xbc, 0x37, 0x21, 0x19, 0x0a, 0xee, 0x74, 0x89, 0xbd, 0xf3, 0x88,
0x7b, 0xe5, 0x63, 0x09, 0x6a, 0xbe, 0xa4, 0x75, 0xc2, 0xf3, 0x84, 0x33, 0xc3, 0x9c, 0xb7, 0xe0,
0x7c, 0xcc, 0x2a, 0x79, 0x1c, 0x8c, 0x07, 0xf7, 0xca, 0x77, 0x84, 0xac, 0x37, 0x8d, 0xae, 0x61,
0x1f, 0x9e, 0x70, 0xcb, 0x63, 0x3e, 0xfc, 0x02, 0xc8, 0x71, 0x0f, 0xe7, 0xc8, 0xff, 0x8f, 0x14,
0x94, 0x76, 0x35, 0x47, 0xcc, 0x3b, 0xbb, 0xd2, 0xe1, 0x44, 0x2d, 0xf2, 0x06, 0x4c, 0xd2, 0xb0,
0x23, 0xc9, 0x5f, 0xd7, 0x1c, 0x3c, 0x56, 0xb4, 0x95, 0xc5, 0xd4, 0xba, 0xe6, 0x60, 0xb4, 0x05,
0x15, 0xaf, 0xf1, 0xcd, 0x84, 0x8d, 0x13, 0x76, 0x53, 0xde, 0x64, 0x2a, 0xee, 0x3a, 0xcc, 0xd8,
0x9a, 0x83, 0xdb, 0x6d, 0x83, 0x16, 0xe0, 0x07, 0x5d, 0xcd, 0xe9, 0x5b, 0xfc, 0xfd, 0x47, 0x45,
0xee, 0xd0, 0xae, 0x18, 0x51, 0xfe, 0x9a, 0x82, 0x3c, 0x7f, 0x3f, 0x19, 0xb7, 0x6a, 0xf8, 0x22,
0x14, 0x7a, 0xa6, 0x6d, 0x38, 0x02, 0x00, 0x4b, 0xab, 0xe7, 0x3d, 0x5f, 0xe1, 0x32, 0x77, 0x38,
0x83, 0xea, 0xb2, 0xa2, 0xd7, 0x61, 0xc6, 0x33, 0xdd, 0x13, 0xfc, 0x94, 0x23, 0x43, 0x3a, 0x0e,
0x19, 0xbc, 0x28, 0xbf, 0x83, 0x9f, 0x32, 0x50, 0xb8, 0x02, 0x93, 0x81, 0xe9, 0xac, 0xee, 0x53,
0xcb, 0x7e, 0x4e, 0xb4, 0x02, 0x33, 0xe4, 0xed, 0xc3, 0x77, 0x88, 0x41, 0x63, 0x9f, 0x1d, 0x5e,
0x4c, 0x93, 0x21, 0xf7, 0xf4, 0xa2, 0x4e, 0xde, 0xe1, 0x56, 0xdd, 0x7a, 0x0e, 0xeb, 0x4d, 0xfe,
0x7e, 0x43, 0x67, 0xb0, 0x23, 0x55, 0x6f, 0xc1, 0x0d, 0x3a, 0x46, 0xe7, 0xbc, 0x08, 0x39, 0x7a,
0x72, 0x60, 0xd7, 0xf2, 0x34, 0xfb, 0x54, 0xbc, 0xcd, 0xd3, 0x5e, 0x9a, 0xca, 0x87, 0x95, 0x4d,
0xc8, 0x52, 0x02, 0x5a, 0x80, 0x22, 0x3b, 0x6b, 0xe8, 0xf6, 0x3b, 0x54, 0xbf, 0x59, 0xb5, 0x40,
0x09, 0xdb, 0xfd, 0x0e, 0x52, 0x20, 0xd3, 0x35, 0x75, 0x51, 0x6f, 0x4d, 0x71, 0x3d, 0xe4, 0xb6,
0x4d, 0x1d, 0x37, 0xea, 0x2a, 0x1d, 0x53, 0x36, 0xa1, 0x12, 0xd2, 0x2b, 0x79, 0xdd, 0xea, 0x69,
0x96, 0x43, 0x44, 0xee, 0xf1, 0xfe, 0x79, 0x56, 0xa5, 0x6d, 0x95, 0x6d, 0x4a, 0x21, 0xa9, 0xd9,
0xe8, 0xea, 0xf8, 0x48, 0x1c, 0x2b, 0xd2, 0x1b, 0xe5, 0x8f, 0x12, 0xcc, 0x70, 0x51, 0x27, 0x7b,
0x65, 0x7a, 0x36, 0x3e, 0xf3, 0x02, 0x54, 0x3a, 0xda, 0x51, 0x93, 0x1e, 0x33, 0xb0, 0x26, 0x28,
0xef, 0xa1, 0x4e, 0x76, 0xb4, 0x23, 0xaf, 0xe7, 0xa9, 0xfc, 0x5e, 0x82, 0xd9, 0xe0, 0xb6, 0x38,
0x42, 0xbe, 0x02, 0x20, 0x5e, 0xcf, 0xdd, 0x75, 0x4e, 0xf3, 0x75, 0x16, 0x45, 0x5f, 0xb9, 0xae,
0x16, 0x39, 0x53, 0x23, 0xbe, 0xef, 0x9a, 0x3a, 0x8d, 0xbe, 0xeb, 0x18, 0x4d, 0xf8, 0x3f, 0xa5,
0xdc, 0xed, 0x9c, 0xf0, 0x85, 0x60, 0xfc, 0xfd, 0x27, 0x84, 0x69, 0xea, 0xb8, 0x61, 0x9a, 0x1e,
0x3d, 0x4c, 0x33, 0x49, 0x61, 0x7a, 0x1b, 0x26, 0xfb, 0xbd, 0xb6, 0xa9, 0xe9, 0x4d, 0x0b, 0xdb,
0xfd, 0xb6, 0xc3, 0xcf, 0x9f, 0x94, 0xa8, 0x0b, 0x11, 0xa5, 0x3e, 0xe8, 0xf1, 0x63, 0x98, 0x7e,
0xdb, 0x51, 0xcb, 0x7d, 0xdf, 0x9d, 0xf2, 0x3d, 0xaf, 0xe3, 0x1e, 0x61, 0x1d, 0x1c, 0xa6, 0x2f,
0x42, 0x9e, 0x9e, 0x14, 0xbb, 0xc7, 0x85, 0xe1, 0x48, 0xcd, 0x91, 0xe1, 0x86, 0x8e, 0xae, 0x41,
0xe6, 0x50, 0xb3, 0x0f, 0xf9, 0xc7, 0x4d, 0xd3, 0xe2, 0x88, 0x8c, 0x3e, 0x6e, 0x53, 0xb3, 0x0f,
0x55, 0x3a, 0xac, 0xfc, 0x27, 0x05, 0x65, 0x92, 0xf0, 0x84, 0x09, 0xd0, 0x6a, 0x38, 0xa0, 0x4a,
0xab, 0xe7, 0x7c, 0xfb, 0xf3, 0x72, 0xa3, 0x2f, 0xaa, 0x42, 0x20, 0x90, 0x4a, 0x06, 0x81, 0xb4,
0x0f, 0x04, 0xa2, 0x07, 0xa0, 0xd9, 0x11, 0x0e, 0x40, 0xdf, 0x86, 0x73, 0xee, 0x29, 0xa0, 0x2f,
0x1e, 0x49, 0x69, 0x3f, 0x42, 0x70, 0xcc, 0x88, 0xb9, 0x1e, 0xcd, 0x8e, 0xa6, 0xd3, 0xfc, 0xb1,
0xd3, 0x69, 0x42, 0xfe, 0x2b, 0x24, 0xe6, 0xbf, 0xba, 0x7b, 0xcc, 0x15, 0x7c, 0x07, 0x45, 0xff,
0x0f, 0xd3, 0x76, 0xbf, 0xd5, 0xc2, 0xb6, 0xbd, 0xdf, 0x6f, 0x37, 0x39, 0xd2, 0x33, 0x6f, 0xa8,
0x7a, 0x03, 0x3b, 0x0c, 0xe2, 0x7f, 0x97, 0x72, 0xfd, 0x69, 0x4b, 0x7b, 0x82, 0x59, 0x96, 0xf8,
0x1f, 0xc7, 0xd4, 0x67, 0x91, 0x87, 0x13, 0xf3, 0x6a, 0x36, 0x31, 0xaf, 0xb2, 0xb6, 0x7f, 0x44,
0x95, 0xbc, 0x3e, 0xfc, 0xb9, 0x77, 0xf8, 0x7b, 0x1a, 0xe5, 0xfa, 0x33, 0xd1, 0xb4, 0xf2, 0xa9,
0x77, 0x38, 0x1c, 0x57, 0xbd, 0x7f, 0x3e, 0x73, 0xd3, 0xaf, 0xbc, 0x4d, 0x9d, 0xca, 0x6b, 0xc4,
0xf8, 0x5a, 0xb8, 0x09, 0x79, 0x96, 0x06, 0xc4, 0xe6, 0x13, 0xf2, 0x80, 0xab, 0x6e, 0x92, 0x07,
0xc4, 0x94, 0x48, 0x0a, 0xf0, 0x73, 0x3d, 0xdb, 0x14, 0xb0, 0x08, 0x0b, 0xb1, 0x8a, 0xe4, 0x2e,
0xff, 0x89, 0x04, 0x88, 0x8f, 0x9f, 0xa8, 0x5f, 0x34, 0xa6, 0xaf, 0xaf, 0x43, 0x85, 0x75, 0x84,
0x9a, 0xa3, 0xbb, 0xfc, 0x14, 0x9b, 0xe1, 0x16, 0xa7, 0x6e, 0x5b, 0x28, 0xed, 0x6b, 0x0b, 0x29,
0x8f, 0xdd, 0xd2, 0x33, 0xd0, 0xcc, 0xb9, 0x1e, 0x6c, 0xe6, 0x44, 0x1f, 0x33, 0x4a, 0x37, 0xc7,
0xab, 0x90, 0xdd, 0x6e, 0x8e, 0x3f, 0x68, 0xa5, 0xd1, 0x83, 0xf6, 0x97, 0x92, 0xfb, 0xc1, 0x41,
0xe8, 0x33, 0x93, 0xcf, 0x83, 0xea, 0x95, 0x5f, 0xa4, 0xbd, 0xcf, 0x1c, 0x42, 0x1f, 0xa4, 0x7c,
0x3e, 0x01, 0x27, 0x39, 0x97, 0x64, 0x92, 0xdf, 0xd1, 0x2e, 0x43, 0x39, 0xe6, 0xeb, 0xb5, 0x92,
0xed, 0x3b, 0x90, 0x4b, 0x48, 0x83, 0xb9, 0xe3, 0xa6, 0xc1, 0x7c, 0x4c, 0x1a, 0x7c, 0x19, 0x32,
0x5d, 0x7c, 0x24, 0x4e, 0x36, 0x07, 0x58, 0x91, 0xb2, 0x29, 0xef, 0x43, 0x79, 0x5d, 0x73, 0x5a,
0x87, 0xc7, 0xf6, 0xb7, 0x2f, 0x41, 0xc1, 0x62, 0x03, 0x22, 0x9a, 0x64, 0xdf, 0x37, 0xa0, 0x3e,
0xd1, 0x34, 0x9c, 0x5c, 0x5e, 0xe5, 0x6f, 0x00, 0xd5, 0xf0, 0x30, 0xaa, 0xc3, 0x24, 0x3f, 0xc6,
0x67, 0xad, 0x46, 0x1e, 0x44, 0x8b, 0xe1, 0xaf, 0x4a, 0x03, 0x5f, 0x82, 0x6f, 0x4e, 0xa8, 0xe5,
0x3d, 0x1f, 0x19, 0xdd, 0x00, 0x7e, 0xf2, 0xdf, 0x3c, 0xc0, 0xde, 0x67, 0xe7, 0x21, 0x11, 0x5e,
0xb7, 0x7f, 0x73, 0x42, 0x2d, 0xee, 0x09, 0x9a, 0x6f, 0x09, 0x3a, 0xc5, 0x46, 0x8e, 0xa8, 0x91,
0x25, 0x04, 0x52, 0x90, 0xb7, 0x04, 0x46, 0x46, 0x5f, 0x71, 0xbf, 0x47, 0x68, 0x1b, 0xb6, 0xe3,
0xf6, 0x7c, 0x62, 0x3e, 0x8e, 0xf5, 0x24, 0xf0, 0x45, 0x13, 0x22, 0xfa, 0x06, 0xcc, 0xf1, 0xf9,
0x36, 0x76, 0x9a, 0x9a, 0xf7, 0x5d, 0x02, 0x6f, 0xff, 0x5c, 0x0b, 0x8b, 0x8a, 0xfd, 0x94, 0x62,
0x73, 0x42, 0x9d, 0xdd, 0x8b, 0x19, 0x46, 0x6b, 0x50, 0xe6, 0xdd, 0xf2, 0x3d, 0x52, 0x24, 0xf0,
0x36, 0xd0, 0x85, 0x70, 0xeb, 0xd8, 0xff, 0xba, 0xbe, 0x39, 0xa1, 0x96, 0x4c, 0x8f, 0x4a, 0xf4,
0xc4, 0x45, 0xb4, 0x68, 0x31, 0xcb, 0x0b, 0xe9, 0xc5, 0xb0, 0x8c, 0xc0, 0xcb, 0x24, 0xd1, 0x93,
0xe9, 0x23, 0x13, 0x53, 0x71, 0x29, 0xc4, 0x54, 0x85, 0xb0, 0xa9, 0xc2, 0x07, 0x33, 0xc4, 0x54,
0xa6, 0xa0, 0x11, 0x25, 0xf3, 0xc9, 0x54, 0xc9, 0xc5, 0xb0, 0x92, 0x23, 0x07, 0x1f, 0x44, 0xc9,
0xa6, 0x4b, 0x44, 0xf7, 0x61, 0xc6, 0xaf, 0x05, 0x61, 0x70, 0xa0, 0x72, 0x94, 0x58, 0x65, 0x84,
0xad, 0x3e, 0x6d, 0x86, 0xc7, 0xd0, 0x43, 0x98, 0xe5, 0x52, 0xf7, 0x69, 0x8a, 0x15, 0x62, 0x4b,
0x54, 0xec, 0x95, 0xb0, 0xd8, 0x98, 0x82, 0x66, 0x73, 0x42, 0x45, 0x66, 0x64, 0x90, 0x68, 0x5c,
0x00, 0x0c, 0xb3, 0x5a, 0x39, 0xac, 0xf1, 0x98, 0x2e, 0x0b, 0xd1, 0xb8, 0xed, 0x23, 0xa3, 0xdb,
0x30, 0x25, 0xa4, 0x70, 0xc3, 0xb1, 0x33, 0xfc, 0x8b, 0x11, 0x31, 0x61, 0xcb, 0x89, 0xa7, 0x73,
0xd3, 0xdd, 0x87, 0x19, 0x21, 0xa8, 0xa3, 0x3d, 0xc1, 0x1c, 0x26, 0xe9, 0x29, 0x7e, 0x5c, 0x79,
0x14, 0x79, 0x57, 0x21, 0xda, 0xb3, 0xc3, 0x63, 0x44, 0x7b, 0x81, 0x4d, 0x0a, 0xed, 0x55, 0xc2,
0xda, 0x4b, 0xac, 0xcc, 0x89, 0xf6, 0xec, 0xc8, 0x20, 0x7a, 0x0c, 0xe7, 0x84, 0xe0, 0xa0, 0x5d,
0xaa, 0x54, 0xf2, 0xd5, 0x88, 0xe4, 0x78, 0xc3, 0x88, 0x3d, 0x07, 0x2c, 0xb3, 0xe6, 0x41, 0x3f,
0xf5, 0xc4, 0xe9, 0x70, 0x38, 0x45, 0x6b, 0x2a, 0x12, 0x4e, 0xb6, 0x47, 0x45, 0x5b, 0x50, 0x15,
0x22, 0x74, 0x9e, 0x43, 0x6b, 0x28, 0x7c, 0x80, 0x15, 0x5f, 0x23, 0x6c, 0x4e, 0xa8, 0x15, 0x3b,
0x38, 0xb2, 0x5e, 0x84, 0x3c, 0x1f, 0x55, 0xde, 0x82, 0x49, 0x8e, 0xb3, 0x3c, 0x25, 0x7f, 0x19,
0x8a, 0x16, 0xbf, 0x16, 0x90, 0xbd, 0x10, 0x81, 0x6c, 0x36, 0x4e, 0x31, 0xdb, 0xe3, 0x56, 0xfe,
0x05, 0x30, 0x1d, 0x61, 0x40, 0x1b, 0xf1, 0xa8, 0x7d, 0x31, 0x09, 0xb5, 0xd9, 0xd4, 0x08, 0x6c,
0xdf, 0x8c, 0x81, 0xed, 0x85, 0x58, 0xd8, 0x76, 0x05, 0xf8, 0x70, 0x7b, 0x23, 0x1e, 0xb7, 0x2f,
0x26, 0xe1, 0x76, 0x78, 0x11, 0xdc, 0x94, 0x6f, 0xc4, 0x01, 0xf7, 0x85, 0x78, 0xe0, 0x76, 0x45,
0xf8, 0x91, 0xfb, 0x9b, 0x43, 0x90, 0xfb, 0x85, 0x61, 0xc8, 0xed, 0x4a, 0x8d, 0x87, 0xee, 0xf5,
0x58, 0xe8, 0x5e, 0x4c, 0x80, 0x6e, 0x57, 0x58, 0x00, 0xbb, 0x37, 0xe2, 0xb1, 0xfb, 0x62, 0x12,
0x76, 0x7b, 0xba, 0x0a, 0x80, 0xf7, 0xcd, 0x18, 0xf0, 0x5e, 0x88, 0x05, 0x6f, 0xcf, 0x60, 0x1e,
0x7a, 0xbf, 0x11, 0x87, 0xde, 0x17, 0xe2, 0xd1, 0xdb, 0xd3, 0xb4, 0x0f, 0xbe, 0x1f, 0x0c, 0x82,
0xef, 0x2b, 0x03, 0xe1, 0xdb, 0x95, 0x17, 0x83, 0xdf, 0x8f, 0x06, 0xe2, 0xf7, 0xd5, 0xc1, 0xf8,
0xed, 0x0a, 0x8e, 0x03, 0xf0, 0x8d, 0x78, 0x00, 0xbf, 0x98, 0x04, 0xe0, 0x9e, 0xda, 0x03, 0x08,
0xbe, 0x99, 0x80, 0xe0, 0x4b, 0x89, 0x08, 0xee, 0x0a, 0x0a, 0x41, 0xf8, 0x83, 0x41, 0x10, 0x7e,
0x65, 0x20, 0x84, 0x7b, 0x1a, 0x8c, 0x62, 0xf8, 0xa3, 0x81, 0x18, 0x7e, 0x75, 0x30, 0x86, 0x7b,
0x1a, 0x8c, 0x01, 0xf1, 0xaf, 0x0f, 0x06, 0xf1, 0x6b, 0x43, 0x40, 0xdc, 0x95, 0x1d, 0x8b, 0xe2,
0xeb, 0xb1, 0x28, 0xbe, 0x98, 0x80, 0xe2, 0x5e, 0x64, 0xf9, 0x61, 0x7c, 0x3b, 0x11, 0xc6, 0x2f,
0x0f, 0x80, 0x71, 0x57, 0x56, 0x04, 0xc7, 0x01, 0x0a, 0x62, 0x78, 0xf5, 0x9f, 0xd3, 0x50, 0xd8,
0xe2, 0x32, 0xd0, 0x16, 0x94, 0x19, 0x6c, 0xf2, 0x7f, 0x66, 0x07, 0x97, 0xc8, 0xf2, 0x10, 0x2c,
0x46, 0x75, 0x28, 0xde, 0xc6, 0x0e, 0x97, 0x35, 0xa0, 0x56, 0x96, 0x07, 0x01, 0x32, 0x59, 0x14,
0xd3, 0x65, 0xd2, 0xa2, 0x02, 0xd9, 0x54, 0x1e, 0x82, 0xcd, 0x68, 0x13, 0x4a, 0x44, 0xa9, 0x6c,
0xcc, 0x46, 0x83, 0xca, 0x67, 0x79, 0x20, 0x44, 0x23, 0x0c, 0xb3, 0xbb, 0x62, 0x7b, 0x7e, 0x30,
0x1d, 0xad, 0x8c, 0x96, 0x47, 0xc4, 0x6c, 0xf4, 0x16, 0x94, 0xa8, 0xb7, 0xf2, 0x6f, 0x75, 0x07,
0xd6, 0xd3, 0xf2, 0x60, 0xc8, 0xa6, 0x06, 0xa6, 0x51, 0xca, 0x85, 0x0d, 0x2e, 0xac, 0xe5, 0x21,
0xd8, 0xcd, 0x0d, 0xcc, 0x65, 0x0d, 0xa8, 0xb0, 0xe5, 0x41, 0x00, 0x2e, 0x2c, 0xc2, 0x06, 0x02,
0x16, 0x89, 0xd4, 0xda, 0xf2, 0x40, 0x28, 0x47, 0xef, 0xc2, 0xb4, 0x2f, 0xb0, 0xf9, 0xba, 0x46,
0xa8, 0xb9, 0xe5, 0x51, 0x80, 0x1d, 0x35, 0x01, 0xf9, 0x43, 0x9b, 0x8b, 0x1f, 0xa5, 0xf6, 0x96,
0x47, 0x02, 0x78, 0x62, 0x1d, 0xfa, 0x5c, 0x71, 0x9c, 0x3d, 0xb8, 0x08, 0x97, 0x87, 0x40, 0x3c,
0xda, 0x81, 0x49, 0x66, 0x2f, 0x21, 0x6f, 0x48, 0x35, 0x2e, 0x0f, 0xc3, 0x7a, 0xa2, 0x5f, 0x0f,
0x91, 0x85, 0xd4, 0x11, 0xaa, 0x72, 0x79, 0x14, 0xd8, 0x27, 0xfa, 0xf5, 0xa9, 0x5d, 0x88, 0x1f,
0xa5, 0x3a, 0x97, 0x47, 0x82, 0x7f, 0xb4, 0x07, 0x33, 0x7e, 0xbd, 0x8b, 0x27, 0x8c, 0x54, 0xa5,
0xcb, 0xa3, 0xa5, 0x01, 0x74, 0x07, 0xca, 0xfe, 0x7f, 0x24, 0xd0, 0xc0, 0x7a, 0x5d, 0x1e, 0x9c,
0x07, 0xd0, 0x3b, 0x50, 0x11, 0xa0, 0x2d, 0x16, 0x3b, 0xb4, 0x70, 0x97, 0x87, 0xe7, 0x04, 0xf4,
0x1a, 0x64, 0x69, 0xc1, 0x8d, 0xe6, 0xe2, 0xbb, 0x2a, 0xf2, 0x7c, 0x42, 0xe9, 0x8e, 0x1e, 0x42,
0x95, 0x81, 0x3c, 0x17, 0x7d, 0xaf, 0xad, 0xc7, 0x2c, 0x29, 0xf4, 0x17, 0x69, 0xcc, 0x92, 0x22,
0x7f, 0x45, 0x7e, 0x0d, 0xaa, 0x01, 0x67, 0x25, 0xb4, 0xcb, 0x83, 0xfd, 0x95, 0x48, 0x56, 0x86,
0xb8, 0x2c, 0x11, 0xb3, 0x0b, 0x53, 0xbe, 0x1f, 0xaf, 0x08, 0x25, 0xea, 0xe8, 0xc1, 0x5f, 0xc4,
0xe4, 0x4b, 0x09, 0x0c, 0x9e, 0xd0, 0x26, 0xa0, 0x90, 0x69, 0x08, 0xf5, 0xca, 0x30, 0xeb, 0x10,
0xe1, 0x57, 0x87, 0x1a, 0x88, 0x2b, 0x24, 0xe0, 0xa6, 0xf1, 0x0a, 0x09, 0xff, 0x01, 0x16, 0xa3,
0x90, 0xe8, 0x1f, 0x59, 0xef, 0x40, 0xc5, 0xef, 0xa3, 0x21, 0x1b, 0xc6, 0xff, 0x27, 0xe5, 0xb7,
0x61, 0xd2, 0x6f, 0x43, 0xef, 0xc2, 0x74, 0x30, 0x87, 0x11, 0x62, 0x60, 0x41, 0xf1, 0x7f, 0xe6,
0x04, 0xe1, 0x21, 0xe1, 0x87, 0x19, 0x92, 0x07, 0x7d, 0x7f, 0xba, 0xf8, 0x03, 0x2b, 0xfa, 0x1f,
0x8d, 0x3f, 0xb0, 0x62, 0x7e, 0x8f, 0x59, 0xcf, 0x3c, 0x4e, 0xf5, 0xf6, 0xf6, 0x72, 0xf4, 0x5c,
0xf6, 0xd5, 0xff, 0x06, 0x00, 0x00, 0xff, 0xff, 0x70, 0x7c, 0x53, 0x8c, 0xd4, 0x44, 0x00, 0x00,
}
type DRPCMetainfoClient interface {

View File

@ -215,7 +215,7 @@ message ListSegmentsRequestOld {
bytes bucket = 1;
bytes prefix = 2;
bytes start_after = 3;
bytes end_before = 4;
bytes end_before = 4 [deprecated=true];
bool recursive = 5;
int32 limit = 6;
fixed32 meta_flags = 7;

View File

@ -77,9 +77,9 @@ func (create CreateObject) Object(bucket Bucket, path Path) Object {
type ListDirection int8
const (
// Before lists backwards from cursor, without cursor
// Before lists backwards from cursor, without cursor [NOT SUPPORTED]
Before = ListDirection(-2)
// Backward lists backwards from cursor, including cursor
// Backward lists backwards from cursor, including cursor [NOT SUPPORTED]
Backward = ListDirection(-1)
// Forward lists forwards from cursor, including cursor
Forward = ListDirection(1)
@ -114,24 +114,12 @@ func (opts ListOptions) NextPage(list ObjectList) ListOptions {
return ListOptions{}
}
switch opts.Direction {
case Before, Backward:
return ListOptions{
Prefix: opts.Prefix,
Cursor: list.Items[0].Path,
Direction: Before,
Limit: opts.Limit,
}
case After, Forward:
return ListOptions{
Prefix: opts.Prefix,
Cursor: list.Items[len(list.Items)-1].Path,
Direction: After,
Limit: opts.Limit,
}
return ListOptions{
Prefix: opts.Prefix,
Cursor: list.Items[len(list.Items)-1].Path,
Direction: After,
Limit: opts.Limit,
}
return ListOptions{}
}
// BucketListOptions lists objects
@ -153,22 +141,11 @@ func (opts BucketListOptions) NextPage(list BucketList) BucketListOptions {
return BucketListOptions{}
}
switch opts.Direction {
case Before, Backward:
return BucketListOptions{
Cursor: list.Items[0].Name,
Direction: Before,
Limit: opts.Limit,
}
case After, Forward:
return BucketListOptions{
Cursor: list.Items[len(list.Items)-1].Name,
Direction: After,
Limit: opts.Limit,
}
return BucketListOptions{
Cursor: list.Items[len(list.Items)-1].Name,
Direction: After,
Limit: opts.Limit,
}
return BucketListOptions{}
}
// MetainfoLimits lists limits specified for the Metainfo database

View File

@ -2431,7 +2431,13 @@
{
"id": 4,
"name": "end_before",
"type": "bytes"
"type": "bytes",
"options": [
{
"name": "deprecated",
"value": "true"
}
]
},
{
"id": 5,

View File

@ -438,7 +438,7 @@ func (endpoint *Endpoint) ListSegmentsOld(ctx context.Context, req *pb.ListSegme
return nil, rpcstatus.Error(rpcstatus.InvalidArgument, err.Error())
}
items, more, err := endpoint.metainfo.List(ctx, prefix, string(req.StartAfter), string(req.EndBefore), req.Recursive, req.Limit, req.MetaFlags)
items, more, err := endpoint.metainfo.List(ctx, prefix, string(req.StartAfter), req.Recursive, req.Limit, req.MetaFlags)
if err != nil {
return nil, rpcstatus.Error(rpcstatus.Internal, err.Error())
}
@ -924,7 +924,7 @@ func (endpoint *Endpoint) setBucketAttribution(ctx context.Context, header *pb.R
return rpcstatus.Error(rpcstatus.InvalidArgument, err.Error())
}
items, _, err := endpoint.metainfo.List(ctx, prefix, "", "", true, 1, 0)
items, _, err := endpoint.metainfo.List(ctx, prefix, "", true, 1, 0)
if err != nil {
endpoint.log.Error("error while listing segments", zap.Error(err))
return rpcstatus.Error(rpcstatus.Internal, err.Error())
@ -1292,8 +1292,7 @@ func (endpoint *Endpoint) ListObjects(ctx context.Context, req *pb.ObjectListReq
metaflags := meta.All
// TODO use flags
// TODO find out how EncryptedCursor -> startAfter/endAfter
segments, more, err := endpoint.metainfo.List(ctx, prefix, string(req.EncryptedCursor), "", req.Recursive, req.Limit, metaflags)
segments, more, err := endpoint.metainfo.List(ctx, prefix, string(req.EncryptedCursor), req.Recursive, req.Limit, metaflags)
if err != nil {
return nil, rpcstatus.Error(rpcstatus.Internal, err.Error())
}

View File

@ -196,7 +196,7 @@ func (s *Service) GetWithBytes(ctx context.Context, path string) (pointerBytes [
}
// List returns all Path keys in the pointers bucket
func (s *Service) List(ctx context.Context, prefix string, startAfter string, endBefore string, recursive bool, limit int32,
func (s *Service) List(ctx context.Context, prefix string, startAfter string, recursive bool, limit int32,
metaFlags uint32) (items []*pb.ListResponse_Item, more bool, err error) {
defer mon.Task()(&ctx)(&err)
@ -211,7 +211,6 @@ func (s *Service) List(ctx context.Context, prefix string, startAfter string, en
rawItems, more, err := storage.ListV2(ctx, s.db, storage.ListOptions{
Prefix: prefixKey,
StartAfter: storage.Key(startAfter),
EndBefore: storage.Key(endBefore),
Recursive: recursive,
Limit: int(limit),
IncludeValue: metaFlags != meta.None,

View File

@ -597,7 +597,7 @@ func TestRepairMultipleDisqualified(t *testing.T) {
// get a remote segment from metainfo
metainfo := satellite.Metainfo.Service
listResponse, _, err := metainfo.List(ctx, "", "", "", true, 0, 0)
listResponse, _, err := metainfo.List(ctx, "", "", true, 0, 0)
require.NoError(t, err)
var path string
@ -1036,7 +1036,7 @@ func getRemoteSegment(
// get a remote segment from metainfo
metainfo := satellite.Metainfo.Service
listResponse, _, err := metainfo.List(ctx, "", "", "", true, 0, 0)
listResponse, _, err := metainfo.List(ctx, "", "", true, 0, 0)
require.NoError(t, err)
for _, v := range listResponse {

View File

@ -226,12 +226,7 @@ func (client *Client) GetAll(ctx context.Context, keys storage.Keys) (_ storage.
func (client *Client) Iterate(ctx context.Context, opts storage.IterateOptions, fn func(context.Context, storage.Iterator) error) (err error) {
defer mon.Task()(&ctx)(&err)
return client.view(func(bucket *bolt.Bucket) error {
var cursor advancer
if !opts.Reverse {
cursor = forward{bucket.Cursor()}
} else {
cursor = backward{bucket.Cursor()}
}
var cursor advancer = forward{bucket.Cursor()}
start := true
lastPrefix := []byte{}
@ -307,46 +302,6 @@ func (cursor forward) Advance() (key, value []byte) {
return cursor.Next()
}
type backward struct {
*bolt.Cursor
}
func (cursor backward) PositionToFirst(prefix, first storage.Key) (key, value []byte) {
if prefix.IsZero() {
// there's no prefix
if first.IsZero() {
// and no first item, so start from the end
return cursor.Last()
}
} else {
// there's a prefix
if first.IsZero() || storage.AfterPrefix(prefix).Less(first) {
// there's no first, or it's after our prefix
// storage.AfterPrefix("axxx/") is the next item after prefixes
// so we position to the item before
nextkey := storage.AfterPrefix(prefix)
_, _ = cursor.Seek(nextkey)
return cursor.Prev()
}
}
// otherwise try to position on first or one before that
key, value = cursor.Seek(first)
if !bytes.Equal(key, first) {
key, value = cursor.Prev()
}
return key, value
}
func (cursor backward) SkipPrefix(prefix storage.Key) (key, value []byte) {
_, _ = cursor.Seek(prefix)
return cursor.Prev()
}
func (cursor backward) Advance() (key, value []byte) {
return cursor.Prev()
}
// CompareAndSwap atomically compares and swaps oldValue with newValue
func (client *Client) CompareAndSwap(ctx context.Context, key storage.Key, oldValue, newValue storage.Value) (err error) {
defer mon.Task()(&ctx)(&err)

View File

@ -85,8 +85,6 @@ type IterateOptions struct {
First Key
// Recurse, do not collapse items based on Delimiter
Recurse bool
// Reverse iterates in reverse order
Reverse bool
}
// Iterator iterates over a sequence of ListItems

View File

@ -60,26 +60,6 @@ func SortAndCollapse(items Items, prefix []byte) Items {
return result
}
// ReverseItems reverses items in the list
// items will be reused and modified
// TODO: remove this
func ReverseItems(items Items) Items {
for i := len(items)/2 - 1; i >= 0; i-- {
k := len(items) - 1 - i
items[i], items[k] = items[k], items[i]
}
return items
}
// ReverseKeys reverses the list of keys
func ReverseKeys(keys Keys) Keys {
for i := len(keys)/2 - 1; i >= 0; i-- {
k := len(keys) - 1 - i
keys[i], keys[k] = keys[k], keys[i]
}
return keys
}
// StaticIterator implements an iterator over list of items
type StaticIterator struct {
Items Items

View File

@ -5,14 +5,12 @@ package storage
import (
"context"
"errors"
)
// ListOptions are items that are optional for the LIST method
type ListOptions struct {
Prefix Key
StartAfter Key // StartAfter is relative to Prefix
EndBefore Key // EndBefore is relative to Prefix
Recursive bool
IncludeValue bool
Limit int
@ -24,12 +22,9 @@ type ListOptions struct {
// more indicates if the result was truncated. If false
// then the result []ListItem includes all requested keys.
// If true then the caller must call List again to get more
// results by setting `StartAfter` or `EndBefore` appropriately.
// results by setting `StartAfter` appropriately.
func ListV2(ctx context.Context, store KeyValueStore, opts ListOptions) (result Items, more bool, err error) {
defer mon.Task()(&ctx)(&err)
if !opts.StartAfter.IsZero() && !opts.EndBefore.IsZero() {
return nil, false, errors.New("start-after and end-before cannot be combined")
}
limit := opts.Limit
if limit <= 0 || limit > LookupLimit {
@ -37,15 +32,8 @@ func ListV2(ctx context.Context, store KeyValueStore, opts ListOptions) (result
}
more = true
reverse := !opts.EndBefore.IsZero()
var first Key
if !reverse {
first = opts.StartAfter
} else {
first = opts.EndBefore
}
first := opts.StartAfter
iterate := func(ctx context.Context, it Iterator) error {
var item ListItem
skipFirst := true
@ -86,23 +74,15 @@ func ListV2(ctx context.Context, store KeyValueStore, opts ListOptions) (result
}
var firstFull Key
if !reverse && !opts.StartAfter.IsZero() {
if !opts.StartAfter.IsZero() {
firstFull = joinKey(opts.Prefix, opts.StartAfter)
}
if reverse && !opts.EndBefore.IsZero() {
firstFull = joinKey(opts.Prefix, opts.EndBefore)
}
err = store.Iterate(ctx, IterateOptions{
Prefix: opts.Prefix,
First: firstFull,
Reverse: reverse,
Recurse: opts.Recursive,
}, iterate)
if reverse {
result = ReverseItems(result)
}
return result, more, err
}

View File

@ -57,29 +57,6 @@ FROM (
) x
ORDER BY p
LIMIT $4
`
alternateReverseQuery = `
SELECT DISTINCT
$2::BYTEA || x.localpath AS p,
first_value(x.metadata) OVER (PARTITION BY x.localpath ORDER BY x.fullpath) AS m
FROM (
SELECT
pd.fullpath,
local_path(pd.fullpath, $2::BYTEA, set_byte(' '::BYTEA, 0, b.delim)) AS localpath,
pd.metadata
FROM
pathdata pd,
buckets b
WHERE
b.bucketname = $1::BYTEA
AND pd.bucket = b.bucketname
AND pd.fullpath >= $2::BYTEA
AND ($2::BYTEA = ''::BYTEA OR pd.fullpath < bytea_increment($2::BYTEA))
AND ($3::BYTEA = ''::BYTEA OR pd.fullpath <= $3::BYTEA)
) x
ORDER BY p DESC
LIMIT $4
`
)
@ -120,13 +97,7 @@ func (opi *alternateOrderedPostgresIterator) doNextQuery(ctx context.Context) (_
if start == nil {
start = opi.opts.First
}
var query string
if opi.opts.Reverse {
query = alternateReverseQuery
} else {
query = alternateForwardQuery
}
return opi.client.pgConn.Query(query, []byte(opi.bucket), []byte(opi.opts.Prefix), []byte(start), opi.batchSize+1)
return opi.client.pgConn.Query(alternateForwardQuery, []byte(opi.bucket), []byte(opi.opts.Prefix), []byte(start), opi.batchSize+1)
}
func newAlternateOrderedPostgresIterator(ctx context.Context, altClient *AlternateClient, opts storage.IterateOptions, batchSize int) (_ *alternateOrderedPostgresIterator, err error) {

View File

@ -6,7 +6,6 @@ package postgreskv
import (
"context"
"database/sql"
"fmt"
"github.com/lib/pq"
"github.com/zeebo/errs"
@ -254,28 +253,18 @@ func (opi *orderedPostgresIterator) doNextQuery(ctx context.Context) (_ *sql.Row
}
var query string
if !opi.opts.Recurse {
if opi.opts.Reverse {
query = "SELECT p, m FROM list_directory_reverse($1::BYTEA, $2::BYTEA, $3::BYTEA, $4) ld(p, m)"
} else {
query = "SELECT p, m FROM list_directory($1::BYTEA, $2::BYTEA, $3::BYTEA, $4) ld(p, m)"
}
query = "SELECT p, m FROM list_directory($1::BYTEA, $2::BYTEA, $3::BYTEA, $4) ld(p, m)"
} else {
startCmp := ">="
orderDir := ""
if opi.opts.Reverse {
startCmp = "<="
orderDir = " DESC"
}
query = fmt.Sprintf(`
query = `
SELECT fullpath, metadata
FROM pathdata
WHERE bucket = $1::BYTEA
AND ($2::BYTEA = ''::BYTEA OR fullpath >= $2::BYTEA)
AND ($2::BYTEA = ''::BYTEA OR fullpath < bytea_increment($2::BYTEA))
AND ($3::BYTEA = ''::BYTEA OR fullpath %s $3::BYTEA)
ORDER BY fullpath%s
AND ($3::BYTEA = ''::BYTEA OR fullpath >= $3::BYTEA)
ORDER BY fullpath
LIMIT $4
`, startCmp, orderDir)
`
}
return opi.client.pgConn.Query(query, []byte(opi.bucket), []byte(opi.opts.Prefix), []byte(start), opi.batchSize+1)
}

View File

@ -164,21 +164,13 @@ func (client *Client) GetAll(ctx context.Context, keys storage.Keys) (_ storage.
// Iterate iterates over items based on opts
func (client *Client) Iterate(ctx context.Context, opts storage.IterateOptions, fn func(context.Context, storage.Iterator) error) (err error) {
defer mon.Task()(&ctx)(&err)
var all storage.Items
if !opts.Reverse {
all, err = client.allPrefixedItems(opts.Prefix, opts.First, nil)
} else {
all, err = client.allPrefixedItems(opts.Prefix, nil, opts.First)
}
all, err := client.allPrefixedItems(opts.Prefix, opts.First, nil)
if err != nil {
return err
}
if !opts.Recurse {
all = storage.SortAndCollapse(all, opts.Prefix)
}
if opts.Reverse {
all = storage.ReverseItems(all)
}
return fn(ctx, &storage.StaticIterator{
Items: all,
})

View File

@ -74,7 +74,6 @@ func (store *Logger) Iterate(ctx context.Context, opts storage.IterateOptions, f
zap.ByteString("prefix", opts.Prefix),
zap.ByteString("first", opts.First),
zap.Bool("recurse", opts.Recurse),
zap.Bool("reverse", opts.Reverse),
)
return store.store.Iterate(ctx, opts, func(ctx context.Context, it storage.Iterator) error {
return fn(ctx, storage.IteratorFunc(func(ctx context.Context, item *storage.ListItem) bool {

View File

@ -30,7 +30,6 @@ type Client struct {
Put int
List int
GetAll int
ReverseList int
Delete int
Close int
Iterate int
@ -202,12 +201,7 @@ func (store *Client) Iterate(ctx context.Context, opts storage.IterateOptions, f
return errInternal
}
var cursor advancer
if !opts.Reverse {
cursor = &forward{newCursor(store)}
} else {
cursor = &backward{newCursor(store)}
}
var cursor advancer = &forward{newCursor(store)}
cursor.PositionToFirst(opts.Prefix, opts.First)
var lastPrefix storage.Key

View File

@ -194,19 +194,12 @@ func BenchmarkPathOperationsInLargeDb(b *testing.B, store storage.KeyValueStore)
}
doTest("DeepRecursive", deepRecursive)
doTest("DeepRecursiveReverse", deepRecursiveReverse)
doTest("DeepNonRecursive", deepNonRecursive)
doTest("DeepNonRecursiveReverse", deepNonRecursiveReverse)
doTest("ShallowRecursive", shallowRecursive)
doTest("ShallowRecursiveReverse", shallowRecursiveReverse)
doTest("ShallowNonRecursive", shallowNonRecursive)
doTest("ShallowNonRecursiveReverse", shallowNonRecursiveReverse)
doTest("TopRecursiveLimit", topRecursiveLimit)
doTest("TopRecursiveLimitReverse", topRecursiveLimitReverse)
doTest("TopRecursiveStartAt", topRecursiveStartAt)
doTest("TopRecursiveStartAtReverse", topRecursiveStartAtReverse)
doTest("TopNonRecursive", topNonRecursive)
doTest("TopNonRecursiveReverse", topNonRecursiveReverse)
cleanupStore(b, store)
}
@ -347,10 +340,7 @@ func benchAndVerifyIteration(b *testing.B, store storage.KeyValueStore, opts *ve
if result.Key.Equal(lastKey) {
errorf("got the same key (%q) twice in a row, not on a lookup boundary!", lastKey)
}
if opts.iterateOpts.Reverse && !lastKey.IsZero() && lastKey.Less(result.Key) {
errorf("KeyValueStore returned items out of order! %q > %q", result.Key, lastKey)
}
if !opts.iterateOpts.Reverse && result.Key.Less(lastKey) {
if result.Key.Less(lastKey) {
errorf("KeyValueStore returned items out of order! %q < %q", result.Key, lastKey)
}
if result.IsPrefix {
@ -410,31 +400,6 @@ func deepRecursive(b *testing.B, store storage.KeyValueStore) {
benchAndVerifyIteration(b, store, opts)
}
func deepRecursiveReverse(b *testing.B, store storage.KeyValueStore) {
opts := &verifyOpts{
iterateOpts: storage.IterateOptions{
Prefix: storage.Key(largestLevel2Directory),
Recurse: true,
Reverse: true,
},
}
// these are not expected to exhaust all available items
opts.doIterations = 500
opts.batchSize = storage.LookupLimit
opts.expectCount = opts.doIterations * opts.batchSize
// verify with:
// select encode(fullpath, 'escape') from (
// select rank() over (order by fullpath desc), fullpath from pathdata
// where fullpath < bytea_increment($1::bytea)
// ) x where rank = ($2 * $3);
// where $1 = largestLevel2Directory, $2 = doIterations, and $3 = batchSize
opts.expectLastKey = storage.Key("Peronosporales/hateless/apetaly/poikilocythemia/capped/abrash/dugout/notodontid/jasponyx/cassican/brunelliaceous")
benchAndVerifyIteration(b, store, opts)
}
func deepNonRecursive(b *testing.B, store storage.KeyValueStore) {
opts := &verifyOpts{
iterateOpts: storage.IterateOptions{
@ -460,32 +425,6 @@ func deepNonRecursive(b *testing.B, store storage.KeyValueStore) {
benchAndVerifyIteration(b, store, opts)
}
func deepNonRecursiveReverse(b *testing.B, store storage.KeyValueStore) {
opts := &verifyOpts{
iterateOpts: storage.IterateOptions{
Prefix: storage.Key(largestLevel2Directory),
Recurse: false,
Reverse: true,
},
doIterations: 1,
batchSize: 10000,
}
// verify with:
// select count(*) from list_directory(''::bytea, $1::bytea) ld(fp, md);
// where $1 is largestLevel2Directory
opts.expectCount = 119
// verify with:
// select encode(fp, 'escape') from (
// select * from list_directory(''::bytea, $1::bytea) ld(fp, md)
// ) x order by fp limit 1;
// where $1 is largestLevel2Directory
opts.expectLastKey = storage.Key("Peronosporales/hateless/Absyrtus")
benchAndVerifyIteration(b, store, opts)
}
func shallowRecursive(b *testing.B, store storage.KeyValueStore) {
opts := &verifyOpts{
iterateOpts: storage.IterateOptions{
@ -515,36 +454,6 @@ func shallowRecursive(b *testing.B, store storage.KeyValueStore) {
benchAndVerifyIteration(b, store, opts)
}
func shallowRecursiveReverse(b *testing.B, store storage.KeyValueStore) {
opts := &verifyOpts{
iterateOpts: storage.IterateOptions{
Prefix: storage.Key(largestSingleDirectory),
Recurse: true,
Reverse: true,
},
}
// verify with:
// select count(*) from pathdata
// where fullpath > $1::bytea and fullpath < bytea_increment($1::bytea);
// where $1 = largestSingleDirectory
opts.expectCount = 18574
// verify with:
// select convert_from(fullpath, 'UTF8') from pathdata
// where fullpath > $1::bytea and fullpath < bytea_increment($1::bytea)
// order by fullpath limit 1;
// where $1 = largestSingleDirectory
opts.expectLastKey = storage.Key("Peronosporales/hateless/tod/unricht/sniveling/Puyallup/Aaronite")
// i didn't plan it this way, but expectedCount happens to have some nicely-sized factors for
// our purposes with no messy remainder. 74 * 251 = 18574
opts.doIterations = 74
opts.batchSize = 251
benchAndVerifyIteration(b, store, opts)
}
func shallowNonRecursive(b *testing.B, store storage.KeyValueStore) {
opts := &verifyOpts{
iterateOpts: storage.IterateOptions{
@ -570,32 +479,6 @@ func shallowNonRecursive(b *testing.B, store storage.KeyValueStore) {
benchAndVerifyIteration(b, store, opts)
}
func shallowNonRecursiveReverse(b *testing.B, store storage.KeyValueStore) {
opts := &verifyOpts{
iterateOpts: storage.IterateOptions{
Prefix: storage.Key(largestSingleDirectory),
Recurse: false,
Reverse: true,
},
doIterations: 2,
batchSize: 10000,
}
// verify with:
// select count(*) from list_directory(''::bytea, $1::bytea) ld(fp, md);
// where $1 is largestSingleDirectory
opts.expectCount = 18574
// verify with:
// select encode(fp, 'escape') from (
// select * from list_directory(''::bytea, $1::bytea) ld(fp, md)
// ) x order by fp limit 1;
// where $1 = largestSingleDirectory
opts.expectLastKey = storage.Key("Peronosporales/hateless/tod/unricht/sniveling/Puyallup/Aaronite")
benchAndVerifyIteration(b, store, opts)
}
func topRecursiveLimit(b *testing.B, store storage.KeyValueStore) {
opts := &verifyOpts{
iterateOpts: storage.IterateOptions{
@ -618,29 +501,6 @@ func topRecursiveLimit(b *testing.B, store storage.KeyValueStore) {
benchAndVerifyIteration(b, store, opts)
}
func topRecursiveLimitReverse(b *testing.B, store storage.KeyValueStore) {
opts := &verifyOpts{
iterateOpts: storage.IterateOptions{
Recurse: true,
Reverse: true,
},
doIterations: 100,
batchSize: 10000,
}
// not expected to exhaust items
opts.expectCount = opts.doIterations * opts.batchSize
// verify with:
// select encode(fullpath, 'escape') from (
// select rank() over (order by fullpath desc), fullpath from pathdata
// ) x where rank = $1;
// where $1 = expectCount
opts.expectLastKey = storage.Key("nonresuscitation/synchronically/cabook/homeozoic/inclinatorium/iguanodont/thiophenol/congeliturbation/Alaric")
benchAndVerifyIteration(b, store, opts)
}
func topRecursiveStartAt(b *testing.B, store storage.KeyValueStore) {
opts := &verifyOpts{
iterateOpts: storage.IterateOptions{
@ -666,36 +526,6 @@ func topRecursiveStartAt(b *testing.B, store storage.KeyValueStore) {
benchAndVerifyIteration(b, store, opts)
}
func topRecursiveStartAtReverse(b *testing.B, store storage.KeyValueStore) {
opts := &verifyOpts{
iterateOpts: storage.IterateOptions{
Recurse: true,
Reverse: true,
},
doIterations: 61,
batchSize: 10000,
}
// this is pretty arbitrary. just the key 100 positions before the end of the Peronosporales/hateless/ dir.
opts.iterateOpts.First = storage.Key("Peronosporales/hateless/warrener/anthropomancy/geisotherm/wickerwork")
// we *do* expect to exhaust the available items this time.
// verify with:
// select count(*) from (
// select fullpath from pathdata where fullpath <= $1::bytea order by fullpath desc limit $2
// ) x;
// where $1 = iterateOpts.First and $2 = (doIterations * batchSize)
opts.expectCount = 608405
// since expectCount < (doIterations * batchSize), and we're going in reverse, the last key read
// should be the first one lexicographically.
// verify with:
// select encode(fullpath, 'escape') from pathdata order by fullpath limit 1;
opts.expectLastKey = storage.Key("Lissamphibia")
benchAndVerifyIteration(b, store, opts)
}
func topNonRecursive(b *testing.B, store storage.KeyValueStore) {
opts := &verifyOpts{
iterateOpts: storage.IterateOptions{
@ -718,27 +548,6 @@ func topNonRecursive(b *testing.B, store storage.KeyValueStore) {
benchAndVerifyIteration(b, store, opts)
}
func topNonRecursiveReverse(b *testing.B, store storage.KeyValueStore) {
opts := &verifyOpts{
iterateOpts: storage.IterateOptions{
Recurse: false,
Reverse: true,
},
doIterations: 1,
batchSize: 10000,
}
// verify with:
// select count(*) from list_directory(''::bytea, ''::bytea);
opts.expectCount = 21
// verify with:
// select encode(fullpath, 'escape') from pathdata order by fullpath limit 1;
opts.expectLastKey = storage.Key("Lissamphibia")
benchAndVerifyIteration(b, store, opts)
}
func cleanupBigPathset(tb testing.TB, store storage.KeyValueStore) {
if *noCleanDb {
tb.Skip("Instructed not to clean up this KeyValueStore after long benchmarks are complete.")

View File

@ -42,17 +42,6 @@ func testIterate(t *testing.T, store storage.KeyValueStore) {
newItem("g", "g", false),
newItem("h", "h", false),
}},
{"no limits reverse",
storage.IterateOptions{
Reverse: true,
}, storage.Items{
newItem("h", "h", false),
newItem("g", "g", false),
newItem("c/", "", true),
newItem("c", "c", false),
newItem("b/", "", true),
newItem("a", "a", false),
}},
{"at a",
storage.IterateOptions{
@ -66,14 +55,6 @@ func testIterate(t *testing.T, store storage.KeyValueStore) {
newItem("h", "h", false),
}},
{"reverse at a",
storage.IterateOptions{
First: storage.Key("a"),
Reverse: true,
}, storage.Items{
newItem("a", "a", false),
}},
{"after a",
storage.IterateOptions{
First: storage.NextKey(storage.Key("a")),
@ -126,16 +107,6 @@ func testIterate(t *testing.T, store storage.KeyValueStore) {
newItem("g", "g", false),
newItem("h", "h", false),
}},
{"reverse after e",
storage.IterateOptions{
First: storage.NextKey(storage.Key("e")),
Reverse: true,
}, storage.Items{
newItem("c/", "", true),
newItem("c", "c", false),
newItem("b/", "", true),
newItem("a", "a", false),
}},
{"prefix b slash",
storage.IterateOptions{
Prefix: storage.Key("b/"),

View File

@ -61,21 +61,6 @@ func testIterateAll(t *testing.T, store storage.KeyValueStore) {
newItem("g", "g", false),
newItem("h", "h", false),
}},
{"no limits reverse",
storage.IterateOptions{
Recurse: true, Reverse: true,
}, storage.Items{
newItem("h", "h", false),
newItem("g", "g", false),
newItem("c/1", "c/1", false),
newItem("c//", "c//", false),
newItem("c/", "c/", false),
newItem("c", "c", false),
newItem("b/3", "b/3", false),
newItem("b/2", "b/2", false),
newItem("b/1", "b/1", false),
newItem("a", "a", false),
}},
{"at a",
storage.IterateOptions{
@ -93,13 +78,6 @@ func testIterateAll(t *testing.T, store storage.KeyValueStore) {
newItem("g", "g", false),
newItem("h", "h", false),
}},
{"at a reverse",
storage.IterateOptions{
First: storage.Key("a"),
Recurse: true, Reverse: true,
}, storage.Items{
newItem("a", "a", false),
}},
{"after a",
storage.IterateOptions{
@ -180,20 +158,6 @@ func testIterateAll(t *testing.T, store storage.KeyValueStore) {
newItem("g", "g", false),
newItem("h", "h", false),
}},
{"at e reverse",
storage.IterateOptions{
First: storage.Key("e"),
Recurse: true, Reverse: true,
}, storage.Items{
newItem("c/1", "c/1", false),
newItem("c//", "c//", false),
newItem("c/", "c/", false),
newItem("c", "c", false),
newItem("b/3", "b/3", false),
newItem("b/2", "b/2", false),
newItem("b/1", "b/1", false),
newItem("a", "a", false),
}},
{"prefix b slash",
storage.IterateOptions{
@ -221,23 +185,6 @@ func testIterateAll(t *testing.T, store storage.KeyValueStore) {
newItem("b/2", "b/2", false),
newItem("b/3", "b/3", false),
}},
{"reverse prefix b slash",
storage.IterateOptions{
Prefix: storage.Key("b/"),
Recurse: true, Reverse: true,
}, storage.Items{
newItem("b/3", "b/3", false),
newItem("b/2", "b/2", false),
newItem("b/1", "b/1", false),
}},
{"reverse prefix b slash at b slash 2",
storage.IterateOptions{
Prefix: storage.Key("b/"), First: storage.Key("b/2"),
Recurse: true, Reverse: true,
}, storage.Items{
newItem("b/2", "b/2", false),
newItem("b/1", "b/1", false),
}},
{"prefix c slash",
storage.IterateOptions{
@ -248,15 +195,6 @@ func testIterateAll(t *testing.T, store storage.KeyValueStore) {
newItem("c//", "c//", false),
newItem("c/1", "c/1", false),
}},
{"reverse prefix c slash",
storage.IterateOptions{
Prefix: storage.Key("c/"),
Recurse: true, Reverse: true,
}, storage.Items{
newItem("c/1", "c/1", false),
newItem("c//", "c//", false),
newItem("c/", "c/", false),
}},
{"prefix c slash slash",
storage.IterateOptions{
@ -265,12 +203,5 @@ func testIterateAll(t *testing.T, store storage.KeyValueStore) {
}, storage.Items{
newItem("c//", "c//", false),
}},
{"reverse prefix c slash slash",
storage.IterateOptions{
Prefix: storage.Key("c//"),
Recurse: true, Reverse: true,
}, storage.Items{
newItem("c//", "c//", false),
}},
})
}

View File

@ -122,49 +122,6 @@ func testListV2(t *testing.T, store storage.KeyValueStore) {
newItem("my-album/", "", true),
},
},
{"end before 2 recursive",
storage.ListOptions{
Recursive: true,
EndBefore: storage.Key("music/z-song5.mp3"),
Limit: 2,
},
true, storage.Items{
newItem("music/my-album/song3.mp3", "", false),
newItem("music/my-album/song4.mp3", "", false),
},
},
{"end before non-existing 2 recursive",
storage.ListOptions{
Recursive: true,
EndBefore: storage.Key("music/my-album/song5.mp3"),
Limit: 2,
},
true, storage.Items{
newItem("music/my-album/song3.mp3", "", false),
newItem("music/my-album/song4.mp3", "", false),
},
},
{"end before 2",
storage.ListOptions{
Prefix: storage.Key("music/"),
EndBefore: storage.Key("z-song5.mp3"),
Limit: 2,
},
true, storage.Items{
newItem("a-song2.mp3", "", false),
newItem("my-album/", "", true),
},
},
{"end before 2 prefixed",
storage.ListOptions{
Prefix: storage.Key("music/my-album/"),
EndBefore: storage.Key("song4.mp3"),
Limit: 2,
},
false, storage.Items{
newItem("song3.mp3", "", false),
},
},
}
for _, test := range tests {

View File

@ -39,30 +39,12 @@ func testPrefix(t *testing.T, store storage.KeyValueStore) {
newItem("x-b/2", "b/2", false),
newItem("x-b/3", "b/3", false),
}},
{"reverse prefix x dash b slash",
storage.IterateOptions{
Prefix: storage.Key("x-"), First: storage.Key("x-b/3"),
Recurse: true, Reverse: true,
}, storage.Items{
newItem("x-b/3", "b/3", false),
newItem("x-b/2", "b/2", false),
newItem("x-b/1", "b/1", false),
newItem("x-a", "a", false),
}},
{"prefix x dash b slash",
storage.IterateOptions{
Prefix: storage.Key("x-"), First: storage.Key("x-b"),
}, storage.Items{
newItem("x-b/", "", true),
}},
{"reverse x dash b slash",
storage.IterateOptions{
Prefix: storage.Key("x-"), First: storage.Key("x-b/2"),
Reverse: true,
}, storage.Items{
newItem("x-b/", "", true),
newItem("x-a", "a", false),
}},
{"prefix y- slash",
storage.IterateOptions{
Prefix: storage.Key("y-"),

View File

@ -134,7 +134,7 @@ func (client *Client) DeleteSegmentOld(ctx context.Context, bucket string, path
}
// ListSegmentsOld lists the available segments
func (client *Client) ListSegmentsOld(ctx context.Context, bucket string, prefix, startAfter, endBefore storj.Path, recursive bool, limit int32, metaFlags uint32) (items []ListItem, more bool, err error) {
func (client *Client) ListSegmentsOld(ctx context.Context, bucket string, prefix, startAfter, ignoredEndBefore storj.Path, recursive bool, limit int32, metaFlags uint32) (items []ListItem, more bool, err error) {
defer mon.Task()(&ctx)(&err)
response, err := client.client.ListSegmentsOld(ctx, &pb.ListSegmentsRequestOld{
@ -142,7 +142,6 @@ func (client *Client) ListSegmentsOld(ctx context.Context, bucket string, prefix
Bucket: []byte(bucket),
Prefix: []byte(prefix),
StartAfter: []byte(startAfter),
EndBefore: []byte(endBefore),
Recursive: recursive,
Limit: limit,
MetaFlags: metaFlags,

View File

@ -169,15 +169,9 @@ func (db *DB) ListObjects(ctx context.Context, bucket string, options storj.List
prefix: bucket,
}
var startAfter, endBefore string
var startAfter string
switch options.Direction {
// TODO for now we are supporting only storj.After
// case storj.Before:
// // before lists backwards from cursor, without cursor
// endBefore = options.Cursor
// case storj.Backward:
// // backward lists backwards from cursor, including cursor
// endBefore = keyAfter(options.Cursor)
// case storj.Forward:
// // forward lists forwards from cursor, including cursor
// startAfter = keyBefore(options.Cursor)
@ -188,12 +182,7 @@ func (db *DB) ListObjects(ctx context.Context, bucket string, options storj.List
return storj.ObjectList{}, errClass.New("invalid direction %d", options.Direction)
}
// TODO: remove this hack-fix of specifying the last key
if options.Cursor == "" && (options.Direction == storj.Before || options.Direction == storj.Backward) {
endBefore = "\x7f\x7f\x7f\x7f\x7f\x7f\x7f"
}
items, more, err := objects.List(ctx, options.Prefix, startAfter, endBefore, options.Recursive, options.Limit, meta.All)
items, more, err := objects.List(ctx, options.Prefix, startAfter, options.Recursive, options.Limit, meta.All)
if err != nil {
return storj.ObjectList{}, err
}

View File

@ -294,8 +294,6 @@ func TestListObjectsEmpty(t *testing.T) {
// TODO for now we are supporting only storj.After
for _, direction := range []storj.ListDirection{
// storj.Before,
// storj.Backward,
// storj.Forward,
storj.After,
} {
@ -334,311 +332,80 @@ func TestListObjects(t *testing.T) {
result []string
}{
{
options: options("", "", storj.After, 0),
options: options("", "", 0),
result: []string{"a", "a/", "aa", "b", "b/", "bb", "c"},
}, {
options: options("", "`", storj.After, 0),
options: options("", "`", 0),
result: []string{"a", "a/", "aa", "b", "b/", "bb", "c"},
}, {
options: options("", "b", storj.After, 0),
options: options("", "b", 0),
result: []string{"b/", "bb", "c"},
}, {
options: options("", "c", storj.After, 0),
options: options("", "c", 0),
result: []string{},
}, {
options: options("", "ca", storj.After, 0),
options: options("", "ca", 0),
result: []string{},
}, {
options: options("", "", storj.After, 1),
options: options("", "", 1),
more: true,
result: []string{"a"},
}, {
options: options("", "`", storj.After, 1),
options: options("", "`", 1),
more: true,
result: []string{"a"},
}, {
options: options("", "aa", storj.After, 1),
options: options("", "aa", 1),
more: true,
result: []string{"b"},
}, {
options: options("", "c", storj.After, 1),
options: options("", "c", 1),
result: []string{},
}, {
options: options("", "ca", storj.After, 1),
options: options("", "ca", 1),
result: []string{},
}, {
options: options("", "", storj.After, 2),
options: options("", "", 2),
more: true,
result: []string{"a", "a/"},
}, {
options: options("", "`", storj.After, 2),
options: options("", "`", 2),
more: true,
result: []string{"a", "a/"},
}, {
options: options("", "aa", storj.After, 2),
options: options("", "aa", 2),
more: true,
result: []string{"b", "b/"},
}, {
options: options("", "bb", storj.After, 2),
options: options("", "bb", 2),
result: []string{"c"},
}, {
options: options("", "c", storj.After, 2),
options: options("", "c", 2),
result: []string{},
}, {
options: options("", "ca", storj.After, 2),
options: options("", "ca", 2),
result: []string{},
}, {
options: optionsRecursive("", "", storj.After, 0),
options: optionsRecursive("", "", 0),
result: []string{"a", "a/xa", "a/xaa", "a/xb", "a/xbb", "a/xc", "aa", "b", "b/ya", "b/yaa", "b/yb", "b/ybb", "b/yc", "bb", "c"},
}, {
options: options("a", "", storj.After, 0),
options: options("a", "", 0),
result: []string{"xa", "xaa", "xb", "xbb", "xc"},
}, {
options: options("a/", "", storj.After, 0),
options: options("a/", "", 0),
result: []string{"xa", "xaa", "xb", "xbb", "xc"},
}, {
options: options("a/", "xb", storj.After, 0),
options: options("a/", "xb", 0),
result: []string{"xbb", "xc"},
}, {
options: optionsRecursive("", "a/xbb", storj.After, 5),
options: optionsRecursive("", "a/xbb", 5),
more: true,
result: []string{"a/xc", "aa", "b", "b/ya", "b/yaa"},
}, {
options: options("a/", "xaa", storj.After, 2),
options: options("a/", "xaa", 2),
more: true,
result: []string{"xb", "xbb"},
},
// TODO commented until we will decide if we will support direction for object listing
//
// {
// options: options("", "", storj.Forward, 0),
// result: []string{"a", "a/", "aa", "b", "b/", "bb", "c"},
// }, {
// options: options("", "`", storj.Forward, 0),
// result: []string{"a", "a/", "aa", "b", "b/", "bb", "c"},
// }, {
// options: options("", "b", storj.Forward, 0),
// result: []string{"b", "b/", "bb", "c"},
// }, {
// options: options("", "c", storj.Forward, 0),
// result: []string{"c"},
// }, {
// options: options("", "ca", storj.Forward, 0),
// result: []string{},
// }, {
// options: options("", "", storj.Forward, 1),
// more: true,
// result: []string{"a"},
// }, {
// options: options("", "`", storj.Forward, 1),
// more: true,
// result: []string{"a"},
// }, {
// options: options("", "aa", storj.Forward, 1),
// more: true,
// result: []string{"aa"},
// }, {
// options: options("", "c", storj.Forward, 1),
// result: []string{"c"},
// }, {
// options: options("", "ca", storj.Forward, 1),
// result: []string{},
// }, {
// options: options("", "", storj.Forward, 2),
// more: true,
// result: []string{"a", "a/"},
// }, {
// options: options("", "`", storj.Forward, 2),
// more: true,
// result: []string{"a", "a/"},
// }, {
// options: options("", "aa", storj.Forward, 2),
// more: true,
// result: []string{"aa", "b"},
// }, {
// options: options("", "bb", storj.Forward, 2),
// result: []string{"bb", "c"},
// }, {
// options: options("", "c", storj.Forward, 2),
// result: []string{"c"},
// }, {
// options: options("", "ca", storj.Forward, 2),
// result: []string{},
// }, {
// options: optionsRecursive("", "", storj.Forward, 0),
// result: []string{"a", "a/xa", "a/xaa", "a/xb", "a/xbb", "a/xc", "aa", "b", "b/ya", "b/yaa", "b/yb", "b/ybb", "b/yc", "bb", "c"},
// }, {
// options: options("a", "", storj.Forward, 0),
// result: []string{"xa", "xaa", "xb", "xbb", "xc"},
// }, {
// options: options("a/", "", storj.Forward, 0),
// result: []string{"xa", "xaa", "xb", "xbb", "xc"},
// }, {
// options: options("a/", "xb", storj.Forward, 0),
// result: []string{"xb", "xbb", "xc"},
// }, {
// options: optionsRecursive("", "a/xbb", storj.Forward, 5),
// more: true,
// result: []string{"a/xbb", "a/xc", "aa", "b", "b/ya"},
// }, {
// options: options("a/", "xaa", storj.Forward, 2),
// more: true,
// result: []string{"xaa", "xb"},
// }, {
// options: options("", "", storj.Backward, 0),
// result: []string{"a", "a/", "aa", "b", "b/", "bb", "c"},
// }, {
// options: options("", "`", storj.Backward, 0),
// result: []string{},
// }, {
// options: options("", "b", storj.Backward, 0),
// result: []string{"a", "a/", "aa", "b"},
// }, {
// options: options("", "c", storj.Backward, 0),
// result: []string{"a", "a/", "aa", "b", "b/", "bb", "c"},
// }, {
// options: options("", "ca", storj.Backward, 0),
// result: []string{"a", "a/", "aa", "b", "b/", "bb", "c"},
// }, {
// options: options("", "", storj.Backward, 1),
// more: true,
// result: []string{"c"},
// }, {
// options: options("", "`", storj.Backward, 1),
// result: []string{},
// }, {
// options: options("", "aa", storj.Backward, 1),
// more: true,
// result: []string{"aa"},
// }, {
// options: options("", "c", storj.Backward, 1),
// more: true,
// result: []string{"c"},
// }, {
// options: options("", "ca", storj.Backward, 1),
// more: true,
// result: []string{"c"},
// }, {
// options: options("", "", storj.Backward, 2),
// more: true,
// result: []string{"bb", "c"},
// }, {
// options: options("", "`", storj.Backward, 2),
// result: []string{},
// }, {
// options: options("", "a/", storj.Backward, 2),
// result: []string{"a"},
// }, {
// options: options("", "bb", storj.Backward, 2),
// more: true,
// result: []string{"b/", "bb"},
// }, {
// options: options("", "c", storj.Backward, 2),
// more: true,
// result: []string{"bb", "c"},
// }, {
// options: options("", "ca", storj.Backward, 2),
// more: true,
// result: []string{"bb", "c"},
// }, {
// options: optionsRecursive("", "", storj.Backward, 0),
// result: []string{"a", "a/xa", "a/xaa", "a/xb", "a/xbb", "a/xc", "aa", "b", "b/ya", "b/yaa", "b/yb", "b/ybb", "b/yc", "bb", "c"},
// }, {
// options: options("a", "", storj.Backward, 0),
// result: []string{"xa", "xaa", "xb", "xbb", "xc"},
// }, {
// options: options("a/", "", storj.Backward, 0),
// result: []string{"xa", "xaa", "xb", "xbb", "xc"},
// }, {
// options: options("a/", "xb", storj.Backward, 0),
// result: []string{"xa", "xaa", "xb"},
// }, {
// options: optionsRecursive("", "b/yaa", storj.Backward, 5),
// more: true,
// result: []string{"a/xc", "aa", "b", "b/ya", "b/yaa"},
// }, {
// options: options("a/", "xbb", storj.Backward, 2),
// more: true,
// result: []string{"xb", "xbb"},
// }, {
// options: options("", "", storj.Before, 0),
// result: []string{"a", "a/", "aa", "b", "b/", "bb", "c"},
// }, {
// options: options("", "`", storj.Before, 0),
// result: []string{},
// }, {
// options: options("", "a", storj.Before, 0),
// result: []string{},
// }, {
// options: options("", "b", storj.Before, 0),
// result: []string{"a", "a/", "aa"},
// }, {
// options: options("", "c", storj.Before, 0),
// result: []string{"a", "a/", "aa", "b", "b/", "bb"},
// }, {
// options: options("", "ca", storj.Before, 0),
// result: []string{"a", "a/", "aa", "b", "b/", "bb", "c"},
// }, {
// options: options("", "", storj.Before, 1),
// more: true,
// result: []string{"c"},
// }, {
// options: options("", "`", storj.Before, 1),
// result: []string{},
// }, {
// options: options("", "a/", storj.Before, 1),
// result: []string{"a"},
// }, {
// options: options("", "c", storj.Before, 1),
// more: true,
// result: []string{"bb"},
// }, {
// options: options("", "ca", storj.Before, 1),
// more: true,
// result: []string{"c"},
// }, {
// options: options("", "", storj.Before, 2),
// more: true,
// result: []string{"bb", "c"},
// }, {
// options: options("", "`", storj.Before, 2),
// result: []string{},
// }, {
// options: options("", "a/", storj.Before, 2),
// result: []string{"a"},
// }, {
// options: options("", "bb", storj.Before, 2),
// more: true,
// result: []string{"b", "b/"},
// }, {
// options: options("", "c", storj.Before, 2),
// more: true,
// result: []string{"b/", "bb"},
// }, {
// options: options("", "ca", storj.Before, 2),
// more: true,
// result: []string{"bb", "c"},
// }, {
// options: optionsRecursive("", "", storj.Before, 0),
// result: []string{"a", "a/xa", "a/xaa", "a/xb", "a/xbb", "a/xc", "aa", "b", "b/ya", "b/yaa", "b/yb", "b/ybb", "b/yc", "bb", "c"},
// }, {
// options: options("a", "", storj.Before, 0),
// result: []string{"xa", "xaa", "xb", "xbb", "xc"},
// }, {
// options: options("a/", "", storj.Before, 0),
// result: []string{"xa", "xaa", "xb", "xbb", "xc"},
// }, {
// options: options("a/", "xb", storj.Before, 0),
// result: []string{"xa", "xaa"},
// }, {
// options: optionsRecursive("", "b/yaa", storj.Before, 5),
// more: true,
// result: []string{"a/xbb", "a/xc", "aa", "b", "b/ya"},
// }, {
// options: options("a/", "xbb", storj.Before, 2),
// more: true,
// result: []string{"xaa", "xb"},
// },
} {
errTag := fmt.Sprintf("%d. %+v", i, tt)
@ -655,20 +422,20 @@ func TestListObjects(t *testing.T) {
}
})
}
func options(prefix, cursor string, direction storj.ListDirection, limit int) storj.ListOptions {
func options(prefix, cursor string, limit int) storj.ListOptions {
return storj.ListOptions{
Prefix: prefix,
Cursor: cursor,
Direction: direction,
Direction: storj.After,
Limit: limit,
}
}
func optionsRecursive(prefix, cursor string, direction storj.ListDirection, limit int) storj.ListOptions {
func optionsRecursive(prefix, cursor string, limit int) storj.ListOptions {
return storj.ListOptions{
Prefix: prefix,
Cursor: cursor,
Direction: direction,
Direction: storj.After,
Limit: limit,
Recursive: true,
}

View File

@ -59,8 +59,8 @@ func (o *prefixedObjStore) Delete(ctx context.Context, path storj.Path) (err err
return o.store.Delete(ctx, storj.JoinPaths(o.prefix, path))
}
func (o *prefixedObjStore) List(ctx context.Context, prefix, startAfter, endBefore storj.Path, recursive bool, limit int, metaFlags uint32) (items []objects.ListItem, more bool, err error) {
func (o *prefixedObjStore) List(ctx context.Context, prefix, startAfter storj.Path, recursive bool, limit int, metaFlags uint32) (items []objects.ListItem, more bool, err error) {
defer mon.Task()(&ctx)(&err)
return o.store.List(ctx, storj.JoinPaths(o.prefix, prefix), startAfter, endBefore, recursive, limit, metaFlags)
return o.store.List(ctx, storj.JoinPaths(o.prefix, prefix), startAfter, recursive, limit, metaFlags)
}

View File

@ -43,7 +43,7 @@ type Store interface {
Get(ctx context.Context, path storj.Path) (rr ranger.Ranger, meta Meta, err error)
Put(ctx context.Context, path storj.Path, data io.Reader, metadata pb.SerializableMeta, expiration time.Time) (meta Meta, err error)
Delete(ctx context.Context, path storj.Path) (err error)
List(ctx context.Context, prefix, startAfter, endBefore storj.Path, recursive bool, limit int, metaFlags uint32) (items []ListItem, more bool, err error)
List(ctx context.Context, prefix, startAfter storj.Path, recursive bool, limit int, metaFlags uint32) (items []ListItem, more bool, err error)
}
type objStore struct {
@ -123,11 +123,11 @@ func (o *objStore) Delete(ctx context.Context, path storj.Path) (err error) {
return err
}
func (o *objStore) List(ctx context.Context, prefix, startAfter, endBefore storj.Path, recursive bool, limit int, metaFlags uint32) (
func (o *objStore) List(ctx context.Context, prefix, startAfter storj.Path, recursive bool, limit int, metaFlags uint32) (
items []ListItem, more bool, err error) {
defer mon.Task()(&ctx)(&err)
strItems, more, err := o.store.List(ctx, prefix, startAfter, endBefore, o.pathCipher, recursive, limit, metaFlags)
strItems, more, err := o.store.List(ctx, prefix, startAfter, o.pathCipher, recursive, limit, metaFlags)
if err != nil {
return nil, false, err
}

View File

@ -21,7 +21,7 @@ type Store interface {
Get(ctx context.Context, path storj.Path, pathCipher storj.CipherSuite) (ranger.Ranger, Meta, error)
Put(ctx context.Context, path storj.Path, pathCipher storj.CipherSuite, data io.Reader, metadata []byte, expiration time.Time) (Meta, error)
Delete(ctx context.Context, path storj.Path, pathCipher storj.CipherSuite) error
List(ctx context.Context, prefix, startAfter, endBefore storj.Path, pathCipher storj.CipherSuite, recursive bool, limit int, metaFlags uint32) (items []ListItem, more bool, err error)
List(ctx context.Context, prefix, startAfter storj.Path, pathCipher storj.CipherSuite, recursive bool, limit int, metaFlags uint32) (items []ListItem, more bool, err error)
}
type shimStore struct {
@ -66,8 +66,8 @@ func (s *shimStore) Delete(ctx context.Context, path storj.Path, pathCipher stor
}
// List parses the passed in path and dispatches to the typed store.
func (s *shimStore) List(ctx context.Context, prefix storj.Path, startAfter storj.Path, endBefore storj.Path, pathCipher storj.CipherSuite, recursive bool, limit int, metaFlags uint32) (items []ListItem, more bool, err error) {
func (s *shimStore) List(ctx context.Context, prefix storj.Path, startAfter storj.Path, pathCipher storj.CipherSuite, recursive bool, limit int, metaFlags uint32) (items []ListItem, more bool, err error) {
defer mon.Task()(&ctx)(&err)
return s.store.List(ctx, ParsePath(prefix), startAfter, endBefore, pathCipher, recursive, limit, metaFlags)
return s.store.List(ctx, ParsePath(prefix), startAfter, pathCipher, recursive, limit, metaFlags)
}

View File

@ -59,7 +59,7 @@ type typedStore interface {
Get(ctx context.Context, path Path, pathCipher storj.CipherSuite) (ranger.Ranger, Meta, error)
Put(ctx context.Context, path Path, pathCipher storj.CipherSuite, data io.Reader, metadata []byte, expiration time.Time) (Meta, error)
Delete(ctx context.Context, path Path, pathCipher storj.CipherSuite) error
List(ctx context.Context, prefix Path, startAfter, endBefore string, pathCipher storj.CipherSuite, recursive bool, limit int, metaFlags uint32) (items []ListItem, more bool, err error)
List(ctx context.Context, prefix Path, startAfter string, pathCipher storj.CipherSuite, recursive bool, limit int, metaFlags uint32) (items []ListItem, more bool, err error)
}
// streamStore is a store for streams. It implements typedStore as part of an ongoing migration
@ -582,7 +582,7 @@ func pathForKey(raw string) paths.Unencrypted {
}
// List all the paths inside l/, stripping off the l/ prefix
func (s *streamStore) List(ctx context.Context, prefix Path, startAfter, endBefore string, pathCipher storj.CipherSuite, recursive bool, limit int, metaFlags uint32) (items []ListItem, more bool, err error) {
func (s *streamStore) List(ctx context.Context, prefix Path, startAfter string, pathCipher storj.CipherSuite, recursive bool, limit int, metaFlags uint32) (items []ListItem, more bool, err error) {
defer mon.Task()(&ctx)(&err)
// TODO use flags with listing
@ -611,9 +611,9 @@ func (s *streamStore) List(ctx context.Context, prefix Path, startAfter, endBefo
encPrefix = paths.NewEncrypted(encPrefix.Raw()[:lastSlashIdx])
}
// We have to encrypt startAfter and endBefore but only if they don't contain a bucket.
// They contain a bucket if and only if the prefix has no bucket. This is why they are raw
// strings instead of a typed string: it's either a bucket or an unencrypted path component
// We have to encrypt startAfter but only if it doesn't contain a bucket.
// It contains a bucket if and only if the prefix has no bucket. This is why it is a raw
// string instead of a typed string: it's either a bucket or an unencrypted path component
// and that isn't known at compile time.
needsEncryption := prefix.Bucket() != ""
if needsEncryption {

View File

@ -132,7 +132,7 @@ func TestStreamsInterruptedDelete(t *testing.T) {
require.NoError(t, err)
// Ensure the item shows when we list
listItems, _, err := streamStore.List(ctx, bucketName, "", "", storj.EncNull, true, 10, meta.None)
listItems, _, err := streamStore.List(ctx, bucketName, "", storj.EncNull, true, 10, meta.None)
require.NoError(t, err)
require.True(t, len(listItems) == 1)
@ -158,7 +158,7 @@ func TestStreamsInterruptedDelete(t *testing.T) {
// It should *still* show when we list, as we've only deleted one
// segment
listItems, _, err = streamStore.List(ctx, bucketName, "", "", storj.EncNull, true, 10, meta.None)
listItems, _, err = streamStore.List(ctx, bucketName, "", storj.EncNull, true, 10, meta.None)
require.NoError(t, err)
require.True(t, len(listItems) == 1)
@ -168,7 +168,7 @@ func TestStreamsInterruptedDelete(t *testing.T) {
_ = streamStore.Delete(ctx, fullPath, storj.EncNull)
// Now it should have 0 list items
listItems, _, err = streamStore.List(ctx, bucketName, "", "", storj.EncNull, true, 10, meta.None)
listItems, _, err = streamStore.List(ctx, bucketName, "", storj.EncNull, true, 10, meta.None)
require.NoError(t, err)
require.True(t, len(listItems) == 0)
})
@ -203,39 +203,39 @@ func TestStreamStoreList(t *testing.T) {
prefix := bucketName
// should list all
items, more, err := streamStore.List(ctx, prefix, "", "", storj.EncNull, true, 10, meta.None)
items, more, err := streamStore.List(ctx, prefix, "", storj.EncNull, true, 10, meta.None)
require.NoError(t, err)
require.False(t, more)
require.Equal(t, len(objects), len(items))
// should list first two and more = true
items, more, err = streamStore.List(ctx, prefix, "", "", storj.EncNull, true, 2, meta.None)
items, more, err = streamStore.List(ctx, prefix, "", storj.EncNull, true, 2, meta.None)
require.NoError(t, err)
require.True(t, more)
require.Equal(t, 2, len(items))
// should list only prefixes
items, more, err = streamStore.List(ctx, prefix, "", "", storj.EncNull, false, 10, meta.None)
items, more, err = streamStore.List(ctx, prefix, "", storj.EncNull, false, 10, meta.None)
require.NoError(t, err)
require.False(t, more)
require.Equal(t, 2, len(items))
// should list only BBBB bucket
prefix = storj.JoinPaths(bucketName, "bbbb")
items, more, err = streamStore.List(ctx, prefix, "", "", storj.EncNull, false, 10, meta.None)
items, more, err = streamStore.List(ctx, prefix, "", storj.EncNull, false, 10, meta.None)
require.NoError(t, err)
require.False(t, more)
require.Equal(t, 3, len(items))
// should list only BBBB bucket after afile
items, more, err = streamStore.List(ctx, prefix, "afile1", "", storj.EncNull, false, 10, meta.None)
items, more, err = streamStore.List(ctx, prefix, "afile1", storj.EncNull, false, 10, meta.None)
require.NoError(t, err)
require.False(t, more)
require.Equal(t, 2, len(items))
// should list nothing
prefix = storj.JoinPaths(bucketName, "cccc")
items, more, err = streamStore.List(ctx, prefix, "", "", storj.EncNull, true, 10, meta.None)
items, more, err = streamStore.List(ctx, prefix, "", storj.EncNull, true, 10, meta.None)
require.NoError(t, err)
require.False(t, more)
require.Equal(t, 0, len(items))