void setrangeCommand(redisClient *c) { robj *o; long offset; sds value = c->argv[3]->ptr; if (getLongFromObjectOrReply(c,c->argv[2],&offset,NULL) != REDIS_OK) return; if (offset < 0) { addReplyError(c,"offset is out of range"); return; } o = lookupKeyWrite(c->db,c->argv[1]); if (o == NULL) { /* Return 0 when setting nothing on a non-existing string */ if (sdslen(value) == 0) { addReply(c,shared.czero); return; } /* Return when the resulting string exceeds allowed size */ if (checkStringLength(c,offset+sdslen(value)) != REDIS_OK) return; o = createObject(REDIS_STRING,sdsempty()); dbAdd(c->db,c->argv[1],o); } else { size_t olen; /* Key exists, check type */ if (checkType(c,o,REDIS_STRING)) return; /* Return existing string length when setting nothing */ olen = stringObjectLen(o); if (sdslen(value) == 0) { addReplyLongLong(c,olen); return; } /* Return when the resulting string exceeds allowed size */ if (checkStringLength(c,offset+sdslen(value)) != REDIS_OK) return; /* Create a copy when the object is shared or encoded. */ o = dbUnshareStringValue(c->db,c->argv[1],o); } if (sdslen(value) > 0) { o->ptr = sdsgrowzero(o->ptr,offset+sdslen(value)); memcpy((char*)o->ptr+offset,value,sdslen(value)); signalModifiedKey(c->db,c->argv[1]); notifyKeyspaceEvent(REDIS_NOTIFY_STRING, "setrange",c->argv[1],c->db->id); server.dirty++; } addReplyLongLong(c,sdslen(o->ptr)); }
void appendCommand(redisClient *c) { int retval; size_t totlen; robj *o; o = lookupKeyWrite(c->db,c->argv[1]); c->argv[2] = tryObjectEncoding(c->argv[2]); 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); } touchWatchedKey(c->db,c->argv[1]); server.dirty++; addReplyLongLong(c,totlen); }
void replicationFeedSlaves(list *slaves, int dictid, robj **argv, int argc) { listNode *ln; listIter li; int outc = 0, j; robj **outv; /* We need 1+(ARGS*3) objects since commands are using the new protocol * and we one 1 object for the first "*<count>\r\n" multibulk count, then * for every additional object we have "$<count>\r\n" + object + "\r\n". */ robj *static_outv[REDIS_STATIC_ARGS*3+1]; robj *lenobj; if (argc <= REDIS_STATIC_ARGS) { outv = static_outv; } else { outv = zmalloc(sizeof(robj*)*(argc*3+1)); } lenobj = createObject(REDIS_STRING, sdscatprintf(sdsempty(), "*%d\r\n", argc)); lenobj->refcount = 0; outv[outc++] = lenobj; for (j = 0; j < argc; j++) { lenobj = createObject(REDIS_STRING, sdscatprintf(sdsempty(),"$%lu\r\n", (unsigned long) stringObjectLen(argv[j]))); lenobj->refcount = 0; outv[outc++] = lenobj; outv[outc++] = argv[j]; outv[outc++] = shared.crlf; } /* Increment all the refcounts at start and decrement at end in order to * be sure to free objects if there is no slave in a replication state * able to be feed with commands */ for (j = 0; j < outc; j++) incrRefCount(outv[j]); listRewind(slaves,&li); while((ln = listNext(&li))) { redisClient *slave = ln->value; /* Don't feed slaves that are still waiting for BGSAVE to start */ if (slave->replstate == REDIS_REPL_WAIT_BGSAVE_START) continue; /* Feed all the other slaves, MONITORs and so on */ if (slave->slaveseldb != dictid) { robj *selectcmd; switch(dictid) { case 0: selectcmd = shared.select0; break; case 1: selectcmd = shared.select1; break; case 2: selectcmd = shared.select2; break; case 3: selectcmd = shared.select3; break; case 4: selectcmd = shared.select4; break; case 5: selectcmd = shared.select5; break; case 6: selectcmd = shared.select6; break; case 7: selectcmd = shared.select7; break; case 8: selectcmd = shared.select8; break; case 9: selectcmd = shared.select9; break; default: selectcmd = createObject(REDIS_STRING, sdscatprintf(sdsempty(),"select %d\r\n",dictid)); selectcmd->refcount = 0; break; } addReply(slave,selectcmd); slave->slaveseldb = dictid; } for (j = 0; j < outc; j++) addReply(slave,outv[j]); } for (j = 0; j < outc; j++) decrRefCount(outv[j]); if (outv != static_outv) zfree(outv); }