@ -615,13 +615,18 @@ func (er *erasureObjects) listPath(ctx context.Context, o listPathOptions) (entr
}
}
// Create output for our results.
// Create output for our results.
cacheCh := make ( chan metaCacheEntry , metacacheBlockSize )
var cacheCh chan metaCacheEntry
if ! o . discardResult {
cacheCh = make ( chan metaCacheEntry , metacacheBlockSize )
}
// Create filter for results.
// Create filter for results.
filterCh := make ( chan metaCacheEntry , 100 )
filterCh := make ( chan metaCacheEntry , 100 )
filteredResults := o . gatherResults ( filterCh )
filteredResults := o . gatherResults ( filterCh )
closeChannels := func ( ) {
closeChannels := func ( ) {
close ( cacheCh )
if ! o . discardResult {
close ( cacheCh )
}
close ( filterCh )
close ( filterCh )
}
}
@ -657,54 +662,62 @@ func (er *erasureObjects) listPath(ctx context.Context, o listPathOptions) (entr
} ( )
} ( )
const retryDelay = 200 * time . Millisecond
const retryDelay = 200 * time . Millisecond
const maxTries = 10
const maxTries = 5
// Write results to disk.
var bw * metacacheBlockWriter
bw := newMetacacheBlockWriter ( cacheCh , func ( b * metacacheBlock ) error {
// Don't save single object listings.
if o . discardResult {
if ! o . discardResult {
// Don't save single object listings.
// Write results to disk.
return nil
bw = newMetacacheBlockWriter ( cacheCh , func ( b * metacacheBlock ) error {
}
// if the block is 0 bytes and its a first block skip it.
o . debugln ( "listPath: saving block" , b . n , "to" , o . objectPath ( b . n ) )
// skip only this for Transient caches.
r , err := hash . NewReader ( bytes . NewBuffer ( b . data ) , int64 ( len ( b . data ) ) , "" , "" , int64 ( len ( b . data ) ) , false )
if len ( b . data ) == 0 && b . n == 0 && o . Transient {
logger . LogIf ( ctx , err )
return nil
custom := b . headerKV ( )
_ , err = er . putObject ( ctx , minioMetaBucket , o . objectPath ( b . n ) , NewPutObjReader ( r , nil , nil ) , ObjectOptions { UserDefined : custom } )
if err != nil {
metaMu . Lock ( )
if meta . error != "" {
meta . status = scanStateError
meta . error = err . Error ( )
}
metaMu . Unlock ( )
cancel ( )
return err
}
if b . n == 0 {
return nil
}
// Update block 0 metadata.
var retries int
for {
err := er . updateObjectMeta ( ctx , minioMetaBucket , o . objectPath ( 0 ) , b . headerKV ( ) , ObjectOptions { } )
if err == nil {
break
}
}
switch err . ( type ) {
o . debugln ( "listPath: saving block" , b . n , "to" , o . objectPath ( b . n ) )
case ObjectNotFound :
r , err := hash . NewReader ( bytes . NewReader ( b . data ) , int64 ( len ( b . data ) ) , "" , "" , int64 ( len ( b . data ) ) , false )
logger . LogIf ( ctx , err )
custom := b . headerKV ( )
_ , err = er . putObject ( ctx , minioMetaBucket , o . objectPath ( b . n ) , NewPutObjReader ( r , nil , nil ) , ObjectOptions {
UserDefined : custom ,
NoLock : true , // No need to hold namespace lock, each prefix caches uniquely.
} )
if err != nil {
metaMu . Lock ( )
if meta . error != "" {
meta . status = scanStateError
meta . error = err . Error ( )
}
metaMu . Unlock ( )
cancel ( )
return err
return err
case InsufficientReadQuorum :
default :
logger . LogIf ( ctx , err )
}
}
if retries >= maxTries {
if b . n == 0 {
return err
return nil
}
}
retries ++
// Update block 0 metadata.
time . Sleep ( retryDelay )
var retries int
}
for {
return nil
err := er . updateObjectMeta ( ctx , minioMetaBucket , o . objectPath ( 0 ) , b . headerKV ( ) , ObjectOptions { } )
} )
if err == nil {
break
}
switch err . ( type ) {
case ObjectNotFound :
return err
case InsufficientReadQuorum :
default :
logger . LogIf ( ctx , err )
}
if retries >= maxTries {
return err
}
retries ++
time . Sleep ( retryDelay )
}
return nil
} )
}
// How to resolve results.
// How to resolve results.
resolver := metadataResolutionParams {
resolver := metadataResolutionParams {
@ -721,14 +734,18 @@ func (er *erasureObjects) listPath(ctx context.Context, o listPathOptions) (entr
filterPrefix : o . FilterPrefix ,
filterPrefix : o . FilterPrefix ,
minDisks : listingQuorum ,
minDisks : listingQuorum ,
agreed : func ( entry metaCacheEntry ) {
agreed : func ( entry metaCacheEntry ) {
cacheCh <- entry
if ! o . discardResult {
cacheCh <- entry
}
filterCh <- entry
filterCh <- entry
} ,
} ,
partial : func ( entries metaCacheEntries , nAgreed int , errs [ ] error ) {
partial : func ( entries metaCacheEntries , nAgreed int , errs [ ] error ) {
// Results Disagree :-(
// Results Disagree :-(
entry , ok := entries . resolve ( & resolver )
entry , ok := entries . resolve ( & resolver )
if ok {
if ok {
cacheCh <- * entry
if ! o . discardResult {
cacheCh <- * entry
}
filterCh <- * entry
filterCh <- * entry
}
}
} ,
} ,
@ -749,12 +766,14 @@ func (er *erasureObjects) listPath(ctx context.Context, o listPathOptions) (entr
metaMu . Unlock ( )
metaMu . Unlock ( )
closeChannels ( )
closeChannels ( )
if err := bw . Close ( ) ; err != nil {
if ! o . discardResult {
metaMu . Lock ( )
if err := bw . Close ( ) ; err != nil {
meta . error = err . Error ( )
metaMu . Lock ( )
meta . status = scanStateError
meta . error = err . Error ( )
meta , err = o . updateMetacacheListing ( meta , rpc )
meta . status = scanStateError
metaMu . Unlock ( )
meta , err = o . updateMetacacheListing ( meta , rpc )
metaMu . Unlock ( )
}
}
}
} ( )
} ( )