func (s *Slot) Update(coordConn zkhelper.Conn) error { // status validation switch s.State.Status { case SLOT_STATUS_MIGRATE, SLOT_STATUS_OFFLINE, SLOT_STATUS_ONLINE, SLOT_STATUS_PRE_MIGRATE: { // valid status, OK } default: { return errors.Trace(ErrUnknownSlotStatus) } } data, err := json.Marshal(s) if err != nil { return errors.Trace(err) } coordPath := GetSlotPath(s.ProductName, s.Id) _, err = zkhelper.CreateOrUpdate(coordConn, coordPath, string(data), 0, zkhelper.DefaultFileACLs(), true) if err != nil { return errors.Trace(err) } if s.State.Status == SLOT_STATUS_MIGRATE { err = NewAction(coordConn, s.ProductName, ACTION_TYPE_SLOT_MIGRATE, s, "", true) } else { err = NewAction(coordConn, s.ProductName, ACTION_TYPE_SLOT_CHANGED, s, "", true) } return errors.Trace(err) }
func SetSlotRange(zkConn zkhelper.Conn, productName string, fromSlot, toSlot, groupId int, status SlotStatus) error { if status != SLOT_STATUS_OFFLINE && status != SLOT_STATUS_ONLINE { return errors.New("invalid status") } for i := fromSlot; i <= toSlot; i++ { s, err := GetSlot(zkConn, productName, i) if err != nil { return errors.Trace(err) } s.GroupId = groupId s.State.Status = status data, err := json.Marshal(s) if err != nil { return errors.Trace(err) } zkPath := GetSlotPath(productName, i) _, err = zkhelper.CreateOrUpdate(zkConn, zkPath, string(data), 0, zkhelper.DefaultFileACLs(), true) if err != nil { return errors.Trace(err) } } param := SlotMultiSetParam{ From: fromSlot, To: toSlot, GroupId: groupId, Status: status, } err := NewAction(zkConn, productName, ACTION_TYPE_MULTI_SLOT_CHANGED, param, "", true) return errors.Trace(err) }
func (self *ServerGroup) AddServer(zkConn zkhelper.Conn, s *Server) error { s.GroupId = self.Id servers, err := self.GetServers(zkConn) if err != nil { return errors.Trace(err) } var masterAddr string for _, server := range servers { if server.Type == SERVER_TYPE_MASTER { masterAddr = server.Addr } } // make sure there is only one master if s.Type == SERVER_TYPE_MASTER && len(masterAddr) > 0 { return errors.Trace(ErrNodeExists) } // if this group has no server. auto promote this server to master if len(servers) == 0 { s.Type = SERVER_TYPE_MASTER } val, err := json.Marshal(s) if err != nil { return errors.Trace(err) } zkPath := fmt.Sprintf("/zk/codis/db_%s/servers/group_%d/%s", self.ProductName, self.Id, s.Addr) _, err = zkhelper.CreateOrUpdate(zkConn, zkPath, string(val), 0, zkhelper.DefaultFileACLs(), true) // update servers servers, err = self.GetServers(zkConn) if err != nil { return errors.Trace(err) } self.Servers = servers if s.Type == SERVER_TYPE_MASTER { err = NewAction(zkConn, self.ProductName, ACTION_TYPE_SERVER_GROUP_CHANGED, self, "", true) if err != nil { return errors.Trace(err) } } else if s.Type == SERVER_TYPE_SLAVE && len(masterAddr) > 0 { // send command slaveof to slave err := utils.SlaveOf(s.Addr, masterAddr) if err != nil { return errors.Trace(err) } } return nil }
func CreateActionRootPath(zkConn zkhelper.Conn, path string) error { // if action dir not exists, create it first exists, err := zkhelper.NodeExists(zkConn, path) if err != nil { return errors.Trace(err) } if !exists { _, err := zkhelper.CreateOrUpdate(zkConn, path, "", 0, zkhelper.DefaultDirACLs(), true) if err != nil { return errors.Trace(err) } } return nil }
func (self *ServerGroup) AddServer(zkConn zkhelper.Conn, s *Server) error { s.GroupId = self.Id val, err := json.Marshal(s) if err != nil { return errors.Trace(err) } if s.Type == SERVER_TYPE_MASTER { // make sure there is only one master servers, err := self.GetServers(zkConn) if err != nil { return errors.Trace(err) } for _, server := range servers { if server.Type == SERVER_TYPE_MASTER { return errors.Trace(ErrNodeExists) } } } zkPath := fmt.Sprintf("/zk/codis/db_%s/servers/group_%d/%s", self.ProductName, self.Id, s.Addr) _, err = zkhelper.CreateOrUpdate(zkConn, zkPath, string(val), 0, zkhelper.DefaultFileACLs(), true) // update servers servers, err := self.GetServers(zkConn) if err != nil { return errors.Trace(err) } self.Servers = servers if s.Type == SERVER_TYPE_MASTER { err = NewAction(zkConn, self.ProductName, ACTION_TYPE_SERVER_GROUP_CHANGED, self, "", true) if err != nil { return errors.Trace(err) } } return nil }
func (self *ServerGroup) Create(zkConn zkhelper.Conn) error { if self.Id < 0 { return errors.NotSupportedf("invalid server group id %d", self.Id) } zkPath := fmt.Sprintf("/zk/codis/db_%s/servers/group_%d", self.ProductName, self.Id) _, err := zkhelper.CreateOrUpdate(zkConn, zkPath, "", 0, zkhelper.DefaultDirACLs(), true) if err != nil { return errors.Trace(err) } err = NewAction(zkConn, self.ProductName, ACTION_TYPE_SERVER_GROUP_CHANGED, self, "", false) if err != nil { return errors.Trace(err) } // set no server slots' group id to this server group, no need to return error slots, err := NoGroupSlots(zkConn, self.ProductName) if err == nil && len(slots) > 0 { SetSlots(zkConn, self.ProductName, slots, self.Id, SLOT_STATUS_ONLINE) } return nil }
func SetSlots(coordConn zkhelper.Conn, productName string, slots []*Slot, groupId int, status SlotStatus) error { if status != SLOT_STATUS_OFFLINE && status != SLOT_STATUS_ONLINE { return errors.New("invalid status") } ok, err := GroupExists(coordConn, productName, groupId) if err != nil { return errors.Trace(err) } if !ok { return errors.NotFoundf("group %d", groupId) } for _, s := range slots { s.GroupId = groupId s.State.Status = status data, err := json.Marshal(s) if err != nil { return errors.Trace(err) } coordPath := GetSlotPath(productName, s.Id) _, err = zkhelper.CreateOrUpdate(coordConn, coordPath, string(data), 0, zkhelper.DefaultFileACLs(), true) if err != nil { return errors.Trace(err) } } param := SlotMultiSetParam{ From: -1, To: -1, GroupId: groupId, Status: status, } err = NewAction(coordConn, productName, ACTION_TYPE_MULTI_SLOT_CHANGED, param, "", true) return errors.Trace(err) }
func (sg *ServerGroup) AddServer(coordConn zkhelper.Conn, s *Server, auth string) error { switch s.Type { case SERVER_TYPE_MASTER, SERVER_TYPE_SLAVE, SERVER_TYPE_OFFLINE: default: return errors.NotSupportedf("server type %q", s.Type) } // if type is offline, the server may be down, so we cannot use store function if s.Type != SERVER_TYPE_OFFLINE { // we only support reborn-server and qdb-server // origin redis has no slot_info command // atm, we can use this command to check whether server is alive or not. if _, err := utils.SlotsInfo(s.Addr, 0, 0, auth); err != nil { return errors.Trace(err) } } s.GroupId = sg.Id servers, err := sg.GetServers(coordConn) if err != nil { return errors.Trace(err) } var masterAddr string for _, server := range servers { if server.Type == SERVER_TYPE_MASTER { masterAddr = server.Addr } } // make sure there is only one master if s.Type == SERVER_TYPE_MASTER && len(masterAddr) > 0 { return errors.Trace(ErrNodeExists) } // if this group has no server. // promote this server to master automatically if type is not offline if len(servers) == 0 && s.Type != SERVER_TYPE_OFFLINE { s.Type = SERVER_TYPE_MASTER } if s.Type == SERVER_TYPE_MASTER { if role, err := utils.GetRole(s.Addr, auth); err != nil { return errors.Trace(err) } else if role != "master" { return errors.Errorf("we need master, but server %s is %s", s.Addr, role) } } val, err := json.Marshal(s) if err != nil { return errors.Trace(err) } coordPath := fmt.Sprintf("/zk/reborn/db_%s/servers/group_%d/%s", sg.ProductName, sg.Id, s.Addr) _, err = zkhelper.CreateOrUpdate(coordConn, coordPath, string(val), 0, zkhelper.DefaultFileACLs(), true) // update servers servers, err = sg.GetServers(coordConn) if err != nil { return errors.Trace(err) } sg.Servers = servers if s.Type == SERVER_TYPE_MASTER { err = NewAction(coordConn, sg.ProductName, ACTION_TYPE_SERVER_GROUP_CHANGED, sg, "", true) if err != nil { return errors.Trace(err) } } else if s.Type == SERVER_TYPE_SLAVE && len(masterAddr) > 0 { // send command slaveof to slave err := utils.SlaveOf(s.Addr, masterAddr, auth) if err != nil { return errors.Trace(err) } } return nil }