Implement proper delimiter and prefix handling

With this change Minio server now responds with, delimited
'object names' in conjunction with prefix filtering

~~~
<ListBucketResult>
  <Name>example-bucket</Name>
  <Prefix></Prefix>
  <Marker></Marker>
  <MaxKeys>1000</MaxKeys>
  <Delimiter>/</Delimiter>
  <IsTruncated>false</IsTruncated>
  <Contents>
    <Key>sample.html</Key>
    <LastModified>2011-02-26T01:56:20.000Z</LastModified>
    <ETag>example-bucket#sample.html</ETag>
    <Size>142863</Size>
    <Owner>
      <ID>minio</ID>
      <DisplayName>minio</DisplayName>
    </Owner>
    <StorageClass>STANDARD</StorageClass>
  </Contents>
  <CommonPrefixes>
    <Prefix>photos/</Prefix>
  </CommonPrefixes>
</ListBucketResult>
~~~

~~~
<ListBucketResult>
  <Name>example-bucket</Name>
  <Prefix>photos/2006/</Prefix>
  <Marker></Marker>
  <MaxKeys>1000</MaxKeys>
  <Delimiter>/</Delimiter>
  <IsTruncated>false</IsTruncated>

  <CommonPrefixes>
    <Prefix>photos/2006/feb/</Prefix>
  </CommonPrefixes>
  <CommonPrefixes>
    <Prefix>photos/2006/jan/</Prefix>
  </CommonPrefixes>
</ListBucketResult>
~~~
This commit is contained in:
Harshavardhana
2015-02-28 14:44:26 -08:00
parent acee4d16fd
commit 0c2d58bc6d
5 changed files with 84 additions and 37 deletions

View File

@@ -314,6 +314,29 @@ func (p *Path) getAllFiles(path string, fl os.FileInfo, err error) error {
return nil
}
func delimiter(path, delimiter string) string {
delimited := ""
if !strings.Contains(path, delimiter) {
return delimited
}
index := strings.Index(path, delimiter)
if index == -1 {
return delimited
}
delimitedIndex := index + len(delimiter)
delimited = path[:delimitedIndex]
return delimited
}
func appendU(slice []string, i string) []string {
for _, ele := range slice {
if ele == i {
return slice
}
}
return append(slice, i)
}
type ByObjectKey []mstorage.ObjectMetadata
func (b ByObjectKey) Len() int { return len(b) }
@@ -350,31 +373,44 @@ func (storage *storage) ListObjects(bucket string, resources mstorage.BucketReso
goto ret
}
// TODO handle resources.Marker
if resources.Delimiter != "" {
metadata := mstorage.ObjectMetadata{
Bucket: bucket,
Maxkeys: resources.Maxkeys,
Prefix: resources.Prefix,
Marker: resources.Marker,
Delimiter: resources.Delimiter,
switch true {
case resources.Delimiter != "" && resources.Prefix == "":
delimited := delimiter(name, resources.Delimiter)
switch true {
case delimited == "":
metadata := mstorage.ObjectMetadata{
Bucket: bucket,
Key: name,
Created: file.ModTime(),
Size: file.Size(),
ETag: bucket + "#" + name,
}
metadataList = append(metadataList, metadata)
case delimited != "":
resources.CommonPrefixes = appendU(resources.CommonPrefixes, delimited)
}
metadataList = append(metadataList, metadata)
}
if resources.Delimiter != "" && strings.HasPrefix(name, resources.Prefix) {
metadata := mstorage.ObjectMetadata{}
metadataList = append(metadataList, metadata)
}
if strings.HasPrefix(name, resources.Prefix) {
case resources.Delimiter != "" && strings.HasPrefix(name, resources.Prefix):
delimited := delimiter(name, resources.Delimiter)
switch true {
case delimited == "":
metadata := mstorage.ObjectMetadata{
Bucket: bucket,
Key: name,
Created: file.ModTime(),
Size: file.Size(),
ETag: bucket + "#" + name,
}
metadataList = append(metadataList, metadata)
case delimited != "":
resources.CommonPrefixes = appendU(resources.CommonPrefixes, delimited)
}
case strings.HasPrefix(name, resources.Prefix):
metadata := mstorage.ObjectMetadata{
Bucket: bucket,
Maxkeys: resources.Maxkeys,
Prefix: resources.Prefix,
Marker: resources.Marker,
Delimiter: resources.Delimiter,
Key: name,
Created: file.ModTime(),
Size: file.Size(),
ETag: bucket + "#" + name,
Bucket: bucket,
Key: name,
Created: file.ModTime(),
Size: file.Size(),
ETag: bucket + "#" + name,
}
metadataList = append(metadataList, metadata)
}

View File

@@ -43,12 +43,8 @@ type BucketMetadata struct {
}
type ObjectMetadata struct {
Bucket string
Key string
Maxkeys int
Prefix string
Marker string
Delimiter string
Bucket string
Key string
ContentType string
Created time.Time