From 49fe0eb7ac877f99452a3bb9d3c901eb76a4c867 Mon Sep 17 00:00:00 2001 From: John Hopper Date: Wed, 18 Jun 2014 10:28:14 -0500 Subject: [PATCH 1/2] Cleanup and Enhance Debug Signed-off-by: John Hopper john.hopper@jpserver.net --- backends/backends.go | 3 +- backends/debug.go | 31 ------------- utils/debug.go | 108 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 110 insertions(+), 32 deletions(-) delete mode 100644 backends/debug.go create mode 100644 utils/debug.go diff --git a/backends/backends.go b/backends/backends.go index 6a5b1517cf..eb4d30118e 100644 --- a/backends/backends.go +++ b/backends/backends.go @@ -2,6 +2,7 @@ package backends import ( "github.com/docker/libswarm/beam" + "github.com/docker/libswarm/utils" ) // New returns a new engine, with all backends @@ -13,7 +14,7 @@ import ( func New() *beam.Object { backends := beam.NewTree() backends.Bind("simulator", Simulator()) - backends.Bind("debug", Debug()) + backends.Bind("debug", utils.Debug()) backends.Bind("fakeclient", FakeClient()) backends.Bind("dockerclient", DockerClient()) backends.Bind("exec", Exec()) diff --git a/backends/debug.go b/backends/debug.go deleted file mode 100644 index fa8020676f..0000000000 --- a/backends/debug.go +++ /dev/null @@ -1,31 +0,0 @@ -package backends - -import ( - "fmt" - "strings" - - "github.com/docker/libswarm/beam" -) - -func Debug() beam.Sender { - backend := beam.NewServer() - backend.OnSpawn(beam.Handler(func(ctx *beam.Message) error { - instance := beam.Task(func(in beam.Receiver, out beam.Sender) { - for { - msg, err := in.Receive(beam.Ret) - if err != nil { - fmt.Printf("debug receive: %v", err) - return - } - fmt.Printf("[DEBUG] %s %s\n", msg.Verb, strings.Join(msg.Args, " ")) - if _, err := out.Send(msg); err != nil { - fmt.Printf("debug send: %v", err) - return - } - } - }) - _, err := ctx.Ret.Send(&beam.Message{Verb: beam.Ack, Ret: instance}) - return err - })) - return backend -} diff --git a/utils/debug.go b/utils/debug.go new file mode 100644 index 0000000000..462c09ab6d --- /dev/null +++ b/utils/debug.go @@ -0,0 +1,108 @@ +package utils + +import ( + "fmt" + "log" + + "github.com/docker/libswarm/beam" +) + +// The Debug service is an example of intercepting messages between a receiver and a sender. +// The service also exposes messages passing through it for debug purposes. +func Debug() beam.Sender { + dbgInstance := &debug{ + service: beam.NewServer(), + } + + sender := beam.NewServer() + sender.OnSpawn(beam.Handler(dbgInstance.spawn)) + return sender +} + +// Function for forwarding a messgae including some minor error formatting +func forward(out beam.Sender, msg *beam.Message) (err error) { + if _, err := out.Send(msg); err != nil { + return fmt.Errorf("[debug] Failed to forward msg. Reason: %v\n", err) + } + return +} + +// Debug service type +type debug struct { + service *beam.Server + in beam.Receiver + out beam.Sender +} + +// Spawn will return a new instance as the Ret channel of the message sent back +func (dbg *debug) spawn(msg *beam.Message) (err error) { + // By sending back a task, beam will run the function with the in and out arguments + // set to the services present before and after this one in the pipeline. + instance := beam.Task(func(in beam.Receiver, out beam.Sender) { + // Setup our channels + dbg.in = in + dbg.out = out + + // Set up the debug interceptor + dbg.service.Catchall(beam.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. + beam.Copy(dbg.service, in) + }) + + // Inform the system of our new instance + msg.Ret.Send(&beam.Message{ + Verb: beam.Ack, + Ret: instance, + }) + + return +} + +// Catches all messages sent to the service +func (dbg *debug) catchall(msg *beam.Message) (err error) { + log.Printf("[debug] ---> Upstream Message { Verb: %s, Args: %v }\n", msg.Verb, msg.Args) + + // If there's no output after us then we'll just reply with an error + // informing the receiver that the verb is not implemented. + if dbg.out == nil { + return fmt.Errorf("[debug] Verb: %s is not implemented.", msg.Verb) + } + + // The forwarded message has the return channel set to a new replyHandler. The replyHandler is a small + // callback that allows for interception of downstream messages. + forwardedMessage := &beam.Message{ + Verb: msg.Verb, + Args: msg.Args, + Att: msg.Att, + Ret: &replyHandler{ + out: msg.Ret, + }, + } + + // Send the forwarded message + if err := forward(dbg.out, forwardedMessage); err == nil { + // Hijack the return channel so we can avoid any interference with things such as close + msg.Ret = beam.NopSender{} + } + + return +} + +// We use a replyHandler to provide context for relaying the return channel +// of the origin message. +type replyHandler struct { + out beam.Sender +} + +// Send a message using the out channel +func (rh *replyHandler) Send(msg *beam.Message) (receiver beam.Receiver, err error) { + log.Printf("[debug] <--- Downstream Message { Verb: %s, Args: %v }\n", msg.Verb, msg.Args) + return nil, forward(rh.out, msg) +} + +func (rh *replyHandler) Close() (err error) { + // Since we don't allow the downstream handler to close the return channel, we do so here. + return rh.out.Close() +} From eedfdd348e6afc4f82d72a43bfdd221b0108ca2a Mon Sep 17 00:00:00 2001 From: Solomon Hykes Date: Wed, 18 Jun 2014 20:28:07 -0700 Subject: [PATCH 2/2] Move debug.go to a `debug` sub-package Signed-off-by: Solomon Hykes --- backends/backends.go | 4 ++-- {utils => debug}/debug.go | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) rename {utils => debug}/debug.go (99%) diff --git a/backends/backends.go b/backends/backends.go index eb4d30118e..6cb2c22049 100644 --- a/backends/backends.go +++ b/backends/backends.go @@ -2,7 +2,7 @@ package backends import ( "github.com/docker/libswarm/beam" - "github.com/docker/libswarm/utils" + "github.com/docker/libswarm/debug" ) // New returns a new engine, with all backends @@ -14,7 +14,7 @@ import ( func New() *beam.Object { backends := beam.NewTree() backends.Bind("simulator", Simulator()) - backends.Bind("debug", utils.Debug()) + backends.Bind("debug", debug.Debug()) backends.Bind("fakeclient", FakeClient()) backends.Bind("dockerclient", DockerClient()) backends.Bind("exec", Exec()) diff --git a/utils/debug.go b/debug/debug.go similarity index 99% rename from utils/debug.go rename to debug/debug.go index 462c09ab6d..c287fc4bd8 100644 --- a/utils/debug.go +++ b/debug/debug.go @@ -1,4 +1,4 @@ -package utils +package debug import ( "fmt"