Ejemplo n.º 1
0
func apiPromoteServer(server models.Server, param martini.Params) (int, string) {
	conn := CreateCoordConn()
	defer conn.Close()

	lock := utils.GetCoordLock(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, globalEnv.StoreAuth())
	if err != nil {
		log.Warning(errors.ErrorStack(err))
		log.Warning(err)
		return 500, err.Error()
	}

	return jsonRetSucc()
}
Ejemplo n.º 2
0
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 := CreateCoordConn()
	defer conn.Close()

	g, err := models.GetGroup(conn, globalEnv.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 {
		return 500, "master not found"
	}

	slotInfo, err := utils.SlotsInfo(s.Addr, slotId, slotId, globalEnv.StoreAuth())
	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)

}
Ejemplo n.º 3
0
func (top *Topology) GetSlotByIndex(i int) (*models.Slot, *models.ServerGroup, error) {
	slot, err := models.GetSlot(top.coordConn, 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.coordConn, top.ProductName, slot.GroupId)
	if err != nil {
		return nil, nil, errors.Trace(err)
	}

	return slot, groupServer, nil
}
Ejemplo n.º 4
0
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 := CreateCoordConn()
	defer conn.Close()

	group, err := models.GetGroup(conn, globalEnv.ProductName(), groupId)
	if err != nil {
		log.Warning(err)
		return 500, err.Error()
	}

	b, err := json.MarshalIndent(group, " ", "  ")
	return 200, string(b)
}
Ejemplo n.º 5
0
func (top *Topology) GetGroup(groupId int) (*models.ServerGroup, error) {
	return models.GetGroup(top.coordConn, top.ProductName, groupId)
}
Ejemplo n.º 6
0
func (m *RebornSlotMigrator) Migrate(slot *models.Slot, fromGroup, toGroup int, task *MigrateTask, onProgress func(SlotMigrateProgress)) (err error) {
	groupFrom, err := models.GetGroup(task.coordConn, task.productName, fromGroup)
	if err != nil {
		return errors.Trace(err)
	}
	groupTo, err := models.GetGroup(task.coordConn, task.productName, toGroup)
	if err != nil {
		return errors.Trace(err)
	}

	fromMaster, err := groupFrom.Master(task.coordConn)
	if err != nil {
		return errors.Trace(err)
	}

	toMaster, err := groupTo.Master(task.coordConn)
	if err != nil {
		return errors.Trace(err)
	}

	if fromMaster == nil || toMaster == nil {
		return ErrGroupMasterNotFound
	}

	if err = checkMaster(fromMaster.Addr); err != nil {
		return errors.Trace(err)
	}

	if err = checkMaster(toMaster.Addr); err != nil {
		return errors.Trace(err)
	}

	c, err := redis.Dial("tcp", fromMaster.Addr)
	if err != nil {
		return errors.Trace(err)
	}

	defer c.Close()

	_, remain, err := sendRedisMigrateCmd(c, slot.Id, toMaster.Addr)
	if err != nil {
		return errors.Trace(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 errors.Trace(err)
		}
	}
	return nil
}
Ejemplo n.º 7
0
func (t *MigrateTask) migrateSingleSlot(slotId int, to int) error {
	// set slot status
	s, err := models.GetSlot(t.coordConn, t.productName, slotId)
	if err != nil {
		log.Error(err)
		return errors.Trace(err)
	}
	if s.State.Status != models.SLOT_STATUS_ONLINE && s.State.Status != models.SLOT_STATUS_MIGRATE {
		log.Warning("status is not online && migrate", s)
		return nil
	}

	from := s.GroupId
	if s.State.Status == models.SLOT_STATUS_MIGRATE {
		from = s.State.MigrateStatus.From
	}

	// cannot migrate to itself, just ignore
	if from == to {
		log.Warning("from == to, ignore", s)
		return nil
	}

	// make sure from group & target group exists
	exists, err := models.GroupExists(t.coordConn, t.productName, from)
	if err != nil {
		return errors.Trace(err)
	}
	if !exists {
		log.Errorf("src group %d not exist when migrate from %d to %d", from, from, to)
		return errors.NotFoundf("group %d", from)
	}

	exists, err = models.GroupExists(t.coordConn, t.productName, to)
	if err != nil {
		return errors.Trace(err)
	}
	if !exists {
		return errors.NotFoundf("group %d", to)
	}

	/***************************************************************/
	// make sure to group has at least one master server ---zjp 20160711

	log.Warning("Get group %d has no master master not found")
	groupTo, err := models.GetGroup(t.coordConn, t.productName, to)
	if err != nil {
		log.Warning(err)
		return errors.Trace(err)
	}
	log.Warning("Get to master ")
	toMaster, err := groupTo.Master(t.coordConn)
	if err != nil {
		log.Warning(err)
		return errors.Trace(err)
	}

	if toMaster == nil {
		log.Warning("to master not found")
		return errors.NotFoundf("group %d has no master", to)
	}
	log.Warning("Get to master  != nil")

	var perr error
	for i := 0; i < haMaxRetryNum; i++ {
		if perr = utils.Ping(toMaster.Addr, globalEnv.StoreAuth()); perr == nil {
			break
		}

		perr = errors.Trace(perr)
		time.Sleep(time.Duration(haRetryDelay) * time.Second)
	}

	if perr != nil {
		log.Warning(perr)
		log.Warning("To master is not online")
		return errors.Trace(perr)
	}
	groupFrom, err := models.GetGroup(t.coordConn, t.productName, from)
	if err != nil {
		log.Warning(err)
		return errors.Trace(err)
	}
	log.Warning("Get from master ")
	fromMaster, err := groupFrom.Master(t.coordConn)
	if err != nil {
		log.Warning(err)
		return errors.Trace(err)
	}

	if fromMaster == nil {
		log.Warning(" from master not found")
		return errors.NotFoundf("group %d has no master", to)
	}
	log.Warning("Get from master  != nil")

	var Fmerr error
	for i := 0; i < haMaxRetryNum; i++ {
		if Fmerr = utils.Ping(fromMaster.Addr, globalEnv.StoreAuth()); Fmerr == nil {
			break
		}

		Fmerr = errors.Trace(Fmerr)
		time.Sleep(time.Duration(haRetryDelay) * time.Second)
	}

	if Fmerr != nil {
		log.Warning(Fmerr)
		log.Warning("From master is not online")
		return errors.Trace(Fmerr)
	}
	groupFrom, gerr := models.GetGroup(t.coordConn, t.productName, from)
	if gerr != nil {
		log.Warning(gerr)
		return errors.Trace(gerr)
	}

	/***************************************************************/

	// modify slot status
	if err := s.SetMigrateStatus(t.coordConn, from, to); err != nil {
		log.Error(err)
		return errors.Trace(err)
	}

	err = t.slotMigrator.Migrate(s, from, to, t, func(p SlotMigrateProgress) {
		// on migrate slot progress
		if p.Remain%500 == 0 {
			log.Info(p)
		}
	})
	if err != nil {
		log.Error(err)
		return errors.Trace(err)
	}

	// migrate done, change slot status back
	s.State.Status = models.SLOT_STATUS_ONLINE
	s.State.MigrateStatus.From = models.INVALID_ID
	s.State.MigrateStatus.To = models.INVALID_ID
	if err := s.Update(t.coordConn); err != nil {
		log.Error(err)
		return errors.Trace(err)
	}

	return nil
}