package nsqlookupd

import (
    "fmt"
    "sync"
    "sync/atomic"
    "time"
)
//db(注册中心--内存数据库map)结构体
type RegistrationDB struct {
    sync.RWMutex  //读写锁
    registrationMap map[Registration]Producers //
}
//代表一个生产者  主题 通道    
type Registration struct {
    Category string  //主题
    Key      string  //通道
    SubKey   string  //
}
type Registrations []Registration
//代表客户端nsqd 的配置信息
type PeerInfo struct {
    lastUpdate       int64
    id               string
    RemoteAddress    string `json:"remote_address"`
    Hostname         string `json:"hostname"`
    BroadcastAddress string `json:"broadcast_address"`
    TCPPort          int    `json:"tcp_port"`
    HTTPPort         int    `json:"http_port"`
    Version          string `json:"version"`
}
//生产者
type Producer struct {
    peerInfo     *PeerInfo
    tombstoned   bool
    tombstonedAt time.Time
}

type Producers []*Producer

func (p *Producer) String() string {
    return fmt.Sprintf("%s [%d, %d]", p.peerInfo.BroadcastAddress, p.peerInfo.TCPPort, p.peerInfo.HTTPPort)
}

func (p *Producer) Tombstone() {
    p.tombstoned = true
    p.tombstonedAt = time.Now()
}

func (p *Producer) IsTombstoned(lifetime time.Duration) bool {
    return p.tombstoned && time.Now().Sub(p.tombstonedAt) < lifetime
}

func NewRegistrationDB() *RegistrationDB {
    return &RegistrationDB{
        registrationMap: make(map[Registration]Producers),
    }
}

// add a registration key
func (r *RegistrationDB) AddRegistration(k Registration) {
    r.Lock()
    defer r.Unlock()
    _, ok := r.registrationMap[k]
    if !ok {
        r.registrationMap[k] = Producers{}
    }
}

// add a producer to a registration
func (r *RegistrationDB) AddProducer(k Registration, p *Producer) bool {
    r.Lock()
    defer r.Unlock()
    producers := r.registrationMap[k]
    found := false
    for _, producer := range producers {
        if producer.peerInfo.id == p.peerInfo.id {
            found = true
        }
    }
    if found == false {
        r.registrationMap[k] = append(producers, p)
    }
    return !found
}

// remove a producer from a registration
func (r *RegistrationDB) RemoveProducer(k Registration, id string) (bool, int) {
    r.Lock()
    defer r.Unlock()
    producers, ok := r.registrationMap[k]
    if !ok {
        return false, 0
    }
    removed := false
    cleaned := Producers{}
    for _, producer := range producers {
        if producer.peerInfo.id != id {
            cleaned = append(cleaned, producer)
        } else {
            removed = true
        }
    }
    // Note: this leaves keys in the DB even if they have empty lists
    r.registrationMap[k] = cleaned
    return removed, len(cleaned)
}

// remove a Registration and all it's producers
func (r *RegistrationDB) RemoveRegistration(k Registration) {
    r.Lock()
    defer r.Unlock()
    delete(r.registrationMap, k)
}

func (r *RegistrationDB) needFilter(key string, subkey string) bool {
    return key == "*" || subkey == "*"
}

func (r *RegistrationDB) FindRegistrations(category string, key string, subkey string) Registrations {
    r.RLock()
    defer r.RUnlock()
    if !r.needFilter(key, subkey) {
        k := Registration{category, key, subkey}
        if _, ok := r.registrationMap[k]; ok {
            return Registrations{k}
        }
        return Registrations{}
    }
    results := Registrations{}
    for k := range r.registrationMap {
        if !k.IsMatch(category, key, subkey) {
            continue
        }
        results = append(results, k)
    }
    return results
}

func (r *RegistrationDB) FindProducers(category string, key string, subkey string) Producers {
    r.RLock()
    defer r.RUnlock()
    if !r.needFilter(key, subkey) {
        k := Registration{category, key, subkey}
        return r.registrationMap[k]
    }

    results := Producers{}
    for k, producers := range r.registrationMap {
        if !k.IsMatch(category, key, subkey) {
            continue
        }
        for _, producer := range producers {
            found := false
            for _, p := range results {
                if producer.peerInfo.id == p.peerInfo.id {
                    found = true
                }
            }
            if found == false {
                results = append(results, producer)
            }
        }
    }
    return results
}

func (r *RegistrationDB) LookupRegistrations(id string) Registrations {
    r.RLock()
    defer r.RUnlock()
    results := Registrations{}
    for k, producers := range r.registrationMap {
        for _, p := range producers {
            if p.peerInfo.id == id {
                results = append(results, k)
                break
            }
        }
    }
    return results
}

func (k Registration) IsMatch(category string, key string, subkey string) bool {
    if category != k.Category {
        return false
    }
    if key != "*" && k.Key != key {
        return false
    }
    if subkey != "*" && k.SubKey != subkey {
        return false
    }
    return true
}

