/* load value which hash encoding with zipmap. */ static void *loadHashZipMapObject(unsigned char* zm, unsigned int *rlen) { unsigned char *key, *val, *p; unsigned int klen, vlen, len, i = 0; len = zipmapLen(zm); *rlen = len * 2; sds *results = (sds *) zmalloc(*rlen * sizeof(sds)); p = zipmapRewind(zm); while((p = zipmapNext(p,&key,&klen,&val,&vlen)) != NULL) { results[i] = sdsnewlen(key, klen); results[i+1] = sdsnewlen(val, vlen); i += 2; } return results; }
/* How a good candidate is this object for swapping? * The better candidate it is, the greater the returned value. * * Currently we try to perform a fast estimation of the object size in * memory, and combine it with aging informations. * * Basically swappability = idle-time * log(estimated size) * * Bigger objects are preferred over smaller objects, but not * proportionally, this is why we use the logarithm. This algorithm is * just a first try and will probably be tuned later. */ double computeObjectSwappability(robj *o) { /* actual age can be >= minage, but not < minage. As we use wrapping * 21 bit clocks with minutes resolution for the LRU. */ time_t minage = estimateObjectIdleTime(o); #ifdef _WIN32 ssize_t asize = 0, elesize; #else long asize = 0, elesize; #endif robj *ele; list *l; listNode *ln; dict *d; struct dictEntry *de; if (minage <= 0) return 0; switch(o->type) { case REDIS_STRING: if (o->encoding != REDIS_ENCODING_RAW) { asize = sizeof(*o); } else { #ifdef _WIN32 asize = sdslen(o->ptr)+sizeof(*o)+sizeof(size_t)*2; #else asize = sdslen(o->ptr)+sizeof(*o)+sizeof(long)*2; #endif } break; case REDIS_LIST: if (o->encoding == REDIS_ENCODING_ZIPLIST) { asize = sizeof(*o)+ziplistBlobLen(o->ptr); } else { l = o->ptr; ln = listFirst(l); asize = sizeof(list); if (ln) { ele = ln->value; elesize = (ele->encoding == REDIS_ENCODING_RAW) ? (sizeof(*o)+sdslen(ele->ptr)) : sizeof(*o); asize += (sizeof(listNode)+elesize)*listLength(l); } } break; case REDIS_SET: if (o->encoding == REDIS_ENCODING_INTSET) { intset *is = o->ptr; asize = sizeof(*is)+is->encoding*is->length; } else { d = o->ptr; asize = sizeof(dict)+(sizeof(struct dictEntry*)*dictSlots(d)); if (dictSize(d)) { de = dictGetRandomKey(d); ele = dictGetEntryKey(de); elesize = (ele->encoding == REDIS_ENCODING_RAW) ? (sizeof(*o)+sdslen(ele->ptr)) : sizeof(*o); asize += (sizeof(struct dictEntry)+elesize)*dictSize(d); } } break; case REDIS_ZSET: if (o->encoding == REDIS_ENCODING_ZIPLIST) { asize = sizeof(*o)+(ziplistBlobLen(o->ptr) / 2); } else { d = ((zset*)o->ptr)->dict; asize = sizeof(zset)+(sizeof(struct dictEntry*)*dictSlots(d)); if (dictSize(d)) { de = dictGetRandomKey(d); ele = dictGetEntryKey(de); elesize = (ele->encoding == REDIS_ENCODING_RAW) ? (sizeof(*o)+sdslen(ele->ptr)) : sizeof(*o); asize += (sizeof(struct dictEntry)+elesize)*dictSize(d); asize += sizeof(zskiplistNode)*dictSize(d); } } break; case REDIS_HASH: if (o->encoding == REDIS_ENCODING_ZIPMAP) { unsigned char *p = zipmapRewind((unsigned char*)o->ptr); unsigned int len = zipmapLen((unsigned char*)o->ptr); unsigned int klen, vlen; unsigned char *key, *val; if ((p = zipmapNext(p,&key,&klen,&val,&vlen)) == NULL) { klen = 0; vlen = 0; } asize = len*(klen+vlen+3); } else if (o->encoding == REDIS_ENCODING_HT) { d = o->ptr; asize = sizeof(dict)+(sizeof(struct dictEntry*)*dictSlots(d)); if (dictSize(d)) { de = dictGetRandomKey(d); ele = dictGetEntryKey(de); elesize = (ele->encoding == REDIS_ENCODING_RAW) ? (sizeof(*o)+sdslen(ele->ptr)) : sizeof(*o); ele = dictGetEntryVal(de); elesize = (ele->encoding == REDIS_ENCODING_RAW) ? (sizeof(*o)+sdslen(ele->ptr)) : sizeof(*o); asize += (sizeof(struct dictEntry)+elesize)*dictSize(d); } } break; } return (double)minage*log(1+(double)asize); }