SSDB.py
import socket class SSDB_Response(object): def __init__(self, code='', data_or_message=None): self.type = 'none' self.code = code self.data = None self.message = None self.set(code, data_or_message) def set(self, code, data_or_message=None): self.code = code if code == 'ok': self.data = data_or_message else: if isinstance(data_or_message, list): if len(data_or_message) > 0: self.message = data_or_message[0] else: self.message = data_or_message def __repr__(self): return ((((str(self.code) + ' ') + str(self.message)) + ' ') + str(self.data)) def ok(self): return self.code == 'ok' def not_found(self): return self.code == 'not_found' def str_resp(self, resp): self.type = 'val' if resp[0] == 'ok': if len(resp) == 2: self.set('ok', resp[1]) else: self.set('server_error', 'Invalid response') else: self.set(resp[0], resp[1:]) return self def str_resp(self, resp): self.type = 'val' if resp[0] == 'ok': if len(resp) == 2: self.set('ok', resp[1]) else: self.set('server_error', 'Invalid response') else: self.set(resp[0], resp[1:]) return self def int_resp(self, resp): self.type = 'val' if resp[0] == 'ok': if len(resp) == 2: try: val = int(resp[1]) self.set('ok', val) except Exception as e: self.set('server_error', 'Invalid response') else: self.set('server_error', 'Invalid response') else: pass self.set(resp[0], resp[1:]) return self def float_resp(self, resp): self.type = 'val' if resp[0] == 'ok': if len(resp) == 2: try: val = float(resp[1]) self.set('ok', val) except Exception as e: self.set('server_error', 'Invalid response') else: self.set('server_error', 'Invalid response') else: self.set(resp[0], resp[1:]) return self def list_resp(self, resp): self.type = 'list' self.set(resp[0], resp[1:]) return self def int_map_resp(self, resp): self.type = 'map' if resp[0] == 'ok': if len(resp) % 2 == 1: data = {'index': [], 'items': {}, } i = 1 while i < len(resp): k = resp[i] v = resp[(i + 1)] try: v = int(v) except Exception as e: v = - (1) data['index'].append(k) data['items'][k] = v i += 2 self.set('ok', data) else: self.set('server_error', 'Invalid response') else: self.set(resp[0], resp[1:]) return self def str_map_resp(self, resp): self.type = 'map' if resp[0] == 'ok': if len(resp) % 2 == 1: data = {'index': [], 'items': {}, } i = 1 while i < len(resp): k = resp[i] v = resp[(i + 1)] data['index'].append(k) data['items'][k] = v i += 2 self.set('ok', data) else: self.set('server_error', 'Invalid response') else: self.set(resp[0], resp[1:]) return self class SSDB(object): def __init__(self, host, port): self.recv_buf = '' self._closed = False self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.sock.connect(tuple([host, port])) self.sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1) def close(self): if not (self._closed): self.sock.close() self._closed = True def closed(self): pass return self._closed def request(self, cmd, params=None): pass if params is None: params = [] params = ([cmd] + params) self.send(params) resp = self.recv() if resp is None: return SSDB_Response('error', 'Unknown error') if len(resp) == 0: return SSDB_Response('disconnected', 'Connection closed') ret = SSDB_Response() # {{{ switch: cmd _continue_1 = False while True: if False or ((cmd) == 'ping') or ((cmd) == 'set') or ((cmd) == 'del') or ((cmd) == 'qset') or ( (cmd) == 'zset') or ((cmd) == 'hset') or ((cmd) == 'qpush') or ((cmd) == 'qpush_front') or ( (cmd) == 'qpush_back') or ((cmd) == 'zdel') or ((cmd) == 'hdel') or ((cmd) == 'multi_set') or ( (cmd) == 'multi_del') or ((cmd) == 'multi_hset') or ((cmd) == 'multi_hdel') or ( (cmd) == 'multi_zset') or ((cmd) == 'multi_zdel'): if len(resp) > 1: return ret.int_resp(resp) else: return SSDB_Response(resp[0], None) break if False or ((cmd) == 'version') or ((cmd) == 'substr') or ((cmd) == 'get') or ((cmd) == 'getset') or ( (cmd) == 'hget') or ((cmd) == 'qfront') or ((cmd) == 'qback') or ((cmd) == 'qget'): pass return ret.str_resp(resp) break if False or ((cmd) == 'qpop') or ((cmd) == 'qpop_front') or ((cmd) == 'qpop_back'): size = 1 try: size = int(params[2]) except Exception as e: pass if size == 1: return ret.str_resp(resp) else: return ret.list_resp(resp) break if False or ((cmd) == 'dbsize') or ((cmd) == 'getbit') or ((cmd) == 'setbit') or ((cmd) == 'countbit') or ( (cmd) == 'bitcount') or ((cmd) == 'strlen') or ((cmd) == 'ttl') or ((cmd) == 'expire') or ( (cmd) == 'setnx') or ((cmd) == 'incr') or ((cmd) == 'decr') or ((cmd) == 'zincr') or ( (cmd) == 'zdecr') or ((cmd) == 'hincr') or ((cmd) == 'hdecr') or ((cmd) == 'hsize') or ( (cmd) == 'zsize') or ((cmd) == 'qsize') or ((cmd) == 'zget') or ((cmd) == 'zrank') or ( (cmd) == 'zrrank') or ((cmd) == 'zsum') or ((cmd) == 'zcount') or ((cmd) == 'zremrangebyrank') or ( (cmd) == 'zremrangebyscore') or ((cmd) == 'hclear') or ((cmd) == 'zclear') or ((cmd) == 'qclear') or ( (cmd) == 'qpush') or ((cmd) == 'qpush_front') or ((cmd) == 'qpush_back') or ( (cmd) == 'qtrim_front') or ((cmd) == 'qtrim_back'): pass return ret.int_resp(resp) break if False or ((cmd) == 'zavg'): pass return ret.float_resp(resp) break if False or ((cmd) == 'keys') or ((cmd) == 'rkeys') or ((cmd) == 'zkeys') or ((cmd) == 'zrkeys') or ( (cmd) == 'hkeys') or ((cmd) == 'hrkeys') or ((cmd) == 'list') or ((cmd) == 'hlist') or ( (cmd) == 'hrlist') or ((cmd) == 'zlist') or ((cmd) == 'zrlist'): pass return ret.list_resp(resp) break if False or ((cmd) == 'scan') or ((cmd) == 'rscan') or ((cmd) == 'hgetall') or ((cmd) == 'hscan') or ( (cmd) == 'hrscan'): pass return ret.str_map_resp(resp) break if False or ((cmd) == 'zscan') or ((cmd) == 'zrscan') or ((cmd) == 'zrange') or ((cmd) == 'zrrange') or ( (cmd) == 'zpop_front') or ((cmd) == 'zpop_back'): pass return ret.int_map_resp(resp) break if False or ((cmd) == 'auth') or ((cmd) == 'exists') or ((cmd) == 'hexists') or ((cmd) == 'zexists'): pass return ret.int_resp(resp) break if False or ((cmd) == 'multi_exists') or ((cmd) == 'multi_hexists') or ((cmd) == 'multi_zexists'): pass return ret.int_map_resp(resp) break if False or ((cmd) == 'multi_get') or ((cmd) == 'multi_hget'): pass return ret.str_map_resp(resp) break if False or ((cmd) == 'multi_hsize') or ((cmd) == 'multi_zsize') or ((cmd) == 'multi_zget'): pass return ret.int_map_resp(resp) break ### default return ret.list_resp(resp) break break if _continue_1: continue # }}} switch return SSDB_Response('error', 'Unknown error') def send(self, data): pass ps = [] _cpy_r_0 = _cpy_l_1 = data if type(_cpy_r_0).__name__ == 'dict': _cpy_b_3 = True; _cpy_l_1 = _cpy_r_0.iterkeys() else: _cpy_b_3 = False; for _cpy_k_2 in _cpy_l_1: if _cpy_b_3: p = _cpy_r_0[_cpy_k_2] else: p = _cpy_k_2 pass p = str(p) ps.append(str(len(p))) ps.append(p) nl = '\n' s = (nl.join(ps) + '\n\n') try: while True: ret = self.sock.send(s.encode()) if ret == 0: return - (1) s = s[ret:] if len(s) == 0: break except socket.error as e: return -(1) return ret def net_read(self): try: data = self.sock.recv(1024 * 8) except Exception as e: data = '' if data == '': self.close() return 0 self.recv_buf += str(data,encoding = "ascii") return len(data) def recv(self): while True: ret = self.parse() if ret is None: if self.net_read() == 0: return [] else: return ret def parse(self): pass ret = [] spos = 0 epos = 0 while True: spos = epos epos = self.recv_buf.find('\n', spos) if epos == - (1): break epos += 1 line = self.recv_buf[spos: epos] spos = epos if line.strip() == '': if len(ret) == 0: continue else: self.recv_buf = self.recv_buf[spos:] return ret try: num = int(line) except Exception as e: return [] epos = (spos + num) if epos > len(self.recv_buf): break data = self.recv_buf[spos: epos] ret.append(data) spos = epos epos = self.recv_buf.find('\n', spos) if epos == - (1): break epos += 1 return None
测试程序
from SSDB import SSDB ssdb = SSDB('192.168.1.250', 8888) l = [] l.append('person_1') l.append('a') l.append('1111') l.append('b') l.append('2222') print(ssdb.request('multi_hset', l)) ''' print(ssdb.request('set', ['test', '123'])) print(ssdb.request('get', ['test'])) print(ssdb.request('incr', ['test', '1'])) print(ssdb.request('decr', ['test', '1'])) print(ssdb.request('scan', ['a', 'z', 10])) print(ssdb.request('rscan', ['z', 'a', 10])) print(ssdb.request('keys', ['a', 'z', 10])) print(ssdb.request('del', ['test'])) print(ssdb.request('get', ['test'])) print("\n") print(ssdb.request('zset', ['test', 'a', 20])) print(ssdb.request('zget', ['test', 'a'])) print(ssdb.request('zincr', ['test', 'a', 20])) print(ssdb.request('zdecr', ['test', 'a', 20])) print(ssdb.request('zscan', ['test', 'a', 0, 100, 10])) print(ssdb.request('zrscan', ['test', 'a', 100, 0, 10])) print(ssdb.request('zkeys', ['test', 'a', 0, 100, 10])) print(ssdb.request('zdel', ['test', 'a'])) print(ssdb.request('zget', ['test', 'a'])) print("\n") print(ssdb.request('hset', ['test', 'a', 20])) print(ssdb.request('hget', ['test', 'a'])) print(ssdb.request('hincr', ['test', 'a', 20])) print(ssdb.request('hdecr', ['test', 'a', 20])) print(ssdb.request('hscan', ['test', '0', 'z', 10])) print(ssdb.request('hrscan', ['test', 'z', '0', 10])) print(ssdb.request('hkeys', ['test', '0', 'z', 10])) print(ssdb.request('hdel', ['test', 'a'])) print(ssdb.request('hget', ['test', 'a'])) print("\n") '''
pyssdb客户端的使用
import pyssdb c = pyssdb.Client('192.168.1.250', 8888) list = ['lastName', '海', 'firstName', '黄'] print(c.multi_hset('person_1', *tuple(list))) c.disconnect()
测试多线程
import pyssdb import threading # 客户端默认是有连接池的 c = pyssdb.Client('192.168.1.250', 8888) def makeCache(func): list = ['lastName', '海', 'firstName', '黄'] for i in range(10000): c.multi_hset('person_huanghai_'+str((func-1)*i), *tuple(list)) print('成功完成线程:'+str(func)) # 定义五个线程 threads = [] t1 = threading.Thread(target=makeCache, args=(1,)) threads.append(t1) t2 = threading.Thread(target=makeCache, args=(2,)) threads.append(t2) t3 = threading.Thread(target=makeCache, args=(3,)) threads.append(t3) t4 = threading.Thread(target=makeCache, args=(4,)) threads.append(t4) t5 = threading.Thread(target=makeCache, args=(5,)) threads.append(t5) for t in threads: t.setDaemon(True) t.start() t1.join() t2.join() t3.join() t4.join() t5.join() c.disconnect() print('程序结束')