Redisソース分析(28)---object redisObjectオブジェクトの作成と解放


今日の学习の効率は比较的に高くて、Rioを分析し终わって、またその中のRedisObjectのファイルを勉强して、RedisObjectのいくつかの転换と作成を话す限り.中の多くの方法は非常に似ています.長いAPIリストが表示されます.
/* ------------  API --------------------- */
robj *createObject(int type, void *ptr) /*      robj    ,            */	
robj *createStringObject(char *ptr, size_t len)
robj *createStringObjectFromLongLong(long long value)
robj *createStringObjectFromLongDouble(long double value)
robj *dupStringObject(robj *o)
robj *createListObject(void)
robj *createZiplistObject(void)
robj *createSetObject(void)
robj *createIntsetObject(void)
robj *createHashObject(void)
robj *createZsetObject(void)
robj *createZsetZiplistObject(void)
void freeStringObject(robj *o) /* free Obj      ,  free  r->ptr */
void freeListObject(robj *o)
void freeSetObject(robj *o)
void freeZsetObject(robj *o)
void freeHashObject(robj *o) /*   hashObject 2   ,1  o-ptr     ,  1      o->ptr */
void incrRefCount(robj *o) /* robj        ,  robj  refcount   */
void decrRefCount(robj *o) /*   robj      ,   0 ,     */
void decrRefCountVoid(void *o)
robj *resetRefCount(robj *obj)
int checkType(redisClient *c, robj *o, int type) /*   robj         Type   */
int isObjectRepresentableAsLongLong(robj *o, long long *llval)
robj *tryObjectEncoding(robj *o) /*     robj       ,         */
robj *getDecodedObject(robj *o) /*       robj */
int compareStringObjectsWithFlags(robj *a, robj *b, int flags)
int compareStringObjects(robj *a, robj *b)
int collateStringObjects(robj *a, robj *b)
int equalStringObjects(robj *a, robj *b)
size_t stringObjectLen(robj *o)
int getDoubleFromObject(robj *o, double *target) /*  robj   double   */
int getDoubleFromObjectOrReply(redisClient *c, robj *o, double *target, const char *msg)
int getLongDoubleFromObject(robj *o, long double *target)
int getLongDoubleFromObjectOrReply(redisClient *c, robj *o, long double *target, const char *msg)
int getLongLongFromObject(robj *o, long long *target)
int getLongLongFromObjectOrReply(redisClient *c, robj *o, long long *target, const char *msg)
int getLongFromObjectOrReply(redisClient *c, robj *o, long *target, const char *msg)
char *strEncoding(int encoding)
unsigned long estimateObjectIdleTime(robj *o)
robj *objectCommandLookup(redisClient *c, robj *key) /* obj     , */
robj *objectCommandLookupOrReply(redisClient *c, robj *key, robj *reply)
void objectCommand(redisClient *c)
前から後ろを見ると、objが最初に作成されます.
/*      robj     */	
robj *createObject(int type, void *ptr) {
    robj *o = zmalloc(sizeof(*o));
    o->type = type;
    o->encoding = REDIS_ENCODING_RAW;
    o->ptr = ptr;
    o->refcount = 1;

    /* Set the LRU to the current lruclock (minutes resolution). */
    o->lru = server.lruclock;
    return o;
}
作成すると必ず解放されるfreeメソッドがあります.
/* free Obj       */
void freeStringObject(robj *o) {
    if (o->encoding == REDIS_ENCODING_RAW) {
        sdsfree(o->ptr);
    }
}
freeメソッドには、どのタイプの空間を解放するか、set、dict、ziplistなど、多くの派生メソッドがあります.次のタイプがあります.
 switch(o->type) {
        case REDIS_STRING: freeStringObject(o); break;
        case REDIS_LIST: freeListObject(o); break;
        case REDIS_SET: freeSetObject(o); break;
        case REDIS_ZSET: freeZsetObject(o); break;
        case REDIS_HASH: freeHashObject(o); break;
        default: redisPanic("Unknown object type"); break;
        }
参照カウントに関する方法を重点的に紹介し、robj->refcountの数値で制御します.
/* robj        ,  robj  refcount   */
void incrRefCount(robj *o) {
	//  robj  refcount  
    o->refcount++;
}
参照カウントを増やすと1行のコードになりますが、減らすと、参照カウントが0になったとき、誰も使っていないことを説明して、空間を解放することができます.
/*   robj      ,   0 ,     */
void decrRefCount(robj *o) {
	//           <=0 ,         
    if (o->refcount <= 0) redisPanic("decrRefCount against refcount <= 0");
    if (o->refcount == 1) {
    	//          1,     ,            ,          
        switch(o->type) {
        case REDIS_STRING: freeStringObject(o); break;
        case REDIS_LIST: freeListObject(o); break;
        case REDIS_SET: freeSetObject(o); break;
        case REDIS_ZSET: freeZsetObject(o); break;
        case REDIS_HASH: freeHashObject(o); break;
        default: redisPanic("Unknown object type"); break;
        }
        zfree(o);
    } else {
    	//    >1        ,               
        o->refcount--;
    }
}
標準の参照カウント法はメモリの管理を制御し、(JVMでのオブジェクトのライフサイクル管理はルート検索法であり、参照カウントではないことを注意してください)、robjでの符号化方法の実装もこのファイルに定義されています.
/* Try to encode a string object in order to save space */
/*     robj       ,         */
robj *tryObjectEncoding(robj *o) {
    long value;
    sds s = o->ptr;
    size_t len;

    if (o->encoding != REDIS_ENCODING_RAW)
    	//  robj      ,     
        return o; /* Already encoded */

    /* It's not safe to encode shared objects: shared objects can be shared
     * everywhere in the "object space" of Redis. Encoded objects can only
     * appear as "values" (and not, for instance, as keys) */
     /*   robj       1       ,        obj,         */
     if (o->refcount > 1) return o;

    /* Currently we try to encode only strings */
    redisAssertWithInfo(NULL,o,o->type == REDIS_STRING);

    /* Check if we can represent this string as a long integer */
    len = sdslen(s);
    if (len > 21 || !string2l(s,len,&value)) {
        /* We can't encode the object...
         *
         * Do the last try, and at least optimize the SDS string inside
         * the string object to require little space, in case there
         * is more than 10% of free space at the end of the SDS string.
         *
         * We do that for larger strings, using the arbitrary value
         * of 32 bytes. This code was backported from the unstable branch
         * where this is performed when the object is too large to be
         * encoded as EMBSTR. */
        if (len > 32 &&
            o->encoding == REDIS_ENCODING_RAW &&
            sdsavail(s) > len/10)
        {
        	//  sdsRemoveFreeSpace 0->ptr             
            o->ptr = sdsRemoveFreeSpace(o->ptr);
        }
        /* Return the original object. */
        return o;
    }
    	.....
は、文字列のスペースを削除するスペースです.対応するためにgetDecodeObject()も存在すると思います.
/* 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 */
robj *getDecodedObject(robj *o) {
    robj *dec;

    if (o->encoding == REDIS_ENCODING_RAW) {
    	//        ,         ,   
        incrRefCount(o);
        return o;
    }
    if (o->type == REDIS_STRING && o->encoding == REDIS_ENCODING_INT) {
        char buf[32];
		//   string,Type   encoding_int   ,      
        ll2string(buf,32,(long)o->ptr);
        dec = createStringObject(buf,strlen(buf));
        return dec;
    } else {
        redisPanic("Unknown encoding type");
    }
}
以上がRedisObjectに対する簡単な分析である.