diff --git a/cmd/lotus-storage-miner/backup.go b/cmd/lotus-storage-miner/backup.go index a1ad360c9..55604b6fb 100644 --- a/cmd/lotus-storage-miner/backup.go +++ b/cmd/lotus-storage-miner/backup.go @@ -60,7 +60,7 @@ func offlineBackup(cctx *cli.Context) error { return xerrors.Errorf("repo at '%s' is not initialized", cctx.String(FlagMinerRepo)) } - lr, err := r.Lock(repo.StorageMiner) + lr, err := r.LockRO(repo.StorageMiner) if err != nil { return xerrors.Errorf("locking repo: %w", err) } diff --git a/node/repo/fsrepo.go b/node/repo/fsrepo.go index a69cdd55d..c4571c478 100644 --- a/node/repo/fsrepo.go +++ b/node/repo/fsrepo.go @@ -226,11 +226,23 @@ func (fsr *FsRepo) Lock(repoType RepoType) (LockedRepo, error) { }, nil } +// Like Lock, except datastores will work in read-only mode +func (fsr *FsRepo) LockRO(repoType RepoType) (LockedRepo, error) { + lr, err := fsr.Lock(repoType) + if err != nil { + return nil, err + } + + lr.(*fsLockedRepo).readonly = true + return lr, nil +} + type fsLockedRepo struct { path string configPath string repoType RepoType closer io.Closer + readonly bool ds map[string]datastore.Batching dsErr error diff --git a/node/repo/fsrepo_ds.go b/node/repo/fsrepo_ds.go index f4afe0dee..aa91d2514 100644 --- a/node/repo/fsrepo_ds.go +++ b/node/repo/fsrepo_ds.go @@ -14,7 +14,7 @@ import ( ldbopts "github.com/syndtr/goleveldb/leveldb/opt" ) -type dsCtor func(path string) (datastore.Batching, error) +type dsCtor func(path string, readonly bool) (datastore.Batching, error) var fsDatastores = map[string]dsCtor{ "chain": chainBadgerDs, @@ -26,9 +26,10 @@ var fsDatastores = map[string]dsCtor{ "client": badgerDs, // client specific } -func chainBadgerDs(path string) (datastore.Batching, error) { +func chainBadgerDs(path string, readonly bool) (datastore.Batching, error) { opts := badger.DefaultOptions opts.GcInterval = 0 // disable GC for chain datastore + opts.ReadOnly = readonly opts.Options = dgbadger.DefaultOptions("").WithTruncate(true). WithValueThreshold(1 << 10) @@ -36,23 +37,26 @@ func chainBadgerDs(path string) (datastore.Batching, error) { return badger.NewDatastore(path, &opts) } -func badgerDs(path string) (datastore.Batching, error) { +func badgerDs(path string, readonly bool) (datastore.Batching, error) { opts := badger.DefaultOptions + opts.ReadOnly = readonly + opts.Options = dgbadger.DefaultOptions("").WithTruncate(true). WithValueThreshold(1 << 10) return badger.NewDatastore(path, &opts) } -func levelDs(path string) (datastore.Batching, error) { +func levelDs(path string, readonly bool) (datastore.Batching, error) { return levelds.NewDatastore(path, &levelds.Options{ Compression: ldbopts.NoCompression, NoSync: false, Strict: ldbopts.StrictAll, + ReadOnly: readonly, }) } -func (fsr *fsLockedRepo) openDatastores() (map[string]datastore.Batching, error) { +func (fsr *fsLockedRepo) openDatastores(readonly bool) (map[string]datastore.Batching, error) { if err := os.MkdirAll(fsr.join(fsDatastore), 0755); err != nil { return nil, xerrors.Errorf("mkdir %s: %w", fsr.join(fsDatastore), err) } @@ -63,7 +67,7 @@ func (fsr *fsLockedRepo) openDatastores() (map[string]datastore.Batching, error) prefix := datastore.NewKey(p) // TODO: optimization: don't init datastores we don't need - ds, err := ctor(fsr.join(filepath.Join(fsDatastore, p))) + ds, err := ctor(fsr.join(filepath.Join(fsDatastore, p)), readonly) if err != nil { return nil, xerrors.Errorf("opening datastore %s: %w", prefix, err) } @@ -78,7 +82,7 @@ func (fsr *fsLockedRepo) openDatastores() (map[string]datastore.Batching, error) func (fsr *fsLockedRepo) Datastore(ns string) (datastore.Batching, error) { fsr.dsOnce.Do(func() { - fsr.ds, fsr.dsErr = fsr.openDatastores() + fsr.ds, fsr.dsErr = fsr.openDatastores(fsr.readonly) }) if fsr.dsErr != nil {