// NewLibstore creates a new instance of a TribServer's libstore. masterServerHostPort // is the master storage server's host:port. myHostPort is this Libstore's host:port // (i.e. the callback address that the storage servers should use to send back // notifications when leases are revoked). // // The mode argument is a debugging flag that determines how the Libstore should // request/handle leases. If mode is Never, then the Libstore should never request // leases from the storage server (i.e. the GetArgs.WantLease field should always // be set to false). If mode is Always, then the Libstore should always request // leases from the storage server (i.e. the GetArgs.WantLease field should always // be set to true). If mode is Normal, then the Libstore should make its own // decisions on whether or not a lease should be requested from the storage server, // based on the requirements specified in the project PDF handout. Note that the // value of the mode flag may also determine whether or not the Libstore should // register to receive RPCs from the storage servers. // // To register the Libstore to receive RPCs from the storage servers, the following // line of code should suffice: // // rpc.RegisterName("LeaseCallbacks", librpc.Wrap(libstore)) // // Note that unlike in the NewTribServer and NewStorageServer functions, there is no // need to create a brand new HTTP handler to serve the requests (the Libstore may // simply reuse the TribServer's HTTP handler since the two run in the same process). func NewLibstore(masterServerHostPort, myHostPort string, mode LeaseMode) (Libstore, error) { fmt.Println("New an libstore") client, err := rpc.DialHTTP("tcp", masterServerHostPort) if err != nil { // log.Fatalln("dialing:", err) return nil, errors.New("meet error when DialHTTP") } args := &storagerpc.GetServersArgs{} reply := &storagerpc.GetServersReply{} num := 0 for reply.Status != storagerpc.OK { if num >= 5 { return nil, errors.New("cannot find the storage server") } err = client.Call("StorageServer.GetServers", args, reply) if err != nil { return nil, errors.New("meet error when client call") } if reply.Status != storagerpc.OK { time.Sleep(1000 * time.Millisecond) } num++ } libstore := &libstore{ Servers: reply.Servers, // keyValueMutex: make(map[string]*sync.Mutex), // keyListMutex: make(map[string]*sync.Mutex), mutex: &sync.Mutex{}, // client: client, keyValue: make(map[string]*valuelib), keylist: make(map[string]*listlib), keyValudhistory: make(map[string]*list.List), keyListhistory: make(map[string]*list.List), keyValueMutex: make(map[string]*sync.Mutex), keyListMutex: make(map[string]*sync.Mutex), mode: mode, clientmap: make(map[string]*rpc.Client), myHostPort: myHostPort, } libstore.clientmap[masterServerHostPort] = client err = rpc.RegisterName("LeaseCallbacks", librpc.Wrap(libstore)) // retry until register sucessfully for err != nil { err = rpc.RegisterName("LeaseCallbacks", librpc.Wrap(libstore)) } go libstore.epochtime() return libstore, nil // return nil, errors.New("not implemented") }
// NewLibstore creates a new instance of a TribServer's libstore. masterServerHostPort // is the master storage server's host:port. myHostPort is this Libstore's host:port // (i.e. the callback address that the storage servers should use to send back // notifications when leases are revoked). // // The mode argument is a debugging flag that determines how the Libstore should // request/handle leases. If mode is Never, then the Libstore should never request // leases from the storage server (i.e. the GetArgs.WantLease field should always // be set to false). If mode is Always, then the Libstore should always request // leases from the storage server (i.e. the GetArgs.WantLease field should always // be set to true). If mode is Normal, then the Libstore should make its own // decisions on whether or not a lease should be requested from the storage server, // based on the requirements specified in the project PDF handout. Note that the // value of the mode flag may also determine whether or not the Libstore should // register to receive RPCs from the storage servers. // // To register the Libstore to receive RPCs from the storage servers, the following // line of code should suffice: // // rpc.RegisterName("LeaseCallbacks", librpc.Wrap(libstore)) // // Note that unlike in the NewTribServer and NewStorageServer functions, there is no // need to create a brand new HTTP handler to serve the requests (the Libstore may // simply reuse the TribServer's HTTP handler since the two run in the same process). func NewLibstore(masterServerHostPort, myHostPort string, mode LeaseMode) (Libstore, error) { client, err := rpc.DialHTTP("tcp", masterServerHostPort) if err != nil { return nil, errors.New("Error DialHTTP in NewLibstore") } args := &storagerpc.GetServersArgs{} reply := &storagerpc.GetServersReply{} storageReady := false for i := 0; i < 5; i++ { err = client.Call("StorageServer.GetServers", args, reply) if err != nil { return nil, errors.New("Error Call in NewLibstore") } if reply.Status == storagerpc.OK { storageReady = true break } else { time.Sleep(1 * time.Second) } } if storageReady == false { return nil, errors.New("Storage not ready after 5 trial in NewLibstore") } ls := &libstore{ StorageServers: reply.Servers, connectionMap: make(map[string]*rpc.Client), HostPort: myHostPort, CacheValueSet: make(map[string]*valueCache), CacheListSet: make(map[string]*listCache), queryGetQueue: make(map[string]*list.List), queryListQueue: make(map[string]*list.List), queryGetMutex: make(map[string]*sync.Mutex), queryListMutex: make(map[string]*sync.Mutex), mutex: &sync.Mutex{}, mode: mode, } ls.connectionMap[masterServerHostPort] = client err = rpc.RegisterName("LeaseCallbacks", librpc.Wrap(ls)) for err != nil { fmt.Println("Error LeaseCallbacks in NewLibstore") // return nil, errors.New("Error LeaseCallbacks in NewLibstore") err = rpc.RegisterName("LeaseCallbacks", librpc.Wrap(ls)) } go func() { for { select { case <-time.After(time.Duration(storagerpc.LeaseSeconds/2) * time.Second): ls.updateCache() case <-time.After(time.Duration(storagerpc.QueryCacheSeconds/2) * time.Second): ls.updateQueue() } } }() return ls, nil }
// NewLibstore creates a new instance of a TribServer's libstore. masterServerHostPort // is the master storage server's host:port. myHostPort is this Libstore's host:port // (i.e. the callback address that the storage servers should use to send back // notifications when leases are revoked). // // The mode argument is a debugging flag that determines how the Libstore should // request/handle leases. If mode is Never, then the Libstore should never request // leases from the storage server (i.e. the GetArgs.WantLease field should always // be set to false). If mode is Always, then the Libstore should always request // leases from the storage server (i.e. the GetArgs.WantLease field should always // be set to true). If mode is Normal, then the Libstore should make its own // decisions on whether or not a lease should be requested from the storage server, // based on the requirements specified in the project PDF handout. Note that the // value of the mode flag may also determine whether or not the Libstore should // register to receive RPCs from the storage servers. // // To register the Libstore to receive RPCs from the storage servers, the following // line of code should suffice: // // rpc.RegisterName("LeaseCallbacks", librpc.Wrap(libstore)) // // Note that unlike in the NewTribServer and NewStorageServer functions, there is no // need to create a brand new HTTP handler to serve the requests (the Libstore may // simply reuse the TribServer's HTTP handler since the two run in the same process). func NewLibstore(masterServerHostPort, myHostPort string, mode LeaseMode) (Libstore, error) { master_server, err := rpc.DialHTTP("tcp", masterServerHostPort) if err != nil { return nil, errors.New("Cannot connect to the master server") } // Call GetServers to get storage servers' information var args storagerpc.GetServersArgs var reply storagerpc.GetServersReply master_server.Call("StorageServer.GetServers", args, &reply) if reply.Status == storagerpc.NotReady { for i := 0; i < 5; i++ { time.Sleep(1 * time.Second) master_server.Call("StorageServer.GetServers", args, &reply) if reply.Status == storagerpc.OK { break } } } master_server.Close() if reply.Status == storagerpc.NotReady { return nil, errors.New("Storage Server is not ready yet") } // Register RPC connection for each storage server ls := &libstore{} // Sort the servers by NodeID sort.Sort(SortNodeByNodeID(reply.Servers)) ls.servers = reply.Servers ls.rpc_connection = make([]*rpc.Client, len(ls.servers)) ls.host_port = myHostPort ls.lease_mode = mode ls.query_record = make(map[string]*list.List) ls.value_cache = make(map[string]*ValueCacheElement) ls.list_cache = make(map[string]*ListCacheElement) ls.query_record_locker = new(sync.Mutex) ls.value_cache_locker = new(sync.Mutex) ls.list_cache_locker = new(sync.Mutex) go ls.CacheCleaner() err = rpc.RegisterName("LeaseCallbacks", librpc.Wrap(ls)) if err != nil { return nil, errors.New("Could not register Libstore") } for i, server := range ls.servers { ls.rpc_connection[i], _ = rpc.DialHTTP("tcp", server.HostPort) } return ls, nil }
// NewLibstore creates a new instance of a TribServer's libstore. masterServerHostPort // is the master storage server's host:port. myHostPort is this Libstore's host:port // (i.e. the callback address that the storage servers should use to send back // notifications when leases are revoked). // // The mode argument is a debugging flag that determines how the Libstore should // request/handle leases. If mode is Never, then the Libstore should never request // leases from the storage server (i.e. the GetArgs.WantLease field should always // be set to false). If mode is Always, then the Libstore should always request // leases from the storage server (i.e. the GetArgs.WantLease field should always // be set to true). If mode is Normal, then the Libstore should make its own // decisions on whether or not a lease should be requested from the storage server, // based on the requirements specified in the project PDF handout. Note that the // value of the mode flag may also determine whether or not the Libstore should // register to receive RPCs from the storage servers. // // To register the Libstore to receive RPCs from the storage servers, the following // line of code should suffice: // // rpc.RegisterName("LeaseCallbacks", librpc.Wrap(libstore)) // // Note that unlike in the NewTribServer and NewStorageServer functions, there is no // need to create a brand new HTTP handler to serve the requests (the Libstore may // simply reuse the TribServer's HTTP handler since the two run in the same process). func NewLibstore(masterServerHostPort, myHostPort string, mode LeaseMode) (Libstore, error) { master, err := rpc.DialHTTP("tcp", masterServerHostPort) if err != nil { return nil, err } args := &storagerpc.GetServersArgs{} var reply storagerpc.GetServersReply for i := 0; i < 5; i++ { master.Call("StorageServer.GetServers", args, &reply) if reply.Status == storagerpc.OK { break } else { time.Sleep(time.Second) } } if reply.Status != storagerpc.OK { return nil, nil // After retry for 5 times... } nodeList := nodes(reply.Servers) sort.Sort(nodeList) nodeListSorted := ([]storagerpc.Node)(nodeList) newLib := &libstore{ master: master, svrMap: make(map[uint32]*rpc.Client), myHostPort: myHostPort, allServerNodes: nodeListSorted, svrMutex: &sync.Mutex{}, counter: make(map[string]int), counterMutex: &sync.Mutex{}, sMutex: &sync.Mutex{}, sCache: make(map[string]*sCachNode), lMutex: &sync.Mutex{}, lCache: make(map[string]*lCachNode), mode: mode, } if mode != Never { rpc.RegisterName("LeaseCallbacks", librpc.Wrap(newLib)) } go newLib.selfRevoke() go newLib.selfCleanCounter() return newLib, nil }
// NewLibstore creates a new instance of a TribServer's libstore. masterServerHostPort // is the master storage server's host:port. myHostPort is this Libstore's host:port // (i.e. the callback address that the storage servers should use to send back // notifications when leases are revoked). // // The mode argument is a debugging flag that determines how the Libstore should // request/handle leases. If mode is Never, then the Libstore should never request // leases from the storage server (i.e. the GetArgs.WantLease field should always // be set to false). If mode is Always, then the Libstore should always request // leases from the storage server (i.e. the GetArgs.WantLease field should always // be set to true). If mode is Normal, then the Libstore should make its own // decisions on whether or not a lease should be requested from the storage server, // based on the requirements specified in the project PDF handout. Note that the // value of the mode flag may also determine whether or not the Libstore should // register to receive RPCs from the storage servers. // // To register the Libstore to receive RPCs from the storage servers, the following // line of code should suffice: // // rpc.RegisterName("LeaseCallbacks", librpc.Wrap(libstore)) // // Note that unlike in the NewTribServer and NewStorageServer functions, there is no // need to create a brand new HTTP handler to serve the requests (the Libstore may // simply reuse the TribServer's HTTP handler since the two run in the same process). func NewLibstore(masterServerHostPort, myHostPort string, mode LeaseMode) (Libstore, error) { ls := &libstore{ myHostPort: myHostPort, mode: mode, storageServers: make(map[uint32]*storagerpc.Node), cache: newCache(), storageRPCHandler: make(map[uint32]*rpc.Client), accessInfoHub: newAccessInfoHub(), } // connect to the master server and get the server list master, err := rpc.DialHTTP("tcp", masterServerHostPort) if err != nil { return nil, err } var args storagerpc.GetServersArgs var reply storagerpc.GetServersReply ok := false for i := 0; i < maximumTrials; i++ { err = master.Call("StorageServer.GetServers", &args, &reply) if reply.Status == storagerpc.OK { ok = true break } time.Sleep(time.Second) } if !ok { return nil, errors.New("Cannot get servers after " + strconv.Itoa(maximumTrials) + " trials") } // adding the server list for _, s := range reply.Servers { ls.storageServers[s.NodeID] = &s ls.storageRPCHandler[s.NodeID], err = rpc.DialHTTP("tcp", s.HostPort) if err != nil { return nil, err } } // register the callback rpc.RegisterName("LeaseCallbacks", librpc.Wrap(ls)) go ls.gc() return ls, nil }
// NewLibstore creates a new instance of a TribServer's libstore. masterServerHostPort // is the master storage server's host:port. myHostPort is this Libstore's host:port // (i.e. the callback address that the storage servers should use to send back // notifications when leases are revoked). // // The mode argument is a debugging flag that determines how the Libstore should // request/handle leases. If mode is Never, then the Libstore should never request // leases from the storage server (i.e. the GetArgs.WantLease field should always // be set to false). If mode is Always, then the Libstore should always request // leases from the storage server (i.e. the GetArgs.WantLease field should always // be set to true). If mode is Normal, then the Libstore should make its own // decisions on whether or not a lease should be requested from the storage server, // based on the requirements specified in the project PDF handout. Note that the // value of the mode flag may also determine whether or not the Libstore should // register to receive RPCs from the storage servers. // // To register the Libstore to receive RPCs from the storage servers, the following // line of code should suffice: // // rpc.RegisterName("LeaseCallbacks", librpc.Wrap(libstore)) // // Note that unlike in the NewTribServer and NewStorageServer functions, there is no // need to create a brand new HTTP handler to serve the requests (the Libstore may // simply reuse the TribServer's HTTP handler since the two run in the same process). func NewLibstore(masterServerHostPort, myHostPort string, mode LeaseMode) (Libstore, error) { cli, err := rpc.DialHTTP("tcp", masterServerHostPort) if err != nil { return nil, err } args := &storagerpc.GetServersArgs{} var reply storagerpc.GetServersReply for i := 0; i < 6; i++ { if err := cli.Call("StorageServer.GetServers", args, &reply); err != nil { return nil, err } if reply.Status != storagerpc.NotReady { break } time.Sleep(time.Duration(1) * time.Second) } if reply.Status != storagerpc.OK { return nil, errors.New("GetServers f****d up mane") } clients := make(map[uint32]*rpc.Client) for _, node := range reply.Servers { cli, err := rpc.DialHTTP("tcp", node.HostPort) if err != nil { return nil, err } clients[node.NodeID] = cli } libstore := createLibStore(clients, mode) go libstore.epochloop() go libstore.eventHandler() rpc.RegisterName("LeaseCallbacks", librpc.Wrap(libstore)) return libstore, nil }
// NewLibstore creates a new instance of a TribServer's libstore. masterServerHostPort // is the master storage server's host:port. myHostPort is this Libstore's host:port // (i.e. the callback address that the storage servers should use to send back // notifications when leases are revoked). // // The mode argument is a debugging flag that determines how the Libstore should // request/handle leases. If mode is Never, then the Libstore should never request // leases from the storage server (i.e. the GetArgs.WantLease field should always // be set to false). If mode is Always, then the Libstore should always request // leases from the storage server (i.e. the GetArgs.WantLease field should always // be set to true). If mode is Normal, then the Libstore should make its own // decisions on whether or not a lease should be requested from the storage server, // based on the requirements specified in the project PDF handout. Note that the // value of the mode flag may also determine whether or not the Libstore should // register to receive RPCs from the storage servers. // // To register the Libstore to receive RPCs from the storage servers, the following // line of code should suffice: // // rpc.RegisterName("LeaseCallbacks", librpc.Wrap(libstore)) // // Note that unlike in the NewTribServer and NewStorageServer functions, there is no // need to create a brand new HTTP handler to serve the requests (the Libstore may // simply reuse the TribServer's HTTP handler since the two run in the same process). func NewLibstore(masterServerHostPort, myHostPort string, mode LeaseMode) (Libstore, error) { //fmt.Println("begin connection") cli, err := rpc.DialHTTP("tcp", masterServerHostPort) if err != nil { return nil, err } defer cli.Close() var args storagerpc.GetServersArgs var reply storagerpc.GetServersReply for i := 0; i < 5; i++ { err = cli.Call("StorageServer.GetServers", &args, &reply) if err != nil { fmt.Println("no such methods") return nil, err } if reply.Status == storagerpc.OK { //fmt.Println("connection succeed!") break } time.Sleep(1000 * time.Millisecond) } if reply.Status == storagerpc.NotReady || reply.Servers == nil { return nil, errors.New("storage server haven't ready") } lib := new(libstore) lib.hostport = myHostPort lib.mode = mode lib.nodes = reply.Servers lib.rpcClient = make([]*rpc.Client, len(lib.nodes)) lib.leases = cache.NewCache() // DO WEEE NEED TO SORT??? //fmt.Println("connection succeed!") rpc.RegisterName("LeaseCallbacks", librpc.Wrap(lib)) go CleanCache(lib.leases) return lib, nil }
func initStorageTester(server, myhostport string) (*storageTester, error) { tester := new(storageTester) tester.myhostport = myhostport tester.recvRevoke = make(map[string]bool) tester.compRevoke = make(map[string]bool) // Create RPC connection to storage server. srv, err := rpc.DialHTTP("tcp", server) if err != nil { return nil, fmt.Errorf("could not connect to server %s", server) } rpc.RegisterName("LeaseCallbacks", librpc.Wrap(tester)) rpc.HandleHTTP() l, err := net.Listen("tcp", fmt.Sprintf(":%d", *portnum)) if err != nil { LOGE.Fatalln("Failed to listen:", err) } go http.Serve(l, nil) tester.srv = srv return tester, nil }
// NewLibstore creates a new instance of a TribServer's libstore. masterServerHostPort // is the master storage server's host:port. myHostPort is this Libstore's host:port // (i.e. the callback address that the storage servers should use to send back // notifications when localCache are revoked). // // The mode argument is a debugging flag that determines how the Libstore should // request/handle localCache. If mode is Never, then the Libstore should never request // localCache from the storage server (i.e. the GetArgs.WantLease field should always // be set to false). If mode is Always, then the Libstore should always request // localCache from the storage server (i.e. the GetArgs.WantLease field should always // be set to true). If mode is Normal, then the Libstore should make its own // decisions on whether or not a lease should be requested from the storage server, // based on the requirements specified in the project PDF handout. Note that the // value of the mode flag may also determine whether or not the Libstore should // register to receive RPCs from the storage servers. // // To register the Libstore to receive RPCs from the storage servers, the following // line of code should suffice: // // rpc.RegisterName("LeaseCallbacks", librpc.Wrap(libstore)) // // Note that unlike in the NewTribServer and NewStorageServer functions, there is no // need to create a brand new HTTP handler to serve the requests (the Libstore may // simply reuse the TribServer's HTTP handler since the two run in the same process). func NewLibstore(masterServerHostPort, myHostPort string, mode LeaseMode) (Libstore, error) { cli, err := rpc.DialHTTP("tcp", masterServerHostPort) if err != nil { return nil, err } defer cli.Close() var args storagerpc.GetServersArgs var reply storagerpc.GetServersReply for i := 0; i < 5; i++ { err = cli.Call("StorageServer.GetServers", &args, &reply) if err != nil { return nil, err } if reply.Status == storagerpc.OK { break } time.Sleep(1000 * time.Millisecond) } if reply.Status == storagerpc.NotReady { return nil, errors.New("storage server haven't ready") } lib := new(libstore) lib.hostport = myHostPort lib.mode = mode sort.Sort(storagerpc.NodeSlice(reply.Servers)) lib.nodes = reply.Servers lib.rpcClientIndex = make(map[uint32]*rpc.Client) lib.localCache = libcache.NewCache() rpc.RegisterName("LeaseCallbacks", librpc.Wrap(lib)) return lib, nil }
// NewLibstore creates a new instance of a TribServer's libstore. masterServerHostPort // is the master storage server's host:port. myHostPort is this Libstore's host:port // (i.e. the callback address that the storage servers should use to send back // notifications when leases are revoked). // // The mode argument is a debugging flag that determines how the Libstore should // request/handle leases. If mode is Never, then the Libstore should never request // leases from the storage server (i.e. the GetArgs.WantLease field should always // be set to false). If mode is Always, then the Libstore should always request // leases from the storage server (i.e. the GetArgs.WantLease field should always // be set to true). If mode is Normal, then the Libstore should make its own // decisions on whether or not a lease should be requested from the storage server, // based on the requirements specified in the project PDF handout. Note that the // value of the mode flag may also determine whether or not the Libstore should // register to receive RPCs from the storage servers. // // To register the Libstore to receive RPCs from the storage servers, the following // line of code should suffice: // // rpc.RegisterName("LeaseCallbacks", librpc.Wrap(libstore)) // // Note that unlike in the NewTribServer and NewStorageServer functions, there is no // need to create a brand new HTTP handler to serve the requests (the Libstore may // simply reuse the TribServer's HTTP handler since the two run in the same process). func NewLibstore(masterServerHostPort, myHostPort string, mode LeaseMode) (Libstore, error) { if myHostPort == "" && mode != Never { fmt.Println("@@@@FatalBughhh") } cli, err := rpc.DialHTTP("tcp", masterServerHostPort) if err != nil { return nil, err } // keep retrying for at most 5 times. args := &storagerpc.GetServersArgs{} var storages []storageNode for i := 0; ; i++ { var reply storagerpc.GetServersReply if cli.Call("StorageServer.GetServers", args, &reply) != nil { fmt.Println("@@@@FatalError: libstore RPC function call failed. -> GetServers!") } if reply.Status == storagerpc.OK { storages = make([]storageNode, len(reply.Servers), len(reply.Servers)) err = WrapNode(reply.Servers, storages) // fmt.Println("After the wrapping:", storages) if err != nil { return nil, err } break } fmt.Println("LibStore retrying connection...", i) time.Sleep(time.Second) if i == 6 { fmt.Println("@@@@FatalError: libstore has tried 5 times, but the master node is still not ready!") return nil, err } } dCache := make(map[string](*dataUnit)) qCache := make(map[string]([]int64)) lib := &libstore{ storages: storages, callback: myHostPort, mode: mode, dataCache: dCache, queryCache: qCache} // register call back if needed if mode != Never { if err = rpc.RegisterName("LeaseCallbacks", librpc.Wrap(lib)); err != nil { fmt.Println("@@@@Fatal Error, cannot register the libstore's RPC", err) return nil, err } } go lib.GarbageCollection() fmt.Println("Libstore created:", lib.callback) return lib, nil }
// NewLibstore creates a new instance of a TribServer's libstore. masterServerHostPort // is the master storage server's host:port. myHostPort is this Libstore's host:port // (i.e. the callback address that the storage servers should use to send back // notifications when leases are revoked). // // The mode argument is a debugging flag that determines how the Libstore should // request/handle leases. If mode is Never, then the Libstore should never request // leases from the storage server (i.e. the GetArgs.WantLease field should always // be set to false). If mode is Always, then the Libstore should always request // leases from the storage server (i.e. the GetArgs.WantLease field should always // be set to true). If mode is Normal, then the Libstore should make its own // decisions on whether or not a lease should be requested from the storage server, // based on the requirements specified in the project PDF handout. Note that the // value of the mode flag may also determine whether or not the Libstore should // register to receive RPCs from the storage servers. // // To register the Libstore to receive RPCs from the storage servers, the following // line of code should suffice: // // rpc.RegisterName("LeaseCallbacks", librpc.Wrap(libstore)) // // Note that unlike in the NewTribServer and NewStorageServer functions, there is no // need to create a brand new HTTP handler to serve the requests (the Libstore may // simply reuse the TribServer's HTTP handler since the two run in the same process). func NewLibstore(masterServerHostPort, myHostPort string, mode LeaseMode) (Libstore, error) { ls := new(libstore) rpc.RegisterName("LeaseCallbacks", librpc.Wrap(ls)) var client *rpc.Client var err error // Connect to master storage server for try := 1; try <= 5; try++ { client, err = rpc.DialHTTP("tcp", masterServerHostPort) if err == nil { break } if try == 5 { return nil, err } time.Sleep(time.Second) } var args storagerpc.GetServersArgs var reply storagerpc.GetServersReply var servers []storagerpc.Node // Try five times to request the list of storage servers from the master for i := 1; i <= 5; i++ { client.Call("StorageServer.GetServers", args, &reply) if reply.Status == storagerpc.OK { // Success! Store list of servers servers = reply.Servers break } else { // Failure, sleep one second and try again if i == 5 { return nil, errors.New("Couldn't connect to storage server") } time.Sleep(time.Second) } } // Create libstore and save the connection to the master server var clients = make([]*rpc.Client, len(reply.Servers)) // WRONG! StorageServer does not assume servers[0] is master //clients[0] = client for j := 0; j < len(servers); j++ { if servers[j].HostPort == masterServerHostPort { clients[j] = client break } } ls.myHostPort = myHostPort ls.mode = mode ls.servers = servers ls.clients = clients ls.cacheGet = make(map[string]string) // maps key to result ls.cacheValid = make(map[string]bool) ls.cacheList = make(map[string][]string) ls.cacheTimes = make(map[string][]time.Time) ls.cacheRecent = make(map[string]int) return ls, nil // So it won't yell at me for fmt fmt.Println(1) return nil, nil }
func NewLibstore(masterServerHostPort, myHostPort string, mode LeaseMode) (Libstore, error) { fmt.Println("Starting NewLibstore-") masterServ, err := rpc.DialHTTP("tcp", masterServerHostPort) if err != nil { return nil, err } getServArgs := storagerpc.GetServersArgs{} //declare empty struct to store return var getServReply storagerpc.GetServersReply //retry every second, if not yet ready //timer := time.NewTimer(time.Second * 1) var tryCount int = 0 Loop: for { //fmt.Println("calling get servers") err = masterServ.Call("StorageServer.GetServers", getServArgs, &getServReply) //fmt.Println("Return from rpc call") if err != nil { return nil, err } else { //err is nil if getServReply.Status == storagerpc.OK { //fmt.Println("NewLibstore: Status OK, breaking..") break Loop } } if tryCount == 4 { return nil, errors.New(TIMEOUT_GETTING_SERVERS) } //status is not OK; wait for timer //fmt.Println("Waiting for timer channel..") time.Sleep(1 * time.Second) //fmt.Println("Slowserv: counting ", tryCount) tryCount++ } //Convert to sort interface type and sort var toBeSortedNodes NodeByID = NodeByID(getServReply.Servers) sort.Sort(toBeSortedNodes) //Convert back to []Node type var sortedNodes []storagerpc.Node = []storagerpc.Node(toBeSortedNodes) fmt.Println(sortedNodes) //initialise server-connection map serverConnMap := make(map[storagerpc.Node]*rpc.Client) //initialise connection with all nodes for _, node := range sortedNodes { serverConn, err := rpc.DialHTTP("tcp", node.HostPort) if err != nil { fmt.Println("Error DialHTTP in libstore with a node") } else { //add to cache serverConnMap[node] = serverConn } } //TODo add master server to map? var newLs libstore = libstore{ masterServ: masterServ, allServerNodes: sortedNodes, serverConnMap: serverConnMap, dataMap: make(map[string]interface{}), dataMapLock: &sync.Mutex{}, queries: make(map[string]([]time.Time)), queriesLock: &sync.Mutex{}, leases: make(map[leaseinfo]bool), leasesLock: &sync.Mutex{}, mode: mode, hostPort: myHostPort, } err = rpc.RegisterName("LeaseCallbacks", librpc.Wrap(&newLs)) if err != nil { fmt.Println(err) return nil, err } go newLs.evictFromCache() //run in background return &newLs, nil }