diff --git a/source/os/src/osFile.c b/source/os/src/osFile.c index d8cccc83ed..ab9829538d 100644 --- a/source/os/src/osFile.c +++ b/source/os/src/osFile.c @@ -560,6 +560,21 @@ int32_t taosFStatFile(TdFilePtr pFile, int64_t *size, int32_t *mtime) { int32_t taosLockFile(TdFilePtr pFile) { #ifdef WINDOWS + BOOL fSuccess = FALSE; + LARGE_INTEGER fileSize; + OVERLAPPED overlapped = {0}; + + HANDLE hFile = (HANDLE)_get_osfhandle(pFile->fd); + + fSuccess = LockFileEx(hFile, LOCKFILE_EXCLUSIVE_LOCK | LOCKFILE_FAIL_IMMEDIATELY, + 0, // reserved + ~0, // number of bytes to lock low + ~0, // number of bytes to lock high + &overlapped // overlapped structure + ); + if (!fSuccess) { + return GetLastError(); + } return 0; #else assert(pFile->fd >= 0); // Please check if you have closed the file. @@ -570,6 +585,14 @@ int32_t taosLockFile(TdFilePtr pFile) { int32_t taosUnLockFile(TdFilePtr pFile) { #ifdef WINDOWS + BOOL fSuccess = FALSE; + OVERLAPPED overlapped = {0}; + HANDLE hFile = (HANDLE)_get_osfhandle(pFile->fd); + + fSuccess = UnlockFileEx(hFile, 0, ~0, ~0, &overlapped); + if (!fSuccess) { + return GetLastError(); + } return 0; #else assert(pFile->fd >= 0); // Please check if you have closed the file. diff --git a/source/os/test/osTests.cpp b/source/os/test/osTests.cpp index cde31cf707..f831f457f9 100644 --- a/source/os/test/osTests.cpp +++ b/source/os/test/osTests.cpp @@ -36,4 +36,97 @@ TEST(osTest, osSystem) { taosPrintTrace(flags, level, dflag); } +void fileOperateOnFree(void *param) { + char * fname = (char *)param; + TdFilePtr pFile = taosOpenFile(fname, TD_FILE_CREATE | TD_FILE_WRITE); + printf("On free thread open file\n"); + ASSERT_NE(pFile, nullptr); + + int ret = taosLockFile(pFile); + printf("On free thread lock file ret:%d\n", ret); + ASSERT_EQ(ret, 0); + + ret = taosUnLockFile(pFile); + printf("On free thread unlock file ret:%d\n", ret); + ASSERT_EQ(ret, 0); + + ret = taosCloseFile(&pFile); + ASSERT_EQ(ret, 0); + printf("On free thread close file ret:%d\n", ret); +} +void *fileOperateOnFreeThread(void *param) { + fileOperateOnFree(param); + return NULL; +} +void fileOperateOnBusy(void *param) { + char * fname = (char *)param; + TdFilePtr pFile = taosOpenFile(fname, TD_FILE_CREATE | TD_FILE_WRITE); + printf("On busy thread open file\n"); + ASSERT_NE(pFile, nullptr); + + int ret = taosLockFile(pFile); + printf("On busy thread lock file ret:%d\n", ret); + ASSERT_NE(ret, 0); + + ret = taosUnLockFile(pFile); + printf("On busy thread unlock file ret:%d\n", ret); +#ifdef _TD_DARWIN_64 + ASSERT_EQ(ret, 0); +#else + ASSERT_NE(ret, 0); +#endif + + ret = taosCloseFile(&pFile); + printf("On busy thread close file ret:%d\n", ret); + ASSERT_EQ(ret, 0); +} +void *fileOperateOnBusyThread(void *param) { + fileOperateOnBusy(param); + return NULL; +} + +TEST(osTest, osFile) { + char *fname = "./osfiletest1.txt"; + + TdFilePtr pOutFD = taosCreateFile(fname, TD_FILE_WRITE | TD_FILE_CREATE | TD_FILE_TRUNC); + ASSERT_NE(pOutFD, nullptr); + printf("create file success\n"); + + TdFilePtr pFile = taosOpenFile(fname, TD_FILE_CREATE | TD_FILE_WRITE); + printf("open file\n"); + ASSERT_NE(pFile, nullptr); + + int ret = taosLockFile(pFile); + printf("lock file ret:%d\n", ret); + ASSERT_EQ(ret, 0); + + TdThreadAttr thattr; + taosThreadAttrInit(&thattr); + + TdThread thread1, thread2; + taosThreadCreate(&(thread1), &thattr, fileOperateOnBusyThread, (void *)fname); + taosThreadAttrDestroy(&thattr); + + taosThreadJoin(thread1, NULL); + taosThreadClear(&thread1); + + ret = taosUnLockFile(pFile); + printf("unlock file ret:%d\n", ret); + ASSERT_EQ(ret, 0); + + ret = taosCloseFile(&pFile); + printf("close file ret:%d\n", ret); + ASSERT_EQ(ret, 0); + + taosThreadCreate(&(thread2), &thattr, fileOperateOnFreeThread, (void *)fname); + taosThreadAttrDestroy(&thattr); + + taosThreadJoin(thread2, NULL); + taosThreadClear(&thread2); + + //int ret = taosRemoveFile(fname); + //ASSERT_EQ(ret, 0); + //printf("remove file success"); +} + #pragma GCC diagnostic pop