stats_queue.go 1.7 KB

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