func main() { flag.Usage = usage flag.Parse() urls := flag.Args() // Non-flag arguments are URLs to receive from if len(urls) == 0 { log.Println("No URL provided") flag.Usage() os.Exit(1) } sentChan := make(chan sent) // Channel to receive all the delivery receipts. var wait sync.WaitGroup // Used by main() to wait for all goroutines to end. wait.Add(len(urls)) // Wait for one goroutine per URL. container := concurrent.NewContainer("") var connections []concurrent.Connection // Store connctions to close on exit // Start a goroutine for each URL to send messages. for _, urlStr := range urls { util.Debugf("Connecting to %v\n", urlStr) go func(urlStr string) { defer wait.Done() // Notify main() that this goroutine is done. url, err := amqp.ParseURL(urlStr) // Like net/url.Parse() but with AMQP defaults. util.ExitIf(err) // Open a new connection conn, err := net.Dial("tcp", url.Host) // Note net.URL.Host is actually "host:port" util.ExitIf(err) c, err := container.NewConnection(conn) util.ExitIf(err) err = c.Open() util.ExitIf(err) connections = append(connections, c) // Save connection so it will be closed when main() ends // Create and open a session ss, err := c.NewSession() util.ExitIf(err) err = ss.Open() util.ExitIf(err) // Create a Sender using the path of the URL as the AMQP address s, err := ss.Sender(url.Path) util.ExitIf(err) // Loop sending messages. for i := int64(0); i < *count; i++ { m := amqp.NewMessage() body := fmt.Sprintf("%v-%v", url.Path, i) m.Marshal(body) sentMessage, err := s.Send(m) util.ExitIf(err) sentChan <- sent{body, sentMessage} } }(urlStr) } // Wait for all the acknowledgements expect := int(*count) * len(urls) util.Debugf("Started senders, expect %v acknowledgements\n", expect) for i := 0; i < expect; i++ { d := <-sentChan disposition, err := d.sentMessage.Disposition() if err != nil { util.Debugf("acknowledgement[%v] %v error: %v\n", i, d.name, err) } else { util.Debugf("acknowledgement[%v] %v (%v)\n", i, d.name, disposition) } } fmt.Printf("Received all %v acknowledgements\n", expect) wait.Wait() // Wait for all goroutines to finish. for _, c := range connections { // Close all connections if c != nil { c.Close(nil) } } }
func main() { flag.Usage = usage flag.Parse() urls := flag.Args() // Non-flag arguments are URLs to receive from if len(urls) == 0 { log.Println("No URL provided") usage() os.Exit(1) } messages := make(chan amqp.Message) // Channel for messages from goroutines to main() stop := make(chan struct{}) // Closing this channel means the program is stopping. var wait sync.WaitGroup // Used by main() to wait for all goroutines to end. wait.Add(len(urls)) // Wait for one goroutine per URL. container := concurrent.NewContainer("") connections := make(chan concurrent.Connection, len(urls)) // Connections to close on exit // Start a goroutine to for each URL to receive messages and send them to the messages channel. // main() receives and prints them. for _, urlStr := range urls { util.Debugf("Connecting to %s\n", urlStr) go func(urlStr string) { // Start the goroutine defer wait.Done() // Notify main() when this goroutine is done. url, err := amqp.ParseURL(urlStr) // Like net/url.Parse() but with AMQP defaults. util.ExitIf(err) // Open a new connection conn, err := net.Dial("tcp", url.Host) // Note net.URL.Host is actually "host:port" util.ExitIf(err) c, err := container.NewConnection(conn) util.ExitIf(err) util.ExitIf(c.Open()) connections <- c // Save connection so we can Close() when main() ends // Create and open a session ss, err := c.NewSession() util.ExitIf(err) err = ss.Open() util.ExitIf(err) // Create a Receiver using the path of the URL as the source address r, err := ss.Receiver(url.Path) util.ExitIf(err) // Loop receiving messages and sending them to the main() goroutine for { rm, err := r.Receive() if err == concurrent.Closed { return } util.ExitIf(err) select { // Send m to main() or stop case messages <- rm.Message: // Send to main() case <-stop: // The program is stopping. return } } }(urlStr) } // All goroutines are started, we are receiving messages. fmt.Printf("Listening on %d connections\n", len(urls)) // print each message until the count is exceeded. for i := uint64(0); i < *count; i++ { m := <-messages util.Debugf("%s\n", util.FormatMessage(m)) } fmt.Printf("Received %d messages\n", *count) // Close all connections, this will interrupt goroutines blocked in Receiver.Receive() for i := 0; i < len(urls); i++ { c := <-connections c.Disconnect(nil) // FIXME aconway 2015-09-25: Close } close(stop) // Signal all goroutines to stop. wait.Wait() // Wait for all goroutines to finish. close(messages) }
func newBroker() *broker { return &broker{ container: concurrent.NewContainer(""), queues: util.MakeQueueMap(), } }