Skip to content

Commit

Permalink
add lab4
Browse files Browse the repository at this point in the history
  • Loading branch information
zhf committed Nov 22, 2012
1 parent b01acd8 commit 9188d86
Show file tree
Hide file tree
Showing 14 changed files with 382 additions and 9 deletions.
2 changes: 1 addition & 1 deletion GNUmakefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
LAB=3
LAB=4
SOL=0
RPC=./rpc
LAB2GE=$(shell expr $(LAB) \>\= 2)
Expand Down
109 changes: 109 additions & 0 deletions handle.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
#include "handle.h"
#include <stdio.h>
#include "tprintf.h"

handle_mgr mgr;

handle::handle(std::string m)
{
h = mgr.get_handle(m);
}

rpcc *
handle::safebind()
{
if (!h)
return NULL;
ScopedLock ml(&h->cl_mutex);
if (h->del)
return NULL;
if (h->cl)
return h->cl;
sockaddr_in dstsock;
make_sockaddr(h->m.c_str(), &dstsock);
rpcc *cl = new rpcc(dstsock);
tprintf("handler_mgr::get_handle trying to bind...%s\n", h->m.c_str());
int ret;
// handle class has to tolerate lossy network, since we may test
// students' lab with RPC_LOSSY=5 from lab 1 to lab 5
ret = cl->bind();
if (ret < 0) {
tprintf("handle_mgr::get_handle bind failure! %s %d\n", h->m.c_str(), ret);
delete cl;
h->del = true;
} else {
tprintf("handle_mgr::get_handle bind succeeded %s\n", h->m.c_str());
h->cl = cl;
}
return h->cl;
}

handle::~handle()
{
if (h) mgr.done_handle(h);
}

handle_mgr::handle_mgr()
{
VERIFY (pthread_mutex_init(&handle_mutex, NULL) == 0);
}

struct hinfo *
handle_mgr::get_handle(std::string m)
{
ScopedLock ml(&handle_mutex);
struct hinfo *h = 0;
if (hmap.find(m) == hmap.end()) {
h = new hinfo;
h->cl = NULL;
h->del = false;
h->refcnt = 1;
h->m = m;
pthread_mutex_init(&h->cl_mutex, NULL);
hmap[m] = h;
} else if (!hmap[m]->del) {
h = hmap[m];
h->refcnt ++;
}
return h;
}

void
handle_mgr::done_handle(struct hinfo *h)
{
ScopedLock ml(&handle_mutex);
h->refcnt--;
if (h->refcnt == 0 && h->del)
delete_handle_wo(h->m);
}

void
handle_mgr::delete_handle(std::string m)
{
ScopedLock ml(&handle_mutex);
delete_handle_wo(m);
}

// Must be called with handle_mutex locked.
void
handle_mgr::delete_handle_wo(std::string m)
{
if (hmap.find(m) == hmap.end()) {
tprintf("handle_mgr::delete_handle_wo: cl %s isn't in cl list\n", m.c_str());
} else {
tprintf("handle_mgr::delete_handle_wo: cl %s refcnt %d\n", m.c_str(),
hmap[m]->refcnt);
struct hinfo *h = hmap[m];
if (h->refcnt == 0) {
if (h->cl) {
h->cl->cancel();
delete h->cl;
}
pthread_mutex_destroy(&h->cl_mutex);
hmap.erase(m);
delete h;
} else {
h->del = true;
}
}
}
79 changes: 79 additions & 0 deletions handle.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
// manage a cache of RPC connections.
// assuming cid is a std::string holding the
// host:port of the RPC server you want
// to talk to:
//
// handle h(cid);
// rpcc *cl = h.safebind();
// if(cl){
// ret = cl->call(...);
// } else {
// bind() failed
// }
//
// if the calling program has not contacted
// cid before, safebind() will create a new
// connection, call bind(), and return
// an rpcc*, or 0 if bind() failed. if the
// program has previously contacted cid,
// safebind() just returns the previously
// created rpcc*. best not to hold any
// mutexes while calling safebind().

#ifndef handle_h
#define handle_h

#include <string>
#include <vector>
#include "rpc.h"

struct hinfo {
rpcc *cl;
int refcnt;
bool del;
std::string m;
pthread_mutex_t cl_mutex;
};

class handle {
private:
struct hinfo *h;
public:
handle(std::string m);
~handle();
/* safebind will try to bind with the rpc server on the first call.
* Since bind may block, the caller probably should not hold a mutex
* when calling safebind.
*
* return:
* if the first safebind succeeded, all later calls would return
* a rpcc object; otherwise, all later calls would return NULL.
*
* Example:
* handle h(dst);
* XXX_protocol::status ret;
* if (h.safebind()) {
* ret = h.safebind()->call(...);
* }
* if (!h.safebind() || ret != XXX_protocol::OK) {
* // handle failure
* }
*/
rpcc *safebind();
};

class handle_mgr {
private:
pthread_mutex_t handle_mutex;
std::map<std::string, struct hinfo *> hmap;
public:
handle_mgr();
struct hinfo *get_handle(std::string m);
void done_handle(struct hinfo *h);
void delete_handle(std::string m);
void delete_handle_wo(std::string m);
};

