func (s *Server) Run(shutdown <-chan interface{}, conn client.Connection) error { node := &Node{ Host: *s.host, ExportPath: fmt.Sprintf("%s:%s", s.host.IPAddr, s.driver.ExportPath()), ExportTime: strconv.FormatInt(time.Now().UnixNano(), 16), } // Create the storage leader and client nodes if exists, _ := conn.Exists("/storage/leader"); !exists { conn.CreateDir("/storage/leader") } storageClientsPath := "/storage/clients" if exists, _ := conn.Exists(storageClientsPath); !exists { conn.CreateDir(storageClientsPath) } leader := conn.NewLeader("/storage/leader", node) leaderW, err := leader.TakeLead() if err != zookeeper.ErrDeadlock && err != nil { glog.Errorf("Could not take storage lead: %s", err) return err } // monitor dfs; log warnings each cycle; restart dfs if needed go s.monitor.MonitorDFSVolume(path.Join("/exports", s.driver.ExportPath()), s.host.IPAddr, node.ExportTime, shutdown, s.monitor.DFSVolumeMonitorPollUpdateFunc) // loop until shutdown event defer leader.ReleaseLead() for { clients, clientW, err := conn.ChildrenW(storageClientsPath) if err != nil { glog.Errorf("Could not set up watch for storage clients: %s", err) return err } s.monitor.SetMonitorStorageClients(conn, storageClientsPath) s.driver.SetClients(clients...) if err := s.driver.Sync(); err != nil { glog.Errorf("Error syncing driver: %s", err) return err } select { case e := <-clientW: glog.Info("storage.server: receieved event: %s", e) case <-leaderW: err := fmt.Errorf("storage.server: lost lead") return err case <-shutdown: return nil } } }
func MonitorRealm(shutdown <-chan interface{}, conn client.Connection, path string) <-chan string { realmC := make(chan string) go func() { defer close(realmC) var realm string leader := conn.NewLeader(path, &HostLeader{}) for { // monitor path for changes _, event, err := conn.ChildrenW(path) if err != nil { return } // Get the current leader and check for changes in its realm var hl HostLeader if err := leader.Current(&hl); err == zookeeper.ErrNoLeaderFound { // pass } else if err != nil { return } else if hl.Realm != realm { realm = hl.Realm select { case realmC <- realm: case <-shutdown: return } } select { case <-event: case <-shutdown: return } } }() return realmC }
// NewHostLeader initializes a new host leader func NewHostLeader(conn client.Connection, hostID, realm, path string) client.Leader { return conn.NewLeader(path, &HostLeader{HostID: hostID, Realm: realm}) }