fix memory leak
This commit is contained in:
parent
9dae1f317b
commit
34581781e6
|
@ -24,7 +24,9 @@
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define TQ_BUCKET_SIZE 0xFF
|
#define TQ_BUCKET_MASK 0xFF
|
||||||
|
#define TQ_BUCKET_SIZE 256
|
||||||
|
|
||||||
#define TQ_PAGE_SIZE 4096
|
#define TQ_PAGE_SIZE 4096
|
||||||
//key + offset + size
|
//key + offset + size
|
||||||
#define TQ_IDX_SIZE 24
|
#define TQ_IDX_SIZE 24
|
||||||
|
@ -35,15 +37,6 @@ extern "C" {
|
||||||
//4096 - 4080
|
//4096 - 4080
|
||||||
#define TQ_IDX_PAGE_HEAD_SIZE 16
|
#define TQ_IDX_PAGE_HEAD_SIZE 16
|
||||||
|
|
||||||
|
|
||||||
inline static int TqMaxEntryOnePage() { //170
|
|
||||||
return TQ_PAGE_SIZE / TQ_IDX_SIZE;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline static int TqEmptyTail() { //16
|
|
||||||
return TQ_PAGE_SIZE - TqMaxEntryOnePage();
|
|
||||||
}
|
|
||||||
|
|
||||||
#define TQ_ACTION_CONST 0
|
#define TQ_ACTION_CONST 0
|
||||||
#define TQ_ACTION_INUSE 1
|
#define TQ_ACTION_INUSE 1
|
||||||
#define TQ_ACTION_INUSE_CONT 2
|
#define TQ_ACTION_INUSE_CONT 2
|
||||||
|
|
|
@ -130,7 +130,6 @@ TqMetaStore* tqStoreOpen(const char* path,
|
||||||
pMeta->deleter = deleter;
|
pMeta->deleter = deleter;
|
||||||
|
|
||||||
//read idx file and load into memory
|
//read idx file and load into memory
|
||||||
/*char idxBuf[TQ_PAGE_SIZE];*/
|
|
||||||
TqIdxPageBuf idxBuf;
|
TqIdxPageBuf idxBuf;
|
||||||
TqSerializedHead* serializedObj = malloc(TQ_PAGE_SIZE);
|
TqSerializedHead* serializedObj = malloc(TQ_PAGE_SIZE);
|
||||||
if(serializedObj == NULL) {
|
if(serializedObj == NULL) {
|
||||||
|
@ -196,7 +195,7 @@ TqMetaStore* tqStoreOpen(const char* path,
|
||||||
}
|
}
|
||||||
|
|
||||||
//put into list
|
//put into list
|
||||||
int bucketKey = pNode->handle.key & TQ_BUCKET_SIZE;
|
int bucketKey = pNode->handle.key & TQ_BUCKET_MASK;
|
||||||
TqMetaList* pBucketNode = pMeta->bucket[bucketKey];
|
TqMetaList* pBucketNode = pMeta->bucket[bucketKey];
|
||||||
if(pBucketNode == NULL) {
|
if(pBucketNode == NULL) {
|
||||||
pMeta->bucket[bucketKey] = pNode;
|
pMeta->bucket[bucketKey] = pNode;
|
||||||
|
@ -205,15 +204,18 @@ TqMetaStore* tqStoreOpen(const char* path,
|
||||||
pMeta->bucket[bucketKey] = pNode;
|
pMeta->bucket[bucketKey] = pNode;
|
||||||
} else {
|
} else {
|
||||||
while(pBucketNode->next &&
|
while(pBucketNode->next &&
|
||||||
pBucketNode->next->handle.key == pNode->handle.key) {
|
pBucketNode->next->handle.key != pNode->handle.key) {
|
||||||
pBucketNode = pBucketNode->next;
|
pBucketNode = pBucketNode->next;
|
||||||
}
|
}
|
||||||
if(pBucketNode->next) {
|
if(pBucketNode->next) {
|
||||||
ASSERT(pBucketNode->next->handle.key == pNode->handle.key);
|
ASSERT(pBucketNode->next->handle.key == pNode->handle.key);
|
||||||
TqMetaList *pNodeTmp = pBucketNode->next;
|
TqMetaList *pNodeFound = pBucketNode->next;
|
||||||
pBucketNode->next = pNodeTmp->next;
|
pNode->next = pNodeFound->next;
|
||||||
pBucketNode = pNodeTmp;
|
pBucketNode->next = pNode;
|
||||||
|
pBucketNode = pNodeFound;
|
||||||
} else {
|
} else {
|
||||||
|
pNode->next = pMeta->bucket[bucketKey];
|
||||||
|
pMeta->bucket[bucketKey] = pNode;
|
||||||
pBucketNode = NULL;
|
pBucketNode = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -359,11 +361,13 @@ int32_t tqStorePersist(TqMetaStore* pMeta) {
|
||||||
*(bufPtr++) = pNode->handle.offset;
|
*(bufPtr++) = pNode->handle.offset;
|
||||||
*(bufPtr++) = (int64_t)nBytes;
|
*(bufPtr++) = (int64_t)nBytes;
|
||||||
idxBuf.head.writeOffset += TQ_IDX_SIZE;
|
idxBuf.head.writeOffset += TQ_IDX_SIZE;
|
||||||
|
|
||||||
if(idxBuf.head.writeOffset >= TQ_PAGE_SIZE) {
|
if(idxBuf.head.writeOffset >= TQ_PAGE_SIZE) {
|
||||||
nBytes = write(pMeta->idxFd, &idxBuf, TQ_PAGE_SIZE);
|
nBytes = write(pMeta->idxFd, &idxBuf, TQ_PAGE_SIZE);
|
||||||
//TODO: handle error with tfile
|
//TODO: handle error with tfile
|
||||||
ASSERT(nBytes == TQ_PAGE_SIZE);
|
ASSERT(nBytes == TQ_PAGE_SIZE);
|
||||||
memset(&idxBuf, 0, TQ_PAGE_SIZE);
|
memset(&idxBuf, 0, TQ_PAGE_SIZE);
|
||||||
|
idxBuf.head.writeOffset = TQ_IDX_PAGE_HEAD_SIZE;
|
||||||
bufPtr = (int64_t*)&idxBuf.buffer;
|
bufPtr = (int64_t*)&idxBuf.buffer;
|
||||||
}
|
}
|
||||||
//remove from unpersist list
|
//remove from unpersist list
|
||||||
|
@ -376,7 +380,7 @@ int32_t tqStorePersist(TqMetaStore* pMeta) {
|
||||||
if(pNode->handle.valueInUse == TQ_DELETE_TOKEN &&
|
if(pNode->handle.valueInUse == TQ_DELETE_TOKEN &&
|
||||||
pNode->handle.valueInTxn == NULL
|
pNode->handle.valueInTxn == NULL
|
||||||
) {
|
) {
|
||||||
int bucketKey = pNode->handle.key & TQ_BUCKET_SIZE;
|
int bucketKey = pNode->handle.key & TQ_BUCKET_MASK;
|
||||||
TqMetaList* pBucketHead = pMeta->bucket[bucketKey];
|
TqMetaList* pBucketHead = pMeta->bucket[bucketKey];
|
||||||
if(pBucketHead == pNode) {
|
if(pBucketHead == pNode) {
|
||||||
pMeta->bucket[bucketKey] = pNode->next;
|
pMeta->bucket[bucketKey] = pNode->next;
|
||||||
|
@ -409,7 +413,7 @@ int32_t tqStorePersist(TqMetaStore* pMeta) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static int32_t tqHandlePutCommitted(TqMetaStore* pMeta, int64_t key, void* value) {
|
static int32_t tqHandlePutCommitted(TqMetaStore* pMeta, int64_t key, void* value) {
|
||||||
int64_t bucketKey = key & TQ_BUCKET_SIZE;
|
int64_t bucketKey = key & TQ_BUCKET_MASK;
|
||||||
TqMetaList* pNode = pMeta->bucket[bucketKey];
|
TqMetaList* pNode = pMeta->bucket[bucketKey];
|
||||||
while(pNode) {
|
while(pNode) {
|
||||||
if(pNode->handle.key == key) {
|
if(pNode->handle.key == key) {
|
||||||
|
@ -442,7 +446,7 @@ static int32_t tqHandlePutCommitted(TqMetaStore* pMeta, int64_t key, void* value
|
||||||
}
|
}
|
||||||
|
|
||||||
void* tqHandleGet(TqMetaStore* pMeta, int64_t key) {
|
void* tqHandleGet(TqMetaStore* pMeta, int64_t key) {
|
||||||
int64_t bucketKey = key & TQ_BUCKET_SIZE;
|
int64_t bucketKey = key & TQ_BUCKET_MASK;
|
||||||
TqMetaList* pNode = pMeta->bucket[bucketKey];
|
TqMetaList* pNode = pMeta->bucket[bucketKey];
|
||||||
while(pNode) {
|
while(pNode) {
|
||||||
if(pNode->handle.key == key) {
|
if(pNode->handle.key == key) {
|
||||||
|
@ -460,7 +464,7 @@ void* tqHandleGet(TqMetaStore* pMeta, int64_t key) {
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t tqHandleMovePut(TqMetaStore* pMeta, int64_t key, void* value) {
|
int32_t tqHandleMovePut(TqMetaStore* pMeta, int64_t key, void* value) {
|
||||||
int64_t bucketKey = key & TQ_BUCKET_SIZE;
|
int64_t bucketKey = key & TQ_BUCKET_MASK;
|
||||||
TqMetaList* pNode = pMeta->bucket[bucketKey];
|
TqMetaList* pNode = pMeta->bucket[bucketKey];
|
||||||
while(pNode) {
|
while(pNode) {
|
||||||
if(pNode->handle.key == key) {
|
if(pNode->handle.key == key) {
|
||||||
|
@ -498,7 +502,7 @@ int32_t tqHandleCopyPut(TqMetaStore* pMeta, int64_t key, void* value, size_t vsi
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
memcpy(vmem, value, vsize);
|
memcpy(vmem, value, vsize);
|
||||||
int64_t bucketKey = key & TQ_BUCKET_SIZE;
|
int64_t bucketKey = key & TQ_BUCKET_MASK;
|
||||||
TqMetaList* pNode = pMeta->bucket[bucketKey];
|
TqMetaList* pNode = pMeta->bucket[bucketKey];
|
||||||
while(pNode) {
|
while(pNode) {
|
||||||
if(pNode->handle.key == key) {
|
if(pNode->handle.key == key) {
|
||||||
|
@ -530,7 +534,7 @@ int32_t tqHandleCopyPut(TqMetaStore* pMeta, int64_t key, void* value, size_t vsi
|
||||||
}
|
}
|
||||||
|
|
||||||
static void* tqHandleGetUncommitted(TqMetaStore* pMeta, int64_t key) {
|
static void* tqHandleGetUncommitted(TqMetaStore* pMeta, int64_t key) {
|
||||||
int64_t bucketKey = key & TQ_BUCKET_SIZE;
|
int64_t bucketKey = key & TQ_BUCKET_MASK;
|
||||||
TqMetaList* pNode = pMeta->bucket[bucketKey];
|
TqMetaList* pNode = pMeta->bucket[bucketKey];
|
||||||
while(pNode) {
|
while(pNode) {
|
||||||
if(pNode->handle.key == key) {
|
if(pNode->handle.key == key) {
|
||||||
|
@ -548,10 +552,13 @@ static void* tqHandleGetUncommitted(TqMetaStore* pMeta, int64_t key) {
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t tqHandleCommit(TqMetaStore* pMeta, int64_t key) {
|
int32_t tqHandleCommit(TqMetaStore* pMeta, int64_t key) {
|
||||||
int64_t bucketKey = key & TQ_BUCKET_SIZE;
|
int64_t bucketKey = key & TQ_BUCKET_MASK;
|
||||||
TqMetaList* pNode = pMeta->bucket[bucketKey];
|
TqMetaList* pNode = pMeta->bucket[bucketKey];
|
||||||
while(pNode) {
|
while(pNode) {
|
||||||
if(pNode->handle.key == key) {
|
if(pNode->handle.key == key) {
|
||||||
|
if(pNode->handle.valueInTxn == NULL) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
if(pNode->handle.valueInUse
|
if(pNode->handle.valueInUse
|
||||||
&& pNode->handle.valueInUse != TQ_DELETE_TOKEN) {
|
&& pNode->handle.valueInUse != TQ_DELETE_TOKEN) {
|
||||||
pMeta->deleter(pNode->handle.valueInUse);
|
pMeta->deleter(pNode->handle.valueInUse);
|
||||||
|
@ -564,11 +571,11 @@ int32_t tqHandleCommit(TqMetaStore* pMeta, int64_t key) {
|
||||||
pNode = pNode->next;
|
pNode = pNode->next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return -1;
|
return -2;
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t tqHandleAbort(TqMetaStore* pMeta, int64_t key) {
|
int32_t tqHandleAbort(TqMetaStore* pMeta, int64_t key) {
|
||||||
int64_t bucketKey = key & TQ_BUCKET_SIZE;
|
int64_t bucketKey = key & TQ_BUCKET_MASK;
|
||||||
TqMetaList* pNode = pMeta->bucket[bucketKey];
|
TqMetaList* pNode = pMeta->bucket[bucketKey];
|
||||||
while(pNode) {
|
while(pNode) {
|
||||||
if(pNode->handle.key == key) {
|
if(pNode->handle.key == key) {
|
||||||
|
@ -589,7 +596,7 @@ int32_t tqHandleAbort(TqMetaStore* pMeta, int64_t key) {
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t tqHandleDel(TqMetaStore* pMeta, int64_t key) {
|
int32_t tqHandleDel(TqMetaStore* pMeta, int64_t key) {
|
||||||
int64_t bucketKey = key & TQ_BUCKET_SIZE;
|
int64_t bucketKey = key & TQ_BUCKET_MASK;
|
||||||
TqMetaList* pNode = pMeta->bucket[bucketKey];
|
TqMetaList* pNode = pMeta->bucket[bucketKey];
|
||||||
while(pNode) {
|
while(pNode) {
|
||||||
if(pNode->handle.valueInTxn != TQ_DELETE_TOKEN) {
|
if(pNode->handle.valueInTxn != TQ_DELETE_TOKEN) {
|
||||||
|
|
|
@ -176,3 +176,119 @@ TEST_F(TqMetaTest, intxnPersist) {
|
||||||
pFoo1 = (Foo*)tqHandleGet(pMeta, 1);
|
pFoo1 = (Foo*)tqHandleGet(pMeta, 1);
|
||||||
EXPECT_EQ(pFoo1->a, 4);
|
EXPECT_EQ(pFoo1->a, 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(TqMetaTest, multiplePage) {
|
||||||
|
srand(0);
|
||||||
|
std::vector<int> v;
|
||||||
|
for(int i = 0; i < 1000; i++) {
|
||||||
|
v.push_back(rand());
|
||||||
|
Foo foo;
|
||||||
|
foo.a = v[i];
|
||||||
|
tqHandleCopyPut(pMeta, i, &foo, sizeof(Foo));
|
||||||
|
}
|
||||||
|
for(int i = 0; i < 500; i++) {
|
||||||
|
tqHandleCommit(pMeta, i);
|
||||||
|
Foo* pFoo = (Foo*)tqHandleGet(pMeta, i);
|
||||||
|
ASSERT_EQ(pFoo != NULL, true) << " at idx " << i << "\n";
|
||||||
|
EXPECT_EQ(pFoo->a, v[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
tqStoreClose(pMeta);
|
||||||
|
pMeta = tqStoreOpen(pathName,
|
||||||
|
FooSerializer, FooDeserializer, FooDeleter);
|
||||||
|
ASSERT(pMeta);
|
||||||
|
|
||||||
|
for(int i = 500; i < 1000; i++) {
|
||||||
|
tqHandleCommit(pMeta, i);
|
||||||
|
Foo* pFoo = (Foo*)tqHandleGet(pMeta, i);
|
||||||
|
ASSERT_EQ(pFoo != NULL, true) << " at idx " << i << "\n";
|
||||||
|
EXPECT_EQ(pFoo->a, v[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
for(int i = 0; i < 1000; i++) {
|
||||||
|
Foo* pFoo = (Foo*)tqHandleGet(pMeta, i);
|
||||||
|
ASSERT_EQ(pFoo != NULL, true) << " at idx " << i << "\n";
|
||||||
|
EXPECT_EQ(pFoo->a, v[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(TqMetaTest, multipleRewrite) {
|
||||||
|
srand(0);
|
||||||
|
std::vector<int> v;
|
||||||
|
for(int i = 0; i < 1000; i++) {
|
||||||
|
v.push_back(rand());
|
||||||
|
Foo foo;
|
||||||
|
foo.a = v[i];
|
||||||
|
tqHandleCopyPut(pMeta, i, &foo, sizeof(Foo));
|
||||||
|
}
|
||||||
|
|
||||||
|
for(int i = 0; i < 500; i++) {
|
||||||
|
tqHandleCommit(pMeta, i);
|
||||||
|
v[i] = rand();
|
||||||
|
Foo foo;
|
||||||
|
foo.a = v[i];
|
||||||
|
tqHandleCopyPut(pMeta, i, &foo, sizeof(Foo));
|
||||||
|
}
|
||||||
|
|
||||||
|
for(int i = 500; i < 1000; i++) {
|
||||||
|
v[i] = rand();
|
||||||
|
Foo foo;
|
||||||
|
foo.a = v[i];
|
||||||
|
tqHandleCopyPut(pMeta, i, &foo, sizeof(Foo));
|
||||||
|
}
|
||||||
|
|
||||||
|
for(int i = 0; i < 1000; i++) {
|
||||||
|
tqHandleCommit(pMeta, i);
|
||||||
|
}
|
||||||
|
|
||||||
|
tqStoreClose(pMeta);
|
||||||
|
pMeta = tqStoreOpen(pathName,
|
||||||
|
FooSerializer, FooDeserializer, FooDeleter);
|
||||||
|
ASSERT(pMeta);
|
||||||
|
|
||||||
|
for(int i = 500; i < 1000; i++) {
|
||||||
|
v[i] = rand();
|
||||||
|
Foo foo;
|
||||||
|
foo.a = v[i];
|
||||||
|
tqHandleCopyPut(pMeta, i, &foo, sizeof(Foo));
|
||||||
|
tqHandleCommit(pMeta, i);
|
||||||
|
}
|
||||||
|
|
||||||
|
for(int i = 0; i < 1000; i++) {
|
||||||
|
Foo* pFoo = (Foo*)tqHandleGet(pMeta, i);
|
||||||
|
ASSERT_EQ(pFoo != NULL, true) << " at idx " << i << "\n";
|
||||||
|
EXPECT_EQ(pFoo->a, v[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(TqMetaTest, dupCommit) {
|
||||||
|
srand(0);
|
||||||
|
std::vector<int> v;
|
||||||
|
for(int i = 0; i < 1000; i++) {
|
||||||
|
v.push_back(rand());
|
||||||
|
Foo foo;
|
||||||
|
foo.a = v[i];
|
||||||
|
tqHandleCopyPut(pMeta, i, &foo, sizeof(Foo));
|
||||||
|
}
|
||||||
|
|
||||||
|
for(int i = 0; i < 1000; i++) {
|
||||||
|
int ret = tqHandleCommit(pMeta, i);
|
||||||
|
EXPECT_EQ(ret, 0);
|
||||||
|
ret = tqHandleCommit(pMeta, i);
|
||||||
|
EXPECT_EQ(ret, -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
for(int i = 0; i < 1000; i++) {
|
||||||
|
int ret = tqHandleCommit(pMeta, i);
|
||||||
|
EXPECT_EQ(ret, -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
for(int i = 0; i < 1000; i++) {
|
||||||
|
Foo* pFoo = (Foo*)tqHandleGet(pMeta, i);
|
||||||
|
ASSERT_EQ(pFoo != NULL, true) << " at idx " << i << "\n";
|
||||||
|
EXPECT_EQ(pFoo->a, v[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue