@@ -34,6 +34,8 @@ const (
34
34
attrIDFixedLen = 1 + oid .Size + utf8DelimiterLen // prefix first
35
35
)
36
36
37
+ const binPropMarker = "1" // ROOT, PHY, etc.
38
+
37
39
var (
38
40
maxUint256 = new (big.Int ).SetBytes ([]byte {255 , 255 , 255 , 255 , 255 , 255 , 255 , 255 , 255 , 255 , 255 , 255 , 255 , 255 , 255 , 255 ,
39
41
255 , 255 , 255 , 255 , 255 , 255 , 255 , 255 , 255 , 255 , 255 , 255 , 255 , 255 , 255 , 255 })
@@ -45,10 +47,10 @@ func invalidMetaBucketKeyErr(key []byte, cause error) error {
45
47
}
46
48
47
49
// TODO: fill on migration.
48
- // TODO: ROOT and PHY props.
49
50
// TODO: cleaning on obj removal.
50
51
func putMetadata (tx * bbolt.Tx , cnr cid.ID , id oid.ID , ver version.Version , owner user.ID , typ object.Type , creationEpoch uint64 ,
51
- payloadLen uint64 , pldHash , pldHmmHash , splitID []byte , parentID , firstID oid.ID , attrs []object.Attribute ) error {
52
+ payloadLen uint64 , pldHash , pldHmmHash , splitID []byte , parentID , firstID oid.ID , attrs []object.Attribute ,
53
+ root , phy bool ) error {
52
54
metaBkt , err := tx .CreateBucketIfNotExists (metaBucketKey (cnr ))
53
55
if err != nil {
54
56
return fmt .Errorf ("create meta bucket for container: %w" , err )
@@ -96,6 +98,16 @@ func putMetadata(tx *bbolt.Tx, cnr cid.ID, id oid.ID, ver version.Version, owner
96
98
return err
97
99
}
98
100
}
101
+ if root {
102
+ if err = putPlainAttribute (metaBkt , & keyBuf , id , object .FilterRoot , binPropMarker ); err != nil {
103
+ return err
104
+ }
105
+ }
106
+ if phy {
107
+ if err = putPlainAttribute (metaBkt , & keyBuf , id , object .FilterPhysical , binPropMarker ); err != nil {
108
+ return err
109
+ }
110
+ }
99
111
for i := range attrs {
100
112
ak , av := attrs [i ].Key (), attrs [i ].Value ()
101
113
if n , isInt := parseInt (av ); isInt && n .Cmp (maxUint256Neg ) >= 0 && n .Cmp (maxUint256 ) <= 0 {
@@ -195,7 +207,7 @@ func (db *DB) search(cnr cid.ID, fs object.SearchFilters, attrs []string, cursor
195
207
func (db * DB ) searchInBucket (metaBkt * bbolt.Bucket , fs object.SearchFilters , attrs []string ,
196
208
cursor * SearchCursor , count uint16 ) ([]client.SearchResultItem , * SearchCursor , error ) {
197
209
// TODO: make as much as possible outside the Bolt tx
198
- primMatcher := fs [0 ]. Operation ( )
210
+ primMatcher , primVal := convertFilterValue ( fs [0 ])
199
211
intPrimMatcher := isNumericOp (primMatcher )
200
212
notPresentPrimMatcher := primMatcher == object .MatchNotPresent
201
213
primAttr := fs [0 ].Header () // attribute emptiness already prevented
@@ -223,7 +235,7 @@ func (db *DB) searchInBucket(metaBkt *bbolt.Bucket, fs object.SearchFilters, att
223
235
if primMatcher == object .MatchStringEqual || primMatcher == object .MatchCommonPrefix ||
224
236
primMatcher == object .MatchNumGT || primMatcher == object .MatchNumGE {
225
237
var err error
226
- if primSeekKey , primSeekPrefix , err = seekKeyForAttribute (primAttr , fs [ 0 ]. Value () ); err != nil {
238
+ if primSeekKey , primSeekPrefix , err = seekKeyForAttribute (primAttr , primVal ); err != nil {
227
239
return nil , nil , fmt .Errorf ("invalid primary filter value: %w" , err )
228
240
}
229
241
} else {
@@ -279,11 +291,12 @@ nextPrimKey:
279
291
if i > 0 && attr != primAttr {
280
292
continue
281
293
}
282
- checkedDBVal , fltVal , err := combineValues (attr , dbVal , fs [i ].Value ()) // TODO: deduplicate DB value preparation
294
+ mch , val := convertFilterValue (fs [i ])
295
+ checkedDBVal , fltVal , err := combineValues (attr , dbVal , val ) // TODO: deduplicate DB value preparation
283
296
if err != nil {
284
297
return nil , nil , fmt .Errorf ("invalid key in meta bucket: invalid attribute %s value: %w" , attr , err )
285
298
}
286
- if ! matchValues (checkedDBVal , fs [ i ]. Operation () , fltVal ) {
299
+ if ! matchValues (checkedDBVal , mch , fltVal ) {
287
300
continue nextPrimKey
288
301
}
289
302
// TODO: attribute value can be requested, it can be collected here, or we can
@@ -311,7 +324,7 @@ nextPrimKey:
311
324
if j > 0 && fs [j ].Header () != attr {
312
325
continue
313
326
}
314
- m := fs [j ]. Operation ( )
327
+ m , val := convertFilterValue ( fs [j ])
315
328
if dbVal == nil {
316
329
if m == object .MatchNotPresent {
317
330
continue
@@ -347,7 +360,7 @@ nextPrimKey:
347
360
} else {
348
361
checkedDBVal = dbVal
349
362
}
350
- checkedDBVal , fltVal , err := combineValues (attr , checkedDBVal , fs [ j ]. Value () ) // TODO: deduplicate DB value preparation
363
+ checkedDBVal , fltVal , err := combineValues (attr , checkedDBVal , val ) // TODO: deduplicate DB value preparation
351
364
if err != nil {
352
365
return nil , nil , invalidMetaBucketKeyErr (primKey , fmt .Errorf ("invalid attribute %s value: %w" , attr , err ))
353
366
}
@@ -507,7 +520,7 @@ func seekKeyForAttribute(attr, fltVal string) ([]byte, []byte, error) {
507
520
return nil , nil , fmt .Errorf ("decode %q UUID attribute: %w" , attr , err )
508
521
}
509
522
dbVal = uid [:]
510
- case object .FilterVersion , object .FilterType :
523
+ case object .FilterVersion , object .FilterType , object . FilterRoot , object . FilterPhysical :
511
524
}
512
525
key := make ([]byte , 1 + len (attr )+ utf8DelimiterLen + len (dbVal )) // prefix 1st
513
526
key [0 ] = metaPrefixAttrIDPlain
@@ -794,3 +807,10 @@ func (x *metaAttributeSeeker) restoreVal(id []byte, attr string, stored []byte)
794
807
}
795
808
return string (stored ), nil
796
809
}
810
+
811
+ func convertFilterValue (f object.SearchFilter ) (object.SearchMatchType , string ) {
812
+ if attr := f .Header (); attr == object .FilterRoot || attr == object .FilterPhysical {
813
+ return object .MatchStringEqual , binPropMarker
814
+ }
815
+ return f .Operation (), f .Value ()
816
+ }
0 commit comments