Pass the last paging flag to storage drivers
Storage drivers may be able to take advantage of the hint to start their walk more efficiently. For S3: The API takes a start-after parameter. Registries with many repositories can drastically reduce calls to s3 by telling s3 to only list results lexographically after the last parameter. For the fallback: We can start deeper in the tree and avoid statting the files and directories before the hint in a walk. For a filesystem this improves performance a little, but many of the API based drivers are currently treated like a filesystem, so this drastically improves the performance of GCP and Azure blob. Signed-off-by: James Hewitt <james.hewitt@uk.ibm.com>
This commit is contained in:
parent
3a44c2e10e
commit
e22f7cbc73
13 changed files with 390 additions and 63 deletions
|
@ -491,6 +491,7 @@ func TestWalk(t *testing.T) {
|
|||
|
||||
fileset := []string{
|
||||
"/file1",
|
||||
"/folder1-suffix/file1",
|
||||
"/folder1/file1",
|
||||
"/folder2/file1",
|
||||
"/folder3/subfolder1/subfolder1/file1",
|
||||
|
@ -524,18 +525,23 @@ func TestWalk(t *testing.T) {
|
|||
}
|
||||
}()
|
||||
|
||||
noopFn := func(fileInfo storagedriver.FileInfo) error { return nil }
|
||||
|
||||
tcs := []struct {
|
||||
name string
|
||||
fn storagedriver.WalkFn
|
||||
from string
|
||||
options []func(*storagedriver.WalkOptions)
|
||||
expected []string
|
||||
err bool
|
||||
}{
|
||||
{
|
||||
name: "walk all",
|
||||
fn: func(fileInfo storagedriver.FileInfo) error { return nil },
|
||||
fn: noopFn,
|
||||
expected: []string{
|
||||
"/file1",
|
||||
"/folder1-suffix",
|
||||
"/folder1-suffix/file1",
|
||||
"/folder1",
|
||||
"/folder1/file1",
|
||||
"/folder2",
|
||||
|
@ -564,6 +570,8 @@ func TestWalk(t *testing.T) {
|
|||
},
|
||||
expected: []string{
|
||||
"/file1",
|
||||
"/folder1-suffix",
|
||||
"/folder1-suffix/file1",
|
||||
"/folder1",
|
||||
"/folder1/file1",
|
||||
"/folder2",
|
||||
|
@ -574,22 +582,101 @@ func TestWalk(t *testing.T) {
|
|||
"/folder4/file1",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "start late without from",
|
||||
fn: noopFn,
|
||||
options: []func(*storagedriver.WalkOptions){
|
||||
storagedriver.WithStartAfterHint("/folder3/subfolder1/subfolder1/file1"),
|
||||
},
|
||||
expected: []string{
|
||||
// start late
|
||||
"/folder3",
|
||||
"/folder3/subfolder2",
|
||||
"/folder3/subfolder2/subfolder1",
|
||||
"/folder3/subfolder2/subfolder1/file1",
|
||||
"/folder4",
|
||||
"/folder4/file1",
|
||||
},
|
||||
err: false,
|
||||
},
|
||||
{
|
||||
name: "start late with from",
|
||||
fn: noopFn,
|
||||
from: "/folder3",
|
||||
options: []func(*storagedriver.WalkOptions){
|
||||
storagedriver.WithStartAfterHint("/folder3/subfolder1/subfolder1/file1"),
|
||||
},
|
||||
expected: []string{
|
||||
// start late
|
||||
"/folder3/subfolder2",
|
||||
"/folder3/subfolder2/subfolder1",
|
||||
"/folder3/subfolder2/subfolder1/file1",
|
||||
},
|
||||
err: false,
|
||||
},
|
||||
{
|
||||
name: "start after from",
|
||||
fn: noopFn,
|
||||
from: "/folder1",
|
||||
options: []func(*storagedriver.WalkOptions){
|
||||
storagedriver.WithStartAfterHint("/folder2"),
|
||||
},
|
||||
expected: []string{},
|
||||
err: false,
|
||||
},
|
||||
{
|
||||
name: "start matches from",
|
||||
fn: noopFn,
|
||||
from: "/folder3",
|
||||
options: []func(*storagedriver.WalkOptions){
|
||||
storagedriver.WithStartAfterHint("/folder3"),
|
||||
},
|
||||
expected: []string{
|
||||
"/folder3/subfolder1",
|
||||
"/folder3/subfolder1/subfolder1",
|
||||
"/folder3/subfolder1/subfolder1/file1",
|
||||
"/folder3/subfolder2",
|
||||
"/folder3/subfolder2/subfolder1",
|
||||
"/folder3/subfolder2/subfolder1/file1",
|
||||
},
|
||||
err: false,
|
||||
},
|
||||
{
|
||||
name: "start doesn't exist",
|
||||
fn: noopFn,
|
||||
from: "/folder3",
|
||||
options: []func(*storagedriver.WalkOptions){
|
||||
storagedriver.WithStartAfterHint("/folder3/notafolder/notafile"),
|
||||
},
|
||||
expected: []string{
|
||||
"/folder3/subfolder1",
|
||||
"/folder3/subfolder1/subfolder1",
|
||||
"/folder3/subfolder1/subfolder1/file1",
|
||||
"/folder3/subfolder2",
|
||||
"/folder3/subfolder2/subfolder1",
|
||||
"/folder3/subfolder2/subfolder1/file1",
|
||||
},
|
||||
err: false,
|
||||
},
|
||||
{
|
||||
name: "stop early",
|
||||
fn: func(fileInfo storagedriver.FileInfo) error {
|
||||
if fileInfo.Path() == "/folder1/file1" {
|
||||
return storagedriver.ErrSkipDir
|
||||
return storagedriver.ErrFilledBuffer
|
||||
}
|
||||
return nil
|
||||
},
|
||||
expected: []string{
|
||||
"/file1",
|
||||
"/folder1-suffix",
|
||||
"/folder1-suffix/file1",
|
||||
"/folder1",
|
||||
"/folder1/file1",
|
||||
// stop early
|
||||
},
|
||||
err: false,
|
||||
},
|
||||
|
||||
{
|
||||
name: "error",
|
||||
fn: func(fileInfo storagedriver.FileInfo) error {
|
||||
|
@ -602,7 +689,7 @@ func TestWalk(t *testing.T) {
|
|||
},
|
||||
{
|
||||
name: "from folder",
|
||||
fn: func(fileInfo storagedriver.FileInfo) error { return nil },
|
||||
fn: noopFn,
|
||||
expected: []string{
|
||||
"/folder1/file1",
|
||||
},
|
||||
|
@ -619,7 +706,7 @@ func TestWalk(t *testing.T) {
|
|||
err := drvr.Walk(context.Background(), tc.from, func(fileInfo storagedriver.FileInfo) error {
|
||||
walked = append(walked, fileInfo.Path())
|
||||
return tc.fn(fileInfo)
|
||||
})
|
||||
}, tc.options...)
|
||||
if tc.err && err == nil {
|
||||
t.Fatalf("expected err")
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue