You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

97 lines
2.2 KiB

  1. package broker
  2. import (
  3. "fmt"
  4. "sync"
  5. "time"
  6. "github.com/chrislusf/seaweedfs/weed/filer2"
  7. "github.com/chrislusf/seaweedfs/weed/glog"
  8. "github.com/chrislusf/seaweedfs/weed/pb/messaging_pb"
  9. "github.com/chrislusf/seaweedfs/weed/util/log_buffer"
  10. )
  11. type TopicPartition struct {
  12. Namespace string
  13. Topic string
  14. Partition int32
  15. }
  16. type TopicLock struct {
  17. sync.Mutex
  18. cond *sync.Cond
  19. subscriberCount int
  20. publisherCount int
  21. logBuffer *log_buffer.LogBuffer
  22. }
  23. type TopicLocks struct {
  24. sync.Mutex
  25. locks map[TopicPartition]*TopicLock
  26. broker *MessageBroker
  27. }
  28. func NewTopicLocks(messageBroker *MessageBroker) *TopicLocks {
  29. return &TopicLocks{
  30. locks: make(map[TopicPartition]*TopicLock),
  31. broker: messageBroker,
  32. }
  33. }
  34. func (locks *TopicLocks) buildLogBuffer(tl *TopicLock, tp TopicPartition, topicConfig *messaging_pb.TopicConfiguration) *log_buffer.LogBuffer {
  35. flushFn := func(startTime, stopTime time.Time, buf []byte) {
  36. targetFile := fmt.Sprintf(
  37. "%s/%s/%s/%04d-%02d-%02d/%02d-%02d.part%02d",
  38. filer2.TopicsDir, tp.Namespace, tp.Topic,
  39. startTime.Year(), startTime.Month(), startTime.Day(), startTime.Hour(), startTime.Minute(),
  40. tp.Partition,
  41. )
  42. if err := locks.broker.appendToFile(targetFile, topicConfig, buf); err != nil {
  43. glog.V(0).Infof("log write failed %s: %v", targetFile, err)
  44. }
  45. }
  46. logBuffer := log_buffer.NewLogBuffer(time.Minute, flushFn, func() {
  47. tl.cond.Broadcast()
  48. })
  49. return logBuffer
  50. }
  51. func (tl *TopicLocks) RequestLock(partition TopicPartition, topicConfig *messaging_pb.TopicConfiguration, isPublisher bool) *TopicLock {
  52. tl.Lock()
  53. defer tl.Unlock()
  54. lock, found := tl.locks[partition]
  55. if !found {
  56. lock = &TopicLock{}
  57. lock.cond = sync.NewCond(&lock.Mutex)
  58. tl.locks[partition] = lock
  59. lock.logBuffer = tl.buildLogBuffer(lock, partition, topicConfig)
  60. }
  61. if isPublisher {
  62. lock.publisherCount++
  63. } else {
  64. lock.subscriberCount++
  65. }
  66. return lock
  67. }
  68. func (tl *TopicLocks) ReleaseLock(partition TopicPartition, isPublisher bool) {
  69. tl.Lock()
  70. defer tl.Unlock()
  71. lock, found := tl.locks[partition]
  72. if !found {
  73. return
  74. }
  75. if isPublisher {
  76. lock.publisherCount--
  77. } else {
  78. lock.subscriberCount--
  79. }
  80. if lock.subscriberCount <= 0 && lock.publisherCount <= 0 {
  81. delete(tl.locks, partition)
  82. }
  83. }