gitlab.com/SiaPrime/SiaPrime@v1.4.1/modules/host/contractmanager/storagefoldershrink.go (about)

     1  package contractmanager
     2  
     3  import (
     4  	"sync/atomic"
     5  
     6  	"gitlab.com/SiaPrime/SiaPrime/modules"
     7  )
     8  
     9  type (
    10  	// storageFolderReduction dictates a completed storage folder reduction to
    11  	// the WAL.
    12  	storageFolderReduction struct {
    13  		Index          uint16
    14  		NewSectorCount uint32
    15  	}
    16  )
    17  
    18  // commitStorageFolderReduction commits a storage folder reduction to the state
    19  // and filesystem.
    20  func (wal *writeAheadLog) commitStorageFolderReduction(sfr storageFolderReduction) {
    21  	sf, exists := wal.cm.storageFolders[sfr.Index]
    22  	if !exists {
    23  		wal.cm.log.Critical("ERROR: storage folder reduction established for a storage folder that does not exist")
    24  		return
    25  	}
    26  	if atomic.LoadUint64(&sf.atomicUnavailable) == 1 {
    27  		// Cannot complete the storage folder reduction - storage folder is not
    28  		// available.
    29  		return
    30  	}
    31  
    32  	// Shrink the sector usage, but only if the sector usage is not already
    33  	// smaller.
    34  	if uint32(len(sf.usage)) > sfr.NewSectorCount/storageFolderGranularity {
    35  		// Unset the usage in all bits
    36  		for i := sfr.NewSectorCount; i < uint32(len(sf.usage))*storageFolderGranularity; i++ {
    37  			sf.clearUsage(i)
    38  		}
    39  		// Truncate the usage field.
    40  		sf.usage = sf.usage[:sfr.NewSectorCount/storageFolderGranularity]
    41  	}
    42  
    43  	// Truncate the storage folder.
    44  	err := sf.metadataFile.Truncate(int64(sfr.NewSectorCount * sectorMetadataDiskSize))
    45  	if err != nil {
    46  		wal.cm.log.Printf("Error: unable to truncate metadata file as storage folder %v is resized\n", sf.path)
    47  	}
    48  	err = sf.sectorFile.Truncate(int64(modules.SectorSize * uint64(sfr.NewSectorCount)))
    49  	if err != nil {
    50  		wal.cm.log.Printf("Error: unable to truncate sector file as storage folder %v is resized\n", sf.path)
    51  	}
    52  }
    53  
    54  // shrinkStoragefolder will truncate a storage folder, moving all of the
    55  // sectors in the truncated space to new storage folders.
    56  func (wal *writeAheadLog) shrinkStorageFolder(index uint16, newSectorCount uint32, force bool) error {
    57  	// Retrieve the specified storage folder.
    58  	wal.mu.Lock()
    59  	sf, exists := wal.cm.storageFolders[index]
    60  	wal.mu.Unlock()
    61  	if !exists {
    62  		return errStorageFolderNotFound
    63  	}
    64  	if atomic.LoadUint64(&sf.atomicUnavailable) == 1 {
    65  		// TODO: Better error.
    66  		return errStorageFolderNotFound
    67  	}
    68  
    69  	// Lock the storage folder for the duration of the operation.
    70  	sf.mu.Lock()
    71  	defer sf.mu.Unlock()
    72  
    73  	// Clear out the sectors in the storage folder.
    74  	_, err := wal.managedEmptyStorageFolder(index, newSectorCount)
    75  	if err != nil && !force {
    76  		return err
    77  	}
    78  
    79  	// Wait for a synchronize to confirm that all of the moves have succeeded
    80  	// in full.
    81  	wal.mu.Lock()
    82  	syncChan := wal.syncChan
    83  	wal.mu.Unlock()
    84  	<-syncChan
    85  
    86  	// Allow unclean shutdown to be simulated by returning before the state
    87  	// change gets committed.
    88  	if wal.cm.dependencies.Disrupt("incompleteShrinkStorageFolder") {
    89  		return nil
    90  	}
    91  
    92  	// Submit a storage folder truncation to the WAL and wait until the update
    93  	// is synced.
    94  	wal.mu.Lock()
    95  	wal.appendChange(stateChange{
    96  		StorageFolderReductions: []storageFolderReduction{{
    97  			Index:          index,
    98  			NewSectorCount: newSectorCount,
    99  		}},
   100  	})
   101  	syncChan = wal.syncChan
   102  	wal.mu.Unlock()
   103  
   104  	// Wait until the shrink action has been synchronized.
   105  	<-syncChan
   106  	return nil
   107  }