######################################## # # The implemention of DFSNodeServer. # DFSNodeServer is the service interface that the DFS data node can provide to DFSClient. # Every data node in dfs use dfsnodeserver to transport file chunks and communicate with master. # DFSNodeServer announce a Connection, # listen the message from other computing equipment, # and do appropriate operation,such as read, write, delete or lineoffset the DFSChunk. # # @author Yang Fan(fyabc) # ######################################## implement DFSNodeServer; include "sys.m"; include "draw.m"; include "bufio.m"; include "dfsutil.m"; include "dfsclient.m"; Connection : import sys; DFSFile : import dfsutil; DFSChunk : import dfsutil; DFSNode : import dfsutil; FD : import sys; Iobuf : import bufio; sys : Sys; bufio : Bufio; dfsutil : DFSUtil; dfsclient : DFSClient; dataPath := string "/appl/MR/ser/"; homePath := string "/appl/MR/"; localPort := int 2334; chunkNumber := int 0; DFSNodeServer : 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; bufio = load Bufio Bufio->PATH; dfsutil = load DFSUtil DFSUtil->PATH; dfsclient = load DFSClient DFSClient->PATH; dfsutil->init(); buffer := bufio->open("/appl/MR/config", Bufio->OREAD); buffer.gets('\n'); localAddr := buffer.gets('\n'); localAddr = localAddr[:len localAddr - 1]; spawn heartBeat(localAddr); (n, conn) := sys->announce("tcp!*!" + string localPort); if (n < 0) { sys->print("DFSServer: announce failed %r\n"); exit; } while(1) { listen(conn, ctxt); } } heartBeat(localAddr : string) { while (1) { dfsclient->init(); dfsclient->updateNode(localAddr, localPort, chunkNumber); dfsclient->disconnect(); sys->sleep(30000); } } listen(conn : Connection, ctxt : ref Draw->Context) { buf := array [sys->ATOMICIO] of byte; (ok, c) := sys->listen(conn); if (ok < 0) { sys->print("DFSSlaveServer: 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; "read" => { chunkId := int hd msg; datafd := sys->open(dataPath + string chunkId, Sys->OREAD); if(datafd != nil) sendReadData(datafd, chunkId, conn); break receive; } "write" => { dfd := sys->open(conn.dir + "/data", sys->ORDWR); sys->fprint(dfd, "start"); sys->export(dfd, dataPath, Sys->EXPWAIT); chunkNumber++; break receive; } "delete" => { chunkId := hd msg; ok := sys->remove(dataPath + chunkId); sys->fprint(wdfd, "%d", ok); chunkNumber--; } "lineos" => { } "lineosc" =>{ } * => sys->fprint(wdfd, "Unknown message!\n"); } msglen = sys->read(rdfd, msgStr, len msgStr); } } sendReadData(datafd : ref FD, chunkId : int, conn : Connection) { dfd := sys->open(conn.dir + "/data", sys->ORDWR); sys->mount(dfd, nil, dataPath + "remote",Sys->MCREATE, nil); datacopyfd := sys->create(dataPath + "remote/" + string chunkId, sys->ORDWR, 8r600); buf := array [Sys->ATOMICIO] of byte; length : int; do { length = sys->read(datafd, buf, len buf); sys->write(datacopyfd, buf[:length], length); }while (length == len buf); sys->unmount(nil, dataPath + "remote"); }