github.com/Synthesix/Sia@v1.3.3-0.20180413141344-f863baeed3ca/modules/renter/contractor/update.go (about)

     1  package contractor
     2  
     3  import (
     4  	"github.com/Synthesix/Sia/modules"
     5  	"github.com/Synthesix/Sia/types"
     6  )
     7  
     8  // managedArchiveContracts will figure out which contracts are no longer needed
     9  // and move them to the historic set of contracts.
    10  //
    11  // TODO: This function should be performed by threadedContractMaintenance.
    12  // threadedContractMaintenance will currently quit if there are no hosts, but it
    13  // should at least run this code before quitting.
    14  func (c *Contractor) managedArchiveContracts() {
    15  	err := c.tg.Add()
    16  	if err != nil {
    17  		return
    18  	}
    19  	defer c.tg.Done()
    20  
    21  	// Determine the current block height.
    22  	c.mu.RLock()
    23  	currentHeight := c.blockHeight
    24  	c.mu.RUnlock()
    25  
    26  	// Loop through the current set of contracts and migrate any expired ones to
    27  	// the set of old contracts.
    28  	var expired []types.FileContractID
    29  	for _, contract := range c.contracts.ViewAll() {
    30  		if currentHeight > contract.EndHeight {
    31  			id := contract.ID
    32  			c.mu.Lock()
    33  			c.oldContracts[id] = contract
    34  			c.mu.Unlock()
    35  			expired = append(expired, id)
    36  			c.log.Println("INFO: archived expired contract", id)
    37  		}
    38  	}
    39  
    40  	// Save.
    41  	c.mu.Lock()
    42  	c.save()
    43  	c.mu.Unlock()
    44  
    45  	// Delete all the expired contracts from the contract set.
    46  	for _, id := range expired {
    47  		if sc, ok := c.contracts.Acquire(id); ok {
    48  			c.contracts.Delete(sc)
    49  		}
    50  	}
    51  }
    52  
    53  // ProcessConsensusChange will be called by the consensus set every time there
    54  // is a change in the blockchain. Updates will always be called in order.
    55  func (c *Contractor) ProcessConsensusChange(cc modules.ConsensusChange) {
    56  	c.mu.Lock()
    57  	for _, block := range cc.RevertedBlocks {
    58  		if block.ID() != types.GenesisID {
    59  			c.blockHeight--
    60  		}
    61  	}
    62  	for _, block := range cc.AppliedBlocks {
    63  		if block.ID() != types.GenesisID {
    64  			c.blockHeight++
    65  		}
    66  	}
    67  
    68  	// If we have entered the next period, update currentPeriod
    69  	// NOTE: "period" refers to the duration of contracts, whereas "cycle"
    70  	// refers to how frequently the period metrics are reset.
    71  	// TODO: How to make this more explicit.
    72  	cycleLen := c.allowance.Period - c.allowance.RenewWindow
    73  	if c.blockHeight >= c.currentPeriod+cycleLen {
    74  		c.currentPeriod += cycleLen
    75  		// COMPATv1.0.4-lts
    76  		// if we were storing a special metrics contract, it will be invalid
    77  		// after we enter the next period.
    78  		delete(c.oldContracts, metricsContractID)
    79  	}
    80  
    81  	c.lastChange = cc.ID
    82  	err := c.save()
    83  	if err != nil {
    84  		c.log.Println("Unable to save while processing a consensus change:", err)
    85  	}
    86  	c.mu.Unlock()
    87  
    88  	// Perform contract maintenance if our blockchain is synced. Use a separate
    89  	// goroutine so that the rest of the contractor is not blocked during
    90  	// maintenance.
    91  	if cc.Synced {
    92  		go c.threadedContractMaintenance()
    93  		go c.managedArchiveContracts()
    94  	}
    95  }