tbase-1422: free resource
This commit is contained in:
parent
f2eac06a33
commit
051af216a5
|
@ -465,6 +465,12 @@ void tscDestroyResPointerInfo(SSqlRes *pRes);
|
||||||
|
|
||||||
void tscFreeSqlCmdData(SSqlCmd *pCmd);
|
void tscFreeSqlCmdData(SSqlCmd *pCmd);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* free query result of the sql object
|
||||||
|
* @param pObj
|
||||||
|
*/
|
||||||
|
void tscFreeSqlResult(SSqlObj* pSql);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* only free part of resources allocated during query.
|
* only free part of resources allocated during query.
|
||||||
* Note: this function is multi-thread safe.
|
* Note: this function is multi-thread safe.
|
||||||
|
|
|
@ -694,7 +694,7 @@ int taos_select_db(TAOS *taos, const char *db) {
|
||||||
return taos_query(taos, sql);
|
return taos_query(taos, sql);
|
||||||
}
|
}
|
||||||
|
|
||||||
void taos_free_result(TAOS_RES *res) {
|
void taos_free_result_imp(TAOS_RES* res, int keepCmd) {
|
||||||
if (res == NULL) return;
|
if (res == NULL) return;
|
||||||
|
|
||||||
SSqlObj *pSql = (SSqlObj *)res;
|
SSqlObj *pSql = (SSqlObj *)res;
|
||||||
|
@ -712,6 +712,8 @@ void taos_free_result(TAOS_RES *res) {
|
||||||
pSql->thandle = NULL;
|
pSql->thandle = NULL;
|
||||||
tscFreeSqlObj(pSql);
|
tscFreeSqlObj(pSql);
|
||||||
tscTrace("%p Async SqlObj is freed by app", pSql);
|
tscTrace("%p Async SqlObj is freed by app", pSql);
|
||||||
|
} else if (keepCmd) {
|
||||||
|
tscFreeSqlResult(pSql);
|
||||||
} else {
|
} else {
|
||||||
tscFreeSqlObjPartial(pSql);
|
tscFreeSqlObjPartial(pSql);
|
||||||
}
|
}
|
||||||
|
@ -761,8 +763,13 @@ void taos_free_result(TAOS_RES *res) {
|
||||||
* Then this object will be reused and no free operation is required.
|
* Then this object will be reused and no free operation is required.
|
||||||
*/
|
*/
|
||||||
pSql->thandle = NULL;
|
pSql->thandle = NULL;
|
||||||
tscFreeSqlObjPartial(pSql);
|
if (keepCmd) {
|
||||||
tscTrace("%p sql result is freed by app", pSql);
|
tscFreeSqlResult(pSql);
|
||||||
|
tscTrace("%p sql result is freed by app while sql command is kept", pSql);
|
||||||
|
} else {
|
||||||
|
tscFreeSqlObjPartial(pSql);
|
||||||
|
tscTrace("%p sql result is freed by app", pSql);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// if no free resource msg is sent to vnode, we free this object immediately.
|
// if no free resource msg is sent to vnode, we free this object immediately.
|
||||||
|
@ -772,6 +779,9 @@ void taos_free_result(TAOS_RES *res) {
|
||||||
assert(pRes->numOfRows == 0 || (pCmd->command > TSDB_SQL_LOCAL));
|
assert(pRes->numOfRows == 0 || (pCmd->command > TSDB_SQL_LOCAL));
|
||||||
tscFreeSqlObj(pSql);
|
tscFreeSqlObj(pSql);
|
||||||
tscTrace("%p Async sql result is freed by app", pSql);
|
tscTrace("%p Async sql result is freed by app", pSql);
|
||||||
|
} else if (keepCmd) {
|
||||||
|
tscFreeSqlResult(pSql);
|
||||||
|
tscTrace("%p sql result is freed while sql command is kept", pSql);
|
||||||
} else {
|
} else {
|
||||||
tscFreeSqlObjPartial(pSql);
|
tscFreeSqlObjPartial(pSql);
|
||||||
tscTrace("%p sql result is freed", pSql);
|
tscTrace("%p sql result is freed", pSql);
|
||||||
|
@ -779,6 +789,10 @@ void taos_free_result(TAOS_RES *res) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void taos_free_result(TAOS_RES *res) {
|
||||||
|
taos_free_result_imp(res, 0);
|
||||||
|
}
|
||||||
|
|
||||||
int taos_errno(TAOS *taos) {
|
int taos_errno(TAOS *taos) {
|
||||||
STscObj *pObj = (STscObj *)taos;
|
STscObj *pObj = (STscObj *)taos;
|
||||||
int code;
|
int code;
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
#include "ttimer.h"
|
#include "ttimer.h"
|
||||||
#include "tutil.h"
|
#include "tutil.h"
|
||||||
#include "tscUtil.h"
|
#include "tscUtil.h"
|
||||||
|
#include "tcache.h"
|
||||||
|
|
||||||
typedef struct SSubscriptionProgress {
|
typedef struct SSubscriptionProgress {
|
||||||
int64_t uid;
|
int64_t uid;
|
||||||
|
@ -82,7 +83,7 @@ void tscUpdateSubscriptionProgress(void* sub, int64_t uid, TSKEY ts) {
|
||||||
else if (p->uid < uid)
|
else if (p->uid < uid)
|
||||||
s = m + 1;
|
s = m + 1;
|
||||||
else {
|
else {
|
||||||
if (ts >= p->key) p->key = ts + 1;
|
if (ts >= p->key) p->key = ts;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -148,25 +149,27 @@ static void tscProcessSubscriptionTimer(void *handle, void *tmrId) {
|
||||||
TAOS_RES* res = taos_consume(pSub);
|
TAOS_RES* res = taos_consume(pSub);
|
||||||
if (res != NULL) {
|
if (res != NULL) {
|
||||||
pSub->fp(pSub, res, pSub->param, 0);
|
pSub->fp(pSub, res, pSub->param, 0);
|
||||||
// TODO: memory leak
|
|
||||||
}
|
}
|
||||||
|
|
||||||
taosTmrReset(tscProcessSubscriptionTimer, pSub->interval, pSub, tscTmr, &pSub->pTimer);
|
taosTmrReset(tscProcessSubscriptionTimer, pSub->interval, pSub, tscTmr, &pSub->pTimer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool tscUpdateSubscription(STscObj* pObj, SSub* pSub) {
|
int tscUpdateSubscription(STscObj* pObj, SSub* pSub) {
|
||||||
int code = (uint8_t)tsParseSql(pSub->pSql, pObj->acctId, pObj->db, false);
|
int code = (uint8_t)tsParseSql(pSub->pSql, pObj->acctId, pObj->db, false);
|
||||||
if (code != TSDB_CODE_SUCCESS) {
|
if (code != TSDB_CODE_SUCCESS) {
|
||||||
taos_unsubscribe(pSub);
|
tscError("failed to parse sql statement: %s", pSub->topic);
|
||||||
return false;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int numOfMeters = 0;
|
int numOfMeters = 0;
|
||||||
SSubscriptionProgress* progress = NULL;
|
SSubscriptionProgress* progress = NULL;
|
||||||
|
|
||||||
// ??? if there's more than one vnode
|
|
||||||
SSqlCmd* pCmd = &pSub->pSql->cmd;
|
SSqlCmd* pCmd = &pSub->pSql->cmd;
|
||||||
|
if (pCmd->command != TSDB_SQL_SELECT) {
|
||||||
|
tscError("only 'select' statement is allowed in subscription: %s", pSub->topic);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
SMeterMetaInfo *pMeterMetaInfo = tscGetMeterMetaInfo(pCmd, 0);
|
SMeterMetaInfo *pMeterMetaInfo = tscGetMeterMetaInfo(pCmd, 0);
|
||||||
if (UTIL_METER_IS_NOMRAL_METER(pMeterMetaInfo)) {
|
if (UTIL_METER_IS_NOMRAL_METER(pMeterMetaInfo)) {
|
||||||
|
@ -177,14 +180,20 @@ bool tscUpdateSubscription(STscObj* pObj, SSub* pSub) {
|
||||||
progress[0].key = tscGetSubscriptionProgress(pSub, uid);
|
progress[0].key = tscGetSubscriptionProgress(pSub, uid);
|
||||||
} else {
|
} else {
|
||||||
SMetricMeta* pMetricMeta = pMeterMetaInfo->pMetricMeta;
|
SMetricMeta* pMetricMeta = pMeterMetaInfo->pMetricMeta;
|
||||||
SVnodeSidList *pVnodeSidList = tscGetVnodeSidList(pMetricMeta, pMeterMetaInfo->vnodeIndex);
|
for (int32_t i = 0; i < pMetricMeta->numOfVnodes; i++) {
|
||||||
numOfMeters = pVnodeSidList->numOfSids;
|
SVnodeSidList *pVnodeSidList = tscGetVnodeSidList(pMetricMeta, pMeterMetaInfo->vnodeIndex);
|
||||||
|
numOfMeters += pVnodeSidList->numOfSids;
|
||||||
|
}
|
||||||
progress = calloc(numOfMeters, sizeof(SSubscriptionProgress));
|
progress = calloc(numOfMeters, sizeof(SSubscriptionProgress));
|
||||||
for (int32_t i = 0; i < numOfMeters; ++i) {
|
numOfMeters = 0;
|
||||||
SMeterSidExtInfo *pMeterInfo = tscGetMeterSidInfo(pVnodeSidList, i);
|
for (int32_t i = 0; i < pMetricMeta->numOfVnodes; i++) {
|
||||||
int64_t uid = pMeterInfo->uid;
|
SVnodeSidList *pVnodeSidList = tscGetVnodeSidList(pMetricMeta, pMeterMetaInfo->vnodeIndex);
|
||||||
progress[i].uid = uid;
|
for (int32_t j = 0; j < pVnodeSidList->numOfSids; j++) {
|
||||||
progress[i].key = tscGetSubscriptionProgress(pSub, uid);
|
SMeterSidExtInfo *pMeterInfo = tscGetMeterSidInfo(pVnodeSidList, j);
|
||||||
|
int64_t uid = pMeterInfo->uid;
|
||||||
|
progress[numOfMeters].uid = uid;
|
||||||
|
progress[numOfMeters++].key = tscGetSubscriptionProgress(pSub, uid);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
qsort(progress, numOfMeters, sizeof(SSubscriptionProgress), tscCompareSubscriptionProgress);
|
qsort(progress, numOfMeters, sizeof(SSubscriptionProgress), tscCompareSubscriptionProgress);
|
||||||
}
|
}
|
||||||
|
@ -193,33 +202,26 @@ bool tscUpdateSubscription(STscObj* pObj, SSub* pSub) {
|
||||||
pSub->numOfMeters = numOfMeters;
|
pSub->numOfMeters = numOfMeters;
|
||||||
pSub->progress = progress;
|
pSub->progress = progress;
|
||||||
|
|
||||||
// timestamp must in the output column
|
|
||||||
SFieldInfo* pFieldInfo = &pCmd->fieldsInfo;
|
|
||||||
tscFieldInfoSetValue(pFieldInfo, pFieldInfo->numOfOutputCols, TSDB_DATA_TYPE_TIMESTAMP, "_c0", TSDB_KEYSIZE);
|
|
||||||
tscSqlExprInsertEmpty(pCmd, pFieldInfo->numOfOutputCols - 1, TSDB_FUNC_PRJ);
|
|
||||||
tscFieldInfoUpdateVisible(pFieldInfo, pFieldInfo->numOfOutputCols - 1, false);
|
|
||||||
tscFieldInfoCalOffset(pCmd);
|
|
||||||
|
|
||||||
pSub->lastSyncTime = taosGetTimestampMs();
|
pSub->lastSyncTime = taosGetTimestampMs();
|
||||||
|
|
||||||
return true;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void tscLoadSubscriptionProgress(SSub* pSub) {
|
static int tscLoadSubscriptionProgress(SSub* pSub) {
|
||||||
char buf[TSDB_MAX_SQL_LEN];
|
char buf[TSDB_MAX_SQL_LEN];
|
||||||
sprintf(buf, "%s/subscribe/%s", dataDir, pSub->topic);
|
sprintf(buf, "%s/subscribe/%s", dataDir, pSub->topic);
|
||||||
|
|
||||||
FILE* fp = fopen(buf, "r");
|
FILE* fp = fopen(buf, "r");
|
||||||
if (fp == NULL) {
|
if (fp == NULL) {
|
||||||
tscTrace("subscription progress file does not exist: %s", pSub->topic);
|
tscTrace("subscription progress file does not exist: %s", pSub->topic);
|
||||||
return true;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fgets(buf, sizeof(buf), fp) == NULL) {
|
if (fgets(buf, sizeof(buf), fp) == NULL) {
|
||||||
tscTrace("invalid subscription progress file: %s", pSub->topic);
|
tscTrace("invalid subscription progress file: %s", pSub->topic);
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
return false;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < sizeof(buf); i++) {
|
for (int i = 0; i < sizeof(buf); i++) {
|
||||||
|
@ -233,13 +235,13 @@ static void tscLoadSubscriptionProgress(SSub* pSub) {
|
||||||
if (strcmp(buf, pSub->pSql->sqlstr) != 0) {
|
if (strcmp(buf, pSub->pSql->sqlstr) != 0) {
|
||||||
tscTrace("subscription sql statement mismatch: %s", pSub->topic);
|
tscTrace("subscription sql statement mismatch: %s", pSub->topic);
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
return false;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fgets(buf, sizeof(buf), fp) == NULL || atoi(buf) < 0) {
|
if (fgets(buf, sizeof(buf), fp) == NULL || atoi(buf) < 0) {
|
||||||
tscTrace("invalid subscription progress file: %s", pSub->topic);
|
tscTrace("invalid subscription progress file: %s", pSub->topic);
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
return false;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int numOfMeters = atoi(buf);
|
int numOfMeters = atoi(buf);
|
||||||
|
@ -248,7 +250,7 @@ static void tscLoadSubscriptionProgress(SSub* pSub) {
|
||||||
if (fgets(buf, sizeof(buf), fp) == NULL) {
|
if (fgets(buf, sizeof(buf), fp) == NULL) {
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
free(progress);
|
free(progress);
|
||||||
return false;
|
return 0;
|
||||||
}
|
}
|
||||||
int64_t uid, key;
|
int64_t uid, key;
|
||||||
sscanf(buf, "uid=%" SCNd64 ",progress=%" SCNd64, &uid, &key);
|
sscanf(buf, "uid=%" SCNd64 ",progress=%" SCNd64, &uid, &key);
|
||||||
|
@ -261,7 +263,8 @@ static void tscLoadSubscriptionProgress(SSub* pSub) {
|
||||||
qsort(progress, numOfMeters, sizeof(SSubscriptionProgress), tscCompareSubscriptionProgress);
|
qsort(progress, numOfMeters, sizeof(SSubscriptionProgress), tscCompareSubscriptionProgress);
|
||||||
pSub->numOfMeters = numOfMeters;
|
pSub->numOfMeters = numOfMeters;
|
||||||
pSub->progress = progress;
|
pSub->progress = progress;
|
||||||
return true;
|
tscTrace("subscription progress loaded, %d tables: %s", numOfMeters, pSub->topic);
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void tscSaveSubscriptionProgress(void* sub) {
|
void tscSaveSubscriptionProgress(void* sub) {
|
||||||
|
@ -291,7 +294,6 @@ void tscSaveSubscriptionProgress(void* sub) {
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
TAOS_SUB *taos_subscribe(const char* topic, int restart, TAOS *taos, const char *sql, TAOS_SUBSCRIBE_CALLBACK fp, void *param, int interval) {
|
TAOS_SUB *taos_subscribe(const char* topic, int restart, TAOS *taos, const char *sql, TAOS_SUBSCRIBE_CALLBACK fp, void *param, int interval) {
|
||||||
STscObj* pObj = (STscObj*)taos;
|
STscObj* pObj = (STscObj*)taos;
|
||||||
if (pObj == NULL || pObj->signature != pObj) {
|
if (pObj == NULL || pObj->signature != pObj) {
|
||||||
|
@ -313,6 +315,7 @@ TAOS_SUB *taos_subscribe(const char* topic, int restart, TAOS *taos, const char
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!tscUpdateSubscription(pObj, pSub)) {
|
if (!tscUpdateSubscription(pObj, pSub)) {
|
||||||
|
taos_unsubscribe(pSub, 1);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -326,39 +329,55 @@ TAOS_SUB *taos_subscribe(const char* topic, int restart, TAOS *taos, const char
|
||||||
return pSub;
|
return pSub;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void taos_free_result_imp(SSqlObj* pSql, int keepCmd);
|
||||||
|
|
||||||
TAOS_RES *taos_consume(TAOS_SUB *tsub) {
|
TAOS_RES *taos_consume(TAOS_SUB *tsub) {
|
||||||
SSub *pSub = (SSub *)tsub;
|
SSub *pSub = (SSub *)tsub;
|
||||||
if (pSub == NULL) return NULL;
|
if (pSub == NULL) return NULL;
|
||||||
|
|
||||||
if (taosGetTimestampMs() - pSub->lastSyncTime > 30 * 60 * 1000) {
|
|
||||||
taos_query(pSub->taos, "reset query cache;");
|
|
||||||
// TODO: clear memory
|
|
||||||
if (!tscUpdateSubscription(pSub->taos, pSub)) return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
SSqlObj* pSql = pSub->pSql;
|
SSqlObj* pSql = pSub->pSql;
|
||||||
SSqlRes *pRes = &pSql->res;
|
SSqlRes *pRes = &pSql->res;
|
||||||
|
|
||||||
pRes->numOfRows = 1;
|
if (taosGetTimestampMs() - pSub->lastSyncTime > 10 * 1000) {
|
||||||
pRes->numOfTotal = 0;
|
char* sqlstr = pSql->sqlstr;
|
||||||
pRes->qhandle = 0;
|
pSql->sqlstr = NULL;
|
||||||
pSql->thandle = NULL;
|
taos_free_result_imp(pSql, 0);
|
||||||
pSql->cmd.command = TSDB_SQL_SELECT;
|
pSql->sqlstr = sqlstr;
|
||||||
|
taosClearDataCache(tscCacheHandle);
|
||||||
|
if (!tscUpdateSubscription(pSub->taos, pSub)) return NULL;
|
||||||
|
} else {
|
||||||
|
uint16_t type = pSql->cmd.type;
|
||||||
|
taos_free_result_imp(pSql, 1);
|
||||||
|
pRes->numOfRows = 1;
|
||||||
|
pRes->numOfTotal = 0;
|
||||||
|
pRes->qhandle = 0;
|
||||||
|
pSql->thandle = NULL;
|
||||||
|
pSql->cmd.command = TSDB_SQL_SELECT;
|
||||||
|
pSql->cmd.type = type;
|
||||||
|
}
|
||||||
|
|
||||||
tscDoQuery(pSql);
|
tscDoQuery(pSql);
|
||||||
if (pRes->code != TSDB_CODE_SUCCESS) {
|
if (pRes->code != TSDB_CODE_SUCCESS) {
|
||||||
|
tscRemoveFromSqlList(pSql);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
return pSql;
|
return pSql;
|
||||||
}
|
}
|
||||||
|
|
||||||
void taos_unsubscribe(TAOS_SUB *tsub) {
|
void taos_unsubscribe(TAOS_SUB *tsub, int keepProgress) {
|
||||||
SSub *pSub = (SSub *)tsub;
|
SSub *pSub = (SSub *)tsub;
|
||||||
if (pSub == NULL || pSub->signature != pSub) return;
|
if (pSub == NULL || pSub->signature != pSub) return;
|
||||||
|
|
||||||
if (pSub->pTimer != NULL) {
|
if (pSub->pTimer != NULL) {
|
||||||
taosTmrStop(pSub->pTimer);
|
taosTmrStop(pSub->pTimer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!keepProgress) {
|
||||||
|
char path[256];
|
||||||
|
sprintf(path, "%s/subscribe/%s", dataDir, pSub->topic);
|
||||||
|
remove(path);
|
||||||
|
}
|
||||||
|
|
||||||
tscFreeSqlObj(pSub->pSql);
|
tscFreeSqlObj(pSub->pSql);
|
||||||
free(pSub->progress);
|
free(pSub->progress);
|
||||||
memset(pSub, 0, sizeof(*pSub));
|
memset(pSub, 0, sizeof(*pSub));
|
||||||
|
|
|
@ -376,6 +376,21 @@ void tscFreeSqlCmdData(SSqlCmd* pCmd) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void tscFreeSqlResult(SSqlObj* pSql) {
|
||||||
|
tfree(pSql->res.pRsp);
|
||||||
|
pSql->res.row = 0;
|
||||||
|
pSql->res.numOfRows = 0;
|
||||||
|
pSql->res.numOfTotal = 0;
|
||||||
|
|
||||||
|
pSql->res.numOfGroups = 0;
|
||||||
|
tfree(pSql->res.pGroupRec);
|
||||||
|
|
||||||
|
tscDestroyLocalReducer(pSql);
|
||||||
|
|
||||||
|
tscDestroyResPointerInfo(&pSql->res);
|
||||||
|
tfree(pSql->res.pColumnIndex);
|
||||||
|
}
|
||||||
|
|
||||||
void tscFreeSqlObjPartial(SSqlObj* pSql) {
|
void tscFreeSqlObjPartial(SSqlObj* pSql) {
|
||||||
if (pSql == NULL || pSql->signature != pSql) {
|
if (pSql == NULL || pSql->signature != pSql) {
|
||||||
return;
|
return;
|
||||||
|
@ -399,20 +414,9 @@ void tscFreeSqlObjPartial(SSqlObj* pSql) {
|
||||||
tfree(pSql->sqlstr);
|
tfree(pSql->sqlstr);
|
||||||
pthread_mutex_unlock(&pObj->mutex);
|
pthread_mutex_unlock(&pObj->mutex);
|
||||||
|
|
||||||
tfree(pSql->res.pRsp);
|
tscFreeSqlResult(pSql);
|
||||||
pSql->res.row = 0;
|
|
||||||
pSql->res.numOfRows = 0;
|
|
||||||
pSql->res.numOfTotal = 0;
|
|
||||||
|
|
||||||
pSql->res.numOfGroups = 0;
|
|
||||||
tfree(pSql->res.pGroupRec);
|
|
||||||
|
|
||||||
tscDestroyLocalReducer(pSql);
|
|
||||||
|
|
||||||
tfree(pSql->pSubs);
|
tfree(pSql->pSubs);
|
||||||
pSql->numOfSubs = 0;
|
pSql->numOfSubs = 0;
|
||||||
tscDestroyResPointerInfo(pRes);
|
|
||||||
tfree(pSql->res.pColumnIndex);
|
|
||||||
|
|
||||||
tscFreeSqlCmdData(pCmd);
|
tscFreeSqlCmdData(pCmd);
|
||||||
tscRemoveAllMeterMetaInfo(pCmd, false);
|
tscRemoveAllMeterMetaInfo(pCmd, false);
|
||||||
|
|
|
@ -119,7 +119,7 @@ DLL_EXPORT void taos_fetch_row_a(TAOS_RES *res, void (*fp)(void *param, TAOS_RES
|
||||||
typedef void (*TAOS_SUBSCRIBE_CALLBACK)(TAOS_SUB* tsub, TAOS_RES *res, void* param, int code);
|
typedef void (*TAOS_SUBSCRIBE_CALLBACK)(TAOS_SUB* tsub, TAOS_RES *res, void* param, int code);
|
||||||
DLL_EXPORT TAOS_SUB *taos_subscribe(const char* topic, int restart, TAOS *taos, const char *sql, TAOS_SUBSCRIBE_CALLBACK fp, void *param, int interval);
|
DLL_EXPORT TAOS_SUB *taos_subscribe(const char* topic, int restart, TAOS *taos, const char *sql, TAOS_SUBSCRIBE_CALLBACK fp, void *param, int interval);
|
||||||
DLL_EXPORT TAOS_RES *taos_consume(TAOS_SUB *tsub);
|
DLL_EXPORT TAOS_RES *taos_consume(TAOS_SUB *tsub);
|
||||||
DLL_EXPORT void taos_unsubscribe(TAOS_SUB *tsub);
|
DLL_EXPORT void taos_unsubscribe(TAOS_SUB *tsub, int keepProgress);
|
||||||
|
|
||||||
DLL_EXPORT TAOS_STREAM *taos_open_stream(TAOS *taos, const char *sql, void (*fp)(void *param, TAOS_RES *, TAOS_ROW row),
|
DLL_EXPORT TAOS_STREAM *taos_open_stream(TAOS *taos, const char *sql, void (*fp)(void *param, TAOS_RES *, TAOS_ROW row),
|
||||||
int64_t stime, void *param, void (*callback)(void *));
|
int64_t stime, void *param, void (*callback)(void *));
|
||||||
|
|
|
@ -29,7 +29,8 @@ int main(int argc, char *argv[]) {
|
||||||
const char* user = "root";
|
const char* user = "root";
|
||||||
const char* passwd = "taosdata";
|
const char* passwd = "taosdata";
|
||||||
const char* sql = "select * from meters;";
|
const char* sql = "select * from meters;";
|
||||||
int async = 1, restart = 0;
|
const char* topic = "test-multiple";
|
||||||
|
int async = 1, restart = 0, keep = 1;
|
||||||
TAOS_SUB* tsub = NULL;
|
TAOS_SUB* tsub = NULL;
|
||||||
|
|
||||||
for (int i = 1; i < argc; i++) {
|
for (int i = 1; i < argc; i++) {
|
||||||
|
@ -55,6 +56,11 @@ int main(int argc, char *argv[]) {
|
||||||
}
|
}
|
||||||
if (strcmp(argv[i], "-single") == 0) {
|
if (strcmp(argv[i], "-single") == 0) {
|
||||||
sql = "select * from t0;";
|
sql = "select * from t0;";
|
||||||
|
topic = "test-single";
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (strcmp(argv[i], "-nokeep") == 0) {
|
||||||
|
keep = 0;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -69,9 +75,9 @@ int main(int argc, char *argv[]) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (async) {
|
if (async) {
|
||||||
tsub = taos_subscribe("test", restart, taos, sql, subscribe_callback, NULL, 1000);
|
tsub = taos_subscribe(topic, restart, taos, sql, subscribe_callback, NULL, 1000);
|
||||||
} else {
|
} else {
|
||||||
tsub = taos_subscribe("test", restart, taos, sql, NULL, NULL, 0);
|
tsub = taos_subscribe(topic, restart, taos, sql, NULL, NULL, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tsub == NULL) {
|
if (tsub == NULL) {
|
||||||
|
@ -87,7 +93,7 @@ int main(int argc, char *argv[]) {
|
||||||
getchar();
|
getchar();
|
||||||
}
|
}
|
||||||
|
|
||||||
taos_unsubscribe(tsub);
|
taos_unsubscribe(tsub, keep);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue