package mr import "log" import "net" import "os" import "net/rpc" import "net/http" import "sync" type status uint8 const ( idle status = iota progress completed ) type Coordinator struct { // Your definitions here. mapJobStatus map[string]status reduceJobStatus map[string]status workerStatus map[int]status intermediateFiles map[string][]string nReduce int workerCount int m sync.Mutex } func (c *Coordinator) areMapJobsDone() bool { done := true for _, job := range c.mapJobStatus { if job != completed { done = false } } return done } // Your code here -- RPC handlers for the worker to call. // // an example RPC handler. // // the RPC argument and reply types are defined in rpc.go. // func (c *Coordinator) Example(args *ExampleArgs, reply *ExampleReply) error { reply.Y = args.X + 1 return nil } func (c *Coordinator) Register(args *RegisterArgs, reply *RegisterReply) error { c.m.Lock() defer c.m.Unlock() reply.WorkerId = c.workerCount c.workerCount += 1 c.workerStatus[reply.WorkerId] = idle return nil } func (c *Coordinator) GetJob(args *GetJobArgs, reply *GetJobReply) error { c.m.Lock() c.m.Unlock() if !c.areMapJobsDone() { for filename, jobStatus := range c.mapJobStatus { if jobStatus == idle { var job MapJob job.InputFile = filename job.ReducerCount = c.nReduce c.mapJobStatus[filename] = progress reply.Finished = false reply.JobType = Map reply.MapJob = job c.workerStatus[args.WorkerId] = progress return nil } } } return nil } func (c *Coordinator) Finish(args *MapResult, reply *FinishReply) error { c.m.Lock() defer c.m.Unlock() c.intermediateFiles[args.InputFile] = args.IntermediateFiles c.mapJobStatus[args.InputFile] = completed c.workerStatus[args.WorkerId] = idle return nil } // // start a thread that listens for RPCs from worker.go // func (c *Coordinator) server() { rpc.Register(c) rpc.HandleHTTP() //l, e := net.Listen("tcp", ":1234") sockname := coordinatorSock() os.Remove(sockname) l, e := net.Listen("unix", sockname) if e != nil { log.Fatal("listen error:", e) } go http.Serve(l, nil) } // // main/mrcoordinator.go calls Done() periodically to find out // if the entire job has finished. // func (c *Coordinator) Done() bool { ret := false // Your code here. return ret } // // create a Coordinator. // main/mrcoordinator.go calls this function. // nReduce is the number of reduce tasks to use. // func MakeCoordinator(files []string, nReduce int) *Coordinator { c := Coordinator{} // Your code here. c.mapJobStatus = make(map[string]status) c.intermediateFiles = make(map[string][]string) c.workerStatus = make(map[int]status) c.nReduce = nReduce for _, v := range files { c.mapJobStatus[v] = idle c.intermediateFiles[v] = make([]string, nReduce) } c.server() return &c }