diff options
author | Jose <jose@zeroc.com> | 2009-12-04 06:51:23 +0100 |
---|---|---|
committer | Jose <jose@zeroc.com> | 2009-12-04 06:51:23 +0100 |
commit | 0ad40835182795b5f9bedeea10aeb6f07c666e7d (patch) | |
tree | 5dff55b02aefb5854a972eb2cef128d1537d5c47 /cpp/src/IceUtil/FileUtil.cpp | |
parent | Bug 4408 - plugin does not work with x64 only installation (diff) | |
download | ice-0ad40835182795b5f9bedeea10aeb6f07c666e7d.tar.bz2 ice-0ad40835182795b5f9bedeea10aeb6f07c666e7d.tar.xz ice-0ad40835182795b5f9bedeea10aeb6f07c666e7d.zip |
4089 - IceGrid database corruption.
Diffstat (limited to 'cpp/src/IceUtil/FileUtil.cpp')
-rw-r--r-- | cpp/src/IceUtil/FileUtil.cpp | 92 |
1 files changed, 92 insertions, 0 deletions
diff --git a/cpp/src/IceUtil/FileUtil.cpp b/cpp/src/IceUtil/FileUtil.cpp index 67f1569fdc0..22628852541 100644 --- a/cpp/src/IceUtil/FileUtil.cpp +++ b/cpp/src/IceUtil/FileUtil.cpp @@ -10,7 +10,13 @@ #include <IceUtil/DisableWarnings.h> #include <IceUtil/FileUtil.h> #include <IceUtil/Unicode.h> +#include <IceUtil/Exception.h> #include <climits> +#include <string.h> + +#ifdef _WIN32 +# include <process.h> +#endif #ifdef _WIN32 # include <io.h> @@ -19,6 +25,7 @@ #ifdef __BCPLUSPLUS__ # include <dir.h> #endif + using namespace std; // @@ -172,6 +179,37 @@ IceUtilInternal::close(int fd) #endif } +IceUtilInternal::FileLock::FileLock(const std::string& path) : + _fd(INVALID_HANDLE_VALUE), + _path(path) +{ + _fd = ::CreateFileW(IceUtil::stringToWstring(path).c_str(), GENERIC_WRITE, 0, NULL, + OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); + _path = path; + + if(_fd == INVALID_HANDLE_VALUE) + { + throw IceUtil::FileLockException(__FILE__, __LINE__, GetLastError(), _path); + } + + if(::LockFile(_fd, 0, 0, 0, 0) == 0) + { + ::CloseHandle(_fd); + throw IceUtil::FileLockException(__FILE__, __LINE__, GetLastError(), _path); + } + // + // In Windows implementation we don't write the process pid to the file, as is + // not posible to read the file from other process while it is locked here. + // +} + +IceUtilInternal::FileLock::~FileLock() +{ + assert(_fd != INVALID_HANDLE_VALUE); + CloseHandle(_fd); + unlink(_path); +} + #ifdef _STLP_BEGIN_NAMESPACE namespace { @@ -407,6 +445,60 @@ IceUtilInternal::close(int fd) return ::close(fd); } +IceUtilInternal::FileLock::FileLock(const std::string& path) : + _fd(-1), + _path(path) +{ + _fd = ::open(path.c_str(), O_RDWR | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); + if(_fd < 0) + { + throw IceUtil::FileLockException(__FILE__, __LINE__, errno, _path); + } + + struct ::flock lock; + lock.l_type = F_WRLCK; // Write lock + lock.l_whence = SEEK_SET; // Begining of file + lock.l_start = 0; + lock.l_len = 0; + + // + // F_SETLK tells fcntl to not block if it cannot + // acquire the lock, if the lock cannot be acquired + // it returns -1 without wait. + // + if(::fcntl(_fd, F_SETLK, &lock) == -1) + { + IceUtil::FileLockException ex(__FILE__, __LINE__, errno, _path); + close(_fd); + throw ex; + } + + // + // If there is an error after here, we close the fd, + // to release the lock. + // + + // + // Now that we have acquire an excluxive write lock, + // write the process pid there. + // + ostringstream os; + os << getpid(); + + if(write(_fd, os.str().c_str(), os.str().size()) == -1) + { + IceUtil::FileLockException ex(__FILE__, __LINE__, errno, _path); + close(_fd); + throw ex; + } +} + +IceUtilInternal::FileLock::~FileLock() +{ + assert(_fd > -1); + unlink(_path); +} + IceUtilInternal::ifstream::ifstream() { } |