func (rr Registrations) Filter(category string, key string, subkey string) Registrations {
    output := Registrations{}
    for _, k := range rr {
        if k.IsMatch(category, key, subkey) {
            output = append(output, k)
        }
    }
    return output
}

func (rr Registrations) Keys() []string {
    keys := make([]string, len(rr))
    for i, k := range rr {
        keys[i] = k.Key
    }
    return keys
}

func (rr Registrations) SubKeys() []string {
    subkeys := make([]string, len(rr))
    for i, k := range rr {
        subkeys[i] = k.SubKey
    }
    return subkeys
}

func (pp Producers) FilterByActive(inactivityTimeout time.Duration, tombstoneLifetime time.Duration) Producers {
    now := time.Now()
    results := Producers{}
    for _, p := range pp {
        cur := time.Unix(0, atomic.LoadInt64(&p.peerInfo.lastUpdate))
        if now.Sub(cur) > inactivityTimeout || p.IsTombstoned(tombstoneLifetime) {
            continue
        }
        results = append(results, p)
    }
    return results
}

func (pp Producers) PeerInfo() []*PeerInfo {
    results := []*PeerInfo{}
    for _, p := range pp {
        results = append(results, p.peerInfo)
    }
    return results
}

registration_db.go的更多相关文章

  1. go语言nsq源码解读五 nsqlookupd源码registration_db.go

    本篇将讲解registration_db.go文件. 1234567891011121314151617181920212223242526272829303132333435363738394041 ...

  2. flume的使用

    1.flume的安装和配置 1.1 配置java_home,修改/opt/cdh/flume-1.5.0-cdh5.3.6/conf/flume-env.sh文件

  3. go语言nsq源码解读七 lookup_protocol_v1.go

    本篇将解读nsqlookup处理tcp请求的核心代码文件lookup_protocol_v1.go. 1234567891011121314151617181920212223242526272829 ...

  4. go语言 nsq源码解读三 nsqlookupd源码nsqlookupd.go

    从本节开始,将逐步阅读nsq各模块的代码. 读一份代码,我的思路一般是: 1.了解用法,知道了怎么使用,对理解代码有宏观上有很大帮助. 2.了解各大模块的功能特点,同时再想想,如果让自己来实现这些模块 ...

随机推荐

  1. rails应用ajax之一:使用纯js方法

    考虑如下需求: 1. 用户输入一个用户名,当焦点跳出文本框时,检查该用户名是否有效 2. 动态更新检查的结果 我们使用ajax的方式来实现这个简单的功能,首先建立view:check.html.erb ...

  2. iOS苹果自带UIMenuController

    一.UIMenuController认识 1.默认情况下,UITextView / UITextFiled / UIWebView 都有苹果自带的有UIMenuController功能 2.UITex ...

  3. 乐学习知选择--我的J2EE技术历程

    转眼换工作已经两个多月了,转眼今年已经到9月份了,转眼女朋友也来到了自己身边.有太多的转眼,如今在这个经理不在的早晨,可以肆意的点点这里看看那里,想想自己,有点吉利思的感觉. 这两个多月,知道了什么叫 ...

  4. PhpStudy如何开启Apache的gzip压缩功能?

    要让apache支持gzip功能,要用到deflate_Module和headers_Module. 打开apache的配置文件httpd.conf,大约在105行左右,找到以下两行内容:(这两行不是 ...

  5. sql server对并发的处理-乐观锁和悲观锁

    https://www.cnblogs.com/dengshaojun/p/3955826.html sql server对并发的处理-乐观锁和悲观锁 假如两个线程同时修改数据库同一条记录,就会导致后 ...

  6. BugFix:URL or HTTP headers are too long (IP=127.0.0.1)

    错误提示: URL or HTTP headers are too long (IP=127.0.0.1) com.caucho.server.dispatch.BadRequestException ...

  7. (转)java之Spring(IOC)注解装配Bean详解

    java之Spring(IOC)注解装配Bean详解   在这里我们要详细说明一下利用Annotation-注解来装配Bean. 因为如果你学会了注解,你就再也不愿意去手动配置xml文件了,下面就看看 ...

  8. XGBoost算法--学习笔记

    学习背景 最近想要学习和实现一下XGBoost算法,原因是最近对项目有些想法,准备做个回归预测.作为当下比较火的回归预测算法,准备直接套用试试效果. 一.基础知识 (1)泰勒公式 泰勒公式是一个用函数 ...

  9. Beta项目总结

    Beta冲刺成员名单和工作量比例 姓名 学号 负责内容 工作量比例 张梨贤 170327109 负责企业人员的委托/收回授权.第三方机构的委托授权管理.分级统计展示.分级列表展示 26% 黄腾飞 17 ...

  10. Nginx负载均衡和反向代理

    1:反向代理 代理就是中介,那有反向代理就有正向代理,两者的区别是什么嘞? 正向代理隐藏真实客户端,服务端不知道实际发起请求的客户端.,proxy和client同属一个LAN,对server透明: 反 ...