func (s *server) doSearch(ctx context.Context, backend *Backend, q *client.Query) (*api.ReplySearch, error) { var cl client.Client var search client.Search var err error select { case cl = <-backend.Clients: case <-ctx.Done(): return nil, ErrTimedOut } defer backend.CheckIn(cl) search, err = cl.Query(q) if err != nil { log.Printf(ctx, "error talking to backend err=%s", err) return nil, err } reply := &api.ReplySearch{Results: make([]*client.Result, 0)} for r := range search.Results() { reply.Results = append(reply.Results, r) } reply.Info, err = search.Close() if err != nil { return nil, err } return reply, nil }
// rpcCallTablet wil execute the RPC on the remote server. func (client *GoRpcTabletManagerClient) rpcCallTablet(ctx context.Context, tablet *topo.TabletInfo, name string, args, reply interface{}) error { // create the RPC client, using ctx.Deadline if set, or no timeout. var connectTimeout time.Duration deadline, ok := ctx.Deadline() if ok { connectTimeout = deadline.Sub(time.Now()) if connectTimeout < 0 { return fmt.Errorf("Timeout connecting to TabletManager.%v on %v", name, tablet.Alias) } } rpcClient, err := bsonrpc.DialHTTP("tcp", tablet.Addr(), connectTimeout, nil) if err != nil { return fmt.Errorf("RPC error for %v: %v", tablet.Alias, err.Error()) } defer rpcClient.Close() // use the context Done() channel. Will handle context timeout. call := rpcClient.Go(ctx, "TabletManager."+name, args, reply, nil) select { case <-ctx.Done(): return fmt.Errorf("Timeout waiting for TabletManager.%v to %v", name, tablet.Alias) case <-call.Done: if call.Error != nil { return fmt.Errorf("Remote error for %v: %v", tablet.Alias, call.Error.Error()) } else { return nil } } }
func Recv(ctx context.Context, errc chan<- error, sysfd int, tcpconn *net.TCPConn) (reqc chan *Request) { reqc = make(chan *Request, 10) // TODO(zog): is 10 a good number? go func() { defer func() { glog.Infof("Recv is stoped") }() var req *Request var err error for { select { case <-ctx.Done(): glog.Infof("Done for Recv") return default: if req, err = recv(tcpconn); err != nil { errc <- fmt.Errorf("in Recv: %s", err) return } reqc <- req } } }() return reqc }
func Send(ctx context.Context, errc chan<- error, sysfd int, tcpconn *net.TCPConn) (rspc chan *Response) { rspc = make(chan *Response, 10) // TODO(zog): is 10 a good number? go func() { defer func() { glog.Infof("Send is stoped") }() for { select { case <-ctx.Done(): glog.Infof("Done for Send") return case rsp := <-rspc: if err := send(tcpconn, rsp); err != nil { errc <- fmt.Errorf("in Send: %s", err) return } } } }() return rspc }
func Work(ctx context.Context, errc chan<- error, sysfd int, reqc <-chan *Request, inreqc <-chan *Request, rspc chan<- *Response) { go func() { defer func() { glog.Infof("Work is stoped") }() for { var rsp *Response var err error select { case <-ctx.Done(): glog.Infof("Done for Work") return case req := <-reqc: if rsp, err = work(req); err != nil { errc <- fmt.Errorf("in Work req channel: %s", err) return } rspc <- rsp case req := <-inreqc: var rsp *Response if rsp, err = work(req); err != nil { errc <- fmt.Errorf("in Work inner req channel: %s", err) return } rspc <- rsp } } }() }
// newGateway does all the gateway initialisation once the gateway name is known func (g *Gateway) newGateway(ctx context.Context, certificateFile, keyFile string) (*Gateway, error) { gips, err := lookupGateway(g.gateway) if nil != err { return nil, err } ipMap := map[string]int8{} for _, ip := range gips { ipMap[ip] = 0 } g.gips = ips{ipMap: ipMap} g.errors = make(chan *PushNotificationRequestResponse) g.senders = []*Sender{} // TODO GSE: Enable the possibilty to choose the number of senders err = g.newSender(ctx, certificateFile, keyFile) if err != nil { return nil, err } go func() { for { select { case <-ctx.Done(): return case pnrr := <-g.errors: if g.onError != nil { go g.onError(pnrr.Notification, pnrr.Response) } } } }() return g, nil }
func transmitter(id string, ws *websocket.Conn, c chan *registrar.T, ctx context.Context, cancel context.CancelFunc) { var err error var data *registrar.T defer ws.Close() //defer close(c) defer cancel() defer registrar.RemoveConnection(id) Loop: for { select { case data = <-c: err = websocket.JSON.Send(ws, *data) //websocket.Message.Send(ws, data.Msg) if err != nil { if !ws.IsClientConn() { log.Printf("transmitter closed\n") } else { log.Printf("transmitter error %v\n", err) } break Loop } case <-ctx.Done(): log.Printf("transmitter closed") break Loop } } }
// Send sends push notification to the APNs. func (c *PersistentClient) Send(ctx context.Context, pn *PushNotification) *PushNotificationResponse { resp := NewPushNotificationResponse(pn) payload, err := pn.ToBytes() if err != nil { resp.Success = false resp.Error = err return resp } _, err = c.Write(payload) if err != nil { resp.Success = false resp.ResponseCommand = LocalResponseCommand resp.ResponseStatus = RetryPushNotificationStatus resp.Error = err return resp } log.Println("Sending push notification with ID", pn.Identifier) // This channel will contain the raw response // from Apple in the event of a failure. responseChannel := make(chan []byte, 1) go func() { buffer := make([]byte, 6) n, err := c.Read(buffer) if n != 6 && err != nil { buffer[0] = LocalResponseCommand e, ok := err.(net.Error) switch { case err == io.EOF: // Socket has been closed buffer[1] = RetryPushNotificationStatus case ok && e.Timeout(): // There is an error and it is a timeout buffer[1] = NoErrorsStatus default: buffer[1] = UnknownErrorStatus } } responseChannel <- buffer }() select { case <-ctx.Done(): <-responseChannel // Wait for the read to end. resp.Success = false resp.ResponseCommand = LocalResponseCommand resp.ResponseStatus = CanceledPushNotificationStatus resp.Error = ctx.Err() case r := <-responseChannel: resp.FromRawAppleResponse(r) } return resp }
// WithContext constructs and returns a Process that respects // given context. It is the equivalent of: // // func ProcessWithContext(ctx context.Context) goprocess.Process { // p := goprocess.WithParent(goprocess.Background()) // go func() { // <-ctx.Done() // p.Close() // }() // return p // } // func WithContext(ctx context.Context) goprocess.Process { if ctx == nil { panic("nil Context") } p := goprocess.WithParent(goprocess.Background()) go func() { <-ctx.Done() p.Close() }() return p }
// httpDo issues the HTTP request and calls f with the response. If ctx.Done is // closed while the request or f is running, httpDo cancels the request, waits // for f to exit, and returns ctx.Err. Otherwise, httpDo returns f's error. func httpDo(ctx context.Context, req *http.Request, f func(*http.Response, error) error) error { // Run the HTTP request in a goroutine and pass the response to f. tr := &http.Transport{} client := &http.Client{Transport: tr} c := make(chan error, 1) go func() { c <- f(client.Do(req)) }() select { case <-ctx.Done(): tr.CancelRequest(req) <-c // Wait for f to return. return ctx.Err() case err := <-c: return err } }
func main() { var server string var ( ctx context.Context cancel context.CancelFunc ) ctx, cancel = context.WithCancel(context.Background()) runtime.GOMAXPROCS(1) server = os.Args[1] id := os.Args[2] LogConditional(printLog, fmt.Printf, "Client Id %s\n", id) //fmt.Printf("Client Id %s\n", id) var headers http.Header = make(http.Header) headers.Add("X-Client-ID", id) var srvurl = "ws://173.39.210.210:8080/echo/" origin = fmt.Sprintf("http://%s/", server) srvurl = fmt.Sprintf("ws://%s:8080/echo/?id=%s", server, id) u, err := url.Parse(srvurl) o, err := url.Parse(origin) ws, err := websocket.DialConfig(&websocket.Config{Location: u, Header: headers, Origin: o, Version: 13}) if err != nil { log.Fatal(err) } c := make(chan []byte) go collectdTcp(cancel, c) go collectSyslog(c) go writer(ws, id, c) //go reader(ws, id) select { case <-ctx.Done(): } }
func main() { var server string runtime.GOMAXPROCS(1) R = *new(responses) R.waiting = make(map[int64]response) rand.Seed(time.Now().UnixNano()) var ( ctx context.Context ) ctx, _ = context.WithCancel(context.Background()) server = os.Args[1] id := os.Args[2] printLog = (os.Args[3] == "1") fmt.Sscanf(os.Args[4], "%d", &loopCount) LogConditional(printLog, fmt.Printf, "Client Id %s\n", id) //fmt.Printf("Client Id %s\n", id) var headers http.Header = make(http.Header) headers.Add("X-Client-ID", id) var srvurl = "ws://173.39.210.210:8080/echo/" origin = fmt.Sprintf("http://%s/", server) srvurl = fmt.Sprintf("ws://%s:8080/echo/?id=%s", server, id) u, err := url.Parse(srvurl) o, err := url.Parse(origin) ws, err := websocket.DialConfig(&websocket.Config{Location: u, Header: headers, Origin: o, Version: 13}) if err != nil { log.Fatal(err) } go writer(ws, id) go reader(ws, id) select { case <-ctx.Done(): } }
// Listen will handle connections on given port. // Listen will return upon cancellation of context. func Listen(ctx context.Context, port string, handle Handler) error { ln, err := net.Listen("tcp", port) if err != nil { return err } // Stop accepting connections upon cancellation. go func() { <-ctx.Done() ln.Close() }() for { conn, err := ln.Accept() if err != nil { select { case <-ctx.Done(): // No error because the server has been intentionally cancelled. return nil default: log.Error(err) continue // TODO should this continue? } } // Create a connection specific logger. l := log.WithFields(log.Fields{ "remote": conn.RemoteAddr(), }) ctx := tcplog.NewContext(ctx, l) go func() { l.Debugf("handling connection") err := handle(ctx, conn) if err != nil { l.Error(err) } // Close the connection once the handler has returned. conn.Close() }() } }
func Update(ctx context.Context, errc chan<- error, sysfd int, rspc chan<- *Response) { go func() { defer func() { glog.Infof("Update is stoped") }() for { select { case <-ctx.Done(): glog.Infof("Done for Update") return default: if err := update(sysfd, rspc); err != nil { errc <- fmt.Errorf("in Update: %s", err) return } } } }() }
// redial continually connects to the URL, exiting the program when no longer possible func redial(ctx context.Context, url string) chan chan session { sessions := make(chan chan session) go func() { sess := make(chan session) defer close(sessions) for { select { case sessions <- sess: case <-ctx.Done(): log.Println("shutting down session factory") return } conn, err := amqp.Dial(url) if err != nil { log.Fatalf("cannot (re)dial: %v: %q", err, url) } ch, err := conn.Channel() if err != nil { log.Fatalf("cannot create channel: %v", err) } if err := ch.ExchangeDeclare(exchange, "fanout", false, true, false, false, nil); err != nil { log.Fatalf("cannot declare fanout exchange: %v", err) } select { case sess <- session{conn, ch}: case <-ctx.Done(): log.Println("shutting down new session") return } } }() return sessions }
// Call sends the request, waits for it to complete, and returns its error status. func (client *Client) Call(ctx context.Context, req proto.Message, resp proto.Message) error { // Setup a new call call := &Call{ Req: req, Resp: resp, cancelc: make(chan interface{}), } // Make sure a service name is passed if serviceName, ok := ServiceNameFromContext(ctx); !ok { return ErrServiceNameMissing } else { call.Service = serviceName } // If a manual deadline is not passed, setup with default timeout if _, ok := ctx.Deadline(); !ok { ctx, _ = context.WithDeadline(ctx, time.Now().Add(RequestTimeout)) } // Run the request in a goroutine and write the reponse to c c := make(chan error, 1) go func() { c <- client.send(ctx, call) }() select { // Use context done to manually trigger cancel case <-ctx.Done(): // Cancel the request in flight call.cancelc <- true <-c // Wait for the request to finish if ctx.Err() == context.DeadlineExceeded { return ErrTimeout } return ctx.Err() // Request finished case err := <-c: return err } }
/*! * Get the next job to run, after sleeping until the time it's supposed * to run. * * @return The next job to run, or nil if the context has been canceled. */ func (jq *JobQueue) Pop(now time.Time, ctx context.Context) *Job { if jq.Empty() { // just wait till the context has been canceled <-ctx.Done() return nil } else { // get next-scheduled job job := heap.Pop(&jq.q).(*Job) // sleep till it's time to run it if now.Before(*job.NextRunTime) { afterChan := time.After(job.NextRunTime.Sub(now)) select { case now = <-afterChan: case <-ctx.Done(): // abort! heap.Push(&jq.q, job) return nil } } // schedule this job's next run job.NextRunTime = nextRunTime(job, now.Add(time.Second)) if job.NextRunTime != nil { heap.Push(&jq.q, job) } // decide whether we really should run this job if job.ShouldRun() { return job } else { // skip this job return jq.Pop(now, ctx) } } }
func (s *Sender) senderJob(ctx context.Context) { ticker := time.Tick(time.Second) for { select { case <-ctx.Done(): if s.conn != nil { s.conn.Close() } s.prioNotifc.Close() return case ev := <-s.readc: s.handleRead(ev) case pn := <-s.prioNotifc.Receive(): log.Printf("Sending notification %v", pn.Identifier) s.doSend(pn) case <-ticker: if s.conn != nil { s.conn.Expire() } } } }