# -*- coding: utf--8 -*-
import time
from twisted.internet import reactor
from twisted.internet.protocol import ServerFactory
from twisted.protocols.basic import LineReceiver
#from twisted.python.threadpool import ThreadPool
import fnmatch
import shlex
class Error(Exception): pass
class WrongNumberArgumentsError(Error): pass
class WrongValueTypeError(Error): pass
class RedisServerProtocol(LineReceiver):
def __init__(self):
self.argc = 0 # 参数个数
self.argl = 0 # 参数长度
self.argv = [] # 参数数组
self.db = 0
def connectionMade(self):
#self.SELECT(['', '0'])
#self.SELECT(['', self.db])
self.db = 0
def dataReceived(self, data):
return LineReceiver.dataReceived(self, data)
def rawDataReceived(self, data):
self.argv.append(data[:self.argl])
self.argc -= 1
if not self.argc:
self.process(self.argv)
self.argv = []
self.setLineMode(data[self.argl+2:])
def lineReceived(self, line):
if self.argc:
self.argl = int(line[1:])
self.setRawMode()
return
if line[0] == '*':
self.argc = int(line[1:])
if self.argv:
self.sendLine('-ERR: %r' % self.argv)
return
self.process(shlex.split(line))
#获取命令行,并且将命令转化为大写,对应到本类的方法名
def process(self, argv):
command = argv[0].upper()
handler = getattr(self, command, self.todo)
#print "------------------------"
#print argv
try:
handler(argv)
except WrongNumberArgumentsError:
self.sendError("wrong number of arguments for %r command" % command)
except WrongValueTypeError:
self.sendError('Operation against a key holding the wrong kind of value')
"""except Exception, e:
import pdb;pdb.set_trace()
self.sendLine('-ERR %r' % e)
"""
#目前还没有处理的命令,返回字符串ok
def todo(self, argv):
print 'TODO', self.argv
self.sendOK()
#第一个字节是字符“+”,后面跟着一行表示执行结果的提示信息(line reply)比如set命令执行成功 后,会返回”+OK\r\n”
def sendOK(self):
self.sendLine('+OK')
#第一个字节是字符“:”,后面跟着一个整数值(integer reply)比如incr命令,成功时会返回对象+1后的值。
def sendInteger(self, i):
self.sendLine(':%d' % i)
#第一个字节是字符“$”,后面先跟一行,仅有一个数字,该数字表示下一行字符的个数(若不存在,则数字为-1)(bulk reply)比如get命令,成功时返回值的类似于“$7\r\nmyvalue”,不存在时返回的信息为“$-1\r\n”
def sendBulk(self, bulk):
if bulk is None:
self.sendLine('$-1')
return
self.sendLine('$%d' % len(bulk))
self.sendLine(bulk)
第一个字节是字符“*”,后面先跟一行,仅有一个数字,该数字表示bulk reply的个数(若不存在,则数字为-1)(multi-bulk reply)
def sendBulks(self, bulks):
self.sendLine('*%d' % len(bulks))
for bulk in bulks:
self.sendBulk(bulk)
print bulk
#map(self.sendBulk, bulks)
#第一个字节是字符“-”,后面跟着一行出错信息(error reply)比如lpop命令,当操作的对象不是一个链表时,会返回如下出错信息:“-ERR Operation against a key holding the wrong kind of value\r\n”
def sendError(self, message):
self.sendLine('-ERR %s' % message)
def sendLine(self, line):
#print line
return LineReceiver.sendLine(self, line)
#选择db
def SELECT(self, argv):
self.db = argv[1]
self.sendOK()
def GET(self, argv):
if len(argv) != 2: raise WrongNumberArgumentsError
key = argv[1]
#self.db = [{}] * 16该fake的数据都存在该数据结构中,当然你也可以定义在自己的数据结构中,这样做的话,重启后数据就不存在,当然你也可以存在数据可或者是真实的redis中。我们的项目是做了redis的转发,取数据的时候判断测试redis中是否有该数据,没有的话去开发测试集群取该数据,并且保存在测试的redis中,作为测试准备数据,可以保证自动化测试基准版本和测试版本访问的redis数据是相同的
value = "你自己的获取value的方法"
self.sendBulk(value)
def SET(self, argv):
if len(argv) != 3: raise WrongNumberArgumentsError
argv[1]是key
argv[2]是value
self.sendOK()
class RedisServer(ServerFactory):
protocol = RedisServerProtocol
def __init__(self):
self.db = [{}] * 16
#指定server的实现类
reactor.listenTCP(6666, RedisServer())
#设定线程个数
reactor.suggestThreadPoolSize(30)
reactor.run()