Fix reference counting failure in the dict. This is caused by std::swap also swapping refcounts
This commit is contained in:
parent
242d6aabb2
commit
51d3e2cbbc
16
src/dict.cpp
16
src/dict.cpp
@ -204,7 +204,7 @@ int dictMerge(dict *dst, dict *src)
|
|||||||
|
|
||||||
if (dictSize(dst) == 0)
|
if (dictSize(dst) == 0)
|
||||||
{
|
{
|
||||||
std::swap(*dst, *src);
|
dict::swap(*dst, *src);
|
||||||
std::swap(dst->pauserehash, src->pauserehash);
|
std::swap(dst->pauserehash, src->pauserehash);
|
||||||
return DICT_OK;
|
return DICT_OK;
|
||||||
}
|
}
|
||||||
@ -212,7 +212,7 @@ int dictMerge(dict *dst, dict *src)
|
|||||||
size_t expectedSize = dictSize(src) + dictSize(dst);
|
size_t expectedSize = dictSize(src) + dictSize(dst);
|
||||||
if (dictSize(src) > dictSize(dst) && src->asyncdata == nullptr && dst->asyncdata == nullptr)
|
if (dictSize(src) > dictSize(dst) && src->asyncdata == nullptr && dst->asyncdata == nullptr)
|
||||||
{
|
{
|
||||||
std::swap(*dst, *src);
|
dict::swap(*dst, *src);
|
||||||
std::swap(dst->pauserehash, src->pauserehash);
|
std::swap(dst->pauserehash, src->pauserehash);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -465,6 +465,18 @@ bool dictRehashSomeAsync(dictAsyncRehashCtl *ctl, size_t hashes) {
|
|||||||
return ctl->hashIdx < ctl->queue.size();
|
return ctl->hashIdx < ctl->queue.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void discontinueAsyncRehash(dict *d) {
|
||||||
|
if (d->asyncdata != nullptr) {
|
||||||
|
auto adata = d->asyncdata;
|
||||||
|
while (adata != nullptr) {
|
||||||
|
adata->abondon = true;
|
||||||
|
adata = adata->next;
|
||||||
|
}
|
||||||
|
d->rehashidx = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void dictCompleteRehashAsync(dictAsyncRehashCtl *ctl, bool fFree) {
|
void dictCompleteRehashAsync(dictAsyncRehashCtl *ctl, bool fFree) {
|
||||||
dict *d = ctl->dict;
|
dict *d = ctl->dict;
|
||||||
assert(ctl->done);
|
assert(ctl->done);
|
||||||
|
22
src/dict.h
22
src/dict.h
@ -110,12 +110,16 @@ struct dictAsyncRehashCtl {
|
|||||||
std::atomic<bool> abondon { false };
|
std::atomic<bool> abondon { false };
|
||||||
|
|
||||||
dictAsyncRehashCtl(struct dict *d, dictAsyncRehashCtl *next);
|
dictAsyncRehashCtl(struct dict *d, dictAsyncRehashCtl *next);
|
||||||
|
dictAsyncRehashCtl(const dictAsyncRehashCtl&) = delete;
|
||||||
|
dictAsyncRehashCtl(dictAsyncRehashCtl&&) = delete;
|
||||||
~dictAsyncRehashCtl();
|
~dictAsyncRehashCtl();
|
||||||
};
|
};
|
||||||
#else
|
#else
|
||||||
struct dictAsyncRehashCtl;
|
struct dictAsyncRehashCtl;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
void discontinueAsyncRehash(dict *d);
|
||||||
|
|
||||||
typedef struct dict {
|
typedef struct dict {
|
||||||
dictType *type;
|
dictType *type;
|
||||||
void *privdata;
|
void *privdata;
|
||||||
@ -125,6 +129,24 @@ typedef struct dict {
|
|||||||
dictAsyncRehashCtl *asyncdata;
|
dictAsyncRehashCtl *asyncdata;
|
||||||
int16_t pauserehash; /* If >0 rehashing is paused (<0 indicates coding error) */
|
int16_t pauserehash; /* If >0 rehashing is paused (<0 indicates coding error) */
|
||||||
uint8_t noshrink = false;
|
uint8_t noshrink = false;
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
dict() = default;
|
||||||
|
dict(dict &) = delete; // No Copy Ctor
|
||||||
|
|
||||||
|
static void swap(dict& a, dict& b) {
|
||||||
|
discontinueAsyncRehash(&a);
|
||||||
|
discontinueAsyncRehash(&b);
|
||||||
|
std::swap(a.type, b.type);
|
||||||
|
std::swap(a.privdata, b.privdata);
|
||||||
|
std::swap(a.ht[0], b.ht[0]);
|
||||||
|
std::swap(a.ht[1], b.ht[1]);
|
||||||
|
std::swap(a.rehashidx, b.rehashidx);
|
||||||
|
// Never swap refcount - they are attached to the specific dict obj
|
||||||
|
std::swap(a.pauserehash, b.pauserehash);
|
||||||
|
std::swap(a.noshrink, b.noshrink);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
} dict;
|
} dict;
|
||||||
|
|
||||||
/* If safe is set to 1 this is a safe iterator, that means, you can call
|
/* If safe is set to 1 this is a safe iterator, that means, you can call
|
||||||
|
@ -26,17 +26,6 @@ public:
|
|||||||
std::vector<dictEntry*> vecde;
|
std::vector<dictEntry*> vecde;
|
||||||
};
|
};
|
||||||
|
|
||||||
void discontinueAsyncRehash(dict *d) {
|
|
||||||
if (d->asyncdata != nullptr) {
|
|
||||||
auto adata = d->asyncdata;
|
|
||||||
while (adata != nullptr) {
|
|
||||||
adata->abondon = true;
|
|
||||||
adata = adata->next;
|
|
||||||
}
|
|
||||||
d->rehashidx = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const redisDbPersistentDataSnapshot *redisDbPersistentData::createSnapshot(uint64_t mvccCheckpoint, bool fOptional)
|
const redisDbPersistentDataSnapshot *redisDbPersistentData::createSnapshot(uint64_t mvccCheckpoint, bool fOptional)
|
||||||
{
|
{
|
||||||
serverAssert(GlobalLocksAcquired());
|
serverAssert(GlobalLocksAcquired());
|
||||||
|
Loading…
x
Reference in New Issue
Block a user