####################################### # # The implemention of DFSServer. # DFSServer is the service interface that DFSMaster can provide to DFSClient. # DFSServer announce a Connection, # listen the message from other computing equipment, # and call appropriate function in dfsmaster. # # @author Kai Yao(yaokai) # @author Yang Fan(fyabc) # ######################################## implement DFSServer; include "sys.m"; include "draw.m"; include "dfsmaster.m"; include "dfsutil.m"; include "hash.m"; include "tables.m"; include "../xml/xmlhandle.m"; include "xml.m"; include "bufio.m"; Connection : import sys; DFSFile : import dfsutil; DFSChunk : import dfsutil; DFSNode : import dfsutil; sys : Sys; dfsmaster : DFSMaster; dfsutil : DFSUtil; xmlhandle : XmlHandle; dataPath : con "/appl/MR/hostser/"; homePath : con "/appl/MR/"; mutex : chan of int; DFSServer : module { init : fn(ctxt : ref Draw->Context, args : list of string); }; init(ctxt : ref Draw->Context, args : list of string) { sys = load Sys Sys->PATH; dfsutil = load DFSUtil DFSUtil->PATH; dfsmaster = load DFSMaster DFSMaster->PATH; xmlhandle = load XmlHandle XmlHandle->PATH; dfsmaster->init(); dfsutil->init(); mutex = chan [1] of int; (n, conn) := sys->announce("tcp!*!2333"); if (n < 0) { sys->print("DFSServer: announce failed %r\n"); exit; } while(1) { listen(conn, ctxt); } } listen(conn : Connection, ctxt : ref Draw->Context) { buf := array [sys->ATOMICIO] of byte; (ok, c) := sys->listen(conn); if (ok < 0) { sys->print("DFSServer: listen failed %r\n"); exit; } rdf := sys->open(conn.dir + "/remote", sys->OREAD); n := sys->read(rdf, buf, len buf); connHandle(c, ctxt); } connHandle(conn : Connection, ctxt : ref Draw->Context) { addr := array [sys->ATOMICIO] of byte; msgStr := array [sys->ATOMICIO] of byte; msg : list of string; rdfd := sys->open(conn.dir + "/data", sys->OREAD); wdfd := sys->open(conn.dir + "/data", sys->OWRITE); rfd := sys->open(conn.dir + "/remote", sys->OREAD); addrlen := sys->read(rfd, addr, len addr); sys->print("Message from: %s\n", string addr[:addrlen]); msglen := sys->read(rdfd, msgStr, len msgStr); receive : while (msglen > 0) { (nil, msg) = sys->tokenize(string msgStr[:msglen], "@"); op := hd msg; msg = tl msg; case (op) { "disconnect" => break receive; "create" => { name := hd msg; msg = tl msg; replicas := int hd msg; dfsmaster->createFile(name, replicas); sys->fprint(wdfd, "Successfully create file %s !\n", name); } "delete" => { name := hd msg; msg =tl msg; ok := dfsmaster->deleteFile(name); if (ok == 0) sys->fprint(wdfd, "Successfully delete file %s !\n", name); else sys->fprint(wdfd, "No such file in file list!\n"); } "list" => { fileList := dfsmaster->listFiles(); sys->fprint(wdfd, "%s", list2string(fileList)); } "get" => { name := hd msg; msg = tl msg; file := dfsmaster->getFile(name); if (file == nil) { sys->fprint(wdfd, "No such file!\n"); break receive; } else sys->fprint(wdfd, "Successly find file %s\n", name); buf := array [100] of byte; sys->read(rdfd, buf, len buf); xmlf := sys->create(dataPath + name + ".xml", sys->ORDWR, 8r600); xmlhandle->file2xml(xmlf, file); sys->seek(xmlf, big 0, Sys->SEEKSTART); sendXml(name, xmlf, conn); break receive; } "chunk" => { name := hd msg; msg = tl msg; offset := big hd msg; msg = tl msg; size := int hd msg; ok := dfsmaster->createChunk(name, offset, size); sys->fprint(wdfd, "%d", ok); } "upNode" => { addr := hd msg; msg = tl msg; port := int hd msg; msg = tl msg; chunkNumber := int hd msg; node := ref DFSNode(addr, port, chunkNumber); dfsmaster->updateNode(node); sys->fprint(wdfd, "Successfully update node %s", node.toString()); } "rmNode" => { addr := hd msg; msg = tl msg; port := int hd msg; msg = tl msg; ok := dfsmaster->removeNode(ref DFSNode(addr, port, 0)); if (ok == 0) sys->fprint(wdfd, "Successfully remove node addr: %s, port: %d\n", addr, port); else sys->fprint(wdfd, "No such node in node list!\n"); } * => sys->fprint(wdfd, "Unknown message!\n"); } msglen = sys->read(rdfd, msgStr, len msgStr); } } list2string(src : list of string) : string { ret : string; for (p := src; p != nil; p = tl p) ret = ret + hd p; return ret; } sendXml(name : string, xmlf : ref Sys->FD, conn : Connection) { mutex <- = 0; dfd := sys->open(conn.dir + "/data", sys->ORDWR); sys->mount(dfd, nil, dataPath + "remote",Sys->MCREATE, nil); xmlf2 := sys->create(dataPath + "remote/" + name + ".xml", sys->ORDWR, 8r600); buf := array [Sys->ATOMICIO] of byte; length : int; do { length = sys->read(xmlf, buf, len buf); sys->write(xmlf2, buf[:length], length); }while ( length == len buf); sys->unmount(nil, dataPath + "remote"); sys->remove(dataPath + name + ".xml"); <- mutex; }