X-Git-Url: https://git.saurik.com/redis.git/blobdiff_plain/19e61097c58079d6e317983f50006dc917d65cf7..40531be0e338556df5510f49f4472ea50713962f:/src/syncio.c?ds=sidebyside diff --git a/src/syncio.c b/src/syncio.c index 81eeda08..3d0e0451 100644 --- a/src/syncio.c +++ b/src/syncio.c @@ -1,9 +1,4 @@ -/* Synchronous socket I/O operations, with timeouts. - * Redis performs most of the I/O in a nonblocking way, with the exception - * of the SYNC command where the slave does it in a blocking way, and - * the MIGRATE command that must be blocking in order to be atomic from the - * point of view of the two instances (one migrating the key and one receiving - * the key). This is why need the following blocking I/O functions. +/* Synchronous socket and file I/O operations useful across the core. * * Copyright (c) 2009-2010, Salvatore Sanfilippo * All rights reserved. @@ -35,6 +30,14 @@ #include "redis.h" +/* ----------------- Blocking sockets I/O with timeouts --------------------- */ + +/* Redis performs most of the I/O in a nonblocking way, with the exception + * of the SYNC command where the slave does it in a blocking way, and + * the MIGRATE command that must be blocking in order to be atomic from the + * point of view of the two instances (one migrating the key and one receiving + * the key). This is why need the following blocking I/O functions. */ + int syncWrite(int fd, char *ptr, ssize_t size, int timeout) { ssize_t nwritten, ret = size; time_t start = time(NULL); @@ -96,3 +99,70 @@ int syncReadLine(int fd, char *ptr, ssize_t size, int timeout) { } return nread; } + +/* ----------------- Blocking sockets I/O with timeouts --------------------- */ + +/* Write binary-safe string into a file in the bulkformat + * $\r\n\r\n */ +int fwriteBulkString(FILE *fp, char *s, unsigned long len) { + char cbuf[128]; + int clen; + + cbuf[0] = '$'; + clen = 1+ll2string(cbuf+1,sizeof(cbuf)-1,len); + cbuf[clen++] = '\r'; + cbuf[clen++] = '\n'; + if (fwrite(cbuf,clen,1,fp) == 0) return 0; + if (len > 0 && fwrite(s,len,1,fp) == 0) return 0; + if (fwrite("\r\n",2,1,fp) == 0) return 0; + return 1; +} + +/* Write a multi bulk count in the form "*\r\n" */ +int fwriteBulkCount(FILE *fp, char prefix, int count) { + char cbuf[128]; + int clen; + + cbuf[0] = prefix; + clen = 1+ll2string(cbuf+1,sizeof(cbuf)-1,count); + cbuf[clen++] = '\r'; + cbuf[clen++] = '\n'; + if (fwrite(cbuf,clen,1,fp) == 0) return 0; + return 1; +} + +/* Write a double value in bulk format $\r\n\r\n */ +int fwriteBulkDouble(FILE *fp, double d) { + char buf[128], dbuf[128]; + + snprintf(dbuf,sizeof(dbuf),"%.17g\r\n",d); + snprintf(buf,sizeof(buf),"$%lu\r\n",(unsigned long)strlen(dbuf)-2); + if (fwrite(buf,strlen(buf),1,fp) == 0) return 0; + if (fwrite(dbuf,strlen(dbuf),1,fp) == 0) return 0; + return 1; +} + +/* Write a long value in bulk format $\r\n\r\n */ +int fwriteBulkLongLong(FILE *fp, long long l) { + char bbuf[128], lbuf[128]; + unsigned int blen, llen; + llen = ll2string(lbuf,32,l); + blen = snprintf(bbuf,sizeof(bbuf),"$%u\r\n%s\r\n",llen,lbuf); + if (fwrite(bbuf,blen,1,fp) == 0) return 0; + return 1; +} + +/* Delegate writing an object to writing a bulk string or bulk long long. */ +int fwriteBulkObject(FILE *fp, robj *obj) { + /* Avoid using getDecodedObject to help copy-on-write (we are often + * in a child process when this function is called). */ + if (obj->encoding == REDIS_ENCODING_INT) { + return fwriteBulkLongLong(fp,(long)obj->ptr); + } else if (obj->encoding == REDIS_ENCODING_RAW) { + return fwriteBulkString(fp,obj->ptr,sdslen(obj->ptr)); + } else { + redisPanic("Unknown string encoding"); + } +} + +