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 }
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 }
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 }