@ -29,6 +29,7 @@ import (
"sync"
"sync"
"time"
"time"
jsoniter "github.com/json-iterator/go"
"github.com/minio/minio/cmd/logger"
"github.com/minio/minio/cmd/logger"
"github.com/minio/minio/pkg/console"
"github.com/minio/minio/pkg/console"
"github.com/minio/minio/pkg/hash"
"github.com/minio/minio/pkg/hash"
@ -122,11 +123,22 @@ func (o listPathOptions) newMetacache() metacache {
}
}
}
}
func ( o * listPathOptions ) debugf ( format string , data ... interface { } ) {
if metacacheDebug {
console . Debugf ( format , data ... )
}
}
func ( o * listPathOptions ) debugln ( data ... interface { } ) {
if metacacheDebug {
console . Debugln ( data ... )
}
}
// gatherResults will collect all results on the input channel and filter results according to the options.
// gatherResults will collect all results on the input channel and filter results according to the options.
// Caller should close the channel when done.
// Caller should close the channel when done.
// The returned function will return the results once there is enough or input is closed.
// The returned function will return the results once there is enough or input is closed.
func ( o * listPathOptions ) gatherResults ( in <- chan metaCacheEntry ) func ( ) ( metaCacheEntriesSorted , error ) {
func ( o * listPathOptions ) gatherResults ( in <- chan metaCacheEntry ) func ( ) ( metaCacheEntriesSorted , error ) {
const debugPrint = false
var resultsDone = make ( chan metaCacheEntriesSorted )
var resultsDone = make ( chan metaCacheEntriesSorted )
// Copy so we can mutate
// Copy so we can mutate
resCh := resultsDone
resCh := resultsDone
@ -142,32 +154,22 @@ func (o *listPathOptions) gatherResults(in <-chan metaCacheEntry) func() (metaCa
if ! o . IncludeDirectories && entry . isDir ( ) {
if ! o . IncludeDirectories && entry . isDir ( ) {
continue
continue
}
}
if debugPrint {
o . debugln ( "gather got:" , entry . name )
console . Infoln ( "gather got:" , entry . name )
}
if o . Marker != "" && entry . name <= o . Marker {
if o . Marker != "" && entry . name <= o . Marker {
if debugPrint {
o . debugln ( "pre marker" )
console . Infoln ( "pre marker" )
}
continue
continue
}
}
if ! strings . HasPrefix ( entry . name , o . Prefix ) {
if ! strings . HasPrefix ( entry . name , o . Prefix ) {
if debugPrint {
o . debugln ( "not in prefix" )
console . Infoln ( "not in prefix" )
}
continue
continue
}
}
if ! o . Recursive && ! entry . isInDir ( o . Prefix , o . Separator ) {
if ! o . Recursive && ! entry . isInDir ( o . Prefix , o . Separator ) {
if debugPrint {
o . debugln ( "not in dir" , o . Prefix , o . Separator )
console . Infoln ( "not in dir" , o . Prefix , o . Separator )
}
continue
continue
}
}
if ! o . InclDeleted && entry . isObject ( ) {
if ! o . InclDeleted && entry . isObject ( ) {
if entry . isLatestDeletemarker ( ) {
if entry . isLatestDeletemarker ( ) {
if debugPrint {
o . debugln ( "latest delete" )
console . Infoln ( "latest delete" )
}
continue
continue
}
}
}
}
@ -181,9 +183,7 @@ func (o *listPathOptions) gatherResults(in <-chan metaCacheEntry) func() (metaCa
}
}
continue
continue
}
}
if debugPrint {
o . debugln ( "adding..." )
console . Infoln ( "adding..." )
}
results . o = append ( results . o , entry )
results . o = append ( results . o , entry )
}
}
if resCh != nil {
if resCh != nil {
@ -207,19 +207,15 @@ func (o *listPathOptions) findFirstPart(fi FileInfo) (int, error) {
if search == "" {
if search == "" {
return 0 , nil
return 0 , nil
}
}
const debugPrint = false
o . debugln ( "searching for " , search )
if debugPrint {
console . Infoln ( "searching for " , search )
}
var tmp metacacheBlock
var tmp metacacheBlock
var json = jsoniter . ConfigCompatibleWithStandardLibrary
i := 0
i := 0
for {
for {
partKey := fmt . Sprintf ( "%s-metacache-part-%d" , ReservedMetadataPrefixLower , i )
partKey := fmt . Sprintf ( "%s-metacache-part-%d" , ReservedMetadataPrefixLower , i )
v , ok := fi . Metadata [ partKey ]
v , ok := fi . Metadata [ partKey ]
if ! ok {
if ! ok {
if debugPrint {
o . debugln ( "no match in metadata, waiting" )
console . Infoln ( "no match in metadata, waiting" )
}
return - 1 , io . ErrUnexpectedEOF
return - 1 , io . ErrUnexpectedEOF
}
}
err := json . Unmarshal ( [ ] byte ( v ) , & tmp )
err := json . Unmarshal ( [ ] byte ( v ) , & tmp )
@ -231,27 +227,18 @@ func (o *listPathOptions) findFirstPart(fi FileInfo) (int, error) {
return 0 , errFileNotFound
return 0 , errFileNotFound
}
}
if tmp . First >= search {
if tmp . First >= search {
if debugPrint {
o . debugln ( "First >= search" , v )
console . Infoln ( "First >= search" , v )
}
return i , nil
return i , nil
}
}
if tmp . Last >= search {
if tmp . Last >= search {
if debugPrint {
o . debugln ( "Last >= search" , v )
console . Infoln ( "Last >= search" , v )
}
return i , nil
return i , nil
}
}
if tmp . EOS {
if tmp . EOS {
if debugPrint {
o . debugln ( "no match, at EOS" , v )
console . Infoln ( "no match, at EOS" , v )
}
return - 3 , io . EOF
return - 3 , io . EOF
}
}
if debugPrint {
o . debugln ( "First " , tmp . First , "<" , search , " search" , i )
console . Infoln ( "First " , tmp . First , "<" , search , " search" , i )
}
i ++
i ++
}
}
}
}
@ -314,7 +301,6 @@ func (o *listPathOptions) SetFilter() {
// Will return io.EOF if there are no more entries with the same filter.
// Will return io.EOF if there are no more entries with the same filter.
// The last entry can be used as a marker to resume the listing.
// The last entry can be used as a marker to resume the listing.
func ( r * metacacheReader ) filter ( o listPathOptions ) ( entries metaCacheEntriesSorted , err error ) {
func ( r * metacacheReader ) filter ( o listPathOptions ) ( entries metaCacheEntriesSorted , err error ) {
const debugPrint = false
// Forward to prefix, if any
// Forward to prefix, if any
err = r . forwardTo ( o . Prefix )
err = r . forwardTo ( o . Prefix )
if err != nil {
if err != nil {
@ -336,9 +322,8 @@ func (r *metacacheReader) filter(o listPathOptions) (entries metaCacheEntriesSor
}
}
}
}
}
}
if debugPrint {
o . debugln ( "forwarded to " , o . Prefix , "marker:" , o . Marker , "sep:" , o . Separator )
console . Infoln ( "forwarded to " , o . Prefix , "marker:" , o . Marker , "sep:" , o . Separator )
}
// Filter
// Filter
if ! o . Recursive {
if ! o . Recursive {
entries . o = make ( metaCacheEntries , 0 , o . Limit )
entries . o = make ( metaCacheEntries , 0 , o . Limit )
@ -557,10 +542,7 @@ func (er erasureObjects) SetDriveCount() int {
// Will return io.EOF if continuing would not yield more results.
// Will return io.EOF if continuing would not yield more results.
func ( er * erasureObjects ) listPath ( ctx context . Context , o listPathOptions ) ( entries metaCacheEntriesSorted , err error ) {
func ( er * erasureObjects ) listPath ( ctx context . Context , o listPathOptions ) ( entries metaCacheEntriesSorted , err error ) {
const debugPrint = false
o . debugf ( "listPath with options: %#v\n" , o )
if debugPrint {
console . Printf ( "listPath with options: %#v\n" , o )
}
// See if we have the listing stored.
// See if we have the listing stored.
if ! o . Create && ! o . singleObject {
if ! o . Create && ! o . singleObject {
@ -586,9 +568,7 @@ func (er *erasureObjects) listPath(ctx context.Context, o listPathOptions) (entr
rpc := globalNotificationSys . restClientFromHash ( o . Bucket )
rpc := globalNotificationSys . restClientFromHash ( o . Bucket )
var metaMu sync . Mutex
var metaMu sync . Mutex
if debugPrint {
o . debugln ( "listPath: scanning bucket:" , o . Bucket , "basedir:" , o . BaseDir , "prefix:" , o . Prefix , "marker:" , o . Marker )
console . Println ( "listPath: scanning bucket:" , o . Bucket , "basedir:" , o . BaseDir , "prefix:" , o . Prefix , "marker:" , o . Marker )
}
// Disconnect from call above, but cancel on exit.
// Disconnect from call above, but cancel on exit.
ctx , cancel := context . WithCancel ( GlobalContext )
ctx , cancel := context . WithCancel ( GlobalContext )
@ -596,9 +576,7 @@ func (er *erasureObjects) listPath(ctx context.Context, o listPathOptions) (entr
disks := er . getOnlineDisks ( )
disks := er . getOnlineDisks ( )
defer func ( ) {
defer func ( ) {
if debugPrint {
o . debugln ( "listPath returning:" , entries . len ( ) , "err:" , err )
console . Println ( "listPath returning:" , entries . len ( ) , "err:" , err )
}
if err != nil && ! errors . Is ( err , io . EOF ) {
if err != nil && ! errors . Is ( err , io . EOF ) {
go func ( err string ) {
go func ( err string ) {
metaMu . Lock ( )
metaMu . Lock ( )
@ -684,9 +662,7 @@ func (er *erasureObjects) listPath(ctx context.Context, o listPathOptions) (entr
// Don't save single object listings.
// Don't save single object listings.
return nil
return nil
}
}
if debugPrint {
o . debugln ( "listPath: saving block" , b . n , "to" , o . objectPath ( b . n ) )
console . Println ( "listPath: saving block" , b . n , "to" , o . objectPath ( b . n ) )
}
r , err := hash . NewReader ( bytes . NewBuffer ( b . data ) , int64 ( len ( b . data ) ) , "" , "" , int64 ( len ( b . data ) ) , false )
r , err := hash . NewReader ( bytes . NewBuffer ( b . data ) , int64 ( len ( b . data ) ) , "" , "" , int64 ( len ( b . data ) ) , false )
logger . LogIf ( ctx , err )
logger . LogIf ( ctx , err )
custom := b . headerKV ( )
custom := b . headerKV ( )