topic_stat.go 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. // package topic_stat -- небольшая статистика топика
  2. package topic_stat
  3. import (
  4. "fmt"
  5. "sync"
  6. "p78git.ddns.net/svi/gobus/api/netapi"
  7. "p78git.ddns.net/svi/gobus/pkg/alias"
  8. "p78git.ddns.net/svi/gobus/pkg/types"
  9. )
  10. // TopicStat -- небольшая статистика топика
  11. type TopicStat struct {
  12. countMsg int // Количество прокрученных сообщений
  13. countTraff int // Счётчик прокрученного траффика
  14. countErr int // Количество ошибок топика
  15. topicName alias.TopicName // Имя топика
  16. size int // Размер топика
  17. block sync.RWMutex
  18. }
  19. // NewTopicStat -- возвращает статистику топика
  20. func NewTopicStat(msg *netapi.TopicMsg) (*TopicStat, error) {
  21. { // Предусловия
  22. if msg == nil {
  23. return nil, fmt.Errorf("NewTopicStat(): TopicMsg==nil")
  24. }
  25. if msg.Topic == "" {
  26. return nil, fmt.Errorf("NewTopicStat(): topicName is empty")
  27. }
  28. }
  29. sf := &TopicStat{
  30. topicName: alias.TopicName(msg.Topic),
  31. }
  32. _ = types.ITopicStat(sf)
  33. return sf, nil
  34. }
  35. // Size -- возвращает текущий размер топика
  36. func (sf *TopicStat) Size() int {
  37. sf.block.RLock()
  38. defer sf.block.RUnlock()
  39. return sf.size
  40. }
  41. // CountTraff -- возвращает количество траффика пропущенного через топик
  42. func (sf *TopicStat) CountTraff() int {
  43. sf.block.RLock()
  44. defer sf.block.RUnlock()
  45. return sf.countTraff
  46. }
  47. // CountMsg -- возвращает количество сообщений пропущенных через топик
  48. func (sf *TopicStat) CountMsg() int {
  49. sf.block.RLock()
  50. defer sf.block.RUnlock()
  51. return sf.countMsg
  52. }
  53. // CountErr -- возвращает количество ошибок счётчика
  54. func (sf *TopicStat) CountErr() int {
  55. sf.block.RLock()
  56. defer sf.block.RUnlock()
  57. return sf.countErr
  58. }
  59. // Name -- возвращает имя топика
  60. func (sf *TopicStat) Name() alias.TopicName {
  61. return sf.topicName
  62. }
  63. const (
  64. lenHelper = 24 // Длина UUID и номера источника
  65. )
  66. // Update -- обновляет статистику
  67. func (sf *TopicStat) Update(msg *netapi.TopicMsg) error {
  68. sf.block.Lock()
  69. defer sf.block.Unlock()
  70. sf.countMsg++
  71. if msg == nil {
  72. sf.countErr++
  73. return fmt.Errorf("TopicStat.Update(): TopicMsg==nil")
  74. }
  75. if err := sf.check(msg); err != nil {
  76. sf.countErr++
  77. return fmt.Errorf("TopicStat.Update(): in check msg, err=\n\t%w", err)
  78. }
  79. sf.size = len(msg.BinMsg) + len(sf.topicName) + lenHelper
  80. sf.countTraff += sf.size
  81. return nil
  82. }
  83. // Проверяет под блокировкой верхнего уровня правильность сообщения
  84. func (sf *TopicStat) check(msg *netapi.TopicMsg) error {
  85. if msg.Topic != string(sf.topicName) {
  86. return fmt.Errorf("TopicStat.check(): msg.Topic(%q)!=%q", msg.Topic, sf.topicName)
  87. }
  88. if len(msg.StrUuid) != 20 {
  89. return fmt.Errorf("TopicStat.check(): len msg.StrUuuid(%v)!=20", len(msg.StrUuid))
  90. }
  91. return nil
  92. }