// ClientRequestSendMessages checks we are the leader and then queues the messages // Results are only sent once the messages are on the queue func (node *Node) ClientRequestSendMessages(args *rapi.SendMessagesArgs, results *rapi.SendMessagesResults) error { //log.Printf("Starting request send message\n") state := node.getState() if state == SHUTDOWN_NODE { results.Result = rapi.Get_RI_NODE_IN_SHUTDOWN(node.name) return nil } else if state != LEADER_NODE { results.Result = rapi.Get_RI_NODE_NOT_LEADER(node.name, node.getLastSeenLeader()) return nil } //log.Printf("Sending to queue aggregator.\n") //IDs, err := node.log.Queue(node.getTerm(), args.SentMessages) IDs, err := node.writeAggregator.Queue(args.SentMessages) //log.Printf("Got response from write aggregator\n") results.IDs = IDs if err == nil { results.Result = rapi.Get_RI_SUCCESS() if !args.WaitForCommit { return nil } if len(IDs) > 0 { // See if we are waiting on commit waitForIndex := IDs[len(IDs)-1] for node.getState() == LEADER_NODE { if node.commitIndex.WaitOnCommitChange(waitForIndex) >= waitForIndex { return nil } } // If we get here then we are no longer the leader - return an error results.Result = rapi.Get_RI_NODE_NOT_LEADER(node.name, node.getLastSeenLeader()) } } return err }
/* IdentifyNode is used by other peers in the cluster to identify themselves to this node. */ func (handler *RPCHandler) IdentifyNode(args *IdentifyNodeArgs, results *IdentifyNodeResults) error { handler.peerName = args.Name handler.identified = true if args.ClusterID == handler.server.GetClusterID() { results.Result = rapi.Get_RI_SUCCESS() } else { results.Result = rapi.Get_RI_MISMATCHED_CLUSTER_ID(handler.server.address, args.ClusterID, handler.server.GetClusterID()) } return nil }
// ClientReceiveMessages returns messages at and beyond ID // If WaitForMessages is true and no messages are currently present, this method blocks // until at least one message can be returned func (node *Node) ClientReceiveMessages(args *rapi.ReceiveMessagesArgs, results *rapi.ReceiveMessagesResults) error { state := node.getState() if state == SHUTDOWN_NODE { results.Result = rapi.Get_RI_NODE_IN_SHUTDOWN(node.name) return nil } msgs, nextID, err := node.log.Get(args.ID, args.Quantity, args.WaitForMessages) if err == nil { results.Result = rapi.Get_RI_SUCCESS() results.ReceivedMessages = msgs results.NextID = nextID } return err }
func (srv *ServerNode) GetClusterDetails(args *rapi.GetClusterDetailsArgs, results *rapi.GetClusterDetailsResults) error { srv.lock.RLock() defer srv.lock.RUnlock() if srv.inShutdown { results.Result = rapi.Get_RI_NODE_IN_SHUTDOWN(srv.address) return nil } results.ClusterID = srv.config.Cluster_ID results.Peers = make([]string, 0, len(srv.config.Peers)) for _, peerName := range srv.config.Peers { results.Peers = append(results.Peers, peerName) } results.Topics = make([]string, 0, len(srv.config.Topics)) for topicName, _ := range srv.config.Topics { results.Topics = append(results.Topics, topicName) } results.Result = rapi.Get_RI_SUCCESS() return nil }
func (node *Node) GetTopicDetails(args *rapi.GetTopicDetailsArgs, results *rapi.GetTopicDetailsResults) error { state := node.getState() var err error if state == SHUTDOWN_NODE { results.Result = rapi.Get_RI_NODE_IN_SHUTDOWN(node.name) return nil } results.FirstIndex, err = node.log.FirstIndex() if err != nil { results.Result = rapi.Get_RI_INTERNAL_ERROR(node.name, err.Error()) return nil } results.LastIndex, err = node.log.LastIndex() if err != nil { results.Result = rapi.Get_RI_INTERNAL_ERROR(node.name, err.Error()) return nil } results.CommitIndex = node.log.GetCurrentCommit() results.Result = rapi.Get_RI_SUCCESS() return nil }
func (srv *ServerNode) manageConfigurationChanges() { srv_log("Waiting for configuration requests to handle\n") for request := range srv.changeConfig { srv_log("Processing new configuration change request\n") newConfig := request.Configuration if newConfig.Cluster_ID == srv.config.Cluster_ID { var err error srv_log("Recieved new configuration") if newConfig.Scope&CNF_Set_Peers != 0 { srv_log("Change in peers configuration") srv.config.Peers = newConfig.Peers srv.setPeers(newConfig.Peers) var peerConfigToUse ConfigPeers // Use the new configuration for topics only if we are part of the cluster. if newConfig.Peers.Contains(srv.address) { peerConfigToUse = newConfig.Peers } else { peerConfigToUse = make(ConfigPeers, 0) } srv_log("Passing new peer configuration to topics.\n") for _, topic := range srv.topics { topic.ChangePeerConfiguration(peerConfigToUse) } } else if newConfig.Scope&CNF_Set_Topic != 0 { srv_log("Topic configuration") for _, newTopic := range newConfig.Topics { if !srv.config.Topics.Contains(newTopic.Name) { topicConfig := GetDefaultTopicConfiguration() topicConfig.Name = newTopic.Name if newTopic.SegmentSize > 0 { topicConfig.SegmentSize = newTopic.SegmentSize } srv.config.Topics[newTopic.Name] = topicConfig node, err := srv.createTopic(topicConfig) node.StartNode() if err != nil { break } } else { // Modification of existing topic. configChangesToApply := make([]disklog.DiskLogConfigFunction, 0, 3) currentTopic := srv.config.Topics[newTopic.Name] if newTopic.SegmentSize > 0 && currentTopic.SegmentSize != newTopic.SegmentSize { // Change the current configuration currentTopic.SegmentSize = newTopic.SegmentSize configChangesToApply = append(configChangesToApply, disklog.SetTargetSegmentSize(newTopic.SegmentSize)) } if newTopic.SegmentCleanupAge >= 0 && currentTopic.SegmentCleanupAge != newTopic.SegmentCleanupAge { // Change the current configuration currentTopic.SegmentCleanupAge = newTopic.SegmentCleanupAge configChangesToApply = append(configChangesToApply, disklog.SetSegmentCleanupAge(newTopic.SegmentCleanupAge)) } if len(configChangesToApply) > 0 { // Store any changes we've made srv.config.Topics[newTopic.Name] = currentTopic // Update the current configuration. srv.lock.RLock() node := srv.topics[newTopic.Name] diskStorage := node.GetCommitLog().GetLogStorage().(*disklog.DiskLogStorage) diskStorage.ChangeConfiguration(configChangesToApply...) srv.lock.RUnlock() } } } } else if newConfig.Scope&CNF_Remove_Topic != 0 { srv_log("Topic removal") for _, removedTopic := range newConfig.Topics { if srv.config.Topics.Contains(removedTopic.Name) { currentTopic := srv.config.Topics[removedTopic.Name] delete(srv.config.Topics, removedTopic.Name) err = srv.removeTopic(currentTopic) if err != nil { break } } else { srv_log("Topic %v not present - no removal required.\n", removedTopic.Name) } } } if err == nil { srv_log("Saving configuration\n") err = srv.config.SaveConfiguration() } if err != nil { request.Response <- rapi.Get_RI_INTERNAL_ERROR(srv.address, err.Error()) } else { request.Response <- rapi.Get_RI_SUCCESS() } } else { srv_log("Cluster ID give for config change (%v) doesn't match server cluster ID of (%v)\n", newConfig.Cluster_ID, srv.config.Cluster_ID) request.Response <- rapi.Get_RI_MISMATCHED_CLUSTER_ID(srv.address, newConfig.Cluster_ID, srv.config.Cluster_ID) } } srv_log("manageConfigurationChanges shutdown\n") }