github.com/ethersphere/bee/v2@v2.2.0/pkg/storer/recover.go (about)

     1  // Copyright 2023 The Swarm Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package storer
     6  
     7  import (
     8  	"context"
     9  	"errors"
    10  	"io/fs"
    11  	"os"
    12  	"path/filepath"
    13  	"time"
    14  
    15  	"github.com/ethersphere/bee/v2/pkg/sharky"
    16  	storage "github.com/ethersphere/bee/v2/pkg/storage"
    17  	"github.com/ethersphere/bee/v2/pkg/storer/internal/chunkstore"
    18  	"github.com/ethersphere/bee/v2/pkg/swarm"
    19  )
    20  
    21  const (
    22  	sharkyDirtyFileName = ".DIRTY"
    23  )
    24  
    25  func sharkyRecovery(ctx context.Context, sharkyBasePath string, store storage.Store, opts *Options) (closerFn, error) {
    26  	ctx, cancel := context.WithCancel(ctx)
    27  	defer cancel()
    28  
    29  	logger := opts.Logger.WithName(loggerName).Register()
    30  	dirtyFilePath := filepath.Join(sharkyBasePath, sharkyDirtyFileName)
    31  
    32  	closer := func() error { return os.Remove(dirtyFilePath) }
    33  
    34  	if _, err := os.Stat(dirtyFilePath); errors.Is(err, fs.ErrNotExist) {
    35  		return closer, os.WriteFile(dirtyFilePath, []byte{}, 0644)
    36  	}
    37  
    38  	logger.Info("localstore sharky .DIRTY file exists: starting recovery due to previous dirty exit")
    39  	defer func(t time.Time) {
    40  		logger.Info("localstore sharky recovery finished", "time", time.Since(t))
    41  	}(time.Now())
    42  
    43  	sharkyRecover, err := sharky.NewRecovery(sharkyBasePath, sharkyNoOfShards, swarm.SocMaxChunkSize)
    44  	if err != nil {
    45  		return closer, err
    46  	}
    47  
    48  	defer func() {
    49  		if err := sharkyRecover.Close(); err != nil {
    50  			logger.Error(err, "failed closing sharky recovery")
    51  		}
    52  	}()
    53  
    54  	c := chunkstore.IterateLocations(ctx, store)
    55  
    56  	if err := addLocations(c, sharkyRecover); err != nil {
    57  		return closer, err
    58  	}
    59  
    60  	return closer, nil
    61  }
    62  
    63  func addLocations(locationResultC <-chan chunkstore.LocationResult, sharkyRecover *sharky.Recovery) error {
    64  	for res := range locationResultC {
    65  		if res.Err != nil {
    66  			return res.Err
    67  		}
    68  
    69  		if err := sharkyRecover.Add(res.Location); err != nil {
    70  			return err
    71  		}
    72  	}
    73  
    74  	if err := sharkyRecover.Save(); err != nil {
    75  		return err
    76  	}
    77  
    78  	return nil
    79  }