// Publish expored a method for publishing a message for the channel func (c *CometRPC) Migrate(args *myrpc.CometMigrateArgs, ret *int) error { if len(args.Nodes) == 0 { return myrpc.ErrParam } // find current node exists in new nodes has := false for _, str := range args.Nodes { if str == Conf.ZookeeperCometNode { has = true } } if !has { logger.Error("make sure your migrate nodes right, there is no %s in nodes, this will cause all the node hit miss", Conf.ZookeeperCometNode) return ErrMigrate } // init ketama ketama := hash.NewKetama2(args.Nodes, args.Vnode) channels := []Channel{} keys := []string{} // get all the channel lock for i, c := range UserChannel.Channels { c.Lock() for k, v := range c.Data { hn := ketama.Node(k) if hn != Conf.ZookeeperCometNode { channels = append(channels, v) keys = append(keys, k) logger.Tracef("migrate key:\"%s\" hit node:\"%s\"", k, hn) } } for _, k := range keys { delete(c.Data, k) logger.Tracef("migrate delete channel key \"%s\"", k) } c.Unlock() logger.Tracef("migrate channel bucket:%d finished", i) } // close all the migrate channels logger.Trace("close all the migrate channels") for _, channel := range channels { if err := channel.Close(); err != nil { logger.Errorf("channel.Close() error(%v)", err) continue } } logger.Trace("close all the migrate channels finished") return nil }
// handleCometNodeEvent add and remove CometNodeInfo, copy the src map to a new map then replace the variable. func handleCometNodeEvent(conn *zk.Conn, fpath string, retry, ping time.Duration, ch chan *CometNodeEvent) { for { ev := <-ch // copy map from src tmpMap := make(map[string]*CometNodeInfo, len(cometNodeInfoMap)) for k, v := range cometNodeInfoMap { tmpMap[k] = v } // handle event if ev.Event == eventNodeAdd { logger.Infof("add node: \"%s\"", ev.Key) tmpMap[ev.Key] = nil go watchCometNode(conn, ev.Key, fpath, retry, ping, ch) } else if ev.Event == eventNodeDel { logger.Infof("del node: \"%s\"", ev.Key) delete(tmpMap, ev.Key) } else if ev.Event == eventNodeUpdate { logger.Infof("update node: \"%s\"", ev.Key) tmpMap[ev.Key] = ev.Value } else { logger.Errorf("unknown node event: %d", ev.Event) panic("unknown node event") } // if exist old node info, destroy if info, ok := cometNodeInfoMap[ev.Key]; ok { if info != nil { info.CometRPC.Destroy() } } // use the tmpMap atomic replace the global cometNodeInfoMap cometNodeInfoMap = tmpMap // update comet hash, cause node has changed nodes := make([]string, 0, len(tmpMap)) for k, _ := range tmpMap { nodes = append(nodes, k) } cometHash = hash.NewKetama2(nodes, 255) logger.Tracef("cometNodeInfoMap len: %d", len(cometNodeInfoMap)) } }