summaryrefslogtreecommitdiff
path: root/cpp
diff options
context:
space:
mode:
Diffstat (limited to 'cpp')
-rw-r--r--cpp/slice/IceGrid/Observer.ice53
-rw-r--r--cpp/src/IceGrid/Database.cpp3
-rw-r--r--cpp/src/IceGrid/DescriptorHelper.cpp17
-rw-r--r--cpp/src/IceGrid/IceGridRegistry.cpp6
-rw-r--r--cpp/src/IceGrid/NodeI.cpp6
-rw-r--r--cpp/src/IceGrid/ObserverSessionI.cpp96
-rw-r--r--cpp/src/IceGrid/ObserverSessionI.h3
-rw-r--r--cpp/src/IceGrid/Topics.cpp162
-rw-r--r--cpp/src/IceGrid/Topics.h15
-rw-r--r--cpp/test/IceGrid/update/.depend0
-rw-r--r--cpp/test/IceGrid/update/AllTests.cpp507
-rw-r--r--cpp/test/IceGrid/update/Client.cpp55
-rw-r--r--cpp/test/IceGrid/update/Makefile48
-rw-r--r--cpp/test/IceGrid/update/Server.cpp63
-rw-r--r--cpp/test/IceGrid/update/Test.cpp471
-rw-r--r--cpp/test/IceGrid/update/Test.ice25
-rw-r--r--cpp/test/IceGrid/update/TestI.cpp29
-rw-r--r--cpp/test/IceGrid/update/db/.dummy0
-rwxr-xr-xcpp/test/IceGrid/update/run.py58
19 files changed, 1547 insertions, 70 deletions
diff --git a/cpp/slice/IceGrid/Observer.ice b/cpp/slice/IceGrid/Observer.ice
index 99720c26aea..a7f509fcb9a 100644
--- a/cpp/slice/IceGrid/Observer.ice
+++ b/cpp/slice/IceGrid/Observer.ice
@@ -12,6 +12,7 @@
#include <Glacier2/Session.ice>
#include <IceGrid/Descriptor.ice>
+#include <IceGrid/Exception.ice>
module IceGrid
{
@@ -31,9 +32,19 @@ struct AdapterDynamicInfo
};
sequence<AdapterDynamicInfo> AdapterDynamicInfoSeq;
+struct NodeDynamicInfo
+{
+ string name;
+ ServerDynamicInfoSeq servers;
+ AdapterDynamicInfoSeq adapters;
+};
+sequence<NodeDynamicInfo> NodeDynamicInfoSeq;
+
interface NodeObserver
{
- void init(string node, ServerDynamicInfoSeq servers, AdapterDynamicInfoSeq adapters);
+ ["ami"] void init(NodeDynamicInfoSeq nodes);
+
+ void initNode(NodeDynamicInfo node);
void updateServer(string node, ServerDynamicInfo updatedInfo);
@@ -42,7 +53,7 @@ interface NodeObserver
interface RegistryObserver
{
- void init(int serial, ApplicationDescriptorSeq applications, Ice::StringSeq nodesUp);
+ ["ami"] void init(int serial, ApplicationDescriptorSeq applications, Ice::StringSeq nodesUp);
void applicationAdded(int serial, ApplicationDescriptor desc);
void applicationRemoved(int serial, string name);
@@ -133,6 +144,30 @@ interface Session extends Glacier2::Session
/**
*
+ * Add an application. This method must be called to update the
+ * registry applications using the lock mechanism.
+ *
+ * @throws AccessDenied Raised if the session doesn't hold the
+ * exclusive lock.
+ *
+ **/
+ void addApplication(ApplicationDescriptor application)
+ throws AccessDenied, DeploymentException, ApplicationExistsException;
+
+ /**
+ *
+ * Update an application. This method must be called to update the
+ * registry applications using the lock mechanism.
+ *
+ * @throws AccessDenied Raised if the session doesn't hold the
+ * exclusive lock.
+ *
+ **/
+ void syncApplication(ApplicationDescriptor app)
+ throws AccessDenied, DeploymentException, ApplicationNotExistException;
+
+ /**
+ *
* Update an application. This method must be called to update the
* registry applications using the lock mechanism.
*
@@ -141,7 +176,19 @@ interface Session extends Glacier2::Session
*
**/
void updateApplication(ApplicationUpdateDescriptor update)
- throws AccessDenied;
+ throws AccessDenied, DeploymentException, ApplicationNotExistException;
+
+ /**
+ *
+ * Update an application. This method must be called to update the
+ * registry applications using the lock mechanism.
+ *
+ * @throws AccessDenied Raised if the session doesn't hold the
+ * exclusive lock.
+ *
+ **/
+ void removeApplication(string name)
+ throws AccessDenied, ApplicationNotExistException;
/**
*
diff --git a/cpp/src/IceGrid/Database.cpp b/cpp/src/IceGrid/Database.cpp
index b91f4ea8206..39f4a200bde 100644
--- a/cpp/src/IceGrid/Database.cpp
+++ b/cpp/src/IceGrid/Database.cpp
@@ -743,9 +743,6 @@ Database::getServerDescriptor(const std::string& name)
{
ApplicationDescriptorPtr app = getApplicationDescriptor(getServerApplication(name));
- //
- // TODO: Is it really safe to read the application descriptor outside the lock!?
- //
for(ServerInstanceDescriptorSeq::const_iterator p = app->servers.begin(); p != app->servers.end(); ++p)
{
if(p->descriptor->name == name)
diff --git a/cpp/src/IceGrid/DescriptorHelper.cpp b/cpp/src/IceGrid/DescriptorHelper.cpp
index 6366a584fa9..14525b4fcd2 100644
--- a/cpp/src/IceGrid/DescriptorHelper.cpp
+++ b/cpp/src/IceGrid/DescriptorHelper.cpp
@@ -669,9 +669,6 @@ ApplicationDescriptorHelper::update(const ApplicationUpdateDescriptor& update)
newApp->variables.erase(*p);
}
- //
- // TODO: Check if the new templates are valid?
- //
newApp->serverTemplates = newUpdate.serverTemplates;
newApp->serverTemplates.insert(oldApp->serverTemplates.begin(), oldApp->serverTemplates.end());
for(p = newUpdate.removeServerTemplates.begin(); p != newUpdate.removeServerTemplates.end(); ++p)
@@ -679,9 +676,6 @@ ApplicationDescriptorHelper::update(const ApplicationUpdateDescriptor& update)
newApp->serverTemplates.erase(*p);
}
- //
- // TODO: Check if the new templates are valid?
- //
newApp->serviceTemplates = newUpdate.serviceTemplates;
newApp->serviceTemplates.insert(oldApp->serviceTemplates.begin(), oldApp->serviceTemplates.end());
for(p = newUpdate.removeServiceTemplates.begin(); p != newUpdate.removeServiceTemplates.end(); ++p)
@@ -689,9 +683,6 @@ ApplicationDescriptorHelper::update(const ApplicationUpdateDescriptor& update)
newApp->serviceTemplates.erase(*p);
}
- //
- // Update the node descriptors.
- //
newApp->nodes = newUpdate.nodes;
for(NodeDescriptorSeq::const_iterator q = oldApp->nodes.begin(); q != oldApp->nodes.end(); ++q)
{
@@ -721,7 +712,7 @@ ApplicationDescriptorHelper::update(const ApplicationUpdateDescriptor& update)
for_each(newApp->servers.begin(), newApp->servers.end(), AddServerName(updated));
for(ServerInstanceDescriptorSeq::const_iterator q = oldApp->servers.begin(); q != oldApp->servers.end(); ++q)
{
- ServerInstanceDescriptor inst = instantiate(*q); // Re-instantiate old server.
+ ServerInstanceDescriptor inst = instantiate(*q); // Re-instantiate old servers.
if(updated.find(inst.descriptor->name) == updated.end() && remove.find(inst.descriptor->name) == remove.end())
{
if(q->node != inst.node ||
@@ -1123,10 +1114,8 @@ ServerDescriptorHelper::operator==(const ServerDescriptorHelper& helper) const
return false;
}
- if(set<string>(_descriptor->interpreterOptions.begin(),
- _descriptor->interpreterOptions.end()) !=
- set<string>(helper._descriptor->interpreterOptions.begin(),
- helper._descriptor->interpreterOptions.end()))
+ if(set<string>(_descriptor->interpreterOptions.begin(), _descriptor->interpreterOptions.end()) !=
+ set<string>(helper._descriptor->interpreterOptions.begin(), helper._descriptor->interpreterOptions.end()))
{
return false;
}
diff --git a/cpp/src/IceGrid/IceGridRegistry.cpp b/cpp/src/IceGrid/IceGridRegistry.cpp
index c3f4d36f1d0..1e0434daf0e 100644
--- a/cpp/src/IceGrid/IceGridRegistry.cpp
+++ b/cpp/src/IceGrid/IceGridRegistry.cpp
@@ -84,6 +84,12 @@ RegistryService::start(int argc, char* argv[])
return false;
}
+ PropertiesPtr properties = communicator()->getProperties();
+ if(properties->getPropertyAsIntWithDefault("Ice.ThreadPool.Server.Size", 5) <= 5)
+ {
+ properties->setProperty("Ice.ThreadPool.Server.Size", "5");
+ }
+
_registry = new RegistryI(communicator());
if(!_registry->start(nowarn))
{
diff --git a/cpp/src/IceGrid/NodeI.cpp b/cpp/src/IceGrid/NodeI.cpp
index fefcc49ce9c..b5de9dcbbce 100644
--- a/cpp/src/IceGrid/NodeI.cpp
+++ b/cpp/src/IceGrid/NodeI.cpp
@@ -464,7 +464,11 @@ NodeI::initObserver(const Ice::StringSeq& servers)
try
{
- _observer->init(_name, serverInfos, adapterInfos);
+ NodeDynamicInfo info;
+ info.name = _name;
+ info.servers = serverInfos;
+ info.adapters = adapterInfos;
+ _observer->initNode(info);
}
catch(const Ice::LocalException&)
{
diff --git a/cpp/src/IceGrid/ObserverSessionI.cpp b/cpp/src/IceGrid/ObserverSessionI.cpp
index ae4a7c8e977..f2c4e8760a2 100644
--- a/cpp/src/IceGrid/ObserverSessionI.cpp
+++ b/cpp/src/IceGrid/ObserverSessionI.cpp
@@ -73,17 +73,49 @@ ObserverSessionI::setObserversByIdentity(const Ice::Identity& registryObserver,
}
void
-ObserverSessionI::startUpdate(int serial, const Ice::Current&)
+ObserverSessionI::startUpdate(int serial, const Ice::Current& current)
{
Lock sync(*this);
+ if(_destroyed)
+ {
+ Ice::ObjectNotExistException ex(__FILE__, __LINE__);
+ ex.id = current.id;
+ throw ex;
+ }
+
_database->lock(serial, this, _userId);
_updating = true;
}
void
-ObserverSessionI::updateApplication(const ApplicationUpdateDescriptor& update, const Ice::Current&)
+ObserverSessionI::addApplication(const ApplicationDescriptorPtr& app, const Ice::Current& current)
{
Lock sync(*this);
+ if(_destroyed)
+ {
+ Ice::ObjectNotExistException ex(__FILE__, __LINE__);
+ ex.id = current.id;
+ throw ex;
+ }
+
+ if(!_updating)
+ {
+ throw AccessDenied();
+ }
+ _database->addApplicationDescriptor(this, app);
+}
+
+void
+ObserverSessionI::updateApplication(const ApplicationUpdateDescriptor& update, const Ice::Current& current)
+{
+ Lock sync(*this);
+ if(_destroyed)
+ {
+ Ice::ObjectNotExistException ex(__FILE__, __LINE__);
+ ex.id = current.id;
+ throw ex;
+ }
+
if(!_updating)
{
throw AccessDenied();
@@ -92,20 +124,76 @@ ObserverSessionI::updateApplication(const ApplicationUpdateDescriptor& update, c
}
void
-ObserverSessionI::finishUpdate(const Ice::Current&)
+ObserverSessionI::syncApplication(const ApplicationDescriptorPtr& app, const Ice::Current& current)
+{
+ Lock sync(*this);
+ if(_destroyed)
+ {
+ Ice::ObjectNotExistException ex(__FILE__, __LINE__);
+ ex.id = current.id;
+ throw ex;
+ }
+
+ if(!_updating)
+ {
+ throw AccessDenied();
+ }
+ _database->syncApplicationDescriptor(this, app);
+}
+
+void
+ObserverSessionI::removeApplication(const string& name, const Ice::Current& current)
{
Lock sync(*this);
+ if(_destroyed)
+ {
+ Ice::ObjectNotExistException ex(__FILE__, __LINE__);
+ ex.id = current.id;
+ throw ex;
+ }
+
if(!_updating)
{
throw AccessDenied();
}
+ _database->removeApplicationDescriptor(this, name);
+}
+void
+ObserverSessionI::finishUpdate(const Ice::Current& current)
+{
+ Lock sync(*this);
+ if(_destroyed)
+ {
+ Ice::ObjectNotExistException ex(__FILE__, __LINE__);
+ ex.id = current.id;
+ throw ex;
+ }
+
+ if(!_updating)
+ {
+ throw AccessDenied();
+ }
_database->unlock(this);
+ _updating = false;
}
void
-ObserverSessionI::destroy(const Ice::Current&)
+ObserverSessionI::destroy(const Ice::Current& current)
{
+ Lock sync(*this);
+ if(_destroyed)
+ {
+ Ice::ObjectNotExistException ex(__FILE__, __LINE__);
+ ex.id = current.id;
+ throw ex;
+ }
+ if(_updating)
+ {
+ _database->unlock(this);
+ _updating = false;
+ }
+
//
// Unsubscribe from the topics.
//
diff --git a/cpp/src/IceGrid/ObserverSessionI.h b/cpp/src/IceGrid/ObserverSessionI.h
index b8ec32c55bc..7eeab821895 100644
--- a/cpp/src/IceGrid/ObserverSessionI.h
+++ b/cpp/src/IceGrid/ObserverSessionI.h
@@ -32,7 +32,10 @@ public:
virtual void setObserversByIdentity(const Ice::Identity&, const Ice::Identity&, const Ice::Current&);
virtual void startUpdate(int, const Ice::Current&);
+ virtual void addApplication(const ApplicationDescriptorPtr&, const Ice::Current&);
+ virtual void syncApplication(const ApplicationDescriptorPtr&, const Ice::Current&);
virtual void updateApplication(const ApplicationUpdateDescriptor&, const Ice::Current&);
+ virtual void removeApplication(const std::string&, const Ice::Current&);
virtual void finishUpdate(const Ice::Current&);
virtual void destroy(const Ice::Current&);
diff --git a/cpp/src/IceGrid/Topics.cpp b/cpp/src/IceGrid/Topics.cpp
index b92a14de1b4..41427244449 100644
--- a/cpp/src/IceGrid/Topics.cpp
+++ b/cpp/src/IceGrid/Topics.cpp
@@ -14,24 +14,86 @@
using namespace std;
using namespace IceGrid;
+class RegistryInitCB : public AMI_RegistryObserver_init
+{
+public:
+
+ RegistryInitCB(const RegistryObserverTopicPtr& topic, const RegistryObserverPrx& observer, int serial) :
+ _topic(topic),
+ _observer(observer),
+ _serial(serial)
+ {
+ }
+
+ void
+ ice_response()
+ {
+ _topic->subscribe(_observer, _serial);
+ }
+
+ void
+ ice_exception(const Ice::Exception&)
+ {
+ // Ignore
+ }
+
+private:
+
+ const RegistryObserverTopicPtr _topic;
+ const RegistryObserverPrx _observer;
+ const int _serial;
+};
+
+class NodeInitCB : public AMI_NodeObserver_init
+{
+public:
+
+ NodeInitCB(const NodeObserverTopicPtr& topic, const NodeObserverPrx& observer, int serial) :
+ _topic(topic),
+ _observer(observer),
+ _serial(serial)
+ {
+ }
+
+ void
+ ice_response()
+ {
+ _topic->subscribe(_observer, _serial);
+ }
+
+ void
+ ice_exception(const Ice::Exception&)
+ {
+ // Ignore
+ }
+
+private:
+
+ const NodeObserverTopicPtr _topic;
+ const NodeObserverPrx _observer;
+ const int _serial;
+};
+
+
NodeObserverTopic::NodeObserverTopic(const IceStorm::TopicPrx& topic, const NodeObserverPrx& publisher) :
- _topic(topic), _publisher(publisher)
+ _topic(topic), _publisher(publisher), _serial(0)
{
}
void
-NodeObserverTopic::init(const string& node,
- const ServerDynamicInfoSeq& servers,
- const AdapterDynamicInfoSeq& adapters,
- const Ice::Current& current)
+NodeObserverTopic::init(const NodeDynamicInfoSeq&, const Ice::Current&)
+{
+ assert(false);
+}
+
+void
+NodeObserverTopic::initNode(const NodeDynamicInfo& info, const Ice::Current& current)
{
Lock sync(*this);
- _nodes.insert(node);
- _servers[node] = servers;
- _adapters[node] = adapters;
+ _nodes.insert(make_pair(info.name, info));
- _publisher->init(node, servers, adapters);
+ _publisher->initNode(info);
}
void
@@ -40,7 +102,9 @@ NodeObserverTopic::updateServer(const string& node, const ServerDynamicInfo& ser
Lock sync(*this);
assert(_nodes.find(node) != _nodes.end());
- ServerDynamicInfoSeq& servers = _servers[node];
+ ++_serial;
+
+ ServerDynamicInfoSeq& servers = _nodes[node].servers;
ServerDynamicInfoSeq::iterator p = servers.begin();
while(p != servers.end())
{
@@ -65,7 +129,9 @@ NodeObserverTopic::updateAdapter(const string& node, const AdapterDynamicInfo& a
Lock sync(*this);
assert(_nodes.find(node) != _nodes.end());
- AdapterDynamicInfoSeq& adapters = _adapters[node];
+ ++_serial;
+
+ AdapterDynamicInfoSeq& adapters = _nodes[node].adapters;
AdapterDynamicInfoSeq::iterator p = adapters.begin();
while(p != adapters.end())
{
@@ -85,24 +151,34 @@ NodeObserverTopic::updateAdapter(const string& node, const AdapterDynamicInfo& a
}
void
-NodeObserverTopic::subscribe(const NodeObserverPrx& observer)
+NodeObserverTopic::subscribe(const NodeObserverPrx& observer, int serial)
{
- IceStorm::QoS qos;
- qos["reliability"] = "twoway ordered";
-
- Lock sync(*this);
- _topic->subscribe(qos, observer);
- for(set<string>::const_iterator p = _nodes.begin(); p != _nodes.end(); ++p)
+ while(true)
{
- try
+ if(serial == -1)
{
- observer->init(*p, _servers[*p], _adapters[*p]);
+ Lock sync(*this);
+ NodeDynamicInfoSeq nodes;
+ nodes.reserve(_nodes.size());
+ for(map<string, NodeDynamicInfo>::const_iterator p = _nodes.begin(); p != _nodes.end(); ++p)
+ {
+ nodes.push_back(p->second);
+ }
+ observer->init_async(new NodeInitCB(this, observer, _serial), nodes);
+ return;
}
- catch(const Ice::LocalException& ex)
+
+ Lock sync(*this);
+ if(serial != _serial)
{
- cerr << ex << endl;
- break;
+ serial = -1;
+ continue;
}
+
+ IceStorm::QoS qos;
+ qos["reliability"] = "twoway ordered";
+ _topic->subscribe(qos, observer);
+ break;
}
}
@@ -117,11 +193,8 @@ NodeObserverTopic::removeNode(const string& name)
{
Lock sync(*this);
_nodes.erase(name);
- _servers.erase(name);
- _adapters.erase(name);
}
-
RegistryObserverTopic::RegistryObserverTopic(const IceStorm::TopicPrx& topic,
const RegistryObserverPrx& publisher,
NodeObserverTopic& nodeObserver) :
@@ -246,21 +319,34 @@ RegistryObserverTopic::nodeDown(const string& name, const Ice::Current&)
}
void
-RegistryObserverTopic::subscribe(const RegistryObserverPrx& observer)
+RegistryObserverTopic::subscribe(const RegistryObserverPrx& observer, int serial)
{
- IceStorm::QoS qos;
- qos["reliability"] = "twoway ordered";
+ while(true)
+ {
+ if(serial == -1)
+ {
+ Lock sync(*this);
+ assert(_serial != -1);
+ observer->init_async(new RegistryInitCB(this, observer, _serial), _serial, _applications, _nodes);
+ return;
+ }
- Lock sync(*this);
- _topic->subscribe(qos, observer);
+ //
+ // If the registry cache changed since we've send the init()
+ // call we need to do it again. Otherwise, we can subscribe to
+ // the IceStorm topic.
+ //
+ Lock sync(*this);
+ if(serial != _serial)
+ {
+ serial = -1;
+ continue;
+ }
- try
- {
- observer->init(_serial, _applications, _nodes);
- }
- catch(const Ice::LocalException& ex)
- {
- cerr << ex << endl;
+ IceStorm::QoS qos;
+ qos["reliability"] = "twoway ordered";
+ _topic->subscribe(qos, observer);
+ break;
}
}
diff --git a/cpp/src/IceGrid/Topics.h b/cpp/src/IceGrid/Topics.h
index e62cd9d2a1e..f1a57d08292 100644
--- a/cpp/src/IceGrid/Topics.h
+++ b/cpp/src/IceGrid/Topics.h
@@ -25,12 +25,12 @@ public:
NodeObserverTopic(const IceStorm::TopicPrx&, const NodeObserverPrx&);
- virtual void init(const std::string&, const ServerDynamicInfoSeq&, const AdapterDynamicInfoSeq&,
- const Ice::Current&);
+ virtual void init(const NodeDynamicInfoSeq&, const Ice::Current&);
+ virtual void initNode(const NodeDynamicInfo&, const Ice::Current&);
virtual void updateServer(const std::string&, const ServerDynamicInfo&, const Ice::Current&);
virtual void updateAdapter(const std::string&, const AdapterDynamicInfo&, const Ice::Current&);
- void subscribe(const NodeObserverPrx&);
+ void subscribe(const NodeObserverPrx&, int serial = -1);
void unsubscribe(const NodeObserverPrx&);
void removeNode(const std::string&);
@@ -40,10 +40,10 @@ private:
const IceStorm::TopicPrx _topic;
const NodeObserverPrx _publisher;
- std::set<std::string> _nodes;
- std::map<std::string, ServerDynamicInfoSeq> _servers;
- std::map<std::string, AdapterDynamicInfoSeq> _adapters;
+ int _serial;
+ std::map<std::string, NodeDynamicInfo> _nodes;
};
+typedef IceUtil::Handle<NodeObserverTopic> NodeObserverTopicPtr;
class RegistryObserverTopic : public RegistryObserver, public IceUtil::Monitor<IceUtil::Mutex>
{
@@ -60,7 +60,7 @@ public:
virtual void nodeUp(const std::string&, const Ice::Current&);
virtual void nodeDown(const std::string&, const Ice::Current&);
- void subscribe(const RegistryObserverPrx&);
+ void subscribe(const RegistryObserverPrx&, int = -1);
void unsubscribe(const RegistryObserverPrx&);
private:
@@ -75,6 +75,7 @@ private:
ApplicationDescriptorSeq _applications;
Ice::StringSeq _nodes;
};
+typedef IceUtil::Handle<RegistryObserverTopic> RegistryObserverTopicPtr;
};
diff --git a/cpp/test/IceGrid/update/.depend b/cpp/test/IceGrid/update/.depend
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/cpp/test/IceGrid/update/.depend
diff --git a/cpp/test/IceGrid/update/AllTests.cpp b/cpp/test/IceGrid/update/AllTests.cpp
new file mode 100644
index 00000000000..ef29323fd87
--- /dev/null
+++ b/cpp/test/IceGrid/update/AllTests.cpp
@@ -0,0 +1,507 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2005 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/Thread.h>
+#include <Ice/Ice.h>
+#include <IceGrid/Observer.h>
+#include <TestCommon.h>
+#include <Test.h>
+
+using namespace std;
+using namespace Test;
+using namespace IceGrid;
+
+class SessionKeepAliveThread : public IceUtil::Thread, public IceUtil::Monitor<IceUtil::Mutex>
+{
+public:
+
+ SessionKeepAliveThread(const Ice::LoggerPtr& logger, const IceUtil::Time& timeout) :
+ _logger(logger),
+ _timeout(timeout),
+ _terminated(false)
+ {
+ }
+
+ virtual void
+ run()
+ {
+ Lock sync(*this);
+ while(!_terminated)
+ {
+ timedWait(_timeout);
+ if(!_terminated)
+ {
+ vector<SessionPrx>::iterator p = _sessions.begin();
+ while(p != _sessions.end())
+ {
+ try
+ {
+ (*p)->keepAlive();
+ ++p;
+ }
+ catch(const Ice::Exception& ex)
+ {
+ p = _sessions.erase(p);
+ }
+ }
+ }
+ }
+ }
+
+ void
+ add(const SessionPrx& session)
+ {
+ Lock sync(*this);
+ _sessions.push_back(session);
+ }
+
+ void
+ terminate()
+ {
+ Lock sync(*this);
+ _terminated = true;
+ notify();
+ }
+
+private:
+
+ const Ice::LoggerPtr _logger;
+ vector<SessionPrx> _sessions;
+ const IceUtil::Time _timeout;
+ bool _terminated;
+};
+typedef IceUtil::Handle<SessionKeepAliveThread> SessionKeepAliveThreadPtr;
+
+class RegistryObserverI : public RegistryObserver, public IceUtil::Monitor<IceUtil::Mutex>
+{
+public:
+
+ RegistryObserverI() : _updated(false)
+ {
+ }
+
+ virtual void
+ init(int serial, const ApplicationDescriptorSeq& apps, const Ice::StringSeq& nodes, const Ice::Current&)
+ {
+ Lock sync(*this);
+ for(ApplicationDescriptorSeq::const_iterator p = apps.begin(); p != apps.end(); ++p)
+ {
+ this->applications.insert(make_pair((*p)->name, *p));
+ }
+ this->nodes = nodes;
+ updated(serial);
+ }
+
+ virtual void
+ applicationAdded(int serial, const ApplicationDescriptorPtr& app, const Ice::Current&)
+ {
+ Lock sync(*this);
+ this->applications.insert(make_pair(app->name, app));
+ updated(serial);
+ }
+
+ virtual void
+ applicationRemoved(int serial, const std::string& name, const Ice::Current&)
+ {
+ Lock sync(*this);
+ this->applications.erase(name);
+ updated(serial);
+ }
+
+ virtual void
+ applicationUpdated(int serial, const ApplicationUpdateDescriptor& desc, const Ice::Current&)
+ {
+ Lock sync(*this);
+ for(map<string, string>::const_iterator p = desc.variables.begin(); p != desc.variables.end(); ++p)
+ {
+ this->applications[desc.name]->variables[p->first] = p->second;
+ }
+ updated(serial);
+ }
+
+ virtual void
+ applicationSynced(int serial, const ApplicationDescriptorPtr& app, const Ice::Current&)
+ {
+ Lock sync(*this);
+ this->applications[app->name] = app;
+ updated(serial);
+ }
+
+ virtual void
+ nodeUp(const string& name, const Ice::Current& current)
+ {
+ }
+
+ virtual void
+ nodeDown(const string& name, const Ice::Current& current)
+ {
+ }
+
+ void
+ waitForUpdate(const char* file, int line)
+ {
+ Lock sync(*this);
+ while(!_updated)
+ {
+ if(!timedWait(IceUtil::Time::seconds(10)))
+ {
+ cerr << "wait timed out " << file << ":" << line << endl;
+ test(false); // Timeout
+ }
+ }
+ _updated = false;
+ }
+
+ int serial;
+ map<string, ApplicationDescriptorPtr> applications;
+ Ice::StringSeq nodes;
+
+private:
+
+ void
+ updated(int serial)
+ {
+ this->serial = serial;
+ _updated = true;
+ notifyAll();
+ }
+
+ bool _updated;
+};
+
+class NodeObserverI : public NodeObserver
+{
+public:
+
+ virtual void
+ init(const NodeDynamicInfoSeq& info, const Ice::Current&)
+ {
+ }
+
+ virtual void
+ initNode(const NodeDynamicInfo& info, const Ice::Current&)
+ {
+ }
+
+ virtual void
+ updateServer(const string& node, const ServerDynamicInfo& info, const Ice::Current&)
+ {
+ }
+
+ virtual void
+ updateAdapter(const string& node, const AdapterDynamicInfo& info, const Ice::Current& current)
+ {
+ }
+};
+
+void
+allTests(const Ice::CommunicatorPtr& communicator)
+{
+ SessionManagerPrx manager = SessionManagerPrx::checkedCast(communicator->stringToProxy("IceGrid/SessionManager"));
+ test(manager);
+
+ SessionKeepAliveThreadPtr keepAlive;
+ keepAlive = new SessionKeepAliveThread(communicator->getLogger(), IceUtil::Time::seconds(5));
+ keepAlive->start();
+
+ {
+ cout << "testing sessions... " << flush;
+ SessionPrx session1 = manager->createLocalSession("Observer1");
+ SessionPrx session2 = manager->createLocalSession("Observer2");
+
+ keepAlive->add(session1);
+ keepAlive->add(session2);
+
+ Ice::ObjectAdapterPtr adpt1 = communicator->createObjectAdapter("Observer1");
+ RegistryObserverI* regObs1 = new RegistryObserverI();
+ Ice::ObjectPrx ro1 = adpt1->addWithUUID(regObs1);
+ NodeObserverI* nodeObs1 = new NodeObserverI();
+ Ice::ObjectPrx no1 = adpt1->addWithUUID(nodeObs1);
+ adpt1->activate();
+ manager->ice_connection()->setAdapter(adpt1);
+ session1->setObserversByIdentity(ro1->ice_getIdentity(), no1->ice_getIdentity());
+
+ Ice::ObjectAdapterPtr adpt2 = communicator->createObjectAdapterWithEndpoints("Observer2", "default");
+ RegistryObserverI* regObs2 = new RegistryObserverI();
+ Ice::ObjectPrx ro2 = adpt2->addWithUUID(regObs2);
+ NodeObserverI* nodeObs2 = new NodeObserverI();
+ Ice::ObjectPrx no2 = adpt2->addWithUUID(nodeObs2);
+ adpt2->activate();
+ session2->setObservers(RegistryObserverPrx::uncheckedCast(ro2), NodeObserverPrx::uncheckedCast(no2));
+
+ regObs1->waitForUpdate(__FILE__, __LINE__);
+ regObs2->waitForUpdate(__FILE__, __LINE__);
+
+ int serial = regObs1->serial;
+ test(serial == regObs2->serial);
+
+ try
+ {
+ session1->startUpdate(serial + 1);
+ test(false);
+ }
+ catch(const CacheOutOfDate&)
+ {
+ }
+ catch(const AccessDenied&)
+ {
+ test(false);
+ }
+
+ try
+ {
+ session1->startUpdate(serial);
+ }
+ catch(const Ice::UserException&)
+ {
+ test(false);
+ }
+
+ try
+ {
+ session2->startUpdate(regObs2->serial);
+ test(false);
+ }
+ catch(const AccessDenied& ex)
+ {
+ test(ex.lockUserId == "Observer1");
+ }
+
+ try
+ {
+ session1->finishUpdate();
+ }
+ catch(const Ice::UserException&)
+ {
+ test(false);
+ }
+
+ try
+ {
+ session2->startUpdate(regObs2->serial);
+ }
+ catch(const Ice::UserException&)
+ {
+ test(false);
+ }
+
+ try
+ {
+ ApplicationDescriptorPtr app = new ApplicationDescriptor();
+ app->name = "Application";
+ session2->addApplication(app);
+ }
+ catch(const Ice::UserException&)
+ {
+ test(false);
+ }
+
+ try
+ {
+ session1->addApplication(new ApplicationDescriptor());
+ test(false);
+ }
+ catch(const AccessDenied& ex)
+ {
+ }
+
+ try
+ {
+ session2->finishUpdate();
+ }
+ catch(const Ice::UserException&)
+ {
+ test(false);
+ }
+
+ regObs1->waitForUpdate(__FILE__, __LINE__);
+ regObs2->waitForUpdate(__FILE__, __LINE__);
+
+ test(serial + 1 == regObs1->serial);
+ test(serial + 1 == regObs2->serial);
+ ++serial;
+
+ try
+ {
+ session1->startUpdate(serial);
+ ApplicationUpdateDescriptor update;
+ update.name = "Application";
+ update.variables.insert(make_pair("test", "test"));
+ session1->updateApplication(update);
+ session1->finishUpdate();
+ }
+ catch(const Ice::UserException& ex)
+ {
+ cerr << ex << endl;
+ test(false);
+ }
+
+ regObs1->waitForUpdate(__FILE__, __LINE__);
+ regObs2->waitForUpdate(__FILE__, __LINE__);
+
+ test(serial + 1 == regObs1->serial);
+ test(serial + 1 == regObs2->serial);
+ ++serial;
+
+ try
+ {
+ ApplicationUpdateDescriptor update;
+ update.name = "Application";
+ session1->updateApplication(update);
+ test(false);
+ }
+ catch(const AccessDenied&)
+ {
+ }
+
+ try
+ {
+ session2->startUpdate(serial);
+ session2->removeApplication("Application");
+ session2->finishUpdate();
+ }
+ catch(const Ice::UserException&)
+ {
+ test(false);
+ }
+
+ regObs1->waitForUpdate(__FILE__, __LINE__);
+ regObs2->waitForUpdate(__FILE__, __LINE__);
+
+ test(serial + 1 == regObs1->serial);
+ test(serial + 1 == regObs2->serial);
+ ++serial;
+
+ try
+ {
+ session1->startUpdate(serial);
+ }
+ catch(const Ice::UserException& ex)
+ {
+ test(false);
+ }
+ session1->destroy();
+
+ try
+ {
+ session2->startUpdate(serial);
+ session2->finishUpdate();
+ }
+ catch(const Ice::UserException& ex)
+ {
+ test(false);
+ }
+ session2->destroy();
+
+ adpt1->deactivate();
+ adpt2->deactivate();
+
+ adpt1->waitForDeactivate();
+ adpt2->waitForDeactivate();
+
+ //
+ // TODO: test session reaping?
+ //
+
+ cout << "ok" << endl;
+ }
+
+ {
+ cout << "testing observers... " << flush;
+ SessionPrx session1 = manager->createLocalSession("Observer1");
+
+ keepAlive->add(session1);
+
+ Ice::ObjectAdapterPtr adpt1 = communicator->createObjectAdapter("Observer1.1");
+ RegistryObserverI* regObs1 = new RegistryObserverI();
+ Ice::ObjectPrx ro1 = adpt1->addWithUUID(regObs1);
+ NodeObserverI* nodeObs1 = new NodeObserverI();
+ Ice::ObjectPrx no1 = adpt1->addWithUUID(nodeObs1);
+ adpt1->activate();
+ manager->ice_connection()->setAdapter(adpt1);
+ session1->setObserversByIdentity(ro1->ice_getIdentity(), no1->ice_getIdentity());
+
+ regObs1->waitForUpdate(__FILE__, __LINE__);
+
+ int serial = regObs1->serial;
+ test(find(regObs1->nodes.begin(), regObs1->nodes.end(), "localnode") != regObs1->nodes.end());
+ test(regObs1->applications.empty());
+
+ try
+ {
+ ApplicationDescriptorPtr app = new ApplicationDescriptor();
+ app->name = "Application";
+ session1->startUpdate(serial);
+ session1->addApplication(app);
+ regObs1->waitForUpdate(__FILE__, __LINE__);
+ test(regObs1->applications["Application"]);
+ test(++serial == regObs1->serial);
+ }
+ catch(const Ice::UserException&)
+ {
+ test(false);
+ }
+
+ try
+ {
+ ApplicationUpdateDescriptor update;
+ update.name = "Application";
+ update.variables.insert(make_pair("test", "test"));
+ session1->updateApplication(update);
+ regObs1->waitForUpdate(__FILE__, __LINE__);
+ test(regObs1->applications["Application"]);
+ test(regObs1->applications["Application"]->variables["test"] == "test");
+ test(++serial == regObs1->serial);
+ }
+ catch(const Ice::UserException&)
+ {
+ test(false);
+ }
+
+ try
+ {
+ ApplicationDescriptorPtr app;
+ app = ApplicationDescriptorPtr::dynamicCast(regObs1->applications["Application"]->ice_clone());
+ app->variables.clear();
+ app->variables["test1"] = "test";
+ session1->syncApplication(app);
+ regObs1->waitForUpdate(__FILE__, __LINE__);
+ test(regObs1->applications["Application"]);
+ test(regObs1->applications["Application"]->variables.size() == 1);
+ test(regObs1->applications["Application"]->variables["test1"] == "test");
+ test(++serial == regObs1->serial);
+ }
+ catch(const Ice::UserException&)
+ {
+ test(false);
+ }
+
+ try
+ {
+ session1->removeApplication("Application");
+ regObs1->waitForUpdate(__FILE__, __LINE__);
+ test(regObs1->applications.empty());
+ test(++serial == regObs1->serial);
+ }
+ catch(const Ice::UserException&)
+ {
+ test(false);
+ }
+
+ session1->destroy();
+ adpt1->deactivate();
+ adpt1->waitForDeactivate();
+
+ cout << "ok" << endl;
+ }
+
+ keepAlive->terminate();
+ keepAlive->getThreadControl().join();
+ keepAlive = 0;
+}
diff --git a/cpp/test/IceGrid/update/Client.cpp b/cpp/test/IceGrid/update/Client.cpp
new file mode 100644
index 00000000000..4e4c921ec05
--- /dev/null
+++ b/cpp/test/IceGrid/update/Client.cpp
@@ -0,0 +1,55 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2005 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 <Ice/Ice.h>
+#include <TestCommon.h>
+#include <Test.h>
+
+using namespace std;
+
+int
+run(int argc, char* argv[], const Ice::CommunicatorPtr& communicator)
+{
+ void allTests(const Ice::CommunicatorPtr&);
+ allTests(communicator);
+ return EXIT_SUCCESS;
+}
+
+int
+main(int argc, char* argv[])
+{
+ int status;
+ Ice::CommunicatorPtr communicator;
+
+ try
+ {
+ communicator = Ice::initialize(argc, argv);
+ status = run(argc, argv, communicator);
+ }
+ catch(const Ice::Exception& ex)
+ {
+ cerr << ex << endl;
+ status = EXIT_FAILURE;
+ }
+
+ if(communicator)
+ {
+ try
+ {
+ communicator->destroy();
+ }
+ catch(const Ice::Exception& ex)
+ {
+ cerr << ex << endl;
+ status = EXIT_FAILURE;
+ }
+ }
+
+ return status;
+}
diff --git a/cpp/test/IceGrid/update/Makefile b/cpp/test/IceGrid/update/Makefile
new file mode 100644
index 00000000000..27e0fd7113f
--- /dev/null
+++ b/cpp/test/IceGrid/update/Makefile
@@ -0,0 +1,48 @@
+# **********************************************************************
+#
+# Copyright (c) 2003-2005 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
+SERVER = server
+
+TARGETS = $(CLIENT) $(SERVER)
+
+OBJS = Test.o
+
+COBJS = Client.o \
+ AllTests.o
+
+SOBJS = TestI.o \
+ Server.o
+
+SRCS = $(OBJS:.o=.cpp) \
+ $(COBJS:.o=.cpp) \
+ $(SOBJS:.o=.cpp)
+
+SLICE_SRCS = Test.ice
+
+include $(top_srcdir)/config/Make.rules
+
+CPPFLAGS := -I. -I../../include $(CPPFLAGS)
+LINKWITH := -lIce -lIceUtil
+
+$(CLIENT): $(OBJS) $(COBJS)
+ rm -f $@
+ $(CXX) $(LDFLAGS) -o $@ $(OBJS) $(COBJS) -lIceGrid -lGlacier2 $(LIBS)
+
+$(SERVER): $(OBJS) $(SOBJS)
+ rm -f $@
+ $(CXX) $(LDFLAGS) -o $@ $(OBJS) $(SOBJS) $(LIBS)
+
+clean::
+ rm -rf db/node/servers
+ rm -f db/registry/*
+
+include .depend
diff --git a/cpp/test/IceGrid/update/Server.cpp b/cpp/test/IceGrid/update/Server.cpp
new file mode 100644
index 00000000000..5d4ce7a465b
--- /dev/null
+++ b/cpp/test/IceGrid/update/Server.cpp
@@ -0,0 +1,63 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2005 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 <Ice/Ice.h>
+#include <TestI.h>
+#include <TestCommon.h>
+
+using namespace std;
+
+class Server : public Ice::Application
+{
+public:
+
+ virtual int run(int argc, char* argv[]);
+};
+
+int
+Server::run(int argc, char* argv[])
+{
+ Ice::PropertiesPtr properties = communicator()->getProperties();
+
+ Ice::StringSeq args = Ice::argsToStringSeq(argc, argv);
+ args = properties->parseCommandLineOptions("Test", args);
+ Ice::stringSeqToArgs(args, argc, argv);
+
+ string name = properties->getProperty("Ice.ProgramName");
+
+ Ice::ObjectAdapterPtr adapter = communicator()->createObjectAdapter("Server");
+ Ice::ObjectPtr object = new TestI(adapter, properties);
+ adapter->add(object, Ice::stringToIdentity(name));
+
+ shutdownOnInterrupt();
+ try
+ {
+ adapter->activate();
+ }
+ catch(const Ice::ObjectAdapterDeactivatedException&)
+ {
+ }
+ communicator()->waitForShutdown();
+ ignoreInterrupt();
+ return EXIT_SUCCESS;
+}
+
+int
+main(int argc, char* argv[])
+{
+ //
+ // Test if MY_ENV_VARIABLE is set.
+ //
+ char* value = getenv("MY_ENV_VARIABLE");
+ test(value != 0 && string(value) == "12");
+
+ Server app;
+ int rc = app.main(argc, argv);
+ return rc;
+}
diff --git a/cpp/test/IceGrid/update/Test.cpp b/cpp/test/IceGrid/update/Test.cpp
new file mode 100644
index 00000000000..48e5c2fd087
--- /dev/null
+++ b/cpp/test/IceGrid/update/Test.cpp
@@ -0,0 +1,471 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2005 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.
+//
+// **********************************************************************
+
+// Ice version 2.1.0
+// Generated from file `Test.ice'
+
+#include <Test.h>
+#include <Ice/LocalException.h>
+#include <Ice/ObjectFactory.h>
+#include <Ice/BasicStream.h>
+#include <Ice/Object.h>
+
+#ifndef ICE_IGNORE_VERSION
+# if ICE_INT_VERSION / 100 != 201
+# error Ice version mismatch!
+# endif
+# if ICE_INT_VERSION % 100 < 0
+# error Ice patch level mismatch!
+# endif
+#endif
+
+void
+IceInternal::incRef(::Test::TestIntf* p)
+{
+ p->__incRef();
+}
+
+void
+IceInternal::decRef(::Test::TestIntf* p)
+{
+ p->__decRef();
+}
+
+void
+IceInternal::incRef(::IceProxy::Test::TestIntf* p)
+{
+ p->__incRef();
+}
+
+void
+IceInternal::decRef(::IceProxy::Test::TestIntf* p)
+{
+ p->__decRef();
+}
+
+void
+Test::__write(::IceInternal::BasicStream* __os, const ::Test::TestIntfPrx& v)
+{
+ __os->write(::Ice::ObjectPrx(v));
+}
+
+void
+Test::__read(::IceInternal::BasicStream* __is, ::Test::TestIntfPrx& v)
+{
+ ::Ice::ObjectPrx proxy;
+ __is->read(proxy);
+ if(!proxy)
+ {
+ v = 0;
+ }
+ else
+ {
+ v = new ::IceProxy::Test::TestIntf;
+ v->__copyFrom(proxy);
+ }
+}
+
+void
+Test::__write(::IceInternal::BasicStream* __os, const ::Test::TestIntfPtr& v)
+{
+ __os->write(::Ice::ObjectPtr(v));
+}
+
+void
+IceProxy::Test::TestIntf::shutdown()
+{
+ shutdown(__defaultContext());
+}
+
+void
+IceProxy::Test::TestIntf::shutdown(const ::Ice::Context& __ctx)
+{
+ int __cnt = 0;
+ while(true)
+ {
+ try
+ {
+ ::IceInternal::Handle< ::IceDelegate::Ice::Object> __delBase = __getDelegate();
+ ::IceDelegate::Test::TestIntf* __del = dynamic_cast< ::IceDelegate::Test::TestIntf*>(__delBase.get());
+ __del->shutdown(__ctx);
+ return;
+ }
+ catch(const ::IceInternal::NonRepeatable& __ex)
+ {
+ __rethrowException(*__ex.get());
+ }
+ catch(const ::Ice::LocalException& __ex)
+ {
+ __handleException(__ex, __cnt);
+ }
+ }
+}
+
+::std::string
+IceProxy::Test::TestIntf::getProperty(const ::std::string& name)
+{
+ return getProperty(name, __defaultContext());
+}
+
+::std::string
+IceProxy::Test::TestIntf::getProperty(const ::std::string& name, const ::Ice::Context& __ctx)
+{
+ int __cnt = 0;
+ while(true)
+ {
+ try
+ {
+ __checkTwowayOnly("getProperty");
+ ::IceInternal::Handle< ::IceDelegate::Ice::Object> __delBase = __getDelegate();
+ ::IceDelegate::Test::TestIntf* __del = dynamic_cast< ::IceDelegate::Test::TestIntf*>(__delBase.get());
+ return __del->getProperty(name, __ctx);
+ }
+ catch(const ::IceInternal::NonRepeatable& __ex)
+ {
+ __rethrowException(*__ex.get());
+ }
+ catch(const ::Ice::LocalException& __ex)
+ {
+ __handleException(__ex, __cnt);
+ }
+ }
+}
+
+const ::std::string&
+IceProxy::Test::TestIntf::ice_staticId()
+{
+ return ::Test::TestIntf::ice_staticId();
+}
+
+::IceInternal::Handle< ::IceDelegateM::Ice::Object>
+IceProxy::Test::TestIntf::__createDelegateM()
+{
+ return ::IceInternal::Handle< ::IceDelegateM::Ice::Object>(new ::IceDelegateM::Test::TestIntf);
+}
+
+::IceInternal::Handle< ::IceDelegateD::Ice::Object>
+IceProxy::Test::TestIntf::__createDelegateD()
+{
+ return ::IceInternal::Handle< ::IceDelegateD::Ice::Object>(new ::IceDelegateD::Test::TestIntf);
+}
+
+bool
+IceProxy::Test::operator==(const ::IceProxy::Test::TestIntf& l, const ::IceProxy::Test::TestIntf& r)
+{
+ return static_cast<const ::IceProxy::Ice::Object&>(l) == static_cast<const ::IceProxy::Ice::Object&>(r);
+}
+
+bool
+IceProxy::Test::operator!=(const ::IceProxy::Test::TestIntf& l, const ::IceProxy::Test::TestIntf& r)
+{
+ return static_cast<const ::IceProxy::Ice::Object&>(l) != static_cast<const ::IceProxy::Ice::Object&>(r);
+}
+
+bool
+IceProxy::Test::operator<(const ::IceProxy::Test::TestIntf& l, const ::IceProxy::Test::TestIntf& r)
+{
+ return static_cast<const ::IceProxy::Ice::Object&>(l) < static_cast<const ::IceProxy::Ice::Object&>(r);
+}
+
+static const ::std::string __Test__TestIntf__shutdown_name = "shutdown";
+
+void
+IceDelegateM::Test::TestIntf::shutdown(const ::Ice::Context& __context)
+{
+ ::IceInternal::Outgoing __og(__connection.get(), __reference.get(), __Test__TestIntf__shutdown_name, static_cast< ::Ice::OperationMode>(0), __context, __compress);
+ bool __ok = __og.invoke();
+ try
+ {
+ ::IceInternal::BasicStream* __is = __og.is();
+ if(!__ok)
+ {
+ __is->throwException();
+ }
+ }
+ catch(const ::Ice::UserException&)
+ {
+ throw ::Ice::UnknownUserException(__FILE__, __LINE__);
+ }
+ catch(const ::Ice::LocalException& __ex)
+ {
+ throw ::IceInternal::NonRepeatable(__ex);
+ }
+}
+
+static const ::std::string __Test__TestIntf__getProperty_name = "getProperty";
+
+::std::string
+IceDelegateM::Test::TestIntf::getProperty(const ::std::string& name, const ::Ice::Context& __context)
+{
+ ::IceInternal::Outgoing __og(__connection.get(), __reference.get(), __Test__TestIntf__getProperty_name, static_cast< ::Ice::OperationMode>(0), __context, __compress);
+ try
+ {
+ ::IceInternal::BasicStream* __os = __og.os();
+ __os->write(name);
+ }
+ catch(const ::Ice::LocalException& __ex)
+ {
+ __og.abort(__ex);
+ }
+ bool __ok = __og.invoke();
+ try
+ {
+ ::IceInternal::BasicStream* __is = __og.is();
+ if(!__ok)
+ {
+ __is->throwException();
+ }
+ ::std::string __ret;
+ __is->read(__ret);
+ return __ret;
+ }
+ catch(const ::Ice::UserException&)
+ {
+ throw ::Ice::UnknownUserException(__FILE__, __LINE__);
+ }
+ catch(const ::Ice::LocalException& __ex)
+ {
+ throw ::IceInternal::NonRepeatable(__ex);
+ }
+}
+
+void
+IceDelegateD::Test::TestIntf::shutdown(const ::Ice::Context& __context)
+{
+ ::Ice::Current __current;
+ __initCurrent(__current, "shutdown", static_cast< ::Ice::OperationMode>(0), __context);
+ while(true)
+ {
+ ::IceInternal::Direct __direct(__current);
+ ::Test::TestIntf* __servant = dynamic_cast< ::Test::TestIntf*>(__direct.servant().get());
+ if(!__servant)
+ {
+ ::Ice::OperationNotExistException __opEx(__FILE__, __LINE__);
+ __opEx.id = __current.id;
+ __opEx.facet = __current.facet;
+ __opEx.operation = __current.operation;
+ throw __opEx;
+ }
+ try
+ {
+ __servant->shutdown(__current);
+ return;
+ }
+ catch(const ::Ice::LocalException& __ex)
+ {
+ throw ::IceInternal::NonRepeatable(__ex);
+ }
+ }
+}
+
+::std::string
+IceDelegateD::Test::TestIntf::getProperty(const ::std::string& name, const ::Ice::Context& __context)
+{
+ ::Ice::Current __current;
+ __initCurrent(__current, "getProperty", static_cast< ::Ice::OperationMode>(0), __context);
+ while(true)
+ {
+ ::IceInternal::Direct __direct(__current);
+ ::Test::TestIntf* __servant = dynamic_cast< ::Test::TestIntf*>(__direct.servant().get());
+ if(!__servant)
+ {
+ ::Ice::OperationNotExistException __opEx(__FILE__, __LINE__);
+ __opEx.id = __current.id;
+ __opEx.facet = __current.facet;
+ __opEx.operation = __current.operation;
+ throw __opEx;
+ }
+ try
+ {
+ return __servant->getProperty(name, __current);
+ }
+ catch(const ::Ice::LocalException& __ex)
+ {
+ throw ::IceInternal::NonRepeatable(__ex);
+ }
+ }
+}
+
+static const ::std::string __Test__TestIntf_ids[2] =
+{
+ "::Ice::Object",
+ "::Test::TestIntf"
+};
+
+bool
+Test::TestIntf::ice_isA(const ::std::string& _s, const ::Ice::Current&) const
+{
+ return ::std::binary_search(__Test__TestIntf_ids, __Test__TestIntf_ids + 2, _s);
+}
+
+::std::vector< ::std::string>
+Test::TestIntf::ice_ids(const ::Ice::Current&) const
+{
+ return ::std::vector< ::std::string>(&__Test__TestIntf_ids[0], &__Test__TestIntf_ids[2]);
+}
+
+const ::std::string&
+Test::TestIntf::ice_id(const ::Ice::Current&) const
+{
+ return __Test__TestIntf_ids[1];
+}
+
+const ::std::string&
+Test::TestIntf::ice_staticId()
+{
+ return __Test__TestIntf_ids[1];
+}
+
+::IceInternal::DispatchStatus
+Test::TestIntf::___shutdown(::IceInternal::Incoming& __inS, const ::Ice::Current& __current)
+{
+ shutdown(__current);
+ return ::IceInternal::DispatchOK;
+}
+
+::IceInternal::DispatchStatus
+Test::TestIntf::___getProperty(::IceInternal::Incoming& __inS, const ::Ice::Current& __current)
+{
+ ::IceInternal::BasicStream* __is = __inS.is();
+ ::IceInternal::BasicStream* __os = __inS.os();
+ ::std::string name;
+ __is->read(name);
+ ::std::string __ret = getProperty(name, __current);
+ __os->write(__ret);
+ return ::IceInternal::DispatchOK;
+}
+
+static ::std::string __Test__TestIntf_all[] =
+{
+ "getProperty",
+ "ice_id",
+ "ice_ids",
+ "ice_isA",
+ "ice_ping",
+ "shutdown"
+};
+
+::IceInternal::DispatchStatus
+Test::TestIntf::__dispatch(::IceInternal::Incoming& in, const ::Ice::Current& current)
+{
+ ::std::pair< ::std::string*, ::std::string*> r = ::std::equal_range(__Test__TestIntf_all, __Test__TestIntf_all + 6, current.operation);
+ if(r.first == r.second)
+ {
+ return ::IceInternal::DispatchOperationNotExist;
+ }
+
+ switch(r.first - __Test__TestIntf_all)
+ {
+ case 0:
+ {
+ return ___getProperty(in, current);
+ }
+ case 1:
+ {
+ return ___ice_id(in, current);
+ }
+ case 2:
+ {
+ return ___ice_ids(in, current);
+ }
+ case 3:
+ {
+ return ___ice_isA(in, current);
+ }
+ case 4:
+ {
+ return ___ice_ping(in, current);
+ }
+ case 5:
+ {
+ return ___shutdown(in, current);
+ }
+ }
+
+ assert(false);
+ return ::IceInternal::DispatchOperationNotExist;
+}
+
+void
+Test::TestIntf::__write(::IceInternal::BasicStream* __os) const
+{
+ __os->writeTypeId(ice_staticId());
+ __os->startWriteSlice();
+ __os->endWriteSlice();
+#if defined(_MSC_VER) && (_MSC_VER < 1300) // VC++ 6 compiler bug
+ Object::__write(__os);
+#else
+ ::Ice::Object::__write(__os);
+#endif
+}
+
+void
+Test::TestIntf::__read(::IceInternal::BasicStream* __is, bool __rid)
+{
+ if(__rid)
+ {
+ ::std::string myId;
+ __is->readTypeId(myId);
+ }
+ __is->startReadSlice();
+ __is->endReadSlice();
+#if defined(_MSC_VER) && (_MSC_VER < 1300) // VC++ 6 compiler bug
+ Object::__read(__is, true);
+#else
+ ::Ice::Object::__read(__is, true);
+#endif
+}
+
+void
+Test::TestIntf::__write(const ::Ice::OutputStreamPtr&) const
+{
+ Ice::MarshalException ex(__FILE__, __LINE__);
+ ex.reason = "type Test::TestIntf was not generated with stream support";
+ throw ex;
+}
+
+void
+Test::TestIntf::__read(const ::Ice::InputStreamPtr&, bool)
+{
+ Ice::MarshalException ex(__FILE__, __LINE__);
+ ex.reason = "type Test::TestIntf was not generated with stream support";
+ throw ex;
+}
+
+void
+Test::__patch__TestIntfPtr(void* __addr, ::Ice::ObjectPtr& v)
+{
+ ::Test::TestIntfPtr* p = static_cast< ::Test::TestIntfPtr*>(__addr);
+ assert(p);
+ *p = ::Test::TestIntfPtr::dynamicCast(v);
+ if(v && !*p)
+ {
+ ::Ice::NoObjectFactoryException e(__FILE__, __LINE__);
+ e.type = ::Test::TestIntf::ice_staticId();
+ throw e;
+ }
+}
+
+bool
+Test::operator==(const ::Test::TestIntf& l, const ::Test::TestIntf& r)
+{
+ return static_cast<const ::Ice::Object&>(l) == static_cast<const ::Ice::Object&>(r);
+}
+
+bool
+Test::operator!=(const ::Test::TestIntf& l, const ::Test::TestIntf& r)
+{
+ return static_cast<const ::Ice::Object&>(l) != static_cast<const ::Ice::Object&>(r);
+}
+
+bool
+Test::operator<(const ::Test::TestIntf& l, const ::Test::TestIntf& r)
+{
+ return static_cast<const ::Ice::Object&>(l) < static_cast<const ::Ice::Object&>(r);
+}
diff --git a/cpp/test/IceGrid/update/Test.ice b/cpp/test/IceGrid/update/Test.ice
new file mode 100644
index 00000000000..1d7c73a9d88
--- /dev/null
+++ b/cpp/test/IceGrid/update/Test.ice
@@ -0,0 +1,25 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2005 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.
+//
+// **********************************************************************
+
+#ifndef TEST_ICE
+#define TEST_ICE
+
+module Test
+{
+
+interface TestIntf
+{
+ void shutdown();
+
+ string getProperty(string name);
+};
+
+};
+
+#endif
diff --git a/cpp/test/IceGrid/update/TestI.cpp b/cpp/test/IceGrid/update/TestI.cpp
new file mode 100644
index 00000000000..f33c9a227a9
--- /dev/null
+++ b/cpp/test/IceGrid/update/TestI.cpp
@@ -0,0 +1,29 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2005 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 <Ice/Ice.h>
+#include <TestI.h>
+
+TestI::TestI(const Ice::ObjectAdapterPtr& adapter, const Ice::PropertiesPtr& properties) :
+ _adapter(adapter),
+ _properties(properties)
+{
+}
+
+void
+TestI::shutdown(const Ice::Current&)
+{
+ _adapter->getCommunicator()->shutdown();
+}
+
+std::string
+TestI::getProperty(const std::string& name, const Ice::Current&)
+{
+ return _properties->getProperty(name);
+}
diff --git a/cpp/test/IceGrid/update/db/.dummy b/cpp/test/IceGrid/update/db/.dummy
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/cpp/test/IceGrid/update/db/.dummy
diff --git a/cpp/test/IceGrid/update/run.py b/cpp/test/IceGrid/update/run.py
new file mode 100755
index 00000000000..6f94ef3559b
--- /dev/null
+++ b/cpp/test/IceGrid/update/run.py
@@ -0,0 +1,58 @@
+#!/usr/bin/env python
+# **********************************************************************
+#
+# Copyright (c) 2003-2005 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
+
+for toplevel in [".", "..", "../..", "../../..", "../../../.."]:
+ toplevel = os.path.normpath(toplevel)
+ if os.path.exists(os.path.join(toplevel, "config", "TestUtil.py")):
+ break
+else:
+ raise "can't find toplevel directory!"
+
+sys.path.append(os.path.join(toplevel, "config"))
+import TestUtil
+import IceGridAdmin
+
+name = os.path.join("IceGrid", "update")
+testdir = os.path.join(toplevel, "test", name)
+client = os.path.join(testdir, "client")
+
+#
+# Add locator options for the client and server. Since the server
+# invokes on the locator it's also considered to be a client.
+#
+additionalOptions = " --Ice.Default.Locator=\"IceGrid/Locator:default -p 12345\" " + \
+ "--Ice.PrintAdapterReady=0 --Ice.PrintProcessId=0"
+
+IceGridAdmin.cleanDbDir(os.path.join(testdir, "db"))
+iceGridRegistryThread = IceGridAdmin.startIceGridRegistry("12345", testdir)
+iceGridNodeThread = IceGridAdmin.startIceGridNode(testdir)
+
+print "starting client...",
+clientPipe = os.popen(client + TestUtil.clientServerOptions + additionalOptions + " 2>&1")
+print "ok"
+
+try:
+ TestUtil.printOutputFromPipe(clientPipe)
+except:
+ pass
+
+clientStatus = clientPipe.close()
+if clientStatus:
+ TestUtil.killServers()
+ sys.exit(1)
+
+IceGridAdmin.shutdownIceGridNode()
+iceGridNodeThread.join()
+IceGridAdmin.shutdownIceGridRegistry()
+iceGridRegistryThread.join()
+
+sys.exit(0)