github.com/DARA-Project/GoDist-Scheduler@v0.0.0-20201030134746-668de4acea0d/structured/rsm/kvlib/kvlib.go (about) 1 package kvlib 2 3 import ( 4 "net/rpc" 5 "errors" 6 "time" 7 "sync" 8 ) 9 10 // args in get(args) 11 type GetArgs struct { 12 Key string // key to look up 13 Clientid uint8 // client id issuing this get 14 Clock uint64 // value of lamport clock at the issuing client 15 } 16 17 // args in put(args) 18 type PutArgs struct { 19 Key string // key to associate value with 20 Val string // value 21 Clientid uint8 // client id issueing this put 22 Clock uint64 // value of lamport clock at the issuing client 23 } 24 25 // args in clockupdate(args) 26 type ClockUpdateArgs struct { 27 Clientid uint8 // client id issueing this put 28 Clock uint64 // value of lamport clock at the issuing client 29 } 30 31 // args in disconnect(args) 32 type DisconnectArgs struct { 33 Clientid uint8 // client id issueing this put 34 } 35 36 // Reply from service for all the API calls above. 37 type ValReply struct { 38 Val string // value; depends on the call 39 } 40 41 type KVService struct { 42 Clientid uint8 43 ClockUpdateRate uint8 44 Clock uint64 45 Replicas []*rpc.Client 46 Mux sync.Mutex 47 } 48 49 func (kv *KVService) Get(key string) (string, error) { 50 var err error 51 kv.Mux.Lock() 52 kv.Clock += 1 53 args := GetArgs{key, kv.Clientid, kv.Clock} 54 kv.Mux.Unlock() 55 var reply ValReply 56 for _, c := range kv.Replicas { 57 err = c.Call("KeyValService.Get", &args, &reply) 58 if err == nil { 59 return reply.Val, nil 60 } 61 } 62 return reply.Val, err 63 } 64 65 func (kv *KVService) Put(key string, val string) error { 66 var err error 67 kv.Mux.Lock() 68 kv.Clock += 1 69 putArgs := PutArgs{key, val, kv.Clientid, kv.Clock} 70 kv.Mux.Unlock() 71 var reply ValReply 72 num_errors := 0 73 for _, c := range kv.Replicas { 74 err = c.Call("KeyValService.Put", &putArgs, &reply) 75 if err != nil { 76 num_errors += 1 77 } 78 } 79 if num_errors == len(kv.Replicas) { 80 return errors.New("All replicas failed.") 81 } 82 return nil 83 } 84 85 func (kv *KVService) Disconnect() error { 86 var err error 87 kv.Mux.Lock() 88 kv.Clock += 1 89 kv.Mux.Unlock() 90 dcArgs := DisconnectArgs{kv.Clientid} 91 var reply ValReply 92 for _, c := range kv.Replicas { 93 err = c.Call("KeyValService.Disconnect", &dcArgs, &reply) 94 } 95 return err 96 } 97 98 func (kv *KVService) clockUpdate() { 99 ticker := time.NewTicker(time.Duration(kv.ClockUpdateRate) * time.Millisecond) 100 for { 101 select { 102 case <- ticker.C: 103 kv.Mux.Lock() 104 kv.Clock += 1 105 kv.Mux.Unlock() 106 args := ClockUpdateArgs{kv.Clientid, kv.Clock} 107 var reply ValReply 108 for _, c := range kv.Replicas { 109 c.Call("KeyValService.ClockUpdate", &args, &reply) 110 } 111 } 112 } 113 } 114 115 func Init(id uint8, updateRate uint8, addresses []string) (*KVService, error) { 116 clients := []*rpc.Client{} 117 for _, s := range addresses { 118 client, err := rpc.Dial("tcp", s) 119 if err != nil { 120 return nil, err 121 } 122 clients = append(clients, client) 123 } 124 kvService := &KVService{Clientid : id, ClockUpdateRate : updateRate, Clock : 0, Replicas : clients} 125 go kvService.clockUpdate() 126 return kvService, nil 127 }