This commit is contained in:
Yun-Sheng Chang 2025-03-11 18:59:22 -04:00
parent fc8b51698c
commit a1610fb282
7 changed files with 48 additions and 10 deletions

View File

@ -19,12 +19,39 @@ func MakeClerk(clnt *tester.Clnt, servers []string) kvtest.IKVClerk {
return ck return ck
} }
// Get fetches the current value and version for a key. It returns
// ErrNoKey if the key does not exist. It keeps trying forever in the
// face of all other errors.
//
// You can send an RPC to server i with code like this:
// ok := ck.clnt.Call(ck.servers[i], "KVServer.Get", &args, &reply)
//
// The types of args and reply (including whether they are pointers)
// must match the declared types of the RPC handler function's
// arguments. Additionally, reply must be passed as a pointer.
func (ck *Clerk) Get(key string) (string, rpc.Tversion, rpc.Err) { func (ck *Clerk) Get(key string) (string, rpc.Tversion, rpc.Err) {
// You will have to modify this function. // You will have to modify this function.
return "", 0, "" return "", 0, ""
} }
// Put updates key with value only if the version in the
// request matches the version of the key at the server. If the
// versions numbers don't match, the server should return
// ErrVersion. If Put receives an ErrVersion on its first RPC, Put
// should return ErrVersion, since the Put was definitely not
// performed at the server. If the server returns ErrVersion on a
// resend RPC, then Put must return ErrMaybe to the application, since
// its earlier RPC might have been processed by the server successfully
// but the response was lost, and the the Clerk doesn't know if
// the Put was performed or not.
//
// You can send an RPC to server i with code like this:
// ok := ck.clnt.Call(ck.servers[i], "KVServer.Put", &args, &reply)
//
// The types of args and reply (including whether they are pointers)
// must match the declared types of the RPC handler function's
// arguments. Additionally, reply must be passed as a pointer.
func (ck *Clerk) Put(key string, value string, version rpc.Tversion) rpc.Err { func (ck *Clerk) Put(key string, value string, version rpc.Tversion) rpc.Err {
// You will have to modify this function. // You will have to modify this function.
return "" return ""

Binary file not shown.

View File

@ -46,7 +46,9 @@ type RSM struct {
// servers[] contains the ports of the set of // servers[] contains the ports of the set of
// servers that will cooperate via Raft to // servers that will cooperate via Raft to
// form the fault-tolerant key/value service. // form the fault-tolerant key/value service.
//
// me is the index of the current server in servers[]. // me is the index of the current server in servers[].
//
// the k/v server should store snapshots through the underlying Raft // the k/v server should store snapshots through the underlying Raft
// implementation, which should call persister.SaveStateAndSnapshot() to // implementation, which should call persister.SaveStateAndSnapshot() to
// atomically save the Raft state along with the snapshot. // atomically save the Raft state along with the snapshot.

Binary file not shown.

View File

@ -19,6 +19,11 @@ type KVServer struct {
// Your definitions here. // Your definitions here.
} }
// To type-cast req to the right type, take a look at Go's type switches or type
// assertions below:
//
// https://go.dev/tour/methods/16
// https://go.dev/tour/methods/15
func (kv *KVServer) DoOp(req any) any { func (kv *KVServer) DoOp(req any) any {
// Your code here // Your code here
return nil return nil

View File

@ -150,19 +150,19 @@ func (sg *ServerGrp) cleanup() {
} }
} }
// attach server i to servers listed in to // attach server i to servers listed in to caller must hold cfg.mu.
// caller must hold cfg.mu
func (sg *ServerGrp) connect(i int, to []int) { func (sg *ServerGrp) connect(i int, to []int) {
//log.Printf("connect peer %d to %v\n", i, to) //log.Printf("connect peer %d to %v\n", i, to)
sg.connected[i] = true sg.connected[i] = true
// outgoing socket files // connect outgoing end points
sg.srvs[i].connect(to) sg.srvs[i].connect(sg, to)
// incoming socket files // connect incoming end points to me
for j := 0; j < len(to); j++ { for j := 0; j < len(to); j++ {
if sg.IsConnected(j) { if sg.IsConnected(to[j]) {
//log.Printf("connect %d (%v) to %d", to[j], sg.srvs[to[j]].endNames[i], i)
endname := sg.srvs[to[j]].endNames[i] endname := sg.srvs[to[j]].endNames[i]
sg.net.Enable(endname, true) sg.net.Enable(endname, true)
} }

View File

@ -1,7 +1,7 @@
package tester package tester
import ( import (
// "log" //"log"
"sync" "sync"
"6.5840/labrpc" "6.5840/labrpc"
@ -46,13 +46,17 @@ func (s *Server) startServer(gid Tgid) *Server {
return srv return srv
} }
func (s *Server) connect(to []int) { // connect s to servers listed in to
func (s *Server) connect(sg *ServerGrp, to []int) {
s.mu.Lock() s.mu.Lock()
defer s.mu.Unlock() defer s.mu.Unlock()
for j := 0; j < len(to); j++ { for j := 0; j < len(to); j++ {
if sg.IsConnected(to[j]) {
//log.Printf("connect %d to %d (%v)", s.id, to[j], s.endNames[to[j]])
endname := s.endNames[to[j]] endname := s.endNames[to[j]]
s.net.Enable(endname, true) s.net.Enable(endname, true)
} }
}
} }
func (s *Server) disconnect(from []int) { func (s *Server) disconnect(from []int) {