func MigrateSingleSlot(zkConn zkhelper.Conn, slotId, fromGroup, toGroup int, delay int, stopChan <-chan struct{}) error { groupFrom, err := models.GetGroup(zkConn, productName, fromGroup) if err != nil { return err } groupTo, err := models.GetGroup(zkConn, productName, toGroup) if err != nil { return err } fromMaster, err := groupFrom.Master(zkConn) if err != nil { return err } toMaster, err := groupTo.Master(zkConn) if err != nil { return err } if fromMaster == nil || toMaster == nil { return ErrGroupMasterNotFound } c, err := redis.Dial("tcp", fromMaster.Addr) if err != nil { return err } defer c.Close() _, remain, err := sendRedisMigrateCmd(c, slotId, toMaster.Addr) if err != nil { return err } for remain > 0 { if delay > 0 { time.Sleep(time.Duration(delay) * time.Millisecond) } if stopChan != nil { select { case <-stopChan: return ErrStopMigrateByUser default: } } _, remain, err = sendRedisMigrateCmd(c, slotId, toMaster.Addr) if remain%500 == 0 && remain > 0 { log.Info("remain:", remain) } if err != nil { return err } } return nil }
// will block until all keys are migrated func (task *MigrateTask) Migrate(slot *models.Slot, fromGroup, toGroup int, onProgress func(SlotMigrateProgress)) (err error) { groupFrom, err := models.GetGroup(task.zkConn, task.productName, fromGroup) if err != nil { return err } groupTo, err := models.GetGroup(task.zkConn, task.productName, toGroup) if err != nil { return err } fromMaster, err := groupFrom.Master(task.zkConn) if err != nil { return err } toMaster, err := groupTo.Master(task.zkConn) if err != nil { return err } if fromMaster == nil || toMaster == nil { return errors.Trace(ErrGroupMasterNotFound) } c, err := utils.DialTo(fromMaster.Addr, globalEnv.Password()) if err != nil { return err } defer c.Close() _, remain, err := utils.SlotsMgrtTagSlot(c, slot.Id, toMaster.Addr) if err != nil { return err } for remain > 0 { if task.Delay > 0 { time.Sleep(time.Duration(task.Delay) * time.Millisecond) } _, remain, err = utils.SlotsMgrtTagSlot(c, slot.Id, toMaster.Addr) if remain >= 0 { onProgress(SlotMigrateProgress{ SlotId: slot.Id, FromGroup: fromGroup, ToGroup: toGroup, Remain: remain, }) } if err != nil { return err } } return nil }
func (top *Topology) GetSlotByIndex(i int) (*models.Slot, *models.ServerGroup, error) { var slot *models.Slot var groupServer *models.ServerGroup var err error for { slot, err = models.GetSlot(top.zkConn, top.ProductName, i) if err == nil || top.IsFatalErr(err) { break } else { time.Sleep(ZK_RECONNECT_INTERVAL * time.Second) } if err != nil { log.ErrorErrorf(err, " GetSlot ") } } if err != nil { return nil, nil, errors.Trace(err) } for { groupServer, err = models.GetGroup(top.zkConn, top.ProductName, slot.GroupId) if err == nil || top.IsFatalErr(err) { break } else { time.Sleep(ZK_RECONNECT_INTERVAL * time.Second) } if err != nil { log.ErrorErrorf(err, " GetGroup ") } } if err != nil { return nil, nil, errors.Trace(err) } return slot, groupServer, nil }
func apiPromoteServer(server models.Server, param martini.Params) (int, string) { lock := utils.GetZkLock(safeZkConn, globalEnv.ProductName()) if err := lock.LockWithTimeout(0, fmt.Sprintf("promote server %+v", server)); err != nil { return 500, err.Error() } defer func() { err := lock.Unlock() if err != nil && err != zk.ErrNoNode { log.ErrorErrorf(err, "unlock node failed") } }() group, err := models.GetGroup(safeZkConn, globalEnv.ProductName(), server.GroupId) if err != nil { log.ErrorErrorf(err, "get group %d failed", server.GroupId) return 500, err.Error() } err = group.Promote(safeZkConn, server.Addr, globalEnv.Password()) if err != nil { log.ErrorErrorf(err, "promote group %d failed", server.GroupId) return 500, err.Error() } return jsonRetSucc() }
func apiPromoteServer(server models.Server, param martini.Params) (int, string) { conn := CreateZkConn() defer conn.Close() lock := utils.GetZkLock(conn, globalEnv.ProductName()) lock.Lock(fmt.Sprintf("promote server %+v", server)) defer func() { err := lock.Unlock() if err != nil { log.Warning(err) } }() group, err := models.GetGroup(conn, globalEnv.ProductName(), server.GroupId) if err != nil { log.Warning(err) return 500, err.Error() } err = group.Promote(conn, server.Addr) if err != nil { log.Warning(errors.ErrorStack(err)) log.Warning(err) return 500, err.Error() } return jsonRetSucc() }
func runPromoteServerToMaster(groupId int, addr string) error { group, err := models.GetGroup(zkConn, productName, groupId) if err != nil { return err } err = group.Promote(zkConn, addr) if err != nil { return err } return nil }
func (top *Topology) GetSlotByIndex(i int) (*models.Slot, *models.ServerGroup, error) { slot, err := models.GetSlot(top.zkConn, top.ProductName, i) if err != nil { return nil, nil, errors.Trace(err) } groupServer, err := models.GetGroup(top.zkConn, top.ProductName, slot.GroupId) if err != nil { return nil, nil, errors.Trace(err) } return slot, groupServer, nil }
func apiGetServerGroup(param martini.Params) (int, string) { id := param["id"] groupId, err := strconv.Atoi(id) if err != nil { log.Warning(err) return 500, err.Error() } group, err := models.GetGroup(safeZkConn, globalEnv.ProductName(), groupId) if err != nil { log.Warning(err) return 500, err.Error() } b, err := json.MarshalIndent(group, " ", " ") return 200, string(b) }
func (top *Topology) GetGroup(groupId int) (*models.ServerGroup, error) { var group *models.ServerGroup var err error for { group, err = models.GetGroup(top.zkConn, top.ProductName, groupId) if err == nil || top.IsFatalErr(err) { break } else { time.Sleep(ZK_RECONNECT_INTERVAL * time.Second) } if err != nil { log.ErrorErrorf(err, " GetGroup ") } } return group, err }
func runRemoveServerFromGroup(groupId int, addr string) error { serverGroup, err := models.GetGroup(zkConn, productName, groupId) if err != nil { log.Warning(err) return err } for _, s := range serverGroup.Servers { if s.Addr == addr { err := serverGroup.RemoveServer(zkConn, s) if err != nil { log.Warning(err) return err } } } return nil }
func apiGetRedisSlotInfoFromGroupId(param martini.Params) (int, string) { groupId, err := strconv.Atoi(param["group_id"]) if err != nil { log.Warning(err) return 500, err.Error() } slotId, err := strconv.Atoi(param["slot_id"]) if err != nil { log.Warning(err) return 500, err.Error() } conn := CreateZkConn() defer conn.Close() g, err := models.GetGroup(conn, productName, groupId) if err != nil { log.Warning(err) return 500, err.Error() } s, err := g.Master(conn) if err != nil { log.Warning(err) return 500, err.Error() } if s == nil { log.Warning("this group has no master server") return 500, "this group has no master server" } slotInfo, err := utils.SlotsInfo(s.Addr, slotId, slotId) if err != nil { log.Warning(err) return 500, err.Error() } out, _ := json.MarshalIndent(map[string]interface{}{ "keys": slotInfo[slotId], "slot_id": slotId, "group_id": groupId, "addr": s.Addr, }, " ", " ") return 200, string(out) }
func apiGetServerGroup(param martini.Params) (int, string) { id := param["id"] groupId, err := strconv.Atoi(id) if err != nil { log.Warning(err) return 500, err.Error() } conn := CreateZkConn() defer conn.Close() group, err := models.GetGroup(conn, productName, groupId) if err != nil { log.Warning(err) return 500, err.Error() } b, err := json.MarshalIndent(group, " ", " ") return 200, string(b) }
func (top *Topology) GetSlotByIndex(i int) (*models.Slot, *models.ServerGroup, error) { slot, err := models.GetSlot(top.zkConn, top.ProductName, i) if err != nil { return nil, nil, errors.Trace(err) } log.Debugf("get slot %d : %+v", i, slot) if slot.State.Status != models.SLOT_STATUS_ONLINE && slot.State.Status != models.SLOT_STATUS_MIGRATE { log.Errorf("slot not online, %+v", slot) } groupServer, err := models.GetGroup(top.zkConn, top.ProductName, slot.GroupId) if err != nil { return nil, nil, errors.Trace(err) } return slot, groupServer, nil }
func apiGetRedisSlotInfoFromGroupId(param martini.Params) (int, string) { groupId, err := strconv.Atoi(param["group_id"]) if err != nil { log.Warning(err) return 500, err.Error() } slotId, err := strconv.Atoi(param["slot_id"]) if err != nil { log.Warning(err) return 500, err.Error() } g, err := models.GetGroup(safeZkConn, globalEnv.ProductName(), groupId) if err != nil { log.Warning(err) return 500, err.Error() } s, err := g.Master(safeZkConn) if err != nil { log.Warning(err) return 500, err.Error() } if s == nil { return 500, "master not found" } slotInfo, err := utils.SlotsInfo(s.Addr, slotId, slotId) if err != nil { log.Warning(err) return 500, err.Error() } out, _ := json.MarshalIndent(map[string]interface{}{ "keys": slotInfo[slotId], "slot_id": slotId, "group_id": groupId, "addr": s.Addr, }, " ", " ") return 200, string(out) }
func (top *Topology) GetGroup(groupId int) (*models.ServerGroup, error) { return models.GetGroup(top.zkConn, top.ProductName, groupId) }
func (m *CodisSlotMigrator) Migrate(slot *models.Slot, fromGroup, toGroup int, task *MigrateTask, onProgress func(SlotMigrateProgress)) (err error) { groupFrom, err := models.GetGroup(task.zkConn, task.productName, fromGroup) if err != nil { return err } groupTo, err := models.GetGroup(task.zkConn, task.productName, toGroup) if err != nil { return err } fromMaster, err := groupFrom.Master(task.zkConn) if err != nil { return err } toMaster, err := groupTo.Master(task.zkConn) if err != nil { return err } if fromMaster == nil || toMaster == nil { return ErrGroupMasterNotFound } c, err := redis.Dial("tcp", fromMaster.Addr) if err != nil { return err } defer c.Close() _, remain, err := sendRedisMigrateCmd(c, slot.Id, toMaster.Addr) if err != nil { return err } for remain > 0 { if task.Delay > 0 { time.Sleep(time.Duration(task.Delay) * time.Millisecond) } if task.stopChan != nil { select { case <-task.stopChan: return ErrStopMigrateByUser default: } } _, remain, err = sendRedisMigrateCmd(c, slot.Id, toMaster.Addr) if remain >= 0 { onProgress(SlotMigrateProgress{ SlotId: slot.Id, FromGroup: fromGroup, ToGroup: toGroup, Remain: remain, }) } if err != nil { return err } } return nil }