示例#1
0
文件: dns.go 项目: badoo/thunder
func (r *resolver) resolveAndUpdate(item cacheItem) (cacheItem, error) {
	ips, err := net.LookupHost(item.host)
	if err != nil {
		if r.logger != nil {
			r.logger.Warnf("resolveAndUpdate %v: %v", item.host, err)
		}

		r.cacheLock.Lock()
		delete(r.cache, item.host)
		r.cacheLock.Unlock()

		return cacheItem{err: err}, err
	}

	if item.ips == nil || !util.StrSliceEqual(item.ips, ips) {
		if r.logger != nil {
			r.logger.Debugf("resolveAndUpdate: %s ips changed %v -> %v", item.host, item.ips, ips)
		}

		item.ips = ips
		item.err = err

		r.cacheLock.Lock()
		r.cache[item.host] = item
		r.cacheLock.Unlock()
	}

	return item, nil
}
示例#2
0
文件: client.go 项目: badoo/thunder
func NewClient(address string, p Protocol, c ClientCodec, connect_timeout, request_timeout time.Duration) *Client {
	ips, err := dns.LookupHostPort(address)
	if err != nil {
		log.Errorf("dns.LookupHostPort() faield: %v", err)
		// FIXME(antoxa): just reusing existing ips here, which actually sucks
		//                this only works because cli.Call() uses net.Dial() which resolves the name again
	}

	canUseClient := func(client *Client) bool {
		// readLoop() might be modifying this conn
		// but don't really need to lock for ips comparison, since ips are never modified for existing client
		client.lk.Lock()
		defer client.lk.Unlock()

		// TODO(antoxa): can just use one ip for client and recheck not full equality
		//               but only if new ips contain old ip
		if !util.StrSliceEqual(client.ips, ips) {
			return false
		}

		if client.closed {
			return false
		}

		return true
	}

	const max_tries = 3 // arbitrary limit, i know

	for done_tries := 0; done_tries < max_tries; done_tries++ {
		client := Pcm.GetClient(address)
		if client == nil {
			break
		}

		if !canUseClient(client) {
			client.closeNoReuse()
			continue
		}

		log.Debugf("reused existing client %p for %s (after %d tries)", client, address, done_tries)
		return client
	}

	log.Debugf("creating new cli for %s", address)
	return &Client{
		address:         address,
		ips:             ips,
		Proto:           p,
		Codec:           c,
		connect_timeout: connect_timeout,
		request_timeout: request_timeout,
	}
}