// 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")

}
Example #2
0
// 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
}
Example #3
0
// 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
}
Example #4
0
// 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
}
Example #5
0
// 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
}
Example #6
0
// 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
}
Example #7
0
// 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
}
Example #8
0
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
}
Example #9
0
// 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
}
Example #11
0
// 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
}
Example #12
0
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
}