mirror of
https://github.com/fluencelabs/redis
synced 2025-06-17 19:21:21 +00:00
redis.c split into many different C files.
networking related stuff moved into networking.c moved more code more work on layout of source code SDS instantaneuos memory saving. By Pieter and Salvatore at VMware ;) cleanly compiling again after the first split, now splitting it in more C files moving more things around... work in progress split replication code splitting more Sets split Hash split replication split even more splitting more splitting minor change
This commit is contained in:
251
src/t_string.c
Normal file
251
src/t_string.c
Normal file
@ -0,0 +1,251 @@
|
||||
#include "redis.h"
|
||||
|
||||
/*-----------------------------------------------------------------------------
|
||||
* String Commands
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
void setGenericCommand(redisClient *c, int nx, robj *key, robj *val, robj *expire) {
|
||||
int retval;
|
||||
long seconds = 0; /* initialized to avoid an harmness warning */
|
||||
|
||||
if (expire) {
|
||||
if (getLongFromObjectOrReply(c, expire, &seconds, NULL) != REDIS_OK)
|
||||
return;
|
||||
if (seconds <= 0) {
|
||||
addReplySds(c,sdsnew("-ERR invalid expire time in SETEX\r\n"));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
touchWatchedKey(c->db,key);
|
||||
if (nx) deleteIfVolatile(c->db,key);
|
||||
retval = dbAdd(c->db,key,val);
|
||||
if (retval == REDIS_ERR) {
|
||||
if (!nx) {
|
||||
dbReplace(c->db,key,val);
|
||||
incrRefCount(val);
|
||||
} else {
|
||||
addReply(c,shared.czero);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
incrRefCount(val);
|
||||
}
|
||||
server.dirty++;
|
||||
removeExpire(c->db,key);
|
||||
if (expire) setExpire(c->db,key,time(NULL)+seconds);
|
||||
addReply(c, nx ? shared.cone : shared.ok);
|
||||
}
|
||||
|
||||
void setCommand(redisClient *c) {
|
||||
setGenericCommand(c,0,c->argv[1],c->argv[2],NULL);
|
||||
}
|
||||
|
||||
void setnxCommand(redisClient *c) {
|
||||
setGenericCommand(c,1,c->argv[1],c->argv[2],NULL);
|
||||
}
|
||||
|
||||
void setexCommand(redisClient *c) {
|
||||
setGenericCommand(c,0,c->argv[1],c->argv[3],c->argv[2]);
|
||||
}
|
||||
|
||||
int getGenericCommand(redisClient *c) {
|
||||
robj *o;
|
||||
|
||||
if ((o = lookupKeyReadOrReply(c,c->argv[1],shared.nullbulk)) == NULL)
|
||||
return REDIS_OK;
|
||||
|
||||
if (o->type != REDIS_STRING) {
|
||||
addReply(c,shared.wrongtypeerr);
|
||||
return REDIS_ERR;
|
||||
} else {
|
||||
addReplyBulk(c,o);
|
||||
return REDIS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
void getCommand(redisClient *c) {
|
||||
getGenericCommand(c);
|
||||
}
|
||||
|
||||
void getsetCommand(redisClient *c) {
|
||||
if (getGenericCommand(c) == REDIS_ERR) return;
|
||||
dbReplace(c->db,c->argv[1],c->argv[2]);
|
||||
incrRefCount(c->argv[2]);
|
||||
server.dirty++;
|
||||
removeExpire(c->db,c->argv[1]);
|
||||
}
|
||||
|
||||
void mgetCommand(redisClient *c) {
|
||||
int j;
|
||||
|
||||
addReplySds(c,sdscatprintf(sdsempty(),"*%d\r\n",c->argc-1));
|
||||
for (j = 1; j < c->argc; j++) {
|
||||
robj *o = lookupKeyRead(c->db,c->argv[j]);
|
||||
if (o == NULL) {
|
||||
addReply(c,shared.nullbulk);
|
||||
} else {
|
||||
if (o->type != REDIS_STRING) {
|
||||
addReply(c,shared.nullbulk);
|
||||
} else {
|
||||
addReplyBulk(c,o);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void msetGenericCommand(redisClient *c, int nx) {
|
||||
int j, busykeys = 0;
|
||||
|
||||
if ((c->argc % 2) == 0) {
|
||||
addReplySds(c,sdsnew("-ERR wrong number of arguments for MSET\r\n"));
|
||||
return;
|
||||
}
|
||||
/* Handle the NX flag. The MSETNX semantic is to return zero and don't
|
||||
* set nothing at all if at least one already key exists. */
|
||||
if (nx) {
|
||||
for (j = 1; j < c->argc; j += 2) {
|
||||
if (lookupKeyWrite(c->db,c->argv[j]) != NULL) {
|
||||
busykeys++;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (busykeys) {
|
||||
addReply(c, shared.czero);
|
||||
return;
|
||||
}
|
||||
|
||||
for (j = 1; j < c->argc; j += 2) {
|
||||
c->argv[j+1] = tryObjectEncoding(c->argv[j+1]);
|
||||
dbReplace(c->db,c->argv[j],c->argv[j+1]);
|
||||
incrRefCount(c->argv[j+1]);
|
||||
removeExpire(c->db,c->argv[j]);
|
||||
}
|
||||
server.dirty += (c->argc-1)/2;
|
||||
addReply(c, nx ? shared.cone : shared.ok);
|
||||
}
|
||||
|
||||
void msetCommand(redisClient *c) {
|
||||
msetGenericCommand(c,0);
|
||||
}
|
||||
|
||||
void msetnxCommand(redisClient *c) {
|
||||
msetGenericCommand(c,1);
|
||||
}
|
||||
|
||||
void incrDecrCommand(redisClient *c, long long incr) {
|
||||
long long value;
|
||||
robj *o;
|
||||
|
||||
o = lookupKeyWrite(c->db,c->argv[1]);
|
||||
if (o != NULL && checkType(c,o,REDIS_STRING)) return;
|
||||
if (getLongLongFromObjectOrReply(c,o,&value,NULL) != REDIS_OK) return;
|
||||
|
||||
value += incr;
|
||||
o = createStringObjectFromLongLong(value);
|
||||
dbReplace(c->db,c->argv[1],o);
|
||||
server.dirty++;
|
||||
addReply(c,shared.colon);
|
||||
addReply(c,o);
|
||||
addReply(c,shared.crlf);
|
||||
}
|
||||
|
||||
void incrCommand(redisClient *c) {
|
||||
incrDecrCommand(c,1);
|
||||
}
|
||||
|
||||
void decrCommand(redisClient *c) {
|
||||
incrDecrCommand(c,-1);
|
||||
}
|
||||
|
||||
void incrbyCommand(redisClient *c) {
|
||||
long long incr;
|
||||
|
||||
if (getLongLongFromObjectOrReply(c, c->argv[2], &incr, NULL) != REDIS_OK) return;
|
||||
incrDecrCommand(c,incr);
|
||||
}
|
||||
|
||||
void decrbyCommand(redisClient *c) {
|
||||
long long incr;
|
||||
|
||||
if (getLongLongFromObjectOrReply(c, c->argv[2], &incr, NULL) != REDIS_OK) return;
|
||||
incrDecrCommand(c,-incr);
|
||||
}
|
||||
|
||||
void appendCommand(redisClient *c) {
|
||||
int retval;
|
||||
size_t totlen;
|
||||
robj *o;
|
||||
|
||||
o = lookupKeyWrite(c->db,c->argv[1]);
|
||||
if (o == NULL) {
|
||||
/* Create the key */
|
||||
retval = dbAdd(c->db,c->argv[1],c->argv[2]);
|
||||
incrRefCount(c->argv[2]);
|
||||
totlen = stringObjectLen(c->argv[2]);
|
||||
} else {
|
||||
if (o->type != REDIS_STRING) {
|
||||
addReply(c,shared.wrongtypeerr);
|
||||
return;
|
||||
}
|
||||
/* If the object is specially encoded or shared we have to make
|
||||
* a copy */
|
||||
if (o->refcount != 1 || o->encoding != REDIS_ENCODING_RAW) {
|
||||
robj *decoded = getDecodedObject(o);
|
||||
|
||||
o = createStringObject(decoded->ptr, sdslen(decoded->ptr));
|
||||
decrRefCount(decoded);
|
||||
dbReplace(c->db,c->argv[1],o);
|
||||
}
|
||||
/* APPEND! */
|
||||
if (c->argv[2]->encoding == REDIS_ENCODING_RAW) {
|
||||
o->ptr = sdscatlen(o->ptr,
|
||||
c->argv[2]->ptr, sdslen(c->argv[2]->ptr));
|
||||
} else {
|
||||
o->ptr = sdscatprintf(o->ptr, "%ld",
|
||||
(unsigned long) c->argv[2]->ptr);
|
||||
}
|
||||
totlen = sdslen(o->ptr);
|
||||
}
|
||||
server.dirty++;
|
||||
addReplySds(c,sdscatprintf(sdsempty(),":%lu\r\n",(unsigned long)totlen));
|
||||
}
|
||||
|
||||
void substrCommand(redisClient *c) {
|
||||
robj *o;
|
||||
long start = atoi(c->argv[2]->ptr);
|
||||
long end = atoi(c->argv[3]->ptr);
|
||||
size_t rangelen, strlen;
|
||||
sds range;
|
||||
|
||||
if ((o = lookupKeyReadOrReply(c,c->argv[1],shared.nullbulk)) == NULL ||
|
||||
checkType(c,o,REDIS_STRING)) return;
|
||||
|
||||
o = getDecodedObject(o);
|
||||
strlen = sdslen(o->ptr);
|
||||
|
||||
/* convert negative indexes */
|
||||
if (start < 0) start = strlen+start;
|
||||
if (end < 0) end = strlen+end;
|
||||
if (start < 0) start = 0;
|
||||
if (end < 0) end = 0;
|
||||
|
||||
/* indexes sanity checks */
|
||||
if (start > end || (size_t)start >= strlen) {
|
||||
/* Out of range start or start > end result in null reply */
|
||||
addReply(c,shared.nullbulk);
|
||||
decrRefCount(o);
|
||||
return;
|
||||
}
|
||||
if ((size_t)end >= strlen) end = strlen-1;
|
||||
rangelen = (end-start)+1;
|
||||
|
||||
/* Return the result */
|
||||
addReplySds(c,sdscatprintf(sdsempty(),"$%zu\r\n",rangelen));
|
||||
range = sdsnewlen((char*)o->ptr+start,rangelen);
|
||||
addReplySds(c,range);
|
||||
addReply(c,shared.crlf);
|
||||
decrRefCount(o);
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user