// Exec 执行redis命令 func (pool *Pool) Exec(cmd string, args ...interface{}) (interface{}, error) { log.Debug("Exec|req|%s|%v", cmd, args) ch := redisChanPool.Get().(chan redisResp) pool.reqCh <- &redisReq{ch, cmd, args} resp := <-ch redisChanPool.Put(ch) log.Debug("Exec|resp|%v|%v", resp.reply, resp.err) return resp.reply, resp.err }
func cmdIncrBy(conn *Conn, args [][]byte) (err error) { log.Debug("cmdIncrBy|%s|%v", args[0], args[1]) if inc, err := strconv.ParseInt(string(args[1]), 10, 64); err == nil { respChan := make(chan bdbIncrByResp, 1) workChan <- bdbIncrByReq{args[0], inc, respChan} resp := <-respChan if resp.err != nil { if resp.err == ErrRequest { _, err = conn.wb.WriteString("-ERR value is not an integer or out of range\r\n") } else { conn.wb.WriteString("-ERR ") conn.wb.WriteString(resp.err.Error()) _, err = conn.wb.WriteString("\r\n") } } else { var buf [64]byte out := strconv.AppendInt(buf[:0], resp.result, 10) conn.wb.WriteString(":") conn.wb.Write(out) _, err = conn.wb.WriteString("\r\n") } } else { _, err = conn.wb.WriteString("-ERR argument err") } return }
func discardRequest(reqs []*redisReq) { log.Debug("discardRequest") for _, req := range reqs { req.ch <- redisResp{nil, ErrBusy} } reqsPool.Put(reqs) }
func Init(configFile string) { tomlstr, err := ioutil.ReadFile(configFile) if err != nil { log.Error("read file error: %s", err) } if _, err := toml.Decode(string(tomlstr), &SConfig); err != nil { log.Error("toml.Decode error: %s", err) } log.Debug("%#v", SConfig) }
func Init() { visitfile, err := os.Open("visitcount.conf") if err != nil { log.Error("Init error: %s", err) } var buf []byte = make([]byte, 10) length, _ := visitfile.Read(buf) visitfile.Close() log.Debug("visitcount: %v, %s, %d", buf, string(buf[:length-1]), length) go refreshVisitCount() }
func (pool *Pool) cleanConn() { log.Info("cleanConn") for pool.total > 0 { var conn *redisConn select { case conn = <-pool.connCh: case conn = <-pool.badCh: } conn.conn.Close() pool.total-- } log.Debug("cleanConn|ok") }
func cmdSet(conn *Conn, args [][]byte) (err error) { log.Debug("cmdSet|%s|%v", args[0], args[1]) respChan := make(chan bdbSetResp, 1) workChan <- bdbSetReq{args[0], args[1], 0, false, respChan} resp := <-respChan if resp.err != nil { conn.wb.WriteString("-ERR ") conn.wb.WriteString(resp.err.Error()) _, err = conn.wb.WriteString("\r\n") } else { _, err = conn.wb.WriteString("+OK\r\n") } return }
func cmdGet(conn *Conn, args [][]byte) (err error) { log.Debug("cmdGet|%s", args[0]) respChan := make(chan bdbGetResp, 1) workChan <- bdbGetReq{args[0], respChan} resp := <-respChan if resp.err != nil { _, err = conn.wb.WriteString("-ERR dberr\r\n") } else if resp.value == nil { _, err = conn.wb.WriteString("$-1\r\n") } else { conn.writeLen('$', len(resp.value)) conn.wb.Write(resp.value) _, err = conn.wb.WriteString("\r\n") } return }
func cmdIncr(conn *Conn, args [][]byte) (err error) { log.Debug("cmdIncr|%s", args[0]) respChan := make(chan bdbIncrByResp, 1) workChan <- bdbIncrByReq{args[0], 1, respChan} resp := <-respChan if resp.err != nil { if resp.err == ErrRequest { _, err = conn.wb.WriteString("-ERR value is not an integer or out of range\r\n") } else { conn.wb.WriteString("-ERR ") conn.wb.WriteString(resp.err.Error()) _, err = conn.wb.WriteString("\r\n") } } else { _, err = conn.wb.WriteString("+OK\r\n") } return }
func cmdSetNx(conn *Conn, args [][]byte) (err error) { log.Debug("cmdSetNx|%s|%v", args[0], args[1]) respChan := make(chan bdbSetResp, 1) workChan <- bdbSetReq{args[0], args[1], 0, true, respChan} resp := <-respChan if resp.err != nil { if resp.err == bdb.ErrKeyExist { _, err = conn.wb.WriteString(":0\r\n") } else { conn.wb.WriteString("-ERR ") conn.wb.WriteString(resp.err.Error()) _, err = conn.wb.WriteString("\r\n") } } else { _, err = conn.wb.WriteString(":1\r\n") } return }
func cmdSetEx(conn *Conn, args [][]byte) (err error) { log.Debug("cmdSetEx|%s|%s|%s", args[0], args[1], args[2]) if sec, err := strconv.ParseUint(string(args[1]), 10, 32); err == nil { respChan := make(chan bdbSetResp, 1) workChan <- bdbSetReq{args[0], args[2], uint32(sec), false, respChan} resp := <-respChan if resp.err != nil { conn.wb.WriteString("-ERR ") conn.wb.WriteString(resp.err.Error()) _, err = conn.wb.WriteString("\r\n") } else { _, err = conn.wb.WriteString("+OK\r\n") } } else { _, err = conn.wb.WriteString("-ERR argument err") } return }
func processRequest(conn *redisConn, reqs []*redisReq) (err error) { var slaveError error log.Debug("processRequest|%v|%v", conn.id, len(reqs)) for _, req := range reqs { conn.conn.Send(req.cmd, req.args...) } err = conn.conn.Flush() if err != nil { // 发送请求失败 for _, req := range reqs { req.ch <- redisResp{nil, err} } return } for _, req := range reqs { var ok bool if err != nil { // 判断是否处于错误状态 // 处于错误状态就不用再receive了 req.ch <- redisResp{nil, err} } else { var v interface{} v, err = conn.conn.Receive() req.ch <- redisResp{v, err} if err != nil { log.Error("processRequest|Receive|%v", err) if err, ok = err.(redis.Error); ok { // redis.Error表示的是具体某个请求的数据错误 // 该类型错误不影响后续请求的处理 if strings.HasPrefix(err.Error(), "ERR slavewrite,") { slaveError = err } err = nil } } } } if slaveError != nil { err = slaveError } return }
func (pool *Pool) checkPool() { var pos = 0 for pool.total < pool.max { log.Debug("checkPool|%v|%v", pool.max, pool.total) // 需要新的连接 var addrs = pool.addrs if pos >= len(addrs) { // 兜了一圈了,看看其他消息吧 // 可能会有newAddr这样的消息需要切换服务器组 log.Error("checkPool|retry_after") return } if conn, err := makeConn(addrs[pos], pool.pwd); err != nil { log.Error("checkPool|makeConn|%v", err) pos++ } else { pool.connCh <- conn pool.total++ } } }
func (pool *Pool) testConn() { // testConn每次只检查一个连接 var conn *redisConn select { case conn = <-pool.connCh: default: // 没有空闲的连接 // 表示现在比较忙 // 暂时就不检查了 return } var masterAddr = pool.addrs[0] if conn.addr != masterAddr { if newconn, err := makeConn(masterAddr, pool.pwd); err != nil { log.Error("bkWorker|makeConn|%v", err) } else { // 主服务器已经能够连上了 conn.conn.Close() conn = newconn } } if time.Now().Unix() > conn.pingTime { // 超过pingInterval,则ping一下连接 if _, err := conn.conn.Do("set", "__ping", "1"); err != nil { if strings.HasPrefix(err.Error(), "ERR slavewrite,") { pool.processSlaveWrite(conn, err.Error()) } else { log.Info("process|ping|%v", err) pool.badCh <- conn } } else { log.Debug("bgWorker|ping") pool.connCh <- conn } } else { pool.connCh <- conn } return }
//export Debug func Debug(msg *C.char) { log.Debug(C.GoString(msg)) }
// NewAddr 切换服务器列表 func (pool *Pool) NewAddr(addr []string, pwd string) { log.Debug("NewAddr%v|%v|%v", addr, pwd) pool.addrCh <- poolAddr{addr, pwd} }