| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194 | // Copyright 2015 The etcd Authors//// Licensed under the Apache License, Version 2.0 (the "License");// you may not use this file except in compliance with the License.// You may obtain a copy of the License at////     http://www.apache.org/licenses/LICENSE-2.0//// Unless required by applicable law or agreed to in writing, software// distributed under the License is distributed on an "AS IS" BASIS,// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.// See the License for the specific language governing permissions and// limitations under the License.package mvccimport (	"bytes"	"errors"	"sync"	"go.etcd.io/etcd/mvcc/mvccpb")// AutoWatchID is the watcher ID passed in WatchStream.Watch when no// user-provided ID is available. If pass, an ID will automatically be assigned.const AutoWatchID WatchID = 0var (	ErrWatcherNotExist    = errors.New("mvcc: watcher does not exist")	ErrEmptyWatcherRange  = errors.New("mvcc: watcher range is empty")	ErrWatcherDuplicateID = errors.New("mvcc: duplicate watch ID provided on the WatchStream"))type WatchID int64// FilterFunc returns true if the given event should be filtered out.type FilterFunc func(e mvccpb.Event) booltype WatchStream interface {	// Watch creates a watcher. The watcher watches the events happening or	// happened on the given key or range [key, end) from the given startRev.	//	// The whole event history can be watched unless compacted.	// If "startRev" <=0, watch observes events after currentRev.	//	// The returned "id" is the ID of this watcher. It appears as WatchID	// in events that are sent to the created watcher through stream channel.	// The watch ID is used when it's not equal to AutoWatchID. Otherwise,	// an auto-generated watch ID is returned.	Watch(id WatchID, key, end []byte, startRev int64, fcs ...FilterFunc) (WatchID, error)	// Chan returns a chan. All watch response will be sent to the returned chan.	Chan() <-chan WatchResponse	// RequestProgress requests the progress of the watcher with given ID. The response	// will only be sent if the watcher is currently synced.	// The responses will be sent through the WatchRespone Chan attached	// with this stream to ensure correct ordering.	// The responses contains no events. The revision in the response is the progress	// of the watchers since the watcher is currently synced.	RequestProgress(id WatchID)	// Cancel cancels a watcher by giving its ID. If watcher does not exist, an error will be	// returned.	Cancel(id WatchID) error	// Close closes Chan and release all related resources.	Close()	// Rev returns the current revision of the KV the stream watches on.	Rev() int64}type WatchResponse struct {	// WatchID is the WatchID of the watcher this response sent to.	WatchID WatchID	// Events contains all the events that needs to send.	Events []mvccpb.Event	// Revision is the revision of the KV when the watchResponse is created.	// For a normal response, the revision should be the same as the last	// modified revision inside Events. For a delayed response to a unsynced	// watcher, the revision is greater than the last modified revision	// inside Events.	Revision int64	// CompactRevision is set when the watcher is cancelled due to compaction.	CompactRevision int64}// watchStream contains a collection of watchers that share// one streaming chan to send out watched events and other control events.type watchStream struct {	watchable watchable	ch        chan WatchResponse	mu sync.Mutex // guards fields below it	// nextID is the ID pre-allocated for next new watcher in this stream	nextID   WatchID	closed   bool	cancels  map[WatchID]cancelFunc	watchers map[WatchID]*watcher}// Watch creates a new watcher in the stream and returns its WatchID.func (ws *watchStream) Watch(id WatchID, key, end []byte, startRev int64, fcs ...FilterFunc) (WatchID, error) {	// prevent wrong range where key >= end lexicographically	// watch request with 'WithFromKey' has empty-byte range end	if len(end) != 0 && bytes.Compare(key, end) != -1 {		return -1, ErrEmptyWatcherRange	}	ws.mu.Lock()	defer ws.mu.Unlock()	if ws.closed {		return -1, ErrEmptyWatcherRange	}	if id == AutoWatchID {		for ws.watchers[ws.nextID] != nil {			ws.nextID++		}		id = ws.nextID		ws.nextID++	} else if _, ok := ws.watchers[id]; ok {		return -1, ErrWatcherDuplicateID	}	w, c := ws.watchable.watch(key, end, startRev, id, ws.ch, fcs...)	ws.cancels[id] = c	ws.watchers[id] = w	return id, nil}func (ws *watchStream) Chan() <-chan WatchResponse {	return ws.ch}func (ws *watchStream) Cancel(id WatchID) error {	ws.mu.Lock()	cancel, ok := ws.cancels[id]	w := ws.watchers[id]	ok = ok && !ws.closed	ws.mu.Unlock()	if !ok {		return ErrWatcherNotExist	}	cancel()	ws.mu.Lock()	// The watch isn't removed until cancel so that if Close() is called,	// it will wait for the cancel. Otherwise, Close() could close the	// watch channel while the store is still posting events.	if ww := ws.watchers[id]; ww == w {		delete(ws.cancels, id)		delete(ws.watchers, id)	}	ws.mu.Unlock()	return nil}func (ws *watchStream) Close() {	ws.mu.Lock()	defer ws.mu.Unlock()	for _, cancel := range ws.cancels {		cancel()	}	ws.closed = true	close(ws.ch)	watchStreamGauge.Dec()}func (ws *watchStream) Rev() int64 {	ws.mu.Lock()	defer ws.mu.Unlock()	return ws.watchable.rev()}func (ws *watchStream) RequestProgress(id WatchID) {	ws.mu.Lock()	w, ok := ws.watchers[id]	ws.mu.Unlock()	if !ok {		return	}	ws.watchable.progress(w)}
 |