示例#1
0
// 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
}
示例#2
0
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
}
示例#3
0
// 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
}
示例#4
0
// 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
			}
		}
	}
}
示例#5
0
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()
}
示例#6
0
// 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)
}
示例#7
0
// 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
	})
}
示例#8
0
// 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
			}
		}
	}
}
示例#9
0
// 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
}
示例#10
0
文件: rpc.go 项目: ranjib/nomad
// 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
}
示例#11
0
文件: bucket.go 项目: n8sabes/gocb
func releaseTimer(t *time.Timer, wasRead bool) {
	stopped := t.Stop()
	if !wasRead && !stopped {
		<-t.C
	}
	timerPool.Put(t)
}
示例#12
0
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
		}
	}
}
示例#13
0
// 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
			}
		}
	}
}
示例#14
0
// 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
	}
}
示例#15
0
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
}
示例#16
0
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
}
示例#17
0
文件: stream.go 项目: xtaci/yamux
// 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
	}
}
示例#18
0
文件: ggs.go 项目: sloonz/ua
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)
	}
}
示例#19
0
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
}
示例#20
0
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
}
示例#21
0
文件: timer.go 项目: cnhup/httpmq
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:
		}
	}
}
示例#22
0
func stopTimer(timer *time.Timer) {
	if timer.Stop() {
		return
	}

	select {
	case <-timer.C:
	default:
	}
}
示例#23
0
文件: q_test.go 项目: y0ssar1an/qq
// 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
}
示例#24
0
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
				}
			}
		}
	}
}
示例#25
0
文件: clientLib.go 项目: izouxv/raftX
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
}
示例#26
0
文件: main.go 项目: dadgar/onecache
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
	}
}
示例#27
0
文件: reader.go 项目: Eric-Chen/nsq
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)
}
示例#28
0
文件: conn.go 项目: ming-hai/doozer
// 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
}
示例#29
0
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
}
示例#30
0
// 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
}