Implement Cacher for watch in apiserver

This commit is contained in:
Wojciech Tyczynski
2015-07-28 08:26:53 +02:00
parent 8dcbebae5e
commit e424da7d0d
5 changed files with 703 additions and 18 deletions

View File

@@ -170,30 +170,27 @@ func (r *Reflector) resyncChan() (<-chan time.Time, func() bool) {
return t.C, t.Stop
}
func (r *Reflector) ListAndWatch(stopCh <-chan struct{}) {
// Returns error if ListAndWatch didn't even tried to initialize watch.
func (r *Reflector) ListAndWatch(stopCh <-chan struct{}) error {
var resourceVersion string
resyncCh, cleanup := r.resyncChan()
defer cleanup()
list, err := r.listerWatcher.List()
if err != nil {
util.HandleError(fmt.Errorf("%s: Failed to list %v: %v", r.name, r.expectedType, err))
return
return fmt.Errorf("%s: Failed to list %v: %v", r.name, r.expectedType, err)
}
meta, err := meta.Accessor(list)
if err != nil {
util.HandleError(fmt.Errorf("%s: Unable to understand list result %#v", r.name, list))
return
return fmt.Errorf("%s: Unable to understand list result %#v", r.name, list)
}
resourceVersion = meta.ResourceVersion()
items, err := runtime.ExtractList(list)
if err != nil {
util.HandleError(fmt.Errorf("%s: Unable to understand list result %#v (%v)", r.name, list, err))
return
return fmt.Errorf("%s: Unable to understand list result %#v (%v)", r.name, list, err)
}
if err := r.syncWith(items, resourceVersion); err != nil {
util.HandleError(fmt.Errorf("%s: Unable to sync list result: %v", r.name, err))
return
return fmt.Errorf("%s: Unable to sync list result: %v", r.name, err)
}
r.setLastSyncResourceVersion(resourceVersion)
@@ -220,13 +217,13 @@ func (r *Reflector) ListAndWatch(stopCh <-chan struct{}) {
}
}
}
return
return nil
}
if err := r.watchHandler(w, &resourceVersion, resyncCh, stopCh); err != nil {
if err != errorResyncRequested && err != errorStopRequested {
glog.Warningf("%s: watch of %v ended with: %v", r.name, r.expectedType, err)
}
return
return nil
}
}
}
@@ -277,6 +274,7 @@ loop:
util.HandleError(fmt.Errorf("%s: unable to understand watch event %#v", r.name, event))
continue
}
newResourceVersion := meta.ResourceVersion()
switch event.Type {
case watch.Added:
r.store.Add(event.Object)
@@ -290,8 +288,8 @@ loop:
default:
util.HandleError(fmt.Errorf("%s: unable to understand watch event %#v", r.name, event))
}
*resourceVersion = meta.ResourceVersion()
r.setLastSyncResourceVersion(*resourceVersion)
*resourceVersion = newResourceVersion
r.setLastSyncResourceVersion(newResourceVersion)
eventCount++
}
}

View File

@@ -123,13 +123,20 @@ func objectToVersionedRuntimeObject(obj interface{}) (runtime.Object, uint64, er
if err != nil {
return nil, 0, err
}
resourceVersion, err := strconv.ParseUint(meta.ResourceVersion(), 10, 64)
resourceVersion, err := parseResourceVersion(meta.ResourceVersion())
if err != nil {
return nil, 0, err
}
return object, resourceVersion, nil
}
func parseResourceVersion(resourceVersion string) (uint64, error) {
if resourceVersion == "" {
return 0, nil
}
return strconv.ParseUint(resourceVersion, 10, 64)
}
func (w *WatchCache) processEvent(event watch.Event, resourceVersion uint64, updateFunc func(runtime.Object) error) error {
w.Lock()
defer w.Unlock()
@@ -186,7 +193,7 @@ func (w *WatchCache) Replace(objs []interface{}) error {
}
func (w *WatchCache) ReplaceWithVersion(objs []interface{}, resourceVersion string) error {
version, err := strconv.ParseUint(resourceVersion, 10, 64)
version, err := parseResourceVersion(resourceVersion)
if err != nil {
return err
}
@@ -227,15 +234,15 @@ func (w *WatchCache) GetAllEventsSince(resourceVersion uint64) ([]watch.Event, e
if size > 0 {
oldest = w.cache[w.startIndex%w.capacity].resourceVersion
}
if resourceVersion < oldest {
return nil, fmt.Errorf("too old resource version: %d (%d)", resourceVersion, oldest)
}
// Binary seatch the smallest index at which resourceVersion is not smaller than
// the given one.
f := func(i int) bool {
return w.cache[(w.startIndex+i)%w.capacity].resourceVersion >= resourceVersion
}
if size > 0 && resourceVersion < oldest {
return nil, fmt.Errorf("too old resource version: %d (%d)", resourceVersion, oldest)
}
first := sort.Search(size, f)
result := make([]watch.Event, size-first)
for i := 0; i < size-first; i++ {