github.com/rosedblabs/rosedb/v2@v2.3.7-0.20240423093736-a89ea823e5b9/watch.go (about)

     1  package rosedb
     2  
     3  import (
     4  	"sync"
     5  	"time"
     6  )
     7  
     8  type WatchActionType = byte
     9  
    10  const (
    11  	WatchActionPut WatchActionType = iota
    12  	WatchActionDelete
    13  )
    14  
    15  // Event is the event that occurs when the database is modified.
    16  // It is used to synchronize the watch of the database.
    17  type Event struct {
    18  	Action  WatchActionType
    19  	Key     []byte
    20  	Value   []byte
    21  	BatchId uint64
    22  }
    23  
    24  // Watcher temporarily stores event information,
    25  // as it is generated until it is synchronized to DB's watch.
    26  //
    27  // If the event is overflow, It will remove the oldest data,
    28  // even if event hasn't been read yet.
    29  type Watcher struct {
    30  	queue eventQueue
    31  	mu    sync.RWMutex
    32  }
    33  
    34  func NewWatcher(capacity uint64) *Watcher {
    35  	return &Watcher{
    36  		queue: eventQueue{
    37  			Events:   make([]*Event, capacity),
    38  			Capacity: capacity,
    39  		},
    40  	}
    41  }
    42  
    43  func (w *Watcher) putEvent(e *Event) {
    44  	w.mu.Lock()
    45  	w.queue.push(e)
    46  	if w.queue.isFull() {
    47  		w.queue.frontTakeAStep()
    48  	}
    49  	w.mu.Unlock()
    50  }
    51  
    52  // getEvent if queue is empty, it will return nil.
    53  func (w *Watcher) getEvent() *Event {
    54  	w.mu.RLock()
    55  	defer w.mu.RUnlock()
    56  	if w.queue.isEmpty() {
    57  		return nil
    58  	}
    59  	return w.queue.pop()
    60  }
    61  
    62  // sendEvent send events to DB's watch
    63  func (w *Watcher) sendEvent(c chan *Event) {
    64  	for {
    65  		event := w.getEvent()
    66  		if event == nil {
    67  			time.Sleep(100 * time.Millisecond)
    68  			continue
    69  		}
    70  		c <- event
    71  	}
    72  }
    73  
    74  type eventQueue struct {
    75  	Events   []*Event
    76  	Capacity uint64
    77  	Front    uint64 // read point
    78  	Back     uint64 // write point
    79  }
    80  
    81  func (eq *eventQueue) push(e *Event) {
    82  	eq.Events[eq.Back] = e
    83  	eq.Back = (eq.Back + 1) % eq.Capacity
    84  }
    85  
    86  func (eq *eventQueue) pop() *Event {
    87  	e := eq.Events[eq.Front]
    88  	eq.frontTakeAStep()
    89  	return e
    90  }
    91  
    92  func (eq *eventQueue) isFull() bool {
    93  	return (eq.Back+1)%eq.Capacity == eq.Front
    94  }
    95  
    96  func (eq *eventQueue) isEmpty() bool {
    97  	return eq.Back == eq.Front
    98  }
    99  
   100  func (eq *eventQueue) frontTakeAStep() {
   101  	eq.Front = (eq.Front + 1) % eq.Capacity
   102  }