diff --git a/source/os/CMakeLists.txt b/source/os/CMakeLists.txt index 5d9b6ee5cc..3aac5e9775 100644 --- a/source/os/CMakeLists.txt +++ b/source/os/CMakeLists.txt @@ -59,4 +59,8 @@ endif() IF (JEMALLOC_ENABLED) target_link_libraries(os PUBLIC -ljemalloc) -ENDIF () \ No newline at end of file +ENDIF () + +if(${BUILD_TEST}) + add_subdirectory(test) +endif(${BUILD_TEST}) \ No newline at end of file diff --git a/source/os/src/osFile.c b/source/os/src/osFile.c index fce276bc35..3f527e9130 100644 --- a/source/os/src/osFile.c +++ b/source/os/src/osFile.c @@ -526,6 +526,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. @@ -536,6 +551,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 d79e1934de..f831f457f9 100644 --- a/source/os/test/osTests.cpp +++ b/source/os/test/osTests.cpp @@ -27,6 +27,7 @@ #pragma GCC diagnostic ignored "-Wpointer-arith" #include "os.h" +#include "tlog.h" TEST(osTest, osSystem) { const char *flags = "UTL FATAL "; @@ -35,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