//添加or替换,如果key不存在就执行添加操作,返回1 //如果key存在更新value的值,返回0 int dictReplace(dict *d, void *key, void *val) { dictEntry *entry, auxentry; /* Try to add the element. If the key * does not exists dictAdd will suceed. */ //只有在这个key存在的情况下,才会返回DICT_ERR,所以如果返回为DICT_OK, //说明key不存在,并且添加成功. if (dictAdd(d, key, val) == DICT_OK) return 1; /* It already exists, get the entry */ entry = dictFind(d, key); /* Set the new value and free the old one. Note that it is important * to do that in this order, as the value may just be exactly the same * as the previous one. In this context, think to reference counting, * you want to increment (set), and then decrement (free), and not the * reverse. */ auxentry = *entry; //!!!这里有个疑问,这里说明必须首先设置然后再释放,但是执行了设置操作之后 //该entry的值为新的value(可能是覆盖),接下来的释放操作如果将它free了呢? //也就是该哈希表的valDup函数为NULL,但是ValDestructor函数将free这个entry的value //那么这就编程了一个空悬指针!!! //有待加深理解。。。 //既然作者的注释说明这样的顺序是防止两个value为同一个对象并且使用了引用计数, //如果这样可以简单的进行判断是否指向同一个对象,如果是直接返回 //不知道我这样理解是否违反了作者的意图~~~ dictSetVal(d, entry, val); dictFreeVal(d, &auxentry); return 0; }
/* Add the specified value into a set. * * If the value was already member of the set, nothing is done and 0 is * returned, otherwise the new element is added and 1 is returned. */ int setTypeAdd(robj *subject, sds value) { long long llval; if (subject->encoding == OBJ_ENCODING_HT) { dict *ht = subject->ptr; dictEntry *de = dictAddRaw(ht,value); if (de) { dictSetKey(ht,de,sdsdup(value)); dictSetVal(ht,de,NULL); return 1; } } else if (subject->encoding == OBJ_ENCODING_INTSET) { if (isSdsRepresentableAsLongLong(value,&llval) == C_OK) { uint8_t success = 0; subject->ptr = intsetAdd(subject->ptr,llval,&success); if (success) { /* Convert to regular set when the intset contains * too many entries. */ if (intsetLen(subject->ptr) > server.set_max_intset_entries) setTypeConvert(subject,OBJ_ENCODING_HT); return 1; } } else { /* Failed to get integer from object, convert to regular set. */ setTypeConvert(subject,OBJ_ENCODING_HT); /* The set *was* an intset and this value is not integer * encodable, so dictAdd should always work. */ serverAssert(dictAdd(subject->ptr,sdsdup(value),NULL) == DICT_OK); return 1; } } else { serverPanic("Unknown set encoding"); } return 0; }
/* Add an element to the target hash table */ int dictAdd(dict *d, void *key, void *val) { dictEntry *entry = dictAddRaw(d,key); if (!entry) return DICT_ERR; dictSetVal(d, entry, val); return DICT_OK; }
//添加一个元素到字典中 //注意,当前的字典只允许调用该API添加一个值为void*类型的key-value对 int dictAdd(dict *d, void *key, void *val) { //创建该key值对应的entry,然后设置其对应的值 dictEntry *entry = dictAddRaw(d,key); if (!entry) return DICT_ERR; //这里设置这个entry的value值 dictSetVal(d, entry, val); return DICT_OK; }
/* 将新元素添加到字典,如果 key 已经存在,那么新元素覆盖旧元素。 * * Args: * d * key 新元素的关键字 * val 新元素的值 * * Return: * 1 key 不存在,新建元素添加成功 * 0 key 已经存在,旧元素被新元素覆盖 */ int dictReplace(dict *d, void *key, void *val) { dictEntry *entry, auxentry; // 尝试添加元素,如果 key 不存在, 那么 dictAdd 完成工作 if (dictAdd(d, key, val) == DICT_OK) return 1; // dictAdd 不成功,说明 key 已经存在 // 找出这个元素并更新它的值 entry = dictFind(d, key); auxentry = *entry; // 用变量保存 entry 的引用 dictSetVal(d, entry, val); // 设置新值 dictFreeVal(d, &auxentry); // 释放旧值 return 0; }
void lrw_dict_put(LRWDict *d, const Term *key, const void *value) { dictEntry *entry = dictFind(d->dict, key); // pstring *t = term_to_s(key); // printf("adding %.*s to size %d\n", t->len, t->val,dictSize(d->dict)); if(entry == NULL) { if(dictSize(d->dict) >= d->capacity) { _truncate(d); } entry = dictAddRaw(d->dict, (void *) key); if(!entry && dictIsRehashing(d->dict)) { entry = dictFind(d->dict, key); } assert(entry); } dictSetVal(d->dict, entry, (void *) value); _bump(d, entry->key); }
/* Add an element, discarding the old if the key already exists. * Return 1 if the key was added from scratch, 0 if there was already an * element with such key and dictReplace() just performed a value update * operation. */ int dictReplace(dict *d, void *key, void *val) { dictEntry *entry, auxentry; /* Try to add the element. If the key * does not exists dictAdd will suceed. */ if (dictAdd(d, key, val) == DICT_OK) return 1; /* It already exists, get the entry */ entry = dictFind(d, key); /* Set the new value and free the old one. Note that it is important * to do that in this order, as the value may just be exactly the same * as the previous one. In this context, think to reference counting, * you want to increment (set), and then decrement (free), and not the * reverse. */ auxentry = *entry; dictSetVal(d, entry, val); dictFreeVal(d, &auxentry); return 0; }