mirror of
https://github.com/pocoproject/poco.git
synced 2024-12-12 10:13:51 +01:00
File lock (#4734)
* add RWLock implementation for file [posix] * add implementation FileStreamRWLock for windows replace FileStreamRWLock to the Process package * add files FileStreamRWLock* into makefile and vcproj * remove unnecessary file from makefile * use absolute path to the TesApp with ProcessRunner * fix vc*.proj * add new test files into vc.proj.filters * fix comments * fix spelling fo PR #4723 add atomic_bool _locked and check if FileStreamRWLock is locked on destruction for force unlock * add atomic header * File lock (#4740) * throw error on any errno not only on EDEADLK * fix function naming * fix windows build * fix windows build --------- Co-authored-by: Alexander B <ale.bychuk@gmail.com> Co-authored-by: bas524 <bas524@ya.ru>
This commit is contained in:
parent
6f34ec89ce
commit
e5752a5c6d
@ -977,6 +977,35 @@
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release_static_mt|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release_static_mt|x64'">true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\FileStreamRWLock.cpp" />
|
||||
<ClCompile Include="src\FileStreamRWLock_POSIX.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug_shared|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug_shared|x64'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug_static_md|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug_static_md|x64'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug_static_mt|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug_static_mt|x64'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release_shared|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release_shared|x64'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release_static_md|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release_static_md|x64'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release_static_mt|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release_static_mt|x64'">true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\FileStreamRWLock_WIN32.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug_shared|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug_shared|x64'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug_static_md|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug_static_md|x64'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug_static_mt|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug_static_mt|x64'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release_shared|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release_shared|x64'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release_static_md|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release_static_md|x64'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release_static_mt|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release_static_mt|x64'">true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\NamedMutex.cpp" />
|
||||
<ClCompile Include="src\NamedMutex_UNIX.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug_shared|Win32'">true</ExcludedFromBuild>
|
||||
@ -1613,6 +1642,9 @@
|
||||
<ClInclude Include="include\Poco\FileStreamFactory.h" />
|
||||
<ClInclude Include="include\Poco\FileStream_POSIX.h" />
|
||||
<ClInclude Include="include\Poco\FileStream_WIN32.h" />
|
||||
<ClInclude Include="include\Poco\FileStreamRWLock.h" />
|
||||
<ClInclude Include="include\Poco\FileStreamRWLock_POSIX.h" />
|
||||
<ClInclude Include="include\Poco\FileStreamRWLock_WIN32.h" />
|
||||
<ClInclude Include="include\Poco\File_UNIX.h" />
|
||||
<ClInclude Include="include\Poco\File_WIN32U.h" />
|
||||
<ClInclude Include="include\Poco\Format.h" />
|
||||
@ -1891,4 +1923,4 @@
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets" />
|
||||
</Project>
|
||||
</Project>
|
||||
|
@ -1415,6 +1415,47 @@
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release_static_mt|x64'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release_static_mt|ARM64'">true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\FileStreamRWLock.cpp" />
|
||||
<ClCompile Include="src\FileStreamRWLock_POSIX.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug_shared|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug_shared|x64'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug_shared|ARM64'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug_static_md|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug_static_md|x64'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug_static_md|ARM64'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug_static_mt|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug_static_mt|x64'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug_static_mt|ARM64'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release_shared|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release_shared|x64'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release_shared|ARM64'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release_static_md|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release_static_md|x64'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release_static_md|ARM64'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release_static_mt|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release_static_mt|x64'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release_static_mt|ARM64'">true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\FileStreamRWLock_WIN32.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug_shared|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug_shared|x64'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug_shared|ARM64'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug_static_md|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug_static_md|x64'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug_static_md|ARM64'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug_static_mt|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug_static_mt|x64'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug_static_mt|ARM64'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release_shared|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release_shared|x64'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release_shared|ARM64'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release_static_md|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release_static_md|x64'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release_static_md|ARM64'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release_static_mt|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release_static_mt|x64'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release_static_mt|ARM64'">true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\NamedMutex.cpp" />
|
||||
<ClCompile Include="src\NamedMutex_UNIX.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug_shared|Win32'">true</ExcludedFromBuild>
|
||||
@ -2231,6 +2272,9 @@
|
||||
<ClInclude Include="include\Poco\FileStreamFactory.h" />
|
||||
<ClInclude Include="include\Poco\FileStream_POSIX.h" />
|
||||
<ClInclude Include="include\Poco\FileStream_WIN32.h" />
|
||||
<ClInclude Include="include\Poco\FileStreamRWLock.h" />
|
||||
<ClInclude Include="include\Poco\FileStreamRWLock_POSIX.h" />
|
||||
<ClInclude Include="include\Poco\FileStreamRWLock_WIN32.h" />
|
||||
<ClInclude Include="include\Poco\File_UNIX.h" />
|
||||
<ClInclude Include="include\Poco\File_WIN32U.h" />
|
||||
<ClInclude Include="include\Poco\Format.h" />
|
||||
@ -2533,4 +2577,4 @@
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets" />
|
||||
</Project>
|
||||
</Project>
|
||||
|
@ -34,7 +34,7 @@ objects = ArchiveStrategy Ascii ASCIIEncoding AsyncChannel AsyncNotificationCent
|
||||
FileStreamFactory URIStreamFactory URIStreamOpener UTF32Encoding UTF16Encoding UTF8Encoding UTF8String \
|
||||
Unicode UnicodeConverter Windows1250Encoding Windows1251Encoding Windows1252Encoding \
|
||||
UUID UUIDGenerator Void Var VarHolder VarIterator VarVisitor Format Pipe PipeImpl PipeStream SharedMemory \
|
||||
MemoryStream FileStream AtomicCounter DataURIStream DataURIStreamFactory
|
||||
MemoryStream FileStream AtomicCounter DataURIStream DataURIStreamFactory FileStreamRWLock
|
||||
|
||||
zlib_objects = adler32 compress crc32 deflate \
|
||||
infback inffast inflate inftrees trees zutil
|
||||
|
204
Foundation/include/Poco/FileStreamRWLock.h
Normal file
204
Foundation/include/Poco/FileStreamRWLock.h
Normal file
@ -0,0 +1,204 @@
|
||||
//
|
||||
// FileStreamRWLock.h
|
||||
//
|
||||
// Library: Foundation
|
||||
// Package: Processes
|
||||
// Module: FileStreamRWLock
|
||||
//
|
||||
// Definition of the FileStreamRWLock class.
|
||||
//
|
||||
// Copyright (c) 2004-2024, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
|
||||
#ifndef Foundation_FileStreamRWLock_INCLUDED
|
||||
#define Foundation_FileStreamRWLock_INCLUDED
|
||||
|
||||
|
||||
#include "Poco/Foundation.h"
|
||||
#include "Poco/Exception.h"
|
||||
#include "Poco/FileStream.h"
|
||||
#include <atomic>
|
||||
|
||||
#if defined(POCO_OS_FAMILY_WINDOWS)
|
||||
#include "Poco/FileStreamRWLock_WIN32.h"
|
||||
#else
|
||||
#include "Poco/FileStreamRWLock_POSIX.h"
|
||||
#endif
|
||||
|
||||
|
||||
namespace Poco {
|
||||
|
||||
|
||||
class ScopedFStreamRWLock;
|
||||
class ScopedFStreamReadRWLock;
|
||||
class ScopedFStreamWriteRWLock;
|
||||
|
||||
|
||||
class Foundation_API FileStreamRWLock: private FileStreamRWLockImpl
|
||||
/// A reader writer lock on the file region allows multiple concurrent
|
||||
/// process-readers or one exclusive process-writer.
|
||||
{
|
||||
public:
|
||||
using ScopedLock = ScopedFStreamRWLock;
|
||||
using ScopedReadLock = ScopedFStreamReadRWLock;
|
||||
using ScopedWriteLock = ScopedFStreamWriteRWLock;
|
||||
|
||||
FileStreamRWLock(const FileStream &fs, Poco::UInt64 offset, Poco::UInt64 size);
|
||||
/// Creates the Reader/Writer lock on the file region.
|
||||
/// offset - from start of the file
|
||||
/// size - size of the locker region
|
||||
|
||||
~FileStreamRWLock();
|
||||
/// Destroys the Reader/Writer lock on the file region.
|
||||
|
||||
void readLock();
|
||||
/// Acquires a read lock. If another process currently holds a write lock,
|
||||
/// waits until the write lock is released.
|
||||
|
||||
bool tryReadLock();
|
||||
/// Tries to acquire a read lock. Immediately returns true if successful, or
|
||||
/// false if another process currently holds a write lock.
|
||||
|
||||
void writeLock();
|
||||
/// Acquires a write lock on the file region. If one or more other processes currently hold
|
||||
/// locks, waits until all locks are released.
|
||||
|
||||
bool tryWriteLock();
|
||||
/// Tries to acquire a write lock on the file region. Immediately returns true if successful,
|
||||
/// or false if one or more other processes currently hold
|
||||
/// locks.
|
||||
|
||||
void unlock();
|
||||
/// Releases the read or write lock.
|
||||
|
||||
private:
|
||||
std::atomic_bool _locked = false;
|
||||
FileStreamRWLock(const FileStreamRWLock&);
|
||||
FileStreamRWLock& operator = (const FileStreamRWLock&);
|
||||
};
|
||||
|
||||
|
||||
class Foundation_API ScopedFStreamRWLock
|
||||
/// A variant of ScopedLock for reader/writer locks.
|
||||
{
|
||||
public:
|
||||
ScopedFStreamRWLock(FileStreamRWLock& rwl, bool write = false);
|
||||
~ScopedFStreamRWLock();
|
||||
|
||||
private:
|
||||
FileStreamRWLock& _rwl;
|
||||
|
||||
ScopedFStreamRWLock();
|
||||
ScopedFStreamRWLock(const ScopedFStreamRWLock&);
|
||||
ScopedFStreamRWLock& operator = (const ScopedFStreamRWLock&);
|
||||
};
|
||||
|
||||
|
||||
class Foundation_API ScopedFStreamReadRWLock : public ScopedFStreamRWLock
|
||||
/// A variant of ScopedLock for reader locks.
|
||||
{
|
||||
public:
|
||||
ScopedFStreamReadRWLock(FileStreamRWLock& rwl);
|
||||
~ScopedFStreamReadRWLock();
|
||||
};
|
||||
|
||||
|
||||
class Foundation_API ScopedFStreamWriteRWLock : public ScopedFStreamRWLock
|
||||
/// A variant of ScopedLock for writer locks.
|
||||
{
|
||||
public:
|
||||
ScopedFStreamWriteRWLock(FileStreamRWLock& rwl);
|
||||
~ScopedFStreamWriteRWLock();
|
||||
};
|
||||
|
||||
|
||||
//
|
||||
// inlines
|
||||
//
|
||||
inline void FileStreamRWLock::readLock()
|
||||
{
|
||||
readLockImpl();
|
||||
_locked = true;
|
||||
}
|
||||
|
||||
|
||||
inline bool FileStreamRWLock::tryReadLock()
|
||||
{
|
||||
bool locked = tryReadLockImpl();
|
||||
if (locked) _locked = true; // assign only if success lock
|
||||
return locked;
|
||||
}
|
||||
|
||||
|
||||
inline void FileStreamRWLock::writeLock()
|
||||
{
|
||||
writeLockImpl();
|
||||
_locked = true;
|
||||
}
|
||||
|
||||
|
||||
inline bool FileStreamRWLock::tryWriteLock()
|
||||
{
|
||||
bool locked = tryWriteLockImpl();
|
||||
if (locked) _locked = true; // assign only if success lock
|
||||
return locked;
|
||||
}
|
||||
|
||||
|
||||
inline void FileStreamRWLock::unlock()
|
||||
{
|
||||
unlockImpl();
|
||||
_locked = false;
|
||||
}
|
||||
|
||||
|
||||
inline ScopedFStreamRWLock::ScopedFStreamRWLock(FileStreamRWLock& rwl, bool write): _rwl(rwl)
|
||||
{
|
||||
if (write)
|
||||
_rwl.writeLock();
|
||||
else
|
||||
_rwl.readLock();
|
||||
}
|
||||
|
||||
|
||||
inline ScopedFStreamRWLock::~ScopedFStreamRWLock()
|
||||
{
|
||||
try
|
||||
{
|
||||
_rwl.unlock();
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
poco_unexpected();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
inline ScopedFStreamReadRWLock::ScopedFStreamReadRWLock(FileStreamRWLock& rwl): ScopedFStreamRWLock(rwl, false)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
inline ScopedFStreamReadRWLock::~ScopedFStreamReadRWLock()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
inline ScopedFStreamWriteRWLock::ScopedFStreamWriteRWLock(FileStreamRWLock& rwl): ScopedFStreamRWLock(rwl, true)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
inline ScopedFStreamWriteRWLock::~ScopedFStreamWriteRWLock()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
} // namespace Poco
|
||||
|
||||
|
||||
#endif // Foundation_FileStreamRWLock_INCLUDED
|
115
Foundation/include/Poco/FileStreamRWLock_POSIX.h
Normal file
115
Foundation/include/Poco/FileStreamRWLock_POSIX.h
Normal file
@ -0,0 +1,115 @@
|
||||
//
|
||||
// FileStreamRWLock_POSIX.h
|
||||
//
|
||||
// Library: Foundation
|
||||
// Package: Processes
|
||||
// Module: FileStreamRWLock
|
||||
//
|
||||
// Definition of the FileStreamRWLockImpl class for POSIX FileStream.
|
||||
//
|
||||
// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
|
||||
#ifndef Foundation_FileStreamRWLock_POSIX_INCLUDED
|
||||
#define Foundation_FileStreamRWLock_POSIX_INCLUDED
|
||||
|
||||
|
||||
#include "Poco/Foundation.h"
|
||||
#include "Poco/Exception.h"
|
||||
#include "Poco/FileStream.h"
|
||||
#include <fcntl.h>
|
||||
#include <cerrno>
|
||||
|
||||
|
||||
namespace Poco {
|
||||
|
||||
|
||||
class Foundation_API FileStreamRWLockImpl
|
||||
{
|
||||
protected:
|
||||
FileStreamRWLockImpl(const FileStream::NativeHandle &fd, Poco::UInt64 offset, Poco::UInt64 size);
|
||||
~FileStreamRWLockImpl();
|
||||
void readLockImpl();
|
||||
bool tryReadLockImpl();
|
||||
void writeLockImpl();
|
||||
bool tryWriteLockImpl();
|
||||
void unlockImpl();
|
||||
|
||||
private:
|
||||
FileStream::NativeHandle _fd;
|
||||
struct flock _flock;
|
||||
int _lockMode;
|
||||
};
|
||||
|
||||
|
||||
//
|
||||
// inlines
|
||||
//
|
||||
inline void FileStreamRWLockImpl::readLockImpl()
|
||||
{
|
||||
_flock.l_type = F_RDLCK;
|
||||
_lockMode = F_SETLKW;
|
||||
int rc = fcntl(_fd, _lockMode, &_flock);
|
||||
if (rc == -1)
|
||||
throw SystemException("cannot lock reader lock", errno);
|
||||
}
|
||||
|
||||
|
||||
inline bool FileStreamRWLockImpl::tryReadLockImpl()
|
||||
{
|
||||
_flock.l_type = F_RDLCK;
|
||||
_lockMode = F_SETLK;
|
||||
int rc = fcntl(_fd, _lockMode, &_flock);
|
||||
if (rc == 0)
|
||||
return true;
|
||||
else if (errno == EAGAIN || errno == EACCES)
|
||||
return false;
|
||||
else
|
||||
throw SystemException("cannot lock try-reader lock", errno);
|
||||
|
||||
}
|
||||
|
||||
|
||||
inline void FileStreamRWLockImpl::writeLockImpl()
|
||||
{
|
||||
_flock.l_type = F_WRLCK;
|
||||
_lockMode = F_SETLKW;
|
||||
int rc = fcntl(_fd, _lockMode, &_flock);
|
||||
if (rc == -1)
|
||||
throw SystemException("cannot lock writer lock", errno);
|
||||
}
|
||||
|
||||
|
||||
inline bool FileStreamRWLockImpl::tryWriteLockImpl()
|
||||
{
|
||||
_flock.l_type = F_WRLCK;
|
||||
_lockMode = F_SETLK;
|
||||
int rc = fcntl(_fd, _lockMode, &_flock);
|
||||
if (rc != -1)
|
||||
return true;
|
||||
else if (errno == EAGAIN || errno == EACCES)
|
||||
return false;
|
||||
else
|
||||
throw SystemException("cannot lock writer lock", errno);
|
||||
|
||||
}
|
||||
|
||||
|
||||
inline void FileStreamRWLockImpl::unlockImpl()
|
||||
{
|
||||
_flock.l_type = F_UNLCK;
|
||||
_lockMode = F_SETLKW;
|
||||
int rc = fcntl(_fd, _lockMode, &_flock);
|
||||
if (rc == -1)
|
||||
throw SystemException("cannot unlock", errno);
|
||||
}
|
||||
|
||||
|
||||
} // namespace Poco
|
||||
|
||||
|
||||
#endif // Foundation_FileStreamRWLock_POSIX_INCLUDED
|
134
Foundation/include/Poco/FileStreamRWLock_WIN32.h
Normal file
134
Foundation/include/Poco/FileStreamRWLock_WIN32.h
Normal file
@ -0,0 +1,134 @@
|
||||
//
|
||||
// FileStreamRWLock_WIN32.h
|
||||
//
|
||||
// Library: Foundation
|
||||
// Package: Processes
|
||||
// Module: FileStreamRWLock
|
||||
//
|
||||
// Definition of the FileStreamRWLockImpl class for WIN32 FileStream.
|
||||
//
|
||||
// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
|
||||
#ifndef Foundation_FileStreamRWLock_WIN32_INCLUDED
|
||||
#define Foundation_FileStreamRWLock_WIN32_INCLUDED
|
||||
|
||||
|
||||
#include "Poco/Foundation.h"
|
||||
#include "Poco/Exception.h"
|
||||
#include "Poco/FileStream.h"
|
||||
#include <Windows.h>
|
||||
|
||||
namespace Poco {
|
||||
|
||||
struct LockMode
|
||||
{
|
||||
static constexpr DWORD READ = 0;
|
||||
static constexpr DWORD WRITE = LOCKFILE_EXCLUSIVE_LOCK;
|
||||
static constexpr DWORD TRY_READ = LOCKFILE_FAIL_IMMEDIATELY;
|
||||
static constexpr DWORD TRY_WRITE = (LOCKFILE_EXCLUSIVE_LOCK | LOCKFILE_FAIL_IMMEDIATELY);
|
||||
};
|
||||
|
||||
class Foundation_API FileStreamRWLockImpl
|
||||
{
|
||||
protected:
|
||||
FileStreamRWLockImpl(const FileStream::NativeHandle &fd, Poco::UInt64 offset, Poco::UInt64 size);
|
||||
~FileStreamRWLockImpl();
|
||||
void readLockImpl();
|
||||
bool tryReadLockImpl();
|
||||
void writeLockImpl();
|
||||
bool tryWriteLockImpl();
|
||||
void unlockImpl();
|
||||
|
||||
private:
|
||||
FileStream::NativeHandle _fd;
|
||||
OVERLAPPED _overlapped;
|
||||
LARGE_INTEGER _size;
|
||||
};
|
||||
|
||||
|
||||
//
|
||||
// inlines
|
||||
//
|
||||
inline void FileStreamRWLockImpl::readLockImpl()
|
||||
{
|
||||
BOOL fSuccess = LockFileEx(_fd, LockMode::READ, 0, _size.LowPart, _size.HighPart, &_overlapped);
|
||||
if (!fSuccess)
|
||||
{
|
||||
throw SystemException("cannot lock reader lock", GetLastError());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
inline bool FileStreamRWLockImpl::tryReadLockImpl()
|
||||
{
|
||||
BOOL fSuccess = LockFileEx(_fd, LockMode::TRY_READ, 0, _size.LowPart, _size.HighPart, &_overlapped);
|
||||
if (fSuccess)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
auto lastError = GetLastError();
|
||||
if (lastError == ERROR_IO_PENDING || lastError == ERROR_LOCK_VIOLATION)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw SystemException("cannot lock try-reader lock", lastError);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
inline void FileStreamRWLockImpl::writeLockImpl()
|
||||
{
|
||||
BOOL fSuccess = LockFileEx(_fd, LockMode::WRITE, 0, _size.LowPart, _size.HighPart, &_overlapped);
|
||||
if (!fSuccess)
|
||||
{
|
||||
throw SystemException("cannot lock writer lock", GetLastError());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
inline bool FileStreamRWLockImpl::tryWriteLockImpl()
|
||||
{
|
||||
BOOL fSuccess = LockFileEx(_fd, LockMode::TRY_WRITE, 0, _size.LowPart, _size.HighPart, &_overlapped);
|
||||
if (fSuccess)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
auto lastError = GetLastError();
|
||||
if (lastError == ERROR_IO_PENDING || lastError == ERROR_LOCK_VIOLATION)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw SystemException("cannot lock try-writer lock", lastError);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
inline void FileStreamRWLockImpl::unlockImpl()
|
||||
{
|
||||
BOOL fSuccess = UnlockFileEx(_fd, 0, _size.LowPart, _size.HighPart, &_overlapped);
|
||||
if (!fSuccess)
|
||||
{
|
||||
throw SystemException("cannot unlock ", GetLastError());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} // namespace Poco
|
||||
|
||||
|
||||
#endif // Foundation_FileStreamRWLock_WIN32_INCLUDED
|
44
Foundation/src/FileStreamRWLock.cpp
Normal file
44
Foundation/src/FileStreamRWLock.cpp
Normal file
@ -0,0 +1,44 @@
|
||||
//
|
||||
// FileStreamRWLock.cpp
|
||||
//
|
||||
// Library: Foundation
|
||||
// Package: Processes
|
||||
// Module: FileStreamRWLock
|
||||
//
|
||||
// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
|
||||
#include "Poco/FileStreamRWLock.h"
|
||||
|
||||
|
||||
#if defined(POCO_OS_FAMILY_WINDOWS)
|
||||
#include "FileStreamRWLock_WIN32.cpp"
|
||||
#else
|
||||
#include "FileStreamRWLock_POSIX.cpp"
|
||||
#endif
|
||||
|
||||
|
||||
namespace Poco {
|
||||
|
||||
|
||||
FileStreamRWLock::FileStreamRWLock(const FileStream &fs, Poco::UInt64 offset, Poco::UInt64 size) :
|
||||
FileStreamRWLockImpl(fs.nativeHandle(), offset, size)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
FileStreamRWLock::~FileStreamRWLock()
|
||||
{
|
||||
if (_locked)
|
||||
{
|
||||
unlockImpl();
|
||||
_locked = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} // namespace Poco
|
36
Foundation/src/FileStreamRWLock_POSIX.cpp
Normal file
36
Foundation/src/FileStreamRWLock_POSIX.cpp
Normal file
@ -0,0 +1,36 @@
|
||||
//
|
||||
// FileStreamRWLock_POSIX.cpp
|
||||
//
|
||||
// Library: Foundation
|
||||
// Package: Processes
|
||||
// Module: FileStreamRWLock
|
||||
//
|
||||
// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
|
||||
#include "Poco/FileStreamRWLock_POSIX.h"
|
||||
|
||||
|
||||
namespace Poco {
|
||||
|
||||
|
||||
FileStreamRWLockImpl::FileStreamRWLockImpl(const FileStream::NativeHandle &fd, Poco::UInt64 offset, Poco::UInt64 size):
|
||||
_fd(fd), _lockMode(0)
|
||||
{
|
||||
_flock.l_whence = SEEK_SET;
|
||||
_flock.l_start = offset;
|
||||
_flock.l_len = size;
|
||||
_flock.l_pid = 0;
|
||||
}
|
||||
|
||||
|
||||
FileStreamRWLockImpl::~FileStreamRWLockImpl()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
} // namespace Poco
|
39
Foundation/src/FileStreamRWLock_WIN32.cpp
Normal file
39
Foundation/src/FileStreamRWLock_WIN32.cpp
Normal file
@ -0,0 +1,39 @@
|
||||
//
|
||||
// FileStreamRWLock_WIN32.cpp
|
||||
//
|
||||
// Library: Foundation
|
||||
// Package: Processes
|
||||
// Module: FileStreamRWLock
|
||||
//
|
||||
// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
|
||||
#include "Poco/FileStreamRWLock_WIN32.h"
|
||||
|
||||
|
||||
namespace Poco {
|
||||
|
||||
|
||||
FileStreamRWLockImpl::FileStreamRWLockImpl(const FileStream::NativeHandle &fd, Poco::UInt64 offset, Poco::UInt64 size):
|
||||
_fd(fd)
|
||||
{
|
||||
LARGE_INTEGER offt;
|
||||
offt.QuadPart = offset;
|
||||
memset(&_overlapped, 0, sizeof(OVERLAPPED));
|
||||
|
||||
_overlapped.Offset = offt.LowPart;
|
||||
_overlapped.OffsetHigh = offt.HighPart;
|
||||
_size.QuadPart = size;
|
||||
}
|
||||
|
||||
|
||||
FileStreamRWLockImpl::~FileStreamRWLockImpl()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
} // namespace Poco
|
@ -38,7 +38,7 @@ objects = ActiveMethodTest ActivityTest ActiveDispatcherTest \
|
||||
UniqueExpireCacheTest UniqueExpireLRUCacheTest UnicodeConverterTest \
|
||||
TuplesTest NamedTuplesTest TypeListTest VarTest DynamicTestSuite FileStreamTest \
|
||||
MemoryStreamTest ObjectPoolTest DirectoryWatcherTest DirectoryIteratorsTest \
|
||||
DataURIStreamTest
|
||||
DataURIStreamTest FileStreamRWLockTest
|
||||
|
||||
target = testrunner
|
||||
target_version = 1
|
||||
|
@ -663,6 +663,7 @@
|
||||
<ClCompile Include="src\FileChannelTest.cpp" />
|
||||
<ClCompile Include="src\FileStreamTest.cpp" />
|
||||
<ClCompile Include="src\FilesystemTestSuite.cpp" />
|
||||
<ClCompile Include="src\FileStreamRWLockTest.cpp" />
|
||||
<ClCompile Include="src\FileTest.cpp" />
|
||||
<ClCompile Include="src\FormatTest.cpp" />
|
||||
<ClCompile Include="src\FoundationTestSuite.cpp" />
|
||||
@ -806,7 +807,9 @@
|
||||
<ClInclude Include="src\FIFOEventTest.h" />
|
||||
<ClInclude Include="src\FileChannelTest.h" />
|
||||
<ClInclude Include="src\FileStreamTest.h" />
|
||||
<ClInclude Include="src\FileStreamRWLockTest.h" />
|
||||
<ClInclude Include="src\FilesystemTestSuite.h" />
|
||||
<ClInclude Include="src\FilesystemRWLockTest.h" />
|
||||
<ClInclude Include="src\FileTest.h" />
|
||||
<ClInclude Include="src\FormatTest.h" />
|
||||
<ClInclude Include="src\FoundationTestSuite.h" />
|
||||
@ -912,4 +915,4 @@
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets" />
|
||||
</Project>
|
||||
</Project>
|
||||
|
@ -603,6 +603,8 @@
|
||||
<ClCompile Include="src\ActiveThreadPoolTest.cpp">
|
||||
<Filter>Threading\Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\FileStreamRWLockTest.cpp">
|
||||
<Filter>Processes\Source Files</Filter>
|
||||
<ClCompile Include="src\JSONFormatterTest.cpp">
|
||||
<Filter>Logging\Source Files</Filter>
|
||||
</ClCompile>
|
||||
@ -1031,8 +1033,10 @@
|
||||
<ClInclude Include="src\ActiveThreadPoolTest.h">
|
||||
<Filter>Threading\Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\FileStreamRWLockTest.h">
|
||||
<Filter>Processes\Header Files</Filter>
|
||||
<ClInclude Include="src\JSONFormatterTest.h">
|
||||
<Filter>Logging\Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
</Project>
|
||||
|
@ -996,6 +996,7 @@
|
||||
<ClCompile Include="src\FileChannelTest.cpp" />
|
||||
<ClCompile Include="src\FileStreamTest.cpp" />
|
||||
<ClCompile Include="src\FilesystemTestSuite.cpp" />
|
||||
<ClCompile Include="src\FileStreamRWLockTest.cpp" />
|
||||
<ClCompile Include="src\FileTest.cpp" />
|
||||
<ClCompile Include="src\FormatTest.cpp" />
|
||||
<ClCompile Include="src\FoundationTestSuite.cpp" />
|
||||
@ -1140,6 +1141,7 @@
|
||||
<ClInclude Include="src\FileChannelTest.h" />
|
||||
<ClInclude Include="src\FileStreamTest.h" />
|
||||
<ClInclude Include="src\FilesystemTestSuite.h" />
|
||||
<ClInclude Include="src\FileStreamRWLockTest.h" />
|
||||
<ClInclude Include="src\FileTest.h" />
|
||||
<ClInclude Include="src\FormatTest.h" />
|
||||
<ClInclude Include="src\FoundationTestSuite.h" />
|
||||
@ -1245,4 +1247,4 @@
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets" />
|
||||
</Project>
|
||||
</Project>
|
||||
|
@ -603,6 +603,8 @@
|
||||
<ClCompile Include="src\ActiveThreadPoolTest.cpp">
|
||||
<Filter>Threading\Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\FileStreamRWLockTest.cpp">
|
||||
<Filter>Processes\Source Files</Filter>
|
||||
<ClCompile Include="src\JSONFormatterTest.cpp">
|
||||
<Filter>Logging\Source Files</Filter>
|
||||
</ClCompile>
|
||||
@ -1031,8 +1033,10 @@
|
||||
<ClInclude Include="src\ActiveThreadPoolTest.h">
|
||||
<Filter>Threading\Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\FileStreamRWLockTest.h">
|
||||
<Filter>Processes\Header Files</Filter>
|
||||
<ClInclude Include="src\JSONFormatterTest.h">
|
||||
<Filter>Logging\Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
</Project>
|
||||
|
264
Foundation/testsuite/src/FileStreamRWLockTest.cpp
Normal file
264
Foundation/testsuite/src/FileStreamRWLockTest.cpp
Normal file
@ -0,0 +1,264 @@
|
||||
//
|
||||
// FileStreamRWLockTest.cpp
|
||||
//
|
||||
// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
|
||||
#include "FileStreamRWLockTest.h"
|
||||
#include "CppUnit/TestCaller.h"
|
||||
#include "CppUnit/TestSuite.h"
|
||||
#include "Poco/FileStreamRWLock.h"
|
||||
#include "Poco/FileStream.h"
|
||||
#include "Poco/TemporaryFile.h"
|
||||
#include "Poco/Thread.h"
|
||||
#include "Poco/Runnable.h"
|
||||
#include "Poco/ProcessRunner.h"
|
||||
#include "Poco/Path.h"
|
||||
#include "Poco/Stopwatch.h"
|
||||
|
||||
|
||||
using Poco::FileStreamRWLock;
|
||||
using Poco::Thread;
|
||||
using Poco::Runnable;
|
||||
using Poco::FileStream;
|
||||
using Poco::TemporaryFile;
|
||||
using Poco::ProcessRunner;
|
||||
using Poco::Path;
|
||||
using Poco::Stopwatch;
|
||||
|
||||
static std::string getTestAppName()
|
||||
{
|
||||
std::string name("TestApp");
|
||||
std::string ext;
|
||||
#if POCO_OS == POCO_OS_WINDOWS_NT
|
||||
ext = ".exe";
|
||||
#endif // POCO_OS == POCO_OS_WINDOWS_NT
|
||||
|
||||
#if defined(_DEBUG)
|
||||
Poco::File testapp(name + ext);
|
||||
if (!testapp.exists())
|
||||
{
|
||||
name += "d";
|
||||
}
|
||||
#endif
|
||||
Poco::Path testAppPath = Poco::Path::current();
|
||||
testAppPath.append(name + ext).makeFile();
|
||||
return testAppPath.toString();
|
||||
}
|
||||
|
||||
#if POCO_OS == POCO_OS_WINDOWS_NT
|
||||
|
||||
#include "Poco/File_WIN32U.h"
|
||||
|
||||
HANDLE createFileWithRWAccess(const std::string &path)
|
||||
{
|
||||
DWORD access = GENERIC_READ | GENERIC_WRITE;
|
||||
DWORD shareMode = FILE_SHARE_READ | FILE_SHARE_WRITE;
|
||||
|
||||
HANDLE handle = CreateFileA(path.c_str(), access, shareMode, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
|
||||
if (handle == INVALID_HANDLE_VALUE)
|
||||
Poco::File::handleLastError(path);
|
||||
|
||||
return handle;
|
||||
}
|
||||
#endif
|
||||
|
||||
class FileStreamRWLockRunnable: public Runnable
|
||||
{
|
||||
public:
|
||||
FileStreamRWLockRunnable(std::string fileLock): _fileLock(std::move(fileLock)), _cmd(getTestAppName())
|
||||
{
|
||||
}
|
||||
|
||||
void run() override
|
||||
{
|
||||
std::string pid = Poco::format("%spid%ld.file", Path::tempHome(), Thread::currentOsTid());
|
||||
std::vector<std::string> args;
|
||||
args.push_back(std::string("--lock-file=").append(_fileLock));
|
||||
args.push_back(std::string("--pidfile=").append(pid));
|
||||
ProcessRunner pr(_cmd, args, pid, 0, 10, true);
|
||||
while (pr.running())
|
||||
{
|
||||
Poco::Thread::sleep(100);
|
||||
}
|
||||
int result = pr.result();
|
||||
_ok = (result >= 0);
|
||||
}
|
||||
|
||||
bool ok() const
|
||||
{
|
||||
return _ok;
|
||||
}
|
||||
|
||||
private:
|
||||
std::string _fileLock;
|
||||
bool _ok{false};
|
||||
std::string _cmd;
|
||||
};
|
||||
|
||||
|
||||
class FileStreamRWTryLockRunnable: public Runnable
|
||||
{
|
||||
public:
|
||||
|
||||
FileStreamRWTryLockRunnable(std::string fileLock): _fileLock(std::move(fileLock)), _cmd(getTestAppName())
|
||||
{
|
||||
}
|
||||
|
||||
void run() override
|
||||
{
|
||||
std::string pid = Poco::format("%spid%ld.file", Path::tempHome(), Thread::currentOsTid());
|
||||
std::vector<std::string> args;
|
||||
args.push_back(std::string("--trylock-file=").append(_fileLock));
|
||||
args.push_back(std::string("--pidfile=").append(pid));
|
||||
ProcessRunner pr(_cmd, args, pid, 0, 10, true);
|
||||
while (pr.running())
|
||||
{
|
||||
Poco::Thread::sleep(100);
|
||||
}
|
||||
int result = pr.result();
|
||||
_ok = (result >= 0);
|
||||
}
|
||||
|
||||
bool ok() const
|
||||
{
|
||||
return _ok;
|
||||
}
|
||||
|
||||
private:
|
||||
std::string _fileLock;
|
||||
bool _ok{false};
|
||||
std::string _cmd;
|
||||
};
|
||||
|
||||
|
||||
FileStreamRWLockTest::FileStreamRWLockTest(const std::string& name): CppUnit::TestCase(name)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
FileStreamRWLockTest::~FileStreamRWLockTest()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void FileStreamRWLockTest::testFSLock()
|
||||
{
|
||||
TemporaryFile fl;
|
||||
#if POCO_OS != POCO_OS_WINDOWS_NT
|
||||
FileStream fs(fl.path(), std::ios::in | std::ios::out | std::ios::binary);
|
||||
#else
|
||||
FileStream fs;
|
||||
fs.openHandle(createFileWithRWAccess(fl.path()), std::ios::in | std::ios::out | std::ios::binary);
|
||||
#endif // POCO_OS != POCO_OS_WINDOWS_NT
|
||||
|
||||
Poco::Int32 i32 = 0;
|
||||
fs.seekp(0, std::ios::beg);
|
||||
fs.write((const char *)&i32, sizeof(i32));
|
||||
fs.flushToDisk();
|
||||
|
||||
const auto &path = fl.path();
|
||||
FileStreamRWLockRunnable r1(path);
|
||||
FileStreamRWLockRunnable r2(path);
|
||||
FileStreamRWLockRunnable r3(path);
|
||||
FileStreamRWLockRunnable r4(path);
|
||||
FileStreamRWLockRunnable r5(path);
|
||||
Thread t1;
|
||||
Thread t2;
|
||||
Thread t3;
|
||||
Thread t4;
|
||||
Thread t5;
|
||||
t1.start(r1);
|
||||
t2.start(r2);
|
||||
t3.start(r3);
|
||||
t4.start(r4);
|
||||
t5.start(r5);
|
||||
t1.join();
|
||||
t2.join();
|
||||
t3.join();
|
||||
t4.join();
|
||||
t5.join();
|
||||
|
||||
fs.seekp(0, std::ios::beg);
|
||||
fs.read((char *)&i32, sizeof(i32));
|
||||
assertEqual(500, i32);
|
||||
assertTrue (r1.ok());
|
||||
assertTrue (r2.ok());
|
||||
assertTrue (r3.ok());
|
||||
assertTrue (r4.ok());
|
||||
assertTrue (r5.ok());
|
||||
}
|
||||
|
||||
|
||||
void FileStreamRWLockTest::testFSTryLock()
|
||||
{
|
||||
TemporaryFile fl;
|
||||
#if POCO_OS != POCO_OS_WINDOWS_NT
|
||||
FileStream fs(fl.path(), std::ios::in | std::ios::out | std::ios::binary);
|
||||
#else
|
||||
FileStream fs;
|
||||
fs.openHandle(createFileWithRWAccess(fl.path()), std::ios::in | std::ios::out | std::ios::binary);
|
||||
#endif // POCO_OS != POCO_OS_WINDOWS_NT
|
||||
|
||||
Poco::Int32 i32 = 0;
|
||||
fs.seekp(0, std::ios::beg);
|
||||
fs.write((const char *)&i32, sizeof(i32));
|
||||
fs.flushToDisk();
|
||||
|
||||
const auto &path = fl.path();
|
||||
FileStreamRWTryLockRunnable r1(path);
|
||||
FileStreamRWTryLockRunnable r2(path);
|
||||
FileStreamRWTryLockRunnable r3(path);
|
||||
FileStreamRWTryLockRunnable r4(path);
|
||||
FileStreamRWTryLockRunnable r5(path);
|
||||
Thread t1;
|
||||
Thread t2;
|
||||
Thread t3;
|
||||
Thread t4;
|
||||
Thread t5;
|
||||
t1.start(r1);
|
||||
t2.start(r2);
|
||||
t3.start(r3);
|
||||
t4.start(r4);
|
||||
t5.start(r5);
|
||||
t1.join();
|
||||
t2.join();
|
||||
t3.join();
|
||||
t4.join();
|
||||
t5.join();
|
||||
|
||||
fs.seekp(0, std::ios::beg);
|
||||
fs.read((char *)&i32, sizeof(i32));
|
||||
assertEqual(500, i32);
|
||||
assertTrue (r1.ok());
|
||||
assertTrue (r2.ok());
|
||||
assertTrue (r3.ok());
|
||||
assertTrue (r4.ok());
|
||||
assertTrue (r5.ok());
|
||||
}
|
||||
|
||||
|
||||
void FileStreamRWLockTest::setUp()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void FileStreamRWLockTest::tearDown()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
CppUnit::Test* FileStreamRWLockTest::suite()
|
||||
{
|
||||
CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("FileStreamRWLockTest");
|
||||
|
||||
CppUnit_addLongTest(pSuite, FileStreamRWLockTest, testFSLock);
|
||||
CppUnit_addLongTest(pSuite, FileStreamRWLockTest, testFSTryLock);
|
||||
|
||||
return pSuite;
|
||||
}
|
39
Foundation/testsuite/src/FileStreamRWLockTest.h
Normal file
39
Foundation/testsuite/src/FileStreamRWLockTest.h
Normal file
@ -0,0 +1,39 @@
|
||||
//
|
||||
// FileStreamRWLockTest.h
|
||||
//
|
||||
// Definition of the FileStreamRWLockTest class.
|
||||
//
|
||||
// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
|
||||
#ifndef FileStreamRWLockTest_INCLUDED
|
||||
#define FileStreamRWLockTest_INCLUDED
|
||||
|
||||
|
||||
#include "Poco/Foundation.h"
|
||||
#include "CppUnit/TestCase.h"
|
||||
|
||||
|
||||
class FileStreamRWLockTest: public CppUnit::TestCase
|
||||
{
|
||||
public:
|
||||
FileStreamRWLockTest(const std::string& name);
|
||||
~FileStreamRWLockTest();
|
||||
|
||||
void testFSLock();
|
||||
void testFSTryLock();
|
||||
|
||||
void setUp();
|
||||
void tearDown();
|
||||
|
||||
static CppUnit::Test* suite();
|
||||
|
||||
private:
|
||||
};
|
||||
|
||||
|
||||
#endif // FileStreamRWLockTest_INCLUDED
|
@ -14,6 +14,7 @@
|
||||
#include "NamedEventTest.h"
|
||||
#include "SharedMemoryTest.h"
|
||||
#include "ProcessRunnerTest.h"
|
||||
#include "FileStreamRWLockTest.h"
|
||||
|
||||
|
||||
CppUnit::Test* ProcessesTestSuite::suite()
|
||||
@ -25,6 +26,7 @@ CppUnit::Test* ProcessesTestSuite::suite()
|
||||
pSuite->addTest(NamedEventTest::suite());
|
||||
pSuite->addTest(SharedMemoryTest::suite());
|
||||
pSuite->addTest(ProcessRunnerTest::suite());
|
||||
pSuite->addTest(FileStreamRWLockTest::suite());
|
||||
|
||||
return pSuite;
|
||||
}
|
||||
|
@ -19,10 +19,13 @@
|
||||
#include <cstdlib>
|
||||
#include <signal.h>
|
||||
|
||||
#include "Poco/FileStreamRWLock.h"
|
||||
|
||||
#if defined(POCO_OS_FAMILY_UNIX)
|
||||
#include "Poco/Thread.h"
|
||||
#include "Poco/Runnable.h"
|
||||
#elif defined(POCO_OS_FAMILY_WINDOWS)
|
||||
#include "Poco/Thread.h"
|
||||
#include "Poco/Process.h"
|
||||
#include "Poco/Event.h"
|
||||
#include "Poco/NamedEvent.h"
|
||||
@ -98,6 +101,7 @@ public:
|
||||
_terminate.wait();
|
||||
_terminated.set();
|
||||
}
|
||||
|
||||
#elif defined(POCO_OS_FAMILY_UNIX)
|
||||
void waitForTerminationRequest()
|
||||
{
|
||||
@ -156,6 +160,22 @@ public:
|
||||
#if defined(POCO_OS_FAMILY_WINDOWS)
|
||||
Poco::Event MyApp::_terminated;
|
||||
Poco::NamedEvent MyApp::_terminate(Poco::ProcessImpl::terminationEventName(Poco::Process::id()));
|
||||
|
||||
#include "Poco/File.h"
|
||||
#include "Poco/File_WIN32U.h"
|
||||
|
||||
HANDLE openFileWithRWAccess(const std::string& path)
|
||||
{
|
||||
DWORD access = GENERIC_READ | GENERIC_WRITE;
|
||||
DWORD shareMode = FILE_SHARE_READ | FILE_SHARE_WRITE;
|
||||
|
||||
HANDLE handle = CreateFileA(path.c_str(), access, shareMode, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
|
||||
if (handle == INVALID_HANDLE_VALUE)
|
||||
Poco::File::handleLastError(path);
|
||||
|
||||
return handle;
|
||||
}
|
||||
#endif
|
||||
|
||||
int main(int argc, char** argv)
|
||||
@ -222,6 +242,153 @@ int main(int argc, char** argv)
|
||||
}
|
||||
}
|
||||
#endif
|
||||
else if (argc > 2 && arg.find("--lock-file") != std::string::npos && std::string(argv[2]).find("--pidfile") != std::string::npos)
|
||||
{
|
||||
std::string pidfArg = std::string(argv[2]);
|
||||
std::unique_ptr<PIDFile> pidF;
|
||||
size_t equals_pos = pidfArg.find('=');
|
||||
if (equals_pos != std::string::npos)
|
||||
{
|
||||
std::string pidPath = pidfArg.substr(equals_pos + 1);
|
||||
pidF = std::make_unique<PIDFile>(pidPath, true);
|
||||
}
|
||||
if (pidF == nullptr)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
equals_pos = arg.find('=');
|
||||
if (equals_pos != std::string::npos)
|
||||
{
|
||||
std::string fl = arg.substr(equals_pos + 1);
|
||||
#if POCO_OS != POCO_OS_WINDOWS_NT
|
||||
FileStream fs(fl, std::ios::in | std::ios::out | std::ios::binary);
|
||||
#else
|
||||
FileStream fs;
|
||||
fs.openHandle(openFileWithRWAccess(fl), std::ios::in | std::ios::out | std::ios::binary);
|
||||
#endif // POCO_OS != POCO_OS_WINDOWS_NT
|
||||
Poco::Int32 ok = 1;
|
||||
Poco::Int32 lastCount = 0;
|
||||
Poco::Int32 counter = 0;
|
||||
FileStreamRWLock lock(fs, 0, sizeof(counter));
|
||||
for (int i = 0; i < 100; ++i)
|
||||
{
|
||||
lock.readLock();
|
||||
fs.seekg(0, std::ios::beg);
|
||||
fs.read((char *)&counter, sizeof(counter));
|
||||
lastCount = counter;
|
||||
for (int k = 0; k < 100; ++k)
|
||||
{
|
||||
if (counter != lastCount) ok = -1;
|
||||
}
|
||||
lock.unlock();
|
||||
lock.writeLock();
|
||||
for (int k = 0; k < 100; ++k)
|
||||
{
|
||||
counter = 0;
|
||||
fs.seekg(0, std::ios::beg);
|
||||
fs.read((char *)&counter, sizeof(counter));
|
||||
--counter;
|
||||
fs.seekp(0, std::ios::beg);
|
||||
fs.write((char *)&counter, sizeof(counter));
|
||||
fs.flushToDisk();
|
||||
}
|
||||
for (int k = 0; k < 100; ++k)
|
||||
{
|
||||
fs.seekg(0, std::ios::beg);
|
||||
fs.read((char *)&counter, sizeof(counter));
|
||||
++counter;
|
||||
fs.seekp(0, std::ios::beg);
|
||||
fs.write((char *)&counter, sizeof(counter));
|
||||
fs.flushToDisk();
|
||||
}
|
||||
fs.seekg(0, std::ios::beg);
|
||||
fs.read((char *)&counter, sizeof(counter));
|
||||
++counter;
|
||||
fs.seekp(0, std::ios::beg);
|
||||
fs.write((char *)&counter, sizeof(counter));
|
||||
fs.flushToDisk();
|
||||
if (counter <= lastCount) ok = -1;
|
||||
lock.unlock();
|
||||
}
|
||||
return ok * counter;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
else if (argc > 2 && arg.find("--trylock-file") != std::string::npos && std::string(argv[2]).find("--pidfile") != std::string::npos)
|
||||
{
|
||||
std::string pidfArg = std::string(argv[2]);
|
||||
std::unique_ptr<PIDFile> pidF;
|
||||
size_t equals_pos = pidfArg.find('=');
|
||||
if (equals_pos != std::string::npos)
|
||||
{
|
||||
std::string pidPath = pidfArg.substr(equals_pos + 1);
|
||||
pidF = std::make_unique<PIDFile>(pidPath, true);
|
||||
}
|
||||
if (pidF == nullptr)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
equals_pos = arg.find('=');
|
||||
if (equals_pos != std::string::npos)
|
||||
{
|
||||
std::string fl = arg.substr(equals_pos + 1);
|
||||
#if POCO_OS != POCO_OS_WINDOWS_NT
|
||||
FileStream fs(fl, std::ios::in | std::ios::out | std::ios::binary);
|
||||
#else
|
||||
FileStream fs;
|
||||
fs.openHandle(openFileWithRWAccess(fl), std::ios::in | std::ios::out | std::ios::binary);
|
||||
#endif // POCO_OS != POCO_OS_WINDOWS_NT
|
||||
Poco::Int32 ok = 1;
|
||||
Poco::Int32 lastCount = 0;
|
||||
Poco::Int32 counter = 0;
|
||||
FileStreamRWLock lock(fs, 0, sizeof(counter));
|
||||
for (int i = 0; i < 100; ++i)
|
||||
{
|
||||
while (!lock.tryReadLock()) Thread::yield();
|
||||
fs.seekg(0, std::ios::beg);
|
||||
fs.read((char *)&counter, sizeof(counter));
|
||||
lastCount = counter;
|
||||
for (int k = 0; k < 100; ++k)
|
||||
{
|
||||
if (counter != lastCount) ok = -1;
|
||||
Thread::yield();
|
||||
}
|
||||
lock.unlock();
|
||||
while (!lock.tryWriteLock()) Thread::yield();
|
||||
for (int k = 0; k < 100; ++k)
|
||||
{
|
||||
counter = 0;
|
||||
fs.seekg(0, std::ios::beg);
|
||||
fs.read((char *)&counter, sizeof(counter));
|
||||
--counter;
|
||||
fs.seekp(0, std::ios::beg);
|
||||
fs.write((char *)&counter, sizeof(counter));
|
||||
fs.flushToDisk();
|
||||
Thread::yield();
|
||||
}
|
||||
for (int k = 0; k < 100; ++k)
|
||||
{
|
||||
fs.seekg(0, std::ios::beg);
|
||||
fs.read((char *)&counter, sizeof(counter));
|
||||
++counter;
|
||||
fs.seekp(0, std::ios::beg);
|
||||
fs.write((char *)&counter, sizeof(counter));
|
||||
fs.flushToDisk();
|
||||
Thread::yield();
|
||||
}
|
||||
fs.seekg(0, std::ios::beg);
|
||||
fs.read((char *)&counter, sizeof(counter));
|
||||
++counter;
|
||||
fs.seekp(0, std::ios::beg);
|
||||
fs.write((char *)&counter, sizeof(counter));
|
||||
fs.flushToDisk();
|
||||
if (counter <= lastCount) ok = -1;
|
||||
lock.unlock();
|
||||
}
|
||||
return ok * counter;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return argc - 1;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user