Example #1
2
// Close the release channel when you want to clean up nicely.
func CreatePidNode(zconn zookeeper.Conn, zkPath string, contents string, done chan struct{}) error {
	// On the first try, assume the cluster is up and running, that will
	// help hunt down any config issues present at startup
	if _, err := zconn.Create(zkPath, []byte(contents), zookeeper.FlagEphemeral, zookeeper.WorldACL(PERM_FILE)); err != nil {
		if ZkErrorEqual(err, zookeeper.ErrNodeExists) {
			err = zconn.Delete(zkPath, -1)
		}
		if err != nil {
			return fmt.Errorf("zkutil: failed deleting pid node: %v: %v", zkPath, err)
		}
		_, err = zconn.Create(zkPath, []byte(contents), zookeeper.FlagEphemeral, zookeeper.WorldACL(PERM_FILE))
		if err != nil {
			return fmt.Errorf("zkutil: failed creating pid node: %v: %v", zkPath, err)
		}
	}

	go func() {
		for {
			_, _, watch, err := zconn.GetW(zkPath)
			if err != nil {
				if ZkErrorEqual(err, zookeeper.ErrNoNode) {
					_, err = zconn.Create(zkPath, []byte(contents), zookeeper.FlagEphemeral, zookeeper.WorldACL(zookeeper.PermAll))
					if err != nil {
						log.Warningf("failed recreating pid node: %v: %v", zkPath, err)
					} else {
						log.Infof("recreated pid node: %v", zkPath)
						continue
					}
				} else {
					log.Warningf("failed reading pid node: %v", err)
				}
			} else {
				select {
				case event := <-watch:
					if ZkEventOk(event) && event.Type == zookeeper.EventNodeDeleted {
						// Most likely another process has started up. However,
						// there is a chance that an ephemeral node is deleted by
						// the session expiring, yet that same session gets a watch
						// notification. This seems like buggy behavior, but rather
						// than race too hard on the node, just wait a bit and see
						// if the situation resolves itself.
						log.Warningf("pid deleted: %v", zkPath)
					} else {
						log.Infof("pid node event: %v", event)
					}
					// break here and wait for a bit before attempting
				case <-done:
					log.Infof("pid watcher stopped on done: %v", zkPath)
					return
				}
			}
			select {
			// No one likes a thundering herd, least of all zookeeper.
			case <-time.After(5*time.Second + time.Duration(rand.Int63n(55e9))):
			case <-done:
				log.Infof("pid watcher stopped on done: %v", zkPath)
				return
			}
		}
	}()

	return nil
}
Example #2
0
/**
 * Watches a Zookeeper node continuously in a loop. When a watch fires, the new config is rendered.
 * When first registering the watch, the initial payload is also rendered
 */
func (z ZookeeperClient) watchLocalProxyConfig(conn *zk.Conn, path string) {

	go func() {
		for {
			payload, _, watch, err := conn.GetW(path)
			must(err)

			RenderLocalProxyConfig(payload, ConfigObj)
			// block till event fires
			event := <-watch

			log.Info("Received Zookeeper event: " + event.Type.String())
			RenderLocalProxyConfig(payload, ConfigObj)
		}
	}()

}
Example #3
0
func sinkSelfEvents(conn *zk.Conn, path string, sink chan<- zk.Event) chan<- bool {
	control := make(chan bool)
	go func() {
		_, _, selfCh, err := conn.GetW(path)
		if err != nil {
			logger.Panicf("failed to set listener on path: %s", err.Error())
		}
		for {
			select {
			case _ = <-control:
				break
			case ev := <-selfCh:
				sink <- ev
				_, _, selfCh, err = conn.GetW(path)
				if err != nil {
					logger.Printf("failed to set listener on path: %s\n", err.Error())
				}
			}
		}
	}()

	return control
}