stats_queue.go 1.7 KB

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