// background routine to initiate a connection sequence // only connect if state == CELL_DISCONNECTED // will change state to CELL_CONNECTING during the connection process // will then change to CELL_CONNECTED (and braodcast the cond) // or to CELL_BACKOFF (and schedule a new reconnection soon) func (zcell *zkCell) connect() { // change our state, we're working on connecting zcell.mutex.Lock() if zcell.state != CELL_DISCONNECTED { // someone else is already connecting zcell.mutex.Unlock() return } zcell.state = CELL_CONNECTING zcell.mutex.Unlock() // now connect zconn, session, err := zk.DialZkTimeout(zcell.zkAddr, *baseTimeout, *connectTimeout) if err == nil { zcell.zconn = zconn go zcell.handleSessionEvents(session) } // and change our state zcell.mutex.Lock() if zcell.state != CELL_CONNECTING { panic(fmt.Errorf("Unexpected state: %v", zcell.state)) } if err == nil { log.Infof("zk cell conn: cell %v connected", zcell.cellName) zcell.state = CELL_CONNECTED zcell.lastErr = nil } else { log.Infof("zk cell conn: cell %v connection failed: %v", zcell.cellName, err) zcell.state = CELL_BACKOFF zcell.lastErr = err go func() { // we're going to try to reconnect at some point // FIXME(alainjobart) backoff algorithm? <-time.NewTimer(time.Duration(*reconnectInterval) * time.Second).C // switch back to DISCONNECTED, and trigger a connect zcell.mutex.Lock() zcell.state = CELL_DISCONNECTED zcell.mutex.Unlock() zcell.connect() }() } // we broadcast on the condition to get everybody unstuck, // whether we succeeded to connect or not zcell.ready.Broadcast() zcell.mutex.Unlock() }
func main() { defer logutil.Flush() flag.Usage = func() { fmt.Fprintf(os.Stderr, "Usage of %v:\n", os.Args[0]) flag.PrintDefaults() fmt.Fprintf(os.Stderr, doc) } flag.Parse() args := flag.Args() if len(args) == 0 { flag.Usage() os.Exit(1) } if *zkAddrs != "" { if *zkoccAddr != "" { log.Fatalf("zk.addrs and zk.zkocc-addr are mutually exclusive") } var err error zconn, _, err = zk.DialZkTimeout(*zkAddrs, 5*time.Second, 10*time.Second) if err != nil { log.Fatalf("zk connect failed: %v", err.Error()) } } if *zkoccAddr != "" { var err error zconn, err = zk.DialZkocc(*zkoccAddr, 5*time.Second) if err != nil { log.Fatalf("zkocc connect failed: %v", err.Error()) } } cmdName := args[0] args = args[1:] if cmd, ok := cmdMap[cmdName]; ok { subFlags := flag.NewFlagSet(cmdName, flag.ExitOnError) cmd(subFlags, args) } }