├── README.md ├── .gitignore ├── Program.cs ├── Link.cs └── Client.cs /README.md: -------------------------------------------------------------------------------- 1 | dotnetssdb 2 | ========== 3 | 4 | SSDB .Net client 5 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | *.a 3 | *.class 4 | .DS_Store 5 | *.pyc 6 | *.swp 7 | *_cpy_* 8 | 9 | -------------------------------------------------------------------------------- /Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace ssdb 7 | { 8 | class Program 9 | { 10 | static void Main(string[] args) { 11 | Client client = new Client("127.0.0.1", 8888); 12 | List resp = client.request("set", "a", "100"); 13 | foreach(byte[] bs in resp) { 14 | Console.WriteLine(Encoding.Default.GetString(bs)); 15 | } 16 | 17 | resp = client.request("get", "a"); 18 | foreach(byte[] bs in resp) { 19 | Console.WriteLine(Encoding.Default.GetString(bs)); 20 | } 21 | 22 | client.set("a", "99"); 23 | string val; 24 | client.get("a", out val); 25 | Console.WriteLine(val); 26 | 27 | Console.WriteLine("-----------------"); 28 | { 29 | KeyValuePair[] kvs = client.scan("", "", 3); 30 | Console.WriteLine(kvs.Length + " kvs"); 31 | foreach(KeyValuePair kv in kvs) { 32 | Console.WriteLine(" " + kv.Key + ": " + Encoding.Default.GetString(kv.Value)); 33 | } 34 | } 35 | Console.WriteLine("-----------------"); 36 | { 37 | KeyValuePair[] kvs = client.zscan("z", "", Int64.MinValue, Int64.MaxValue, 3); 38 | Console.WriteLine(kvs.Length + " kvs"); 39 | foreach(KeyValuePair kv in kvs) { 40 | Console.WriteLine(" " + kv.Key + ": " + kv.Value); 41 | } 42 | } 43 | Console.WriteLine("-----------------"); 44 | { 45 | KeyValuePair[] kvs = client.zrscan("z", "", Int64.MaxValue, Int64.MinValue, 3); 46 | Console.WriteLine(kvs.Length + " kvs"); 47 | foreach(KeyValuePair kv in kvs) { 48 | Console.WriteLine(" " + kv.Key + ": " + kv.Value); 49 | } 50 | } 51 | 52 | Console.WriteLine(client.zsize("z").ToString()); 53 | 54 | Console.ReadLine(); 55 | 56 | client.close(); 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /Link.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Net; 6 | using System.Net.Sockets; 7 | using System.IO; 8 | 9 | namespace ssdb 10 | { 11 | class Link 12 | { 13 | private TcpClient sock; 14 | private MemoryStream recv_buf = new MemoryStream(8 * 1024); 15 | 16 | public Link(string host, int port) { 17 | sock = new TcpClient(host, port); 18 | sock.NoDelay = true; 19 | sock.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, true); 20 | } 21 | 22 | ~Link() { 23 | this.close(); 24 | } 25 | 26 | public void close() { 27 | if(sock != null){ 28 | sock.Close(); 29 | } 30 | sock = null; 31 | } 32 | 33 | public List request(string cmd, params string[] args) { 34 | List req = new List(1 + args.Length); 35 | req.Add(Encoding.Default.GetBytes(cmd)); 36 | foreach(string s in args) { 37 | req.Add(Encoding.Default.GetBytes(s)); 38 | } 39 | return this.request(req); 40 | } 41 | 42 | public List request(string cmd, params byte[][] args) { 43 | List req = new List(1 + args.Length); 44 | req.Add(Encoding.Default.GetBytes(cmd)); 45 | req.AddRange(args); 46 | return this.request(req); 47 | } 48 | 49 | public List request(List req) { 50 | MemoryStream buf = new MemoryStream(); 51 | foreach(byte[] p in req) { 52 | byte[] len = Encoding.Default.GetBytes(p.Length.ToString()); 53 | buf.Write(len, 0, len.Length); 54 | buf.WriteByte((byte)'\n'); 55 | buf.Write(p, 0, p.Length); 56 | buf.WriteByte((byte)'\n'); 57 | } 58 | buf.WriteByte((byte)'\n'); 59 | 60 | byte[] bs = buf.GetBuffer(); 61 | sock.GetStream().Write(bs, 0, (int)buf.Length); 62 | //Console.Write(Encoding.Default.GetString(bs, 0, (int)buf.Length)); 63 | return recv(); 64 | } 65 | 66 | private List recv() { 67 | while(true) { 68 | List ret = parse(); 69 | if(ret != null) { 70 | return ret; 71 | } 72 | byte[] bs = new byte[8192]; 73 | int len = sock.GetStream().Read(bs, 0, bs.Length); 74 | //Console.WriteLine("<< " + Encoding.Default.GetString(bs)); 75 | recv_buf.Write(bs, 0, len); 76 | } 77 | } 78 | 79 | private static int memchr(byte[] bs, byte b, int offset) { 80 | for(int i = offset; i < bs.Length; i++) { 81 | if(bs[i] == b) { 82 | return i; 83 | } 84 | } 85 | return -1; 86 | } 87 | 88 | private List parse() { 89 | List list = new List(); 90 | byte[] buf = recv_buf.GetBuffer(); 91 | 92 | int idx = 0; 93 | while(true) { 94 | int pos = memchr(buf, (byte)'\n', idx); 95 | //System.out.println("pos: " + pos + " idx: " + idx); 96 | if(pos == -1) { 97 | break; 98 | } 99 | if(pos == idx || (pos == idx + 1 && buf[idx] == '\r')) { 100 | idx += 1; // if '\r', next time will skip '\n' 101 | // ignore empty leading lines 102 | if(list.Count == 0) { 103 | continue; 104 | } else { 105 | int left = (int)recv_buf.Length - idx; 106 | recv_buf = new MemoryStream(8192); 107 | if(left > 0) { 108 | recv_buf.Write(buf, idx, left); 109 | } 110 | return list; 111 | } 112 | } 113 | byte[] lens = new byte[pos - idx]; 114 | Array.Copy(buf, idx, lens, 0, lens.Length); 115 | int len = Int32.Parse(Encoding.Default.GetString(lens)); 116 | 117 | idx = pos + 1; 118 | if(idx + len >= recv_buf.Length) { 119 | break; 120 | } 121 | byte[] data = new byte[len]; 122 | Array.Copy(buf, idx, data, 0, (int)data.Length); 123 | 124 | //Console.WriteLine("len: " + len + " data: " + Encoding.Default.GetString(data)); 125 | idx += len + 1; // skip '\n' 126 | list.Add(data); 127 | } 128 | return null; 129 | } 130 | } 131 | } 132 | -------------------------------------------------------------------------------- /Client.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace ssdb { 7 | public class Client { 8 | private Link link; 9 | private string resp_code; 10 | 11 | public Client(string host, int port) { 12 | link = new Link(host, port); 13 | } 14 | 15 | ~Client() { 16 | this.close(); 17 | } 18 | 19 | public void close() { 20 | link.close(); 21 | } 22 | 23 | public List request(string cmd, params string[] args) { 24 | return link.request(cmd, args); 25 | } 26 | 27 | public List request(string cmd, params byte[][] args) { 28 | return link.request(cmd, args); 29 | } 30 | 31 | public List request(List req) { 32 | return link.request(req); 33 | } 34 | 35 | 36 | private void assert_ok() { 37 | if (resp_code != "ok") 38 | { 39 | throw new Exception(resp_code); 40 | } 41 | } 42 | 43 | private byte[] _bytes(string s) { 44 | return Encoding.Default.GetBytes(s); 45 | } 46 | 47 | private string _string(byte[] bs) { 48 | return Encoding.Default.GetString(bs); 49 | } 50 | 51 | private KeyValuePair[] parse_scan_resp(List resp) { 52 | resp_code = _string(resp[0]); 53 | this.assert_ok(); 54 | 55 | int size = (resp.Count - 1) / 2; 56 | KeyValuePair[] kvs = new KeyValuePair[size]; 57 | for (int i = 0; i < size; i += 1) 58 | { 59 | string key = _string(resp[i * 2 + 1]); 60 | byte[] val = resp[i * 2 + 2]; 61 | kvs[i] = new KeyValuePair(key, val); 62 | } 63 | return kvs; 64 | } 65 | 66 | /***** kv *****/ 67 | 68 | public bool exists(byte[] key) { 69 | List resp = request("exists", key); 70 | resp_code = _string(resp[0]); 71 | if (resp_code == "not_found") 72 | { 73 | return false; 74 | } 75 | this.assert_ok(); 76 | if (resp.Count != 2) 77 | { 78 | throw new Exception("Bad response!"); 79 | } 80 | return (_string(resp[1]) == "1" ? true : false); 81 | } 82 | 83 | public bool exists(string key) { 84 | return this.exists(_bytes(key)); 85 | } 86 | 87 | public void set(byte[] key, byte[] val) { 88 | List resp = request("set", key, val); 89 | resp_code = _string(resp[0]); 90 | this.assert_ok(); 91 | } 92 | 93 | public void set(string key, string val) { 94 | this.set(_bytes(key), _bytes(val)); 95 | } 96 | 97 | /// 98 | /// 99 | /// 100 | /// 101 | /// 102 | /// returns true if name.key is found, otherwise returns false. 103 | public bool get(byte[] key, out byte[] val) { 104 | val = null; 105 | List resp = request("get", key); 106 | resp_code = _string(resp[0]); 107 | if (resp_code == "not_found") 108 | { 109 | return false; 110 | } 111 | this.assert_ok(); 112 | if (resp.Count != 2) 113 | { 114 | throw new Exception("Bad response!"); 115 | } 116 | val = resp[1]; 117 | return true; 118 | } 119 | 120 | public bool get(string key, out byte[] val) { 121 | return this.get(_bytes(key), out val); 122 | } 123 | 124 | public bool get(string key, out string val) { 125 | val = null; 126 | byte[] bs; 127 | if (!this.get(key, out bs)) 128 | { 129 | return false; 130 | } 131 | val = _string(bs); 132 | return true; 133 | } 134 | 135 | public void del(byte[] key) { 136 | List resp = request("del", key); 137 | resp_code = _string(resp[0]); 138 | this.assert_ok(); 139 | } 140 | 141 | public void del(string key) { 142 | this.del(_bytes(key)); 143 | } 144 | 145 | public KeyValuePair[] scan(string key_start, string key_end, Int64 limit) { 146 | List resp = request("scan", key_start, key_end, limit.ToString()); 147 | return parse_scan_resp(resp); 148 | } 149 | 150 | public KeyValuePair[] rscan(string key_start, string key_end, Int64 limit) { 151 | List resp = request("rscan", key_start, key_end, limit.ToString()); 152 | return parse_scan_resp(resp); 153 | } 154 | 155 | /***** hash *****/ 156 | 157 | public void hset(byte[] name, byte[] key, byte[] val) { 158 | List resp = request("hset", name, key, val); 159 | resp_code = _string(resp[0]); 160 | this.assert_ok(); 161 | } 162 | 163 | public void hset(string name, string key, byte[] val) { 164 | this.hset(_bytes(name), _bytes(key), val); 165 | } 166 | 167 | public void hset(string name, string key, string val) { 168 | this.hset(_bytes(name), _bytes(key), _bytes(val)); 169 | } 170 | 171 | /// 172 | /// 173 | /// 174 | /// 175 | /// 176 | /// 177 | /// returns true if name.key is found, otherwise returns false. 178 | public bool hget(byte[] name, byte[] key, out byte[] val) { 179 | val = null; 180 | List resp = request("hget", name, key); 181 | resp_code = _string(resp[0]); 182 | if (resp_code == "not_found") 183 | { 184 | return false; 185 | } 186 | this.assert_ok(); 187 | if (resp.Count != 2) 188 | { 189 | throw new Exception("Bad response!"); 190 | } 191 | val = resp[1]; 192 | return true; 193 | } 194 | 195 | public bool hget(string name, string key, out byte[] val) { 196 | return this.hget(_bytes(name), _bytes(key), out val); 197 | } 198 | 199 | public bool hget(string name, string key, out string val) { 200 | val = null; 201 | byte[] bs; 202 | if (!this.hget(name, key, out bs)) 203 | { 204 | return false; 205 | } 206 | val = _string(bs); 207 | return true; 208 | } 209 | 210 | public void hdel(byte[] name, byte[] key) { 211 | List resp = request("hdel", name, key); 212 | resp_code = _string(resp[0]); 213 | this.assert_ok(); 214 | } 215 | 216 | public void hdel(string name, string key) { 217 | this.hdel(_bytes(name), _bytes(key)); 218 | } 219 | 220 | public bool hexists(byte[] name, byte[] key) { 221 | List resp = request("hexists", name, key); 222 | resp_code = _string(resp[0]); 223 | if (resp_code == "not_found") 224 | { 225 | return false; 226 | } 227 | this.assert_ok(); 228 | if (resp.Count != 2) 229 | { 230 | throw new Exception("Bad response!"); 231 | } 232 | return (_string(resp[1]) == "1" ? true : false); 233 | } 234 | 235 | public bool hexists(string name, string key) { 236 | return this.hexists(_bytes(name), _bytes(key)); 237 | } 238 | 239 | public Int64 hsize(byte[] name) { 240 | List resp = request("hsize", name); 241 | resp_code = _string(resp[0]); 242 | this.assert_ok(); 243 | if (resp.Count != 2) 244 | { 245 | throw new Exception("Bad response!"); 246 | } 247 | return Int64.Parse(_string(resp[1])); 248 | } 249 | 250 | public Int64 hsize(string name) { 251 | return this.hsize(_bytes(name)); 252 | } 253 | 254 | public KeyValuePair[] hscan(string name, string key_start, string key_end, Int64 limit) { 255 | List resp = request("hscan", name, key_start, key_end, limit.ToString()); 256 | return parse_scan_resp(resp); 257 | } 258 | 259 | public KeyValuePair[] hrscan(string name, string key_start, string key_end, Int64 limit) { 260 | List resp = request("hrscan", name, key_start, key_end, limit.ToString()); 261 | return parse_scan_resp(resp); 262 | } 263 | 264 | public void multi_hset(byte[] name, KeyValuePair[] kvs) 265 | { 266 | byte[][] req = new byte[(kvs.Length * 2) + 1][]; 267 | req[0] = name; 268 | for (int i = 0; i < kvs.Length; i++) 269 | { 270 | req[(2 * i) + 1] = kvs[i].Key; 271 | req[(2 * i) + 2] = kvs[i].Value; 272 | 273 | } 274 | List resp = request("multi_hset", req); 275 | resp_code = _string(resp[0]); 276 | this.assert_ok(); 277 | } 278 | 279 | public void multi_hset(string name, KeyValuePair[] kvs) 280 | { 281 | KeyValuePair[] req = new KeyValuePair[kvs.Length]; 282 | for (int i = 0; i < kvs.Length; i++) 283 | { 284 | req[i] = new KeyValuePair(_bytes(kvs[i].Key), _bytes(kvs[i].Value)); 285 | } 286 | this.multi_hset(_bytes(name), req); 287 | } 288 | 289 | public void multi_hdel(byte[] name, byte[][] keys) 290 | { 291 | byte[][] req = new byte[keys.Length + 1][]; 292 | req[0] = name; 293 | for (int i = 0; i < keys.Length; i++) 294 | { 295 | req[i + 1] = keys[i]; 296 | } 297 | List resp = request("multi_hdel", req); 298 | resp_code = _string(resp[0]); 299 | this.assert_ok(); 300 | } 301 | 302 | public void multi_hdel(string name, string[] keys) 303 | { 304 | byte[][] req = new byte[keys.Length][]; 305 | for (int i = 0; i < keys.Length; i++) 306 | { 307 | req[i] = _bytes(keys[i]); 308 | } 309 | this.multi_hdel(_bytes(name), req); 310 | } 311 | 312 | public KeyValuePair[] multi_hget(byte[] name, byte[][] keys) 313 | { 314 | byte[][] req = new byte[keys.Length + 1][]; 315 | req[0] = name; 316 | for (int i = 0; i < keys.Length; i++) 317 | { 318 | req[i + 1] = keys[i]; 319 | } 320 | List resp = request("multi_hget", req); 321 | KeyValuePair[] ret = parse_scan_resp(resp); 322 | 323 | return ret; 324 | } 325 | 326 | public KeyValuePair[] multi_hget(string name, string[] keys) 327 | { 328 | byte[][] req = new byte[keys.Length][]; 329 | for (int i = 0; i < keys.Length; i++) 330 | { 331 | req[i] = _bytes(keys[i]); 332 | } 333 | return this.multi_hget(_bytes(name), req); 334 | } 335 | 336 | /***** zset *****/ 337 | 338 | public void zset(byte[] name, byte[] key, Int64 score) { 339 | List resp = request("zset", name, key, _bytes(score.ToString())); 340 | resp_code = _string(resp[0]); 341 | this.assert_ok(); 342 | } 343 | 344 | public void zset(string name, string key, Int64 score) { 345 | this.zset(_bytes(name), _bytes(key), score); 346 | } 347 | 348 | public Int64 zincr(byte[] name, byte[] key, Int64 increment) { 349 | List resp = request("zincr", name, key, _bytes(increment.ToString())); 350 | resp_code = _string(resp[0]); 351 | this.assert_ok(); 352 | if (resp.Count != 2) 353 | { 354 | throw new Exception("Bad response!"); 355 | } 356 | return Int64.Parse(_string(resp[1])); 357 | } 358 | 359 | public Int64 zincr(string name, string key, Int64 increment) { 360 | return this.zincr(_bytes(name), _bytes(key), increment); 361 | } 362 | 363 | /// 364 | /// 365 | /// 366 | /// 367 | /// 368 | /// 369 | /// returns true if name.key is found, otherwise returns false. 370 | public bool zget(byte[] name, byte[] key, out Int64 score) { 371 | score = -1; 372 | List resp = request("zget", name, key); 373 | resp_code = _string(resp[0]); 374 | if (resp_code == "not_found") 375 | { 376 | return false; 377 | } 378 | this.assert_ok(); 379 | if (resp.Count != 2) 380 | { 381 | throw new Exception("Bad response!"); 382 | } 383 | score = Int64.Parse(_string(resp[1])); 384 | return true; 385 | } 386 | 387 | public bool zget(string name, string key, out Int64 score) { 388 | return this.zget(_bytes(name), _bytes(key), out score); 389 | } 390 | 391 | public void zdel(byte[] name, byte[] key) { 392 | List resp = request("zdel", name, key); 393 | resp_code = _string(resp[0]); 394 | this.assert_ok(); 395 | } 396 | 397 | public void zdel(string name, string key) { 398 | this.zdel(_bytes(name), _bytes(key)); 399 | } 400 | 401 | public Int64 zsize(byte[] name) { 402 | List resp = request("zsize", name); 403 | resp_code = _string(resp[0]); 404 | this.assert_ok(); 405 | if (resp.Count != 2) 406 | { 407 | throw new Exception("Bad response!"); 408 | } 409 | return Int64.Parse(_string(resp[1])); 410 | } 411 | 412 | public Int64 zsize(string name) { 413 | return this.zsize(_bytes(name)); 414 | } 415 | 416 | public bool zexists(byte[] name, byte[] key) { 417 | List resp = request("zexists", name, key); 418 | resp_code = _string(resp[0]); 419 | if (resp_code == "not_found") 420 | { 421 | return false; 422 | } 423 | this.assert_ok(); 424 | if (resp.Count != 2) 425 | { 426 | throw new Exception("Bad response!"); 427 | } 428 | return (_string(resp[1]) == "1" ? true : false); 429 | } 430 | 431 | public bool zexists(string name, string key) { 432 | return this.zexists(_bytes(name), _bytes(key)); 433 | } 434 | 435 | public KeyValuePair[] zrange(string name, Int32 offset, Int32 limit) { 436 | List resp = request("zrange", name, offset.ToString(), limit.ToString()); 437 | KeyValuePair[] kvs = parse_scan_resp(resp); 438 | KeyValuePair[] ret = new KeyValuePair[kvs.Length]; 439 | for (int i = 0; i < kvs.Length; i++) 440 | { 441 | string key = kvs[i].Key; 442 | Int64 score = Int64.Parse(_string(kvs[i].Value)); 443 | ret[i] = new KeyValuePair(key, score); 444 | } 445 | return ret; 446 | } 447 | 448 | public KeyValuePair[] zrrange(string name, Int32 offset, Int32 limit) { 449 | List resp = request("zrrange", name, offset.ToString(), limit.ToString()); 450 | KeyValuePair[] kvs = parse_scan_resp(resp); 451 | KeyValuePair[] ret = new KeyValuePair[kvs.Length]; 452 | for (int i = 0; i < kvs.Length; i++) 453 | { 454 | string key = kvs[i].Key; 455 | Int64 score = Int64.Parse(_string(kvs[i].Value)); 456 | ret[i] = new KeyValuePair(key, score); 457 | } 458 | return ret; 459 | } 460 | 461 | public KeyValuePair[] zscan(string name, string key_start, Int64 score_start, Int64 score_end, Int64 limit) { 462 | string score_s = ""; 463 | string score_e = ""; 464 | if (score_start != Int64.MinValue) 465 | { 466 | score_s = score_start.ToString(); 467 | } 468 | if (score_end != Int64.MaxValue) 469 | { 470 | score_e = score_end.ToString(); 471 | } 472 | List resp = request("zscan", name, key_start, score_s, score_e, limit.ToString()); 473 | KeyValuePair[] kvs = parse_scan_resp(resp); 474 | KeyValuePair[] ret = new KeyValuePair[kvs.Length]; 475 | for (int i = 0; i < kvs.Length; i++) 476 | { 477 | string key = kvs[i].Key; 478 | Int64 score = Int64.Parse(_string(kvs[i].Value)); 479 | ret[i] = new KeyValuePair(key, score); 480 | } 481 | return ret; 482 | } 483 | 484 | public KeyValuePair[] zrscan(string name, string key_start, Int64 score_start, Int64 score_end, Int64 limit) { 485 | string score_s = ""; 486 | string score_e = ""; 487 | if (score_start != Int64.MaxValue) 488 | { 489 | score_s = score_start.ToString(); 490 | } 491 | if (score_end != Int64.MinValue) 492 | { 493 | score_e = score_end.ToString(); 494 | } 495 | List resp = request("zrscan", name, key_start, score_s, score_e, limit.ToString()); 496 | KeyValuePair[] kvs = parse_scan_resp(resp); 497 | KeyValuePair[] ret = new KeyValuePair[kvs.Length]; 498 | for (int i = 0; i < kvs.Length; i++) 499 | { 500 | string key = kvs[i].Key; 501 | Int64 score = Int64.Parse(_string(kvs[i].Value)); 502 | ret[i] = new KeyValuePair(key, score); 503 | } 504 | return ret; 505 | } 506 | 507 | public void multi_zset(byte[] name, KeyValuePair[] kvs) 508 | { 509 | byte[][] req = new byte[(kvs.Length * 2) + 1][]; 510 | req[0] = name; 511 | for (int i = 0; i < kvs.Length; i++) 512 | { 513 | req[(2 * i) + 1] = kvs[i].Key; 514 | req[(2 * i) + 2] = _bytes(kvs[i].Value.ToString()); 515 | 516 | } 517 | List resp = request("multi_zset", req); 518 | resp_code = _string(resp[0]); 519 | this.assert_ok(); 520 | } 521 | 522 | public void multi_zset(string name, KeyValuePair[] kvs) 523 | { 524 | KeyValuePair[] req = new KeyValuePair[kvs.Length]; 525 | for (int i = 0; i < kvs.Length; i++) 526 | { 527 | req[i] = new KeyValuePair(_bytes(kvs[i].Key), kvs[i].Value); 528 | } 529 | this.multi_zset(_bytes(name), req); 530 | } 531 | 532 | public void multi_zdel(byte[] name, byte[][] keys) 533 | { 534 | byte[][] req = new byte[keys.Length + 1][]; 535 | req[0] = name; 536 | for (int i = 0; i < keys.Length; i++) 537 | { 538 | req[i + 1] = keys[i]; 539 | } 540 | List resp = request("multi_zdel", req); 541 | resp_code = _string(resp[0]); 542 | this.assert_ok(); 543 | } 544 | 545 | public void multi_zdel(string name, string[] keys) 546 | { 547 | byte[][] req = new byte[keys.Length][]; 548 | for (int i = 0; i < keys.Length; i++) 549 | { 550 | req[i] = _bytes(keys[i]); 551 | } 552 | this.multi_zdel(_bytes(name), req); 553 | } 554 | 555 | public KeyValuePair[] multi_zget(byte[] name, byte[][] keys) 556 | { 557 | byte[][] req = new byte[keys.Length + 1][]; 558 | req[0] = name; 559 | for (int i = 0; i < keys.Length; i++) 560 | { 561 | req[i + 1] = keys[i]; 562 | } 563 | List resp = request("multi_zget", req); 564 | KeyValuePair[] kvs = parse_scan_resp(resp); 565 | KeyValuePair[] ret = new KeyValuePair[kvs.Length]; 566 | for (int i = 0; i < kvs.Length; i++) 567 | { 568 | string key = kvs[i].Key; 569 | Int64 score = Int64.Parse(_string(kvs[i].Value)); 570 | ret[i] = new KeyValuePair(key, score); 571 | } 572 | return ret; 573 | } 574 | 575 | public KeyValuePair[] multi_zget(string name, string[] keys) 576 | { 577 | byte[][] req = new byte[keys.Length][]; 578 | for (int i = 0; i < keys.Length; i++) 579 | { 580 | req[i] = _bytes(keys[i]); 581 | } 582 | return this.multi_zget(_bytes(name), req); 583 | } 584 | 585 | } 586 | } 587 | 588 | 589 | 590 | --------------------------------------------------------------------------------