diff --git a/src/shardkv1/kvsrv1/client.go b/src/shardkv1/kvsrv1/client.go deleted file mode 100644 index 73f1d29..0000000 --- a/src/shardkv1/kvsrv1/client.go +++ /dev/null @@ -1,56 +0,0 @@ -package kvsrv - -import ( - "6.5840/kvsrv1/rpc" - "6.5840/kvtest1" - "6.5840/tester1" -) - - -type Clerk struct { - clnt *tester.Clnt - server string -} - -func MakeClerk(clnt *tester.Clnt, server string) kvtest.IKVClerk { - ck := &Clerk{clnt: clnt, server: server} - // You may add code here. - 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 with code like this: -// ok := ck.clnt.Call(ck.server, "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) { - // You will have to modify this function. - return "", 0, rpc.ErrNoKey -} - -// 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 with code like this: -// ok := ck.clnt.Call(ck.server, "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, value string, version rpc.Tversion) rpc.Err { - // You will have to modify this function. - return rpc.ErrNoKey -} diff --git a/src/shardkv1/kvsrv1/kvsrv_test.go b/src/shardkv1/kvsrv1/kvsrv_test.go deleted file mode 100644 index 68c1c79..0000000 --- a/src/shardkv1/kvsrv1/kvsrv_test.go +++ /dev/null @@ -1,162 +0,0 @@ -package kvsrv - -import ( - // "log" - "runtime" - "testing" - "time" - - "6.5840/kvsrv1/rpc" - "6.5840/kvtest1" -) - -// Test Put with a single client and a reliable network -func TestReliablePut(t *testing.T) { - const Val = "6.5840" - const Ver = 0 - - ts := MakeTestKV(t, true) - defer ts.Cleanup() - - ts.Begin("One client and reliable Put") - - ck := ts.MakeClerk() - if err := ck.Put("k", Val, Ver); err != rpc.OK { - t.Fatalf("Put err %v", err) - } - - if val, ver, err := ck.Get("k"); err != rpc.OK { - t.Fatalf("Get err %v; expected OK", err) - } else if val != Val { - t.Fatalf("Get value err %v; expected %v", val, Val) - } else if ver != Ver+1 { - t.Fatalf("Get wrong version %v; expected %v", ver, Ver+1) - } - - if err := ck.Put("k", Val, 0); err != rpc.ErrVersion { - t.Fatalf("expected Put to fail with ErrVersion; got err=%v", err) - } - - if err := ck.Put("y", Val, rpc.Tversion(1)); err != rpc.ErrNoKey { - t.Fatalf("expected Put to fail with ErrNoKey; got err=%v", err) - } - - if _, _, err := ck.Get("y"); err != rpc.ErrNoKey { - t.Fatalf("expected Get to fail with ErrNoKey; got err=%v", err) - } -} - -// Many clients putting on same key. -func TestPutConcurrentReliable(t *testing.T) { - const ( - PORCUPINETIME = 10 * time.Second - NCLNT = 10 - NSEC = 1 - ) - - ts := MakeTestKV(t, true) - defer ts.Cleanup() - - ts.Begin("Test: many clients racing to put values to the same key") - - rs := ts.SpawnClientsAndWait(NCLNT, NSEC*time.Second, func(me int, ck kvtest.IKVClerk, done chan struct{}) kvtest.ClntRes { - return ts.OneClientPut(me, ck, []string{"k"}, done) - }) - ck := ts.MakeClerk() - ts.CheckPutConcurrent(ck, "k", rs, &kvtest.ClntRes{}) - ts.CheckPorcupineT(PORCUPINETIME) -} - -// Check if memory used on server is reasonable -func TestMemPutManyClientsReliable(t *testing.T) { - const ( - NCLIENT = 100_000 - MEM = 1000 - ) - - ts := MakeTestKV(t, true) - defer ts.Cleanup() - - v := kvtest.RandValue(MEM) - - cks := make([]kvtest.IKVClerk, NCLIENT) - for i, _ := range cks { - cks[i] = ts.MakeClerk() - } - - // force allocation of ends for server in each client - for i := 0; i < NCLIENT; i++ { - if err := cks[i].Put("k", "", 1); err != rpc.ErrNoKey { - t.Fatalf("Put failed %v", err) - } - } - - ts.Begin("Test: memory use many put clients") - - // allow threads started by labrpc to start - time.Sleep(1 * time.Second) - - runtime.GC() - runtime.GC() - - var st runtime.MemStats - runtime.ReadMemStats(&st) - m0 := st.HeapAlloc - - for i := 0; i < NCLIENT; i++ { - if err := cks[i].Put("k", v, rpc.Tversion(i)); err != rpc.OK { - t.Fatalf("Put failed %v", err) - } - } - - runtime.GC() - time.Sleep(1 * time.Second) - runtime.GC() - - runtime.ReadMemStats(&st) - m1 := st.HeapAlloc - f := (float64(m1) - float64(m0)) / NCLIENT - if m1 > m0+(NCLIENT*200) { - t.Fatalf("error: server using too much memory %d %d (%.2f per client)\n", m0, m1, f) - } -} - -// Test with one client and unreliable network. If Clerk.Put returns -// ErrMaybe, the Put must have happened, since the test uses only one -// client. -func TestUnreliableNet(t *testing.T) { - const NTRY = 100 - - ts := MakeTestKV(t, false) - defer ts.Cleanup() - - ts.Begin("One client") - - ck := ts.MakeClerk() - - retried := false - for try := 0; try < NTRY; try++ { - for i := 0; true; i++ { - if err := ts.PutJson(ck, "k", i, rpc.Tversion(try), 0); err != rpc.ErrMaybe { - if i > 0 && err != rpc.ErrVersion { - t.Fatalf("Put shouldn't have happen more than once %v", err) - } - break - } - // Try put again; it should fail with ErrVersion - retried = true - } - v := 0 - if ver := ts.GetJson(ck, "k", 0, &v); ver != rpc.Tversion(try+1) { - t.Fatalf("Wrong version %d expect %d", ver, try+1) - } - if v != 0 { - t.Fatalf("Wrong value %d expect %d", v, 0) - } - } - if !retried { - t.Fatalf("Clerk.Put never returned ErrMaybe") - } - - ts.CheckPorcupine() -} diff --git a/src/shardkv1/kvsrv1/lock/lock.go b/src/shardkv1/kvsrv1/lock/lock.go deleted file mode 100644 index f788304..0000000 --- a/src/shardkv1/kvsrv1/lock/lock.go +++ /dev/null @@ -1,31 +0,0 @@ -package lock - -import ( - - "6.5840/kvsrv1/rpc" - "6.5840/shardkv1/kvsrv1" - "6.5840/shardkv1/shardctrler/param" -) - - -type Lock struct { - ck *kvsrv.Clerk - -} - -// Use l as the key to store the "lock state" (you would have to decide -// precisely what the lock state is). -func MakeLock(ck kvtest.IKVClerk, l string) *Lock { - lk := &Lock{ck: ck.(*kvsrv.Clerk)} - // You may add code here - return lk -} - - -func (lk *Lock) Acquire() { - // You may add code here. -} - -func (lk *Lock) Release() { - // You may add code here. -} diff --git a/src/shardkv1/kvsrv1/lock/lock_test.go b/src/shardkv1/kvsrv1/lock/lock_test.go deleted file mode 100644 index 92c9e67..0000000 --- a/src/shardkv1/kvsrv1/lock/lock_test.go +++ /dev/null @@ -1,89 +0,0 @@ -package lock - -import ( - "fmt" - // "log" - "strconv" - "testing" - "time" - - "6.5840/kvsrv1" - "6.5840/kvsrv1/rpc" - "6.5840/kvtest1" -) - -const ( - NACQUIRE = 10 - NCLNT = 10 - NSEC = 2 -) - -func oneClient(t *testing.T, me int, ck kvtest.IKVClerk, done chan struct{}) kvtest.ClntRes { - lk := MakeLock(ck, "l") - ck.Put("l0", "", 0) - for i := 1; true; i++ { - select { - case <-done: - return kvtest.ClntRes{i, 0} - default: - lk.Acquire() - - // log.Printf("%d: acquired lock", me) - - b := strconv.Itoa(me) - val, ver, err := ck.Get("l0") - if err == rpc.OK { - if val != "" { - t.Fatalf("%d: two clients acquired lock %v", me, val) - } - } else { - t.Fatalf("%d: get failed %v", me, err) - } - - err = ck.Put("l0", string(b), ver) - if !(err == rpc.OK || err == rpc.ErrMaybe) { - t.Fatalf("%d: put failed %v", me, err) - } - - time.Sleep(10 * time.Millisecond) - - err = ck.Put("l0", "", ver+1) - if !(err == rpc.OK || err == rpc.ErrMaybe) { - t.Fatalf("%d: put failed %v", me, err) - } - - // log.Printf("%d: release lock", me) - - lk.Release() - } - } - return kvtest.ClntRes{} -} - -// Run test clients -func runClients(t *testing.T, nclnt int, reliable bool) { - ts := kvsrv.MakeTestKV(t, reliable) - defer ts.Cleanup() - - ts.Begin(fmt.Sprintf("Test: %d lock clients", nclnt)) - - ts.SpawnClientsAndWait(nclnt, NSEC*time.Second, func(me int, myck kvtest.IKVClerk, done chan struct{}) kvtest.ClntRes { - return oneClient(t, me, myck, done) - }) -} - -func TestOneClientReliable(t *testing.T) { - runClients(t, 1, true) -} - -func TestManyClientsReliable(t *testing.T) { - runClients(t, NCLNT, true) -} - -func TestOneClientUnreliable(t *testing.T) { - runClients(t, 1, false) -} - -func TestManyClientsUnreliable(t *testing.T) { - runClients(t, NCLNT, false) -} diff --git a/src/shardkv1/kvsrv1/server.go b/src/shardkv1/kvsrv1/server.go deleted file mode 100644 index 83c256a..0000000 --- a/src/shardkv1/kvsrv1/server.go +++ /dev/null @@ -1,48 +0,0 @@ -package kvsrv - -import ( - "sync" - - - "6.5840/kvsrv1/rpc" - "6.5840/labrpc" - "6.5840/tester1" -) - - -type KVServer struct { - mu sync.Mutex - - // Your definitions here. -} - -func MakeKVServer() *KVServer { - kv := &KVServer{} - // Your code here. - return kv -} - -// Get returns the value and version for args.Key, if args.Key -// exists. Otherwise, Get returns ErrNoKey. -func (kv *KVServer) Get(args *rpc.GetArgs, reply *rpc.GetReply) { - // Your code here. -} - -// Update the value for a key if args.Version matches the version of -// the key on the server. If versions don't match, return ErrVersion. -// If the key doesn't exist, Put installs the value if the -// args.Version is 0, and returns ErrNoKey otherwise. -func (kv *KVServer) Put(args *rpc.PutArgs, reply *rpc.PutReply) { - // Your code here. -} - -// You can ignore Kill() for this lab -func (kv *KVServer) Kill() { -} - - -// You can ignore all arguments; they are for replicated KVservers -func StartKVServer(ends []*labrpc.ClientEnd, gid tester.Tgid, srv int, persister *tester.Persister) []tester.IService { - kv := MakeKVServer() - return []tester.IService{kv} -} diff --git a/src/shardkv1/kvsrv1/test.go b/src/shardkv1/kvsrv1/test.go deleted file mode 100644 index bd8269b..0000000 --- a/src/shardkv1/kvsrv1/test.go +++ /dev/null @@ -1,36 +0,0 @@ -package kvsrv - -import ( - // "log" - "testing" - - "6.5840/kvtest1" - "6.5840/tester1" -) - -type TestKV struct { - *kvtest.Test - t *testing.T - reliable bool -} - -func MakeTestKV(t *testing.T, reliable bool) *TestKV { - cfg := tester.MakeConfig(t, 1, reliable, StartKVServer) - ts := &TestKV{ - t: t, - reliable: reliable, - } - ts.Test = kvtest.MakeTest(t, cfg, false, ts) - return ts -} - -func (ts *TestKV) MakeClerk() kvtest.IKVClerk { - clnt := ts.Config.MakeClient() - ck := MakeClerk(clnt, tester.ServerName(tester.GRP0, 0)) - return &kvtest.TestClerk{ck, clnt} -} - -func (ts *TestKV) DeleteClerk(ck kvtest.IKVClerk) { - tck := ck.(*kvtest.TestClerk) - ts.DeleteClient(tck.Clnt) -}