From 9e121592307ecb0162d0a121f4d03ada6c4fb4e6 Mon Sep 17 00:00:00 2001 From: Michael Eischer Date: Sat, 6 Nov 2021 01:23:12 +0100 Subject: [PATCH] Fix O(n) backend list calls in FindFilteredSnapshots When resolving snapshotIDs in FindFilteredSnapshots either FindLatestSnapshot or FindSnapshot is called. Both operations issue a list operation to the backend. When for example passing a long list of snapshot ids to `forget` this could lead to a large number of list operations. --- cmd/restic/find.go | 9 ++++++++- internal/backend/utils.go | 4 ++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/cmd/restic/find.go b/cmd/restic/find.go index a319d23de..f93f37278 100644 --- a/cmd/restic/find.go +++ b/cmd/restic/find.go @@ -3,6 +3,7 @@ package main import ( "context" + "github.com/restic/restic/internal/backend" "github.com/restic/restic/internal/restic" ) @@ -12,10 +13,16 @@ func FindFilteredSnapshots(ctx context.Context, be restic.Lister, loader restic. go func() { defer close(out) if len(snapshotIDs) != 0 { + // memorize snapshots list to prevent repeated backend listings + be, err := backend.MemorizeList(ctx, be, restic.SnapshotFile) + if err != nil { + Warnf("could not load snapshots: %v\n", err) + return + } + var ( id restic.ID usedFilter bool - err error ) ids := make(restic.IDs, 0, len(snapshotIDs)) // Process all snapshot IDs given as arguments. diff --git a/internal/backend/utils.go b/internal/backend/utils.go index 0dd081232..be1c2a9e0 100644 --- a/internal/backend/utils.go +++ b/internal/backend/utils.go @@ -81,6 +81,10 @@ func (m *memorizedLister) List(ctx context.Context, t restic.FileType, fn func(r } func MemorizeList(ctx context.Context, be restic.Lister, t restic.FileType) (restic.Lister, error) { + if _, ok := be.(*memorizedLister); ok { + return be, nil + } + var fileInfos []restic.FileInfo err := be.List(ctx, t, func(fi restic.FileInfo) error { fileInfos = append(fileInfos, fi)