// Dequeue is used to perform a blocking dequeue func (b *EvalBroker) Dequeue(schedulers []string, timeout time.Duration) (*structs.Evaluation, string, error) { var timeoutTimer *time.Timer var timeoutCh <-chan time.Time SCAN: // Scan for work eval, token, err := b.scanForSchedulers(schedulers) if err != nil { if timeoutTimer != nil { timeoutTimer.Stop() } return nil, "", err } // Check if we have something if eval != nil { if timeoutTimer != nil { timeoutTimer.Stop() } return eval, token, nil } // Setup the timeout channel the first time around if timeoutTimer == nil && timeout != 0 { timeoutTimer = time.NewTimer(timeout) timeoutCh = timeoutTimer.C } // Block until we get work scan := b.waitForSchedulers(schedulers, timeoutCh) if scan { goto SCAN } return nil, "", nil }
func (log *Log) Watch(last int64, expire time.Duration) int64 { expired := false var timer *time.Timer cv := sync.NewCond(&log.mx) if expire > 0 { timer = time.AfterFunc(expire, func() { log.lock() expired = true cv.Broadcast() log.unlock() }) } else { expired = true } log.lock() log.cvs[cv] = true for { if log.id != last || expired { break } cv.Wait() } delete(log.cvs, cv) if log.id != last { last = log.id } log.unlock() if timer != nil { timer.Stop() } return last }
// execute some action in the context of the current process. Actions // executed via this func are to be executed in a concurrency-safe manner: // no two actions should execute at the same time. invocations of this func // should not block for very long, unless the action backlog is full or the // process is terminating. // returns errProcessTerminated if the process already ended. func (self *procImpl) doLater(deferredAction Action) (err <-chan error) { a := Action(func() { self.wg.Add(1) defer self.wg.Done() deferredAction() }) scheduled := false self.writeLock.Lock() defer self.writeLock.Unlock() var timer *time.Timer for err == nil && !scheduled { switch s := self.state.get(); s { case stateRunning: select { case self.backlog <- a: scheduled = true default: if timer == nil { timer = time.AfterFunc(self.maxRescheduleWait, self.changed.Broadcast) } else { timer.Reset(self.maxRescheduleWait) } self.changed.Wait() timer.Stop() } case stateTerminal: err = ErrorChan(errProcessTerminated) default: err = ErrorChan(errIllegalState) } } return }
// fillBatch coalesces individual log lines into batches. Delivery of the // batch happens on timeout after at least one message is received // or when the batch is full. // returns the channel status, completed batch func (b Batcher) fillBatch() (bool, Batch) { batch := NewBatch(b.batchSize) timeout := new(time.Timer) // start with a nil channel and no timeout for { select { case <-timeout.C: return false, batch case line, chanOpen := <-b.inLogs: // if the channel is closed, then line will be a zero value Line, so just // return the batch and signal shutdown if !chanOpen { return true, batch } // Set a timeout if we don't have one if timeout.C == nil { defer func(t time.Time) { b.fillTime.UpdateSince(t) }(time.Now()) timeout = time.NewTimer(b.timeout) defer timeout.Stop() // ensure timer is stopped when done } if full := batch.Add(line); full { return false, batch } } } }
func (p *Process) Stop() { p.lock.Lock() p.stopped = true if proc := p.process; proc != nil { var timer *time.Timer p.shutdown() if p.stopTime > 0 { timer = time.AfterFunc(p.stopTime, func() { p.logger.Printf("Graceful shutdown timed out") p.lock.Lock() p.kill() p.lock.Unlock() }) } p.lock.Unlock() p.waiter.Wait() p.lock.Lock() if timer != nil { timer.Stop() } } p.process = nil p.lock.Unlock() }
// Reset a timer - Doesn't work properly < go 1.1 // // This is quite hard to do properly under go < 1.1 so we do a crude // approximation and hope that everyone upgrades to go 1.1 quickly func resetTimer(t *time.Timer, d time.Duration) { t.Stop() // Very likely this doesn't actually work if we are already // selecting on t.C. However we've stopped the original timer // so won't break transfers but may not time them out :-( *t = *time.NewTimer(d) }
// timedDecoder returns a Decorated decoder that generates the given error if no events // are decoded for some number of sequential timeouts. The returned Decoder is not safe // to share across goroutines. // TODO(jdef) this probably isn't the right place for all of this logic (and it's not // just monitoring the heartbeat messages, it's counting all of them..). Heartbeat monitoring // has specific requirements. Get rid of this and implement something better elsewhere. func timedDecoder(dec records.Decoder, dur time.Duration, timeouts int, err error) records.Decoder { var t *time.Timer return records.DecoderFunc(func(v interface{}) error { if t == nil { t = time.NewTimer(dur) } else { t.Reset(dur) } defer t.Stop() errCh := make(chan error, 1) go func() { // there's no way to abort this so someone else will have // to make sure that it dies (and it should if the response // body is closed) errCh <- dec.Decode(v) }() for x := 0; x < timeouts; x++ { select { case <-t.C: // check for a tie select { case e := <-errCh: return e default: // noop, continue } case e := <-errCh: return e } } return err }) }
// fillBatch coalesces individual log lines into batches. Delivery of the // batch happens on timeout after at least one message is received // or when the batch is full. // returns the channel status, completed batch func (batcher Batcher) fillBatch() (bool, Batch) { batch := NewBatch(batcher.batchSize) // Make a batch timeout := new(time.Timer) // Gives us a nil channel and no timeout to start with chanOpen := true // Assume the channel is open count := 0 for { select { case <-timeout.C: return !chanOpen, batch case line, chanOpen := <-batcher.inLogs: if !chanOpen { return !chanOpen, batch } // We have a line now, so set a timeout if timeout.C == nil { defer func(t time.Time) { batcher.stats <- NewNamedValue("batch.fill.time", time.Since(t).Seconds()) }(time.Now()) timeout = time.NewTimer(batcher.timeout) defer timeout.Stop() // ensure timer is stopped when done } batch.Add(line) count += 1 if count >= batcher.batchSize { return !chanOpen, batch } } } }
// watchSerial monitors for a change in a specific serial number. It returns // the new serial number when it changes. If the serial number has not // changed in the given duration then the old value is returned. A poll // can be done by supplying 0 for the expiration. func (m *Manager) watchSerial(old int64, src *int64, expire time.Duration) int64 { expired := false cv := sync.NewCond(&m.mx) var timer *time.Timer var rv int64 // Schedule timeout if expire > 0 { timer = time.AfterFunc(expire, func() { m.lock() expired = true cv.Broadcast() m.unlock() }) } else { expired = true } m.lock() m.cvs[cv] = true for { rv = *src if rv != old || expired { break } cv.Wait() } delete(m.cvs, cv) m.unlock() if timer != nil { timer.Stop() } return rv }
// blockingRPC is used for queries that need to wait for a // minimum index. This is used to block and wait for changes. func (s *Server) blockingRPC(opts *blockingOptions) error { var timeout *time.Timer var notifyCh chan struct{} var state *state.StateStore // Fast path non-blocking if opts.queryOpts.MinQueryIndex == 0 { goto RUN_QUERY } // Restrict the max query time, and ensure there is always one if opts.queryOpts.MaxQueryTime > maxQueryTime { opts.queryOpts.MaxQueryTime = maxQueryTime } else if opts.queryOpts.MaxQueryTime <= 0 { opts.queryOpts.MaxQueryTime = defaultQueryTime } // Apply a small amount of jitter to the request opts.queryOpts.MaxQueryTime += randomStagger(opts.queryOpts.MaxQueryTime / jitterFraction) // Setup a query timeout timeout = time.NewTimer(opts.queryOpts.MaxQueryTime) // Setup the notify channel notifyCh = make(chan struct{}, 1) // Ensure we tear down any watchers on return state = s.fsm.State() defer func() { timeout.Stop() if opts.allocWatch != "" { state.StopWatchAllocs(opts.allocWatch, notifyCh) } }() REGISTER_NOTIFY: // Register the notification channel. This may be done // multiple times if we have not reached the target wait index. if opts.allocWatch != "" { state.WatchAllocs(opts.allocWatch, notifyCh) } RUN_QUERY: // Update the query meta data s.setQueryMeta(opts.queryMeta) // Run the query function metrics.IncrCounter([]string{"nomad", "rpc", "query"}, 1) err := opts.run() // Check for minimum query time if err == nil && opts.queryMeta.Index > 0 && opts.queryMeta.Index <= opts.queryOpts.MinQueryIndex { select { case <-notifyCh: goto REGISTER_NOTIFY case <-timeout.C: } } return err }
func releaseTimer(t *time.Timer, wasRead bool) { stopped := t.Stop() if !wasRead && !stopped { <-t.C } timerPool.Put(t) }
func process_action(ac chan action, sv *server) { var a action var timer *time.Timer ch := make(chan bool, 2) defer func() { if timer != nil { timer.Stop() } sv.lock.Lock() delete(sv.kt, a.key) close(ac) sv.lock.Unlock() close(ch) }() for { select { case a = <-ac: if timer != nil { timer.Stop() } timer = time.AfterFunc(a.exptime, func() { sv.s.db.Delete([]byte(a.key), sv.s.wo) ch <- true }) case <-ch: relog.Info("delete successed") return } } }
// fillBatch coalesces individual log lines into batches. Delivery of the // batch happens on timeout after at least one message is received // or when the batch is full. func (batcher *Batcher) fillBatch(batch *Batch) (chanOpen bool) { timeout := new(time.Timer) // Gives us a nil channel and no timeout to start with chanOpen = true // Assume the channel is open for { select { case <-timeout.C: return !chanOpen case line, chanOpen := <-batcher.inLogs: if !chanOpen { return !chanOpen } // We have a line now, so set a timeout if timeout.C == nil { defer func(t time.Time) { batcher.stats <- NewNamedValue("batch.fill.time", time.Since(t).Seconds()) }(time.Now()) timeout = time.NewTimer(batcher.timeout) defer timeout.Stop() // ensure timer is stopped when done } batch.Write(line) if batch.Full() { return !chanOpen } } } }
// GetDuplicates returns all the duplicate evaluations and blocks until the // passed timeout. func (b *BlockedEvals) GetDuplicates(timeout time.Duration) []*structs.Evaluation { var timeoutTimer *time.Timer var timeoutCh <-chan time.Time SCAN: b.l.Lock() if len(b.duplicates) != 0 { dups := b.duplicates b.duplicates = nil b.l.Unlock() return dups } b.l.Unlock() // Create the timer if timeoutTimer == nil && timeout != 0 { timeoutTimer = time.NewTimer(timeout) timeoutCh = timeoutTimer.C defer timeoutTimer.Stop() } select { case <-b.stopCh: return nil case <-timeoutCh: return nil case <-b.duplicateCh: goto SCAN } }
func (r repository) clone(schema string) error { cmd := exec.Command( "git", "clone", "--depth=1", "-b", r.params.version, r.cloneURL(schema), ) cmd.Dir = r.dir var stdout bytes.Buffer var stderr bytes.Buffer cmd.Stdout = &stdout cmd.Stderr = &stderr err := cmd.Start() if err != nil { r.logger.WithFields(log.Fields{"command": cmd.Path, "args": cmd.Args, "stdout": stdout.String(), "stderr": stderr.String()}).Warnf("git clone error: %v", err) return err } // kill process if token is invalid (wait password) var timer *time.Timer timer = time.AfterFunc(30*time.Second, func() { cmd.Process.Kill() }) err = cmd.Wait() if err != nil { r.logger.WithFields(log.Fields{"command": cmd.Path, "args": cmd.Args, "stdout": stdout.String(), "stderr": stderr.String()}).Warnf("git clone error: %v", err) return err } timer.Stop() r.logger.WithFields(log.Fields{"command": cmd.Path, "args": cmd.Args, "stdout": stdout.String(), "stderr": stderr.String()}).Info("git clone successfully") return err }
func (r repository) listRemote() error { cmd := exec.Command( "git", "ls-remote", r.cloneURL("https"), "HEAD", ) cmd.Dir = r.dir err := cmd.Start() if err != nil { return err } // kill process if token is invalid (wait password) var timer *time.Timer timer = time.AfterFunc(5*time.Second, func() { cmd.Process.Kill() }) err = cmd.Wait() if err != nil { return err } timer.Stop() return err }
// Read is used to read from the stream func (s *Stream) Read(b []byte) (n int, err error) { var bufsiz int defer asyncNotify(s.recvNotifyCh) START: s.stateLock.Lock() switch s.state { case streamLocalClose: fallthrough case streamRemoteClose: fallthrough case streamClosed: s.recvLock.Lock() if s.recvBuf == nil || s.recvBuf.Len() == 0 { s.recvLock.Unlock() s.stateLock.Unlock() return 0, io.EOF } s.recvLock.Unlock() case streamReset: s.stateLock.Unlock() return 0, ErrConnectionReset } s.stateLock.Unlock() // If there is no data available, block s.recvLock.Lock() if s.recvBuf == nil || s.recvBuf.Len() == 0 { s.recvLock.Unlock() goto WAIT } // Read any bytes n, _ = s.recvBuf.Read(b) bufsiz = s.recvBuf.Len() s.recvLock.Unlock() // Send a window update potentially if uint32(bufsiz)+atomic.LoadUint32(&s.recvWindow) < s.session.config.MaxStreamWindowSize { err = s.sendWindowUpdate() } return n, err WAIT: var timeout <-chan time.Time var timer *time.Timer if !s.readDeadline.IsZero() { delay := s.readDeadline.Sub(time.Now()) timer = time.NewTimer(delay) timeout = timer.C } select { case <-s.recvNotifyCh: if timer != nil { timer.Stop() } goto START case <-timeout: return 0, ErrTimeout } }
func process(cmd *Command) { var timer *time.Timer var err error log.Print(cmd.Command) sp := exec.Command("sh", "-c", cmd.Command) sp.Stdout = os.Stdout sp.Stderr = os.Stderr if err = sp.Start(); err != nil { log.Printf("%s failed: %s", err.Error(), cmd.Command) return } if cmd.Timeout > 0 { timer = time.AfterFunc(time.Duration(cmd.Timeout)*time.Second, func() { timer = nil if sp.ProcessState == nil { sp.Process.Kill() } }) } err = sp.Wait() if timer != nil { timer.Stop() } if err != nil { log.Printf("%s failed: %s", err.Error(), cmd.Command) } }
func (t *Transport) tries(req *http.Request, try uint) (*http.Response, error) { startTime := time.Now() var timer *time.Timer rCancler := make(chan struct{}) req.Cancel = rCancler if t.RequestTimeout != 0 { timer = time.AfterFunc(t.RequestTimeout, func() { //t.CancelRequest(req) t.startOnce.Do(t.start) if bc, ok := req.Body.(*bodyCloser); ok { bc.timer.Stop() } close(rCancler) t.transport.CancelRequest(req) }) } res, err := t.transport.RoundTrip(req) headerTime := time.Now() if err != nil { if timer != nil { timer.Stop() } var stats *Stats if t.Stats != nil { stats = &Stats{ Request: req, Response: res, Error: err, } stats.Duration.Header = headerTime.Sub(startTime) stats.Retry.Count = try } if try < t.MaxTries && req.Method == "GET" && t.shouldRetryError(err) { if t.Stats != nil { stats.Retry.Pending = true t.Stats(stats) } return t.tries(req, try+1) } if t.Stats != nil { t.Stats(stats) } return nil, err } res.Body = &bodyCloser{ ReadCloser: res.Body, timer: timer, res: res, transport: t, startTime: startTime, headerTime: headerTime, } return res, nil }
func (m *Monitor) Run() { // catch interrupt signal userInterrupt := make(chan os.Signal, 1) signal.Notify(userInterrupt, os.Interrupt) stats := &Stats{} stats.responseTimeData = make([]time.Duration, 0, m.c.config.requests) var timelimit time.Timer if m.c.config.timelimit > 0 { timelimit = *time.NewTimer(time.Duration(m.c.config.timelimit) * time.Second) } defer timelimit.Stop() // waiting for all of http workers to start m.c.start.Wait() fmt.Printf("Benchmarking %s (be patient)\n", m.c.config.host) sw := &StopWatch{} sw.Start() loop: for { select { case record := <-m.collector: updateStats(stats, record) if record.Error != nil && !ContinueOnError { break loop } if stats.totalRequests >= 10 && stats.totalRequests%(m.c.config.requests/10) == 0 { fmt.Printf("Completed %d requests\n", stats.totalRequests) } if stats.totalRequests == m.c.config.requests { fmt.Printf("Finished %d requests\n", stats.totalRequests) break loop } case <-timelimit.C: break loop case <-userInterrupt: break loop } } sw.Stop() stats.totalExecutionTime = sw.Elapsed // shutdown benchmark and all of httpworkers to stop close(m.c.stop) signal.Stop(userInterrupt) m.output <- stats }
func stopTimer(t *time.Timer) { if !t.Stop() { // Collect possibly added time from the channel // if timer has been stopped and nobody collected its' value. select { case <-t.C: default: } } }
func stopTimer(timer *time.Timer) { if timer.Stop() { return } select { case <-timer.C: default: } }
// getTimer returns an expire timer or a 5s timer. func getTimer(expired bool) *time.Timer { var timer *time.Timer if expired { timer = time.NewTimer(0) timer.Stop() } else { timer = time.NewTimer(5 * time.Second) } return timer }
func (dms *DiskMetricStore) loop(persistenceInterval time.Duration) { lastPersist := time.Now() persistScheduled := false lastWrite := time.Time{} persistDone := make(chan time.Time) var persistTimer *time.Timer checkPersist := func() { if !persistScheduled && lastWrite.After(lastPersist) { persistTimer = time.AfterFunc( persistenceInterval-lastWrite.Sub(lastPersist), func() { persistStarted := time.Now() if err := dms.persist(); err != nil { log.Print("Error persisting metrics: ", err) } else { log.Printf( "Metrics persisted to '%s'.", dms.persistenceFile, ) } persistDone <- persistStarted }, ) persistScheduled = true } } for { select { case wr := <-dms.writeQueue: dms.processWriteRequest(wr) lastWrite = time.Now() checkPersist() case lastPersist = <-persistDone: persistScheduled = false checkPersist() // In case something has been written in the meantime. case <-dms.drain: // Prevent a scheduled persist from firing later. if persistTimer != nil { persistTimer.Stop() } // Now draining... for { select { case wr := <-dms.writeQueue: dms.processWriteRequest(wr) default: dms.done <- dms.persist() return } } } } }
func (c *Client) sendMsg(req *Request, sendType MsgSendType, addr string) *Response { bytes, err := proto.Marshal(req) if err != nil { log.Printf("proto.Marshal: %v\n", err) // return nil, errors.New("proto.Marshal(req):"+err.Error()) resp := NewRespByReq(req, "", Err_PROTO_MARSHAL) return resp } reqItem := &ClientRequestItem{Req: req, ReqChan: make(chan *Response)} c.rwLock.Lock() c.msgItems[req.GetTag()] = reqItem c.rwLock.Unlock() // log.Printf("sendMsg req: des: %v\n", req.String()) switch sendType { case kMsgSendToAll: c.clients.SendAllConns(bytes) case kMsgSendWithIp: c.clients.SendWithIp(addr, bytes) case kMsgSendWithHash: c.clients.SendByHash(addr, bytes) } var timer *time.Timer timer = time.AfterFunc(time.Second*3, func() { c.rwLock.Lock() defer c.rwLock.Unlock() delete(c.msgItems, req.GetTag()) resp := NewRespByReq(req, "", Err_TIME_OUT) reqItem.ReqChan <- resp //TODO: 超时的问题,当lib发现超时的消息,ser如果被堵塞,会接收到到,处理完返回给lib。这个时候就会数据不一致 //TODO: 需要在每个msgItem上加一个timestamp,ser接收到发现超时了就不操作。 //TODO: lib->ser , ser operation, ser->lib 超时 // log.Printf("ErrorCode: %v\n", resp.String()) }) //TODO:需要处理timeout resp := <-reqItem.ReqChan timer.Stop() //log.Printf("cliRecv: [%v : %v]\n", req.String(), resp.String()) if resp.GetErrCode() == Err_NOT_LEADER { //TODO: 需要延时在重发 } else if resp.GetErrCode() == Err_TIME_OUT { log.Printf("libError: \n%v\n%v\n", req.String(), resp.String()) return resp } return resp }
func main() { flag.Parse() config := buildConfig() logger := log.New(config.LogOutput, "", log.LstdFlags) node, err := onecache.Create(config) if err != nil { logger.Printf("[ERROR] onecache: could not create node: %v\n", err) os.Exit(1) } // Handle interupts. c := make(chan os.Signal, 1) signal.Notify(c, os.Interrupt) node.Start() if *join != "" { peerNodes := strings.Split(*join, ",") if err := node.Join(peerNodes); err != nil { logger.Printf("[ERROR] onecache: could not join peers %v: %v", peerNodes, err) node.Exit() return } } if *retry_join != "" { var retry *time.Timer retryNodes := strings.Split(*retry_join, ",") retry = time.AfterFunc(0, func() { if err := node.Join(retryNodes); err != nil { logger.Printf("[DEBUG] onecache: could not join peers %v: %v\n", retryNodes, err) logger.Printf("[DEBUG] onecache: retrying in %v", *retry_interval) retry.Reset(*retry_interval) } else { retry.Stop() } }) } if *pprofEnabled { go func() { logger.Println(http.ListenAndServe(fmt.Sprintf(":%d", *pprofPort), nil)) }() } // Exit the node upon an interupt. for range c { node.Exit() return } }
func (q *Reader) rdyLoop(c *nsqConn) { readyChan := c.readyChan var backoffTimer *time.Timer var backoffTimerChan <-chan time.Time for { select { case <-backoffTimerChan: log.Printf("[%s] backoff time expired, continuing with RDY 1...", c) // while in backoff only ever let 1 message at a time through q.updateRDY(c, 1) readyChan = c.readyChan case <-readyChan: backoffCounter := atomic.LoadInt32(&c.backoffCounter) // send ready immediately if backoffCounter == 0 || q.maxBackoffDuration == 0 { remain := atomic.LoadInt64(&c.rdyCount) lastRdyCount := atomic.LoadInt64(&c.lastRdyCount) count := q.ConnectionMaxInFlight() // refill when at 1, or at 25% whichever comes first if remain <= 1 || remain < (lastRdyCount/4) { if q.VerboseLogging { log.Printf("[%s] sending RDY %d (%d remain)", c, count, remain) } q.updateRDY(c, count) } else { if q.VerboseLogging { log.Printf("[%s] skip sending RDY (%d remain out of %d)", c, remain, lastRdyCount) } } continue } backoffDuration := q.backoffDuration(backoffCounter) backoffTimer = time.NewTimer(backoffDuration) backoffTimerChan = backoffTimer.C readyChan = nil log.Printf("[%s] backing off for %.02f seconds", c, backoffDuration.Seconds()) case <-c.exitChan: if backoffTimer != nil { backoffTimer.Stop() } goto exit } } exit: log.Printf("[%s] rdyLoop exiting", c) }
// Waits for the first change, on or after rev, to any file matching glob, // within the specific time expressed as time.Duration func (c *Conn) WaitTimeout(glob string, rev int64, timeout time.Duration) (ev Event, err error) { var timer *time.Timer if timeout > 0 { timer = time.AfterFunc(timeout, func() { c.err = ErrWaitTimeout c.stopped <- true }) } ev, err = c.Wait(glob, rev) if timer != nil { timer.Stop() } return }
func getFlushChan(t *time.Timer, flushDelay time.Duration) <-chan time.Time { if flushDelay <= 0 { return closedFlushChan } if !t.Stop() { // Exhaust expired timer's chan. select { case <-t.C: default: } } t.Reset(flushDelay) return t.C }
// Write attempts to flush the events to the downstream sink until it succeeds // or the sink is closed. func (rs *RetryingSink) Write(event Event) error { logger := logrus.WithField("event", event) var timer *time.Timer retry: select { case <-rs.closed: return ErrSinkClosed default: } if backoff := rs.strategy.Proceed(event); backoff > 0 { if timer == nil { timer = time.NewTimer(backoff) defer timer.Stop() } else { timer.Reset(backoff) } select { case <-timer.C: goto retry case <-rs.closed: return ErrSinkClosed } } if err := rs.sink.Write(event); err != nil { if err == ErrSinkClosed { // terminal! return err } logger := logger.WithError(err) // shadow!! if rs.strategy.Failure(event, err) { logger.Errorf("retryingsink: dropped event") return nil } logger.Errorf("retryingsink: error writing event, retrying") goto retry } rs.strategy.Success(event) return nil }