This function computes the digest of a data structure stored in the * object 'o'. It is the core of the DEBUG DIGEST command: when taking the * digest of a whole dataset, we take the digest of the key and the value * pair, and xor all those together. * * Note that this function does not reset the initial 'digest' passed, it * will continue mixing this object digest to anything that was alrea
| 148 | * will continue mixing this object digest to anything that was already |
| 149 | * present. */ |
| 150 | void xorObjectDigest(unsigned char *digest, robj_roptr o) { |
| 151 | uint32_t aux = htonl(o->type); |
| 152 | mixDigest(digest,&aux,sizeof(aux)); |
| 153 | const expireEntry *pexpire = o->FExpires() ? &o->expire : nullptr; |
| 154 | long long expiretime = INVALID_EXPIRE; |
| 155 | char buf[128]; |
| 156 | |
| 157 | if (pexpire != nullptr) |
| 158 | pexpire->FGetPrimaryExpire(&expiretime); |
| 159 | |
| 160 | /* Save the key and associated value */ |
| 161 | if (o->type == OBJ_STRING) { |
| 162 | mixStringObjectDigest(digest,o); |
| 163 | } else if (o->type == OBJ_LIST) { |
| 164 | listTypeIterator *li = listTypeInitIterator(o,0,LIST_TAIL); |
| 165 | listTypeEntry entry; |
| 166 | while(listTypeNext(li,&entry)) { |
| 167 | robj *eleobj = listTypeGet(&entry); |
| 168 | mixStringObjectDigest(digest,eleobj); |
| 169 | decrRefCount(eleobj); |
| 170 | } |
| 171 | listTypeReleaseIterator(li); |
| 172 | } else if (o->type == OBJ_SET) { |
| 173 | setTypeIterator *si = setTypeInitIterator(o); |
| 174 | sds sdsele; |
| 175 | while((sdsele = setTypeNextObject(si)) != NULL) { |
| 176 | xorDigest(digest,sdsele,sdslen(sdsele)); |
| 177 | sdsfree(sdsele); |
| 178 | } |
| 179 | setTypeReleaseIterator(si); |
| 180 | } else if (o->type == OBJ_ZSET) { |
| 181 | unsigned char eledigest[20]; |
| 182 | |
| 183 | if (o->encoding == OBJ_ENCODING_ZIPLIST) { |
| 184 | unsigned char *zl = (unsigned char*)ptrFromObj(o); |
| 185 | unsigned char *eptr, *sptr; |
| 186 | unsigned char *vstr; |
| 187 | unsigned int vlen; |
| 188 | long long vll; |
| 189 | double score; |
| 190 | |
| 191 | eptr = ziplistIndex(zl,0); |
| 192 | serverAssert(eptr != NULL); |
| 193 | sptr = ziplistNext(zl,eptr); |
| 194 | serverAssert(sptr != NULL); |
| 195 | |
| 196 | while (eptr != NULL) { |
| 197 | serverAssert(ziplistGet(eptr,&vstr,&vlen,&vll)); |
| 198 | score = zzlGetScore(sptr); |
| 199 | |
| 200 | memset(eledigest,0,20); |
| 201 | if (vstr != NULL) { |
| 202 | mixDigest(eledigest,vstr,vlen); |
| 203 | } else { |
| 204 | ll2string(buf,sizeof(buf),vll); |
| 205 | mixDigest(eledigest,buf,strlen(buf)); |
| 206 | } |
| 207 |
no test coverage detected