summaryrefslogtreecommitdiff
path: root/library/dir_lock.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'library/dir_lock.cpp')
-rw-r--r--library/dir_lock.cpp70
1 files changed, 37 insertions, 33 deletions
diff --git a/library/dir_lock.cpp b/library/dir_lock.cpp
index f4ed8e07..3d443b11 100644
--- a/library/dir_lock.cpp
+++ b/library/dir_lock.cpp
@@ -17,6 +17,7 @@
#include "../shared/serialize.h"
#include <boost/cstdint.hpp>
#include "../shared/build_info.h"
+#include <wx/log.h>
#ifdef FFS_WIN
#include <tlhelp32.h>
@@ -40,6 +41,9 @@ const size_t EMIT_LIFE_SIGN_INTERVAL = 5000; //show life sign; unit [ms]
const size_t POLL_LIFE_SIGN_INTERVAL = 6000; //poll for life sign; unit [ms]
const size_t DETECT_EXITUS_INTERVAL = 30000; //assume abandoned lock; unit [ms]
+const char LOCK_FORMAT_DESCR[] = "FreeFileSync";
+const int LOCK_FORMAT_VER = 1; //lock file format version
+
typedef Zbase<Zchar, StorageDeepCopy> BasicString; //thread safe string class
}
@@ -72,7 +76,7 @@ public:
}
catch (const std::exception& e) //exceptions must be catched per thread
{
- wxMessageBox(wxString::FromAscii(e.what()), wxString(_("An exception occurred!")) + wxT("(Dirlock)"), wxOK | wxICON_ERROR);
+ wxSafeShowMessage(wxString(_("An exception occurred!")) + wxT("(Dirlock)"), wxString::FromAscii(e.what())); //simple wxMessageBox won't do for threads
}
}
@@ -130,18 +134,6 @@ private:
namespace
{
-bool somethingExists(const Zstring& objname) //throw() check whether any object with this name exists
-{
-#ifdef FFS_WIN
- return ::GetFileAttributes(applyLongPathPrefix(objname).c_str()) != INVALID_FILE_ATTRIBUTES;
-
-#elif defined FFS_LINUX
- struct stat fileInfo;
- return ::lstat(objname.c_str(), &fileInfo) == 0;
-#endif
-}
-
-
void deleteLockFile(const Zstring& filename) //throw (FileError)
{
#ifdef FFS_WIN
@@ -207,24 +199,25 @@ Zstring deleteAbandonedLockName(const Zstring& lockfilename)
namespace
{
+//read string from file stream
inline
-std::string readString(wxInputStream& stream) //read string from file stream
+std::string readString(wxInputStream& stream) //throw (std::exception)
{
const boost::uint32_t strLength = util::readNumber<boost::uint32_t>(stream);
std::string output;
- if (strLength > 0)
- {
- output.resize(strLength);
- stream.Read(&output[0], strLength);
- }
+ if (strLength > 0)
+ {
+ output.resize(strLength); //may throw for corrupted data
+ stream.Read(&output[0], strLength);
+ }
return output;
}
inline
void writeString(wxOutputStream& stream, const std::string& str) //write string to filestream
-{
- const boost::uint32_t strLength = static_cast<boost::uint32_t>(str.length());
+{
+ const boost::uint32_t strLength = static_cast<boost::uint32_t>(str.length());
util::writeNumber<boost::uint32_t>(stream, strLength);
stream.Write(str.c_str(), strLength);
}
@@ -246,6 +239,7 @@ struct LockInformation
{
LockInformation()
{
+ lockId = util::generateGUID();
#ifdef FFS_WIN
procDescr.processId = ::GetCurrentProcessId();
#elif defined FFS_LINUX
@@ -254,9 +248,16 @@ struct LockInformation
procDescr.computerId = getComputerId();
}
- LockInformation(wxInputStream& stream) : //read
- lockId(util::UniqueId(stream))
+ LockInformation(wxInputStream& stream) //read
{
+ char formatDescr[sizeof(LOCK_FORMAT_DESCR)] = {};
+ stream.Read(formatDescr, sizeof(LOCK_FORMAT_DESCR)); //file format header
+ const int lockFileVersion = util::readNumber<boost::int32_t>(stream); //
+ (void)lockFileVersion;
+
+ //some format checking here?
+
+ lockId = readString(stream);
procDescr.processId = static_cast<ProcessId>(util::readNumber<boost::uint64_t>(stream)); //possible loss of precision (32/64 bit process) covered by buildId
procDescr.computerId = readString(stream);
}
@@ -265,7 +266,10 @@ struct LockInformation
{
assert_static(sizeof(ProcessId) <= sizeof(boost::uint64_t)); //ensure portability
- lockId.toStream(stream);
+ stream.Write(LOCK_FORMAT_DESCR, sizeof(LOCK_FORMAT_DESCR));
+ util::writeNumber<boost::int32_t>(stream, LOCK_FORMAT_VER);
+
+ writeString(stream, lockId);
util::writeNumber<boost::uint64_t>(stream, procDescr.processId);
writeString(stream, procDescr.computerId);
}
@@ -276,7 +280,7 @@ struct LockInformation
typedef pid_t ProcessId;
#endif
- util::UniqueId lockId; //16 byte portable construct
+ std::string lockId; //16 byte UUID
struct ProcessDescription
{
@@ -314,7 +318,6 @@ ProcessStatus getProcessStatus(const LockInformation::ProcessDescription& procDe
if (!::Process32First(snapshot, //__in HANDLE hSnapshot,
&processEntry)) //__inout LPPROCESSENTRY32 lppe
return PROC_STATUS_NO_IDEA;
-
do
{
if (processEntry.th32ProcessID == procDescr.processId)
@@ -335,7 +338,7 @@ ProcessStatus getProcessStatus(const LockInformation::ProcessDescription& procDe
void writeLockInfo(const Zstring& lockfilename) //throw (FileError)
{
- //write GUID at the beginning of the file: this ID is a universal identifier for this lock (no matter what the path is, considering symlinks ,etc.)
+ //write GUID at the beginning of the file: this ID is a universal identifier for this lock (no matter what the path is, considering symlinks, distributed network, etc.)
FileOutputStream lockFile(lockfilename); //throw FileError()
LockInformation().toStream(lockFile);
}
@@ -349,7 +352,7 @@ LockInformation retrieveLockInfo(const Zstring& lockfilename) //throw (FileError
}
-util::UniqueId retrieveLockId(const Zstring& lockfilename) //throw (FileError, ErrorNotExisting)
+std::string retrieveLockId(const Zstring& lockfilename) //throw (FileError, ErrorNotExisting)
{
return retrieveLockInfo(lockfilename).lockId;
}
@@ -541,7 +544,7 @@ public:
try //actual check based on lock UUID, deadlock prevention: "lockfilename" may be an alternative name for an already active lock
{
- const util::UniqueId lockId = retrieveLockId(lockfilename); //throw (FileError, ErrorNotExisting)
+ const std::string lockId = retrieveLockId(lockfilename); //throw (FileError, ErrorNotExisting)
const boost::shared_ptr<SharedDirLock>& activeLock = findActive(lockId); //returns null-lock if not found
if (activeLock)
@@ -554,7 +557,7 @@ public:
//not yet in buffer, so create a new directory lock
boost::shared_ptr<SharedDirLock> newLock(new SharedDirLock(lockfilename, callback)); //throw (FileError)
- const util::UniqueId newLockId = retrieveLockId(lockfilename); //throw (FileError, ErrorNotExisting)
+ const std::string newLockId = retrieveLockId(lockfilename); //throw (FileError, ErrorNotExisting)
//update registry
fileToUuid[lockfilename] = newLockId; //throw()
@@ -566,7 +569,7 @@ public:
private:
LockAdmin() {}
- boost::shared_ptr<SharedDirLock> findActive(const util::UniqueId& lockId) //returns null-lock if not found
+ boost::shared_ptr<SharedDirLock> findActive(const std::string& lockId) //returns null-lock if not found
{
UuidToLockMap::const_iterator iterLock = uuidToLock.find(lockId);
return iterLock != uuidToLock.end() ?
@@ -576,8 +579,9 @@ private:
typedef boost::weak_ptr<SharedDirLock> SharedLock;
- typedef std::map<Zstring, util::UniqueId, LessFilename> FileToUuidMap; //n:1 handle uppper/lower case correctly
- typedef std::map<util::UniqueId, SharedLock> UuidToLockMap; //1:1
+ typedef std::string UniqueId;
+ typedef std::map<Zstring, UniqueId, LessFilename> FileToUuidMap; //n:1 handle uppper/lower case correctly
+ typedef std::map<UniqueId, SharedLock> UuidToLockMap; //1:1
FileToUuidMap fileToUuid; //lockname |-> UUID; locks can be referenced by a lockfilename or alternatively a UUID
UuidToLockMap uuidToLock; //UUID |-> "shared lock ownership"
bgstack15