这里主要是generic分配,功能比较直白。
- /* Defrag helper for generic allocations.
-  *
-  * returns NULL in case the allocation wasn't moved.
-  * when it returns a non-null value, the old pointer was already released
-  * and should NOT be accessed. */
- void* activeDefragAlloc(void *ptr) {
-     size_t size;
-     void *newptr;
-     if(!je_get_defrag_hint(ptr)) {
-         server.stat_active_defrag_misses++;
-         return NULL;
-     }
-     /* move this allocation to a new allocation.
-      * make sure not to use the thread cache. so that we don't get back the same
-      * pointers we try to free */
-     size = zmalloc_size(ptr);
-     newptr = zmalloc_no_tcache(size);
-     memcpy(newptr, ptr, size);
-     zfree_no_tcache(ptr);
-     return newptr;
- }
-  
- /*Defrag helper for sds strings
-  *
-  * returns NULL in case the allocation wasn't moved.
-  * when it returns a non-null value, the old pointer was already released
-  * and should NOT be accessed. */
- sds activeDefragSds(sds sdsptr) {
-     void* ptr = sdsAllocPtr(sdsptr);
-     void* newptr = activeDefragAlloc(ptr);
-     if (newptr) {
-         size_t offset = sdsptr - (char*)ptr;
-         sdsptr = (char*)newptr + offset;
-         return sdsptr;
-     }
-     return NULL;
- }
-  
- /* Defrag helper for robj and/or string objects
-  *
-  * returns NULL in case the allocation wasn't moved.
-  * when it returns a non-null value, the old pointer was already released
-  * and should NOT be accessed. */
- robj *activeDefragStringOb(robj* ob, long *defragged) {
-     robj *ret = NULL;
-     if (ob->refcount!=1)
-         return NULL;
-  
-     /* try to defrag robj (only if not an EMBSTR type (handled below). */
-     if (ob->type!=OBJ_STRING || ob->encoding!=OBJ_ENCODING_EMBSTR) {
-         if ((ret = activeDefragAlloc(ob))) {
-             ob = ret;
-             (*defragged)++;
-         }
-     }
-  
-     /* try to defrag string object */
-     if (ob->type == OBJ_STRING) {
-         if(ob->encoding==OBJ_ENCODING_RAW) {
-             sds newsds = activeDefragSds((sds)ob->ptr);
-             if (newsds) {
-                 ob->ptr = newsds;
-                 (*defragged)++;
-             }
-         } else if (ob->encoding==OBJ_ENCODING_EMBSTR) {
-             /* The sds is embedded in the object allocation, calculate the
-              * offset and update the pointer in the new allocation. */
-             long ofs = (intptr_t)ob->ptr - (intptr_t)ob;
-             if ((ret = activeDefragAlloc(ob))) {
-                 ret->ptr = (void*)((intptr_t)ret + ofs);
-                 (*defragged)++;
-             }
-         } else if (ob->encoding!=OBJ_ENCODING_INT) {
-             serverPanic("Unknown string encoding");
-         }
-     }
-     return ret;
- }
-  
- /* Defrag helper for dictEntries to be used during dict iteration (called on
-  * each step). Returns a stat of how many pointers were moved. */
- long dictIterDefragEntry(dictIterator *iter) {
-     /* This function is a little bit dirty since it messes with the internals
-      * of the dict and it's iterator, but the benefit is that it is very easy
-      * to use, and require no other changes in the dict. */
-     long defragged = 0;
-     dictht *ht;
-     /* Handle the next entry (if there is one), and update the pointer in the
-      * current entry. */
-     if (iter->nextEntry) {
-         dictEntry *newde = activeDefragAlloc(iter->nextEntry);
-         if (newde) {
-             defragged++;
-             iter->nextEntry = newde;
-             iter->entry->next = newde;
-         }
-     }
-     /* handle the case of the first entry in the hash bucket. */
-     ht = &iter->d->ht[iter->table];
-     if (ht->table[iter->index] == iter->entry) {
-         dictEntry *newde = activeDefragAlloc(iter->entry);
-         if (newde) {
-             iter->entry = newde;
-             ht->table[iter->index] = newde;
-             defragged++;
-         }
-     }
-     return defragged;
- }
-  
- /* Defrag helper for dict main allocations (dict struct, and hash tables).
-  * receives a pointer to the dict* and implicitly updates it when the dict
-  * struct itself was moved. Returns a stat of how many pointers were moved. */
- long dictDefragTables(dict* d) {
-     dictEntry **newtable;
-     long defragged = 0;
-     /* handle the first hash table */
-     newtable = activeDefragAlloc(d->ht[0].table);
-     if (newtable)
-         defragged++, d->ht[0].table = newtable;
-     /* handle the second hash table */
-     if (d->ht[1].table) {
-         newtable = activeDefragAlloc(d->ht[1].table);
-         if (newtable)
-             defragged++, d->ht[1].table = newtable;
-     }
-     return defragged;
- }
-  
- /* Internal function used by zslDefrag */
- void zslUpdateNode(zskiplist *zsl, zskiplistNode *oldnode, zskiplistNode *newnode, zskiplistNode **update) {
-     int i;
-     for (i = 0; i < zsl->level; i++) {
-         if (update[i]->level[i].forward == oldnode)
-             update[i]->level[i].forward = newnode;
-     }
-     serverAssert(zsl->header!=oldnode);
-     if (newnode->level[0].forward) {
-         serverAssert(newnode->level[0].forward->backward==oldnode);
-         newnode->level[0].forward->backward = newnode;
-     } else {
-         serverAssert(zsl->tail==oldnode);
-         zsl->tail = newnode;
-     }
- }
-  
- /* Defrag helper for sorted set.
-  * Update the robj pointer, defrag the skiplist struct and return the new score
-  * reference. We may not access oldele pointer (not even the pointer stored in
-  * the skiplist), as it was already freed. Newele may be null, in which case we
-  * only need to defrag the skiplist, but not update the obj pointer.
-  * When return value is non-NULL, it is the score reference that must be updated
-  * in the dict record. */
- double *zslDefrag(zskiplist *zsl, double score, sds oldele, sds newele) {
-     zskiplistNode *update[ZSKIPLIST_MAXLEVEL], *x, *newx;
-     int i;
-     sds ele = newele? newele: oldele;
-  
-     /* find the skiplist node referring to the object that was moved,
-      * and all pointers that need to be updated if we'll end up moving the skiplist node. */
-     x = zsl->header;
-     for (i = zsl->level-1; i >= 0; i--) {
-         while (x->level[i].forward &&
-             x->level[i].forward->ele != oldele && /* make sure not to access the
-                                                      ->obj pointer if it matches
-                                                      oldele */
-             (x->level[i].forward->score < score ||
-                 (x->level[i].forward->score == score &&
-                 sdscmp(x->level[i].forward->ele,ele) < 0)))
-             x = x->level[i].forward;
-         update[i] = x;
-     }
-  
-     /* update the robj pointer inside the skip list record. */
-     x = x->level[0].forward;
-     serverAssert(x && score == x->score && x->ele==oldele);
-     if (newele)
-         x->ele = newele;
-  
-     /* try to defrag the skiplist record itself */
-     newx = activeDefragAlloc(x);
-     if (newx) {
-         zslUpdateNode(zsl, x, newx, update);
-         return &newx->score;
-     }
-     return NULL;
- }
-  
- /* Defrag helper for sorted set.
-  * Defrag a single dict entry key name, and corresponding skiplist struct */
- long activeDefragZsetEntry(zset *zs, dictEntry *de) {
-     sds newsds;
-     double* newscore;
-     long defragged = 0;
-     sds sdsele = dictGetKey(de);
-     if ((newsds = activeDefragSds(sdsele)))
-         defragged++, de->key = newsds;
-     newscore = zslDefrag(zs->zsl, *(double*)dictGetVal(de), sdsele, newsds);
-     if (newscore) {
-         dictSetVal(zs->dict, de, newscore);
-         defragged++;
-     }
-     return defragged;
- }
-  
- #define DEFRAG_SDS_DICT_NO_VAL 0
- #define DEFRAG_SDS_DICT_VAL_IS_SDS 1
- #define DEFRAG_SDS_DICT_VAL_IS_STROB 2
- #define DEFRAG_SDS_DICT_VAL_VOID_PTR 3
-  
- /* Defrag a dict with sds key and optional value (either ptr, sds or robj string) */
- long activeDefragSdsDict(dict* d, int val_type) {
-     dictIterator *di;
-     dictEntry *de;
-     long defragged = 0;
-     di = dictGetIterator(d);
-     while((de = dictNext(di)) != NULL) {
-         sds sdsele = dictGetKey(de), newsds;
-         if ((newsds = activeDefragSds(sdsele)))
-             de->key = newsds, defragged++;
-         /* defrag the value */
-         if (val_type == DEFRAG_SDS_DICT_VAL_IS_SDS) {
-             sdsele = dictGetVal(de);
-             if ((newsds = activeDefragSds(sdsele)))
-                 de->v.val = newsds, defragged++;
-         } else if (val_type == DEFRAG_SDS_DICT_VAL_IS_STROB) {
-             robj *newele, *ele = dictGetVal(de);
-             if ((newele = activeDefragStringOb(ele, &defragged)))
-                 de->v.val = newele;
-         } else if (val_type == DEFRAG_SDS_DICT_VAL_VOID_PTR) {
-             void *newptr, *ptr = dictGetVal(de);
-             if ((newptr = activeDefragAlloc(ptr)))
-                 de->v.val = newptr, defragged++;
-         }
-         defragged += dictIterDefragEntry(di);
-     }
-     dictReleaseIterator(di);
-     return defragged;
- }
-  
- /* Defrag a list of ptr, sds or robj string values */
- long activeDefragList(list *l, int val_type) {
-     long defragged = 0;
-     listNode *ln, *newln;
-     for (ln = l->head; ln; ln = ln->next) {
-         if ((newln = activeDefragAlloc(ln))) {
-             if (newln->prev)
-                 newln->prev->next = newln;
-             else
-                 l->head = newln;
-             if (newln->next)
-                 newln->next->prev = newln;
-             else
-                 l->tail = newln;
-             ln = newln;
-             defragged++;
-         }
-         if (val_type == DEFRAG_SDS_DICT_VAL_IS_SDS) {
-             sds newsds, sdsele = ln->value;
-             if ((newsds = activeDefragSds(sdsele)))
-                 ln->value = newsds, defragged++;
-         } else if (val_type == DEFRAG_SDS_DICT_VAL_IS_STROB) {
-             robj *newele, *ele = ln->value;
-             if ((newele = activeDefragStringOb(ele, &defragged)))
-                 ln->value = newele;
-         } else if (val_type == DEFRAG_SDS_DICT_VAL_VOID_PTR) {
-             void *newptr, *ptr = ln->value;
-             if ((newptr = activeDefragAlloc(ptr)))
-                 ln->value = newptr, defragged++;
-         }
-     }
-     return defragged;
- }

 
                

















