func (a *HostAgent) processChildrenAndWait(conn *zk.Conn) bool { processing := make(map[string]chan int) ssDone := make(chan stateResult, 25) hostPath := zzk.HostPath(a.hostId) for { children, _, zkEvent, err := conn.ChildrenW(hostPath) if err != nil { glog.V(0).Infoln("Unable to read children, retrying.") time.Sleep(3 * time.Second) return true } a.startMissingChildren(conn, children, processing, ssDone) select { case errc := <-a.closing: glog.V(1).Info("Agent received interrupt") err = waitForSsNodes(processing, ssDone) errc <- err return false case ssResult := <-ssDone: glog.V(1).Infof("Goroutine finished %s", ssResult.id) delete(processing, ssResult.id) case evt := <-zkEvent: glog.V(1).Info("Agent event: ", evt) } } }
func GetRouters(conn *zk.Conn) []string { nodes, _, _, err := conn.ChildrenW(ZOOKEEPER_ROUTER_PATH) if err != nil { log.Error("get router from zk error:%v", err) return []string{} } return nodes }
func GetRoomConnector(conn *zk.Conn, roomid string) []string { fpath := path.Join(ZOOKEEPER_ROOM_PATH, roomid) nodes, _, _, err := conn.ChildrenW(fpath) if err != nil { log.Error("get roomid:%s from zk error:%v", roomid, err) return []string{} } return nodes }
func watchService(cpDao dao.ControlPlane, conn *zk.Conn, shutdown <-chan int, done chan<- string, serviceId string) { defer func() { glog.V(3).Info("Exiting function watchService ", serviceId) done <- serviceId }() for { var service dao.Service _, zkEvent, err := zzk.LoadServiceW(conn, serviceId, &service) if err != nil { glog.Errorf("Unable to load service %s: %v", serviceId, err) return } _, _, childEvent, err := conn.ChildrenW(zzk.ServicePath(serviceId)) glog.V(1).Info("Leader watching for changes to service ", service.Name) // check current state var serviceStates []*dao.ServiceState err = zzk.GetServiceStates(conn, &serviceStates, serviceId) if err != nil { glog.Error("Unable to retrieve running service states: ", err) return } // Is the service supposed to be running at all? switch { case service.DesiredState == dao.SVC_STOP: shutdownServiceInstances(conn, serviceStates, len(serviceStates)) case service.DesiredState == dao.SVC_RUN: updateServiceInstances(cpDao, conn, &service, serviceStates) default: glog.Warningf("Unexpected desired state %d for service %s", service.DesiredState, service.Name) } select { case evt := <-zkEvent: if evt.Type == zk.EventNodeDeleted { glog.V(0).Info("Shutting down due to node delete ", serviceId) shutdownServiceInstances(conn, serviceStates, len(serviceStates)) return } glog.V(1).Infof("Service %s received event: %v", service.Name, evt) continue case evt := <-childEvent: glog.V(1).Infof("Service %s received child event: %v", service.Name, evt) continue case <-shutdown: glog.V(1).Info("Leader stopping watch on ", service.Name) return } } }
func WatchChildren(conn *zk.Conn, zkPath string, onChange func(children []string)) { CreateRecursive(conn, zkPath, "", 0, DefaultDirACLs()) for { children, _, ch, err := conn.ChildrenW(zkPath) if err != nil { log.Errorf("watch children path error, path:%s, err:%v", zkPath, err) continue } onChange(children) select { case <-ch: } } }
func WatchConnChange(conn *zk.Conn) { fpath := ZOOKEEPER_CONN_PATH for { log.Info("zk path:%s set a watch", fpath) _, _, watch, err := conn.ChildrenW(fpath) if err != nil { log.Info("path:%s get error ,try later", fpath) time.Sleep(10 * time.Second) continue } event := <-watch log.Info("zk path:%s receive a event %v", fpath, event) UpdateConnectorList() } }
// GetNodesW get all child from zk path with a watch. func GetNodesW(conn *zk.Conn, path string) ([]string, <-chan zk.Event, error) { nodes, stat, watch, err := conn.ChildrenW(path) if err != nil { if err == zk.ErrNoNode { return nil, nil, ErrNodeNotExist } glog.Errorf("zk.ChildrenW(\"%s\") error(%v)", path, err) return nil, nil, err } if stat == nil { return nil, nil, ErrNodeNotExist } if len(nodes) == 0 { return nil, nil, ErrNoChild } return nodes, watch, nil }
func mirror(conn *zk.Conn, path string) (chan []string, chan error) { snapshots := make(chan []string) errors := make(chan error) go func() { for { snapshot, _, events, err := conn.ChildrenW(path) if err != nil { errors <- err return } snapshots <- snapshot evt := <-events if evt.Err != nil { errors <- evt.Err return } } }() return snapshots, errors }
func watchServices(cpDao dao.ControlPlane, conn *zk.Conn) { processing := make(map[string]chan int) sDone := make(chan string) // When this function exits, ensure that any started goroutines get // a signal to shutdown defer func() { glog.V(0).Info("Leader shutting down child goroutines") for key, shutdown := range processing { glog.V(1).Info("Sending shutdown signal for ", key) shutdown <- 1 } }() for { glog.V(1).Info("Leader watching for changes to ", zzk.SERVICE_PATH) serviceIds, _, zkEvent, err := conn.ChildrenW(zzk.SERVICE_PATH) if err != nil { glog.Errorf("Leader unable to find any services: ", err) return } for _, serviceId := range serviceIds { if processing[serviceId] == nil { glog.V(2).Info("Leader starting goroutine to watch ", serviceId) serviceChannel := make(chan int) processing[serviceId] = serviceChannel go watchService(cpDao, conn, serviceChannel, sDone, serviceId) } } select { case evt := <-zkEvent: glog.V(1).Info("Leader event: ", evt) case serviceId := <-sDone: glog.V(1).Info("Leading cleaning up for service ", serviceId) delete(processing, serviceId) } } }
func sinkChildEvents(conn *zk.Conn, path string, sink chan<- zk.Event) chan<- bool { control := make(chan bool) go func() { _, _, selfCh, err := conn.ChildrenW(path) if err != nil { logger.Panic("failed to set listener on path") } for { select { case _ = <-control: break case ev := <-selfCh: sink <- ev _, _, selfCh, err = conn.ChildrenW(path) if err != nil { logger.Panic("failed to set listener on path") } } } }() return control }
func WatchRoomConnChange(conn *zk.Conn, roomid string, cancel <-chan int) { fpath := path.Join(ZOOKEEPER_ROOM_PATH, roomid) for { log.Info("zk path:%s set a watch", fpath) _, _, watch, err := conn.ChildrenW(fpath) if err != nil { log.Info("path:%s get error ,try later", fpath) time.Sleep(10 * time.Second) continue } select { case event := <-watch: log.Info("zk path:%s receive a event %v", fpath, event) err = GetRoomConnectorFromZk(roomid) if err != nil { log.Error("get room:%s from zk error", roomid) } case <-cancel: log.Info("cancel room:%s watch", roomid) break } } }