extern class handle_mgr mgr;

#endif
58 changes: 58 additions & 0 deletions lock_client_cache.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
// RPC stubs for clients to talk to lock_server, and cache the locks
// see lock_client.cache.h for protocol details.

#include "lock_client_cache.h"
#include "rpc.h"
#include <sstream>
#include <iostream>
#include <stdio.h>
#include "tprintf.h"


lock_client_cache::lock_client_cache(std::string xdst,
class lock_release_user *_lu)
: lock_client(xdst), lu(_lu)
{
rpcs *rlsrpc = new rpcs(0);
rlsrpc->reg(rlock_protocol::revoke, this, &lock_client_cache::revoke_handler);
rlsrpc->reg(rlock_protocol::retry, this, &lock_client_cache::retry_handler);

const char *hname;
hname = "127.0.0.1";
std::ostringstream host;
host << hname << ":" << rlsrpc->port();
id = host.str();
}

lock_protocol::status
lock_client_cache::acquire(lock_protocol::lockid_t lid)
{
int ret = lock_protocol::OK;
return lock_protocol::OK;
}

lock_protocol::status
lock_client_cache::release(lock_protocol::lockid_t lid)
{
return lock_protocol::OK;

}

rlock_protocol::status
lock_client_cache::revoke_handler(lock_protocol::lockid_t lid,
int &)
{
int ret = rlock_protocol::OK;
return ret;
}

rlock_protocol::status
lock_client_cache::retry_handler(lock_protocol::lockid_t lid,
int &)
{
int ret = rlock_protocol::OK;
return ret;
}



40 changes: 40 additions & 0 deletions lock_client_cache.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// lock client interface.

#ifndef lock_client_cache_h

#define lock_client_cache_h

#include <string>
#include "lock_protocol.h"
#include "rpc.h"
#include "lock_client.h"
#include "lang/verify.h"

// Classes that inherit lock_release_user can override dorelease so that
// that they will be called when lock_client releases a lock.
// You will not need to do anything with this class until Lab 5.
class lock_release_user {
public:
virtual void dorelease(lock_protocol::lockid_t) = 0;
virtual ~lock_release_user() {};
};

class lock_client_cache : public lock_client {
private:
class lock_release_user *lu;
int rlock_port;
std::string hostname;
std::string id;
public:
lock_client_cache(std::string xdst, class lock_release_user *l = 0);
virtual ~lock_client_cache() {};
lock_protocol::status acquire(lock_protocol::lockid_t);
lock_protocol::status release(lock_protocol::lockid_t);
rlock_protocol::status revoke_handler(lock_protocol::lockid_t,
int &);
rlock_protocol::status retry_handler(lock_protocol::lockid_t,
int &);
};


#endif
10 changes: 10 additions & 0 deletions lock_protocol.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,21 @@ class lock_protocol {
enum xxstatus { OK, RETRY, RPCERR, NOENT, IOERR };
typedef int status;
typedef unsigned long long lockid_t;
typedef unsigned long long xid_t;
enum rpc_numbers {
acquire = 0x7001,
release,
stat
};
};

class rlock_protocol {
public:
enum xxstatus { OK, RPCERR };
typedef int status;
enum rpc_numbers {
revoke = 0x8001,
retry = 0x8002
};
};
#endif
40 changes: 40 additions & 0 deletions lock_server_cache.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// the caching lock server implementation

#include "lock_server_cache.h"
#include <sstream>
#include <stdio.h>
#include <unistd.h>
#include <arpa/inet.h>
#include "lang/verify.h"
#include "handle.h"
#include "tprintf.h"


lock_server_cache::lock_server_cache()
{
}


int lock_server_cache::acquire(lock_protocol::lockid_t lid, std::string id,
int &)
{
lock_protocol::status ret = lock_protocol::OK;
return ret;
}

int
lock_server_cache::release(lock_protocol::lockid_t lid, std::string id,
int &r)
{
lock_protocol::status ret = lock_protocol::OK;
return ret;
}

lock_protocol::status
lock_server_cache::stat(lock_protocol::lockid_t lid, int &r)
{
tprintf("stat request\n");
r = nacquire;
return lock_protocol::OK;
}

22 changes: 22 additions & 0 deletions lock_server_cache.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#ifndef lock_server_cache_h
#define lock_server_cache_h

#include <string>

#include <map>
#include "lock_protocol.h"
#include "rpc.h"
#include "lock_server.h"


class lock_server_cache {
private:
int nacquire;
public:
lock_server_cache();
lock_protocol::status stat(lock_protocol::lockid_t, int &);
int acquire(lock_protocol::lockid_t, std::string id, int &);
int release(lock_protocol::lockid_t, std::string id, int &);
};

#endif
2 changes: 1 addition & 1 deletion lock_smain.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
#include <arpa/inet.h>
#include <stdlib.h>
#include <stdio.h>
#include "lock_server.h"
#include "lock_server_cache.h"

#include "jsl_log.h"

Expand Down
Loading

0 comments on commit 9188d86

Please sign in to comment.