func ProcessCommand(msg protocol.Message) protocol.Message { var ( name []byte argc int64 cmd command.Command ok bool ) switch msg.GetProtocolType() { case protocol.ArraysType: if argc = msg.GetIntegersValue(); argc > 0 { name = msg.GetArraysValue()[0].GetBytesValue() } } if cmd, ok = commandSet.SearchCommand(name); !ok { return protocol.NewMessageString(protocol.ERR_unknown_command, name) } if !cmd.CheckArgc(argc) { return protocol.NewMessageString(protocol.ERR_wrong_number_command, cmd.Name()) } if cmd.CheckForbidden() { return protocol.NewMessageString(protocol.ERR_forbidden_command, cmd.Name()) } return cmd.Proc(cmd, msg) }
func MGetCommand(cmd command.Command, msg protocol.Message) (msgAck protocol.Message) { var ( elements []protocol.Message = msg.GetArraysValue() element protocol.Message hashSlot uint16 classification map[uint16]protocol.Message = make(map[uint16]protocol.Message) msgSpice protocol.Message ok bool ) for _, element = range elements[1:] { hashSlot = crc16.HashSlot(element.GetBytesValue()) if msgSpice, ok = classification[hashSlot]; !ok { msgSpice = protocol.NewMessage().AppendArraysValue(elements[0]) } classification[hashSlot] = msgSpice.AppendArraysValue(element) } // 按slot分命令 var ( node nodes.Nodes msgAckSplit protocol.Message msgAckMap map[protocol.Message]protocol.Message = make(map[protocol.Message]protocol.Message) msgKey int msgValue protocol.Message ) for hashSlot, msgSpice = range classification { if node, ok = cluster.GetClusterParameter().GetSlot(hashSlot); !ok { logger.Warningf("获取不到slot节点: %d", hashSlot) continue } msgAckSplit = forwardMsg(msgSpice, node, cmd.CheckReadonly()) if msgAckSplit.GetProtocolType() != protocol.ArraysType { logger.Warningf("命令结果预期不符: %v", msgSpice) continue } if msgSpice.GetIntegersValue()-1 != msgAckSplit.GetIntegersValue() { logger.Warningf("命令结果预期不符: %v", msgSpice) continue } for msgKey, msgValue = range msgSpice.GetArraysValue()[1:] { msgAckMap[msgValue] = msgAckSplit.GetArraysValue()[msgKey] } } // 整合结果 msgAck = protocol.NewMessage() for _, element = range elements[1:] { if msgValue, ok = msgAckMap[element]; ok { msgAck.AppendArraysValue(msgAckMap[element]) } else { msgAck.AppendArraysValue(protocol.NullBulkString) } } return }
func (c *cluster) refresh(server string) (err error) { var ( connPool connection.Pool = c.GetNodePool(server) conn connection.Conn slotsMsgAck protocol.Message ) if conn, err = connPool.Get(); err != nil { return } // 发送cluster slots if slotsMsgAck, err = conn.HandelMessage(protocol.ClusterSlots); err != nil { connPool.Remove(conn) return } connPool.Put(conn) // 处理返回值 if slotsMsgAck.GetProtocolType() != protocol.ArraysType || slotsMsgAck.GetIntegersValue() <= 0 { return fmt.Errorf("slots数据无效") } var slotsMsgAckValue protocol.Message for _, slotsMsgAckValue = range slotsMsgAck.GetArraysValue() { if slotsMsgAckValue.GetProtocolType() != protocol.ArraysType || slotsMsgAckValue.GetIntegersValue() < 3 { return fmt.Errorf("slots节点数据无效") } var ( slotsMsgAckValueArrays []protocol.Message = slotsMsgAckValue.GetArraysValue() nodeMsgValue protocol.Message nodeMsgValueArrays []protocol.Message connPoolList []connection.Pool ) if slotsMsgAckValueArrays[0].GetProtocolType() != protocol.IntegersType || slotsMsgAckValueArrays[1].GetProtocolType() != protocol.IntegersType { return fmt.Errorf("slots节点起始或者结束数据无效") } for _, nodeMsgValue = range slotsMsgAckValueArrays[2:] { if nodeMsgValue.GetProtocolType() != protocol.ArraysType || nodeMsgValue.GetIntegersValue() < 2 { return fmt.Errorf("slot节点数据无效") } nodeMsgValueArrays = nodeMsgValue.GetArraysValue() if nodeMsgValueArrays[0].GetProtocolType() != protocol.BulkStringsType { return fmt.Errorf("slot节点IP无效") } if nodeMsgValueArrays[1].GetProtocolType() != protocol.IntegersType { return fmt.Errorf("slot节点PORT无效") } connPoolList = append( connPoolList, c.GetNodePool(fmt.Sprintf("%s:%d", nodeMsgValueArrays[0].GetBytesValue(), nodeMsgValueArrays[1].GetIntegersValue())), ) } c.clusterSlots.AddSlots( slotsMsgAckValueArrays[0].GetIntegersValue(), slotsMsgAckValueArrays[1].GetIntegersValue(), nodes.NewNodes().Set(connPoolList), // TODO 同一个List用同一个Nodes ) } return }