gitlab.com/SiaPrime/SiaPrime@v1.4.1/modules/renter/stuckstack.go (about)

     1  package renter
     2  
     3  import (
     4  	"sync"
     5  
     6  	"gitlab.com/SiaPrime/SiaPrime/modules"
     7  )
     8  
     9  type (
    10  	// stuckStack contains a LIFO stack of files that have had a stuck chunk
    11  	// successfully repaired
    12  	stuckStack struct {
    13  		stack    []modules.SiaPath
    14  		siaPaths map[modules.SiaPath]struct{}
    15  
    16  		mu sync.Mutex
    17  	}
    18  )
    19  
    20  // callNewStuckStack returns an initialized stuckStack
    21  func callNewStuckStack() stuckStack {
    22  	return stuckStack{
    23  		stack:    make([]modules.SiaPath, 0, maxSuccessfulStuckRepairFiles),
    24  		siaPaths: make(map[modules.SiaPath]struct{}),
    25  	}
    26  }
    27  
    28  // managedLen returns the length of the stack
    29  func (ss *stuckStack) managedLen() int {
    30  	ss.mu.Lock()
    31  	defer ss.mu.Unlock()
    32  	return len(ss.stack)
    33  }
    34  
    35  // managedPop returns the top element in the stack
    36  func (ss *stuckStack) managedPop() (sp modules.SiaPath) {
    37  	ss.mu.Lock()
    38  	defer ss.mu.Unlock()
    39  
    40  	// Check that there are elements to return
    41  	if len(ss.stack) == 0 {
    42  		return
    43  	}
    44  
    45  	// Pop top element
    46  	sp, ss.stack = ss.stack[len(ss.stack)-1], ss.stack[:len(ss.stack)-1]
    47  	delete(ss.siaPaths, sp)
    48  	return
    49  }
    50  
    51  // managedPush tries to add a file to the stack
    52  func (ss *stuckStack) managedPush(siaPath modules.SiaPath) {
    53  	ss.mu.Lock()
    54  	defer ss.mu.Unlock()
    55  
    56  	// Check if there is room in the stack
    57  	if len(ss.stack) >= maxSuccessfulStuckRepairFiles {
    58  		// Prune oldest elements
    59  		pruneToIndex := len(ss.stack) - maxSuccessfulStuckRepairFiles + 1
    60  		ss.stack = ss.stack[pruneToIndex:]
    61  	}
    62  
    63  	// Check if the file is already being tracked
    64  	if _, ok := ss.siaPaths[siaPath]; ok {
    65  		// Remove the old entry from the array
    66  		//
    67  		// NOTE: currently just iterating over the array since the array is
    68  		// known to be very small. If this changes in the future a heap or
    69  		// linked list should be used in order to avoid this slow iteration
    70  		for i, sp := range ss.stack {
    71  			if !siaPath.Equals(sp) {
    72  				continue
    73  			}
    74  			ss.stack = append(ss.stack[:i], ss.stack[i+1:]...)
    75  			break
    76  		}
    77  	}
    78  
    79  	// Add file to the stack
    80  	ss.stack = append(ss.stack, siaPath)
    81  	ss.siaPaths[siaPath] = struct{}{}
    82  	return
    83  }