Пример #1
0
// 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
}
Пример #2
0
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
}
Пример #3
0
func discardRequest(reqs []*redisReq) {
	log.Debug("discardRequest")
	for _, req := range reqs {
		req.ch <- redisResp{nil, ErrBusy}
	}
	reqsPool.Put(reqs)
}
Пример #4
0
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)
}
Пример #5
0
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()
}
Пример #6
0
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")
}
Пример #7
0
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
}
Пример #8
0
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
}
Пример #9
0
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
}
Пример #10
0
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
}
Пример #11
0
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
}
Пример #12
0
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
}
Пример #13
0
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++
		}
	}
}
Пример #14
0
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
}
Пример #15
0
//export Debug
func Debug(msg *C.char) {
	log.Debug(C.GoString(msg))
}
Пример #16
0
// NewAddr 切换服务器列表
func (pool *Pool) NewAddr(addr []string, pwd string) {
	log.Debug("NewAddr%v|%v|%v", addr, pwd)
	pool.addrCh <- poolAddr{addr, pwd}
}