OSDN Git Service

Thanos did someting
[bytom/vapor.git] / vendor / github.com / rjeczalik / notify / tree_recursive.go
diff --git a/vendor/github.com/rjeczalik/notify/tree_recursive.go b/vendor/github.com/rjeczalik/notify/tree_recursive.go
deleted file mode 100644 (file)
index 7f00dfe..0000000
+++ /dev/null
@@ -1,354 +0,0 @@
-// Copyright (c) 2014-2015 The Notify Authors. All rights reserved.
-// Use of this source code is governed by the MIT license that can be
-// found in the LICENSE file.
-
-package notify
-
-import "sync"
-
-// watchAdd TODO(rjeczalik)
-func watchAdd(nd node, c chan<- EventInfo, e Event) eventDiff {
-       diff := nd.Watch.Add(c, e)
-       if wp := nd.Child[""].Watch; len(wp) != 0 {
-               e = wp.Total()
-               diff[0] |= e
-               diff[1] |= e
-               if diff[0] == diff[1] {
-                       return none
-               }
-       }
-       return diff
-}
-
-// watchAddInactive TODO(rjeczalik)
-func watchAddInactive(nd node, c chan<- EventInfo, e Event) eventDiff {
-       wp := nd.Child[""].Watch
-       if wp == nil {
-               wp = make(watchpoint)
-               nd.Child[""] = node{Watch: wp}
-       }
-       diff := wp.Add(c, e)
-       e = nd.Watch.Total()
-       diff[0] |= e
-       diff[1] |= e
-       if diff[0] == diff[1] {
-               return none
-       }
-       return diff
-}
-
-// watchCopy TODO(rjeczalik)
-func watchCopy(src, dst node) {
-       for c, e := range src.Watch {
-               if c == nil {
-                       continue
-               }
-               watchAddInactive(dst, c, e)
-       }
-       if wpsrc := src.Child[""].Watch; len(wpsrc) != 0 {
-               wpdst := dst.Child[""].Watch
-               for c, e := range wpsrc {
-                       if c == nil {
-                               continue
-                       }
-                       wpdst.Add(c, e)
-               }
-       }
-}
-
-// watchDel TODO(rjeczalik)
-func watchDel(nd node, c chan<- EventInfo, e Event) eventDiff {
-       diff := nd.Watch.Del(c, e)
-       if wp := nd.Child[""].Watch; len(wp) != 0 {
-               diffInactive := wp.Del(c, e)
-               e = wp.Total()
-               // TODO(rjeczalik): add e if e != all?
-               diff[0] |= diffInactive[0] | e
-               diff[1] |= diffInactive[1] | e
-               if diff[0] == diff[1] {
-                       return none
-               }
-       }
-       return diff
-}
-
-// watchTotal TODO(rjeczalik)
-func watchTotal(nd node) Event {
-       e := nd.Watch.Total()
-       if wp := nd.Child[""].Watch; len(wp) != 0 {
-               e |= wp.Total()
-       }
-       return e
-}
-
-// watchIsRecursive TODO(rjeczalik)
-func watchIsRecursive(nd node) bool {
-       ok := nd.Watch.IsRecursive()
-       // TODO(rjeczalik): add a test for len(wp) != 0 change the condition.
-       if wp := nd.Child[""].Watch; len(wp) != 0 {
-               // If a watchpoint holds inactive watchpoints, it means it's a parent
-               // one, which is recursive by nature even though it may be not recursive
-               // itself.
-               ok = true
-       }
-       return ok
-}
-
-// recursiveTree TODO(rjeczalik)
-type recursiveTree struct {
-       rw   sync.RWMutex // protects root
-       root root
-       // TODO(rjeczalik): merge watcher + recursiveWatcher after #5 and #6
-       w interface {
-               watcher
-               recursiveWatcher
-       }
-       c chan EventInfo
-}
-
-// newRecursiveTree TODO(rjeczalik)
-func newRecursiveTree(w recursiveWatcher, c chan EventInfo) *recursiveTree {
-       t := &recursiveTree{
-               root: root{nd: newnode("")},
-               w: struct {
-                       watcher
-                       recursiveWatcher
-               }{w.(watcher), w},
-               c: c,
-       }
-       go t.dispatch()
-       return t
-}
-
-// dispatch TODO(rjeczalik)
-func (t *recursiveTree) dispatch() {
-       for ei := range t.c {
-               dbgprintf("dispatching %v on %q", ei.Event(), ei.Path())
-               go func(ei EventInfo) {
-                       nd, ok := node{}, false
-                       dir, base := split(ei.Path())
-                       fn := func(it node, isbase bool) error {
-                               if isbase {
-                                       nd = it
-                               } else {
-                                       it.Watch.Dispatch(ei, recursive)
-                               }
-                               return nil
-                       }
-                       t.rw.RLock()
-                       defer t.rw.RUnlock()
-                       // Notify recursive watchpoints found on the path.
-                       if err := t.root.WalkPath(dir, fn); err != nil {
-                               dbgprint("dispatch did not reach leaf:", err)
-                               return
-                       }
-                       // Notify parent watchpoint.
-                       nd.Watch.Dispatch(ei, 0)
-                       // If leaf watchpoint exists, notify it.
-                       if nd, ok = nd.Child[base]; ok {
-                               nd.Watch.Dispatch(ei, 0)
-                       }
-               }(ei)
-       }
-}
-
-// Watch TODO(rjeczalik)
-func (t *recursiveTree) Watch(path string, c chan<- EventInfo, events ...Event) error {
-       if c == nil {
-               panic("notify: Watch using nil channel")
-       }
-       // Expanding with empty event set is a nop.
-       if len(events) == 0 {
-               return nil
-       }
-       path, isrec, err := cleanpath(path)
-       if err != nil {
-               return err
-       }
-       eventset := joinevents(events)
-       if isrec {
-               eventset |= recursive
-       }
-       t.rw.Lock()
-       defer t.rw.Unlock()
-       // case 1: cur is a child
-       //
-       // Look for parent watch which already covers the given path.
-       parent := node{}
-       self := false
-       err = t.root.WalkPath(path, func(nd node, isbase bool) error {
-               if watchTotal(nd) != 0 {
-                       parent = nd
-                       self = isbase
-                       return errSkip
-               }
-               return nil
-       })
-       cur := t.root.Add(path) // add after the walk, so it's less to traverse
-       if err == nil && parent.Watch != nil {
-               // Parent watch found. Register inactive watchpoint, so we have enough
-               // information to shrink the eventset on eventual Stop.
-               // return t.resetwatchpoint(parent, parent, c, eventset|inactive)
-               var diff eventDiff
-               if self {
-                       diff = watchAdd(cur, c, eventset)
-               } else {
-                       diff = watchAddInactive(parent, c, eventset)
-               }
-               switch {
-               case diff == none:
-                       // the parent watchpoint already covers requested subtree with its
-                       // eventset
-               case diff[0] == 0:
-                       // TODO(rjeczalik): cleanup this panic after implementation is stable
-                       panic("dangling watchpoint: " + parent.Name)
-               default:
-                       if isrec || watchIsRecursive(parent) {
-                               err = t.w.RecursiveRewatch(parent.Name, parent.Name, diff[0], diff[1])
-                       } else {
-                               err = t.w.Rewatch(parent.Name, diff[0], diff[1])
-                       }
-                       if err != nil {
-                               watchDel(parent, c, diff.Event())
-                               return err
-                       }
-                       watchAdd(cur, c, eventset)
-                       // TODO(rjeczalik): account top-most path for c
-                       return nil
-               }
-               if !self {
-                       watchAdd(cur, c, eventset)
-               }
-               return nil
-       }
-       // case 2: cur is new parent
-       //
-       // Look for children nodes, unwatch n-1 of them and rewatch the last one.
-       var children []node
-       fn := func(nd node) error {
-               if len(nd.Watch) == 0 {
-                       return nil
-               }
-               children = append(children, nd)
-               return errSkip
-       }
-       switch must(cur.Walk(fn)); len(children) {
-       case 0:
-               // no child watches, cur holds a new watch
-       case 1:
-               watchAdd(cur, c, eventset) // TODO(rjeczalik): update cache c subtree root?
-               watchCopy(children[0], cur)
-               err = t.w.RecursiveRewatch(children[0].Name, cur.Name, watchTotal(children[0]),
-                       watchTotal(cur))
-               if err != nil {
-                       // Clean inactive watchpoint. The c chan did not exist before.
-                       cur.Child[""] = node{}
-                       delete(cur.Watch, c)
-                       return err
-               }
-               return nil
-       default:
-               watchAdd(cur, c, eventset)
-               // Copy children inactive watchpoints to the new parent.
-               for _, nd := range children {
-                       watchCopy(nd, cur)
-               }
-               // Watch parent subtree.
-               if err = t.w.RecursiveWatch(cur.Name, watchTotal(cur)); err != nil {
-                       // Clean inactive watchpoint. The c chan did not exist before.
-                       cur.Child[""] = node{}
-                       delete(cur.Watch, c)
-                       return err
-               }
-               // Unwatch children subtrees.
-               var e error
-               for _, nd := range children {
-                       if watchIsRecursive(nd) {
-                               e = t.w.RecursiveUnwatch(nd.Name)
-                       } else {
-                               e = t.w.Unwatch(nd.Name)
-                       }
-                       if e != nil {
-                               err = nonil(err, e)
-                               // TODO(rjeczalik): child is still watched, warn all its watchpoints
-                               // about possible duplicate events via Error event
-                       }
-               }
-               return err
-       }
-       // case 3: cur is new, alone node
-       switch diff := watchAdd(cur, c, eventset); {
-       case diff == none:
-               // TODO(rjeczalik): cleanup this panic after implementation is stable
-               panic("watch requested but no parent watchpoint found: " + cur.Name)
-       case diff[0] == 0:
-               if isrec {
-                       err = t.w.RecursiveWatch(cur.Name, diff[1])
-               } else {
-                       err = t.w.Watch(cur.Name, diff[1])
-               }
-               if err != nil {
-                       watchDel(cur, c, diff.Event())
-                       return err
-               }
-       default:
-               // TODO(rjeczalik): cleanup this panic after implementation is stable
-               panic("watch requested but no parent watchpoint found: " + cur.Name)
-       }
-       return nil
-}
-
-// Stop TODO(rjeczalik)
-//
-// TODO(rjeczalik): Split parent watchpoint - transfer watches to children
-// if parent is no longer needed. This carries a risk that underlying
-// watcher calls could fail - reconsider if it's worth the effort.
-func (t *recursiveTree) Stop(c chan<- EventInfo) {
-       var err error
-       fn := func(nd node) (e error) {
-               diff := watchDel(nd, c, all)
-               switch {
-               case diff == none && watchTotal(nd) == 0:
-                       // TODO(rjeczalik): There's no watchpoints deeper in the tree,
-                       // probably we should remove the nodes as well.
-                       return nil
-               case diff == none:
-                       // Removing c from nd does not require shrinking its eventset.
-               case diff[1] == 0:
-                       if watchIsRecursive(nd) {
-                               e = t.w.RecursiveUnwatch(nd.Name)
-                       } else {
-                               e = t.w.Unwatch(nd.Name)
-                       }
-               default:
-                       if watchIsRecursive(nd) {
-                               e = t.w.RecursiveRewatch(nd.Name, nd.Name, diff[0], diff[1])
-                       } else {
-                               e = t.w.Rewatch(nd.Name, diff[0], diff[1])
-                       }
-               }
-               fn := func(nd node) error {
-                       watchDel(nd, c, all)
-                       return nil
-               }
-               err = nonil(err, e, nd.Walk(fn))
-               // TODO(rjeczalik): if e != nil store dummy chan in nd.Watch just to
-               // retry un/rewatching next time and/or let the user handle the failure
-               // vie Error event?
-               return errSkip
-       }
-       t.rw.Lock()
-       e := t.root.Walk("", fn) // TODO(rjeczalik): use max root per c
-       t.rw.Unlock()
-       if e != nil {
-               err = nonil(err, e)
-       }
-       dbgprintf("Stop(%p) error: %v\n", c, err)
-}
-
-// Close TODO(rjeczalik)
-func (t *recursiveTree) Close() error {
-       err := t.w.Close()
-       close(t.c)
-       return err
-}