include "bufio.m"; bufio: Bufio; Iobuf: import bufio;
include "string.m"; str: String;
include "redis.m"; redis: Redis;
- call, sendcmd, packcmd, parsecmd, printresult, parseresult: import redis;
+ RedisClient, packcmd, parsecmd: import redis;
RedisC: module {
init: fn(nil: ref Draw->Context, args: list of string);
bufio = load Bufio Bufio->PATH;
str = load String String->PATH;
redis = load Redis Redis->PATH;
+
+ debug := 0;
+
if(redis == nil) {
sys->fprint(sys->fildes(2), "Can't load %s! %r\n", Redis->PATH);
raise "fail:load";
arg->usage();
return;
'D' =>
- redis->setdebug(1);
+ debug = 1;
* =>
arg->usage();
raise "fail:usage";
}
if(cmd == nil)
interactive = 1;
-
- conn := dial->dial(addr, nil);
- if(conn == nil) {
- sys->fprint(sys->fildes(2), "redis: dialing %s: %r\n", addr);
+ redis->setdebug(debug);
+
+ c := redis->connect(addr);
+ if(c == nil) {
+ sys->fprint(sys->fildes(2), "redis: connecting to %s: %r\n", addr);
raise "fail:errors";
}
- io := bufio->fopen(conn.dfd, bufio->ORDWR);
- if(io == nil)
- raise "fail:bufio";
-
stdin := bufio->fopen(sys->fildes(0), bufio->OREAD);
- if(io == nil)
+ if(stdin == nil)
raise "fail:bufio";
- # sys->fprint(sys->fildes(2), "redis: dialing %s, selecting %s\n", addr, dbno);
- selectdb(io, dbno);
+ if(debug)
+ sys->fprint(sys->fildes(2), "redis: dialing %s, selecting %s\n", addr, dbno);
+ selectdb(c, dbno);
cmd = rev(cmd);
arg->usage();
raise "fail:parse";
}
- if(sendcmd(io, ls)) {
+ if(c.sendcmd(ls)) {
cmd = tl cmd;
- printresult(io);
+ c.printresult();
}
}
if(!interactive)
(ls, donep) := parsecmd(l, quotechar);
if(donep) {
l = "";
- if(sendcmd(io, ls))
- printresult(io);
+ if(c.sendcmd(ls))
+ c.printresult();
}
}
}
-selectdb(io: ref Iobuf, dbno: string) {
- sendcmd(io, parsecmd("SELECT " + dbno, 0).t0);
- printresult(io);
+selectdb(c: ref Redis->RedisClient, dbno: string) {
+ c.sendcmd(parsecmd("SELECT " + dbno, 0).t0);
+ c.printresult();
}
rev[T](s: list of T): list of T {
debug = 0;
}
-call(io: ref Iobuf, cmd: list of string): list of (int, string) {
- if(!sendcmd(io, cmd))
+connect(addr: string): ref RedisClient {
+ conn := dial->dial(addr, nil);
+ if(conn == nil) {
+ if(debug)
+ sys->fprint(sys->fildes(2), "redis: dialing %s: %r\n", addr);
+ return nil;
+ }
+
+ io := bufio->fopen(conn.dfd, bufio->ORDWR);
+ if(io == nil)
+ return nil;
+
+ return client(io);
+}
+
+client(io: ref Iobuf): ref RedisClient {
+ return ref RedisClient(io);
+}
+
+RedisClient.call(c: self ref RedisClient, cmd: list of string): list of (int, string) {
+ if(!c.sendcmd(cmd))
return nil;
- return parseresult(io);
+ return c.parseresult();
}
setdebug(state: int) {
# particular, we expect to only parse atoms and arrays and we flatten all of the
# data we get back into a list of (tag, data) tuples, even if the data that
# comes back is not a list.
-parseresult(io: ref Iobuf): list of (int, string) {
+RedisClient.parseresult(cl: self ref RedisClient): list of (int, string) {
r: list of (int, string) = nil;
lt := array[256] of {
'-' => RErr,
sys->fprint(sys->fildes(2), "Connection dropped: %r\n");
raise "fail:errors";
- c := io.getb();
+ c := cl.io.getb();
if(debug)
sys->fprint(sys->fildes(2), "« %c", c);
case c {
'-' or ':' or '+' =>
- ln := chomp(io.gets('\n'));
+ ln := chomp(cl.io.gets('\n'));
r = (lt[c], ln) :: r;
'$' => # String
- ln := io.gets('\n');
+ ln := cl.io.gets('\n');
sz := str->toint(ln, 10).t0;
if(debug)
sys->fprint(sys->fildes(2), "%s\n", ln);
r = (RStr, chomp(ln)) :: r;
}
'*' => # Array
- ln := io.gets('\n');
+ ln := cl.io.gets('\n');
sz := str->toint(ln, 10).t0;
for(i := sz; i > 0; i--) {
- nx := parseresult(io);
+ nx := cl.parseresult();
while(nx != nil) {
r = hd nx :: r;
nx = tl nx;
return rev2(r, nil);
}
-printresult(io: ref Iobuf) {
+RedisClient.printresult(cl: self ref RedisClient) {
# Error: -ERROR\r\n
# Ints: :NUMBER\r\n
# Strings: $size\r\nRAW\r\n *or* +RAW\r\n
# Lists: *size\r\nSTRING1 or INT1\r\n⋯\r\n
- c := io.getb();
+ c := cl.io.getb();
if(debug)
sys->fprint(sys->fildes(2), "« %c", c);
}
case c {
'-' or ':' or '+' =>
- ln := chomp(io.gets('\n'));
+ ln := chomp(cl.io.gets('\n'));
if(debug)
sys->fprint(sys->fildes(2), "%s\n", ln);
sys->print("%s\n", ln);
'$' =>
- ln := io.gets('\n');
+ ln := cl.io.gets('\n');
if(debug)
sys->fprint(sys->fildes(2), "%s\n", ln);
sz := str->toint(ln, 10).t0;
return;
}
buf := array[sz + 2] of byte; # For the extra crlf.
- i := io.read(buf, len buf);
+ i := cl.io.read(buf, len buf);
if(debug)
sys->fprint(sys->fildes(2), "%s\n", string buf[:i]);
s := chomp(string buf[:i]);
sys->print("%s\n", s);
'*' =>
- ln := io.gets('\n');
+ ln := cl.io.gets('\n');
if(debug)
sys->fprint(sys->fildes(2), "%s\n", ln);
sz := str->toint(ln, 10).t0;
return;
}
for(i := sz; i; i--)
- printresult(io);
+ cl.printresult();
* =>
sys->fprint(sys->fildes(2), "Mystery response: %d %r\n", c);
raise "fail:errors";
return s;
}
-sendcmd(io: ref Iobuf, cmd: list of string): int {
+RedisClient.sendcmd(c: self ref RedisClient, cmd: list of string): int {
cs := packcmd(cmd);
if(debug)
sys->fprint(sys->fildes(2), "» %s\n", cs);
if(cs == nil)
return 0;
- io.puts(cs);
+ c.io.puts(cs);
return 1;
}
PATH: con "/dis/lib/redis.dis";
initmod: fn(s: Sys, d: Dial, b: Bufio, st: String);
- call: fn(io: ref Iobuf, cmd: list of string): list of (int, string);
- sendcmd: fn(io: ref Iobuf, cmd: list of string): int;
- packcmd: fn(cmd: list of string): string;
+ connect: fn(addr: string): ref RedisClient;
+ client: fn(io: ref Iobuf): ref RedisClient;
+
parsecmd: fn(s: string, qc: int): (list of string, int);
- printresult: fn(io: ref Iobuf);
- parseresult: fn(io: ref Iobuf): list of (int, string);
+ packcmd: fn(cmd: list of string): string;
RStr, RInt, RErr: con iota + 1;
setdebug: fn(state: int);
+
+ RedisClient: adt {
+ call: fn(c: self ref RedisClient, cmd: list of string): list of (int, string);
+
+ # You probably won't need these:
+ sendcmd: fn(c: self ref RedisClient, cmd: list of string): int;
+ printresult: fn(c: self ref RedisClient);
+ parseresult: fn(c: self ref RedisClient): list of (int, string);
+
+ # Internal:
+ io: ref Bufio->Iobuf;
+ };
};