int compareStringObjectsWithFlags(robj *a, robj *b, int flags) { serverAssertWithInfo(NULL,a,a->type == OBJ_STRING && b->type == OBJ_STRING); char bufa[128], bufb[128], *astr, *bstr; size_t alen, blen, minlen; if (a == b) return 0; if (sdsEncodedObject(a)) { astr = a->ptr; alen = sdslen(astr); } else { alen = ll2string(bufa,sizeof(bufa),(long) a->ptr); astr = bufa; } if (sdsEncodedObject(b)) { bstr = b->ptr; blen = sdslen(bstr); } else { blen = ll2string(bufb,sizeof(bufb),(long) b->ptr); bstr = bufb; } if (flags & REDIS_COMPARE_COLL) { return strcoll(astr,bstr); } else { int cmp; minlen = (alen < blen) ? alen : blen; cmp = memcmp(astr,bstr,minlen); if (cmp == 0) return alen-blen; return cmp; } }
int getDoubleFromObject(robj *o, double *target) { double value; char *eptr; if (o == NULL) { value = 0; } else { serverAssertWithInfo(NULL,o,o->type == OBJ_STRING); if (sdsEncodedObject(o)) { errno = 0; value = strtod(o->ptr, &eptr); if (isspace(((char*)o->ptr)[0]) || eptr[0] != '\0' || (errno == ERANGE && (value == HUGE_VAL || value == -HUGE_VAL || value == 0)) || errno == EINVAL || isnan(value)) return VR_ERROR; } else if (o->encoding == OBJ_ENCODING_INT) { value = (long)o->ptr; } else { serverPanic("Unknown string encoding"); } } *target = value; return VR_OK; }
/* * 尝试从对象中取出 double 值 * * - 转换成功则将值保存在 *target 中,函数返回 REDIS_OK * * - 否则,函数返回 REDIS_ERR */ int getDoubleFromObject(robj *o, double *target) { double value; char *eptr; if (o == NULL) { value = 0; } else { redisAssertWithInfo(NULL,o,o->type == REDIS_STRING); // 尝试从字符串中转换 double 值 if (sdsEncodedObject(o)) { errno = 0; value = strtod(o->ptr, &eptr); if (isspace(((char*)o->ptr)[0]) || eptr[0] != '\0' || (errno == ERANGE && (value == HUGE_VAL || value == -HUGE_VAL || value == 0)) || errno == EINVAL || isnan(value)) return REDIS_ERR; // INT 编码 } else if (o->encoding == REDIS_ENCODING_INT) { value = (long)o->ptr; } else { redisPanic("Unknown string encoding"); } } // 返回值 *target = value; return REDIS_OK; }
/* * 尝试从对象中取出 long double 值 * * - 转换成功则将值保存在 *target 中,函数返回 REDIS_OK * * - 否则,函数返回 REDIS_ERR */ int getLongDoubleFromObject(robj *o, long double *target) { long double value; char *eptr; if (o == NULL) { value = 0; } else { redisAssertWithInfo(NULL,o,o->type == REDIS_STRING); // RAW 编码,尝试从字符串中转换 long double if (sdsEncodedObject(o)) { errno = 0; value = strtold(o->ptr, &eptr); if (isspace(((char*)o->ptr)[0]) || eptr[0] != '\0' || errno == ERANGE || isnan(value)) return REDIS_ERR; // INT 编码,直接保存 } else if (o->encoding == REDIS_ENCODING_INT) { value = (long)o->ptr; } else { redisPanic("Unknown string encoding"); } } *target = value; return REDIS_OK; }
int getLongLongFromObject(robj *o, long long *target) { long long value; char *eptr; if (o == NULL) { // o 为 NULL 时,将值设为 0 。 value = 0; } else { // 确保对象为 REDIS_STRING 类型 redisAssertWithInfo(NULL,o,o->type == REDIS_STRING); if (sdsEncodedObject(o)) { errno = 0; // T = O(N) value = strtoll(o->ptr, &eptr, 10); if (isspace(((char*)o->ptr)[0]) || eptr[0] != '\0' || errno == ERANGE) return REDIS_ERR; } else if (o->encoding == REDIS_ENCODING_INT) { // 对于 REDIS_ENCODING_INT 编码的整数值 // 直接将它的值保存到 value 中 value = (long)o->ptr; } else { redisPanic("Unknown string encoding"); } } // 保存值到指针 if (target) *target = value; // 返回结果标识符 return REDIS_OK; }
//从对象中将字符串值转换为long double并存储在target中 int getLongDoubleFromObject(robj *o, long double *target) { long double value; char *eptr; if (o == NULL) { //对象不存在 value = 0; } else { serverAssertWithInfo(NULL,o,o->type == OBJ_STRING); //如果是字符串编码的两种类型 if (sdsEncodedObject(o)) { errno = 0; value = strtold(o->ptr, &eptr); //将字符串转换为long double类型 if (isspace(((char*)o->ptr)[0]) || eptr[0] != '\0' || errno == ERANGE || isnan(value)) //转换失败返回-1 return C_ERR; } else if (o->encoding == OBJ_ENCODING_INT) { //整数编码 value = (long)o->ptr; //保存整数值 } else { serverPanic("Unknown string encoding"); } } *target = value; //将值存到传入参数中,返回0成功 return C_OK; }
size_t stringObjectLen(robj *o) { serverAssertWithInfo(NULL,o,o->type == OBJ_STRING); if (sdsEncodedObject(o)) { return sdslen(o->ptr); } else { return sdigits10((long)o->ptr); } }
/* Compare the given object with the entry at the current position. */ int listTypeEqual(listTypeEntry *entry, robj *o) { if (entry->li->encoding == OBJ_ENCODING_QUICKLIST) { serverAssertWithInfo(NULL,o,sdsEncodedObject(o)); return quicklistCompare(entry->entry.zi,o->ptr,sdslen(o->ptr)); } else { serverPanic("Unknown list encoding"); } }
size_t stringObjectLen(robj *o) { assert(o->type == OBJ_STRING); if (sdsEncodedObject(o)) { return sdslen(o->ptr); } else { return sdigits10((long)o->ptr); } }
//获取字符串的长度 size_t stringObjectLen(robj *o) { redisAssertWithInfo(NULL,o,o->type == REDIS_STRING); if (sdsEncodedObject(o)) { return sdslen(o->ptr); } else { char buf[32]; return ll2string(buf,32,(long)o->ptr); } }
//返回字符串对象的字符串长度 size_t stringObjectLen(robj *o) { serverAssertWithInfo(NULL,o,o->type == OBJ_STRING); //如果是字符串编码的两种类型 if (sdsEncodedObject(o)) { return sdslen(o->ptr); } else { //如果是整数编码类型 return sdigits10((long)o->ptr); //计算出整数值的位数返回 } }
/* Delegate writing an object to writing a bulk string or bulk long long. * This is not placed in rio.c since that adds the redis.h dependency. */ int rioWriteBulkObject(rio *r, 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 rioWriteBulkLongLong(r,(long)obj->ptr); } else if (sdsEncodedObject(obj)) { return rioWriteBulkString(r,obj->ptr,sdslen(obj->ptr)); } else { redisPanic("Unknown string encoding"); } }
/* Compare the given object with the entry at the current position. */ int listTypeEqual(listTypeEntry *entry, robj *o) { listTypeIterator *li = entry->li; if (li->encoding == REDIS_ENCODING_ZIPLIST) { redisAssertWithInfo(NULL,o,sdsEncodedObject(o)); return ziplistCompare(entry->zi,o->ptr,sdslen(o->ptr)); } else if (li->encoding == REDIS_ENCODING_LINKEDLIST) { return equalStringObjects(o,listNodeValue(entry->ln)); } else { redisPanic("Unknown list encoding"); } }
//比较列表类型的entry结构与对象的entry节点的值是否等,相等返回1 int listTypeEqual(listTypeEntry *entry, robj *o) { //对列表对象编码为quicklist类型操作 if (entry->li->encoding == OBJ_ENCODING_QUICKLIST) { //确保objptr的编码类型是简单动态字符串类型的RAW或EMBSTR serverAssertWithInfo(NULL,o,sdsEncodedObject(o)); //比较listTypeEntry结构中的entry值和给定的对象的值 return quicklistCompare(entry->entry.zi,o->ptr,sdslen(o->ptr)); } else { serverPanic("Unknown list encoding"); } }
void serverLogObjectDebugInfo(robj *o) { serverLog(LL_WARNING,"Object type: %d", o->type); serverLog(LL_WARNING,"Object encoding: %d", o->encoding); serverLog(LL_WARNING,"Object refcount: %d", o->refcount); if (o->type == OBJ_STRING && sdsEncodedObject(o)) { serverLog(LL_WARNING,"Object raw string len: %zu", sdslen(o->ptr)); if (sdslen(o->ptr) < 4096) { sds repr = sdscatrepr(sdsempty(),o->ptr,sdslen(o->ptr)); serverLog(LL_WARNING,"Object raw string content: %s", repr); sdsfree(repr); } } }
/* Check the length of a number of objects to see if we need to convert a * ziplist to a real hash. Note that we only check string encoded objects * as their string length can be queried in constant time. */ void hashTypeTryConversion(robj *o, robj **argv, int start, int end) { int i; if (o->encoding != REDIS_ENCODING_ZIPLIST) return; for (i = start; i <= end; i++) { if (sdsEncodedObject(argv[i]) && sdslen(argv[i]->ptr) > server.hash_max_ziplist_value) { hashTypeConvert(o, REDIS_ENCODING_HT); break; } } }
/* * 返回字符串对象中字符串值的长度 */ size_t stringObjectLen(robj *o) { redisAssertWithInfo(NULL,o,o->type == REDIS_STRING); if (sdsEncodedObject(o)) { return sdslen(o->ptr); // INT 编码,计算将这个值转换为字符串要多少字节 // 相当于返回它的长度 } else { char buf[32]; return ll2string(buf,32,(long)o->ptr); } }
//根据flags比较两个字符串对象a和b,返回0表示相等,非零表示不相等 int compareStringObjectsWithFlags(robj *a, robj *b, int flags) { serverAssertWithInfo(NULL,a,a->type == OBJ_STRING && b->type == OBJ_STRING); char bufa[128], bufb[128], *astr, *bstr; size_t alen, blen, minlen; if (a == b) return 0; //如果是同一对象直接返回 //如果是指向字符串值的两种OBJ_ENCODING_EMBSTR或OBJ_ENCODING_RAW的两类对象 if (sdsEncodedObject(a)) { astr = a->ptr; alen = sdslen(astr); //获取字符串的长度 } else { //如果是整数类型的OBJ_ENCODING_INT编码 alen = ll2string(bufa,sizeof(bufa),(long) a->ptr); //转换为字符串 astr = bufa; } //如果是指向字符串值的两种OBJ_ENCODING_EMBSTR或OBJ_ENCODING_RAW的两类对象 if (sdsEncodedObject(b)) { bstr = b->ptr; blen = sdslen(bstr); //获取字符串的长度 } else { //如果是整数类型的OBJ_ENCODING_INT编码 blen = ll2string(bufb,sizeof(bufb),(long) b->ptr); //转换为字符串 bstr = bufb; } //以本地指定的字符次序进行比较 if (flags & REDIS_COMPARE_COLL) { //strcoll()会依环境变量LC_COLLATE所指定的文字排列次序来比较两字符串 return strcoll(astr,bstr); //比较a和b的字符串对象,相等返回0 } else { //以二进制方式进行比较 int cmp; minlen = (alen < blen) ? alen : blen; cmp = memcmp(astr,bstr,minlen); //相等返回0,否则返回第一个字符串和第二个字符串的长度差 if (cmp == 0) return alen-blen; return cmp; } }
/* Get a decoded version of an encoded object (returned as a new object). * If the object is already raw-encoded just increment the ref count. */ robj *getDecodedObject(robj *o) { robj *dec; if (sdsEncodedObject(o)) { return o; } if (o->type == OBJ_STRING && o->encoding == OBJ_ENCODING_INT) { char buf[32]; ll2string(buf,32,(long)o->ptr); dec = createStringObject(buf,strlen(buf)); return dec; } else { serverPanic("Unknown encoding type"); } }
//将对象是整型的解码为字符串并返回,如果是字符串编码则之间返回输入对象,只需增加引用计数 robj *getDecodedObject(robj *o) { robj *dec; if (sdsEncodedObject(o)) { //如果是OBJ_ENCODING_RAW或OBJ_ENCODING_EMBSTR类型的对象 incrRefCount(o); //增加应用计数 return o; } if (o->type == OBJ_STRING && o->encoding == OBJ_ENCODING_INT) { //如果是整数对象 char buf[32]; ll2string(buf,32,(long)o->ptr); //将整数转换为字符串 dec = createStringObject(buf,strlen(buf)); //创建一个字符串对象 return dec; } else { serverPanic("Unknown encoding type"); } }
int getLongLongFromObject(robj *o, long long *target) { long long value; if (o == NULL) { value = 0; } else { serverAssertWithInfo(NULL,o,o->type == OBJ_STRING); if (sdsEncodedObject(o)) { if (string2ll(o->ptr,sdslen(o->ptr),&value) == 0) return C_ERR; } else if (o->encoding == OBJ_ENCODING_INT) { value = (long)o->ptr; } else { serverPanic("Unknown string encoding"); } } if (target) *target = value; return C_OK; }
/* Get a decoded version of an encoded object (returned as a new object). * If the object is already raw-encoded just increment the ref count. */ robj *getDecodedObject(robj *o) { robj *dec; if (sdsEncodedObject(o)) { incrRefCount(o); return o; } if (o->type == OBJ_STRING && o->encoding == OBJ_ENCODING_INT) { char buf[32]; ll2string(buf,32,(long)o->ptr); dec = createStringObject(buf,strlen(buf)); return dec; } else { rr_log(RR_LOG_ERROR,"Unknown encoding type"); return NULL; } }
/// 将STRING类型的obj以string编码返回 robj *getDecodedObject(robj *o) { robj *dec; /// 已经是RAW编码,直接返回 if (sdsEncodedObject(o)) { incrRefCount(o); return o; } /// 将INT类型编码转为STRING编码并返回新的obj if (o->type == REDIS_STRING && o->encoding == REDIS_ENCODING_INT) { char buf[32]; ll2string(buf,32,(long)o->ptr); dec = createStringObject(buf,strlen(buf)); return dec; } else { redisPanic("Unknown encoding type"); } }
/* Get a decoded version of an encoded object (returned as a new object). * * 以新对象的形式,返回一个输入对象的解码版本(RAW 编码)。 * * If the object is already raw-encoded just increment the ref count. * * 如果对象已经是 RAW 编码的,那么对输入对象的引用计数增一, * 然后返回输入对象。 */ robj *getDecodedObject(robj *o) { robj *dec; if (sdsEncodedObject(o)) { incrRefCount(o); return o; } // 解码对象,将对象的值从整数转换为字符串 if (o->type == REDIS_STRING && o->encoding == REDIS_ENCODING_INT) { char buf[32]; ll2string(buf,32,(long)o->ptr); dec = createStringObject(buf,strlen(buf)); return dec; } else { redisPanic("Unknown encoding type"); } }
//从对象中将字符串值转换为long long并存储在target中 int getLongLongFromObject(robj *o, long long *target) { long long value; if (o == NULL) { //对象不存在 value = 0; } else { serverAssertWithInfo(NULL,o,o->type == OBJ_STRING); //如果是字符串编码的两种类型 if (sdsEncodedObject(o)) { //转换失败发送-1,成功保存值到value中 if (string2ll(o->ptr,sdslen(o->ptr),&value) == 0) return C_ERR; } else if (o->encoding == OBJ_ENCODING_INT) { //整型编码 value = (long)o->ptr; //保存整数值 } else { serverPanic("Unknown string encoding"); } } if (target) *target = value; //将值存到传入参数中,返回0成功 return C_OK; }
/* Create a new slowlog entry. * Incrementing the ref count of all the objects retained is up to * this function. */ slowlogEntry *slowlogCreateEntry(robj **argv, int argc, long long duration) { slowlogEntry *se = zmalloc(sizeof(*se)); int j, slargc = argc; if (slargc > SLOWLOG_ENTRY_MAX_ARGC) slargc = SLOWLOG_ENTRY_MAX_ARGC; se->argc = slargc; se->argv = zmalloc(sizeof(robj*)*slargc); for (j = 0; j < slargc; j++) { /* Logging too many arguments is a useless memory waste, so we stop * at SLOWLOG_ENTRY_MAX_ARGC, but use the last argument to specify * how many remaining arguments there were in the original command. */ if (slargc != argc && j == slargc-1) { se->argv[j] = createObject(OBJ_STRING, sdscatprintf(sdsempty(),"... (%d more arguments)", argc-slargc+1)); } else { /* Trim too long strings as well... */ if (argv[j]->type == OBJ_STRING && sdsEncodedObject(argv[j]) && sdslen(argv[j]->ptr) > SLOWLOG_ENTRY_MAX_STRING) { sds s = sdsnewlen(argv[j]->ptr, SLOWLOG_ENTRY_MAX_STRING); s = sdscatprintf(s,"... (%lu more bytes)", (unsigned long) sdslen(argv[j]->ptr) - SLOWLOG_ENTRY_MAX_STRING); se->argv[j] = createObject(OBJ_STRING,s); } else { se->argv[j] = argv[j]; incrRefCount(argv[j]); } } } se->time = time(NULL); se->duration = duration; se->id = server.slowlog_entry_id++; return se; }
void _prezAssertPrintClientInfo(prezClient *c) { int j; bugReportStart(); prezLog(PREZ_WARNING,"=== ASSERTION FAILED CLIENT CONTEXT ==="); //prezLog(PREZ_WARNING,"client->flags = %d", c->flags); prezLog(PREZ_WARNING,"client->fd = %d", c->fd); prezLog(PREZ_WARNING,"client->argc = %d", c->argc); for (j=0; j < c->argc; j++) { char buf[128]; char *arg; if (c->argv[j]->type == PREZ_STRING && sdsEncodedObject(c->argv[j])) { arg = (char*) c->argv[j]->ptr; } else { snprintf(buf,sizeof(buf),"Object type: %d, encoding: %d", c->argv[j]->type, c->argv[j]->encoding); arg = buf; } prezLog(PREZ_WARNING,"client->argv[%d] = \"%s\" (refcount: %d)", j, arg, c->argv[j]->refcount); } }
void prezLogObjectDebugInfo(robj *o) { prezLog(PREZ_WARNING,"Object type: %d", o->type); prezLog(PREZ_WARNING,"Object encoding: %d", o->encoding); prezLog(PREZ_WARNING,"Object refcount: %d", o->refcount); if (o->type == PREZ_STRING && sdsEncodedObject(o)) { prezLog(PREZ_WARNING,"Object raw string len: %zu", sdslen(o->ptr)); if (sdslen(o->ptr) < 4096) { sds repr = sdscatrepr(sdsempty(),o->ptr,sdslen(o->ptr)); prezLog(PREZ_WARNING,"Object raw string content: %s", repr); sdsfree(repr); } } /*else if (o->type == PREZ_LIST) { prezLog(PREZ_WARNING,"List length: %d", (int) listTypeLength(o)); } else if (o->type == PREZ_SET) { prezLog(PREZ_WARNING,"Set size: %d", (int) setTypeSize(o)); } else if (o->type == PREZ_HASH) { prezLog(PREZ_WARNING,"Hash size: %d", (int) hashTypeLength(o)); } else if (o->type == PREZ_ZSET) { prezLog(PREZ_WARNING,"Sorted set size: %d", (int) zsetLength(o)); if (o->encoding == PREZ_ENCODING_SKIPLIST) prezLog(PREZ_WARNING,"Skiplist level: %d", (int) ((zset*)o->ptr)->zsl->level); } */ }
unsigned int dictEncObjHash(const void *key) { robj *o = (robj*) key; if (sdsEncodedObject(o)) { return dictGenHashFunction(o->ptr, sdslen((sds)o->ptr)); } else { if (o->encoding == OBJ_ENCODING_INT) { char buf[32]; int len; len = ll2string(buf,32,(long)o->ptr); return dictGenHashFunction((unsigned char*)buf, len); } else { unsigned int hash; o = getDecodedObject(o); hash = dictGenHashFunction(o->ptr, sdslen((sds)o->ptr)); decrRefCount(o); return hash; } } }
int getLongLongFromObject(robj *o, long long *target) { long long value; char *eptr; if (o == NULL) { value = 0; } else { redisAssertWithInfo(NULL,o,o->type == REDIS_STRING); if (sdsEncodedObject(o)) { errno = 0; value = strtoll(o->ptr, &eptr, 10); if (isspace(((char*)o->ptr)[0]) || eptr[0] != '\0' || errno == ERANGE) return REDIS_ERR; } else if (o->encoding == REDIS_ENCODING_INT) { value = (long)o->ptr; } else { redisPanic("Unknown string encoding"); } } if (target) *target = value; return REDIS_OK; }