func (ss *cohortStorageServer) RegisterServer(args *storagerpc.RegisterArgs, reply *storagerpc.RegisterReply) error { // Node not yet seen by MasterServer ss.rw.Lock() if _, ok := ss.exists[args.ServerInfo.NodeId]; !ok { ss.exists[args.ServerInfo.NodeId] = true ss.servers = append(ss.servers, args.ServerInfo) } if len(ss.servers) < ss.numNodes { ss.rw.Unlock() reply.Status = storagerpc.NotReady return nil } /// sort the nodes by nodeID starting from lowest nodeSorter := func(n1, n2 *storagerpc.Node) bool { return n1.NodeId < n2.NodeId } By(nodeSorter).Sort(ss.servers) ss.rw.Unlock() reply.Status = storagerpc.OK reply.Servers = ss.servers return nil }
func NewCohortStorageServer(masterHostPort, selfHostPort string, nodeId uint32, numNodes int) (CohortStorageServer, error) { ss := new(cohortStorageServer) ss.nodeId = nodeId ss.masterHostPort = masterHostPort ss.selfHostPort = selfHostPort ss.servers = make([]storagerpc.Node, 0, numNodes) // Consistent hashing ring. Empty if not instance is not master. ss.storage = make(map[string]string) ss.locks = make(map[string]*sync.RWMutex) ss.exists = make(map[uint32]bool) ss.rw = new(sync.RWMutex) ss.undoLog = make(map[int]LogEntry) // TransactionId to Store 1. Key 2. TransactionId. (Old)Value ss.redoLog = make(map[int]LogEntry) // TransactionId to Store 1. Key 2. TransactionID. (New)Value ss.numNodes = numNodes ss.tickers = make(map[string]uint64) ss.setTickers() // server is the master and must init the ring and listen for 'RegisterServer' calls if masterHostPort == "" { ss.master = true masterNode := storagerpc.Node{HostPort: selfHostPort, NodeId: nodeId, Master: true} ss.exists[nodeId] = true ss.servers = append(ss.servers, masterNode) for errCount := 0; ; errCount++ { err := rpc.RegisterName("CohortStorageServer", storagerpc.Wrap(ss)) if err != nil { if errCount == 5 { return nil, err } time.Sleep(time.Second) continue } else { break } } var err error listener, err := net.Listen("tcp", selfHostPort) log.Println("Master listening on: ", selfHostPort) if err != nil { return nil, err } rpc.HandleHTTP() go http.Serve(listener, nil) return ss, nil } // server is a slave in the ring cli, err := util.TryDial(masterHostPort) if err != nil { log.Println("error: ", err) return nil, err } // Try to register the slave into the ring with the masterNode slaveNode := storagerpc.Node{HostPort: selfHostPort, NodeId: nodeId, Master: false} args := &storagerpc.RegisterArgs{ServerInfo: slaveNode} var reply storagerpc.RegisterReply // break out when status == storagerpc.OK for reply.Status = storagerpc.NotReady; reply.Status == storagerpc.NotReady; time.Sleep(time.Second) { if err := cli.Call("CohortStorageServer.RegisterServer", args, &reply); err != nil { log.Println("Failed to RegisterServer: ", err) return nil, err } } ss.servers = reply.Servers for errCount := 0; ; errCount++ { err := rpc.RegisterName("CohortStorageServer", storagerpc.Wrap(ss)) if err != nil { if errCount == 5 { return nil, err } time.Sleep(time.Second) continue } else { break } } listener, err := net.Listen("tcp", selfHostPort) if err != nil { return nil, err } rpc.HandleHTTP() go http.Serve(listener, nil) return ss, nil }