Skip to content

Commit 093e6eb

Browse files
committed
cloud: move list delimiter into options struct
This commit updates the `ExternalStorage` `List` interface to take in an options struct and moves `delimiter` into the struct. This is to facilitate further work in adding more options to the `List` call. Epic: None Release note: None
1 parent 5b67446 commit 093e6eb

File tree

27 files changed

+171
-130
lines changed

27 files changed

+171
-130
lines changed

pkg/backup/backup_job.go

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1889,9 +1889,12 @@ func (b *backupResumer) deleteCheckpoint(
18891889
defer exportStore.Close()
18901890
// Delete will not delete a nonempty directory, so we have to go through
18911891
// all files and delete each file one by one.
1892-
return exportStore.List(ctx, backupinfo.BackupProgressDirectory, "", func(p string) error {
1893-
return exportStore.Delete(ctx, backupinfo.BackupProgressDirectory+p)
1894-
})
1892+
return exportStore.List(
1893+
ctx, backupinfo.BackupProgressDirectory, cloud.ListOptions{},
1894+
func(p string) error {
1895+
return exportStore.Delete(ctx, backupinfo.BackupProgressDirectory+p)
1896+
},
1897+
)
18951898
}(); err != nil {
18961899
log.Dev.Warningf(ctx, "unable to delete checkpointed backup descriptor file in progress directory: %+v", err)
18971900
}

pkg/backup/backup_test.go

