func (ss *storageServer) isInServerRange(key string) bool {
	//only consider the part before colon
	hashKey := strings.Split(key, ":")[0]

	//two helper variable
	var minNodeID uint32
	var targetNodeID uint32
	minNodeID = math.MaxUint32
	targetNodeID = math.MaxUint32

	hashVal := libstore.StoreHash(hashKey)
	for i := 0; i < len(ss.nodeList); i++ {
		nodeID := ss.nodeList[i].NodeID
		if nodeID >= hashVal && nodeID < targetNodeID {
			targetNodeID = nodeID
		}

		//find the min value in all nodeIDs
		if nodeID < minNodeID {
			minNodeID = nodeID
		}
	}

	//case : hash value lager than the largest nodeID in consistent hashing ring
	if targetNodeID == math.MaxUint32 {
		targetNodeID = minNodeID
	}

	if targetNodeID == ss.nodeID {
		return true
	} else {
		return false
	}
}
func (ss *storageServer) GetList(args *storagerpc.GetArgs, reply *storagerpc.GetListReply) error {
	if DBG {
		fmt.Println("Entered storageserver GetList")
	}
	if !ss.inRange(libstore.StoreHash(args.Key)) {
		reply.Status = storagerpc.WrongServer
		return nil
	}
	ss.dataLock.Lock()
	val, ok := ss.dataStore[args.Key]
	ss.dataLock.Unlock()
	if ok {
		reply.Status = storagerpc.OK
		reply.Value = ListToSlice(val.(*list.List))
		if args.WantLease && ss.pendingMap[args.Key].pending == 0 {
			ss.leaseLock.Lock()
			lease := storagerpc.Lease{Granted: true, ValidSeconds: storagerpc.LeaseSeconds}
			reply.Lease = lease
			// Track that this lease was issued
			leaseWrap := LeaseWrapper{lease: lease, timeGranted: time.Now(), hostport: args.HostPort}
			_, ok := ss.leaseStore[args.Key]
			if !ok {
				ss.leaseStore[args.Key] = list.New()
			}
			ss.leaseStore[args.Key].PushBack(leaseWrap)
			ss.leaseLock.Unlock()
		}
	} else {
		reply.Status = storagerpc.KeyNotFound
	}
	return nil
}
/// find the routing address given the server ring.
func FindPartitionNode(ring []storagerpc.Node, pKey string) storagerpc.Node {

	//	fmt.Println("Partitioning with", ring)
	// extract only the real key from the pKey
	tID := libstore.StoreHash(pKey)

	firstNode, targetNode := 0, 0

	for idx, node := range ring {
		if node.NodeID < ring[firstNode].NodeID {
			firstNode = idx
		}

		if node.NodeID >= tID && (node.NodeID < ring[targetNode].NodeID || ring[targetNode].NodeID < tID) {
			targetNode = idx
		}
	}
	//
	//	fmt.Println(ring)
	//	fmt.Println("TargetID:", tID)
	//	fmt.Println("firstNode:", ring[firstNode].NodeID)
	//	fmt.Println("targetNode:", ring[targetNode].NodeID)

	if ring[targetNode].NodeID < tID {
		return ring[firstNode]
	} else {
		return ring[targetNode]
	}
}
func (ss *storageServer) Delete(args *storagerpc.DeleteArgs, reply *storagerpc.DeleteReply) error {
	if DBG {
		fmt.Println("Entered storageserver delete")
	}
	if !ss.inRange(libstore.StoreHash(args.Key)) {
		reply.Status = storagerpc.WrongServer
		return nil
	}

	_, ok := ss.dataStore[args.Key]
	if !ok {
		reply.Status = storagerpc.KeyNotFound
		return nil
	}

	// Leasing check
	ss.leaseLock.Lock()
	pendingModifications, ok := ss.pendingMap[args.Key]

	if !ok {
		reply.Status = storagerpc.KeyNotFound
		ss.leaseLock.Unlock()
		return nil
	}

	pendingModifications.pending++
	leaseHolders, ok := ss.leaseStore[args.Key]
	ss.leaseLock.Unlock()

	if pendingModifications.pending > 1 { // Block until it's our turn to modify key
		response := make(chan int)
		pendingModifications.pendingCh <- response
		<-response
	}

	if ok {
		ss.revokeLeases(leaseHolders, args.Key)
	}

	ss.dataLock.Lock()
	delete(ss.dataStore, args.Key)
	ss.dataLock.Unlock()
	reply.Status = storagerpc.OK
	pendingModifications.pending--
Loop:
	for {
		select {
		case ch := <-pendingModifications.pendingCh:
			ch <- 1
			break Loop
		default:
			break Loop
		}
	}
	return nil
}
func correctServer(serv *storageServer, key string) bool {
	keyhash := int(libstore.StoreHash(key))
	id := serv.nodeIDs[0]
	for _, nodeID := range serv.nodeIDs {
		if keyhash <= nodeID {
			id = nodeID
			break
		}
	}
	return serv.nodeID == id
}
/* Check if the key is in this server's range */
func (ss *storageServer) IsKeyInRange(key string) bool {
	hashValue := libstore.StoreHash(key)
	var correctNodeID uint32
	correctNodeID = ss.nodes[0].NodeID
	for _, node := range ss.nodes {
		if node.NodeID >= hashValue {
			correctNodeID = node.NodeID
			break
		}
	}
	return correctNodeID == ss.nodeID
}
func (ss *storageServer) CheckKeyInRange(key string) bool {
	hashedValue := libstore.StoreHash(key)
	serverId := 0

	for i := 0; i < len(ss.nodesList); i++ {
		if i == len(ss.nodesList)-1 {
			serverId = 0
			break
		}
		if hashedValue > ss.nodesList[i].NodeID && hashedValue <= ss.nodesList[i+1].NodeID {
			serverId = i + 1
			break
		}
	}
	return ss.nodesList[serverId].NodeID == ss.nodeId
}
func (ss *storageServer) Put(args *storagerpc.PutArgs, reply *storagerpc.PutReply) error {
	if DBG {
		fmt.Println("Entered storage server put with key ", args.Key)
	}

	if !ss.inRange(libstore.StoreHash(args.Key)) {
		reply.Status = storagerpc.WrongServer
		return nil
	}

	// Leasing check
	ss.leaseLock.Lock()
	// If we have not seen this key before, initialize lease tracker
	_, ok := ss.pendingMap[args.Key]
	if !ok {
		ss.pendingMap[args.Key] = &TrackPending{pending: 0, pendingCh: make(chan chan int, 1)}
	}
	pendingModifications, _ := ss.pendingMap[args.Key]
	pendingModifications.pending++
	leaseHolders, ok := ss.leaseStore[args.Key]
	ss.leaseLock.Unlock()
	if pendingModifications.pending > 1 { // Block until it's our turn to modify key
		response := make(chan int)
		pendingModifications.pendingCh <- response
		<-response
	}
	if ok {
		ss.revokeLeases(leaseHolders, args.Key)
	}
	ss.dataLock.Lock()
	ss.dataStore[args.Key] = args.Value
	reply.Status = storagerpc.OK
	ss.dataLock.Unlock()
	pendingModifications.pending--
Loop:
	for {
		select {
		case ch := <-pendingModifications.pendingCh:
			ch <- 1
			break Loop
		default:
			break Loop
		}
	}
	return nil
}
func (ss *storageServer) getServerID(key string) uint32 {
	ss.serverMutex.Lock()
	defer ss.serverMutex.Unlock()
	hash := libstore.StoreHash(key)
	if ss.serverList.Len() <= 0 {
		fmt.Println("Fatal Error: servers lost", ss.serverList.Len())
		return 0
	}
	serverID := ss.serverList.Front().Value.(storagerpc.Node).NodeID
	for e := ss.serverList.Front(); e != nil; e = e.Next() {
		if hash <= e.Value.(storagerpc.Node).NodeID {
			serverID = e.Value.(storagerpc.Node).NodeID
			break
		}
	}
	return serverID
}
Exemple #10
0
func rightStorageServer(ss *storageServer, key string) bool {
	nextIndex := -1
	minIndex := -1
	hash := libstore.StoreHash(key)
	for i := 0; i < len(ss.servers); i++ {
		server := ss.servers[i]
		loc := server.NodeID
		if (loc >= hash) && ((nextIndex == -1) || (loc < ss.servers[nextIndex].NodeID)) {
			nextIndex = i
		}
		if (minIndex == -1) || (loc < ss.servers[minIndex].NodeID) {
			minIndex = i
		}
	}
	if nextIndex == -1 {
		nextIndex = minIndex
	}
	return ss.nodeID == ss.servers[nextIndex].NodeID
}
Exemple #11
0
func makeTribHash(tribValue string) string {
	return fmt.Sprintf("%d", libstore.StoreHash(tribValue))
}
func (ss *storageServer) RemoveFromList(args *storagerpc.PutArgs, reply *storagerpc.PutReply) error {
	if DBG {
		fmt.Println("Entered storageserver RemoveFromList")
	}

	if !ss.inRange(libstore.StoreHash(args.Key)) {
		reply.Status = storagerpc.WrongServer
		return nil
	}
	// Leasing check
	ss.leaseLock.Lock()
	pendingModifications, ok := ss.pendingMap[args.Key]
	// Initialize lease tracker if we haven't seen this key yet
	if !ok {
		reply.Status = storagerpc.KeyNotFound
		ss.leaseLock.Unlock()
		return nil
	}
	pendingModifications.pending++
	leaseHolders, ok := ss.leaseStore[args.Key]
	ss.leaseLock.Unlock()
	if pendingModifications.pending > 1 { // Block until it's our turn to modify key
		response := make(chan int)
		pendingModifications.pendingCh <- response
		<-response
	}
	if ok {
		ss.revokeLeases(leaseHolders, args.Key)
	}

	ss.dataLock.Lock()
	defer ss.dataLock.Unlock()
	val, ok := ss.dataStore[args.Key]
	if !ok {
		reply.Status = storagerpc.KeyNotFound
		return nil
	} else {
		listVal := val.(*list.List)
		for e := listVal.Front(); e != nil; e = e.Next() {
			if args.Value == e.Value.(string) {
				reply.Status = storagerpc.OK
				listVal.Remove(e)
				pendingModifications.pending--
			Loop1:
				for {
					select {
					case ch := <-pendingModifications.pendingCh:
						ch <- 1
						break Loop1
					default:
						break Loop1
					}
				}
				return nil
			}
		}
		reply.Status = storagerpc.ItemNotFound
		pendingModifications.pending--
	Loop:
		for {
			select {
			case ch := <-pendingModifications.pendingCh:
				ch <- 1
				break Loop
			default:
				break Loop
			}
		}
		return nil
	}
}
func (ss *storageServer) AppendToList(args *storagerpc.PutArgs, reply *storagerpc.PutReply) error {
	if DBG {
		fmt.Println("Entered storageserver AppendToList")
	}

	if !ss.inRange(libstore.StoreHash(args.Key)) {
		reply.Status = storagerpc.WrongServer
		return nil
	}

	// Leasing check
	ss.leaseLock.Lock()
	// If we have not seen this key before, initialize lease tracker
	_, ok := ss.pendingMap[args.Key]
	if !ok {
		ss.pendingMap[args.Key] = &TrackPending{pending: 0, pendingCh: make(chan chan int, 1)}
	}
	pendingModifications, _ := ss.pendingMap[args.Key]
	pendingModifications.pending++
	leaseHolders, ok := ss.leaseStore[args.Key]

	ss.leaseLock.Unlock()

	if pendingModifications.pending > 1 { // Block until it's our turn to modify key
		response := make(chan int)
		pendingModifications.pendingCh <- response
		<-response
	}
	if ok {
		ss.revokeLeases(leaseHolders, args.Key)
	}
	ss.dataLock.Lock()
	defer ss.dataLock.Unlock()
	val, ok := ss.dataStore[args.Key]
	if !ok { // Create a new list and add this element
		l := list.New()
		l.PushBack(args.Value)
		ss.dataStore[args.Key] = l
	} else {
		// Check if element is already in list
		listVal := val.(*list.List)
		for e := listVal.Front(); e != nil; e = e.Next() {
			if args.Value == e.Value.(string) {
				reply.Status = storagerpc.ItemExists
				pendingModifications.pending--
			Loop1:
				for {
					select {
					case ch := <-pendingModifications.pendingCh:
						ch <- 1
						break Loop1
					default:
						break Loop1
					}
				}
				return nil
			}
		}
		listVal.PushBack(args.Value)
	}
	reply.Status = storagerpc.OK
	pendingModifications.pending--
Loop:
	for {
		select {
		case ch := <-pendingModifications.pendingCh:
			ch <- 1
			break Loop
		default:
			break Loop
		}
	}
	return nil
}