func cmdDaemon(c *cli.Context) { app := libswarm.NewServer() app.OnLog(func(args ...string) error { log.Printf("%s\n", strings.Join(args, " ")) return nil }) app.OnError(func(args ...string) error { Fatalf("Fatal: %v", strings.Join(args[:1], "")) return nil }) back := backends.New() if len(c.Args()) == 0 { names, err := back.Ls() if err != nil { Fatalf("ls: %v", err) } fmt.Println(strings.Join(names, "\n")) return } var previousInstanceR libswarm.Receiver // FIXME: refactor into a Pipeline for idx, backendArg := range c.Args() { bName, bArgs, err := parseCmd(backendArg) if err != nil { Fatalf("parse: %v", err) } _, backend, err := back.Attach(bName) if err != nil { Fatalf("%s: %v\n", bName, err) } instance, err := backend.Spawn(bArgs...) if err != nil { Fatalf("spawn %s: %v\n", bName, err) } instanceR, instanceW, err := instance.Attach("") if err != nil { Fatalf("attach: %v", err) } go func(r libswarm.Receiver, w libswarm.Sender, idx int) { if r != nil { libswarm.Copy(w, r) } w.Close() }(previousInstanceR, instanceW, idx) if err := instance.Start(); err != nil { Fatalf("start: %v", err) } previousInstanceR = instanceR } _, err := libswarm.Copy(app, previousInstanceR) if err != nil { Fatalf("copy: %v", err) } }
func (a *aggregator) attach(name string, ret libswarm.Sender) error { if name != "" { // TODO: implement this? return fmt.Errorf("attaching to a child is not implemented") } if _, err := ret.Send(&libswarm.Message{Verb: libswarm.Ack, Ret: a.server}); err != nil { return err } var copies sync.WaitGroup for _, b := range a.backends { r, _, err := b.Attach("") if err != nil { return err } copies.Add(1) go func() { log.Printf("copying output from %#v\n", b) libswarm.Copy(ret, r) log.Printf("finished output from %#v\n", b) copies.Done() }() } copies.Wait() return nil }
func Task(f func(in libswarm.Receiver, out libswarm.Sender)) libswarm.Sender { var running bool var l sync.RWMutex inR, inW := libswarm.Pipe() outR, outW := libswarm.Pipe() obj := libswarm.NewServer() obj.OnVerb(libswarm.Attach, libswarm.Handler(func(msg *libswarm.Message) error { msg.Ret.Send(&libswarm.Message{Verb: libswarm.Ack, Ret: inW}) fmt.Printf("copying task output from %#v to %#v\n", outR, msg.Ret) defer fmt.Printf("(DONE) copying task output from %#v to %#v\n", outR, msg.Ret) libswarm.Copy(msg.Ret, outR) return nil })) obj.OnVerb(libswarm.Start, libswarm.Handler(func(msg *libswarm.Message) error { l.RLock() r := running l.RUnlock() if r { return fmt.Errorf("already running") } l.Lock() go f(inR, outW) running = true l.Unlock() msg.Ret.Send(&libswarm.Message{Verb: libswarm.Ack}) return nil })) return obj }
func Simulator() libswarm.Sender { s := libswarm.NewServer() s.OnVerb(libswarm.Spawn, libswarm.Handler(func(ctx *libswarm.Message) error { containers := ctx.Args instance := utils.Task(func(in libswarm.Receiver, out libswarm.Sender) { libswarm.AsClient(out).Log("[simulator] starting\n") s := libswarm.NewServer() s.OnVerb(libswarm.Ls, libswarm.Handler(func(msg *libswarm.Message) error { libswarm.AsClient(out).Log("[simulator] generating fake list of objects...\n") libswarm.AsClient(msg.Ret).Set(containers...) return nil })) libswarm.Copy(s, in) }) ctx.Ret.Send(&libswarm.Message{Verb: libswarm.Ack, Ret: instance}) return nil })) return s }
// Spawn will return a new instance as the Ret channel of the message sent back func (dbg *debug) spawn(msg *libswarm.Message) (err error) { // By sending back a task, libswarm will run the function with the in and out arguments // set to the services present before and after this one in the pipeline. instance := utils.Task(func(in libswarm.Receiver, out libswarm.Sender) { // Setup our channels dbg.out = out // Set up the debug interceptor dbg.service.Catchall(libswarm.Handler(dbg.catchall)) // Copy everything from the receiver to our service. By copying like this in the task // we can use the catchall handler instead of handling the message here. libswarm.Copy(dbg.service, in) }) // Inform the system of our new instance msg.Ret.Send(&libswarm.Message{ Verb: libswarm.Ack, Ret: instance, }) return }