stats_queue.go 1.7 KB

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