func (p Poller) Rcv(msg bh.Msg, ctx bh.RcvContext) error { dict := ctx.Dict(driversDict) dict.ForEach(func(k string, v interface{}) { node := nom.UID(k) query := nom.FlowStatsQuery{ Node: node, } sendToMaster(query, node, ctx) nd := v.(nodeDrivers) for i := range nd.Drivers { // TODO(soheil): remove the hardcoded value. if nd.Drivers[i].OutPings > MaxPings { ctx.SendToBee(nom.NodeDisconnected{ Node: nom.Node{ID: nom.NodeID(node)}, Driver: nd.Drivers[i].Driver, }, ctx.ID()) continue } ctx.SendToBee(nom.Ping{}, nd.Drivers[i].BeeID) nd.Drivers[i].OutPings++ } if err := dict.Put(k, nd); err != nil { glog.Warningf("error in encoding drivers: %v", err) } }) return nil }
func sendToMaster(msg interface{}, node nom.UID, ctx bh.RcvContext) error { d := ctx.Dict(driversDict) v, err := d.Get(string(node)) if err != nil { if err == state.ErrNoSuchKey { return fmt.Errorf("nom: cannot find node %s", node) } return err } nd := v.(nodeDrivers) ctx.SendToBee(msg, nd.master().BeeID) return nil }
func (h nodeConnectedHandler) Rcv(msg bh.Msg, ctx bh.RcvContext) error { nc := msg.Data().(nom.NodeConnected) ddict := ctx.Dict(driversDict) k := string(nc.Node.ID) n := nodeDrivers{ Node: nc.Node, } if v, err := ddict.Get(k); err == nil { n = v.(nodeDrivers) } if _, ok := n.driver(nc.Driver); ok { return fmt.Errorf("driver %v reconnects to %v", nc.Driver, n.Node) } gdict := ctx.Dict(genDict) gen := uint64(0) if v, err := gdict.Get("gen"); err == nil { gen = v.(uint64) } gen++ db := nc.Driver.BeeID if len(n.Drivers) == 0 { nc.Driver.Role = nom.DriverRoleMaster ctx.Emit(nom.NodeJoined(nc.Node)) glog.V(2).Infof("%v connected to master controller", nc.Node) } else { nc.Driver.Role = nom.DriverRoleSlave glog.V(2).Infof("%v connected to slave controller", nc.Node) } n.Drivers = append(n.Drivers, driverInfo{ Driver: nc.Driver, LastSeen: time.Now(), }) ctx.SendToBee(nom.ChangeDriverRole{ Node: nc.Node.UID(), Role: nc.Driver.Role, Generation: gen, }, db) gdict.Put("gen", gen) return ddict.Put(k, n) }
func (h nodeDisconnectedHandler) Rcv(msg bh.Msg, ctx bh.RcvContext) error { dc := msg.Data().(nom.NodeDisconnected) d := ctx.Dict(driversDict) k := string(dc.Node.ID) v, err := d.Get(k) if err != nil { return fmt.Errorf("driver %v disconnects from %v before connecting", dc.Driver, dc.Node) } nd := v.(nodeDrivers) ndd, ok := nd.driver(dc.Driver) if !ok { return fmt.Errorf("driver %v disconnects from %v before connecting", dc.Driver, dc.Node) } nd.removeDriver(dc.Driver) if len(nd.Drivers) == 0 { ctx.Emit(nom.NodeLeft(nd.Node)) return d.Del(k) } if ndd.Role == nom.DriverRoleMaster { // TODO(soheil): Maybe a smarter load balacning technique. gdict := ctx.Dict(genDict) gen := uint64(0) if v, err := gdict.Get("gen"); err == nil { gen = v.(uint64) } gen++ nd.Drivers[0].Role = nom.DriverRoleMaster ctx.SendToBee(nom.ChangeDriverRole{ Node: nd.Node.UID(), Role: nom.DriverRoleMaster, Generation: gen, }, nd.master().BeeID) } return d.Put(k, nd) }