initial commit ?
This commit is contained in:
parent
fa6877b02d
commit
9d4d24dc3e
@ -32,7 +32,7 @@ func main() {
|
|||||||
func loadPlugin(filename string) (func(string, string) []mr.KeyValue, func(string, []string) string) {
|
func loadPlugin(filename string) (func(string, string) []mr.KeyValue, func(string, []string) string) {
|
||||||
p, err := plugin.Open(filename)
|
p, err := plugin.Open(filename)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("cannot load plugin %v", filename)
|
log.Fatalf("cannot load plugin %v: %s", filename, err)
|
||||||
}
|
}
|
||||||
xmapf, err := p.Lookup("Map")
|
xmapf, err := p.Lookup("Map")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@ -5,11 +5,42 @@ import "net"
|
|||||||
import "os"
|
import "os"
|
||||||
import "net/rpc"
|
import "net/rpc"
|
||||||
import "net/http"
|
import "net/http"
|
||||||
|
import "sync"
|
||||||
|
|
||||||
|
type status uint8
|
||||||
|
|
||||||
|
const (
|
||||||
|
idle status = iota
|
||||||
|
progress
|
||||||
|
completed
|
||||||
|
)
|
||||||
|
|
||||||
type Coordinator struct {
|
type Coordinator struct {
|
||||||
// Your definitions here.
|
// 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.
|
// Your code here -- RPC handlers for the worker to call.
|
||||||
@ -24,6 +55,54 @@ func (c *Coordinator) Example(args *ExampleArgs, reply *ExampleReply) error {
|
|||||||
return nil
|
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
|
// start a thread that listens for RPCs from worker.go
|
||||||
@ -63,7 +142,15 @@ func MakeCoordinator(files []string, nReduce int) *Coordinator {
|
|||||||
c := Coordinator{}
|
c := Coordinator{}
|
||||||
|
|
||||||
// Your code here.
|
// 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()
|
c.server()
|
||||||
return &c
|
return &c
|
||||||
|
|||||||
@ -24,6 +24,54 @@ type ExampleReply struct {
|
|||||||
|
|
||||||
// Add your RPC definitions here.
|
// Add your RPC definitions here.
|
||||||
|
|
||||||
|
type JobType uint8
|
||||||
|
const (
|
||||||
|
Map JobType = iota
|
||||||
|
Reduce
|
||||||
|
)
|
||||||
|
|
||||||
|
type MapJob struct {
|
||||||
|
//Index int
|
||||||
|
InputFile string
|
||||||
|
ReducerCount int
|
||||||
|
//IntermediateFiles []string
|
||||||
|
}
|
||||||
|
|
||||||
|
type ReduceJob struct {
|
||||||
|
ReducerNumber int
|
||||||
|
IntermediateFiles []string
|
||||||
|
}
|
||||||
|
|
||||||
|
type MapResult struct {
|
||||||
|
InputFile string
|
||||||
|
IntermediateFiles []string
|
||||||
|
WorkerId int
|
||||||
|
}
|
||||||
|
|
||||||
|
type RegisterArgs struct {
|
||||||
|
// empty
|
||||||
|
}
|
||||||
|
|
||||||
|
type RegisterReply struct {
|
||||||
|
WorkerId int
|
||||||
|
}
|
||||||
|
|
||||||
|
type GetJobArgs struct {
|
||||||
|
WorkerId int
|
||||||
|
}
|
||||||
|
|
||||||
|
type GetJobReply struct {
|
||||||
|
JobType JobType
|
||||||
|
|
||||||
|
MapJob MapJob
|
||||||
|
ReduceJob ReduceJob
|
||||||
|
|
||||||
|
Finished bool
|
||||||
|
}
|
||||||
|
|
||||||
|
type FinishReply struct {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
// Cook up a unique-ish UNIX-domain socket name
|
// Cook up a unique-ish UNIX-domain socket name
|
||||||
// in /var/tmp, for the coordinator.
|
// in /var/tmp, for the coordinator.
|
||||||
|
|||||||
103
src/mr/worker.go
103
src/mr/worker.go
@ -4,7 +4,9 @@ import "fmt"
|
|||||||
import "log"
|
import "log"
|
||||||
import "net/rpc"
|
import "net/rpc"
|
||||||
import "hash/fnv"
|
import "hash/fnv"
|
||||||
|
import "os"
|
||||||
|
import "io"
|
||||||
|
import "encoding/json"
|
||||||
|
|
||||||
//
|
//
|
||||||
// Map functions return a slice of KeyValue.
|
// Map functions return a slice of KeyValue.
|
||||||
@ -24,20 +26,88 @@ func ihash(key string) int {
|
|||||||
return int(h.Sum32() & 0x7fffffff)
|
return int(h.Sum32() & 0x7fffffff)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var id int
|
||||||
|
|
||||||
//
|
//
|
||||||
// main/mrworker.go calls this function.
|
// main/mrworker.go calls this function.
|
||||||
//
|
//
|
||||||
func Worker(mapf func(string, string) []KeyValue,
|
func Worker(mapf func(string, string) []KeyValue, reducef func(string, []string) string) {
|
||||||
reducef func(string, []string) string) {
|
|
||||||
|
|
||||||
// Your worker implementation here.
|
// Your worker implementation here.
|
||||||
|
|
||||||
|
registerReply := Register()
|
||||||
|
id = registerReply.WorkerId
|
||||||
|
|
||||||
|
done := false
|
||||||
|
|
||||||
|
for !done {
|
||||||
|
reply := GetJob(GetJobArgs{id})
|
||||||
|
|
||||||
|
if reply.Finished {
|
||||||
|
done = true
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if reply.JobType == Map {
|
||||||
|
doMap(mapf, reply.MapJob)
|
||||||
|
} else if reply.JobType == Reduce {
|
||||||
|
doReduce(reducef, reply.ReduceJob)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// uncomment to send the Example RPC to the coordinator.
|
// uncomment to send the Example RPC to the coordinator.
|
||||||
// CallExample()
|
// CallExample()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func doMap(mapf func(string, string) []KeyValue, job MapJob) {
|
||||||
|
file, err := os.Open(job.InputFile)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("[Error] Could not open file %s", job.InputFile)
|
||||||
|
}
|
||||||
|
|
||||||
|
content, err := io.ReadAll(file)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("[Error] Could not read file %s", job.InputFile)
|
||||||
|
}
|
||||||
|
file.Close()
|
||||||
|
|
||||||
|
kva := mapf(job.InputFile, string(content))
|
||||||
|
|
||||||
|
sort.Sort(ByKey(kva))
|
||||||
|
|
||||||
|
partitions := make([][]KeyValue, job.ReducerCount)
|
||||||
|
|
||||||
|
for _, v := range kva {
|
||||||
|
i := ihash(v.Key) % job.ReducerCount
|
||||||
|
partitions[i] = append(partitions[i], v)
|
||||||
|
}
|
||||||
|
|
||||||
|
intermediateFiles := make([]string, job.ReducerCount)
|
||||||
|
|
||||||
|
for i, v := range partitions {
|
||||||
|
filename := fmt.Sprintf("mr-%v-%v.txt", job.Index, i)
|
||||||
|
file, err := os.Open(filename);
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("[Error] Could not open file %s", filename)
|
||||||
|
}
|
||||||
|
|
||||||
|
enc := json.NewEncoder(file)
|
||||||
|
for _, kv := range v {
|
||||||
|
err := enc.Encode(&kv)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("[Error] Could not write to file %s", filename)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
intermediateFiles[i] = filename
|
||||||
|
|
||||||
|
file.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
Finish(MapResult{job.InputFile, intermediateFiles, id})
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// example function to show how to make an RPC call to the coordinator.
|
// example function to show how to make an RPC call to the coordinator.
|
||||||
//
|
//
|
||||||
@ -65,6 +135,33 @@ func CallExample() {
|
|||||||
} else {
|
} else {
|
||||||
fmt.Printf("call failed!\n")
|
fmt.Printf("call failed!\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
call("Coordinatior.Wrong", &args, &reply);
|
||||||
|
}
|
||||||
|
|
||||||
|
func Register() RegisterReply {
|
||||||
|
var args RegisterArgs
|
||||||
|
|
||||||
|
var reply RegisterReply
|
||||||
|
|
||||||
|
call("Coordinator.Register", &args, &reply)
|
||||||
|
return reply
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetJob(args GetJobArgs) GetJobReply {
|
||||||
|
var reply GetJobReply
|
||||||
|
|
||||||
|
call("Coordinator.GetJob", &args, &reply)
|
||||||
|
|
||||||
|
return reply
|
||||||
|
}
|
||||||
|
|
||||||
|
func Finish(args MapResult) FinishReply {
|
||||||
|
var reply FinishReply
|
||||||
|
|
||||||
|
call("Coordinator.Finish", &args, &reply)
|
||||||
|
|
||||||
|
return reply
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user