@ -23,7 +23,6 @@ import (
"fmt"
"io"
"io/ioutil"
"net/url"
"os"
"path/filepath"
"strconv"
@ -421,6 +420,42 @@ func (fs Filesystem) CompleteMultipartUpload(bucket, object, uploadID string, pa
return newObject , nil
}
func ( fs * Filesystem ) saveListMultipartObjectCh ( params listMultipartObjectParams , ch multipartObjectInfoChannel ) {
fs . listMultipartObjectMapMutex . Lock ( )
defer fs . listMultipartObjectMapMutex . Unlock ( )
channels := [ ] multipartObjectInfoChannel { ch }
if _ , ok := fs . listMultipartObjectMap [ params ] ; ok {
channels = append ( fs . listMultipartObjectMap [ params ] , ch )
}
fs . listMultipartObjectMap [ params ] = channels
}
func ( fs * Filesystem ) lookupListMultipartObjectCh ( params listMultipartObjectParams ) * multipartObjectInfoChannel {
fs . listMultipartObjectMapMutex . Lock ( )
defer fs . listMultipartObjectMapMutex . Unlock ( )
if channels , ok := fs . listMultipartObjectMap [ params ] ; ok {
for i , channel := range channels {
if ! channel . IsTimedOut ( ) {
chs := channels [ i + 1 : ]
if len ( chs ) > 0 {
fs . listMultipartObjectMap [ params ] = chs
} else {
delete ( fs . listMultipartObjectMap , params )
}
return & channel
}
}
// As all channels are timed out, delete the map entry
delete ( fs . listMultipartObjectMap , params )
}
return nil
}
// ListMultipartUploads - list incomplete multipart sessions for a given BucketMultipartResourcesMetadata
func ( fs Filesystem ) ListMultipartUploads ( bucket , objectPrefix , keyMarker , uploadIDMarker , delimiter string , maxUploads int ) ( ListMultipartsInfo , * probe . Error ) {
result := ListMultipartsInfo { }
@ -442,13 +477,6 @@ func (fs Filesystem) ListMultipartUploads(bucket, objectPrefix, keyMarker, uploa
return result , probe . NewError ( fmt . Errorf ( "delimiter '%s' is not supported" , delimiter ) )
}
// Unescape keyMarker string
if tmpKeyMarker , err := url . QueryUnescape ( keyMarker ) ; err == nil {
keyMarker = tmpKeyMarker
} else {
return result , probe . NewError ( err )
}
if keyMarker != "" && ! strings . HasPrefix ( keyMarker , objectPrefix ) {
return result , probe . NewError ( fmt . Errorf ( "Invalid combination of marker '%s' and prefix '%s'" , keyMarker , objectPrefix ) )
}
@ -490,48 +518,48 @@ func (fs Filesystem) ListMultipartUploads(bucket, objectPrefix, keyMarker, uploa
bucketDir := filepath . Join ( fs . path , bucket )
// If listMultipartObjectChannel is available for given parameters, then use it, else create new one
o bjectInfoCh := fs . po pListMultipartObjectCh( listMultipartObjectParams { bucket , delimiter , markerPath , prefixPath , uploadIDMarker } )
if o bjectInfoCh == nil {
multipartO bjectInfoCh := fs . looku pListMultipartObjectCh( listMultipartObjectParams { bucket , delimiter , markerPath , prefixPath , uploadIDMarker } )
if multipartO bjectInfoCh == nil {
ch := scanMultipartDir ( bucketDir , objectPrefix , keyMarker , uploadIDMarker , recursive )
o bjectInfoCh = & ch
multipartO bjectInfoCh = & ch
}
nextKeyMarker := ""
nextUploadIDMarker := ""
for i := 0 ; i < maxUploads ; {
o bjInfo, ok := o bjectInfoCh. Read ( )
multipartO bjInfo, ok := multipartO bjectInfoCh. Read ( )
if ! ok {
// Closed channel.
return result , nil
}
if o bjInfo. Err != nil {
return ListMultipartsInfo { } , probe . NewError ( o bjInfo. Err )
if multipartO bjInfo. Err != nil {
return ListMultipartsInfo { } , probe . NewError ( multipartO bjInfo. Err )
}
if strings . Contains ( o bjInfo. Name , "$multiparts" ) || strings . Contains ( o bjInfo. Name , "$tmpobject" ) {
if strings . Contains ( multipartO bjInfo. Name , "$multiparts" ) || strings . Contains ( multipartO bjInfo. Name , "$tmpobject" ) {
continue
}
if o bjInfo. IsDir && skipDir {
if multipartO bjInfo. IsDir && skipDir {
continue
}
if o bjInfo. IsDir {
result . CommonPrefixes = append ( result . CommonPrefixes , o bjInfo. Name )
if multipartO bjInfo. IsDir {
result . CommonPrefixes = append ( result . CommonPrefixes , multipartO bjInfo. Name )
} else {
result . Uploads = append ( result . Uploads , uploadMetadata { Object : o bjInfo. Name , UploadID : o bjInfo. UploadID , Initiated : o bjInfo. ModifiedTime } )
result . Uploads = append ( result . Uploads , uploadMetadata { Object : multipartO bjInfo. Name , UploadID : multipartO bjInfo. UploadID , Initiated : multipartO bjInfo. ModifiedTime } )
}
nextKeyMarker = o bjInfo. Name
nextUploadIDMarker = o bjInfo. UploadID
nextKeyMarker = multipartO bjInfo. Name
nextUploadIDMarker = multipartO bjInfo. UploadID
i ++
}
if ! o bjectInfoCh. IsClosed ( ) {
if ! multipartO bjectInfoCh. IsClosed ( ) {
result . IsTruncated = true
result . NextKeyMarker = nextKeyMarker
result . NextUploadIDMarker = nextUploadIDMarker
fs . push ListMultipartObjectCh( listMultipartObjectParams { bucket , delimiter , nextKeyMarker , objectPrefix , nextUploadIDMarker } , * o bjectInfoCh)
fs . save ListMultipartObjectCh( listMultipartObjectParams { bucket , delimiter , nextKeyMarker , objectPrefix , nextUploadIDMarker } , * multipartO bjectInfoCh)
}
return result , nil