fix: add fetchtime and version to udf init
This commit is contained in:
parent
a71caffed6
commit
c17d9eca5f
|
@ -276,6 +276,7 @@ typedef enum EUdfFuncType { UDF_FUNC_TYPE_SCALAR = 1, UDF_FUNC_TYPE_AGG = 2 } EU
|
||||||
|
|
||||||
typedef struct SScriptUdfInfo {
|
typedef struct SScriptUdfInfo {
|
||||||
const char *name;
|
const char *name;
|
||||||
|
int32_t version;
|
||||||
|
|
||||||
EUdfFuncType funcType;
|
EUdfFuncType funcType;
|
||||||
int8_t scriptType;
|
int8_t scriptType;
|
||||||
|
|
|
@ -100,7 +100,6 @@ int32_t udfdCPluginUdfInit(SScriptUdfInfo *udf, void **pUdfCtx) {
|
||||||
}
|
}
|
||||||
int32_t code = 0;
|
int32_t code = 0;
|
||||||
if (udfCtx->initFunc) {
|
if (udfCtx->initFunc) {
|
||||||
// TODO: handle init call return error
|
|
||||||
code = (udfCtx->initFunc)();
|
code = (udfCtx->initFunc)();
|
||||||
if (code != 0) {
|
if (code != 0) {
|
||||||
uv_dlclose(&udfCtx->lib);
|
uv_dlclose(&udfCtx->lib);
|
||||||
|
@ -245,7 +244,7 @@ typedef struct SUvUdfWork {
|
||||||
typedef enum { UDF_STATE_INIT = 0, UDF_STATE_LOADING, UDF_STATE_READY } EUdfState;
|
typedef enum { UDF_STATE_INIT = 0, UDF_STATE_LOADING, UDF_STATE_READY } EUdfState;
|
||||||
|
|
||||||
typedef struct SUdf {
|
typedef struct SUdf {
|
||||||
char name[TSDB_FUNC_NAME_LEN + 1];
|
char name[TSDB_FUNC_NAME_LEN + 1];
|
||||||
int32_t version;
|
int32_t version;
|
||||||
|
|
||||||
int8_t funcType;
|
int8_t funcType;
|
||||||
|
@ -264,9 +263,11 @@ typedef struct SUdf {
|
||||||
|
|
||||||
SUdfScriptPlugin *scriptPlugin;
|
SUdfScriptPlugin *scriptPlugin;
|
||||||
void *scriptUdfCtx;
|
void *scriptUdfCtx;
|
||||||
|
|
||||||
|
int64_t lastFetchTime; // last fetch time in milliseconds
|
||||||
|
bool expired;
|
||||||
} SUdf;
|
} SUdf;
|
||||||
|
|
||||||
// TODO: add private udf structure.
|
|
||||||
typedef struct SUdfcFuncHandle {
|
typedef struct SUdfcFuncHandle {
|
||||||
SUdf *udf;
|
SUdf *udf;
|
||||||
} SUdfcFuncHandle;
|
} SUdfcFuncHandle;
|
||||||
|
@ -319,7 +320,8 @@ static void udfdCloseWalkCb(uv_handle_t *handle, void *arg);
|
||||||
static int32_t udfdRun();
|
static int32_t udfdRun();
|
||||||
static void udfdConnectMnodeThreadFunc(void *args);
|
static void udfdConnectMnodeThreadFunc(void *args);
|
||||||
|
|
||||||
void udfdInitializeCPlugin(SUdfScriptPlugin *plugin) {
|
SUdf *udfdNewUdf(const char *udfName);
|
||||||
|
void udfdInitializeCPlugin(SUdfScriptPlugin *plugin) {
|
||||||
plugin->scriptType = TSDB_FUNC_SCRIPT_BIN_LIB;
|
plugin->scriptType = TSDB_FUNC_SCRIPT_BIN_LIB;
|
||||||
plugin->openFunc = udfdCPluginOpen;
|
plugin->openFunc = udfdCPluginOpen;
|
||||||
plugin->closeFunc = udfdCPluginClose;
|
plugin->closeFunc = udfdCPluginClose;
|
||||||
|
@ -501,6 +503,7 @@ void convertUdf2UdfInfo(SUdf *udf, SScriptUdfInfo *udfInfo) {
|
||||||
udfInfo->funcType = UDF_FUNC_TYPE_SCALAR;
|
udfInfo->funcType = UDF_FUNC_TYPE_SCALAR;
|
||||||
}
|
}
|
||||||
udfInfo->name = udf->name;
|
udfInfo->name = udf->name;
|
||||||
|
udfInfo->version = udf->version;
|
||||||
udfInfo->outputLen = udf->outputLen;
|
udfInfo->outputLen = udf->outputLen;
|
||||||
udfInfo->outputType = udf->outputType;
|
udfInfo->outputType = udf->outputType;
|
||||||
udfInfo->path = udf->path;
|
udfInfo->path = udf->path;
|
||||||
|
@ -510,9 +513,9 @@ void convertUdf2UdfInfo(SUdf *udf, SScriptUdfInfo *udfInfo) {
|
||||||
int32_t udfdRenameUdfFile(SUdf *udf) {
|
int32_t udfdRenameUdfFile(SUdf *udf) {
|
||||||
char newPath[PATH_MAX];
|
char newPath[PATH_MAX];
|
||||||
if (udf->scriptType == TSDB_FUNC_SCRIPT_BIN_LIB) {
|
if (udf->scriptType == TSDB_FUNC_SCRIPT_BIN_LIB) {
|
||||||
snprintf(newPath, PATH_MAX, "%s/lib%s.so", tsTempDir, udf->name);
|
snprintf(newPath, PATH_MAX, "%s/lib%s_%d_%"PRId64".so", tsTempDir, udf->name, udf->version, udf->lastFetchTime);
|
||||||
} else if (udf->scriptType == TSDB_FUNC_SCRIPT_PYTHON) {
|
} else if (udf->scriptType == TSDB_FUNC_SCRIPT_PYTHON) {
|
||||||
snprintf(newPath, PATH_MAX, "%s/%s.py", tsTempDir, udf->name);
|
snprintf(newPath, PATH_MAX, "%s/%s_%d_%"PRId64".py", tsTempDir, udf->name, udf->version, udf->lastFetchTime);
|
||||||
} else {
|
} else {
|
||||||
return TSDB_CODE_UDF_SCRIPT_NOT_SUPPORTED;
|
return TSDB_CODE_UDF_SCRIPT_NOT_SUPPORTED;
|
||||||
}
|
}
|
||||||
|
@ -557,40 +560,53 @@ int32_t udfdInitUdf(char *udfName, SUdf *udf) {
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
fnInfo("udf init succeeded. name %s type %d context %p", udf->name, udf->scriptType, (void*)udf->scriptUdfCtx);
|
fnInfo("udf init succeeded. name %s type %d context %p", udf->name, udf->scriptType, (void *)udf->scriptUdfCtx);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
SUdf *udfdGetOrCreateUdf(const char *udfName) {
|
SUdf *udfdNewUdf(const char *udfName) {
|
||||||
SUdf *udf = NULL;
|
SUdf *udfNew = taosMemoryCalloc(1, sizeof(SUdf));
|
||||||
uv_mutex_lock(&global.udfsMutex);
|
udfNew->refCount = 1;
|
||||||
SUdf **udfInHash = taosHashGet(global.udfsHash, udfName, strlen(udfName));
|
strncpy(udfNew->name, udfName, TSDB_FUNC_NAME_LEN);
|
||||||
if (udfInHash) {
|
|
||||||
++(*udfInHash)->refCount;
|
|
||||||
udf = *udfInHash;
|
|
||||||
uv_mutex_unlock(&global.udfsMutex);
|
|
||||||
} else {
|
|
||||||
SUdf *udfNew = taosMemoryCalloc(1, sizeof(SUdf));
|
|
||||||
udfNew->refCount = 1;
|
|
||||||
strncpy(udfNew->name, udfName, TSDB_FUNC_NAME_LEN);
|
|
||||||
|
|
||||||
udfNew->state = UDF_STATE_INIT;
|
udfNew->state = UDF_STATE_INIT;
|
||||||
uv_mutex_init(&udfNew->lock);
|
uv_mutex_init(&udfNew->lock);
|
||||||
uv_cond_init(&udfNew->condReady);
|
uv_cond_init(&udfNew->condReady);
|
||||||
|
|
||||||
udf = udfNew;
|
udfNew->resident = false;
|
||||||
udf->resident = false;
|
udfNew->expired = false;
|
||||||
for (int32_t i = 0; i < taosArrayGetSize(global.residentFuncs); ++i) {
|
for (int32_t i = 0; i < taosArrayGetSize(global.residentFuncs); ++i) {
|
||||||
char *funcName = taosArrayGet(global.residentFuncs, i);
|
char *funcName = taosArrayGet(global.residentFuncs, i);
|
||||||
if (strcmp(udfName, funcName) == 0) {
|
if (strcmp(udfName, funcName) == 0) {
|
||||||
udf->resident = true;
|
udfNew->resident = true;
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
SUdf **pUdf = &udf;
|
|
||||||
taosHashPut(global.udfsHash, udfName, strlen(udfName), pUdf, POINTER_BYTES);
|
|
||||||
uv_mutex_unlock(&global.udfsMutex);
|
|
||||||
}
|
}
|
||||||
|
return udfNew;
|
||||||
|
}
|
||||||
|
|
||||||
|
SUdf *udfdGetOrCreateUdf(const char *udfName) {
|
||||||
|
uv_mutex_lock(&global.udfsMutex);
|
||||||
|
SUdf **pUdfHash = taosHashGet(global.udfsHash, udfName, strlen(udfName));
|
||||||
|
int64_t currTime = taosGetTimestampSec();
|
||||||
|
bool expired = currTime - (*pUdfHash)->lastFetchTime > 10 * 1000;
|
||||||
|
if (pUdfHash && !expired) {
|
||||||
|
++(*pUdfHash)->refCount;
|
||||||
|
SUdf *udf = *pUdfHash;
|
||||||
|
uv_mutex_unlock(&global.udfsMutex);
|
||||||
|
return udf;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pUdfHash && expired) {
|
||||||
|
(*pUdfHash)->expired = true;
|
||||||
|
taosHashRemove(global.udfsHash, udfName, strlen(udfName));
|
||||||
|
}
|
||||||
|
|
||||||
|
SUdf *udf = udfdNewUdf(udfName);
|
||||||
|
SUdf **pUdf = &udf;
|
||||||
|
taosHashPut(global.udfsHash, udfName, strlen(udfName), pUdf, POINTER_BYTES);
|
||||||
|
uv_mutex_unlock(&global.udfsMutex);
|
||||||
|
|
||||||
return udf;
|
return udf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -761,17 +777,19 @@ void udfdProcessTeardownRequest(SUvUdfWork *uvUdf, SUdfRequest *request) {
|
||||||
|
|
||||||
uv_mutex_lock(&global.udfsMutex);
|
uv_mutex_lock(&global.udfsMutex);
|
||||||
udf->refCount--;
|
udf->refCount--;
|
||||||
if (udf->refCount == 0 && !udf->resident) {
|
if ((udf->refCount == 0 && !udf->resident) ||
|
||||||
|
(udf->resident && udf->expired)) {
|
||||||
unloadUdf = true;
|
unloadUdf = true;
|
||||||
taosHashRemove(global.udfsHash, udf->name, strlen(udf->name));
|
taosHashRemove(global.udfsHash, udf->name, strlen(udf->name));
|
||||||
}
|
}
|
||||||
uv_mutex_unlock(&global.udfsMutex);
|
uv_mutex_unlock(&global.udfsMutex);
|
||||||
if (unloadUdf) {
|
if (unloadUdf) {
|
||||||
fnInfo("udf teardown. udf name: %s type %d: context %p", udf->name, udf->scriptType, (void*)(udf->scriptUdfCtx));
|
fnInfo("udf teardown. udf name: %s type %d: context %p", udf->name, udf->scriptType, (void *)(udf->scriptUdfCtx));
|
||||||
uv_cond_destroy(&udf->condReady);
|
uv_cond_destroy(&udf->condReady);
|
||||||
uv_mutex_destroy(&udf->lock);
|
uv_mutex_destroy(&udf->lock);
|
||||||
code = udf->scriptPlugin->udfDestroyFunc(udf->scriptUdfCtx);
|
code = udf->scriptPlugin->udfDestroyFunc(udf->scriptUdfCtx);
|
||||||
fnDebug("udfd destroy function returns %d", code);
|
fnDebug("udfd destroy function returns %d", code);
|
||||||
|
taosRemoveFile(udf->path);
|
||||||
taosMemoryFree(udf);
|
taosMemoryFree(udf);
|
||||||
}
|
}
|
||||||
taosMemoryFree(handle);
|
taosMemoryFree(handle);
|
||||||
|
@ -792,6 +810,35 @@ void udfdProcessTeardownRequest(SUvUdfWork *uvUdf, SUdfRequest *request) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int32_t udfdSaveFuncBodyToFile(SFuncInfo* pFuncInfo, SUdf* udf) {
|
||||||
|
if (!osTempSpaceAvailable()) {
|
||||||
|
terrno = TSDB_CODE_NO_AVAIL_DISK;
|
||||||
|
fnError("udfd create shared library failed since %s", terrstr(terrno));
|
||||||
|
return terrno;
|
||||||
|
}
|
||||||
|
|
||||||
|
char path[PATH_MAX] = {0};
|
||||||
|
#ifdef WINDOWS
|
||||||
|
snprintf(path, sizeof(path), "%s%s_%d_%" PRId64, tsTempDir, pFuncInfo->name, udf->version, udf->lastFetchTime);
|
||||||
|
#else
|
||||||
|
snprintf(path, sizeof(path), "%s/%s_%d_%" PRId64, tsTempDir, pFuncInfo->name, udf->version, udf->lastFetchTime);
|
||||||
|
#endif
|
||||||
|
TdFilePtr file = taosOpenFile(path, TD_FILE_CREATE | TD_FILE_WRITE | TD_FILE_READ | TD_FILE_TRUNC);
|
||||||
|
if (file == NULL) {
|
||||||
|
fnError("udfd write udf shared library: %s failed, error: %d %s", path, errno, strerror(errno));
|
||||||
|
return TSDB_CODE_FILE_CORRUPTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
int64_t count = taosWriteFile(file, pFuncInfo->pCode, pFuncInfo->codeSize);
|
||||||
|
if (count != pFuncInfo->codeSize) {
|
||||||
|
fnError("udfd write udf shared library failed");
|
||||||
|
return TSDB_CODE_FILE_CORRUPTED;
|
||||||
|
}
|
||||||
|
taosCloseFile(&file);
|
||||||
|
strncpy(udf->path, path, PATH_MAX);
|
||||||
|
return TSDB_CODE_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
void udfdProcessRpcRsp(void *parent, SRpcMsg *pMsg, SEpSet *pEpSet) {
|
void udfdProcessRpcRsp(void *parent, SRpcMsg *pMsg, SEpSet *pEpSet) {
|
||||||
SUdfdRpcSendRecvInfo *msgInfo = (SUdfdRpcSendRecvInfo *)pMsg->info.ahandle;
|
SUdfdRpcSendRecvInfo *msgInfo = (SUdfdRpcSendRecvInfo *)pMsg->info.ahandle;
|
||||||
|
|
||||||
|
@ -830,49 +877,23 @@ void udfdProcessRpcRsp(void *parent, SRpcMsg *pMsg, SEpSet *pEpSet) {
|
||||||
} else if (msgInfo->rpcType == UDFD_RPC_RETRIVE_FUNC) {
|
} else if (msgInfo->rpcType == UDFD_RPC_RETRIVE_FUNC) {
|
||||||
SRetrieveFuncRsp retrieveRsp = {0};
|
SRetrieveFuncRsp retrieveRsp = {0};
|
||||||
tDeserializeSRetrieveFuncRsp(pMsg->pCont, pMsg->contLen, &retrieveRsp);
|
tDeserializeSRetrieveFuncRsp(pMsg->pCont, pMsg->contLen, &retrieveRsp);
|
||||||
if (retrieveRsp.pFuncInfos == NULL) {
|
|
||||||
goto _return;
|
|
||||||
}
|
|
||||||
SFuncInfo *pFuncInfo = (SFuncInfo *)taosArrayGet(retrieveRsp.pFuncInfos, 0);
|
SFuncInfo *pFuncInfo = (SFuncInfo *)taosArrayGet(retrieveRsp.pFuncInfos, 0);
|
||||||
SUdf *udf = msgInfo->param;
|
SUdf *udf = msgInfo->param;
|
||||||
udf->funcType = pFuncInfo->funcType;
|
udf->funcType = pFuncInfo->funcType;
|
||||||
udf->scriptType = pFuncInfo->scriptType;
|
udf->scriptType = pFuncInfo->scriptType;
|
||||||
udf->outputType = pFuncInfo->outputType;
|
udf->outputType = pFuncInfo->outputType;
|
||||||
udf->outputLen = pFuncInfo->outputLen;
|
udf->outputLen = pFuncInfo->outputLen;
|
||||||
udf->bufSize = pFuncInfo->bufSize;
|
udf->bufSize = pFuncInfo->bufSize;
|
||||||
udf->version = *(int32_t*)taosArrayGet(retrieveRsp.pFuncVersions,0);
|
udf->version = *(int32_t *)taosArrayGet(retrieveRsp.pFuncVersions, 0);
|
||||||
|
|
||||||
if (!osTempSpaceAvailable()) {
|
msgInfo->code = udfdSaveFuncBodyToFile(pFuncInfo, udf);
|
||||||
terrno = TSDB_CODE_NO_AVAIL_DISK;
|
if (msgInfo->code == 0) {
|
||||||
msgInfo->code = terrno;
|
udf->lastFetchTime = taosGetTimestampMs();
|
||||||
fnError("udfd create shared library failed since %s", terrstr(terrno));
|
|
||||||
goto _return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
char path[PATH_MAX] = {0};
|
|
||||||
#ifdef WINDOWS
|
|
||||||
snprintf(path, sizeof(path), "%s%s%d", tsTempDir, pFuncInfo->name, udf->version);
|
|
||||||
#else
|
|
||||||
snprintf(path, sizeof(path), "%s/%s%d", tsTempDir, pFuncInfo->name, udf->version);
|
|
||||||
#endif
|
|
||||||
TdFilePtr file = taosOpenFile(path, TD_FILE_CREATE | TD_FILE_WRITE | TD_FILE_READ | TD_FILE_TRUNC);
|
|
||||||
if (file == NULL) {
|
|
||||||
fnError("udfd write udf shared library: %s failed, error: %d %s", path, errno, strerror(errno));
|
|
||||||
msgInfo->code = TSDB_CODE_FILE_CORRUPTED;
|
|
||||||
goto _return;
|
|
||||||
}
|
|
||||||
|
|
||||||
int64_t count = taosWriteFile(file, pFuncInfo->pCode, pFuncInfo->codeSize);
|
|
||||||
if (count != pFuncInfo->codeSize) {
|
|
||||||
fnError("udfd write udf shared library failed");
|
|
||||||
msgInfo->code = TSDB_CODE_FILE_CORRUPTED;
|
|
||||||
goto _return;
|
|
||||||
}
|
|
||||||
taosCloseFile(&file);
|
|
||||||
strncpy(udf->path, path, PATH_MAX);
|
|
||||||
tFreeSFuncInfo(pFuncInfo);
|
tFreeSFuncInfo(pFuncInfo);
|
||||||
taosArrayDestroy(retrieveRsp.pFuncInfos);
|
taosArrayDestroy(retrieveRsp.pFuncInfos);
|
||||||
msgInfo->code = 0;
|
taosArrayDestroy(retrieveRsp.pFuncVersions);
|
||||||
}
|
}
|
||||||
|
|
||||||
_return:
|
_return:
|
||||||
|
|
Loading…
Reference in New Issue