Commit 676c5dba authored by Anjo Vahldiek's avatar Anjo Vahldiek
Browse files

lab2

parent cd5cae17
LAB=1
SOL=1
LAB=2
SOL=0
RPC=./rpc
LAB2GE=$(shell expr $(LAB) \>\= 2)
LAB4GE=$(shell expr $(LAB) \>\= 4)
......@@ -15,17 +15,24 @@ else
MACFLAGS=
endif
LDFLAGS = -L. -L/usr/local/lib
LDLIBS = -lpthread
ifeq ($(LAB2GE),1)
LDLIBS = -lfuse -lpthread
ifeq ($(shell uname -s),Darwin)
ifeq ($(shell sw_vers -productVersion | sed -e "s/.*\(10\.[0-9]\).*/\1/"),10.6)
LDLIBS += -lfuse_ino64
else
LDLIBS = -lpthread
LDLIBS += -lfuse
endif
else
LDLIBS += -lfuse
endif
endif
LDLIBS += $(shell test -f `gcc -print-file-name=librt.so` && echo -lrt)
LDLIBS += $(shell test -f `gcc -print-file-name=libdl.so` && echo -ldl)
CC = g++
CXX = g++
lab: lab1
lab: lab2
lab1: rpc/rpctest lock_server lock_tester lock_demo
lab2: yfs_client extent_server
lab3: yfs_client extent_server
......@@ -111,15 +118,15 @@ l1-sol:
$(lock_demo) $(lock_tester) $(hfiles1)
l2:
./mklab.pl 2 0 l2 GNUmakefile $(yfs_client) $(extent_server) start.sh\
stop.sh test-lab-2.pl mkfs.sh $(hfiles2)
./mklab.pl 2 0 l2 GNUmakefile $(rpclib) $(yfs_client) $(extent_server) $(lock_server) start.sh\
stop.sh test-lab-2.pl mkfs.sh $(hfiles2) $(hfiles1)
l2-sol:
./mklab.pl 2 2 l2-sol GNUmakefile $(yfs_client) $(extent_server) $(rpclib) $(lock_server) start.sh\
stop.sh test-lab-2.pl mkfs.sh $(hfiles2) $(hfiles1)
l3:
./mklab.pl 3 0 l3 GNUmakefile $(yfs_client) $(extent_server) start.sh\
./mklab.pl 3 0 l3 GNUmakefile $(rpclib) $(yfs_client) $(extent_server) start.sh\
stop.sh test-lab-2.pl mkfs.sh $(hfiles2) test-lab-3.pl
l3-sol:
......@@ -127,7 +134,7 @@ l3-sol:
stop.sh test-lab-2.pl mkfs.sh $(hfiles2) $(hfiles1) test-lab-3.pl
l4:
./mklab.pl 4 0 l4 GNUmakefile test-lab-4-a.pl $(yfs_client)\
./mklab.pl 4 0 l4 GNUmakefile test-lab-4-a.pl $(rpclib) $(yfs_client)\
$(extent_server) start.sh stop.sh test-lab-2.pl mkfs.sh\
$(hfiles2) $(test-lab-4-b) $(test-lab-4-c)
......@@ -137,7 +144,7 @@ l4-sol:
$(lock_demo) $(lock_tester) $(hfiles1) $(hfiles2) $(test-lab-4-b) $(test-lab-4-c)
l5:
./mklab.pl 5 0 l5 GNUmakefile test-lab-4-a.pl $(yfs_client)\
./mklab.pl 5 0 l5 GNUmakefile test-lab-4-a.pl $(rpclib) $(yfs_client)\
$(extent_server) $(lock_server) start.sh stop.sh test-lab-2.pl \
mkfs.sh $(hfiles1) $(hfiles2) $(hfiles3) $(lock_tester) \
$(test-lab-4-b) $(test-lab-4-c)
......@@ -150,7 +157,7 @@ l5-sol:
l6:
./mklab.pl 6 0 l6 GNUmakefile test-lab-4-a.pl $(yfs_client)\
./mklab.pl 6 0 l6 GNUmakefile test-lab-4-a.pl $(rpclib) $(yfs_client)\
$(extent_server) start.sh stop.sh test-lab-2.pl mkfs.sh\
$(hfiles2) $(test-lab-4-b) $(test-lab-4-c)
......@@ -161,7 +168,7 @@ l6-sol:
l7:
./mklab.pl 7 0 l7 GNUmakefile rsm_tester.pl $(rsm_files) $(hfiles4) lock_smain.cc
./mklab.pl 7 0 l7 GNUmakefile rsm_tester.pl $(rpclib) $(rsm_files) $(hfiles4) lock_smain.cc
l7-sol:
./mklab.pl 7 7 l7-sol GNUmakefile test-lab-4-a.pl $(yfs_client) $(rpclib) $(rpctest) $(lock_server) \
......@@ -170,7 +177,7 @@ l7-sol:
rsm_tester.pl $(rsm_files) $(hfiles4)
l8:
./mklab.pl 8 0 l8 GNUmakefile rsm_client.cc $(hfiles5) rsm.cc rsm.h
./mklab.pl 8 0 l8 GNUmakefile rsm_client.cc $(rpclib) $(hfiles5) rsm.cc rsm.h
l8-sol:
./mklab.pl 8 8 l8-sol GNUmakefile test-lab-4-a.pl $(yfs_client) $(rpclib) $(rpctest) $(lock_server) \
......
// RPC stubs for clients to talk to extent_server
#include "extent_client.h"
#include <sstream>
#include <iostream>
#include <stdio.h>
#include <unistd.h>
#include <time.h>
// The calls assume that the caller holds a lock on the extent
extent_client::extent_client(std::string dst)
{
sockaddr_in dstsock;
make_sockaddr(dst.c_str(), &dstsock);
cl = new rpcc(dstsock);
if (cl->bind() != 0) {
printf("extent_client: bind failed\n");
}
}
extent_protocol::status
extent_client::get(extent_protocol::extentid_t eid, std::string &buf)
{
extent_protocol::status ret = extent_protocol::OK;
ret = cl->call(extent_protocol::get, eid, buf);
return ret;
}
extent_protocol::status
extent_client::getattr(extent_protocol::extentid_t eid,
extent_protocol::attr &attr)
{
extent_protocol::status ret = extent_protocol::OK;
ret = cl->call(extent_protocol::getattr, eid, attr);
return ret;
}
extent_protocol::status
extent_client::put(extent_protocol::extentid_t eid, std::string buf)
{
extent_protocol::status ret = extent_protocol::OK;
int r;
ret = cl->call(extent_protocol::put, eid, buf, r);
return ret;
}
extent_protocol::status
extent_client::remove(extent_protocol::extentid_t eid)
{
extent_protocol::status ret = extent_protocol::OK;
int r;
ret = cl->call(extent_protocol::remove, eid, r);
return ret;
}
// extent client interface.
#ifndef extent_client_h
#define extent_client_h
#include <string>
#include "extent_protocol.h"
#include "rpc.h"
class extent_client {
private:
rpcc *cl;
public:
extent_client(std::string dst);
extent_protocol::status get(extent_protocol::extentid_t eid,
std::string &buf);
extent_protocol::status getattr(extent_protocol::extentid_t eid,
extent_protocol::attr &a);
extent_protocol::status put(extent_protocol::extentid_t eid, std::string buf);
extent_protocol::status remove(extent_protocol::extentid_t eid);
};
#endif
// extent wire protocol
#ifndef extent_protocol_h
#define extent_protocol_h
#include "rpc.h"
class extent_protocol {
public:
typedef int status;
typedef unsigned long long extentid_t;
enum xxstatus { OK, RPCERR, NOENT, IOERR, FBIG};
enum rpc_numbers {
put = 0x6001,
get,
getattr,
remove
};
static const unsigned int maxextent = 8192*1000;
struct attr {
unsigned int atime;
unsigned int mtime;
unsigned int ctime;
unsigned int size;
};
};
inline unmarshall &
operator>>(unmarshall &u, extent_protocol::attr &a)
{
u >> a.atime;
u >> a.mtime;
u >> a.ctime;
u >> a.size;
return u;
}
inline marshall &
operator<<(marshall &m, extent_protocol::attr a)
{
m << a.atime;
m << a.mtime;
m << a.ctime;
m << a.size;
return m;
}
#endif
// the extent server implementation
#include "extent_server.h"
#include <sstream>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
extent_server::extent_server() {}
int extent_server::put(extent_protocol::extentid_t id, std::string buf, int &)
{
return extent_protocol::IOERR;
}
int extent_server::get(extent_protocol::extentid_t id, std::string &buf)
{
return extent_protocol::IOERR;
}
int extent_server::getattr(extent_protocol::extentid_t id, extent_protocol::attr &a)
{
// You replace this with a real implementation. We send a phony response
// for now because it's difficult to get FUSE to do anything (including
// unmount) if getattr fails.
a.size = 0;
a.atime = 0;
a.mtime = 0;
a.ctime = 0;
return extent_protocol::OK;
}
int extent_server::remove(extent_protocol::extentid_t id, int &)
{
return extent_protocol::IOERR;
}
// this is the extent server
#ifndef extent_server_h
#define extent_server_h
#include <string>
#include <map>
#include "extent_protocol.h"
class extent_server {
public:
extent_server();
int put(extent_protocol::extentid_t id, std::string, int &);
int get(extent_protocol::extentid_t id, std::string &);
int getattr(extent_protocol::extentid_t id, extent_protocol::attr &);
int remove(extent_protocol::extentid_t id, int &);
};
#endif
#include "rpc.h"
#include <arpa/inet.h>
#include <stdlib.h>
#include <stdio.h>
#include "extent_server.h"
// Main loop of extent server
int
main(int argc, char *argv[])
{
if(argc != 2){
fprintf(stderr, "Usage: %s port\n", argv[0]);
exit(1);
}
setvbuf(stdout, NULL, _IONBF, 0);
rpcs server(atoi(argv[1]));
extent_server ls;
server.reg(extent_protocol::get, &ls, &extent_server::get);
server.reg(extent_protocol::getattr, &ls, &extent_server::getattr);
server.reg(extent_protocol::put, &ls, &extent_server::put);
server.reg(extent_protocol::remove, &ls, &extent_server::remove);
while(1)
sleep(1000);
}
/*
* receive request from fuse and call methods of yfs_client
*
* started life as low-level example in the fuse distribution. we
* have to use low-level interface in order to get i-numbers. the
* high-level interface only gives us complete paths.
*/
#include <fuse_lowlevel.h>
#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <assert.h>
#include <arpa/inet.h>
#include "yfs_client.h"
int myid;
yfs_client *yfs;
int id() {
return myid;
}
yfs_client::status
getattr(yfs_client::inum inum, struct stat &st)
{
yfs_client::status ret;
bzero(&st, sizeof(st));
st.st_ino = inum;
printf("getattr %016llx %d\n", inum, yfs->isfile(inum));
if(yfs->isfile(inum)){
yfs_client::fileinfo info;
ret = yfs->getfile(inum, info);
if(ret != yfs_client::OK)
return ret;
st.st_mode = S_IFREG | 0666;
st.st_nlink = 1;
st.st_atime = info.atime;
st.st_mtime = info.mtime;
st.st_ctime = info.ctime;
st.st_size = info.size;
printf(" getattr -> %llu\n", info.size);
} else {
yfs_client::dirinfo info;
ret = yfs->getdir(inum, info);
if(ret != yfs_client::OK)
return ret;
st.st_mode = S_IFDIR | 0777;
st.st_nlink = 2;
st.st_atime = info.atime;
st.st_mtime = info.mtime;
st.st_ctime = info.ctime;
printf(" getattr -> %lu %lu %lu\n", info.atime, info.mtime, info.ctime);
}
return yfs_client::OK;
}
void
fuseserver_getattr(fuse_req_t req, fuse_ino_t ino,
struct fuse_file_info *fi)
{
struct stat st;
yfs_client::inum inum = ino; // req->in.h.nodeid;
yfs_client::status ret;
ret = getattr(inum, st);
if(ret != yfs_client::OK){
fuse_reply_err(req, ENOENT);
return;
}
fuse_reply_attr(req, &st, 0);
}
void
fuseserver_setattr(fuse_req_t req, fuse_ino_t ino, struct stat *attr, int to_set, struct fuse_file_info *fi)
{
printf("fuseserver_setattr 0x%x\n", to_set);
if (FUSE_SET_ATTR_SIZE & to_set) {
printf(" fuseserver_setattr set size to %zu\n", attr->st_size);
struct stat st;
// You fill this in
#if 0
fuse_reply_attr(req, &st, 0);
#else
fuse_reply_err(req, ENOSYS);
#endif
} else {
fuse_reply_err(req, ENOSYS);
}
}
void
fuseserver_read(fuse_req_t req, fuse_ino_t ino, size_t size,
off_t off, struct fuse_file_info *fi)
{
// You fill this in
#if 0
fuse_reply_buf(req, buf, size);
#else
fuse_reply_err(req, ENOSYS);
#endif
}
void
fuseserver_write(fuse_req_t req, fuse_ino_t ino,
const char *buf, size_t size, off_t off,
struct fuse_file_info *fi)
{
// You fill this in
#if 0
fuse_reply_write(req, bytes_written);
#else
fuse_reply_err(req, ENOSYS);
#endif
}
yfs_client::status
fuseserver_createhelper(fuse_ino_t parent, const char *name,
mode_t mode, struct fuse_entry_param *e)
{
// You fill this in
return yfs_client::NOENT;
}
void
fuseserver_create(fuse_req_t req, fuse_ino_t parent, const char *name,
mode_t mode, struct fuse_file_info *fi)
{
struct fuse_entry_param e;
if( fuseserver_createhelper( parent, name, mode, &e ) == yfs_client::OK ) {
fuse_reply_create(req, &e, fi);
} else {
fuse_reply_err(req, ENOENT);
}
}
void fuseserver_mknod( fuse_req_t req, fuse_ino_t parent,
const char *name, mode_t mode, dev_t rdev ) {
struct fuse_entry_param e;
if( fuseserver_createhelper( parent, name, mode, &e ) == yfs_client::OK ) {
fuse_reply_entry(req, &e);
} else {
fuse_reply_err(req, ENOENT);
}
}
void
fuseserver_lookup(fuse_req_t req, fuse_ino_t parent, const char *name)
{
struct fuse_entry_param e;
bool found = false;
e.attr_timeout = 0.0;
e.entry_timeout = 0.0;
// You fill this in:
// Look up the file named `name' in the directory referred to by
// `parent' in YFS. If the file was found, initialize e.ino and
// e.attr appropriately.
if (found)
fuse_reply_entry(req, &e);
else
fuse_reply_err(req, ENOENT);
}
struct dirbuf {
char *p;
size_t size;
};
void dirbuf_add(struct dirbuf *b, const char *name, fuse_ino_t ino)
{
struct stat stbuf;
size_t oldsize = b->size;
b->size += fuse_dirent_size(strlen(name));
b->p = (char *) realloc(b->p, b->size);
memset(&stbuf, 0, sizeof(stbuf));
stbuf.st_ino = ino;
fuse_add_dirent(b->p + oldsize, name, &stbuf, b->size);
}
#define min(x, y) ((x) < (y) ? (x) : (y))
int reply_buf_limited(fuse_req_t req, const char *buf, size_t bufsize,
off_t off, size_t maxsize)
{
if (off < bufsize)
return fuse_reply_buf(req, buf + off, min(bufsize - off, maxsize));
else
return fuse_reply_buf(req, NULL, 0);
}
void
fuseserver_readdir(fuse_req_t req, fuse_ino_t ino, size_t size,
off_t off, struct fuse_file_info *fi)
{
yfs_client::inum inum = ino; // req->in.h.nodeid;
struct dirbuf b;
yfs_client::dirent e;
printf("fuseserver_readdir\n");
if(!yfs->isdir(inum)){
fuse_reply_err(req, ENOTDIR);
return;
}
memset(&b, 0, sizeof(b));
// fill in the b data structure using dirbuf_add
reply_buf_limited(req, b.p, b.size, off, size);
free(b.p);
}
void
fuseserver_open(fuse_req_t req, fuse_ino_t ino,
struct fuse_file_info *fi)
{
// You fill this in
#if 0
fuse_reply_open(req, fi);
#else
fuse_reply_err(req, ENOSYS);
#endif
}
void
fuseserver_mkdir(fuse_req_t req, fuse_ino_t parent, const char *name,
mode_t mode)
{
struct fuse_entry_param e;
// You fill this in
#if 0
fuse_reply_entry(req, &e);
#else
fuse_reply_err(req, ENOSYS);
#endif
}
void
fuseserver_unlink(fuse_req_t req, fuse_ino_t parent, const char *name)
{
// You fill this in
// Success: fuse_reply_err(req, 0);
// Not found: fuse_reply_err(req, ENOENT);
fuse_reply_err(req, ENOSYS);
}
void
fuseserver_statfs(fuse_req_t req)
{
struct statvfs buf;
printf("statfs\n");
memset(&buf, 0, sizeof(buf));
buf.f_namemax = 255;
buf.f_bsize = 512;
fuse_reply_statfs(req, &buf);
}
struct fuse_lowlevel_ops fuseserver_oper;
int
main(int argc, char *argv[])
{
char *mountpoint = 0;
int err = -1;
int fd;
setvbuf(stdout, NULL, _IONBF, 0);
if(argc != 4){
fprintf(stderr, "Usage: yfs_client <mountpoint> <port-extent-server> <port-lock-server>\n");
exit(1);
}
mountpoint = argv[1];
srandom(getpid());
myid = random();
yfs = new yfs_client(argv[2], argv[3]);
fuseserver_oper.getattr = fuseserver_getattr;
fuseserver_oper.statfs = fuseserver_statfs;
fuseserver_oper.readdir =