github.com/ghodss/etcd@v0.3.1-0.20140417172404-cc329bfa55cb/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 }