github.com/matm/etcd@v0.3.1-0.20140328024009-5b4a473f1453/server/stats_queue.go (about)

     1  package server
     2  
     3  import (
     4  	"sync"
     5  	"time"
     6  )
     7  
     8  const (
     9  	queueCapacity = 200
    10  )
    11  
    12  type statsQueue struct {
    13  	items        [queueCapacity]*packageStats
    14  	size         int
    15  	front        int
    16  	back         int
    17  	totalPkgSize int
    18  	rwl          sync.RWMutex
    19  }
    20  
    21  func (q *statsQueue) Len() int {
    22  	return q.size
    23  }
    24  
    25  func (q *statsQueue) PkgSize() int {
    26  	return q.totalPkgSize
    27  }
    28  
    29  // FrontAndBack gets the front and back elements in the queue
    30  // We must grab front and back together with the protection of the lock
    31  func (q *statsQueue) frontAndBack() (*packageStats, *packageStats) {
    32  	q.rwl.RLock()
    33  	defer q.rwl.RUnlock()
    34  	if q.size != 0 {
    35  		return q.items[q.front], q.items[q.back]
    36  	}
    37  	return nil, nil
    38  }
    39  
    40  // Insert function insert a packageStats into the queue and update the records
    41  func (q *statsQueue) Insert(p *packageStats) {
    42  	q.rwl.Lock()
    43  	defer q.rwl.Unlock()
    44  
    45  	q.back = (q.back + 1) % queueCapacity
    46  
    47  	if q.size == queueCapacity { //dequeue
    48  		q.totalPkgSize -= q.items[q.front].size
    49  		q.front = (q.back + 1) % queueCapacity
    50  	} else {
    51  		q.size++
    52  	}
    53  
    54  	q.items[q.back] = p
    55  	q.totalPkgSize += q.items[q.back].size
    56  
    57  }
    58  
    59  // Rate function returns the package rate and byte rate
    60  func (q *statsQueue) Rate() (float64, float64) {
    61  	front, back := q.frontAndBack()
    62  
    63  	if front == nil || back == nil {
    64  		return 0, 0
    65  	}
    66  
    67  	if time.Now().Sub(back.Time()) > time.Second {
    68  		q.Clear()
    69  		return 0, 0
    70  	}
    71  
    72  	sampleDuration := back.Time().Sub(front.Time())
    73  
    74  	pr := float64(q.Len()) / float64(sampleDuration) * float64(time.Second)
    75  
    76  	br := float64(q.PkgSize()) / float64(sampleDuration) * float64(time.Second)
    77  
    78  	return pr, br
    79  }
    80  
    81  // Clear function clear up the statsQueue
    82  func (q *statsQueue) Clear() {
    83  	q.rwl.Lock()
    84  	defer q.rwl.Unlock()
    85  	q.back = -1
    86  	q.front = 0
    87  	q.size = 0
    88  	q.totalPkgSize = 0
    89  }