github.com/johnathanhowell/sia@v0.5.1-beta.0.20160524050156-83dcc3d37c94/modules/host/storagemanager/consistency.go (about)

     1  package storagemanager
     2  
     3  import (
     4  	"errors"
     5  )
     6  
     7  // consistency.go contains a bunch of consistency checks for the host. Because
     8  // a lot of the consistency is checking that different parts of the host match
     9  // up, it was decided that all consistency checking should go into a single
    10  // file. As an example, the state of the storage obligations sets the standard
    11  // for what it means for the storage folders to be consistent. And the storage
    12  // folders set the standard for what it means for the sectors to be consistent.
    13  //
    14  // Consistency checks should be run infrequently, and should take only a minute
    15  // or two to complete, even for a host that has millions of sectors. This means
    16  // that certain consistency checks are off-limits.
    17  
    18  // TODO: Check that 'Path' and the symlinked path point to the same place.
    19  
    20  // TODO: Consistency checks should be accompanied by repair tools. Perhaps that
    21  // means instead of calling build.Critical... it just returns some sort of
    22  // diagnostic?
    23  
    24  var (
    25  	// errStorageFolderMaxSizeExceeded is returned when a storage folder is
    26  	// found to have exceeded the maximum set by the build constants.
    27  	errStorageFolderMaxSizeExceeded = errors.New("storage folder has exceeded the maximum allowed size")
    28  
    29  	// errStorageFolderMinSizeViolated is returned when a storage folder has a
    30  	// size which is smaller than the minimum set by the build constants.
    31  	errStorageFolderMinSizeViolated = errors.New("storage folder has less storage than the minimum allowed")
    32  
    33  	// errStorageFolderSizeRemainingDivergence is returned when a storage
    34  	// folder has an amount of storage remaining that indicates an impossible
    35  	// state, such as having more storage remaining than total storage
    36  	// available.
    37  	errStorageFolderSizeRemainingDivergence = errors.New("storage folder has an impossible size remaining value")
    38  
    39  	// errStorageFolderInvalidUIDLen is returned when a storage folder has a
    40  	// UID which has the wrong length.
    41  	errStorageFolderInvalidUIDLen = errors.New("storage folder has a UID with an invalid length, often indicating the wrong build of 'siad' is being used")
    42  
    43  	// errStorageFolderDuplicateUID is returned when a storage folder has a UID
    44  	// which is known to already be owned by a different storage folder.
    45  	errStorageFolderDuplicateUID = errors.New("storage folder has a UID which is already owned by another storage folder")
    46  )
    47  
    48  // storageFolderSizeConsistency checks that all of the storage folders have
    49  // sane sizes.
    50  func (sm *StorageManager) storageFolderSizeConsistency() error {
    51  	knownUIDs := make(map[string]int)
    52  	for i, sf := range sm.storageFolders {
    53  		// The size of a storage folder should be between the minimum and the
    54  		// maximum allowed size.
    55  		if sf.Size > maximumStorageFolderSize {
    56  			sm.log.Critical("storage folder", i, "exceeds the maximum allowed storage folder size")
    57  			return errStorageFolderMaxSizeExceeded
    58  		}
    59  		if sf.Size < minimumStorageFolderSize {
    60  			sm.log.Critical("storage folder", i, "has less than the minimum allowed storage folder size")
    61  			return errStorageFolderMinSizeViolated
    62  		}
    63  
    64  		// The amount of storage remaining should not be greater than the
    65  		// folder size.
    66  		if sf.SizeRemaining > sf.Size {
    67  			sm.log.Critical("storage folder", i, "has more storage remaining than it has storage total")
    68  			return errStorageFolderSizeRemainingDivergence
    69  		}
    70  
    71  		// The UID has a fixed size.
    72  		if len(sf.UID) != storageFolderUIDSize {
    73  			sm.log.Critical("storage folder", i, "has an ID which is not valid")
    74  			return errStorageFolderInvalidUIDLen
    75  		}
    76  
    77  		// Check that the storage folder UID is not conflicting with any other
    78  		// known storage folder UID.
    79  		conflict, exists := knownUIDs[sf.uidString()]
    80  		if exists {
    81  			sm.log.Critical("storage folder", i, "has a duplicate UID, conflicting with storage folder", conflict)
    82  			return errStorageFolderDuplicateUID
    83  		}
    84  		// Add this storage folder's UID to the set of known UIDs.
    85  		knownUIDs[sf.uidString()] = i
    86  	}
    87  	return nil
    88  }