watcher.go 1.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  1. package main
  2. import (
  3. "path"
  4. "strings"
  5. "fmt"
  6. )
  7. type Watcher struct {
  8. chanMap map[string][]chan Notification
  9. }
  10. type Notification struct {
  11. action int
  12. key string
  13. oldValue string
  14. newValue string
  15. }
  16. // global watcher
  17. var w *Watcher
  18. // init the global watcher
  19. func init() {
  20. w = createWatcher()
  21. }
  22. // create a new watcher
  23. func createWatcher() *Watcher {
  24. w := new(Watcher)
  25. w.chanMap = make(map[string][]chan Notification)
  26. return w
  27. }
  28. // register a function with channel and prefix to the watcher
  29. func (w *Watcher) add(prefix string, c chan Notification, f func(chan Notification)) error {
  30. prefix = path.Clean(prefix)
  31. fmt.Println("Add ", prefix)
  32. _, ok := w.chanMap[prefix]
  33. if !ok {
  34. w.chanMap[prefix] = make([]chan Notification, 0)
  35. w.chanMap[prefix] = append(w.chanMap[prefix], c)
  36. } else {
  37. w.chanMap[prefix] = append(w.chanMap[prefix], c)
  38. }
  39. fmt.Println(len(w.chanMap[prefix]), "@", prefix)
  40. go f(c)
  41. return nil
  42. }
  43. // notify the watcher a action happened
  44. func (w *Watcher) notify(action int, key string, oldValue string, newValue string) error {
  45. key = path.Clean(key)
  46. segments := strings.Split(key, "/")
  47. currPath := "/"
  48. // walk through all the pathes
  49. for _, segment := range segments {
  50. currPath := path.Join(currPath, segment)
  51. fmt.Println(currPath)
  52. chans, ok := w.chanMap[currPath]
  53. if ok {
  54. fmt.Println("found ", currPath)
  55. n := Notification {action, key, oldValue, newValue}
  56. // notify all the watchers
  57. for _, c := range chans {
  58. c <- n
  59. }
  60. // we have notified all the watchers at this path
  61. // delete the map
  62. delete(w.chanMap, currPath)
  63. }
  64. }
  65. return nil
  66. }