######################################## # # The implemention of the MapperWorker module. # the mapreduce module and inputFileBlock are downloaded from DFS. # collect() collect the pair of (key , value) into OutputCollector; # saveToLocal() sort and combine the pairs in OutputCollector and write it into a local file. # # @author Yang Fan(fyabc) # @author Guanji Gao(ggj) # ######################################## implement MapperWorker; include "sys.m"; include "draw.m"; include "lists.m"; include "tables.m"; include "sort.m"; include "bufio.m"; include "mapperworker.m"; include "mapreduce.m"; include "mrutil.m"; include "ioutil.m"; include "../dfs/dfsutil.m"; include "../dfs/dfsclient.m"; sys : Sys; lists : Lists; sort : Sort; bufio : Bufio; tables : Tables; mapreduce : MapReduce; ioutil : IOUtil; mrutil : MRUtil; dfsutil : DFSUtil; dfsclient : DFSClient; FD : import sys; Iobuf : import bufio; MapperTask : import mrutil; OutputCollector : import ioutil; DFSFile : import dfsutil; DFSChunkCmp : import dfsutil; Strhash : import tables; mapperPath := "/appl/MR/task/"; mapperAddr : string; downloadMutex : chan of int; downloadMutex2 : chan of int; init() { sys = load Sys Sys->PATH; lists = load Lists Lists->PATH; sort = load Sort Sort->PATH; bufio = load Bufio Bufio->PATH; ioutil = load IOUtil IOUtil->PATH; mrutil = load MRUtil MRUtil->PATH; dfsclient = load DFSClient DFSClient->PATH; dfsutil = load DFSUtil DFSUtil->PATH; tables = load Tables Tables->PATH; ioutil->init(); mrutil->init(); dfsutil->init(); buffer := bufio->open("/appl/MR/config", Bufio->OREAD); buffer.gets('\n'); mapperAddr = buffer.gets('\n'); mapperAddr = mapperAddr[: len mapperAddr - 1]; downloadMutex = chan [1] of int; downloadMutex2 = chan [1] of int; } run(mapperTask : ref MapperTask) { downloadMutex <-= 0; getmr(mapperTask); <-downloadMutex; folderName := mapperPath + "tasks_" + string mapperTask.id + "/"; sys->create(folderName, sys->OREAD, sys->DMDIR + 8r777); downloadMutex2 <-= 0; getFileBlock(mapperTask); <-downloadMutex2; buffer := bufio->open(folderName + mapperTask.inputFileBlock.fileName + "_inputFileBlock", Bufio->OREAD); collector := collect(buffer); saveToLocal(mapperTask, collector, folderName); spawn ioutil->sendRemoteFile(70000 + mapperTask.id,folderName); } collect(buffer : ref Iobuf) : ref OutputCollector { collector := ref OutputCollector(nil); collector.collection = Strhash[ref IOUtil->KVs].new(10000, nil); line : string; while((line = buffer.gets('\n')) != nil) { kvList := mapreduce->filt(line); for ( ; kvList != nil ; kvList = tl kvList) { (key , value) := hd kvList; mapreduce->map(key, value, collector); } } return collector; } saveToLocal(mapperTask : ref MapperTask, collector : ref OutputCollector, folderName : string) { fds := array[mapperTask.reducerAmount] of ref FD; buffers := array[mapperTask.reducerAmount] of ref Iobuf; for(i := 0; i < mapperTask.reducerAmount; i++) { fds[i] = sys->create(folderName + "tcp!" + mapperAddr + "!" + string (70000 + mapperTask.id) + "_part_" + string i, sys->ORDWR, 8r600); buffers[i] = bufio->open(folderName + "tcp!" + mapperAddr + "!" + string (70000 + mapperTask.id) + "_part_" + string i, bufio->OWRITE); } recordMap := collector.getMap(); mapSize := len recordMap; keyRange : int; if(mapreduce->keySpaceSize() % mapperTask.reducerAmount == 0) keyRange = mapreduce->keySpaceSize() / mapperTask.reducerAmount; else keyRange = mapreduce->keySpaceSize() / mapperTask.reducerAmount + 1; for(i = 0; i < mapSize; i++) { key := recordMap[i].key; values := recordMap[i].values; j := mapreduce->hashKey(key) / keyRange; if (mapperTask.combinable == 1) { (key_cb, value_cb) := mapreduce->combine(key, values); buffers[j].puts(key_cb + " " + value_cb + "\n"); } else { for( ; values != nil; values = tl values) { value := hd values; buffers[j].puts(key + " " + value + "\n"); } } } for(i = 0; i < mapperTask.reducerAmount; i++) { buffers[i].flush(); buffers[i].close(); } } getmr(mapperTask : ref MapperTask) { if(sys->open(mapperPath + mapperTask.mrClassName, Sys->OREAD) == nil) { dfsclient->init(); file := dfsclient->getFile(mapperTask.mrClassName); total := (lists->last(file.chunks)).offset + big (lists->last(file.chunks)).size; fd := sys->create(mapperPath + mapperTask.mrClassName, Sys->ORDWR, 8r600); dd(fd, file,big 0,total); } mapreduce = load MapReduce (mapperPath + mapperTask.mrClassName); mapreduce->init(); } getFileBlock(mapperTask : ref MapperTask) { folderName := mapperPath + "tasks_" + string mapperTask.id + "/"; dfsclient->init(); file := dfsclient->getFile(mapperTask.inputFileBlock.fileName); fd := sys->create(folderName + mapperTask.inputFileBlock.fileName + "_inputFileBlock", Sys->ORDWR, 8r600); dd(fd, file, mapperTask.inputFileBlock.offset, big mapperTask.inputFileBlock.size); } dd(fd : ref Sys->FD, file : ref DFSFile, offset : big, size : big) { if (dfsclient == nil) dfsclient = load DFSClient DFSClient->PATH; if (dfsutil == nil) { dfsutil = load DFSUtil DFSUtil->PATH; dfsutil->init(); } if (sys == nil) sys == load Sys Sys->PATH; sort = load Sort Sort->PATH; dfsclient->init(); chunks := file.getChunks(); cmp := ref DFSChunkCmp(); sort->sort(cmp, chunks); i := 0; while (i < len chunks && chunks[i].offset + big chunks[i].size < offset) i++; while (i < len chunks && chunks[i].offset < offset + size) { tempfd := dfsclient->readChunk(chunks[i]); start := big 0; buf := array [Sys->ATOMICIO] of byte; if (chunks[i].offset < offset) start = sys->seek(tempfd, offset - chunks[i].offset, Sys->SEEKSTART); if (chunks[i].offset + big chunks[i].size > offset + size) { total := int (offset + size - chunks[i].offset - start); while (total > len buf) { sys->read(tempfd, buf, len buf); sys->write(fd, buf, len buf); total -= len buf; } if (total > 0) { sys->read(tempfd, buf[:total], total); sys->write(fd, buf[:total], total); } } else while ((length := sys->read(tempfd, buf, len buf)) != 0) sys->write(fd, buf, length); sys->remove(sys->fd2path(tempfd)); i++; } }