lookup_peer.go
package nsqd
import (
"encoding/binary"
"fmt"
"io"
"net"
"time"
"github.com/nsqio/go-nsq"
)
// lookupPeer is a low-level type for connecting/reading/writing to nsqlookupd
//
// A lookupPeer instance is designed to connect lazily to nsqlookupd and reconnect
// gracefully (i.e. it is all handled by the library). Clients can simply use the
// Command interface to perform a round-trip.
type lookupPeer struct {
l Logger
addr string
conn net.Conn
state int32
connectCallback func(*lookupPeer)
maxBodySize int64
Info peerInfo
}
// peerInfo contains metadata for a lookupPeer instance (and is JSON marshalable)
type peerInfo struct {
TCPPort int `json:"tcp_port"`
HTTPPort int `json:"http_port"`
Version string `json:"version"`
BroadcastAddress string `json:"broadcast_address"`
}
// newLookupPeer creates a new lookupPeer instance connecting to the supplied address.
//
// The supplied connectCallback will be called *every* time the instance connects.
func newLookupPeer(addr string, maxBodySize int64, l Logger, connectCallback func(*lookupPeer)) *lookupPeer {
return &lookupPeer{
l: l,
addr: addr,
state: stateDisconnected,
maxBodySize: maxBodySize,
connectCallback: connectCallback,
}
}
// Connect will Dial the specified address, with timeouts
func (lp *lookupPeer) Connect() error {
lp.l.Output(2, fmt.Sprintf("LOOKUP connecting to %s", lp.addr))
conn, err := net.DialTimeout("tcp", lp.addr, time.Second)
if err != nil {
return err
}
lp.conn = conn
return nil
}
// String returns the specified address
func (lp *lookupPeer) String() string {
return lp.addr
}
// Read implements the io.Reader interface, adding deadlines
func (lp *lookupPeer) Read(data []byte) (int, error) {
lp.conn.SetReadDeadline(time.Now().Add(time.Second))
return lp.conn.Read(data)
}
// Write implements the io.Writer interface, adding deadlines
func (lp *lookupPeer) Write(data []byte) (int, error) {
lp.conn.SetWriteDeadline(time.Now().Add(time.Second))
return lp.conn.Write(data)
}
// Close implements the io.Closer interface
func (lp *lookupPeer) Close() error {
lp.state = stateDisconnected
if lp.conn != nil {
return lp.conn.Close()
}
return nil
}
// Command performs a round-trip for the specified Command.
//
// It will lazily connect to nsqlookupd and gracefully handle
// reconnecting in the event of a failure.
//
// It returns the response from nsqlookupd as []byte
func (lp *lookupPeer) Command(cmd *nsq.Command) ([]byte, error) {
initialState := lp.state
if lp.state != stateConnected {
err := lp.Connect()
if err != nil {
return nil, err
}
lp.state = stateConnected
lp.Write(nsq.MagicV1)
if initialState == stateDisconnected {
lp.connectCallback(lp)
}
}
if cmd == nil {
return nil, nil
}
_, err := cmd.WriteTo(lp)
if err != nil {
lp.Close()
return nil, err
}
resp, err := readResponseBounded(lp, lp.maxBodySize)
if err != nil {
lp.Close()
return nil, err
}
return resp, nil
}
func readResponseBounded(r io.Reader, limit int64) ([]byte, error) {
var msgSize int32
// message size
err := binary.Read(r, binary.BigEndian, &msgSize)
if err != nil {
return nil, err
}
if int64(msgSize) > limit {
return nil, fmt.Errorf("response body size (%d) is greater than limit (%d)",
msgSize, limit)
}
// message binary data
buf := make([]byte, msgSize)
_, err = io.ReadFull(r, buf)
if err != nil {
return nil, err
}
return buf, nil
}
lookup_peer.go的更多相关文章
随机推荐
- JSP 分页显示数据 (Oracle)
要实现分页,首先我们要做的就是如何来编写SQL语句,网上也有很多,大家可以搜一下.在这里,我们使用一种比较常用的方式来编写SQL语句.代码如下: ----分页显示 select * from (sel ...
- 《MySQL必知必会》读书笔记_2
通配符:(尾空格可能会干扰通配符匹配) % 匹配任意字符 _ 匹配任意单个字符 正则表达式:REGEXP 用法就是替换掉LIKE的位置,后面配合正则表达式. 默认不区分大小写,如果区分的话添加关键字B ...
- Linux常用资源(不断改进中)
Linux常用命令全集: http://linux.chinaitlab.com/special/linuxcom/Index.html ubuntu 12.04 配置指南: http://www. ...
- log4j2.xml全配置文件
可以参考如下配置 <?xml version="1.0" encoding="UTF-8"?> <!--日志级别以及优先级排序: OFF &g ...
- asp.net MVC 框架中控制器里使用Newtonsoft.Json对前端传过来的字符串进行解析
下面我用一个实例来和大家分享一下我的经验,asp.net MVC 框架中控制器里使用Newtonsoft.Json对前端传过来的字符串进行解析. using Newtonsoft.Json; usin ...
- Android 开发知识体系
知识体系 1.Unix/Linux平台技术:基本命令,Linux下的开发环境 2.企业级数据库技术:SQL语言.SQL语句调优.Oracle数据库技术 3.Java 语言核心技术:Java语言基础.J ...
- django项目部署上线
前言 完善的django项目上线,有很多种上线的方法,比如apache, uwsgi, nginx等.这里只介绍2种,一种是django自带的,另外一种则是nginx + uwsgi完成介绍.这里的系 ...
- hdu-3071 Gcd & Lcm game---质因数分解+状态压缩+线段树
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=3071 题目大意: 给定一个长度为n的序列m次操作,操作的种类一共有三种 查询 L :查询一个区间的所 ...
- .NET之EntityFramework框架运用
1.创建EF模型库 创建类库-->添加新建项-->选择ADO.NET实体数据模型-->选择 来自数据库的EF选择器-->配置数据库链接以及相应的数据库-->看底部(将ap ...
- 在Visual Studio中使用Debug Visualizers在C++中实现对原始类的自定义调试信息显示
在Visual Studio中使用Debug Visualizers在C++中实现对原始类的自定义调试信息显示 当我们在VS的C++中使用vector.list.map等这些STL容器,在开启调试的时 ...