s3: list an unlimited number of items - fixes #22
This commit is contained in:
parent
8d1c0ad07c
commit
0faed16899
1 changed files with 40 additions and 27 deletions
67
s3/s3.go
67
s3/s3.go
|
@ -7,6 +7,7 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
"log"
|
||||||
"mime"
|
"mime"
|
||||||
"net/http"
|
"net/http"
|
||||||
"path"
|
"path"
|
||||||
|
@ -101,7 +102,8 @@ func init() {
|
||||||
|
|
||||||
// Constants
|
// Constants
|
||||||
const (
|
const (
|
||||||
metaMtime = "X-Amz-Meta-Mtime" // the meta key to store mtime in
|
metaMtime = "X-Amz-Meta-Mtime" // the meta key to store mtime in
|
||||||
|
listChunkSize = 1024 // number of items to read at once
|
||||||
)
|
)
|
||||||
|
|
||||||
// FsS3 represents a remote s3 server
|
// FsS3 represents a remote s3 server
|
||||||
|
@ -267,36 +269,47 @@ func (f *FsS3) list(directories bool, fn func(string, *s3.Key)) {
|
||||||
if directories {
|
if directories {
|
||||||
delimiter = "/"
|
delimiter = "/"
|
||||||
}
|
}
|
||||||
// FIXME need to implement ALL loop
|
marker := ""
|
||||||
objects, err := f.b.List(f.root, delimiter, "", 10000)
|
for {
|
||||||
if err != nil {
|
objects, err := f.b.List(f.root, delimiter, marker, listChunkSize)
|
||||||
fs.Stats.Error()
|
if err != nil {
|
||||||
fs.Log(f, "Couldn't read bucket %q: %s", f.bucket, err)
|
fs.Stats.Error()
|
||||||
} else {
|
fs.Log(f, "Couldn't read bucket %q: %s", f.bucket, err)
|
||||||
rootLength := len(f.root)
|
|
||||||
if directories {
|
|
||||||
for _, remote := range objects.CommonPrefixes {
|
|
||||||
if !strings.HasPrefix(remote, f.root) {
|
|
||||||
fs.Log(f, "Odd name received %q", remote)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
remote := remote[rootLength:]
|
|
||||||
if strings.HasSuffix(remote, "/") {
|
|
||||||
remote = remote[:len(remote)-1]
|
|
||||||
}
|
|
||||||
fn(remote, &s3.Key{Key: remote})
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
for i := range objects.Contents {
|
rootLength := len(f.root)
|
||||||
object := &objects.Contents[i]
|
if directories {
|
||||||
if !strings.HasPrefix(object.Key, f.root) {
|
for _, remote := range objects.CommonPrefixes {
|
||||||
fs.Log(f, "Odd name received %q", object.Key)
|
if !strings.HasPrefix(remote, f.root) {
|
||||||
continue
|
fs.Log(f, "Odd name received %q", remote)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
remote := remote[rootLength:]
|
||||||
|
if strings.HasSuffix(remote, "/") {
|
||||||
|
remote = remote[:len(remote)-1]
|
||||||
|
}
|
||||||
|
fn(remote, &s3.Key{Key: remote})
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for i := range objects.Contents {
|
||||||
|
object := &objects.Contents[i]
|
||||||
|
if !strings.HasPrefix(object.Key, f.root) {
|
||||||
|
fs.Log(f, "Odd name received %q", object.Key)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
remote := object.Key[rootLength:]
|
||||||
|
fn(remote, object)
|
||||||
}
|
}
|
||||||
remote := object.Key[rootLength:]
|
|
||||||
fn(remote, object)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if !objects.IsTruncated {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
// Use NextMarker if set, otherwise use last Key
|
||||||
|
marker = objects.NextMarker
|
||||||
|
if marker == "" {
|
||||||
|
marker = objects.Contents[len(objects.Contents)-1].Key
|
||||||
|
}
|
||||||
|
log.Printf("retry with marker = %q", marker)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue