@@ -7,6 +7,7 @@ package metamorphic
7
7
import (
8
8
"bytes"
9
9
"fmt"
10
+ "io"
10
11
"math"
11
12
"math/rand/v2"
12
13
"os"
@@ -926,10 +927,12 @@ func expRandDuration(rng *rand.Rand, meanDur, maxDur time.Duration) time.Duratio
926
927
}
927
928
928
929
func setupInitialState (dataDir string , testOpts * TestOptions ) error {
930
+ fs := testOpts .Opts .FS
931
+
929
932
// Copy (vfs.Default,<initialStatePath>/data) to (testOpts.opts.FS,<dataDir>).
930
933
ok , err := vfs .Clone (
931
934
vfs .Default ,
932
- testOpts . Opts . FS ,
935
+ fs ,
933
936
vfs .Default .PathJoin (testOpts .initialStatePath , "data" ),
934
937
dataDir ,
935
938
vfs .CloneSync ,
@@ -945,58 +948,86 @@ func setupInitialState(dataDir string, testOpts *TestOptions) error {
945
948
return os .ErrNotExist
946
949
}
947
950
948
- // Tests with wal_dir set store their WALs in a `wal` directory. The source
949
- // database (initialStatePath) could've had wal_dir set, or the current test
950
- // options (testOpts) could have wal_dir set, or both.
951
- //
952
- // If the test opts are not configured to use a WAL dir, we add the WAL dir
953
- // as a 'WAL recovery dir' so that we'll read any WALs in the directory in
954
- // Open.
955
- fs := testOpts .Opts .FS
956
- walRecoveryPath := fs .PathJoin (dataDir , "wal" )
957
- if _ , err := fs .Stat (walRecoveryPath ); err == nil {
958
- // Previous test used a WAL dir.
959
- if testOpts .Opts .WALDir == "" {
960
- // This test is not using a WAL dir. Add the previous WAL dir as a
961
- // recovery dir.
962
- testOpts .Opts .WALRecoveryDirs = append (testOpts .Opts .WALRecoveryDirs , wal.Dir {
963
- FS : fs ,
964
- Dirname : pebble .MakeStoreRelativePath (fs , "wal" ),
965
- })
966
- } else {
967
- // Both the previous test and the current test are using a WAL dir. We
968
- // assume that they are the same.
969
- if testOpts .Opts .WALDir != pebble .MakeStoreRelativePath (fs , "wal" ) {
970
- return errors .Errorf ("unsupported wal dir value %q" , testOpts .Opts .WALDir )
971
- }
972
- }
973
- } else {
974
- // Previous test did not use a WAL dir.
975
- if testOpts .Opts .WALDir != "" {
976
- // The current test is using a WAL dir; we add the data directory itself
977
- // as a 'WAL recovery dir' so that we'll read any WALs if the previous
978
- // test was writing them to the data directory.
979
- testOpts .Opts .WALRecoveryDirs = append (testOpts .Opts .WALRecoveryDirs , wal.Dir {
980
- FS : fs ,
981
- Dirname : pebble .MakeStoreRelativePath (fs , "" ),
982
- })
983
- }
951
+ // Find the previous OPTIONS file.
952
+ ls , err := fs .List (dataDir )
953
+ if err != nil {
954
+ return err
984
955
}
985
956
986
- // If the previous test used WAL failover and this test does not use failover,
987
- // add the failover directory as a 'WAL recovery dir' in case the previous
988
- // test was configured to use failover.
989
- failoverDir := testOpts .Opts .FS .PathJoin (dataDir , "wal_secondary" )
990
- if _ , err := testOpts .Opts .FS .Stat (failoverDir ); err == nil {
991
- if testOpts .Opts .WALFailover == nil {
992
- testOpts .Opts .WALRecoveryDirs = append (testOpts .Opts .WALRecoveryDirs , wal.Dir {
993
- FS : testOpts .Opts .FS ,
994
- Dirname : pebble .MakeStoreRelativePath (testOpts .Opts .FS , "wal_secondary" ),
995
- })
996
- } else if testOpts .Opts .WALFailover .Secondary .Dirname != pebble .MakeStoreRelativePath (testOpts .Opts .FS , "wal_secondary" ) {
997
- return errors .Errorf ("unsupported wal failover dir value %q" , testOpts .Opts .WALFailover .Secondary .Dirname )
957
+ var lastOptionsNum base.DiskFileNum
958
+ var lastOptionsFilename string
959
+
960
+ for _ , filename := range ls {
961
+ ft , fn , ok := base .ParseFilename (fs , filename )
962
+ if ok && ft == base .FileTypeOptions && fn > lastOptionsNum {
963
+ lastOptionsNum = fn
964
+ lastOptionsFilename = filename
998
965
}
999
966
}
967
+
968
+ if lastOptionsFilename == "" {
969
+ return errors .Errorf ("could not find any OPTIONS file in %s/data" , testOpts .initialStatePath )
970
+ }
971
+
972
+ f , err := fs .Open (fs .PathJoin (dataDir , lastOptionsFilename ))
973
+ if err != nil {
974
+ return err
975
+ }
976
+ data , err := io .ReadAll (f )
977
+ f .Close ()
978
+ if err != nil {
979
+ return err
980
+ }
981
+
982
+ var opts pebble.Options
983
+ if err := opts .Parse (string (data ), nil /* hooks */ ); err != nil {
984
+ return errors .Wrapf (err , "failed to parse %s/%s" , dataDir , lastOptionsFilename )
985
+ }
986
+
987
+ // WALDir must be either empty or `{store_path}/wal`.
988
+ expectedWALDir := pebble .MakeStoreRelativePath (fs , "wal" )
989
+ if opts .WALDir != "" && opts .WALDir != expectedWALDir {
990
+ return errors .Errorf ("unexpected wal_dir value in initial store: %q" , opts .WALDir )
991
+ }
992
+ if testOpts .Opts .WALDir != "" && testOpts .Opts .WALDir != expectedWALDir {
993
+ return errors .Errorf ("unexpected wal_dir value in test optons: %q" , testOpts .Opts .WALDir )
994
+ }
995
+
996
+ if opts .WALDir == "" && testOpts .Opts .WALDir != "" {
997
+ // The previous test did not use a WAL dir but this test does. Add the
998
+ // store path as a WAL recovery dir.
999
+ testOpts .Opts .WALRecoveryDirs = append (testOpts .Opts .WALRecoveryDirs , wal.Dir {
1000
+ FS : fs ,
1001
+ Dirname : pebble .MakeStoreRelativePath (fs , "" ),
1002
+ })
1003
+ } else if opts .WALDir != "" && testOpts .Opts .WALDir == "" {
1004
+ // The previous test used a WAL dir but this test does not. Add the
1005
+ // previous WAL dir as a WAL recovery dir.
1006
+ testOpts .Opts .WALRecoveryDirs = append (testOpts .Opts .WALRecoveryDirs , wal.Dir {
1007
+ FS : fs ,
1008
+ Dirname : opts .WALDir ,
1009
+ })
1010
+ }
1011
+
1012
+ // WAL secondary must be `{store_path}/wal_secondary` if WAL failover is enabled.
1013
+ expectedSecondaryDir := pebble .MakeStoreRelativePath (fs , "wal_secondary" )
1014
+ if wf := opts .WALFailover ; wf != nil && wf .Secondary .Dirname != expectedSecondaryDir {
1015
+ return errors .Errorf ("unexpected wal_secondary value in initial store: %q" , wf .Secondary .Dirname )
1016
+ }
1017
+ if wf := testOpts .Opts .WALFailover ; wf != nil && wf .Secondary .Dirname != expectedSecondaryDir {
1018
+ return errors .Errorf ("unexpected wal_secondary value in test options: %q" , wf .Secondary .Dirname )
1019
+ }
1020
+
1021
+ if opts .WALFailover != nil && testOpts .Opts .WALFailover == nil {
1022
+ // The previous test used WAL failover but this test does not. Add the
1023
+ // previous secondary directory as a WAL recovery dir.
1024
+ testOpts .Opts .WALRecoveryDirs = append (testOpts .Opts .WALRecoveryDirs , wal.Dir {
1025
+ FS : testOpts .Opts .FS ,
1026
+ Dirname : opts .WALFailover .Secondary .Dirname ,
1027
+ })
1028
+ }
1029
+ // If the previous test did not use WAL failover but this test does, we don't
1030
+ // need to add any recovery dir.
1000
1031
return nil
1001
1032
}
1002
1033
0 commit comments