summaryrefslogtreecommitdiff
path: root/cpp
diff options
context:
space:
mode:
authorJose <jose@zeroc.com>2009-12-04 06:51:23 +0100
committerJose <jose@zeroc.com>2009-12-04 06:51:23 +0100
commit0ad40835182795b5f9bedeea10aeb6f07c666e7d (patch)
tree5dff55b02aefb5854a972eb2cef128d1537d5c47 /cpp
parentBug 4408 - plugin does not work with x64 only installation (diff)
downloadice-0ad40835182795b5f9bedeea10aeb6f07c666e7d.tar.bz2
ice-0ad40835182795b5f9bedeea10aeb6f07c666e7d.tar.xz
ice-0ad40835182795b5f9bedeea10aeb6f07c666e7d.zip
4089 - IceGrid database corruption.
Diffstat (limited to 'cpp')
-rwxr-xr-xcpp/allTests.py3
-rw-r--r--cpp/include/IceUtil/Exception.h21
-rw-r--r--cpp/include/IceUtil/FileUtil.h40
-rw-r--r--cpp/src/Freeze/SharedDbEnv.cpp16
-rw-r--r--cpp/src/Freeze/SharedDbEnv.h2
-rw-r--r--cpp/src/IceDB/SqlTypes.cpp8
-rw-r--r--cpp/src/IceDB/SqlTypes.h5
-rw-r--r--cpp/src/IceUtil/Exception.cpp49
-rw-r--r--cpp/src/IceUtil/FileUtil.cpp92
-rw-r--r--cpp/test/Freeze/Makefile2
-rw-r--r--cpp/test/Freeze/Makefile.mak3
-rw-r--r--cpp/test/Freeze/fileLock/.depend1
-rw-r--r--cpp/test/Freeze/fileLock/.gitignore6
-rw-r--r--cpp/test/Freeze/fileLock/Client.cpp91
-rw-r--r--cpp/test/Freeze/fileLock/ClientFail.cpp80
-rw-r--r--cpp/test/Freeze/fileLock/Makefile41
-rw-r--r--cpp/test/Freeze/fileLock/Makefile.mak44
-rw-r--r--cpp/test/Freeze/fileLock/db/.gitignore0
-rwxr-xr-xcpp/test/Freeze/fileLock/run.py45
-rw-r--r--cpp/test/IceGrid/fileLock/.gitignore1
-rw-r--r--cpp/test/IceGrid/fileLock/db/.gitignore0
-rwxr-xr-xcpp/test/IceGrid/fileLock/run.py61
-rw-r--r--cpp/test/IceUtil/Makefile3
-rw-r--r--cpp/test/IceUtil/Makefile.mak3
-rw-r--r--cpp/test/IceUtil/fileLock/.depend1
-rw-r--r--cpp/test/IceUtil/fileLock/.gitignore6
-rw-r--r--cpp/test/IceUtil/fileLock/Client.cpp47
-rw-r--r--cpp/test/IceUtil/fileLock/ClientFail.cpp57
-rw-r--r--cpp/test/IceUtil/fileLock/Makefile38
-rw-r--r--cpp/test/IceUtil/fileLock/Makefile.mak43
-rwxr-xr-xcpp/test/IceUtil/fileLock/run.py55
31 files changed, 851 insertions, 13 deletions
diff --git a/cpp/allTests.py b/cpp/allTests.py
index 9a663154e90..ac7b4a71d6d 100755
--- a/cpp/allTests.py
+++ b/cpp/allTests.py
@@ -31,6 +31,7 @@ tests = [
("IceUtil/inputUtil", ["once"]),
("IceUtil/uuid", ["once", "noappverifier"]), # This test is very slow with appverifier.
("IceUtil/timer", ["once"]),
+ ("IceUtil/fileLock", ["once"]),
("Slice/errorDetection", ["once"]),
("Slice/keyword", ["once"]),
("Ice/proxy", ["core"]),
@@ -67,6 +68,7 @@ tests = [
("Freeze/dbmap", ["once", "novc6"]),
("Freeze/complex", ["once", "novc6"]),
("Freeze/evictor", ["core", "novc6"]),
+ ("Freeze/fileLock", ["core", "novc6"]),
("IceStorm/single", ["service", "novc6", "noappverifier"]), # This test doensn't work with appverifier is sensitive to timeouts.
("IceStorm/federation", ["service", "novc6"]),
("IceStorm/federation2", ["service", "novc6"]),
@@ -77,6 +79,7 @@ tests = [
("FreezeScript/dbmap", ["once", "novc6"]),
("FreezeScript/evictor", ["once", "novc6"]),
("IceGrid/simple", ["service", "novc6"]),
+ ("IceGrid/fileLock", ["service", "nobcc", "novc6"]),
("IceGrid/deployer", ["service", "nobcc", "novc6"]),
("IceGrid/session", ["service", "nobcc", "novc6"]),
("IceGrid/update", ["service", "nobcc", "novc6"]),
diff --git a/cpp/include/IceUtil/Exception.h b/cpp/include/IceUtil/Exception.h
index e545594c608..afd59ed48e7 100644
--- a/cpp/include/IceUtil/Exception.h
+++ b/cpp/include/IceUtil/Exception.h
@@ -98,6 +98,27 @@ private:
static const char* _name;
};
+class ICE_UTIL_API FileLockException : public Exception
+{
+public:
+
+ FileLockException(const char*, int, int, const std::string&);
+ virtual ~FileLockException() throw();
+ virtual std::string ice_name() const;
+ virtual void ice_print(std::ostream&) const;
+ virtual Exception* ice_clone() const;
+ virtual void ice_throw() const;
+
+ std::string path() const;
+ int error() const;
+
+private:
+
+ const int _error;
+ static const char* _name;
+ std::string _path;
+};
+
}
#endif
diff --git a/cpp/include/IceUtil/FileUtil.h b/cpp/include/IceUtil/FileUtil.h
index 791985dcb39..3928f5ba413 100644
--- a/cpp/include/IceUtil/FileUtil.h
+++ b/cpp/include/IceUtil/FileUtil.h
@@ -11,6 +11,9 @@
#define ICE_FILE_UTIL_H
#include <IceUtil/Config.h>
+#include <IceUtil/Shared.h>
+#include <IceUtil/Handle.h>
+
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
@@ -72,6 +75,40 @@ ICE_UTIL_API int getcwd(std::string&);
ICE_UTIL_API int unlink(const std::string&);
ICE_UTIL_API int close(int);
+//
+// This class is used to implement process file locking. This class
+// is not intended to do file locking within the same process.
+//
+class ICE_UTIL_API FileLock : public IceUtil::Shared, public IceUtil::noncopyable
+{
+public:
+ //
+ // The constructor opens the given file (eventually creating it)
+ // and acquires a lock on the file or throws FileLockException if
+ // the file couldn't be locked.
+ //
+ // If the lock can be acquired, the process pid is written to the
+ // file.
+ //
+ FileLock(const std::string&);
+
+ //
+ // The destructor releases the lock and removes the file.
+ //
+ virtual ~FileLock();
+
+private:
+
+#ifdef _WIN32
+ HANDLE _fd;
+#else
+ int _fd;
+#endif
+ std::string _path;
+};
+
+typedef IceUtil::Handle<FileLock> FileLockPtr;
+
class ICE_UTIL_API ifstream : public std::ifstream
{
public:
@@ -118,6 +155,5 @@ private:
#endif
};
-};
-
+}
#endif
diff --git a/cpp/src/Freeze/SharedDbEnv.cpp b/cpp/src/Freeze/SharedDbEnv.cpp
index 764662d9386..5156b52aa00 100644
--- a/cpp/src/Freeze/SharedDbEnv.cpp
+++ b/cpp/src/Freeze/SharedDbEnv.cpp
@@ -482,6 +482,14 @@ Freeze::SharedDbEnv::SharedDbEnv(const std::string& envName,
}
#endif
+ string propertyPrefix = string("Freeze.DbEnv.") + envName;
+ string dbHome = properties->getPropertyWithDefault(propertyPrefix + ".DbHome", envName);
+
+ //
+ // File lock to prevent multiple process open the same db env.
+ //
+ _fileLock = new ::IceUtilInternal::FileLock(dbHome + "/Freeze.lock");
+
_trace = properties->getPropertyAsInt("Freeze.Trace.DbEnv");
try
@@ -497,11 +505,8 @@ Freeze::SharedDbEnv::SharedDbEnv(const std::string& envName,
out << "opening database environment \"" << envName << "\"";
}
- string propertyPrefix = string("Freeze.DbEnv.") + envName;
-
-
_env->set_errpfx(reinterpret_cast<char*>(this));
-
+
_env->set_errcall(dbErrCallback);
#ifdef _WIN32
@@ -552,9 +557,6 @@ Freeze::SharedDbEnv::SharedDbEnv(const std::string& envName,
// Threading
//
flags |= DB_THREAD;
-
- string dbHome = properties->getPropertyWithDefault(
- propertyPrefix + ".DbHome", envName);
_env->open(Ice::nativeToUTF8(_communicator, dbHome).c_str(), flags, FREEZE_DB_MODE);
diff --git a/cpp/src/Freeze/SharedDbEnv.h b/cpp/src/Freeze/SharedDbEnv.h
index 9d249bea6b5..573a537a18a 100644
--- a/cpp/src/Freeze/SharedDbEnv.h
+++ b/cpp/src/Freeze/SharedDbEnv.h
@@ -11,6 +11,7 @@
#define FREEZE_SHARED_DB_ENV_H
#include <Freeze/Map.h>
+#include <IceUtil/FileUtil.h>
#include <Ice/Ice.h>
#include <db_cxx.h>
#include <map>
@@ -96,6 +97,7 @@ private:
SharedDbMap _sharedDbMap;
IceUtil::Mutex _mutex;
+ IceUtilInternal::FileLockPtr _fileLock;
};
inline DbEnv*
diff --git a/cpp/src/IceDB/SqlTypes.cpp b/cpp/src/IceDB/SqlTypes.cpp
index 829e49b0c50..1f288621d7e 100644
--- a/cpp/src/IceDB/SqlTypes.cpp
+++ b/cpp/src/IceDB/SqlTypes.cpp
@@ -170,6 +170,14 @@ DatabaseCache::DatabaseCache(const Ice::CommunicatorPtr& communicator,
bool requiresBlob)
{
Ice::PropertiesPtr properties = communicator->getProperties();
+
+ //
+ // File lock to prevent multiple process open the same db env.
+ //
+ if(type == "QSQLITE")
+ {
+ _fileLock = new IceUtilInternal::FileLock(name + ".lock");
+ }
_connection = QSqlDatabase::addDatabase(type.c_str(), IceUtil::generateUUID().c_str());
_connection.setDatabaseName(name.c_str());
diff --git a/cpp/src/IceDB/SqlTypes.h b/cpp/src/IceDB/SqlTypes.h
index a2b5600e475..b6613f95f35 100644
--- a/cpp/src/IceDB/SqlTypes.h
+++ b/cpp/src/IceDB/SqlTypes.h
@@ -14,6 +14,7 @@
#include <IceUtil/Handle.h>
#include <IceUtil/Thread.h>
+#include <IceUtil/FileUtil.h>
#include <Ice/CommunicatorF.h>
#include <Ice/Initialize.h> // For ThreadHook
@@ -122,6 +123,10 @@ protected:
QSqlDatabase _connection;
ThreadDatabaseMap _cache;
+
+private:
+
+ IceUtilInternal::FileLockPtr _fileLock;
};
typedef IceUtil::Handle<DatabaseCache> DatabaseCachePtr;
diff --git a/cpp/src/IceUtil/Exception.cpp b/cpp/src/IceUtil/Exception.cpp
index 6ce81a17c23..7f33bc497a4 100644
--- a/cpp/src/IceUtil/Exception.cpp
+++ b/cpp/src/IceUtil/Exception.cpp
@@ -401,3 +401,52 @@ IceUtil::SyscallException::error() const
{
return _error;
}
+
+
+IceUtil::FileLockException::FileLockException(const char* file, int line, int err, const string& path):
+ Exception(file, line),
+ _error(err),
+ _path(path)
+{
+}
+
+IceUtil::FileLockException::~FileLockException() throw()
+{
+}
+
+const char* IceUtil::FileLockException::_name = "IceUtil::FileLockedException";
+
+string
+IceUtil::FileLockException::ice_name() const
+{
+ return _name;
+}
+
+void
+IceUtil::FileLockException::ice_print(ostream& os) const
+{
+ Exception::ice_print(os);
+ os << ":\ncould not lock file: `" << _path << "'";
+ if(_error != 0)
+ {
+ os << "\nsyscall exception: " << IceUtilInternal::errorToString(_error);
+ }
+}
+
+IceUtil::Exception*
+IceUtil::FileLockException::ice_clone() const
+{
+ return new FileLockException(*this);
+}
+
+void
+IceUtil::FileLockException::ice_throw() const
+{
+ throw *this;
+}
+
+int
+IceUtil::FileLockException::error() const
+{
+ return _error;
+}
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()
{
}
diff --git a/cpp/test/Freeze/Makefile b/cpp/test/Freeze/Makefile
index ad720dc8087..45417cc1e3b 100644
--- a/cpp/test/Freeze/Makefile
+++ b/cpp/test/Freeze/Makefile
@@ -11,7 +11,7 @@ top_srcdir = ../..
include $(top_srcdir)/config/Make.rules
-SUBDIRS = dbmap complex evictor
+SUBDIRS = dbmap complex evictor fileLock
$(EVERYTHING)::
@for subdir in $(SUBDIRS); \
diff --git a/cpp/test/Freeze/Makefile.mak b/cpp/test/Freeze/Makefile.mak
index 23c19c6403f..842f559f9ba 100644
--- a/cpp/test/Freeze/Makefile.mak
+++ b/cpp/test/Freeze/Makefile.mak
@@ -13,7 +13,8 @@ top_srcdir = ..\..
SUBDIRS = dbmap \
complex \
- evictor
+ evictor \
+ fileLock
$(EVERYTHING)::
@for %i in ( $(SUBDIRS) ) do \
diff --git a/cpp/test/Freeze/fileLock/.depend b/cpp/test/Freeze/fileLock/.depend
new file mode 100644
index 00000000000..7ed9c7fce30
--- /dev/null
+++ b/cpp/test/Freeze/fileLock/.depend
@@ -0,0 +1 @@
+Client$(OBJEXT): Client.cpp $(includedir)/IceUtil/IceUtil.h $(includedir)/IceUtil/Config.h $(includedir)/IceUtil/AbstractMutex.h $(includedir)/IceUtil/Lock.h $(includedir)/IceUtil/ThreadException.h $(includedir)/IceUtil/Exception.h $(includedir)/IceUtil/Time.h $(includedir)/IceUtil/Cache.h $(includedir)/IceUtil/Handle.h $(includedir)/IceUtil/Mutex.h $(includedir)/IceUtil/MutexProtocol.h $(includedir)/IceUtil/CountDownLatch.h $(includedir)/IceUtil/Cond.h $(includedir)/IceUtil/CtrlCHandler.h $(includedir)/IceUtil/Functional.h $(includedir)/IceUtil/Monitor.h $(includedir)/IceUtil/MutexPtrLock.h $(includedir)/IceUtil/RWRecMutex.h $(includedir)/IceUtil/Thread.h $(includedir)/IceUtil/Shared.h $(includedir)/IceUtil/RecMutex.h $(includedir)/IceUtil/StaticMutex.h $(includedir)/IceUtil/Timer.h $(includedir)/IceUtil/UUID.h $(includedir)/IceUtil/Unicode.h $(includedir)/Freeze/Freeze.h $(includedir)/Freeze/Initialize.h $(includedir)/Ice/Ice.h $(includedir)/Ice/Initialize.h $(includedir)/Ice/CommunicatorF.h $(includedir)/Ice/LocalObjectF.h $(includedir)/Ice/Handle.h $(includedir)/Ice/Config.h $(includedir)/Ice/ProxyHandle.h $(includedir)/Ice/ProxyF.h $(includedir)/Ice/ObjectF.h $(includedir)/Ice/GCCountMap.h $(includedir)/Ice/GCShared.h $(includedir)/Ice/Exception.h $(includedir)/Ice/LocalObject.h $(includedir)/Ice/UndefSysMacros.h $(includedir)/Ice/PropertiesF.h $(includedir)/Ice/Proxy.h $(includedir)/Ice/ProxyFactoryF.h $(includedir)/Ice/ConnectionIF.h $(includedir)/Ice/RequestHandlerF.h $(includedir)/Ice/EndpointIF.h $(includedir)/Ice/EndpointF.h $(includedir)/Ice/EndpointTypes.h $(includedir)/Ice/ObjectAdapterF.h $(includedir)/Ice/ReferenceF.h $(includedir)/Ice/OutgoingAsyncF.h $(includedir)/Ice/Current.h $(includedir)/Ice/ConnectionF.h $(includedir)/Ice/Identity.h $(includedir)/Ice/StreamF.h $(includedir)/Ice/Object.h $(includedir)/Ice/IncomingAsyncF.h $(includedir)/Ice/InstanceF.h $(includedir)/Ice/LoggerF.h $(includedir)/Ice/StatsF.h $(includedir)/Ice/StringConverter.h $(includedir)/Ice/Plugin.h $(includedir)/Ice/BuiltinSequences.h $(includedir)/Ice/Stream.h $(includedir)/Ice/LocalException.h $(includedir)/Ice/Properties.h $(includedir)/Ice/Outgoing.h $(includedir)/Ice/BasicStream.h $(includedir)/Ice/ObjectFactoryF.h $(includedir)/Ice/Buffer.h $(includedir)/Ice/Protocol.h $(includedir)/Ice/OutgoingAsync.h $(includedir)/Ice/Incoming.h $(includedir)/Ice/ServantLocatorF.h $(includedir)/Ice/ServantManagerF.h $(includedir)/Ice/Direct.h $(includedir)/Ice/Logger.h $(includedir)/Ice/LoggerUtil.h $(includedir)/Ice/Stats.h $(includedir)/Ice/Communicator.h $(includedir)/Ice/RouterF.h $(includedir)/Ice/LocatorF.h $(includedir)/Ice/PluginF.h $(includedir)/Ice/ImplicitContextF.h $(includedir)/Ice/ObjectFactory.h $(includedir)/Ice/ObjectAdapter.h $(includedir)/Ice/FacetMap.h $(includedir)/Ice/Endpoint.h $(includedir)/Ice/ServantLocator.h $(includedir)/Ice/IncomingAsync.h $(includedir)/Ice/Process.h $(includedir)/Ice/Application.h $(includedir)/Ice/Connection.h $(includedir)/Ice/Functional.h $(includedir)/Ice/ImplicitContext.h $(includedir)/Ice/Locator.h $(includedir)/Ice/FactoryTableInit.h $(includedir)/Ice/FactoryTable.h $(includedir)/Ice/UserExceptionFactory.h $(includedir)/Ice/ProcessF.h $(includedir)/Ice/Router.h $(includedir)/Ice/DispatchInterceptor.h $(includedir)/Ice/IconvStringConverter.h $(includedir)/Freeze/EvictorF.h $(includedir)/Freeze/ConnectionF.h $(includedir)/Freeze/Index.h $(includedir)/Freeze/DB.h $(includedir)/Freeze/Transaction.h $(includedir)/Freeze/BackgroundSaveEvictor.h $(includedir)/Freeze/Evictor.h $(includedir)/Freeze/Exception.h $(includedir)/Freeze/TransactionalEvictor.h $(includedir)/Freeze/Map.h $(includedir)/Freeze/Connection.h $(includedir)/Freeze/TransactionHolder.h $(includedir)/Freeze/Catalog.h $(includedir)/Freeze/CatalogData.h ../../include/TestCommon.h
diff --git a/cpp/test/Freeze/fileLock/.gitignore b/cpp/test/Freeze/fileLock/.gitignore
new file mode 100644
index 00000000000..e58e5b6b798
--- /dev/null
+++ b/cpp/test/Freeze/fileLock/.gitignore
@@ -0,0 +1,6 @@
+// Generated by makegitignore.py
+
+// IMPORTANT: Do not edit this file -- any edits made here will be lost!
+client
+clientFail
+db/*
diff --git a/cpp/test/Freeze/fileLock/Client.cpp b/cpp/test/Freeze/fileLock/Client.cpp
new file mode 100644
index 00000000000..4ec7180863b
--- /dev/null
+++ b/cpp/test/Freeze/fileLock/Client.cpp
@@ -0,0 +1,91 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2009 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+#include <IceUtil/IceUtil.h>
+#include <Freeze/Freeze.h>
+#include <TestCommon.h>
+
+using namespace std;
+using namespace Ice;
+using namespace Freeze;
+
+//COMPILERFIX: Borland C++ 2010 doesn't support wmain for console applications.
+#if defined(_WIN32) && !defined(__BCPLUSPLUS__)
+int
+wmain(int argc, wchar_t* argv[])
+
+#else
+
+int
+main(int argc, char* argv[])
+
+#endif
+{
+ int status = EXIT_SUCCESS;
+ Ice::CommunicatorPtr communicator;
+
+ string envName = "db";
+
+ communicator = Ice::initialize(argc, argv);
+ if(argc != 1)
+ {
+#if defined(_WIN32) && !defined(__BCPLUSPLUS__)
+ envName = IceUtil::wstringToString(argv[1]);
+#else
+ envName = argv[1];
+#endif
+ envName += "/db";
+ }
+
+ {
+ Freeze::ConnectionPtr connection;
+ try
+ {
+ connection = Freeze::createConnection(communicator, envName);
+ test(true);
+ }
+ catch(const exception& ex)
+ {
+ cerr << "excetpion:\n" << ex.what() << endl;
+ test(false);
+ }
+ catch(...)
+ {
+ test(false);
+ }
+
+ cout << "File lock acquired.\n"
+ << "Enter some input and press enter, to release the lock and terminate the program." << endl;
+ //
+ // Block the test waiting for IO, so the file lock is preserved.
+ //
+ string foo;
+ cin >> foo;
+
+ //
+ // Clean up.
+ //
+ if(connection)
+ {
+ connection->close();
+ }
+ }
+ cout << "File lock released." << endl;
+
+ try
+ {
+ communicator->destroy();
+ }
+ catch(const Ice::Exception& ex)
+ {
+ cerr << ex << endl;
+ status = EXIT_FAILURE;
+ }
+ return status;
+}
diff --git a/cpp/test/Freeze/fileLock/ClientFail.cpp b/cpp/test/Freeze/fileLock/ClientFail.cpp
new file mode 100644
index 00000000000..caeefff91f6
--- /dev/null
+++ b/cpp/test/Freeze/fileLock/ClientFail.cpp
@@ -0,0 +1,80 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2009 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+#include <IceUtil/IceUtil.h>
+#include <Freeze/Freeze.h>
+#include <TestCommon.h>
+
+using namespace std;
+using namespace Ice;
+using namespace Freeze;
+
+//COMPILERFIX: Borland C++ 2010 doesn't support wmain for console applications.
+#if defined(_WIN32) && !defined(__BCPLUSPLUS__)
+int
+wmain(int argc, wchar_t* argv[])
+
+#else
+
+int
+main(int argc, char* argv[])
+
+#endif
+{
+ int status = EXIT_SUCCESS;
+ Ice::CommunicatorPtr communicator;
+
+ string envName = "db";
+
+ communicator = Ice::initialize(argc, argv);
+ if(argc != 1)
+ {
+#if defined(_WIN32) && !defined(__BCPLUSPLUS__)
+ envName = IceUtil::wstringToString(argv[1]);
+#else
+ envName = argv[1];
+#endif
+ envName += "/db";
+ }
+
+ {
+ Freeze::ConnectionPtr connection;
+ try
+ {
+ connection = Freeze::createConnection(communicator, envName);
+ test(false);
+ }
+ catch(const IceUtil::FileLockException&)
+ {
+ cout << "File lock not acquired." << endl;
+ test(true);
+ }
+ catch(const exception& ex)
+ {
+ cerr << "excetpion:\n" << ex.what() << endl;
+ test(false);
+ }
+ catch(...)
+ {
+ test(false);
+ }
+ }
+
+ try
+ {
+ communicator->destroy();
+ }
+ catch(const Ice::Exception& ex)
+ {
+ cerr << ex << endl;
+ status = EXIT_FAILURE;
+ }
+
+ return status;
+}
diff --git a/cpp/test/Freeze/fileLock/Makefile b/cpp/test/Freeze/fileLock/Makefile
new file mode 100644
index 00000000000..d0b4e282dbc
--- /dev/null
+++ b/cpp/test/Freeze/fileLock/Makefile
@@ -0,0 +1,41 @@
+# **********************************************************************
+#
+# Copyright (c) 2003-2009 ZeroC, Inc. All rights reserved.
+#
+# This copy of Ice is licensed to you under the terms described in the
+# ICE_LICENSE file included in this distribution.
+#
+# **********************************************************************
+
+top_srcdir = ../../..
+
+CLIENT = client
+CLIENTF = clientFail
+
+TARGETS = $(CLIENT) $(CLIENTF)
+
+OBJS = Client.o
+
+OBJFS = ClientFail.o
+
+SRCS = $(OBJS:.o=.cpp)
+
+GENPIC = no
+
+include $(top_srcdir)/config/Make.rules
+
+CPPFLAGS := -I. -I../../include $(CPPFLAGS)
+
+$(CLIENT): $(OBJS)
+ rm -f $@
+ $(CXX) $(LDFLAGS) -o $@ $(OBJS) $(DB_RPATH_LINK) -lFreeze $(LIBS)
+
+$(CLIENTF): $(OBJFS)
+ rm -f $@
+ $(CXX) $(LDFLAGS) -o $@ $(OBJFS) $(DB_RPATH_LINK) -lFreeze $(LIBS)
+
+
+clean::
+ -rm -f db/*
+
+include .depend
diff --git a/cpp/test/Freeze/fileLock/Makefile.mak b/cpp/test/Freeze/fileLock/Makefile.mak
new file mode 100644
index 00000000000..19c4a16c85c
--- /dev/null
+++ b/cpp/test/Freeze/fileLock/Makefile.mak
@@ -0,0 +1,44 @@
+# **********************************************************************
+#
+# Copyright (c) 2003-2009 ZeroC, Inc. All rights reserved.
+#
+# This copy of Ice is licensed to you under the terms described in the
+# ICE_LICENSE file included in this distribution.
+#
+# **********************************************************************
+
+top_srcdir = ..\..\..
+
+CLIENT = client.exe
+CLIENTF = clientFail.exe
+TARGETS = $(CLIENT) $(CLIENTF)
+
+OBJS = Client.obj
+
+OBJFS = ClientFail.obj
+
+SRCS = $(OBJS:.obj=.cpp)
+
+!include $(top_srcdir)\config\Make.rules.mak
+
+CPPFLAGS = -I. -I..\..\include $(CPPFLAGS) -DWIN32_LEAN_AND_MEAN
+
+!if "$(GENERATE_PDB)" == "yes"
+CPDBFLAGS = /pdb:$(CLIENT:.exe=.pdb)
+!endif
+
+$(CLIENT): $(OBJS)
+ $(LINK) $(LD_EXEFLAGS) $(PDBFLAGS) $(SETARGV) $(OBJS) $(PREOUT)$@ $(PRELIBS)$(LIBS) freeze$(LIBSUFFIX).lib
+ @if exist $@.manifest echo ^ ^ ^ Embedding manifest using $(MT) && \
+ $(MT) -nologo -manifest $@.manifest -outputresource:$@;#1 && del /q $@.manifest
+
+$(CLIENTF): $(OBJFS)
+ $(LINK) $(LD_EXEFLAGS) $(PDBFLAGS) $(SETARGV) $(OBJFS) $(PREOUT)$@ $(PRELIBS)$(LIBS) freeze$(LIBSUFFIX).lib
+ @if exist $@.manifest echo ^ ^ ^ Embedding manifest using $(MT) && \
+ $(MT) -nologo -manifest $@.manifest -outputresource:$@;#1 && del /q $@.manifest
+
+
+clean::
+ del /q db/*
+
+!include .depend
diff --git a/cpp/test/Freeze/fileLock/db/.gitignore b/cpp/test/Freeze/fileLock/db/.gitignore
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/cpp/test/Freeze/fileLock/db/.gitignore
diff --git a/cpp/test/Freeze/fileLock/run.py b/cpp/test/Freeze/fileLock/run.py
new file mode 100755
index 00000000000..a01c758ea11
--- /dev/null
+++ b/cpp/test/Freeze/fileLock/run.py
@@ -0,0 +1,45 @@
+#!/usr/bin/env python
+# **********************************************************************
+#
+# Copyright (c) 2003-2009 ZeroC, Inc. All rights reserved.
+#
+# This copy of Ice is licensed to you under the terms described in the
+# ICE_LICENSE file included in this distribution.
+#
+# **********************************************************************
+
+import os, sys
+
+path = [ ".", "..", "../..", "../../..", "../../../.." ]
+head = os.path.dirname(sys.argv[0])
+if len(head) > 0:
+ path = [os.path.join(head, p) for p in path]
+path = [os.path.abspath(p) for p in path if os.path.exists(os.path.join(p, "scripts", "TestUtil.py")) ]
+if len(path) == 0:
+ raise "can't find toplevel directory!"
+sys.path.append(os.path.join(path[0]))
+from scripts import *
+
+print "testing Freeze file lock...",
+sys.stdout.flush()
+
+client = os.path.join(os.getcwd(), "client")
+
+clientExe = TestUtil.startClient(client, "", None, None, False)
+clientExe.expect('File lock acquired.\.*')
+
+clientFail = os.path.join(os.getcwd(), "clientFail")
+clientFailExe = TestUtil.startClient(clientFail, "", None, None, False)
+clientFailExe.expect('File lock not acquired')
+
+# send some output to client to terminate it.
+clientExe.sendline('go')
+clientExe.expect('File lock released.')
+
+# The lock is gone try to acquire it again.
+clientExe = TestUtil.startClient(client, "", None, None, False)
+clientExe.expect('File lock acquired.\.*')
+clientExe.sendline('go')
+clientExe.expect('File lock released.')
+
+print "ok" \ No newline at end of file
diff --git a/cpp/test/IceGrid/fileLock/.gitignore b/cpp/test/IceGrid/fileLock/.gitignore
new file mode 100644
index 00000000000..65eef93d691
--- /dev/null
+++ b/cpp/test/IceGrid/fileLock/.gitignore
@@ -0,0 +1 @@
+db
diff --git a/cpp/test/IceGrid/fileLock/db/.gitignore b/cpp/test/IceGrid/fileLock/db/.gitignore
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/cpp/test/IceGrid/fileLock/db/.gitignore
diff --git a/cpp/test/IceGrid/fileLock/run.py b/cpp/test/IceGrid/fileLock/run.py
new file mode 100755
index 00000000000..b580890bce1
--- /dev/null
+++ b/cpp/test/IceGrid/fileLock/run.py
@@ -0,0 +1,61 @@
+#!/usr/bin/env python
+# **********************************************************************
+#
+# Copyright (c) 2003-2009 ZeroC, Inc. All rights reserved.
+#
+# This copy of Ice is licensed to you under the terms described in the
+# ICE_LICENSE file included in this distribution.
+#
+# **********************************************************************
+
+import os, sys
+
+path = [ ".", "..", "../..", "../../..", "../../../.." ]
+head = os.path.dirname(sys.argv[0])
+if len(head) > 0:
+ path = [os.path.join(head, p) for p in path]
+path = [os.path.abspath(p) for p in path if os.path.exists(os.path.join(p, "scripts", "TestUtil.py")) ]
+if len(path) == 0:
+ raise "can't find toplevel directory!"
+sys.path.append(os.path.join(path[0]))
+from scripts import *
+
+def runIceGridRegistry(testdir):
+ iceGrid = ""
+ if TestUtil.isBCC2010() or TestUtil.isVC6():
+ iceGrid = os.path.join(TestUtil.getServiceDir(), "icegridregistry")
+ else:
+ iceGrid = os.path.join(TestUtil.getCppBinDir(), "icegridregistry")
+
+ command = ' --nowarn ' + IceGridAdmin.registryOptions
+
+ name = "registry"
+
+ dataDir = os.path.join(testdir, "db", name)
+ if not os.path.exists(dataDir):
+ os.mkdir(dataDir)
+
+ cmd = command + ' ' + TestUtil.getQtSqlOptions('IceGrid') + \
+ r' --Ice.ProgramName=' + name + \
+ r' --IceGrid.Registry.Client.Endpoints="default -p ' + str(IceGridAdmin.iceGridPort) + '" ' + \
+ r' --IceGrid.Registry.Data=' + dataDir
+
+ driverConfig = TestUtil.DriverConfig("server")
+ driverConfig.lang = "cpp"
+
+ cmd = TestUtil.getCommandLine(iceGrid, driverConfig) + ' ' + cmd
+ proc = TestUtil.spawn(cmd)
+ return proc
+
+IceGridAdmin.cleanDbDir("./db/registry")
+
+print "testing IceGrid file lock...",
+iceGrid1 = runIceGridRegistry(".")
+iceGrid1.expect("[^\n]+ ready\n")
+
+iceGrid2 = runIceGridRegistry(".")
+iceGrid2.expect(".*IceUtil::FileLockedException.*")
+print "ok"
+
+IceGridAdmin.iceGridAdmin("registry shutdown")
+IceGridAdmin.cleanDbDir("./db/registry")
diff --git a/cpp/test/IceUtil/Makefile b/cpp/test/IceUtil/Makefile
index ca30b95fc00..45e93399373 100644
--- a/cpp/test/IceUtil/Makefile
+++ b/cpp/test/IceUtil/Makefile
@@ -18,7 +18,8 @@ SUBDIRS = condvar \
uuid \
ctrlCHandler \
timer \
- priority
+ priority \
+ fileLock
$(EVERYTHING)::
@for subdir in $(SUBDIRS); \
diff --git a/cpp/test/IceUtil/Makefile.mak b/cpp/test/IceUtil/Makefile.mak
index b7363ea211a..78956cbf380 100644
--- a/cpp/test/IceUtil/Makefile.mak
+++ b/cpp/test/IceUtil/Makefile.mak
@@ -18,7 +18,8 @@ SUBDIRS = condvar \
uuid \
ctrlCHandler \
timer \
- priority
+ priority \
+ fileLock
$(EVERYTHING)::
@for %i in ( $(SUBDIRS) ) do \
diff --git a/cpp/test/IceUtil/fileLock/.depend b/cpp/test/IceUtil/fileLock/.depend
new file mode 100644
index 00000000000..d7e10d3f336
--- /dev/null
+++ b/cpp/test/IceUtil/fileLock/.depend
@@ -0,0 +1 @@
+Client$(OBJEXT): Client.cpp $(includedir)/IceUtil/FileUtil.h $(includedir)/IceUtil/Config.h $(includedir)/IceUtil/Shared.h $(includedir)/IceUtil/Handle.h $(includedir)/IceUtil/Exception.h ../../include/TestCommon.h
diff --git a/cpp/test/IceUtil/fileLock/.gitignore b/cpp/test/IceUtil/fileLock/.gitignore
new file mode 100644
index 00000000000..9e130277026
--- /dev/null
+++ b/cpp/test/IceUtil/fileLock/.gitignore
@@ -0,0 +1,6 @@
+// Generated by makegitignore.py
+
+// IMPORTANT: Do not edit this file -- any edits made here will be lost!
+client
+clientFail
+run.pid
diff --git a/cpp/test/IceUtil/fileLock/Client.cpp b/cpp/test/IceUtil/fileLock/Client.cpp
new file mode 100644
index 00000000000..025eafd7e5d
--- /dev/null
+++ b/cpp/test/IceUtil/fileLock/Client.cpp
@@ -0,0 +1,47 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2009 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+#include <IceUtil/FileUtil.h>
+#include <IceUtil/Exception.h>
+#include <TestCommon.h>
+
+using namespace IceUtil;
+using namespace std;
+
+int
+main(int argc, char** argv)
+{
+ {
+ IceUtilInternal::FileLockPtr lock;
+ try
+ {
+ lock = new IceUtilInternal::FileLock("file.lock");
+ test(true);
+ }
+ catch(const exception& ex)
+ {
+ cerr << "exception:\n" << ex.what() << endl;
+ test(false);
+ }
+ catch(...)
+ {
+ test(false);
+ }
+
+ cout << "File lock acquired.\n"
+ << "Enter some input and press enter, to release the lock and terminate the program." << endl;
+ //
+ // Block the test waiting for IO, so the file lock is preserved.
+ //
+ string dummy;
+ cin >> dummy;
+ }
+ cout << "File lock released." << endl;
+ return EXIT_SUCCESS;
+}
diff --git a/cpp/test/IceUtil/fileLock/ClientFail.cpp b/cpp/test/IceUtil/fileLock/ClientFail.cpp
new file mode 100644
index 00000000000..6af48475f31
--- /dev/null
+++ b/cpp/test/IceUtil/fileLock/ClientFail.cpp
@@ -0,0 +1,57 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2009 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+#include <IceUtil/FileUtil.h>
+#include <IceUtil/Exception.h>
+#include <TestCommon.h>
+
+using namespace IceUtil;
+using namespace std;
+
+int
+main(int argc, char** argv)
+{
+ IceUtilInternal::FileLockPtr lock;
+ try
+ {
+ lock = new IceUtilInternal::FileLock("file.lock");
+ test(false);
+ }
+ catch(const IceUtil::FileLockException&)
+ {
+ cout << "File lock not acquired." << endl;
+//
+// Try to read the pid of the lock owner from
+// the lock file.
+//
+// In windows we don't write pid to lock files.
+//
+#ifndef _WIN32
+ IceUtilInternal::ifstream is(string("file.lock"));
+ if(!is.good())
+ {
+ test(false);
+ }
+ string pid;
+ is >> pid;
+ test(pid.size() != 0);
+ cout << "Lock owned by: " << pid << endl;
+#endif
+ }
+ catch(const exception& ex)
+ {
+ cerr << "exception:\n" << ex.what() << endl;
+ test(false);
+ }
+ catch(...)
+ {
+ test(false);
+ }
+ return EXIT_SUCCESS;
+}
diff --git a/cpp/test/IceUtil/fileLock/Makefile b/cpp/test/IceUtil/fileLock/Makefile
new file mode 100644
index 00000000000..92c950c4b30
--- /dev/null
+++ b/cpp/test/IceUtil/fileLock/Makefile
@@ -0,0 +1,38 @@
+# **********************************************************************
+#
+# Copyright (c) 2003-2009 ZeroC, Inc. All rights reserved.
+#
+# This copy of Ice is licensed to you under the terms described in the
+# ICE_LICENSE file included in this distribution.
+#
+# **********************************************************************
+
+top_srcdir = ../../..
+
+CLIENT = client
+CLIENTF = clientFail
+
+TARGETS = $(CLIENT) $(CLIENTF)
+
+OBJS = Client.o
+OBJFS = ClientFail.o
+
+SRCS = $(OBJS:.o=.cpp)
+
+include $(top_srcdir)/config/Make.rules
+
+CPPFLAGS := -I. -I../../include $(CPPFLAGS)
+
+$(CLIENT): $(OBJS)
+ rm -f $@
+ $(CXX) $(LDFLAGS) -o $@ $(OBJS) $(BASELIBS)
+
+
+$(CLIENTF): $(OBJFS)
+ rm -f $@
+ $(CXX) $(LDFLAGS) -o $@ $(OBJFS) $(BASELIBS)
+
+clean::
+ -rm -f run.pid
+
+include .depend
diff --git a/cpp/test/IceUtil/fileLock/Makefile.mak b/cpp/test/IceUtil/fileLock/Makefile.mak
new file mode 100644
index 00000000000..3d1fe8e05c3
--- /dev/null
+++ b/cpp/test/IceUtil/fileLock/Makefile.mak
@@ -0,0 +1,43 @@
+# **********************************************************************
+#
+# Copyright (c) 2003-2009 ZeroC, Inc. All rights reserved.
+#
+# This copy of Ice is licensed to you under the terms described in the
+# ICE_LICENSE file included in this distribution.
+#
+# **********************************************************************
+
+top_srcdir = ..\..\..
+
+CLIENT = client.exe
+CLIENTF = clientFail.exe
+
+TARGETS = $(CLIENT) $(CLIENTF)
+
+OBJS = Client.obj
+OBJFS = ClientFail.obj
+
+SRCS = $(OBJS:.obj=.cpp)
+
+!include $(top_srcdir)/config/Make.rules.mak
+
+CPPFLAGS = -I. -I../../include $(CPPFLAGS) -DWIN32_LEAN_AND_MEAN
+
+!if "$(GENERATE_PDB)" == "yes"
+PDBFLAGS = /pdb:$(CLIENT:.exe=.pdb)
+!endif
+
+$(CLIENT): $(OBJS)
+ $(LINK) $(LD_EXEFLAGS) $(PDBFLAGS) $(SETARGV) $(OBJS) $(PREOUT)$@ $(PRELIBS)$(BASELIBS)
+ @if exist $@.manifest echo ^ ^ ^ Embedding manifest using $(MT) && \
+ $(MT) -nologo -manifest $@.manifest -outputresource:$@;#1 && del /q $@.manifest
+
+$(CLIENTF): $(OBJFS)
+ $(LINK) $(LD_EXEFLAGS) $(PDBFLAGS) $(SETARGV) $(OBJFS) $(PREOUT)$@ $(PRELIBS)$(BASELIBS)
+ @if exist $@.manifest echo ^ ^ ^ Embedding manifest using $(MT) && \
+ $(MT) -nologo -manifest $@.manifest -outputresource:$@;#1 && del /q $@.manifest
+
+clean::
+ del /q run.pid
+
+!include .depend \ No newline at end of file
diff --git a/cpp/test/IceUtil/fileLock/run.py b/cpp/test/IceUtil/fileLock/run.py
new file mode 100755
index 00000000000..67cf14acc21
--- /dev/null
+++ b/cpp/test/IceUtil/fileLock/run.py
@@ -0,0 +1,55 @@
+#!/usr/bin/env python
+# **********************************************************************
+#
+# Copyright (c) 2003-2009 ZeroC, Inc. All rights reserved.
+#
+# This copy of Ice is licensed to you under the terms described in the
+# ICE_LICENSE file included in this distribution.
+#
+# **********************************************************************
+
+import os, sys
+
+path = [ ".", "..", "../..", "../../..", "../../../.." ]
+head = os.path.dirname(sys.argv[0])
+if len(head) > 0:
+ path = [os.path.join(head, p) for p in path]
+path = [os.path.abspath(p) for p in path if os.path.exists(os.path.join(p, "scripts", "TestUtil.py")) ]
+if len(path) == 0:
+ raise "can't find toplevel directory!"
+sys.path.append(os.path.join(path[0]))
+from scripts import *
+
+print "testing process file lock...",
+sys.stdout.flush()
+
+client = os.path.join(os.getcwd(), "client")
+clientFail = os.path.join(os.getcwd(), "clientFail")
+
+clientExe = TestUtil.startClient(client, "", None, None, False)
+clientExe.expect('File lock acquired.\.*')
+
+#
+# Ensure that the file lock exists.
+#
+assert(os.path.exists("file.lock"));
+
+clientFailExe = TestUtil.startClient(clientFail, "", None, None, False)
+clientFailExe.expect('File lock not acquired.')
+
+# send some output to client to terminate it.
+clientExe.sendline('go')
+clientExe.expect('File lock released.')
+
+#
+# Ensure that the file lock was removed.
+#
+assert(not os.path.exists("file.lock"));
+
+# The lock is gone try to acquire it again.
+clientExe = TestUtil.startClient(client, "", None, None, False)
+clientExe.expect('File lock acquired.\.*')
+clientExe.sendline('go')
+clientExe.expect('File lock released.')
+
+print "ok" \ No newline at end of file