gitlab.com/SkynetLabs/skyd@v1.6.9/skymodules/renter/hostdb/hostentry.go (about)

     1  package hostdb
     2  
     3  import (
     4  	"math"
     5  
     6  	"gitlab.com/NebulousLabs/errors"
     7  	"gitlab.com/SkynetLabs/skyd/skymodules"
     8  	"go.sia.tech/siad/types"
     9  )
    10  
    11  // updateHostDBEntry updates a HostDBEntries's historic interactions if more
    12  // than one block passed since the last update. This should be called every time
    13  // before the recent interactions are updated.  if passedTime is e.g. 10, this
    14  // means that the recent interactions were updated 10 blocks ago but never
    15  // since. So we need to apply the decay of 1 block before we append the recent
    16  // interactions from 10 blocks ago and then apply the decay of 9 more blocks in
    17  // which the recent interactions have been 0
    18  func updateHostHistoricInteractions(host *skymodules.HostDBEntry, bh types.BlockHeight) {
    19  	// Check that the last historic update was not in the future.
    20  	if host.LastHistoricUpdate >= bh {
    21  		// The hostdb may be performing a rescan, or maybe no time has passed
    22  		// since the last update, so there is nothing to do.
    23  		return
    24  	}
    25  	passedTime := bh - host.LastHistoricUpdate
    26  
    27  	// tmp float64 values for more accurate decay
    28  	hsi := host.HistoricSuccessfulInteractions
    29  	hfi := host.HistoricFailedInteractions
    30  
    31  	// Apply the decay of a single block.
    32  	decay := historicInteractionDecay
    33  	hsi *= decay
    34  	hfi *= decay
    35  
    36  	// Apply the recent interactions of that single block. Recent interactions
    37  	// cannot represent more than recentInteractionWeightLimit of historic
    38  	// interactions, unless there are less than historicInteractionDecayLimit
    39  	// total interactions, and then the recent interactions cannot count for
    40  	// more than recentInteractionWeightLimit of the decay limit.
    41  	rsi := float64(host.RecentSuccessfulInteractions)
    42  	rfi := float64(host.RecentFailedInteractions)
    43  	if hsi+hfi > historicInteractionDecayLimit {
    44  		if rsi+rfi > recentInteractionWeightLimit*(hsi+hfi) {
    45  			adjustment := recentInteractionWeightLimit * (hsi + hfi) / (rsi + rfi)
    46  			rsi *= adjustment
    47  			rfi *= adjustment
    48  		}
    49  	} else {
    50  		if rsi+rfi > recentInteractionWeightLimit*historicInteractionDecayLimit {
    51  			adjustment := recentInteractionWeightLimit * historicInteractionDecayLimit / (rsi + rfi)
    52  			rsi *= adjustment
    53  			rfi *= adjustment
    54  		}
    55  	}
    56  	hsi += rsi
    57  	hfi += rfi
    58  
    59  	// Apply the decay of the rest of the blocks
    60  	if passedTime > 1 && hsi+hfi > historicInteractionDecayLimit {
    61  		decay := math.Pow(historicInteractionDecay, float64(passedTime-1))
    62  		hsi *= decay
    63  		hfi *= decay
    64  	}
    65  
    66  	// Set new values
    67  	host.HistoricSuccessfulInteractions = hsi
    68  	host.HistoricFailedInteractions = hfi
    69  	host.RecentSuccessfulInteractions = 0
    70  	host.RecentFailedInteractions = 0
    71  
    72  	// Update the time of the last update
    73  	host.LastHistoricUpdate = bh
    74  }
    75  
    76  // IncrementSuccessfulInteractions increments the number of successful
    77  // interactions with a host for a given key
    78  func (hdb *HostDB) IncrementSuccessfulInteractions(key types.SiaPublicKey) error {
    79  	if err := hdb.tg.Add(); err != nil {
    80  		return errors.AddContext(err, "error adding hostdb threadgroup:")
    81  	}
    82  	defer hdb.tg.Done()
    83  
    84  	hdb.mu.Lock()
    85  	defer hdb.mu.Unlock()
    86  
    87  	// Fetch the host.
    88  	host, haveHost := hdb.staticHostTree.Select(key)
    89  	if !haveHost {
    90  		return errors.AddContext(errHostNotFoundInTree, "unable to increment successful interaction:")
    91  	}
    92  
    93  	// Update historic values if necessary
    94  	updateHostHistoricInteractions(&host, hdb.blockHeight)
    95  
    96  	// Increment the successful interactions
    97  	host.RecentSuccessfulInteractions++
    98  	hdb.staticHostTree.Modify(host)
    99  	return nil
   100  }
   101  
   102  // IncrementFailedInteractions increments the number of failed interactions with
   103  // a host for a given key
   104  func (hdb *HostDB) IncrementFailedInteractions(key types.SiaPublicKey) error {
   105  	if err := hdb.tg.Add(); err != nil {
   106  		return errors.AddContext(err, "error adding hostdb threadgroup:")
   107  	}
   108  	defer hdb.tg.Done()
   109  
   110  	// If we are offline it probably wasn't the host's fault
   111  	if !hdb.staticGateway.Online() {
   112  		return nil
   113  	}
   114  
   115  	hdb.mu.Lock()
   116  	defer hdb.mu.Unlock()
   117  
   118  	// Fetch the host.
   119  	host, haveHost := hdb.staticHostTree.Select(key)
   120  	if !haveHost {
   121  		return errors.AddContext(errHostNotFoundInTree, "unable to increment failed interaction:")
   122  	}
   123  
   124  	// Update historic values if necessary
   125  	updateHostHistoricInteractions(&host, hdb.blockHeight)
   126  
   127  	// Increment the failed interactions
   128  	host.RecentFailedInteractions++
   129  	hdb.staticHostTree.Modify(host)
   130  	return nil
   131  }