@@ -6,7 +6,6 @@ package storecache
66import (
77 "bytes"
88 "context"
9- "encoding/binary"
109 "encoding/json"
1110 "fmt"
1211 "io"
@@ -36,7 +35,7 @@ const (
3635 opGetRange = "getrange"
3736 opIter = "iter"
3837 opExists = "exists"
39- opObjectSize = "objectsize "
38+ opAttributes = "attributes "
4039)
4140
4241var errObjNotFound = errors .Errorf ("object not found" )
@@ -291,50 +290,58 @@ func (cb *CachingBucket) GetRange(ctx context.Context, name string, off, length
291290 return r , err
292291}
293292
294- func (cb * CachingBucket ) ObjectSize (ctx context.Context , name string ) (uint64 , error ) {
295- cfgName , cfg := cb .cfg .findObjectSizeConfig (name )
293+ func (cb * CachingBucket ) Attributes (ctx context.Context , name string ) (objstore. ObjectAttributes , error ) {
294+ cfgName , cfg := cb .cfg .findAttributesConfig (name )
296295 if cfg == nil {
297- return cb .Bucket .ObjectSize (ctx , name )
296+ return cb .Bucket .Attributes (ctx , name )
298297 }
299298
300- return cb .cachedObjectSize (ctx , name , cfgName , cfg .cache , cfg .ttl )
299+ return cb .cachedAttributes (ctx , name , cfgName , cfg .cache , cfg .ttl )
301300}
302301
303- func (cb * CachingBucket ) cachedObjectSize (ctx context.Context , name string , cfgName string , cache cache.Cache , ttl time.Duration ) (uint64 , error ) {
304- key := cachingKeyObjectSize (name )
302+ func (cb * CachingBucket ) cachedAttributes (ctx context.Context , name string , cfgName string , cache cache.Cache , ttl time.Duration ) (objstore. ObjectAttributes , error ) {
303+ key := cachingKeyAttributes (name )
305304
306- cb .operationRequests .WithLabelValues (opObjectSize , cfgName ).Inc ()
305+ cb .operationRequests .WithLabelValues (opAttributes , cfgName ).Inc ()
307306
308307 hits := cache .Fetch (ctx , []string {key })
309- if s := hits [key ]; len (s ) == 8 {
310- cb .operationHits .WithLabelValues (opObjectSize , cfgName ).Inc ()
311- return binary .BigEndian .Uint64 (s ), nil
308+ if raw , ok := hits [key ]; ok {
309+ var attrs objstore.ObjectAttributes
310+ err := json .Unmarshal (raw , & attrs )
311+ if err == nil {
312+ cb .operationHits .WithLabelValues (opAttributes , cfgName ).Inc ()
313+ return attrs , nil
314+ }
315+
316+ level .Warn (cb .logger ).Log ("msg" , "failed to decode cached Attributes result" , "key" , key , "err" , err )
312317 }
313318
314- size , err := cb .Bucket .ObjectSize (ctx , name )
319+ attrs , err := cb .Bucket .Attributes (ctx , name )
315320 if err != nil {
316- return 0 , err
321+ return objstore. ObjectAttributes {} , err
317322 }
318323
319- var buf [8 ]byte
320- binary .BigEndian .PutUint64 (buf [:], size )
321- cache .Store (ctx , map [string ][]byte {key : buf [:]}, ttl )
324+ if raw , err := json .Marshal (attrs ); err == nil {
325+ cache .Store (ctx , map [string ][]byte {key : raw }, ttl )
326+ } else {
327+ level .Warn (cb .logger ).Log ("msg" , "failed to encode cached Attributes result" , "key" , key , "err" , err )
328+ }
322329
323- return size , nil
330+ return attrs , nil
324331}
325332
326333func (cb * CachingBucket ) cachedGetRange (ctx context.Context , name string , offset , length int64 , cfgName string , cfg * getRangeConfig ) (io.ReadCloser , error ) {
327334 cb .operationRequests .WithLabelValues (opGetRange , cfgName ).Inc ()
328335 cb .requestedGetRangeBytes .WithLabelValues (cfgName ).Add (float64 (length ))
329336
330- size , err := cb .cachedObjectSize (ctx , name , cfgName , cfg .cache , cfg .objectSizeTTL )
337+ attrs , err := cb .cachedAttributes (ctx , name , cfgName , cfg .cache , cfg .attributesTTL )
331338 if err != nil {
332- return nil , errors .Wrapf (err , "failed to get size of object: %s" , name )
339+ return nil , errors .Wrapf (err , "failed to get object attributes : %s" , name )
333340 }
334341
335342 // If length goes over object size, adjust length. We use it later to limit number of read bytes.
336- if uint64 ( offset + length ) > size {
337- length = int64 ( size - uint64 ( offset ))
343+ if offset + length > attrs . Size {
344+ length = attrs . Size - offset
338345 }
339346
340347 // Start and end range are subrange-aligned offsets into object, that we're going to read.
@@ -347,9 +354,9 @@ func (cb *CachingBucket) cachedGetRange(ctx context.Context, name string, offset
347354 // The very last subrange in the object may have length that is not divisible by subrange size.
348355 lastSubrangeOffset := endRange - cfg .subrangeSize
349356 lastSubrangeLength := int (cfg .subrangeSize )
350- if uint64 ( endRange ) > size {
351- lastSubrangeOffset = (int64 ( size ) / cfg .subrangeSize ) * cfg .subrangeSize
352- lastSubrangeLength = int (int64 ( size ) - lastSubrangeOffset )
357+ if endRange > attrs . Size {
358+ lastSubrangeOffset = (attrs . Size / cfg .subrangeSize ) * cfg .subrangeSize
359+ lastSubrangeLength = int (attrs . Size - lastSubrangeOffset )
353360 }
354361
355362 numSubranges := (endRange - startRange ) / cfg .subrangeSize
@@ -360,8 +367,8 @@ func (cb *CachingBucket) cachedGetRange(ctx context.Context, name string, offset
360367 totalRequestedBytes := int64 (0 )
361368 for off := startRange ; off < endRange ; off += cfg .subrangeSize {
362369 end := off + cfg .subrangeSize
363- if end > int64 ( size ) {
364- end = int64 ( size )
370+ if end > attrs . Size {
371+ end = attrs . Size
365372 }
366373 totalRequestedBytes += (end - off )
367374
@@ -489,8 +496,8 @@ func mergeRanges(input []rng, limit int64) []rng {
489496 return input [:last + 1 ]
490497}
491498
492- func cachingKeyObjectSize (name string ) string {
493- return fmt .Sprintf ("size :%s" , name )
499+ func cachingKeyAttributes (name string ) string {
500+ return fmt .Sprintf ("attrs :%s" , name )
494501}
495502
496503func cachingKeyObjectSubrange (name string , start int64 , end int64 ) string {
0 commit comments