Lines changed: 21 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -10083,16 +10083,18 @@ func TestBackupNoOverwriteCheckpoint(t *testing.T) {
1008310083
r.Close(ctx)
1008410084

1008510085
var actualNumCheckpointsWritten int
10086-
require.NoError(t, store.List(ctx, latestFilePath+"/progress/", "", func(f string) error {
10087-
// Don't double count checkpoints as there will be the manifest and
10088-
// the checksum.
10089-
if !strings.HasSuffix(f, backupinfo.BackupManifestChecksumSuffix) {
10090-
if strings.HasPrefix(f, backupinfo.BackupManifestCheckpointName) {
10091-
actualNumCheckpointsWritten++
10086+
require.NoError(t, store.List(
10087+
ctx, latestFilePath+"/progress/", cloud.ListOptions{},
10088+
func(f string) error {
10089+
// Don't double count checkpoints as there will be the manifest and
10090+
// the checksum.
10091+
if !strings.HasSuffix(f, backupinfo.BackupManifestChecksumSuffix) {
10092+
if strings.HasPrefix(f, backupinfo.BackupManifestCheckpointName) {
10093+
actualNumCheckpointsWritten++
10094+
}
1009210095
}
10093-
}
10094-
return nil
10095-
}))
10096+
return nil
10097+
}))
1009610098

1009710099
// numCheckpointWritten only accounts for checkpoints written in the
1009810100
// progress loop, each time we Resume we write another checkpoint.
@@ -10217,7 +10219,7 @@ func TestBackupTimestampedCheckpointsAreLexicographical(t *testing.T) {
1021710219
}
1021810220
require.NoError(t, err)
1021910221
var actual string
10220-
err = store.List(ctx, "/progress/", "", func(f string) error {
10222+
err = store.List(ctx, "/progress/", cloud.ListOptions{}, func(f string) error {
1022110223
actual = f
1022210224
return cloud.ErrListingDone
1022310225
})
@@ -10248,13 +10250,15 @@ func TestBackupNoOverwriteLatest(t *testing.T) {
1024810250
findNumLatestFiles := func() (int, string) {
1024910251
var numLatestFiles int
1025010252
var latestFile string
10251-
err = store.List(ctx, backupbase.LatestHistoryDirectory, "", func(p string) error {
10252-
if numLatestFiles == 0 {
10253-
latestFile = p
10254-
}
10255-
numLatestFiles++
10256-
return nil
10257-
})
10253+
err = store.List(
10254+
ctx, backupbase.LatestHistoryDirectory, cloud.ListOptions{},
10255+
func(p string) error {
10256+
if numLatestFiles == 0 {
10257+
latestFile = p
10258+
}
10259+
numLatestFiles++
10260+
return nil
10261+
})
1025810262
require.NoError(t, err)
1025910263
return numLatestFiles, latestFile
1026010264
}

pkg/backup/backupdest/backup_destination.go

Lines changed: 24 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -303,18 +303,21 @@ func FindLatestFile(
303303
// empty object with a trailing '/'. The latter is never created by our code
304304
// but can be created by other tools, e.g., AWS DataSync to transfer an existing backup to
305305
// another bucket. (See https://github.com/cockroachdb/cockroach/issues/106070.)
306-
err := exportStore.List(ctx, backupbase.LatestHistoryDirectory, "", func(p string) error {
307-
p = strings.TrimPrefix(p, "/")
308-
if p == "" {
309-
// N.B. skip the empty object with a trailing '/', created by a third-party tool.
310-
return nil
311-
}
312-
latestFile = p
313-
latestFileFound = true
314-
// We only want the first latest file so return an error that it is
315-
// done listing.
316-
return cloud.ErrListingDone
317-
})
306+
err := exportStore.List(
307+
ctx, backupbase.LatestHistoryDirectory, cloud.ListOptions{},
308+
func(p string) error {
309+
p = strings.TrimPrefix(p, "/")
310+
if p == "" {
311+
// N.B. skip the empty object with a trailing '/', created by a third-party tool.
312+
return nil
313+
}
314+
latestFile = p
315+
latestFileFound = true
316+
// We only want the first latest file so return an error that it is
317+
// done listing.
318+
return cloud.ErrListingDone
319+
},
320+
)
318321
// If the list failed because the storage used does not support listing,
319322
// such as http, we can try reading the non-timestamped backup latest
320323
// file directly. This can still fail if it is a mixed cluster and the
@@ -478,12 +481,15 @@ func ListFullBackupsInCollection(
478481
ctx context.Context, store cloud.ExternalStorage,
479482
) ([]string, error) {
480483
var backupPaths []string
481-
if err := store.List(ctx, "", backupbase.ListingDelimDataSlash, func(f string) error {
482-
if deprecatedBackupPathRE.MatchString(f) {
483-
backupPaths = append(backupPaths, f)
484-
}
485-
return nil
486-
}); err != nil {
484+
if err := store.List(
485+
ctx, "", cloud.ListOptions{Delimiter: backupbase.ListingDelimDataSlash},
486+
func(f string) error {
487+
if deprecatedBackupPathRE.MatchString(f) {
488+
backupPaths = append(backupPaths, f)
489+
}
490+
return nil
491+
},
492+
); err != nil {
487493
// Can't happen, just required to handle the error for lint.
488494
return nil, err
489495
}

pkg/backup/backupdest/incrementals.go

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -131,26 +131,29 @@ func LegacyFindPriorBackups(
131131
defer sp.Finish()
132132

133133
var prev []string
134-
if err := store.List(ctx, "", backupbase.ListingDelimDataSlash, func(p string) error {
135-
matchesGlob, err := path.Match(incBackupSubdirGlob+backupbase.DeprecatedBackupManifestName, p)
136-
if err != nil {
137-
return err
138-
} else if !matchesGlob {
139-
matchesGlob, err = path.Match(incBackupSubdirGlobWithSuffix+backupbase.DeprecatedBackupManifestName, p)
134+
if err := store.List(
135+
ctx, "", cloud.ListOptions{Delimiter: backupbase.ListingDelimDataSlash},
136+
func(p string) error {
137+
matchesGlob, err := path.Match(incBackupSubdirGlob+backupbase.DeprecatedBackupManifestName, p)
140138
if err != nil {
141139
return err
140+
} else if !matchesGlob {
141+
matchesGlob, err = path.Match(incBackupSubdirGlobWithSuffix+backupbase.DeprecatedBackupManifestName, p)
142+
if err != nil {
143+
return err
144+
}
142145
}
143-
}
144146

145-
if matchesGlob {
146-
if !includeManifest {
147-
p = strings.TrimSuffix(p, "/"+backupbase.DeprecatedBackupManifestName)
147+
if matchesGlob {
148+
if !includeManifest {
149+
p = strings.TrimSuffix(p, "/"+backupbase.DeprecatedBackupManifestName)
150+
}
151+
prev = append(prev, p)
152+
return nil
148153
}
149-
prev = append(prev, p)
150154
return nil
151-
}
152-
return nil
153-
}); err != nil {
155+
},
156+
); err != nil {
154157
return nil, errors.Wrap(err, "reading previous backup layers")
155158
}
156159
sort.Strings(prev)

pkg/backup/backupencryption/encryption.go

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -479,15 +479,18 @@ func GetEncryptionInfoFiles(ctx context.Context, dest cloud.ExternalStorage) ([]
479479
var files []string
480480
// Look for all files in dest that start with "/ENCRYPTION-INFO"
481481
// and return them.
482-
err := dest.List(ctx, "", backupbase.ListingDelimDataSlash, func(p string) error {
483-
paths := strings.Split(p, "/")
484-
p = paths[len(paths)-1]
485-
if match := strings.HasPrefix(p, backupEncryptionInfoFile); match {
486-
files = append(files, p)
487-
}
482+
err := dest.List(
483+
ctx, "", cloud.ListOptions{Delimiter: backupbase.ListingDelimDataSlash},
484+
func(p string) error {
485+
paths := strings.Split(p, "/")
486+
p = paths[len(paths)-1]
487+
if match := strings.HasPrefix(p, backupEncryptionInfoFile); match {
488+
files = append(files, p)
489+
}
488490

489-
return nil
490-
})
491+
return nil
492+
},
493+
)
491494
if len(files) < 1 {
492495
return nil, errors.New("no ENCRYPTION-INFO files found")
493496
}

pkg/backup/backupinfo/backup_index.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ func IndexExists(ctx context.Context, store cloud.ExternalStorage, subdir string
138138
if err := store.List(
139139
ctx,
140140
indexDir,
141-
"/",
141+
cloud.ListOptions{Delimiter: "/"},
142142
func(file string) error {
143143
indexExists = true
144144
// Because we delimit on `/` and the index subdir does not contain a
@@ -176,7 +176,7 @@ func ListIndexes(
176176
if err := store.List(
177177
ctx,
178178
indexDir+"/",
179-
"",
179+
cloud.ListOptions{},
180180
func(file string) error {
181181
// We assert that if a file ends with .pb in the index, it should be a
182182
// parsable index file. Otherwise, we ignore it. This circumvents any temp

pkg/backup/backupinfo/manifest_handling.go

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1334,21 +1334,24 @@ func CheckForPreviousBackup(
13341334

13351335
// Check for the presence of a BACKUP-LOCK file with a job ID different from
13361336
// that of our job.
1337-
if err := defaultStore.List(ctx, "", backupbase.ListingDelimDataSlash, func(s string) error {
1338-
s = strings.TrimPrefix(s, "/")
1339-
if strings.HasPrefix(s, BackupLockFilePrefix) {
1340-
jobIDSuffix := strings.TrimPrefix(s, BackupLockFilePrefix)
1341-
if len(jobIDSuffix) == 0 {
1342-
return errors.AssertionFailedf("malformed BACKUP-LOCK file %s, expected a job ID suffix", s)
1343-
}
1344-
if jobIDSuffix != strconv.FormatInt(int64(jobID), 10) {
1345-
return pgerror.Newf(pgcode.FileAlreadyExists,
1346-
"%s already contains a `BACKUP-LOCK` file written by job %s",
1347-
redactedURI, jobIDSuffix)
1337+
if err := defaultStore.List(
1338+
ctx, "", cloud.ListOptions{Delimiter: backupbase.ListingDelimDataSlash},
1339+
func(s string) error {
1340+
s = strings.TrimPrefix(s, "/")
1341+
if strings.HasPrefix(s, BackupLockFilePrefix) {
1342+
jobIDSuffix := strings.TrimPrefix(s, BackupLockFilePrefix)
1343+
if len(jobIDSuffix) == 0 {
1344+
return errors.AssertionFailedf("malformed BACKUP-LOCK file %s, expected a job ID suffix", s)
1345+
}
1346+
if jobIDSuffix != strconv.FormatInt(int64(jobID), 10) {
1347+
return pgerror.Newf(pgcode.FileAlreadyExists,
1348+
"%s already contains a `BACKUP-LOCK` file written by job %s",
1349+
redactedURI, jobIDSuffix)
1350+
}
13481351
}
1349-
}
1350-
return nil
1351-
}); err != nil {
1352+
return nil
1353+
},
1354+
); err != nil {
13521355
// HTTP external storage does not support listing, and so we skip checking
13531356
// for a BACKUP-LOCK file.
13541357
if !errors.Is(err, cloud.ErrListingUnsupported) {
@@ -1536,7 +1539,7 @@ func readLatestCheckpointFile(
15361539

15371540
// We name files such that the most recent checkpoint will always
15381541
// be at the top, so just grab the first filename.
1539-
err = exportStore.List(ctx, BackupProgressDirectory, "", func(p string) error {
1542+
err = exportStore.List(ctx, BackupProgressDirectory, cloud.ListOptions{}, func(p string) error {
15401543
// The first file returned by List could be either the checkpoint or
15411544
// checksum file, but we are only concerned with the timestamped prefix.
15421545
// We resolve if it is a checkpoint or checksum file separately below.

pkg/ccl/changefeedccl/sink_cloudstorage_test.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -997,7 +997,9 @@ func (n *mockSinkStorage) Writer(_ context.Context, _ string) (io.WriteCloser, e
997997
return n.writer(), nil
998998
}
999999

1000-
func (n *mockSinkStorage) List(_ context.Context, _, _ string, _ cloud.ListingFn) error {
1000+
func (n *mockSinkStorage) List(
1001+
_ context.Context, _ string, _ cloud.ListOptions, _ cloud.ListingFn,
1002+
) error {
10011003
return nil
10021004
}
10031005

pkg/ccl/workloadccl/fixture.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -694,7 +694,7 @@ func listDir(
694694
if log.V(1) {
695695
log.Dev.Infof(ctx, "Listing %s", dir)
696696
}
697-
return es.List(ctx, dir, "/", lsFn)
697+
return es.List(ctx, dir, cloud.ListOptions{Delimiter: "/"}, lsFn)
698698
}
699699

700700
// ListFixtures returns the object paths to all fixtures stored in a FixtureConfig.

pkg/cli/userfile.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -248,7 +248,7 @@ func runUserFileGet(cmd *cobra.Command, args []string) (resErr error) {
248248
defer f.Close()
249249

250250
var files []string
251-
if err := f.List(ctx, "", "", func(s string) error {
251+
if err := f.List(ctx, "", cloud.ListOptions{}, func(s string) error {
252252
if pattern != "" {
253253
if ok, err := path.Match(pattern, s); err != nil || !ok {
254254
return err
@@ -442,7 +442,7 @@ func listUserFile(ctx context.Context, conn clisqlclient.Conn, glob string) ([]s
442442

443443
displayPrefix := strings.TrimPrefix(conf.Path, "/")
444444
var res []string
445-
if err := f.List(ctx, "", "", func(s string) error {
445+
if err := f.List(ctx, "", cloud.ListOptions{}, func(s string) error {
446446
if pattern != "" {
447447
ok, err := path.Match(pattern, s)
448448
if err != nil || !ok {
@@ -519,7 +519,7 @@ func deleteUserFile(ctx context.Context, conn clisqlclient.Conn, glob string) ([
519519
displayRoot := strings.TrimPrefix(userFileTableConf.FileTableConfig.Path, "/")
520520
var deleted []string
521521

522-
if err := f.List(ctx, "", "", func(s string) error {
522+
if err := f.List(ctx, "", cloud.ListOptions{}, func(s string) error {
523523
if pattern != "" {
524524
ok, err := path.Match(pattern, s)
525525
if err != nil || !ok {

0 commit comments

Comments
 (0)