Use getObjectInfo() in both FS and XL ListObjects() to simplify and to return complete object information (#3247)

master
Anis Elleuch 8 years ago committed by Harshavardhana
parent 716316f711
commit 380d6c6435
  1. 47
      cmd/fs-v1.go
  2. 41
      cmd/object-api-listobjects_test.go
  3. 3
      cmd/storage-datatypes.go
  4. 8
      cmd/xl-v1-list-objects.go

@ -24,7 +24,6 @@ import (
"fmt" "fmt"
"hash" "hash"
"io" "io"
"os"
"path" "path"
"sort" "sort"
"strings" "strings"
@ -502,27 +501,17 @@ func (fs fsObjects) DeleteObject(bucket, object string) error {
// ListObjects - list all objects at prefix upto maxKeys., optionally delimited by '/'. Maintains the list pool // ListObjects - list all objects at prefix upto maxKeys., optionally delimited by '/'. Maintains the list pool
// state for future re-entrant list requests. // state for future re-entrant list requests.
func (fs fsObjects) ListObjects(bucket, prefix, marker, delimiter string, maxKeys int) (ListObjectsInfo, error) { func (fs fsObjects) ListObjects(bucket, prefix, marker, delimiter string, maxKeys int) (ListObjectsInfo, error) {
// Convert entry to FileInfo // Convert entry to ObjectInfo
entryToFileInfo := func(entry string) (fileInfo FileInfo, err error) { entryToObjectInfo := func(entry string) (objInfo ObjectInfo, err error) {
if strings.HasSuffix(entry, slashSeparator) { if strings.HasSuffix(entry, slashSeparator) {
// Object name needs to be full path. // Object name needs to be full path.
fileInfo.Name = entry objInfo.Name = entry
fileInfo.Mode = os.ModeDir objInfo.IsDir = true
return return
} }
if fileInfo, err = fs.storage.StatFile(bucket, entry); err != nil { if objInfo, err = fs.getObjectInfo(bucket, entry); err != nil {
return FileInfo{}, traceError(err) return ObjectInfo{}, err
} }
fsMeta, mErr := readFSMetadata(fs.storage, minioMetaBucket, path.Join(bucketMetaPrefix, bucket, entry, fsMetaJSONFile))
if mErr != nil && errorCause(mErr) != errFileNotFound {
return FileInfo{}, traceError(mErr)
}
if len(fsMeta.Meta) == 0 {
fsMeta.Meta = make(map[string]string)
}
// Object name needs to be full path.
fileInfo.Name = entry
fileInfo.MD5Sum = fsMeta.Meta["md5Sum"]
return return
} }
@ -591,7 +580,7 @@ func (fs fsObjects) ListObjects(bucket, prefix, marker, delimiter string, maxKey
listDir := listDirFactory(isLeaf, fsTreeWalkIgnoredErrs, fs.storage) listDir := listDirFactory(isLeaf, fsTreeWalkIgnoredErrs, fs.storage)
walkResultCh = startTreeWalk(bucket, prefix, marker, recursive, listDir, isLeaf, endWalkCh) walkResultCh = startTreeWalk(bucket, prefix, marker, recursive, listDir, isLeaf, endWalkCh)
} }
var fileInfos []FileInfo var objInfos []ObjectInfo
var eof bool var eof bool
var nextMarker string var nextMarker string
for i := 0; i < maxKeys; { for i := 0; i < maxKeys; {
@ -609,12 +598,12 @@ func (fs fsObjects) ListObjects(bucket, prefix, marker, delimiter string, maxKey
} }
return ListObjectsInfo{}, toObjectErr(walkResult.err, bucket, prefix) return ListObjectsInfo{}, toObjectErr(walkResult.err, bucket, prefix)
} }
fileInfo, err := entryToFileInfo(walkResult.entry) objInfo, err := entryToObjectInfo(walkResult.entry)
if err != nil { if err != nil {
return ListObjectsInfo{}, nil return ListObjectsInfo{}, nil
} }
nextMarker = fileInfo.Name nextMarker = objInfo.Name
fileInfos = append(fileInfos, fileInfo) objInfos = append(objInfos, objInfo)
if walkResult.end { if walkResult.end {
eof = true eof = true
break break
@ -627,19 +616,13 @@ func (fs fsObjects) ListObjects(bucket, prefix, marker, delimiter string, maxKey
} }
result := ListObjectsInfo{IsTruncated: !eof} result := ListObjectsInfo{IsTruncated: !eof}
for _, fileInfo := range fileInfos { for _, objInfo := range objInfos {
result.NextMarker = fileInfo.Name result.NextMarker = objInfo.Name
if fileInfo.Mode.IsDir() { if objInfo.IsDir {
result.Prefixes = append(result.Prefixes, fileInfo.Name) result.Prefixes = append(result.Prefixes, objInfo.Name)
continue continue
} }
result.Objects = append(result.Objects, ObjectInfo{ result.Objects = append(result.Objects, objInfo)
Name: fileInfo.Name,
ModTime: fileInfo.ModTime,
Size: fileInfo.Size,
MD5Sum: fileInfo.MD5Sum,
IsDir: false,
})
} }
return result, nil return result, nil
} }

@ -51,20 +51,21 @@ func testListObjects(obj ObjectLayer, instanceType string, t TestErrHandler) {
testObjects := []struct { testObjects := []struct {
name string name string
content string content string
meta map[string]string
}{ }{
{"Asia-maps", "asis-maps"}, {"Asia-maps.png", "asis-maps", map[string]string{"content-type": "image/png"}},
{"Asia/India/India-summer-photos-1", "contentstring"}, {"Asia/India/India-summer-photos-1", "contentstring", nil},
{"Asia/India/Karnataka/Bangalore/Koramangala/pics", "contentstring"}, {"Asia/India/Karnataka/Bangalore/Koramangala/pics", "contentstring", nil},
{"newPrefix0", "newPrefix0"}, {"newPrefix0", "newPrefix0", nil},
{"newPrefix1", "newPrefix1"}, {"newPrefix1", "newPrefix1", nil},
{"newzen/zen/recurse/again/again/again/pics", "recurse"}, {"newzen/zen/recurse/again/again/again/pics", "recurse", nil},
{"obj0", "obj0"}, {"obj0", "obj0", nil},
{"obj1", "obj1"}, {"obj1", "obj1", nil},
{"obj2", "obj2"}, {"obj2", "obj2", nil},
} }
sha256sum := "" sha256sum := ""
for _, object := range testObjects { for _, object := range testObjects {
_, err = obj.PutObject(testBuckets[0], object.name, int64(len(object.content)), bytes.NewBufferString(object.content), nil, sha256sum) _, err = obj.PutObject(testBuckets[0], object.name, int64(len(object.content)), bytes.NewBufferString(object.content), object.meta, sha256sum)
if err != nil { if err != nil {
t.Fatalf("%s : %s", instanceType, err.Error()) t.Fatalf("%s : %s", instanceType, err.Error())
} }
@ -80,7 +81,7 @@ func testListObjects(obj ObjectLayer, instanceType string, t TestErrHandler) {
{ {
IsTruncated: false, IsTruncated: false,
Objects: []ObjectInfo{ Objects: []ObjectInfo{
{Name: "Asia-maps"}, {Name: "Asia-maps.png", ContentType: "image/png"},
{Name: "Asia/India/India-summer-photos-1"}, {Name: "Asia/India/India-summer-photos-1"},
{Name: "Asia/India/Karnataka/Bangalore/Koramangala/pics"}, {Name: "Asia/India/Karnataka/Bangalore/Koramangala/pics"},
{Name: "newPrefix0"}, {Name: "newPrefix0"},
@ -96,7 +97,7 @@ func testListObjects(obj ObjectLayer, instanceType string, t TestErrHandler) {
{ {
IsTruncated: true, IsTruncated: true,
Objects: []ObjectInfo{ Objects: []ObjectInfo{
{Name: "Asia-maps"}, {Name: "Asia-maps.png", ContentType: "image/png"},
{Name: "Asia/India/India-summer-photos-1"}, {Name: "Asia/India/India-summer-photos-1"},
{Name: "Asia/India/Karnataka/Bangalore/Koramangala/pics"}, {Name: "Asia/India/Karnataka/Bangalore/Koramangala/pics"},
{Name: "newPrefix0"}, {Name: "newPrefix0"},
@ -108,7 +109,7 @@ func testListObjects(obj ObjectLayer, instanceType string, t TestErrHandler) {
{ {
IsTruncated: true, IsTruncated: true,
Objects: []ObjectInfo{ Objects: []ObjectInfo{
{Name: "Asia-maps"}, {Name: "Asia-maps.png", ContentType: "image/png"},
{Name: "Asia/India/India-summer-photos-1"}, {Name: "Asia/India/India-summer-photos-1"},
{Name: "Asia/India/Karnataka/Bangalore/Koramangala/pics"}, {Name: "Asia/India/Karnataka/Bangalore/Koramangala/pics"},
{Name: "newPrefix0"}, {Name: "newPrefix0"},
@ -119,7 +120,7 @@ func testListObjects(obj ObjectLayer, instanceType string, t TestErrHandler) {
{ {
IsTruncated: true, IsTruncated: true,
Objects: []ObjectInfo{ Objects: []ObjectInfo{
{Name: "Asia-maps"}, {Name: "Asia-maps.png", ContentType: "image/png"},
{Name: "Asia/India/India-summer-photos-1"}, {Name: "Asia/India/India-summer-photos-1"},
{Name: "Asia/India/Karnataka/Bangalore/Koramangala/pics"}, {Name: "Asia/India/Karnataka/Bangalore/Koramangala/pics"},
}, },
@ -130,7 +131,7 @@ func testListObjects(obj ObjectLayer, instanceType string, t TestErrHandler) {
{ {
IsTruncated: true, IsTruncated: true,
Objects: []ObjectInfo{ Objects: []ObjectInfo{
{Name: "Asia-maps"}, {Name: "Asia-maps.png", ContentType: "image/png"},
}, },
}, },
// ListObjectsResult-5. // ListObjectsResult-5.
@ -233,7 +234,7 @@ func testListObjects(obj ObjectLayer, instanceType string, t TestErrHandler) {
{ {
IsTruncated: false, IsTruncated: false,
Objects: []ObjectInfo{ Objects: []ObjectInfo{
{Name: "Asia-maps"}, {Name: "Asia-maps.png", ContentType: "image/png"},
{Name: "Asia/India/India-summer-photos-1"}, {Name: "Asia/India/India-summer-photos-1"},
{Name: "Asia/India/Karnataka/Bangalore/Koramangala/pics"}, {Name: "Asia/India/Karnataka/Bangalore/Koramangala/pics"},
{Name: "newPrefix0"}, {Name: "newPrefix0"},
@ -342,7 +343,7 @@ func testListObjects(obj ObjectLayer, instanceType string, t TestErrHandler) {
{ {
IsTruncated: false, IsTruncated: false,
Objects: []ObjectInfo{ Objects: []ObjectInfo{
{Name: "Asia-maps"}, {Name: "Asia-maps.png", ContentType: "image/png"},
{Name: "Asia/India/India-summer-photos-1"}, {Name: "Asia/India/India-summer-photos-1"},
{Name: "Asia/India/Karnataka/Bangalore/Koramangala/pics"}, {Name: "Asia/India/Karnataka/Bangalore/Koramangala/pics"},
}, },
@ -353,7 +354,7 @@ func testListObjects(obj ObjectLayer, instanceType string, t TestErrHandler) {
{ {
IsTruncated: false, IsTruncated: false,
Objects: []ObjectInfo{ Objects: []ObjectInfo{
{Name: "Asia-maps"}, {Name: "Asia-maps.png", ContentType: "image/png"},
}, },
}, },
// ListObjectsResult-26. // ListObjectsResult-26.
@ -548,6 +549,10 @@ func testListObjects(obj ObjectLayer, instanceType string, t TestErrHandler) {
if testCase.result.Objects[j].Name != result.Objects[j].Name { if testCase.result.Objects[j].Name != result.Objects[j].Name {
t.Errorf("Test %d: %s: Expected object name to be \"%s\", but found \"%s\" instead", i+1, instanceType, testCase.result.Objects[j].Name, result.Objects[j].Name) t.Errorf("Test %d: %s: Expected object name to be \"%s\", but found \"%s\" instead", i+1, instanceType, testCase.result.Objects[j].Name, result.Objects[j].Name)
} }
if testCase.result.Objects[j].ContentType != result.Objects[j].ContentType {
t.Errorf("Test %d: %s: Expected object contentType to be \"%s\", but found \"%s\" instead", i+1, instanceType, testCase.result.Objects[j].ContentType, result.Objects[j].ContentType)
}
} }
if testCase.result.IsTruncated != result.IsTruncated { if testCase.result.IsTruncated != result.IsTruncated {
t.Errorf("Test %d: %s: Expected IsTruncated flag to be %v, but instead found it to be %v", i+1, instanceType, testCase.result.IsTruncated, result.IsTruncated) t.Errorf("Test %d: %s: Expected IsTruncated flag to be %v, but instead found it to be %v", i+1, instanceType, testCase.result.IsTruncated, result.IsTruncated)

@ -46,7 +46,4 @@ type FileInfo struct {
// File mode bits. // File mode bits.
Mode os.FileMode Mode os.FileMode
// Hex encoded md5 checksum of the file.
MD5Sum string
} }

@ -93,13 +93,7 @@ func (xl xlObjects) listObjects(bucket, prefix, marker, delimiter string, maxKey
result.Prefixes = append(result.Prefixes, objInfo.Name) result.Prefixes = append(result.Prefixes, objInfo.Name)
continue continue
} }
result.Objects = append(result.Objects, ObjectInfo{ result.Objects = append(result.Objects, objInfo)
Name: objInfo.Name,
ModTime: objInfo.ModTime,
Size: objInfo.Size,
MD5Sum: objInfo.MD5Sum,
IsDir: false,
})
} }
return result, nil return result, nil
} }

Loading…
Cancel
Save