コード例 #1
0
ファイル: keeper.go プロジェクト: haoyixin/parkeeper
func (k *Keeper) sendLoop(t *tomb.Tomb) error {
	var timeout <-chan time.Time = nil
	for {
		select {
		case rep := <-k.sendChan:
			var buf []byte = k.alloc()
			defer k.free(buf)

			bytesWritten, err := EncodePacket(buf[4:], rep)
			if err != nil {
				return err
			}

			// write frame size
			binary.BigEndian.PutUint32(buf[:4], uint32(bytesWritten))

			// write buffer to connection
			_, err = k.conn.Write(buf[:4+bytesWritten])
			if err != nil {
				return err
			}

			// log output
			log.Debug("-> ", fmt.Sprintf("%x", buf[:4+bytesWritten]))
		case <-t.Dying():
			// create a timeout in order to send pending requests (close reply)
			if timeout == nil {
				timeout = time.After(100 * time.Millisecond)
			}
		case <-timeout:
			close(k.sendChan)
			return nil
		}
	}
}
コード例 #2
0
ファイル: keeper.go プロジェクト: haoyixin/parkeeper
func (k *Keeper) Close() {
	k.conn.Close()
	k.tomb.Kill(nil)
	err := k.tomb.Wait()
	if err != nil {
		log.Debug("closed due to: ", err)
	}
}
コード例 #3
0
ファイル: server.go プロジェクト: haoyixin/parkeeper
func (s *Server) Start() {
	laddr, err := net.ResolveTCPAddr("tcp", s.addr)
	if nil != err {
		log.Fatal(err)
	}
	listener, err := net.ListenTCP("tcp", laddr)
	if nil != err {
		log.Fatal(err)
	}
	log.Debug("listening on: ", listener.Addr())

	// Make a new service and send it into the background.
	go s.serve(listener)

	// Handle SIGINT and SIGTERM.
	ch := make(chan os.Signal)
	signal.Notify(ch, syscall.SIGINT, syscall.SIGTERM)
	log.Debug(<-ch)

	// Stop the service gracefully.
	s.Stop()
}
コード例 #4
0
ファイル: server.go プロジェクト: haoyixin/parkeeper
func (s *Server) serve(l *net.TCPListener) {
	defer s.waitGroup.Done()
	s.waitGroup.Add(1)
	for {
		select {
		case <-s.ch:
			log.Debug("stopping listening on: ", l.Addr())
			l.Close()
			return
		default:
		}

		l.SetDeadline(time.Now().Add(1e9))
		conn, err := l.AcceptTCP()
		if err != nil {
			if opErr, ok := err.(*net.OpError); ok && opErr.Timeout() {
				continue
			}
			log.Debug(err)
		}

		// handle the connection in a new goroutine. This returns to listener
		// accepting code so that multiple connections may be served concurrently.
		keeper := NewKeeper(conn, s.storeClient)

		go func() {
			defer s.waitGroup.Done()
			s.waitGroup.Add(1)
			log.Debug("client connected: ", conn.RemoteAddr())
			if err := keeper.Handle(); err != nil {
				log.Debug("client disconnected: ", conn.RemoteAddr(), " with error: ", err)
			} else {
				log.Debug("client disconnected: ", conn.RemoteAddr())
			}
		}()
	}
}
コード例 #5
0
ファイル: keeper.go プロジェクト: haoyixin/parkeeper
func (k *Keeper) recvLoop(t *tomb.Tomb) error {
	for {
		_, err := k.read(k.temp[:4])
		if err != nil {
			return err
		}

		// parse frame size
		len := binary.BigEndian.Uint32(k.temp[:4])
		if len > bufferSize {
			return errors.New(fmt.Sprintf("length should be at most %d bytes (received %d)", bufferSize, len))
		}

		// alloc buffer (freeing if full read from conn wasn't possible)
		var buf = k.alloc()
		defer k.free(buf)

		// read frame
		_, err = k.read(buf[:len])
		if err != nil {
			return err
		}

		// log input
		log.Debug("<- ", fmt.Sprintf("%x%x", k.temp[:4], buf[:len]))

		// send frame to channel
		select {
		case k.recvChan <- buf[:len]:
		case <-t.Dying():
			return nil
		}
	}

	return nil
}