Merge branch 'develop' into feature/TD-1413
This commit is contained in:
commit
95da7b8bd6
|
@ -61,7 +61,7 @@ The use of each configuration item is:
|
||||||
|
|
||||||
* **port**: This is the `http` service port which enables other application to manage rules by `restful API`.
|
* **port**: This is the `http` service port which enables other application to manage rules by `restful API`.
|
||||||
* **database**: rules are stored in a `sqlite` database, this is the path of the database file (if the file does not exist, the alert application creates it automatically).
|
* **database**: rules are stored in a `sqlite` database, this is the path of the database file (if the file does not exist, the alert application creates it automatically).
|
||||||
* **tdengine**: connection string of `TDEngine` server, note in most cases the database information should be put in a rule, thus it should NOT be included here.
|
* **tdengine**: connection string of `TDEngine` server, note the database name should be put in the `sql` field of a rule in most cases, thus it should NOT be included in the string.
|
||||||
* **log > level**: log level, could be `production` or `debug`.
|
* **log > level**: log level, could be `production` or `debug`.
|
||||||
* **log > path**: log output file path.
|
* **log > path**: log output file path.
|
||||||
* **receivers > alertManager**: the alert application pushes alerts to `AlertManager` at this URL.
|
* **receivers > alertManager**: the alert application pushes alerts to `AlertManager` at this URL.
|
||||||
|
|
|
@ -58,7 +58,7 @@ $ go build
|
||||||
|
|
||||||
* **port**:报警监测程序支持使用 `restful API` 对规则进行管理,这个参数用于配置 `http` 服务的侦听端口。
|
* **port**:报警监测程序支持使用 `restful API` 对规则进行管理,这个参数用于配置 `http` 服务的侦听端口。
|
||||||
* **database**:报警监测程序将规则保存到了一个 `sqlite` 数据库中,这个参数用于指定数据库文件的路径(不需要提前创建这个文件,如果它不存在,程序会自动创建它)。
|
* **database**:报警监测程序将规则保存到了一个 `sqlite` 数据库中,这个参数用于指定数据库文件的路径(不需要提前创建这个文件,如果它不存在,程序会自动创建它)。
|
||||||
* **tdengine**:`TDEngine` 的连接信息,一般来说,数据库信息应该在报警规则中指定,所以这里 **不** 应包含这一部分信息。
|
* **tdengine**:`TDEngine` 的连接字符串,一般来说,数据库名应该在报警规则的 `sql` 语句中指定,所以这个字符串中 **不** 应包含数据库名。
|
||||||
* **log > level**:日志的记录级别,可选 `production` 或 `debug`。
|
* **log > level**:日志的记录级别,可选 `production` 或 `debug`。
|
||||||
* **log > path**:日志文件的路径。
|
* **log > path**:日志文件的路径。
|
||||||
* **receivers > alertManager**:报警监测程序会将报警推送到 `AlertManager`,在这里指定 `AlertManager` 的接收地址。
|
* **receivers > alertManager**:报警监测程序会将报警推送到 `AlertManager`,在这里指定 `AlertManager` 的接收地址。
|
||||||
|
|
|
@ -4,7 +4,7 @@ PROJECT(TDengine)
|
||||||
IF (DEFINED VERNUMBER)
|
IF (DEFINED VERNUMBER)
|
||||||
SET(TD_VER_NUMBER ${VERNUMBER})
|
SET(TD_VER_NUMBER ${VERNUMBER})
|
||||||
ELSE ()
|
ELSE ()
|
||||||
SET(TD_VER_NUMBER "2.0.5.1")
|
SET(TD_VER_NUMBER "2.0.6.0")
|
||||||
ENDIF ()
|
ENDIF ()
|
||||||
|
|
||||||
IF (DEFINED VERCOMPATIBLE)
|
IF (DEFINED VERCOMPATIBLE)
|
||||||
|
|
|
@ -123,7 +123,7 @@ if [[ "$pagMode" != "lite" ]] && [[ "$cpuType" != "aarch32" ]]; then
|
||||||
cp -r ${examples_dir}/R ${install_dir}/examples
|
cp -r ${examples_dir}/R ${install_dir}/examples
|
||||||
sed -i '/password/ {s/taosdata/powerdb/g}' ${install_dir}/examples/R/command.txt
|
sed -i '/password/ {s/taosdata/powerdb/g}' ${install_dir}/examples/R/command.txt
|
||||||
cp -r ${examples_dir}/go ${install_dir}/examples
|
cp -r ${examples_dir}/go ${install_dir}/examples
|
||||||
sed -i '/root/ {s/taosdata/powerdb/g}' ${install_dir}/examples/go/src/taosapp/taosapp.go
|
sed -i '/root/ {s/taosdata/powerdb/g}' ${install_dir}/examples/go/taosdemo.go
|
||||||
fi
|
fi
|
||||||
# Copy driver
|
# Copy driver
|
||||||
mkdir -p ${install_dir}/driver
|
mkdir -p ${install_dir}/driver
|
||||||
|
|
|
@ -146,7 +146,7 @@ if [[ "$pagMode" != "lite" ]] && [[ "$cpuType" != "aarch32" ]]; then
|
||||||
cp -r ${examples_dir}/R ${install_dir}/examples
|
cp -r ${examples_dir}/R ${install_dir}/examples
|
||||||
sed -i '/password/ {s/taosdata/powerdb/g}' ${install_dir}/examples/R/command.txt
|
sed -i '/password/ {s/taosdata/powerdb/g}' ${install_dir}/examples/R/command.txt
|
||||||
cp -r ${examples_dir}/go ${install_dir}/examples
|
cp -r ${examples_dir}/go ${install_dir}/examples
|
||||||
sed -i '/root/ {s/taosdata/powerdb/g}' ${install_dir}/examples/go/src/taosapp/taosapp.go
|
sed -i '/root/ {s/taosdata/powerdb/g}' ${install_dir}/examples/go/taosdemo.go
|
||||||
fi
|
fi
|
||||||
# Copy driver
|
# Copy driver
|
||||||
mkdir -p ${install_dir}/driver
|
mkdir -p ${install_dir}/driver
|
||||||
|
|
|
@ -10,6 +10,7 @@ data_dir="/var/lib/taos"
|
||||||
log_dir="/var/log/taos"
|
log_dir="/var/log/taos"
|
||||||
data_link_dir="/usr/local/taos/data"
|
data_link_dir="/usr/local/taos/data"
|
||||||
log_link_dir="/usr/local/taos/log"
|
log_link_dir="/usr/local/taos/log"
|
||||||
|
install_main_dir="/usr/local/taos"
|
||||||
|
|
||||||
# static directory
|
# static directory
|
||||||
cfg_dir="/usr/local/taos/cfg"
|
cfg_dir="/usr/local/taos/cfg"
|
||||||
|
@ -134,6 +135,29 @@ function install_config() {
|
||||||
else
|
else
|
||||||
break
|
break
|
||||||
fi
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# user email
|
||||||
|
#EMAIL_PATTERN='^[A-Za-z0-9\u4e00-\u9fa5]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$'
|
||||||
|
#EMAIL_PATTERN='^[\w-]+(\.[\w-]+)*@[\w-]+(\.[\w-]+)+$'
|
||||||
|
#EMAIL_PATTERN="^[\w-]+(\.[\w-]+)*@[\w-]+(\.[\w-]+)+$"
|
||||||
|
echo
|
||||||
|
echo -e -n "${GREEN}Enter your email address for priority support or enter empty to skip${NC}: "
|
||||||
|
read emailAddr
|
||||||
|
while true; do
|
||||||
|
if [ ! -z "$emailAddr" ]; then
|
||||||
|
# check the format of the emailAddr
|
||||||
|
#if [[ "$emailAddr" =~ $EMAIL_PATTERN ]]; then
|
||||||
|
# Write the email address to temp file
|
||||||
|
email_file="${install_main_dir}/email"
|
||||||
|
${csudo} bash -c "echo $emailAddr > ${email_file}"
|
||||||
|
break
|
||||||
|
#else
|
||||||
|
# read -p "Please enter the correct email address: " emailAddr
|
||||||
|
#fi
|
||||||
|
else
|
||||||
|
break
|
||||||
|
fi
|
||||||
done
|
done
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit 8c58c512b6acda8bcdfa48fdc7140227b5221766
|
Subproject commit 8d7bf743852897110cbdcc7c4322cd7a74d4167b
|
|
@ -97,7 +97,7 @@ void dnodeCleanupModules() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tsModule[TSDB_MOD_MNODE].enable && tsModule[TSDB_MOD_MNODE].cleanUpFp) {
|
if (tsModule[TSDB_MOD_MNODE].cleanUpFp) {
|
||||||
(*tsModule[TSDB_MOD_MNODE].cleanUpFp)();
|
(*tsModule[TSDB_MOD_MNODE].cleanUpFp)();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -190,6 +190,7 @@ void dnodeFreeVnodeWqueue(void *wqueue) {
|
||||||
|
|
||||||
void dnodeSendRpcVnodeWriteRsp(void *pVnode, void *param, int32_t code) {
|
void dnodeSendRpcVnodeWriteRsp(void *pVnode, void *param, int32_t code) {
|
||||||
SWriteMsg *pWrite = (SWriteMsg *)param;
|
SWriteMsg *pWrite = (SWriteMsg *)param;
|
||||||
|
if (pWrite == NULL) return;
|
||||||
|
|
||||||
if (code < 0) pWrite->code = code;
|
if (code < 0) pWrite->code = code;
|
||||||
int32_t count = atomic_add_fetch_32(&pWrite->processedCount, 1);
|
int32_t count = atomic_add_fetch_32(&pWrite->processedCount, 1);
|
||||||
|
|
|
@ -90,11 +90,12 @@ void shellParseArgument(int argc, char *argv[], SShellArguments *arguments) {
|
||||||
}
|
}
|
||||||
} else if (strcmp(argv[i], "-c") == 0) {
|
} else if (strcmp(argv[i], "-c") == 0) {
|
||||||
if (i < argc - 1) {
|
if (i < argc - 1) {
|
||||||
if (strlen(argv[++i]) >= TSDB_FILENAME_LEN) {
|
char *tmp = argv[++i];
|
||||||
fprintf(stderr, "config file path: %s overflow max len %d\n", argv[i], TSDB_FILENAME_LEN - 1);
|
if (strlen(tmp) >= TSDB_FILENAME_LEN) {
|
||||||
|
fprintf(stderr, "config file path: %s overflow max len %d\n", tmp, TSDB_FILENAME_LEN - 1);
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
strcpy(configDir, argv[++i]);
|
strcpy(configDir, tmp);
|
||||||
} else {
|
} else {
|
||||||
fprintf(stderr, "Option -c requires an argument\n");
|
fprintf(stderr, "Option -c requires an argument\n");
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
|
|
|
@ -123,16 +123,18 @@ int32_t mnodeInitSystem() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void mnodeCleanupSystem() {
|
void mnodeCleanupSystem() {
|
||||||
mInfo("starting to clean up mnode");
|
if (tsMgmtIsRunning) {
|
||||||
tsMgmtIsRunning = false;
|
mInfo("starting to clean up mnode");
|
||||||
|
tsMgmtIsRunning = false;
|
||||||
|
|
||||||
dnodeFreeMnodeWqueue();
|
dnodeFreeMnodeWqueue();
|
||||||
dnodeFreeMnodeRqueue();
|
dnodeFreeMnodeRqueue();
|
||||||
dnodeFreeMnodePqueue();
|
dnodeFreeMnodePqueue();
|
||||||
mnodeCleanupTimer();
|
mnodeCleanupTimer();
|
||||||
mnodeCleanupComponents(sizeof(tsMnodeComponents) / sizeof(tsMnodeComponents[0]) - 1);
|
mnodeCleanupComponents(sizeof(tsMnodeComponents) / sizeof(tsMnodeComponents[0]) - 1);
|
||||||
|
|
||||||
mInfo("mnode is cleaned up");
|
mInfo("mnode is cleaned up");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void mnodeStopSystem() {
|
void mnodeStopSystem() {
|
||||||
|
|
|
@ -6771,7 +6771,7 @@ int32_t qRetrieveQueryResultInfo(qinfo_t qinfo, bool* buildRes, void* pRspContex
|
||||||
|
|
||||||
*buildRes = false;
|
*buildRes = false;
|
||||||
if (IS_QUERY_KILLED(pQInfo)) {
|
if (IS_QUERY_KILLED(pQInfo)) {
|
||||||
qDebug("QInfo:%p query is killed, code:%d", pQInfo, pQInfo->code);
|
qDebug("QInfo:%p query is killed, code:0x%08x", pQInfo, pQInfo->code);
|
||||||
return pQInfo->code;
|
return pQInfo->code;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7149,13 +7149,20 @@ void** qRegisterQInfo(void* pMgmt, uint64_t qInfo) {
|
||||||
void** qAcquireQInfo(void* pMgmt, uint64_t _key) {
|
void** qAcquireQInfo(void* pMgmt, uint64_t _key) {
|
||||||
SQueryMgmt *pQueryMgmt = pMgmt;
|
SQueryMgmt *pQueryMgmt = pMgmt;
|
||||||
|
|
||||||
if (pQueryMgmt->qinfoPool == NULL || pQueryMgmt->closed) {
|
if (pQueryMgmt->closed) {
|
||||||
|
terrno = TSDB_CODE_VND_INVALID_VGROUP_ID;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pQueryMgmt->qinfoPool == NULL) {
|
||||||
|
terrno = TSDB_CODE_QRY_INVALID_QHANDLE;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
TSDB_CACHE_PTR_TYPE key = (TSDB_CACHE_PTR_TYPE)_key;
|
TSDB_CACHE_PTR_TYPE key = (TSDB_CACHE_PTR_TYPE)_key;
|
||||||
void** handle = taosCacheAcquireByKey(pQueryMgmt->qinfoPool, &key, sizeof(TSDB_CACHE_PTR_TYPE));
|
void** handle = taosCacheAcquireByKey(pQueryMgmt->qinfoPool, &key, sizeof(TSDB_CACHE_PTR_TYPE));
|
||||||
if (handle == NULL || *handle == NULL) {
|
if (handle == NULL || *handle == NULL) {
|
||||||
|
terrno = TSDB_CODE_QRY_INVALID_QHANDLE;
|
||||||
return NULL;
|
return NULL;
|
||||||
} else {
|
} else {
|
||||||
return handle;
|
return handle;
|
||||||
|
|
|
@ -174,12 +174,15 @@ static void taosStopTcpThread(SThreadObj* pThreadObj) {
|
||||||
pThreadObj->stop = true;
|
pThreadObj->stop = true;
|
||||||
eventfd_t fd = -1;
|
eventfd_t fd = -1;
|
||||||
|
|
||||||
|
// save thread into local variable since pThreadObj is freed when thread exits
|
||||||
|
pthread_t thread = pThreadObj->thread;
|
||||||
|
|
||||||
if (taosComparePthread(pThreadObj->thread, pthread_self())) {
|
if (taosComparePthread(pThreadObj->thread, pthread_self())) {
|
||||||
pthread_detach(pthread_self());
|
pthread_detach(pthread_self());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (taosCheckPthreadValid(pThreadObj->thread) && pThreadObj->pollFd >= 0) {
|
if (taosCheckPthreadValid(pThreadObj->thread)) {
|
||||||
// signal the thread to stop, try graceful method first,
|
// signal the thread to stop, try graceful method first,
|
||||||
// and use pthread_cancel when failed
|
// and use pthread_cancel when failed
|
||||||
struct epoll_event event = { .events = EPOLLIN };
|
struct epoll_event event = { .events = EPOLLIN };
|
||||||
|
@ -196,8 +199,9 @@ static void taosStopTcpThread(SThreadObj* pThreadObj) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (taosCheckPthreadValid(pThreadObj->thread) && pThreadObj->pollFd >= 0) {
|
// at this step, pThreadObj has already been released
|
||||||
pthread_join(pThreadObj->thread, NULL);
|
if (taosCheckPthreadValid(thread)) {
|
||||||
|
pthread_join(thread, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fd != -1) taosCloseSocket(fd);
|
if (fd != -1) taosCloseSocket(fd);
|
||||||
|
|
|
@ -287,16 +287,22 @@ static int32_t vnodeProcessFetchMsg(SVnodeObj *pVnode, SReadMsg *pReadMsg) {
|
||||||
|
|
||||||
memset(pRet, 0, sizeof(SRspRet));
|
memset(pRet, 0, sizeof(SRspRet));
|
||||||
|
|
||||||
|
terrno = TSDB_CODE_SUCCESS;
|
||||||
int32_t code = TSDB_CODE_SUCCESS;
|
int32_t code = TSDB_CODE_SUCCESS;
|
||||||
void ** handle = qAcquireQInfo(pVnode->qMgmt, pRetrieve->qhandle);
|
void ** handle = qAcquireQInfo(pVnode->qMgmt, pRetrieve->qhandle);
|
||||||
if (handle == NULL || (*handle) != (void *)pRetrieve->qhandle) {
|
if (handle == NULL) {
|
||||||
|
code = terrno;
|
||||||
|
terrno = TSDB_CODE_SUCCESS;
|
||||||
|
} else if ((*handle) != (void *)pRetrieve->qhandle) {
|
||||||
code = TSDB_CODE_QRY_INVALID_QHANDLE;
|
code = TSDB_CODE_QRY_INVALID_QHANDLE;
|
||||||
vDebug("vgId:%d, invalid qhandle in retrieving result, QInfo:%p", pVnode->vgId, (void *)pRetrieve->qhandle);
|
}
|
||||||
|
|
||||||
|
if (code != TSDB_CODE_SUCCESS) {
|
||||||
|
vDebug("vgId:%d, invalid handle in retrieving result, code:0x%08x, QInfo:%p", pVnode->vgId, code, (void *)pRetrieve->qhandle);
|
||||||
vnodeBuildNoResultQueryRsp(pRet);
|
vnodeBuildNoResultQueryRsp(pRet);
|
||||||
return code;
|
return code;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pRetrieve->free == 1) {
|
if (pRetrieve->free == 1) {
|
||||||
vWarn("vgId:%d, QInfo:%p, retrieve msg received to kill query and free qhandle", pVnode->vgId, *handle);
|
vWarn("vgId:%d, QInfo:%p, retrieve msg received to kill query and free qhandle", pVnode->vgId, *handle);
|
||||||
qKillQuery(*handle);
|
qKillQuery(*handle);
|
||||||
|
|
|
@ -60,6 +60,7 @@ static int walRestoreWalFile(SWal *pWal, void *pVnode, FWalWrite writeFp);
|
||||||
static int walRemoveWalFiles(const char *path);
|
static int walRemoveWalFiles(const char *path);
|
||||||
static void walProcessFsyncTimer(void *param, void *tmrId);
|
static void walProcessFsyncTimer(void *param, void *tmrId);
|
||||||
static void walRelease(SWal *pWal);
|
static void walRelease(SWal *pWal);
|
||||||
|
static int walGetMaxOldFileId(char *odir);
|
||||||
|
|
||||||
static void walModuleInitFunc() {
|
static void walModuleInitFunc() {
|
||||||
walTmrCtrl = taosTmrInit(1000, 100, 300000, "WAL");
|
walTmrCtrl = taosTmrInit(1000, 100, 300000, "WAL");
|
||||||
|
@ -312,7 +313,7 @@ int walRestore(void *handle, void *pVnode, int (*writeFp)(void *, void *, int))
|
||||||
for (index = minId; index <= maxId; ++index) {
|
for (index = minId; index <= maxId; ++index) {
|
||||||
snprintf(pWal->name, sizeof(pWal->name), "%s/%s%d", opath, walPrefix, index);
|
snprintf(pWal->name, sizeof(pWal->name), "%s/%s%d", opath, walPrefix, index);
|
||||||
terrno = walRestoreWalFile(pWal, pVnode, writeFp);
|
terrno = walRestoreWalFile(pWal, pVnode, writeFp);
|
||||||
if (terrno < 0) break;
|
if (terrno < 0) continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -476,31 +477,26 @@ int walHandleExistingFiles(const char *path) {
|
||||||
int plen = strlen(walPrefix);
|
int plen = strlen(walPrefix);
|
||||||
terrno = 0;
|
terrno = 0;
|
||||||
|
|
||||||
if (access(opath, F_OK) == 0) {
|
int midx = walGetMaxOldFileId(opath);
|
||||||
// old directory is there, it means restore process is not finished
|
int count = 0;
|
||||||
walRemoveWalFiles(path);
|
while ((ent = readdir(dir)) != NULL) {
|
||||||
|
if (strncmp(ent->d_name, walPrefix, plen) == 0) {
|
||||||
} else {
|
midx++;
|
||||||
// move all files to old directory
|
snprintf(oname, sizeof(oname), "%s/%s", path, ent->d_name);
|
||||||
int count = 0;
|
snprintf(nname, sizeof(nname), "%s/old/wal%d", path, midx);
|
||||||
while ((ent = readdir(dir)) != NULL) {
|
if (taosMkDir(opath, 0755) != 0) {
|
||||||
if (strncmp(ent->d_name, walPrefix, plen) == 0) {
|
wError("wal:%s, failed to create directory:%s(%s)", oname, opath, strerror(errno));
|
||||||
snprintf(oname, sizeof(oname), "%s/%s", path, ent->d_name);
|
terrno = TAOS_SYSTEM_ERROR(errno);
|
||||||
snprintf(nname, sizeof(nname), "%s/old/%s", path, ent->d_name);
|
break;
|
||||||
if (taosMkDir(opath, 0755) != 0) {
|
|
||||||
wError("wal:%s, failed to create directory:%s(%s)", oname, opath, strerror(errno));
|
|
||||||
terrno = TAOS_SYSTEM_ERROR(errno);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (rename(oname, nname) < 0) {
|
|
||||||
wError("wal:%s, failed to move to new:%s", oname, nname);
|
|
||||||
terrno = TAOS_SYSTEM_ERROR(errno);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
count++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (rename(oname, nname) < 0) {
|
||||||
|
wError("wal:%s, failed to move to new:%s", oname, nname);
|
||||||
|
terrno = TAOS_SYSTEM_ERROR(errno);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
count++;
|
||||||
}
|
}
|
||||||
|
|
||||||
wDebug("wal:%s, %d files are moved for restoration", path, count);
|
wDebug("wal:%s, %d files are moved for restoration", path, count);
|
||||||
|
@ -563,4 +559,30 @@ int64_t walGetVersion(twalh param) {
|
||||||
if (pWal == 0) return 0;
|
if (pWal == 0) return 0;
|
||||||
|
|
||||||
return pWal->version;
|
return pWal->version;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int walGetMaxOldFileId(char *odir) {
|
||||||
|
int midx = 0;
|
||||||
|
DIR * dir = NULL;
|
||||||
|
struct dirent *dp = NULL;
|
||||||
|
int plen = strlen(walPrefix);
|
||||||
|
|
||||||
|
if (access(odir, F_OK) != 0) return midx;
|
||||||
|
|
||||||
|
dir = opendir(odir);
|
||||||
|
if (dir == NULL) {
|
||||||
|
wError("failed to open directory %s since %s", odir, strerror(errno));
|
||||||
|
terrno = TAOS_SYSTEM_ERROR(errno);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
while ((dp = readdir(dir)) != NULL) {
|
||||||
|
if (strncmp(dp->d_name, walPrefix, plen) == 0) {
|
||||||
|
int idx = atol(dp->d_name + plen);
|
||||||
|
if (midx < idx) midx = idx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
closedir(dir);
|
||||||
|
return midx;
|
||||||
}
|
}
|
Loading…
Reference in New Issue