提交 411d034d 编写于 作者: H Haojun Liao

[td-225] fix bugs in cache.

上级 47665e56
...@@ -481,10 +481,10 @@ static bool tscFreeQhandleInVnode(SSqlObj* pSql) { ...@@ -481,10 +481,10 @@ static bool tscFreeQhandleInVnode(SSqlObj* pSql) {
if (pRes->code == TSDB_CODE_SUCCESS && pRes->completed == false && !tscIsTwoStageSTableQuery(pQueryInfo, 0) && if (pRes->code == TSDB_CODE_SUCCESS && pRes->completed == false && !tscIsTwoStageSTableQuery(pQueryInfo, 0) &&
(pCmd->command == TSDB_SQL_SELECT || (pCmd->command == TSDB_SQL_SELECT ||
pCmd->command == TSDB_SQL_SHOW || pCmd->command == TSDB_SQL_SHOW ||
pCmd->command == TSDB_SQL_RETRIEVE || pCmd->command == TSDB_SQL_RETRIEVE ||
pCmd->command == TSDB_SQL_FETCH) && pCmd->command == TSDB_SQL_FETCH) &&
(pCmd->command == TSDB_SQL_SELECT && pSql->pStream == NULL && pTableMetaInfo->pTableMeta != NULL)) { (pSql->pStream == NULL && pTableMetaInfo->pTableMeta != NULL)) {
pCmd->command = (pCmd->command > TSDB_SQL_MGMT) ? TSDB_SQL_RETRIEVE : TSDB_SQL_FETCH; pCmd->command = (pCmd->command > TSDB_SQL_MGMT) ? TSDB_SQL_RETRIEVE : TSDB_SQL_FETCH;
tscDebug("%p send msg to dnode to free qhandle ASAP, command:%s, ", pSql, sqlCmd[pCmd->command]); tscDebug("%p send msg to dnode to free qhandle ASAP, command:%s, ", pSql, sqlCmd[pCmd->command]);
......
...@@ -413,57 +413,90 @@ void taosCacheRelease(SCacheObj *pCacheObj, void **data, bool _remove) { ...@@ -413,57 +413,90 @@ void taosCacheRelease(SCacheObj *pCacheObj, void **data, bool _remove) {
*data = NULL; *data = NULL;
// note: extend lifespan before dec ref count // note: extend lifespan before dec ref count
if (pCacheObj->extendLifespan) { bool inTrashCan = pNode->inTrashCan;
if (pCacheObj->extendLifespan && (!inTrashCan)) {
atomic_store_64(&pNode->expireTime, pNode->lifespan + taosGetTimestampMs()); atomic_store_64(&pNode->expireTime, pNode->lifespan + taosGetTimestampMs());
uDebug("cache:%s data:%p extend life time to %"PRId64 " before release", pCacheObj->name, pNode->data, pNode->expireTime); uDebug("cache:%s data:%p extend life time to %"PRId64 " before release", pCacheObj->name, pNode->data, pNode->expireTime);
} }
bool inTrashCan = pNode->inTrashCan; if (_remove) {
uDebug("cache:%s, key:%p, %p is released, refcnt:%d", pCacheObj->name, pNode->key, pNode->data, T_REF_VAL_GET(pNode) - 1); __cache_wr_lock(pCacheObj);
// NOTE: once refcount is decrease, pNode may be free by other thread immediately. // NOTE: once refcount is decrease, pNode may be freed by other thread immediately.
int32_t ref = T_REF_DEC(pNode); int32_t ref = T_REF_DEC(pNode);
uDebug("cache:%s, key:%p, %p is released, refcnt:%d", pCacheObj->name, pNode->key, pNode->data, ref);
if (inTrashCan) {
// Remove it if the ref count is 0. /*
// The ref count does not need to load and check again after lock acquired, since ref count can not be increased when * If it is not referenced by other users, remove it immediately. Otherwise move this node to trashcan wait for all users
// the node is in trashcan. * releasing this resources.
if (ref == 0) { *
__cache_wr_lock(pCacheObj); * NOTE: previous ref is 0, and current ref is still 0, remove it. If previous is not 0, there is another thread
assert(pNode->pTNodeHeader->pData == pNode); * that tries to do the same thing.
taosRemoveFromTrashCan(pCacheObj, pNode->pTNodeHeader); */
__cache_unlock(pCacheObj); if (pNode->inTrashCan) {
if (ref == 0) {
assert(pNode->pTNodeHeader->pData == pNode);
taosRemoveFromTrashCan(pCacheObj, pNode->pTNodeHeader);
}
} else {
if (ref > 0) {
assert(pNode->pTNodeHeader == NULL);
taosCacheMoveToTrash(pCacheObj, pNode);
} else {
taosCacheReleaseNode(pCacheObj, pNode);
}
} }
__cache_unlock(pCacheObj);
} else { } else {
assert(pNode->pTNodeHeader == NULL); uDebug("cache:%s, key:%p, %p is released, refcnt:%d", pCacheObj->name, pNode->key, pNode->data, T_REF_VAL_GET(pNode) - 1);
if (_remove) { // not in trash can, but need to remove it // NOTE: once refcount is decrease, pNode may be freed by other thread immediately.
__cache_wr_lock(pCacheObj); int32_t ref = T_REF_DEC(pNode);
/* if (inTrashCan) {
* If not referenced by other users. Otherwise move this node to trashcan wait for all users // Remove it if the ref count is 0.
* releasing this resources. // The ref count does not need to load and check again after lock acquired, since ref count can not be increased when
* // the node is in trashcan.
* NOTE: previous ref is 0, and current ref is still 0, remove it. If previous is not 0, there is another thread
* that tries to do the same thing.
*/
if (ref == 0) { if (ref == 0) {
if (T_REF_VAL_GET(pNode) == 0) { __cache_wr_lock(pCacheObj);
taosCacheReleaseNode(pCacheObj, pNode); assert(pNode->pTNodeHeader->pData == pNode);
} else { taosRemoveFromTrashCan(pCacheObj, pNode->pTNodeHeader);
taosCacheMoveToTrash(pCacheObj, pNode); __cache_unlock(pCacheObj);
}
} }
__cache_unlock(pCacheObj);
// } else { // extend its life time
// if (pCacheObj->extendLifespan) {
// atomic_store_64(&pNode->expireTime, pNode->lifespan + taosGetTimestampMs());
// uDebug("cache:%s data:%p extend life time to %"PRId64 " after release", pCacheObj->name, pNode->data, pNode->expireTime);
// }
} }
} }
// else {
// if (_remove) { // not in trash can, but need to remove it
// __cache_wr_lock(pCacheObj);
//
// /*
// * If not referenced by other users. Otherwise move this node to trashcan wait for all users
// * releasing this resources.
// *
// * NOTE: previous ref is 0, and current ref is still 0, remove it. If previous is not 0, there is another thread
// * that tries to do the same thing.
// */
// if (ref == 0) {
// if (T_REF_VAL_GET(pNode) == 0) {
// taosCacheReleaseNode(pCacheObj, pNode);
// } else {
// taosCacheMoveToTrash(pCacheObj, pNode);
// }
// } else if (ref > 0) {
// if (!pNode->inTrashCan) {
// assert(pNode->pTNodeHeader == NULL);
// taosCacheMoveToTrash(pCacheObj, pNode);
// }
// }
//
// __cache_unlock(pCacheObj);
// }
// }
} }
void taosCacheEmpty(SCacheObj *pCacheObj) { void taosCacheEmpty(SCacheObj *pCacheObj) {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册