go.dedis.ch/onet/v4@v4.0.0-pre1/simul/monitor/bucket_stats.go (about)

     1  package monitor
     2  
     3  import (
     4  	"strconv"
     5  	"strings"
     6  
     7  	"golang.org/x/xerrors"
     8  )
     9  
    10  // bucketRule represents a filter that will tell if a measure must
    11  // be added to a bucket. It follows the logic of a slice indexing
    12  // so that the lower index is inclusive and the upper one is exclusive.
    13  type bucketRule struct {
    14  	low  int
    15  	high int
    16  }
    17  
    18  // newBucketRule takes a string and parses it to instantiate
    19  // a bucket rule.
    20  func newBucketRule(r string) (rule bucketRule, err error) {
    21  	parts := strings.Split(r, ":")
    22  	if len(parts) != 2 {
    23  		err = xerrors.New("malformed rule")
    24  		return
    25  	}
    26  
    27  	rule.low, err = strconv.Atoi(parts[0])
    28  	if err != nil {
    29  		err = xerrors.Errorf("atoi: %v", err)
    30  		return
    31  	}
    32  
    33  	rule.high, err = strconv.Atoi(parts[1])
    34  	if err != nil {
    35  		err = xerrors.Errorf("atoi: %v", err)
    36  		return
    37  	}
    38  
    39  	return
    40  }
    41  
    42  // Match returns true when the index is accepted by the rule, false
    43  // otherwise.
    44  func (r bucketRule) Match(index int) bool {
    45  	return index >= r.low && index < r.high
    46  }
    47  
    48  type bucketRules []bucketRule
    49  
    50  // Match returns true when at least one of the rule accepts the host
    51  // index.
    52  func (rr bucketRules) Match(host int) bool {
    53  	if host < 0 {
    54  		// a value below is considered as an invalid host index
    55  		return false
    56  	}
    57  
    58  	for _, rule := range rr {
    59  		if rule.Match(host) {
    60  			return true
    61  		}
    62  	}
    63  
    64  	return false
    65  }
    66  
    67  // BucketStats splits the statistics into buckets according to network addresses
    68  // and associated rules
    69  type BucketStats struct {
    70  	rules   map[int]bucketRules
    71  	buckets map[int]*Stats
    72  }
    73  
    74  func newBucketStats() *BucketStats {
    75  	return &BucketStats{
    76  		rules:   make(map[int]bucketRules),
    77  		buckets: make(map[int]*Stats),
    78  	}
    79  }
    80  
    81  // Set creates a new bucket at the given index that uses the rules to filter
    82  // incoming measures
    83  func (bs *BucketStats) Set(index int, rules []string, stats *Stats) error {
    84  	bs.rules[index] = make(bucketRules, len(rules))
    85  	for i, str := range rules {
    86  		rule, err := newBucketRule(str)
    87  		if err != nil {
    88  			return xerrors.Errorf("bucket rule: %v", err)
    89  		}
    90  
    91  		bs.rules[index][i] = rule
    92  	}
    93  
    94  	bs.buckets[index] = stats
    95  	return nil
    96  }
    97  
    98  // Get returns the bucket at the given index if it exists, nil otherwise
    99  func (bs *BucketStats) Get(index int) *Stats {
   100  	s := bs.buckets[index]
   101  	if s != nil {
   102  		s.Collect()
   103  	}
   104  
   105  	return s
   106  }
   107  
   108  // Update takes a single measure and fill the buckets that will match
   109  // the host index if defined in the measure
   110  func (bs *BucketStats) Update(m *singleMeasure) {
   111  	for i, rr := range bs.rules {
   112  		if rr.Match(m.Host) {
   113  			bs.buckets[i].Update(m)
   114  		}
   115  	}
   116  }