158 lines
3.2 KiB
Go
158 lines
3.2 KiB
Go
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
|
|
}
|