summaryrefslogtreecommitdiff
path: root/cpp/src
diff options
context:
space:
mode:
Diffstat (limited to 'cpp/src')
-rw-r--r--cpp/src/Ice/CommunicatorI.cpp6
-rw-r--r--cpp/src/Ice/CommunicatorI.h1
-rw-r--r--cpp/src/Ice/Instance.cpp34
-rw-r--r--cpp/src/Ice/Instance.h1
-rw-r--r--cpp/src/Ice/Makefile1
-rw-r--r--cpp/src/Ice/Makefile.mak1
-rw-r--r--cpp/src/Ice/PropertiesAdminI.cpp187
-rw-r--r--cpp/src/Ice/PropertiesAdminI.h42
-rw-r--r--cpp/src/Ice/PropertiesI.cpp23
-rw-r--r--cpp/src/Ice/PropertiesI.h15
-rw-r--r--cpp/src/Ice/PropertyNames.cpp3
-rw-r--r--cpp/src/Ice/PropertyNames.h2
-rw-r--r--cpp/src/IceBox/ServiceManagerI.cpp314
-rw-r--r--cpp/src/IceBox/ServiceManagerI.h1
-rw-r--r--cpp/src/IceGrid/AdminI.cpp24
-rw-r--r--cpp/src/IceGrid/AdminI.h2
-rw-r--r--cpp/src/IceGrid/Database.cpp311
-rw-r--r--cpp/src/IceGrid/Database.h12
-rw-r--r--cpp/src/IceGrid/DescriptorHelper.cpp45
-rw-r--r--cpp/src/IceGrid/DescriptorHelper.h16
-rw-r--r--cpp/src/IceGrid/Internal.ice28
-rw-r--r--cpp/src/IceGrid/NodeCache.cpp94
-rw-r--r--cpp/src/IceGrid/NodeCache.h4
-rw-r--r--cpp/src/IceGrid/NodeI.cpp57
-rw-r--r--cpp/src/IceGrid/NodeI.h11
-rw-r--r--cpp/src/IceGrid/Parser.cpp124
-rw-r--r--cpp/src/IceGrid/ReplicaSessionManager.cpp2
-rw-r--r--cpp/src/IceGrid/ServerCache.cpp119
-rw-r--r--cpp/src/IceGrid/ServerCache.h29
-rwxr-xr-xcpp/src/IceGrid/ServerI.cpp713
-rw-r--r--cpp/src/IceGrid/ServerI.h17
31 files changed, 1678 insertions, 561 deletions
diff --git a/cpp/src/Ice/CommunicatorI.cpp b/cpp/src/Ice/CommunicatorI.cpp
index 25762041b06..2acb01718bb 100644
--- a/cpp/src/Ice/CommunicatorI.cpp
+++ b/cpp/src/Ice/CommunicatorI.cpp
@@ -384,6 +384,12 @@ Ice::CommunicatorI::removeAdminFacet(const string& facet)
return _instance->removeAdminFacet(facet);
}
+Ice::ObjectPtr
+Ice::CommunicatorI::findAdminFacet(const string& facet)
+{
+ return _instance->findAdminFacet(facet);
+}
+
Ice::CommunicatorI::CommunicatorI(const InitializationData& initData)
{
__setNoDelete(true);
diff --git a/cpp/src/Ice/CommunicatorI.h b/cpp/src/Ice/CommunicatorI.h
index d9628478707..384a6a7936c 100644
--- a/cpp/src/Ice/CommunicatorI.h
+++ b/cpp/src/Ice/CommunicatorI.h
@@ -79,6 +79,7 @@ public:
virtual ObjectPrx getAdmin() const;
virtual void addAdminFacet(const ObjectPtr&, const std::string&);
virtual ObjectPtr removeAdminFacet(const std::string&);
+ virtual ObjectPtr findAdminFacet(const std::string&);
private:
diff --git a/cpp/src/Ice/Instance.cpp b/cpp/src/Ice/Instance.cpp
index 5dda22e333c..c062c5a7671 100644
--- a/cpp/src/Ice/Instance.cpp
+++ b/cpp/src/Ice/Instance.cpp
@@ -25,6 +25,7 @@
#include <Ice/ObjectAdapterFactory.h>
#include <Ice/Exception.h>
#include <Ice/PropertiesI.h>
+#include <Ice/PropertiesAdminI.h>
#include <Ice/LoggerI.h>
#include <Ice/Network.h>
#include <Ice/EndpointFactoryManager.h>
@@ -724,6 +725,35 @@ IceInternal::Instance::removeAdminFacet(const string& facet)
{
result = _adminAdapter->removeFacet(_adminIdentity, facet);
}
+
+ return result;
+}
+
+Ice::ObjectPtr
+IceInternal::Instance::findAdminFacet(const string& facet)
+{
+ IceUtil::RecMutex::Lock sync(*this);
+
+ if(_state == StateDestroyed)
+ {
+ throw CommunicatorDestroyedException(__FILE__, __LINE__);
+ }
+
+ ObjectPtr result;
+
+ if(_adminAdapter == 0 || (!_adminFacetFilter.empty() && _adminFacetFilter.find(facet) == _adminFacetFilter.end()))
+ {
+ FacetMap::iterator p = _adminFacets.find(facet);
+ if(p != _adminFacets.end())
+ {
+ result = p->second;
+ }
+ }
+ else
+ {
+ result = _adminAdapter->findFacet(_adminIdentity, facet);
+ }
+
return result;
}
@@ -1074,7 +1104,9 @@ IceInternal::Instance::Instance(const CommunicatorPtr& communicator, const Initi
_adminFacetFilter.insert(facetSeq.begin(), facetSeq.end());
}
- _adminFacets.insert(FacetMap::value_type("Properties", new PropertiesAdminI(_initData.properties)));
+ _adminFacets.insert(
+ FacetMap::value_type("Properties",
+ new PropertiesAdminI("Properties", _initData.properties, _initData.logger)));
_adminFacets.insert(FacetMap::value_type("Process", new ProcessI(communicator)));
IceMX::MetricsAdminIPtr admin = new IceMX::MetricsAdminI(_initData.properties);
_adminFacets.insert(FacetMap::value_type("MetricsAdmin", admin));
diff --git a/cpp/src/Ice/Instance.h b/cpp/src/Ice/Instance.h
index 1cda82f3608..df97e4390d0 100644
--- a/cpp/src/Ice/Instance.h
+++ b/cpp/src/Ice/Instance.h
@@ -85,6 +85,7 @@ public:
Ice::ObjectPrx getAdmin();
void addAdminFacet(const Ice::ObjectPtr&, const std::string&);
Ice::ObjectPtr removeAdminFacet(const std::string&);
+ Ice::ObjectPtr findAdminFacet(const std::string&);
const Ice::ImplicitContextIPtr& getImplicitContext() const
{
diff --git a/cpp/src/Ice/Makefile b/cpp/src/Ice/Makefile
index 4aea8c9f907..54110fbf2fe 100644
--- a/cpp/src/Ice/Makefile
+++ b/cpp/src/Ice/Makefile
@@ -85,6 +85,7 @@ OBJS = Acceptor.o \
PluginManagerI.o \
Plugin.o \
Process.o \
+ PropertiesAdminI.o \
PropertiesI.o \
Properties.o \
PropertyNames.o \
diff --git a/cpp/src/Ice/Makefile.mak b/cpp/src/Ice/Makefile.mak
index e07cc6833bc..a2b12348f0e 100644
--- a/cpp/src/Ice/Makefile.mak
+++ b/cpp/src/Ice/Makefile.mak
@@ -79,6 +79,7 @@ OBJS = Acceptor.obj \
PluginManagerI.obj \
Plugin.obj \
Process.obj \
+ PropertiesAdminI.obj \
PropertiesI.obj \
Properties.obj \
PropertyNames.obj \
diff --git a/cpp/src/Ice/PropertiesAdminI.cpp b/cpp/src/Ice/PropertiesAdminI.cpp
new file mode 100644
index 00000000000..fc929bb959a
--- /dev/null
+++ b/cpp/src/Ice/PropertiesAdminI.cpp
@@ -0,0 +1,187 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2010 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/DisableWarnings.h>
+#include <Ice/PropertiesAdminI.h>
+#include <Ice/Logger.h>
+#include <Ice/LoggerUtil.h>
+
+using namespace std;
+using namespace Ice;
+using namespace IceInternal;
+
+Ice::PropertiesAdminI::PropertiesAdminI(const string& name, const PropertiesPtr& properties, const LoggerPtr& logger) :
+ _name(name), _properties(properties), _logger(logger)
+{
+}
+
+string
+Ice::PropertiesAdminI::getProperty(const string& name, const Ice::Current&)
+{
+ IceUtil::Mutex::Lock sync(*this);
+ return _properties->getProperty(name);
+}
+
+Ice::PropertyDict
+Ice::PropertiesAdminI::getPropertiesForPrefix(const string& prefix, const Ice::Current&)
+{
+ IceUtil::Mutex::Lock sync(*this);
+ return _properties->getPropertiesForPrefix(prefix);
+}
+
+void
+Ice::PropertiesAdminI::setProperties_async(const AMD_PropertiesAdmin_setPropertiesPtr& cb, const PropertyDict& props,
+ const Ice::Current&)
+{
+ PropertyDict added, changed, removed;
+ PropertiesAdminUpdateCallbackPtr callback;
+ {
+ IceUtil::Mutex::Lock sync(*this);
+
+ PropertyDict old = _properties->getPropertiesForPrefix("");
+ PropertyDict::const_iterator p;
+ const int traceLevel = _properties->getPropertyAsInt("Ice.Trace.Admin.Properties");
+
+ //
+ // Compute the difference between the new property set and the existing property set:
+ //
+ // 1) Any properties in the new set that were not defined in the existing set.
+ //
+ // 2) Any properties that appear in both sets but with different values.
+ //
+ // 3) Any properties not present in the new set but present in the existing set.
+ // In other words, the property has been removed.
+ //
+ for(p = props.begin(); p != props.end(); ++p)
+ {
+ PropertyDict::iterator q = old.find(p->first);
+ if(q == old.end())
+ {
+ if(!p->second.empty())
+ {
+ //
+ // This property is new.
+ //
+ added.insert(*p);
+ }
+ }
+ else
+ {
+ if(p->second != q->second)
+ {
+ if(p->second.empty())
+ {
+ //
+ // This property was removed.
+ //
+ removed.insert(*p);
+ }
+ else
+ {
+ //
+ // This property has changed.
+ //
+ changed.insert(*p);
+ }
+ }
+ }
+ }
+
+ if(traceLevel > 0 && (!added.empty() || !changed.empty() || !removed.empty()))
+ {
+ Trace out(_logger, _name);
+
+ out << "Summary of property changes";
+
+ if(!added.empty())
+ {
+ out << "\nNew properties:";
+ for(p = added.begin(); p != added.end(); ++p)
+ {
+ out << "\n " << p->first;
+ if(traceLevel > 1)
+ {
+ out << " = " << p->second;
+ }
+ }
+ }
+
+ if(!changed.empty())
+ {
+ out << "\nChanged properties:";
+ for(p = changed.begin(); p != changed.end(); ++p)
+ {
+ out << "\n " << p->first;
+ if(traceLevel > 1)
+ {
+ out << " = " << p->second << " (old value = " << _properties->getProperty(p->first) << ")";
+ }
+ }
+ }
+
+ if(!removed.empty())
+ {
+ out << "\nRemoved properties:";
+ for(p = removed.begin(); p != removed.end(); ++p)
+ {
+ out << "\n " << p->first;
+ }
+ }
+ }
+
+ //
+ // Update the property set.
+ //
+
+ for(p = added.begin(); p != added.end(); ++p)
+ {
+ _properties->setProperty(p->first, p->second);
+ }
+
+ for(p = changed.begin(); p != changed.end(); ++p)
+ {
+ _properties->setProperty(p->first, p->second);
+ }
+
+ for(p = removed.begin(); p != removed.end(); ++p)
+ {
+ _properties->setProperty(p->first, "");
+ }
+
+ callback = _updateCallback;
+ }
+
+ //
+ // Send the response now so that we do not block the client during the call to the update callback.
+ //
+ cb->ice_response();
+
+ if(callback)
+ {
+ PropertyDict changes = added;
+ changes.insert(changed.begin(), changed.end());
+ changes.insert(removed.begin(), removed.end());
+
+ try
+ {
+ callback->updated(changes);
+ }
+ catch(...)
+ {
+ // Ignore.
+ }
+ }
+}
+
+void
+Ice::PropertiesAdminI::setUpdateCallback(const PropertiesAdminUpdateCallbackPtr& cb)
+{
+ IceUtil::Mutex::Lock sync(*this);
+ _updateCallback = cb;
+}
diff --git a/cpp/src/Ice/PropertiesAdminI.h b/cpp/src/Ice/PropertiesAdminI.h
new file mode 100644
index 00000000000..2ddf420aa3e
--- /dev/null
+++ b/cpp/src/Ice/PropertiesAdminI.h
@@ -0,0 +1,42 @@
+// **********************************************************************
+//
+// 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.
+//
+// **********************************************************************
+
+#ifndef ICE_PROPERTIES_ADMIN_I_H
+#define ICE_PROPERTIES_ADMIN_I_H
+
+#include <IceUtil/Mutex.h>
+#include <Ice/PropertiesAdmin.h>
+#include <Ice/LoggerF.h>
+
+namespace Ice
+{
+
+class ICE_API PropertiesAdminI : public PropertiesAdmin, public NativePropertiesAdmin, private IceUtil::Mutex
+{
+public:
+
+ PropertiesAdminI(const std::string&, const PropertiesPtr&, const LoggerPtr&);
+
+ virtual std::string getProperty(const std::string&, const Current&);
+ virtual PropertyDict getPropertiesForPrefix(const std::string&, const Current&);
+ virtual void setProperties_async(const AMD_PropertiesAdmin_setPropertiesPtr&, const PropertyDict&, const Current&);
+
+ virtual void setUpdateCallback(const PropertiesAdminUpdateCallbackPtr&);
+
+private:
+
+ const std::string _name;
+ const PropertiesPtr _properties;
+ const LoggerPtr _logger;
+ PropertiesAdminUpdateCallbackPtr _updateCallback;
+};
+
+}
+
+#endif
diff --git a/cpp/src/Ice/PropertiesI.cpp b/cpp/src/Ice/PropertiesI.cpp
index 9bde5157184..1c4f2670597 100644
--- a/cpp/src/Ice/PropertiesI.cpp
+++ b/cpp/src/Ice/PropertiesI.cpp
@@ -774,26 +774,3 @@ Ice::PropertiesI::loadConfig()
PropertyValue pv(value, true);
_properties["Ice.Config"] = pv;
}
-
-
-//
-// PropertiesAdminI
-//
-
-
-Ice::PropertiesAdminI::PropertiesAdminI(const PropertiesPtr& properties) :
- _properties(properties)
-{
-}
-
-string
-Ice::PropertiesAdminI::getProperty(const string& name, const Ice::Current&)
-{
- return _properties->getProperty(name);
-}
-
-Ice::PropertyDict
-Ice::PropertiesAdminI::getPropertiesForPrefix(const string& prefix, const Ice::Current&)
-{
- return _properties->getPropertiesForPrefix(prefix);
-}
diff --git a/cpp/src/Ice/PropertiesI.h b/cpp/src/Ice/PropertiesI.h
index ee6df06c1bb..a54b042cff2 100644
--- a/cpp/src/Ice/PropertiesI.h
+++ b/cpp/src/Ice/PropertiesI.h
@@ -72,19 +72,4 @@ private:
const StringConverterPtr _converter;
};
-
-class PropertiesAdminI : public PropertiesAdmin
-{
-public:
-
- PropertiesAdminI(const PropertiesPtr&);
-
- virtual std::string getProperty(const std::string&, const Current&);
- virtual PropertyDict getPropertiesForPrefix(const std::string&, const Current&);
-
-private:
-
- const PropertiesPtr _properties;
-};
-
}
diff --git a/cpp/src/Ice/PropertyNames.cpp b/cpp/src/Ice/PropertyNames.cpp
index b1de65c529d..b9e7b8cd97b 100644
--- a/cpp/src/Ice/PropertyNames.cpp
+++ b/cpp/src/Ice/PropertyNames.cpp
@@ -8,7 +8,7 @@
// **********************************************************************
//
-// Generated by makeprops.py from file ./config/PropertyNames.xml, Fri Aug 10 10:27:32 2012
+// Generated by makeprops.py from file ./config/PropertyNames.xml, Thu Aug 30 14:36:00 2012
// IMPORTANT: Do not edit this file -- any edits made here will be lost!
@@ -137,6 +137,7 @@ const IceInternal::Property IcePropsData[] =
IceInternal::Property("Ice.ThreadPool.Server.ThreadIdleTime", false, 0),
IceInternal::Property("Ice.ThreadPool.Server.ThreadPriority", false, 0),
IceInternal::Property("Ice.ThreadPriority", false, 0),
+ IceInternal::Property("Ice.Trace.Admin.Properties", false, 0),
IceInternal::Property("Ice.Trace.GC", false, 0),
IceInternal::Property("Ice.Trace.Location", true, "Ice.Trace.Locator"),
IceInternal::Property("Ice.Trace.Locator", false, 0),
diff --git a/cpp/src/Ice/PropertyNames.h b/cpp/src/Ice/PropertyNames.h
index ce4a7927dcb..ecb560f6943 100644
--- a/cpp/src/Ice/PropertyNames.h
+++ b/cpp/src/Ice/PropertyNames.h
@@ -8,7 +8,7 @@
// **********************************************************************
//
-// Generated by makeprops.py from file ./config/PropertyNames.xml, Fri Aug 10 10:27:32 2012
+// Generated by makeprops.py from file ./config/PropertyNames.xml, Thu Aug 30 14:36:00 2012
// IMPORTANT: Do not edit this file -- any edits made here will be lost!
diff --git a/cpp/src/IceBox/ServiceManagerI.cpp b/cpp/src/IceBox/ServiceManagerI.cpp
index f91e9cd8da2..ce763ba0844 100644
--- a/cpp/src/IceBox/ServiceManagerI.cpp
+++ b/cpp/src/IceBox/ServiceManagerI.cpp
@@ -14,6 +14,7 @@
#include <Ice/SliceChecksums.h>
#include <Ice/Initialize.h>
#include <Ice/Instance.h>
+#include <Ice/PropertiesAdminI.h>
#include <IceBox/ServiceManagerI.h>
using namespace Ice;
@@ -25,30 +26,6 @@ typedef IceBox::Service* (*SERVICE_FACTORY)(CommunicatorPtr);
namespace
{
-class PropertiesAdminI : public PropertiesAdmin
-{
-public:
-
- PropertiesAdminI(const PropertiesPtr& properties) :
- _properties(properties)
- {
- }
-
- virtual string getProperty(const string& name, const Current&)
- {
- return _properties->getProperty(name);
- }
-
- virtual PropertyDict getPropertiesForPrefix(const string& prefix, const Current&)
- {
- return _properties->getPropertiesForPrefix(prefix);
- }
-
-private:
-
- const PropertiesPtr _properties;
-};
-
struct StartServiceInfo
{
StartServiceInfo(const std::string& service, const std::string& value, const Ice::StringSeq& serverArgs)
@@ -65,8 +42,8 @@ struct StartServiceInfo
}
catch(const IceUtilInternal::BadOptException& ex)
{
- PluginInitializationException e(__FILE__, __LINE__);
- e.reason = "invalid arguments for service `" + name + "':\n" + ex.reason;
+ FailureException e(__FILE__, __LINE__);
+ e.reason = "ServiceManager: invalid arguments for service `" + name + "':\n" + ex.reason;
throw e;
}
@@ -157,7 +134,7 @@ IceBox::ServiceManagerI::startService(const string& name, const Current&)
info.service->start(name, info.communicator == 0 ? _sharedCommunicator : info.communicator, info.args);
started = true;
}
- catch(const Ice::Exception& ex)
+ catch(const Exception& ex)
{
Warning out(_logger);
out << "ServiceManager: exception in start for service " << info.name << ":\n";
@@ -235,7 +212,7 @@ IceBox::ServiceManagerI::stopService(const string& name, const Current&)
info.service->stop();
stopped = true;
}
- catch(const Ice::Exception& ex)
+ catch(const Exception& ex)
{
Warning out(_logger);
out << "ServiceManager: exception while stopping service " << info.name << ":\n";
@@ -276,7 +253,7 @@ IceBox::ServiceManagerI::stopService(const string& name, const Current&)
}
void
-IceBox::ServiceManagerI::addObserver(const ServiceObserverPrx& observer, const Ice::Current&)
+IceBox::ServiceManagerI::addObserver(const ServiceObserverPrx& observer, const Current&)
{
//
// Null observers and duplicate registrations are ignored
@@ -458,18 +435,6 @@ IceBox::ServiceManagerI::start()
try
{
_communicator->addAdminFacet(this, "IceBox.ServiceManager");
-
- //
- // Add a Properties facet for each service
- //
- for(vector<ServiceInfo>::iterator r = _services.begin(); r != _services.end(); ++r)
- {
- const ServiceInfo& info = *r;
- CommunicatorPtr communicator = info.communicator != 0 ? info.communicator : _sharedCommunicator;
- _communicator->addAdminFacet(new PropertiesAdminI(communicator->getProperties()),
- "IceBox.Service." + info.name + ".Properties");
- }
-
_communicator->getAdmin();
}
catch(const ObjectAdapterDeactivatedException&)
@@ -536,11 +501,6 @@ IceBox::ServiceManagerI::start(const string& service, const string& entryPoint,
{
IceUtil::Monitor<IceUtil::Mutex>::Lock lock(*this);
- ServiceInfo info;
- info.name = service;
- info.status = Stopped;
- info.args = args;
-
//
// Load the entry point.
//
@@ -559,57 +519,27 @@ IceBox::ServiceManagerI::start(const string& service, const string& entryPoint,
throw ex;
}
+ ServiceInfo info;
+ info.name = service;
+ info.status = Stopped;
+ info.args = args;
+
//
- // Invoke the factory function.
+ // If Ice.UseSharedCommunicator.<name> is not defined, create
+ // a communicator for the service. The communicator inherits
+ // from the shared communicator properties. If it's defined
+ // add the service properties to the shared commnunicator
+ // property set.
//
- SERVICE_FACTORY factory = (SERVICE_FACTORY)sym;
- try
- {
- info.service = factory(_communicator);
- }
- catch(const FailureException&)
- {
- throw;
- }
- catch(const Exception& ex)
+ Ice::CommunicatorPtr communicator;
+ if(_communicator->getProperties()->getPropertyAsInt("IceBox.UseSharedCommunicator." + service) > 0)
{
- ostringstream s;
- s << "ServiceManager: exception in entry point `" + entryPoint + "' for service " << service << ":\n";
- s << ex;
-
- FailureException e(__FILE__, __LINE__);
- e.reason = s.str();
- throw e;
- }
- catch(...)
- {
- ostringstream s;
- s << "ServiceManager: unknown exception in entry point `" + entryPoint + "' for service " << service;
-
- FailureException e(__FILE__, __LINE__);
- e.reason = s.str();
- throw e;
+ assert(_sharedCommunicator);
+ communicator = _sharedCommunicator;
}
-
- //
- // Invoke Service::start().
- //
- try
+ else
{
- //
- // If Ice.UseSharedCommunicator.<name> is not defined, create
- // a communicator for the service. The communicator inherits
- // from the shared communicator properties. If it's defined
- // add the service properties to the shared commnunicator
- // property set.
- //
- Ice::CommunicatorPtr communicator;
- if(_communicator->getProperties()->getPropertyAsInt("IceBox.UseSharedCommunicator." + service) > 0)
- {
- assert(_sharedCommunicator);
- communicator = _sharedCommunicator;
- }
- else
+ try
{
//
// Create the service properties. We use the communicator properties as the default
@@ -624,19 +554,19 @@ IceBox::ServiceManagerI::start(const string& service, const string& entryPoint,
// read the service config file if it's specified with --Ice.Config.
//
initData.properties = createProperties(info.args, initData.properties);
-
+
//
// Next, parse the service "<service>.*" command line options (the Ice command
// line options were parsed by the createProperties above)
//
info.args = initData.properties->parseCommandLineOptions(service, info.args);
}
-
+
//
// Clone the logger to assign a new prefix.
//
initData.logger = _logger->cloneWithPrefix(initData.properties->getProperty("Ice.ProgramName"));
-
+
//
// Remaining command line options are passed to the communicator. This is
// necessary for Ice plug-in properties (e.g.: IceSSL).
@@ -644,15 +574,69 @@ IceBox::ServiceManagerI::start(const string& service, const string& entryPoint,
info.communicator = initialize(info.args, initData);
communicator = info.communicator;
}
+ catch(const Exception& ex)
+ {
+ ostringstream s;
+ s << "ServiceManager: exception while starting service " << service << ":\n";
+ s << ex;
+ FailureException e(__FILE__, __LINE__);
+ e.reason = s.str();
+ throw e;
+ }
+ }
+
+ try
+ {
+ //
+ // Add a PropertiesAdmin facet to the service manager's communicator that provides
+ // access to this service's property set. We do this prior to instantiating the
+ // service so that the service's constructor is able to access the facet (e.g.,
+ // in case it wants to set a callback).
+ //
+ string facetName = "IceBox.Service." + info.name + ".Properties";
+ _communicator->addAdminFacet(
+ new PropertiesAdminI(facetName, communicator->getProperties(), communicator->getLogger()), facetName);
+
+ //
+ // Invoke the factory function.
+ //
+ SERVICE_FACTORY factory = (SERVICE_FACTORY)sym;
+ try
+ {
+ info.service = factory(_communicator);
+ }
+ catch(const FailureException&)
+ {
+ throw;
+ }
+ catch(const Exception& ex)
+ {
+ ostringstream s;
+ s << "ServiceManager: exception in entry point `" + entryPoint + "' for service " << info.name << ":\n";
+ s << ex;
+
+ FailureException e(__FILE__, __LINE__);
+ e.reason = s.str();
+ throw e;
+ }
+ catch(...)
+ {
+ ostringstream s;
+ s << "ServiceManager: unknown exception in entry point `" + entryPoint + "' for service " << info.name;
+
+ FailureException e(__FILE__, __LINE__);
+ e.reason = s.str();
+ throw e;
+ }
+
//
// Start the service.
//
try
{
- info.service->start(service, communicator, info.args);
- info.status = Started;
-
+ info.service->start(info.name, communicator, info.args);
+
//
// There is no need to notify the observers since the 'start all'
// (that indirectly calls this function) occurs before the creation of
@@ -660,71 +644,61 @@ IceBox::ServiceManagerI::start(const string& service, const string& entryPoint,
// object adapter (so before any observer can be registered)
//
}
+ catch(const FailureException&)
+ {
+ throw;
+ }
+ catch(const Exception& ex)
+ {
+ ostringstream s;
+ s << "ServiceManager: exception while starting service " << info.name << ":\n";
+ s << ex;
+
+ FailureException e(__FILE__, __LINE__);
+ e.reason = s.str();
+ throw e;
+ }
catch(...)
{
- if(info.communicator)
- {
- try
- {
- info.communicator->shutdown();
- info.communicator->waitForShutdown();
- }
- catch(const Ice::CommunicatorDestroyedException&)
- {
- //
- // Ignore, the service might have already destroyed
- // the communicator for its own reasons.
- //
- }
- catch(const Ice::Exception& ex)
- {
- Warning out(_logger);
- out << "ServiceManager: exception while shutting down communicator for service " << service
- << ":\n";
- out << ex;
- }
+ ostringstream s;
+ s << "ServiceManager: unknown exception while starting service " << info.name;
- try
- {
- info.communicator->destroy();
- info.communicator = 0;
- }
- catch(const Exception& ex)
- {
- Warning out(_logger);
- out << "ServiceManager: exception while destroying communicator for service " << service
- << ":\n";
- out << ex;
- }
- }
- throw;
+ FailureException e(__FILE__, __LINE__);
+ e.reason = s.str();
+ throw e;
}
info.library = library;
+ info.status = Started;
_services.push_back(info);
}
- catch(const FailureException&)
+ catch(const ObjectAdapterDeactivatedException&)
{
- throw;
+ //
+ // Can be raised by addAdminFacet if the service manager communicator has been shut down.
+ //
+ if(info.communicator)
+ {
+ destroyServiceCommunicator(info.name, info.communicator);
+ }
}
- catch(const Exception& ex)
+ catch(const Exception&)
{
- ostringstream s;
- s << "ServiceManager: exception while starting service " << service << ":\n";
- s << ex;
+ try
+ {
+ _communicator->removeAdminFacet("IceBox.Service." + info.name + ".Properties");
+ }
+ catch(const LocalException&)
+ {
+ // Ignored
+ }
- FailureException e(__FILE__, __LINE__);
- e.reason = s.str();
- throw e;
- }
- catch(...)
- {
- ostringstream s;
- s << "ServiceManager: unknown exception while starting service " << service;
+ if(info.communicator)
+ {
+ destroyServiceCommunicator(info.name, info.communicator);
+ }
- FailureException e(__FILE__, __LINE__);
- e.reason = s.str();
- throw e;
+ throw;
}
}
@@ -764,7 +738,7 @@ IceBox::ServiceManagerI::stopAll()
info.status = Stopped;
stoppedServices.push_back(info.name);
}
- catch(const Ice::Exception& ex)
+ catch(const Exception& ex)
{
Warning out(_logger);
out << "ServiceManager: exception while stopping service " << info.name << ":\n";
@@ -798,14 +772,14 @@ IceBox::ServiceManagerI::stopAll()
info.communicator->shutdown();
info.communicator->waitForShutdown();
}
- catch(const Ice::CommunicatorDestroyedException&)
+ catch(const CommunicatorDestroyedException&)
{
//
// Ignore, the service might have already destroyed
// the communicator for its own reasons.
//
}
- catch(const Ice::Exception& ex)
+ catch(const Exception& ex)
{
Warning out(_logger);
out << "ServiceManager: exception while stopping service " << info.name << ":\n";
@@ -983,3 +957,37 @@ ServiceManagerI::observerCompleted(const Ice::AsyncResultPtr& result)
}
}
}
+
+void
+IceBox::ServiceManagerI::destroyServiceCommunicator(const string& service, const CommunicatorPtr& communicator)
+{
+ try
+ {
+ communicator->shutdown();
+ communicator->waitForShutdown();
+ }
+ catch(const CommunicatorDestroyedException&)
+ {
+ //
+ // Ignore, the service might have already destroyed
+ // the communicator for its own reasons.
+ //
+ }
+ catch(const Exception& ex)
+ {
+ Warning out(_logger);
+ out << "ServiceManager: exception in shutting down communicator for service " << service << ":\n";
+ out << ex;
+ }
+
+ try
+ {
+ communicator->destroy();
+ }
+ catch(const Exception& ex)
+ {
+ Warning out(_logger);
+ out << "ServiceManager: exception in shutting down communicator for service " << service << ":\n";
+ out << ex;
+ }
+}
diff --git a/cpp/src/IceBox/ServiceManagerI.h b/cpp/src/IceBox/ServiceManagerI.h
index 9c381941b49..a2b5388f4a8 100644
--- a/cpp/src/IceBox/ServiceManagerI.h
+++ b/cpp/src/IceBox/ServiceManagerI.h
@@ -70,6 +70,7 @@ private:
void observerRemoved(const ServiceObserverPrx&, const std::exception&);
Ice::PropertiesPtr createServiceProperties(const std::string&);
+ void destroyServiceCommunicator(const std::string&, const Ice::CommunicatorPtr&);
::Ice::CommunicatorPtr _communicator;
::Ice::CommunicatorPtr _sharedCommunicator;
diff --git a/cpp/src/IceGrid/AdminI.cpp b/cpp/src/IceGrid/AdminI.cpp
index 7453a93902b..624f143c1ba 100644
--- a/cpp/src/IceGrid/AdminI.cpp
+++ b/cpp/src/IceGrid/AdminI.cpp
@@ -187,7 +187,7 @@ void
AdminI::syncApplication(const ApplicationDescriptor& descriptor, const Current&)
{
checkIsReadOnly();
- _database->syncApplicationDescriptor(descriptor, _session.get());
+ _database->syncApplicationDescriptor(descriptor, false, _session.get());
}
void
@@ -200,7 +200,27 @@ AdminI::updateApplication(const ApplicationUpdateDescriptor& descriptor, const C
update.updateUser = _session->getId();
update.descriptor = descriptor;
update.revision = -1; // The database will set it.
- _database->updateApplication(update, _session.get());
+ _database->updateApplication(update, false, _session.get());
+}
+
+void
+AdminI::syncApplicationWithoutRestart(const ApplicationDescriptor& descriptor, const Current&)
+{
+ checkIsReadOnly();
+ _database->syncApplicationDescriptor(descriptor, true, _session.get());
+}
+
+void
+AdminI::updateApplicationWithoutRestart(const ApplicationUpdateDescriptor& descriptor, const Current&)
+{
+ checkIsReadOnly();
+
+ ApplicationUpdateInfo update;
+ update.updateTime = IceUtil::Time::now().toMilliSeconds();
+ update.updateUser = _session->getId();
+ update.descriptor = descriptor;
+ update.revision = -1; // The database will set it.
+ _database->updateApplication(update, true, _session.get());
}
void
diff --git a/cpp/src/IceGrid/AdminI.h b/cpp/src/IceGrid/AdminI.h
index 5ed1c5ee11c..864170dec19 100644
--- a/cpp/src/IceGrid/AdminI.h
+++ b/cpp/src/IceGrid/AdminI.h
@@ -36,6 +36,8 @@ public:
virtual void addApplication(const ApplicationDescriptor&, const Ice::Current&);
virtual void syncApplication(const ApplicationDescriptor&, const Ice::Current&);
virtual void updateApplication(const ApplicationUpdateDescriptor&, const Ice::Current&);
+ virtual void syncApplicationWithoutRestart(const ApplicationDescriptor&, const Ice::Current&);
+ virtual void updateApplicationWithoutRestart(const ApplicationUpdateDescriptor&, const Ice::Current&);
virtual void removeApplication(const std::string&, const Ice::Current&);
virtual void instantiateServer(const std::string&, const std::string&, const ServerInstanceDescriptor&,
const Ice::Current&);
diff --git a/cpp/src/IceGrid/Database.cpp b/cpp/src/IceGrid/Database.cpp
index 9326ea2e62f..0d8fb7888dd 100644
--- a/cpp/src/IceGrid/Database.cpp
+++ b/cpp/src/IceGrid/Database.cpp
@@ -43,30 +43,6 @@ struct ObjectLoadCI : binary_function<pair<Ice::ObjectPrx, float>&, pair<Ice::Ob
}
};
-bool
-isServerUpdated(const ServerInfo& lhs, const ServerInfo& rhs)
-{
- if(lhs.node != rhs.node)
- {
- return true;
- }
-
- IceBoxDescriptorPtr lhsIceBox = IceBoxDescriptorPtr::dynamicCast(lhs.descriptor);
- IceBoxDescriptorPtr rhsIceBox = IceBoxDescriptorPtr::dynamicCast(rhs.descriptor);
- if(lhsIceBox && rhsIceBox)
- {
- return IceBoxHelper(lhsIceBox) != IceBoxHelper(rhsIceBox);
- }
- else if(!lhsIceBox && !rhsIceBox)
- {
- return ServerHelper(lhs.descriptor) != ServerHelper(rhs.descriptor);
- }
- else
- {
- return true;
- }
-}
-
void
halt(const Ice::CommunicatorPtr& com, const DatabaseException& ex)
{
@@ -275,7 +251,7 @@ Database::syncApplications(const ApplicationInfoSeq& newApplications)
{
ApplicationHelper previous(_communicator, q->second.descriptor);
ApplicationHelper helper(_communicator, p->descriptor);
- reload(previous, helper, entries, p->uuid, p->revision);
+ reload(previous, helper, entries, p->uuid, p->revision, false);
}
else
{
@@ -466,12 +442,12 @@ Database::addApplication(const ApplicationInfo& info, AdminSessionI* session)
}
void
-Database::updateApplication(const ApplicationUpdateInfo& updt, AdminSessionI* session)
+Database::updateApplication(const ApplicationUpdateInfo& updt, bool noRestart, AdminSessionI* session)
{
- ServerEntrySeq entries;
ApplicationInfo oldApp;
- ApplicationDescriptor newDesc;
ApplicationUpdateInfo update = updt;
+ auto_ptr<ApplicationHelper> previous;
+ auto_ptr<ApplicationHelper> helper;
try
{
Lock sync(*this);
@@ -495,20 +471,8 @@ Database::updateApplication(const ApplicationUpdateInfo& updt, AdminSessionI* se
update.revision = oldApp.revision + 1;
}
- ApplicationHelper previous(_communicator, oldApp.descriptor);
- ApplicationHelper helper(_communicator, previous.update(update.descriptor), true);
- newDesc = helper.getDefinition();
-
- checkForUpdate(previous, helper, connection);
-
- ApplicationInfo info = oldApp;
- info.updateTime = update.updateTime;
- info.updateUser = update.updateUser;
- info.revision = update.revision;
- info.descriptor = newDesc;
- saveApplication(info, connection);
-
- reload(previous, helper, entries, oldApp.uuid, oldApp.revision + 1);
+ previous.reset(new ApplicationHelper(_communicator, oldApp.descriptor));
+ helper.reset(new ApplicationHelper(_communicator, previous->update(update.descriptor), true));
startUpdating(update.descriptor.name, oldApp.uuid, oldApp.revision + 1);
}
@@ -517,15 +481,16 @@ Database::updateApplication(const ApplicationUpdateInfo& updt, AdminSessionI* se
halt(_communicator, ex);
}
- finishApplicationUpdate(entries, update, oldApp, newDesc, session);
+ finishApplicationUpdate(update, oldApp, *previous, *helper, session, noRestart);
}
void
-Database::syncApplicationDescriptor(const ApplicationDescriptor& newDesc, AdminSessionI* session)
+Database::syncApplicationDescriptor(const ApplicationDescriptor& newDesc, bool noRestart, AdminSessionI* session)
{
- ServerEntrySeq entries;
ApplicationUpdateInfo update;
ApplicationInfo oldApp;
+ auto_ptr<ApplicationHelper> previous;
+ auto_ptr<ApplicationHelper> helper;
try
{
Lock sync(*this);
@@ -544,25 +509,14 @@ Database::syncApplicationDescriptor(const ApplicationDescriptor& newDesc, AdminS
throw ApplicationNotExistException(newDesc.name);
}
- ApplicationHelper previous(_communicator, oldApp.descriptor);
- ApplicationHelper helper(_communicator, newDesc, true);
+ previous.reset(new ApplicationHelper(_communicator, oldApp.descriptor));
+ helper.reset(new ApplicationHelper(_communicator, newDesc, true));
update.updateTime = IceUtil::Time::now().toMilliSeconds();
update.updateUser = _lockUserId;
update.revision = oldApp.revision + 1;
- update.descriptor = helper.diff(previous);
+ update.descriptor = helper->diff(*previous);
- checkForUpdate(previous, helper, connection);
-
- ApplicationInfo info = oldApp;
- info.updateTime = update.updateTime;
- info.updateUser = update.updateUser;
- info.revision = update.revision;
- info.descriptor = newDesc;
- saveApplication(info, connection);
-
- reload(previous, helper, entries, oldApp.uuid, oldApp.revision + 1);
-
startUpdating(update.descriptor.name, oldApp.uuid, oldApp.revision + 1);
}
catch(const DatabaseException& ex)
@@ -570,7 +524,7 @@ Database::syncApplicationDescriptor(const ApplicationDescriptor& newDesc, AdminS
halt(_communicator, ex);
}
- finishApplicationUpdate(entries, update, oldApp, newDesc, session);
+ finishApplicationUpdate(update, oldApp, *previous, *helper, session, noRestart);
}
void
@@ -579,10 +533,10 @@ Database::instantiateServer(const string& application,
const ServerInstanceDescriptor& instance,
AdminSessionI* session)
{
- ServerEntrySeq entries;
ApplicationUpdateInfo update;
ApplicationInfo oldApp;
- ApplicationDescriptor newDesc;
+ auto_ptr<ApplicationHelper> previous;
+ auto_ptr<ApplicationHelper> helper;
try
{
@@ -602,25 +556,13 @@ Database::instantiateServer(const string& application,
throw ApplicationNotExistException(application);
}
- ApplicationHelper previous(_communicator, oldApp.descriptor);
- ApplicationHelper helper(_communicator, previous.instantiateServer(node, instance), true);
- newDesc = helper.getDefinition();
+ previous.reset(new ApplicationHelper(_communicator, oldApp.descriptor));
+ helper.reset(new ApplicationHelper(_communicator, previous->instantiateServer(node, instance), true));
update.updateTime = IceUtil::Time::now().toMilliSeconds();
update.updateUser = _lockUserId;
update.revision = oldApp.revision + 1;
- update.descriptor = helper.diff(previous);
-
- checkForUpdate(previous, helper, connection);
-
- ApplicationInfo info = oldApp;
- info.updateTime = update.updateTime;
- info.updateUser = update.updateUser;
- info.revision = update.revision;
- info.descriptor = newDesc;
- saveApplication(info, connection);
-
- reload(previous, helper, entries, oldApp.uuid, oldApp.revision + 1);
+ update.descriptor = helper->diff(*previous);
startUpdating(update.descriptor.name, oldApp.uuid, oldApp.revision + 1);
}
@@ -629,7 +571,7 @@ Database::instantiateServer(const string& application,
halt(_communicator, ex);
}
- finishApplicationUpdate(entries, update, oldApp, newDesc, session);
+ finishApplicationUpdate(update, oldApp, *previous, *helper, session, true);
}
void
@@ -1034,7 +976,7 @@ Database::getAdapterInfo(const string& id)
// Otherwise, we check the adapter endpoint table -- if there's an
// entry the adapter is managed by the registry itself.
//
- DatabaseConnectionPtr connection = _databaseCache->getConnection();
+ DatabaseConnectionPtr connection = _databaseCache->newConnection();
AdaptersWrapperPtr adaptersWrapper = _databaseCache->getAdapters(connection);
AdapterInfoSeq infos;
try
@@ -1878,7 +1820,7 @@ Database::load(const ApplicationHelper& app, ServerEntrySeq& entries, const stri
map<string, ServerInfo> servers = app.getServerInfos(uuid, revision);
for(map<string, ServerInfo>::const_iterator p = servers.begin(); p != servers.end(); ++p)
{
- entries.push_back(_serverCache.add(p->second));
+ entries.push_back(_serverCache.add(p->second, false));
}
}
@@ -1914,7 +1856,8 @@ Database::reload(const ApplicationHelper& oldApp,
const ApplicationHelper& newApp,
ServerEntrySeq& entries,
const string& uuid,
- int revision)
+ int revision,
+ bool noRestart)
{
const string application = oldApp.getInstance().name;
@@ -1940,7 +1883,7 @@ Database::reload(const ApplicationHelper& oldApp,
else
{
ServerEntryPtr server = _serverCache.get(p->first);
- server->update(q->second); // Just update the server revision on the node.
+ server->update(q->second, noRestart); // Just update the server revision on the node.
entries.push_back(server);
}
}
@@ -2028,7 +1971,7 @@ Database::reload(const ApplicationHelper& oldApp,
//
for(vector<ServerInfo>::const_iterator q = load.begin(); q != load.end(); ++q)
{
- entries.push_back(_serverCache.add(*q));
+ entries.push_back(_serverCache.add(*q, noRestart));
}
}
@@ -2081,17 +2024,205 @@ Database::removeApplication(const string& name, const DatabaseConnectionPtr& con
}
void
-Database::finishApplicationUpdate(ServerEntrySeq& entries,
- const ApplicationUpdateInfo& update,
- const ApplicationInfo& oldApp,
- const ApplicationDescriptor& newDesc,
- AdminSessionI* session)
+Database::checkUpdate(const ApplicationHelper& oldApp,
+ const ApplicationHelper& newApp,
+ const string& uuid,
+ int revision,
+ bool noRestart)
{
+ const string application = oldApp.getInstance().name;
+
+ map<string, ServerInfo> oldServers = oldApp.getServerInfos(uuid, revision);
+ map<string, ServerInfo> newServers = newApp.getServerInfos(uuid, revision + 1);
+
+ map<string, ServerInfo>::const_iterator p;
+ vector<string> servers;
+ vector<string> reasons;
+ if(noRestart)
+ {
+ for(p = oldServers.begin(); p != oldServers.end(); ++p)
+ {
+ map<string, ServerInfo>::const_iterator q = newServers.find(p->first);
+ if(q == newServers.end())
+ {
+ servers.push_back(p->first);
+ reasons.push_back("server `" + p->first + "' needs to be removed");
+ }
+ }
+ }
+
+ vector<CheckUpdateResultPtr> results;
+ set<string> unreachableNodes;
+ for(p = newServers.begin(); p != newServers.end(); ++p)
+ {
+ map<string, ServerInfo>::const_iterator q = oldServers.find(p->first);
+ if(q != oldServers.end() && isServerUpdated(p->second, q->second))
+ {
+ if(noRestart && isServerUpdated(p->second, q->second, true)) // Ignore properties
+ {
+ //
+ // The updates are not only property updates and noRestart is required, no
+ // need to check the server update on the node, we know already it requires
+ // a restart.
+ //
+ servers.push_back(p->first);
+ reasons.push_back("update requires the server `" + p->first + "' to be stopped");
+ }
+ else
+ {
+ //
+ // Ask the node to check the server update.
+ //
+ try
+ {
+ CheckUpdateResultPtr result = _serverCache.get(p->first)->checkUpdate(p->second, noRestart);
+ if(result)
+ {
+ results.push_back(result);
+ }
+ }
+ catch(const NodeUnreachableException& ex)
+ {
+ unreachableNodes.insert(ex.name);
+ }
+ catch(const DeploymentException& ex)
+ {
+ servers.push_back(p->first);
+ reasons.push_back(ex.reason);
+ }
+
+ }
+ }
+ }
+
+ for(vector<CheckUpdateResultPtr>::const_iterator q = results.begin(); q != results.end(); ++q)
+ {
+ try
+ {
+ (*q)->getResult();
+ }
+ catch(const NodeUnreachableException& ex)
+ {
+ unreachableNodes.insert(ex.name);
+ }
+ catch(const DeploymentException& ex)
+ {
+ servers.push_back((*q)->getServer());
+ reasons.push_back(ex.reason);
+ }
+ }
+
+ if(noRestart)
+ {
+ if(!servers.empty() || !unreachableNodes.empty())
+ {
+ if(_traceLevels->application > 0)
+ {
+ Ice::Trace out(_traceLevels->logger, _traceLevels->applicationCat);
+ out << "check for application `" << application << "' update failed:";
+ if(!unreachableNodes.empty())
+ {
+ Ice::StringSeq nodes(unreachableNodes.begin(), unreachableNodes.end());
+ if(nodes.size() == 1)
+ {
+ out << "\nthe node `" << nodes[0] << "' is down";
+ }
+ else
+ {
+ out << "\nthe nodes `" << toString(nodes, ", ") << "' are down";
+ }
+ }
+ if(!reasons.empty())
+ {
+ for(vector<string>::const_iterator p = reasons.begin(); p != reasons.end(); ++p)
+ {
+ out << "\n" << *p;
+ }
+ }
+ }
+
+ ostringstream os;
+ os << "check for application `" << application << "' update failed:";
+ if(!servers.empty())
+ {
+ if(servers.size() == 1)
+ {
+ os << "\nthe server `" << servers[0] << "' would need to be stopped";
+ }
+ else
+ {
+ os << "\nthe servers `" << toString(servers, ", ") << "' would need to be stopped";
+ }
+ }
+ if(!unreachableNodes.empty())
+ {
+ Ice::StringSeq nodes(unreachableNodes.begin(), unreachableNodes.end());
+ if(nodes.size() == 1)
+ {
+ os << "\nthe node `" << nodes[0] << "' is down";
+ }
+ else
+ {
+ os << "\nthe nodes `" << toString(nodes, ", ") << "' are down";
+ }
+ }
+ throw DeploymentException(os.str());
+ }
+ }
+ else if(!reasons.empty())
+ {
+ ostringstream os;
+ os << "check for application `" << application << "' update failed:";
+ for(vector<string>::const_iterator p = reasons.begin(); p != reasons.end(); ++p)
+ {
+ os << "\n" << *p;
+ }
+ throw DeploymentException(os.str());
+ }
+}
+
+void
+Database::finishApplicationUpdate(const ApplicationUpdateInfo& update,
+ const ApplicationInfo& oldApp,
+ const ApplicationHelper& previous,
+ const ApplicationHelper& helper,
+ AdminSessionI* session,
+ bool noRestart)
+{
+ const ApplicationDescriptor& newDesc = helper.getDefinition();
+ DatabaseConnectionPtr connection = _databaseCache->newConnection();
+
+ ServerEntrySeq entries;
+ try
+ {
+ if(_master)
+ {
+ checkUpdate(previous, helper, oldApp.uuid, oldApp.revision, noRestart);
+ }
+
+ Lock sync(*this);
+ checkForUpdate(previous, helper, connection);
+ reload(previous, helper, entries, oldApp.uuid, oldApp.revision + 1, noRestart);
+ }
+ catch(const DeploymentException&)
+ {
+ finishUpdating(update.descriptor.name);
+ throw;
+ }
+
for_each(entries.begin(), entries.end(), IceUtil::voidMemFun(&ServerEntry::sync));
int serial;
{
Lock sync(*this);
+
+ ApplicationInfo info = oldApp;
+ info.updateTime = update.updateTime;
+ info.updateUser = update.updateUser;
+ info.revision = update.revision;
+ info.descriptor = newDesc;
+ saveApplication(info, connection);
+
++_applicationSerial;
serial = _applicationObserverTopic->applicationUpdated(_applicationSerial, update);
}
@@ -2135,8 +2266,8 @@ Database::finishApplicationUpdate(ServerEntrySeq& entries,
ApplicationInfo info = oldApp;
info.revision = update.revision + 1;
- saveApplication(info, _databaseCache->getConnection());
- reload(previous, helper, entries, info.uuid, info.revision);
+ saveApplication(info, connection);
+ reload(previous, helper, entries, info.uuid, info.revision, noRestart);
newUpdate.updateTime = IceUtil::Time::now().toMilliSeconds();
newUpdate.updateUser = _lockUserId;
diff --git a/cpp/src/IceGrid/Database.h b/cpp/src/IceGrid/Database.h
index bd437619dcf..e3bae73ab67 100644
--- a/cpp/src/IceGrid/Database.h
+++ b/cpp/src/IceGrid/Database.h
@@ -73,8 +73,8 @@ public:
void syncObjects(const ObjectInfoSeq&);
void addApplication(const ApplicationInfo&, AdminSessionI* = 0);
- void updateApplication(const ApplicationUpdateInfo&, AdminSessionI* = 0);
- void syncApplicationDescriptor(const ApplicationDescriptor&, AdminSessionI* = 0);
+ void updateApplication(const ApplicationUpdateInfo&, bool, AdminSessionI* = 0);
+ void syncApplicationDescriptor(const ApplicationDescriptor&, bool, AdminSessionI* = 0);
void instantiateServer(const std::string&, const std::string&, const ServerInstanceDescriptor&, AdminSessionI* =0);
void removeApplication(const std::string&, AdminSessionI* = 0);
ApplicationInfo getApplicationInfo(const std::string&);
@@ -140,13 +140,15 @@ private:
void load(const ApplicationHelper&, ServerEntrySeq&, const std::string&, int);
void unload(const ApplicationHelper&, ServerEntrySeq&);
- void reload(const ApplicationHelper&, const ApplicationHelper&, ServerEntrySeq&, const std::string&, int);
+ void reload(const ApplicationHelper&, const ApplicationHelper&, ServerEntrySeq&, const std::string&, int, bool);
+
+ void checkUpdate(const ApplicationHelper&, const ApplicationHelper&, const std::string&, int, bool);
void saveApplication(const ApplicationInfo&, const IceDB::DatabaseConnectionPtr&);
void removeApplication(const std::string&, const IceDB::DatabaseConnectionPtr&);
- void finishApplicationUpdate(ServerEntrySeq&, const ApplicationUpdateInfo&, const ApplicationInfo&,
- const ApplicationDescriptor&, AdminSessionI*);
+ void finishApplicationUpdate(const ApplicationUpdateInfo&, const ApplicationInfo&, const ApplicationHelper&,
+ const ApplicationHelper&, AdminSessionI*, bool);
void checkSessionLock(AdminSessionI*);
diff --git a/cpp/src/IceGrid/DescriptorHelper.cpp b/cpp/src/IceGrid/DescriptorHelper.cpp
index 67467f280f9..ce9a74810e6 100644
--- a/cpp/src/IceGrid/DescriptorHelper.cpp
+++ b/cpp/src/IceGrid/DescriptorHelper.cpp
@@ -915,8 +915,8 @@ Resolver::checkReserved(const string& type, const map<string, string>& values) c
}
}
-CommunicatorHelper::CommunicatorHelper(const CommunicatorDescriptorPtr& desc) :
- _desc(desc)
+CommunicatorHelper::CommunicatorHelper(const CommunicatorDescriptorPtr& desc, bool ignoreProps) :
+ _desc(desc), _ignoreProps(ignoreProps)
{
}
@@ -939,9 +939,12 @@ CommunicatorHelper::operator==(const CommunicatorHelper& helper) const
return false;
}
- if(_desc->propertySet != helper._desc->propertySet)
+ if(!_ignoreProps)
{
- return false;
+ if(_desc->propertySet != helper._desc->propertySet)
+ {
+ return false;
+ }
}
if(set<DbEnvDescriptor>(_desc->dbEnvs.begin(), _desc->dbEnvs.end()) !=
@@ -1206,8 +1209,8 @@ CommunicatorHelper::getProperty(const string& name) const
return IceGrid::getProperty(_desc->propertySet.properties, name);
}
-ServiceHelper::ServiceHelper(const ServiceDescriptorPtr& descriptor) :
- CommunicatorHelper(descriptor),
+ServiceHelper::ServiceHelper(const ServiceDescriptorPtr& descriptor, bool ignoreProps) :
+ CommunicatorHelper(descriptor, ignoreProps),
_desc(descriptor)
{
}
@@ -1284,8 +1287,8 @@ ServiceHelper::print(const Ice::CommunicatorPtr& communicator, Output& out) cons
out << eb;
}
-ServerHelper::ServerHelper(const ServerDescriptorPtr& descriptor) :
- CommunicatorHelper(descriptor),
+ServerHelper::ServerHelper(const ServerDescriptorPtr& descriptor, bool ignoreProps) :
+ CommunicatorHelper(descriptor, ignoreProps),
_desc(descriptor)
{
}
@@ -1504,13 +1507,13 @@ ServerHelper::instantiateImpl(const ServerDescriptorPtr& instance,
instance->propertySet.properties.insert(instance->propertySet.properties.end(), props.begin(), props.end());
}
-IceBoxHelper::IceBoxHelper(const IceBoxDescriptorPtr& descriptor) :
- ServerHelper(descriptor),
+IceBoxHelper::IceBoxHelper(const IceBoxDescriptorPtr& descriptor, bool ignoreProps) :
+ ServerHelper(descriptor, ignoreProps),
_desc(descriptor)
{
for(ServiceInstanceDescriptorSeq::const_iterator p = _desc->services.begin(); p != _desc->services.end(); ++p)
{
- _services.push_back(ServiceInstanceHelper(*p));
+ _services.push_back(ServiceInstanceHelper(*p, ignoreProps));
}
}
@@ -1671,7 +1674,7 @@ InstanceHelper::instantiateParams(const Resolver& resolve,
return params;
}
-ServiceInstanceHelper::ServiceInstanceHelper(const ServiceInstanceDescriptor& desc) :
+ServiceInstanceHelper::ServiceInstanceHelper(const ServiceInstanceDescriptor& desc, bool ignoreProps) :
_def(desc)
{
//
@@ -1686,7 +1689,7 @@ ServiceInstanceHelper::ServiceInstanceHelper(const ServiceInstanceDescriptor& de
if(_def.descriptor)
{
- _service = ServiceHelper(_def.descriptor);
+ _service = ServiceHelper(_def.descriptor, ignoreProps);
}
}
@@ -3153,17 +3156,17 @@ ApplicationHelper::printDiff(Output& out, const ApplicationHelper& helper) const
}
bool
-IceGrid::descriptorEqual(const ServerDescriptorPtr& lhs, const ServerDescriptorPtr& rhs)
+IceGrid::descriptorEqual(const ServerDescriptorPtr& lhs, const ServerDescriptorPtr& rhs, bool ignoreProps)
{
IceBoxDescriptorPtr lhsIceBox = IceBoxDescriptorPtr::dynamicCast(lhs);
IceBoxDescriptorPtr rhsIceBox = IceBoxDescriptorPtr::dynamicCast(rhs);
if(lhsIceBox && rhsIceBox)
{
- return IceBoxHelper(lhsIceBox) == IceBoxHelper(rhsIceBox);
+ return IceBoxHelper(lhsIceBox, ignoreProps) == IceBoxHelper(rhsIceBox, ignoreProps);
}
else if(!lhsIceBox && !rhsIceBox)
{
- return ServerHelper(lhs) == ServerHelper(rhs);
+ return ServerHelper(lhs, ignoreProps) == ServerHelper(rhs, ignoreProps);
}
else
{
@@ -3184,3 +3187,13 @@ IceGrid::createHelper(const ServerDescriptorPtr& desc)
return new ServerHelper(desc);
}
}
+
+bool
+IceGrid::isServerUpdated(const ServerInfo& lhs, const ServerInfo& rhs, bool ignoreProps)
+{
+ if(lhs.node != rhs.node)
+ {
+ return true;
+ }
+ return !descriptorEqual(lhs.descriptor, rhs.descriptor, ignoreProps);
+}
diff --git a/cpp/src/IceGrid/DescriptorHelper.h b/cpp/src/IceGrid/DescriptorHelper.h
index b2b012c5e49..eeda3eee3a1 100644
--- a/cpp/src/IceGrid/DescriptorHelper.h
+++ b/cpp/src/IceGrid/DescriptorHelper.h
@@ -85,8 +85,8 @@ class CommunicatorHelper
{
public:
- CommunicatorHelper(const CommunicatorDescriptorPtr&);
- CommunicatorHelper() { }
+ CommunicatorHelper(const CommunicatorDescriptorPtr&, bool = false);
+ CommunicatorHelper() : _ignoreProps(false) { }
virtual ~CommunicatorHelper() { }
virtual bool operator==(const CommunicatorHelper&) const;
@@ -109,13 +109,14 @@ protected:
private:
CommunicatorDescriptorPtr _desc;
+ bool _ignoreProps;
};
class ServiceHelper : public CommunicatorHelper
{
public:
- ServiceHelper(const ServiceDescriptorPtr&);
+ ServiceHelper(const ServiceDescriptorPtr&, bool = false);
ServiceHelper() { }
virtual bool operator==(const CommunicatorHelper&) const;
@@ -143,7 +144,7 @@ class ServerHelper : public CommunicatorHelper, public IceUtil::SimpleShared
{
public:
- ServerHelper(const ServerDescriptorPtr&);
+ ServerHelper(const ServerDescriptorPtr&, bool = false);
ServerHelper() { }
virtual bool operator==(const CommunicatorHelper&) const;
@@ -185,7 +186,7 @@ class ServiceInstanceHelper : public InstanceHelper
{
public:
- ServiceInstanceHelper(const ServiceInstanceDescriptor&);
+ ServiceInstanceHelper(const ServiceInstanceDescriptor&, bool);
bool operator==(const ServiceInstanceHelper&) const;
bool operator!=(const ServiceInstanceHelper&) const;
@@ -207,7 +208,7 @@ class IceBoxHelper : public ServerHelper
{
public:
- IceBoxHelper(const IceBoxDescriptorPtr&);
+ IceBoxHelper(const IceBoxDescriptorPtr&, bool = false);
IceBoxHelper() { }
virtual bool operator==(const CommunicatorHelper&) const;
@@ -339,7 +340,8 @@ private:
NodeHelperDict _nodes;
};
-bool descriptorEqual(const ServerDescriptorPtr&, const ServerDescriptorPtr&);
+bool descriptorEqual(const ServerDescriptorPtr&, const ServerDescriptorPtr&, bool = false);
ServerHelperPtr createHelper(const ServerDescriptorPtr&);
+bool isServerUpdated(const ServerInfo&, const ServerInfo&, bool = false);
}
diff --git a/cpp/src/IceGrid/Internal.ice b/cpp/src/IceGrid/Internal.ice
index 1362ff7bbe7..bb5ae9b9907 100644
--- a/cpp/src/IceGrid/Internal.ice
+++ b/cpp/src/IceGrid/Internal.ice
@@ -239,6 +239,18 @@ interface Server extends FileReader
/**
*
+ * Check if the given server can be loaded on this node.
+ *
+ * @return True if the server is inactive.
+ *
+ * @throws DeploymentException Raised if the server can't be updated.
+ *
+ **/
+ ["ami"] bool checkUpdate(InternalServerDescriptor svr, bool noRestart)
+ throws DeploymentException;
+
+ /**
+ *
* Enable or disable the server.
*
**/
@@ -359,6 +371,22 @@ interface Node extends FileReader, ReplicaObserver
/**
*
+ * Load the given server and ensure the server won't be
+ * restarted. If the server resources weren't already created
+ * (database environment directories, property files, etc), they
+ * will be created. If the server can't be updated without a
+ * restart, a DeploymentException is raised.
+ *
+ **/
+ ["amd"] idempotent Server* loadServerWithoutRestart(InternalServerDescriptor svr,
+ string replicaName,
+ out AdapterPrxDict adapters,
+ out int actTimeout,
+ out int deactTimeout)
+ throws DeploymentException;
+
+ /**
+ *
* Destroy the given server.
*
**/
diff --git a/cpp/src/IceGrid/NodeCache.cpp b/cpp/src/IceGrid/NodeCache.cpp
index e03a74e51d9..c2d69d64e05 100644
--- a/cpp/src/IceGrid/NodeCache.cpp
+++ b/cpp/src/IceGrid/NodeCache.cpp
@@ -182,10 +182,7 @@ class LoadCB : virtual public IceUtil::Shared
{
public:
- LoadCB(const TraceLevelsPtr& traceLevels,
- const ServerEntryPtr& server,
- const string& node,
- int timeout) :
+ LoadCB(const TraceLevelsPtr& traceLevels, const ServerEntryPtr& server, const string& node, int timeout) :
_traceLevels(traceLevels), _server(server), _id(server->getId()), _node(node), _timeout(timeout)
{
}
@@ -549,7 +546,8 @@ NodeEntry::canRemove()
}
void
-NodeEntry::loadServer(const ServerEntryPtr& entry, const ServerInfo& server, const SessionIPtr& session, int timeout)
+NodeEntry::loadServer(const ServerEntryPtr& entry, const ServerInfo& server, const SessionIPtr& session, int timeout,
+ bool noRestart)
{
try
{
@@ -600,12 +598,23 @@ NodeEntry::loadServer(const ServerEntryPtr& entry, const ServerInfo& server, con
out << " for session `" << session->getId() << "'";
}
}
-
- node->begin_loadServer(desc, _cache.getReplicaName(),
- newCallback_Node_loadServer(
- new LoadCB(_cache.getTraceLevels(), entry, _name, sessionTimeout),
- &LoadCB::response,
- &LoadCB::exception));
+
+ if(noRestart)
+ {
+ node->begin_loadServerWithoutRestart(desc, _cache.getReplicaName(),
+ newCallback_Node_loadServerWithoutRestart(
+ new LoadCB(_cache.getTraceLevels(), entry, _name, sessionTimeout),
+ &LoadCB::response,
+ &LoadCB::exception));
+ }
+ else
+ {
+ node->begin_loadServer(desc, _cache.getReplicaName(),
+ newCallback_Node_loadServer(
+ new LoadCB(_cache.getTraceLevels(), entry, _name, sessionTimeout),
+ &LoadCB::response,
+ &LoadCB::exception));
+ }
}
catch(const NodeUnreachableException& ex)
{
@@ -665,31 +674,27 @@ NodeEntry::getServerInfo(const ServerInfo& server, const SessionIPtr& session)
return info;
}
-ServerDescriptorPtr
-NodeEntry::getServerDescriptor(const ServerInfo& server, const SessionIPtr& session)
+InternalServerDescriptorPtr
+NodeEntry::getInternalServerDescriptor(const ServerInfo& server, const SessionIPtr& session)
{
- assert(_session);
-
- Resolver resolve(_session->getInfo(), _cache.getCommunicator());
- resolve.setReserved("application", server.application);
- resolve.setReserved("server", server.descriptor->id);
- resolve.setContext("server `${server}'");
-
- if(session)
- {
- resolve.setReserved("session.id", session->getId());
- }
-
- IceBoxDescriptorPtr iceBox = IceBoxDescriptorPtr::dynamicCast(server.descriptor);
- if(iceBox)
+ Lock sync(*this);
+ checkSession();
+
+ ServerInfo info = server;
+ try
{
- return IceBoxHelper(iceBox).instantiate(resolve, PropertyDescriptorSeq(), PropertySetDescriptorDict());
+ info.descriptor = getServerDescriptor(server, session);
}
- else
+ catch(const DeploymentException&)
{
- return ServerHelper(server.descriptor).instantiate(resolve, PropertyDescriptorSeq(),
- PropertySetDescriptorDict());
+ //
+ // We ignore the deployment error for now (which can
+ // only be caused in theory by session variables not
+ // being defined because the server isn't
+ // allocated...)
+ //
}
+ return getInternalServerDescriptor(info);
}
void
@@ -854,6 +859,33 @@ NodeEntry::finishedRegistration(const Ice::Exception& ex)
}
}
+ServerDescriptorPtr
+NodeEntry::getServerDescriptor(const ServerInfo& server, const SessionIPtr& session)
+{
+ assert(_session);
+
+ Resolver resolve(_session->getInfo(), _cache.getCommunicator());
+ resolve.setReserved("application", server.application);
+ resolve.setReserved("server", server.descriptor->id);
+ resolve.setContext("server `${server}'");
+
+ if(session)
+ {
+ resolve.setReserved("session.id", session->getId());
+ }
+
+ IceBoxDescriptorPtr iceBox = IceBoxDescriptorPtr::dynamicCast(server.descriptor);
+ if(iceBox)
+ {
+ return IceBoxHelper(iceBox).instantiate(resolve, PropertyDescriptorSeq(), PropertySetDescriptorDict());
+ }
+ else
+ {
+ return ServerHelper(server.descriptor).instantiate(resolve, PropertyDescriptorSeq(),
+ PropertySetDescriptorDict());
+ }
+}
+
InternalServerDescriptorPtr
NodeEntry::getInternalServerDescriptor(const ServerInfo& info) const
{
diff --git a/cpp/src/IceGrid/NodeCache.h b/cpp/src/IceGrid/NodeCache.h
index 03b3a1a914d..af87fe2730b 100644
--- a/cpp/src/IceGrid/NodeCache.h
+++ b/cpp/src/IceGrid/NodeCache.h
@@ -53,9 +53,11 @@ public:
bool canRemove();
- void loadServer(const ServerEntryPtr&, const ServerInfo&, const SessionIPtr&, int);
+ void loadServer(const ServerEntryPtr&, const ServerInfo&, const SessionIPtr&, int, bool);
void destroyServer(const ServerEntryPtr&, const ServerInfo&, int);
+
ServerInfo getServerInfo(const ServerInfo&, const SessionIPtr&);
+ InternalServerDescriptorPtr getInternalServerDescriptor(const ServerInfo&, const SessionIPtr&);
void __incRef();
void __decRef();
diff --git a/cpp/src/IceGrid/NodeI.cpp b/cpp/src/IceGrid/NodeI.cpp
index 1c03de9c4fa..de95ba412d2 100644
--- a/cpp/src/IceGrid/NodeI.cpp
+++ b/cpp/src/IceGrid/NodeI.cpp
@@ -374,6 +374,7 @@ void
NodeI::loadServer_async(const AMD_Node_loadServerPtr& amdCB,
const InternalServerDescriptorPtr& descriptor,
const string& replicaName,
+ bool noRestart,
const Ice::Current& current)
{
ServerCommandPtr command;
@@ -418,7 +419,7 @@ NodeI::loadServer_async(const AMD_Node_loadServerPtr& amdCB,
try
{
- command = server->load(amdCB, descriptor, replicaName);
+ command = server->load(amdCB, descriptor, replicaName, noRestart);
}
catch(const Ice::ObjectNotExistException&)
{
@@ -450,9 +451,57 @@ NodeI::loadServer_async(const AMD_Node_loadServerPtr& amdCB,
}
void
-NodeI::destroyServer_async(const AMD_Node_destroyServerPtr& amdCB,
- const string& serverId,
- const string& uuid,
+NodeI::loadServer_async(const AMD_Node_loadServerPtr& amdCB,
+ const InternalServerDescriptorPtr& descriptor,
+ const string& replicaName,
+ const Ice::Current& current)
+{
+ loadServer_async(amdCB, descriptor, replicaName, false, current);
+}
+
+void
+NodeI::loadServerWithoutRestart_async(const AMD_Node_loadServerWithoutRestartPtr& amdCB,
+ const InternalServerDescriptorPtr& descriptor,
+ const string& replicaName,
+ const Ice::Current& current)
+{
+ class LoadServerCB : public AMD_Node_loadServer
+ {
+ public:
+
+ LoadServerCB(const AMD_Node_loadServerWithoutRestartPtr& cb) : _cb(cb)
+ {
+ }
+
+ virtual void
+ ice_response(const ServerPrx& server, const AdapterPrxDict& adapters, Ice::Int actTimeout, Ice::Int deacTimeout)
+ {
+ _cb->ice_response(server, adapters, actTimeout, deacTimeout);
+ };
+
+ virtual void
+ ice_exception(const ::std::exception& ex)
+ {
+ _cb->ice_exception(ex);
+ }
+
+ virtual void
+ ice_exception()
+ {
+ _cb->ice_exception();
+ }
+
+ private:
+
+ const AMD_Node_loadServerWithoutRestartPtr _cb;
+ };
+ loadServer_async(new LoadServerCB(amdCB), descriptor, replicaName, true, current);
+}
+
+void
+NodeI::destroyServer_async(const AMD_Node_destroyServerPtr& amdCB,
+ const string& serverId,
+ const string& uuid,
int revision,
const string& replicaName,
const Ice::Current& current)
diff --git a/cpp/src/IceGrid/NodeI.h b/cpp/src/IceGrid/NodeI.h
index 508de0f2a48..39d39a976b8 100644
--- a/cpp/src/IceGrid/NodeI.h
+++ b/cpp/src/IceGrid/NodeI.h
@@ -68,8 +68,19 @@ public:
virtual void loadServer_async(const AMD_Node_loadServerPtr&,
const InternalServerDescriptorPtr&,
const std::string&,
+ bool,
const Ice::Current&);
+ virtual void loadServer_async(const AMD_Node_loadServerPtr&,
+ const InternalServerDescriptorPtr&,
+ const std::string&,
+ const Ice::Current&);
+
+ virtual void loadServerWithoutRestart_async(const AMD_Node_loadServerWithoutRestartPtr&,
+ const InternalServerDescriptorPtr&,
+ const std::string&,
+ const Ice::Current&);
+
virtual void destroyServer_async(const AMD_Node_destroyServerPtr&,
const std::string&,
const std::string&,
diff --git a/cpp/src/IceGrid/Parser.cpp b/cpp/src/IceGrid/Parser.cpp
index e80d54408b1..4c068664e0a 100644
--- a/cpp/src/IceGrid/Parser.cpp
+++ b/cpp/src/IceGrid/Parser.cpp
@@ -51,13 +51,17 @@ const char* _commandsHelp[][3] = {
"application describe NAME Describe application NAME.\n"
},
{ "application", "diff",
-"application diff DESC [TARGET ... ] [NAME=VALUE ... ]\n"
+"application diff [-s | --servers] DESC [TARGET ... ] [NAME=VALUE ... ]\n"
" Print the differences betwen the application\n"
" described in DESC and the current deployment.\n"
+" If -s or --servers is specified, print the\n"
+" the list of servers affected by the differences.\n"
},
{ "application", "update",
-"application update DESC [TARGET ... ] [NAME=VALUE ... ]\n"
-" Update the application described in DESC.\n"
+"application update [-n | --no-restart] DESC [TARGET ... ] [NAME=VALUE ... ]\n"
+" Update the application described in DESC. If -n or\n"
+" --no-restart is specified, the update will fail if\n"
+" it requires to stop some servers.\n"
},
{ "application", "patch",
"application patch [-f | --force] NAME\n"
@@ -475,8 +479,28 @@ Parser::describeApplication(const list<string>& args)
}
void
-Parser::diffApplication(const list<string>& args)
+Parser::diffApplication(const list<string>& origArgs)
{
+ list<string> copyArgs = origArgs;
+ copyArgs.push_front("icegridadmin");
+
+ IceUtilInternal::Options opts;
+ opts.addOpt("s", "servers");
+ vector<string> args;
+ try
+ {
+ for(list<string>::const_iterator p = copyArgs.begin(); p != copyArgs.end(); ++p)
+ {
+ args.push_back(*p);
+ }
+ args = opts.parse(args);
+ }
+ catch(const IceUtilInternal::BadOptException& e)
+ {
+ error(e.reason);
+ return;
+ }
+
if(args.size() < 1)
{
invalidCommand("application diff" , "requires at least one argument");
@@ -488,7 +512,7 @@ Parser::diffApplication(const list<string>& args)
StringSeq targets;
map<string, string> vars;
- list<string>::const_iterator p = args.begin();
+ vector<string>::const_iterator p = args.begin();
string desc = *p++;
for(; p != args.end(); ++p)
@@ -511,7 +535,55 @@ Parser::diffApplication(const list<string>& args)
ApplicationHelper oldAppHelper(_communicator, origApp.descriptor);
Output out(cout);
- newAppHelper.printDiff(out, oldAppHelper);
+ if(opts.isSet("servers"))
+ {
+ map<string, ServerInfo> oldServers = oldAppHelper.getServerInfos(origApp.uuid, origApp.revision);
+ map<string, ServerInfo> newServers = newAppHelper.getServerInfos(origApp.uuid, origApp.revision);
+
+ vector<string> messages;
+ map<string, ServerInfo>::const_iterator p;
+ for(p = oldServers.begin(); p != oldServers.end(); ++p)
+ {
+ map<string, ServerInfo>::const_iterator q = newServers.find(p->first);
+ if(q == newServers.end())
+ {
+ messages.push_back("server `" + p->first + "': removed");
+ }
+ }
+
+ for(p = newServers.begin(); p != newServers.end(); ++p)
+ {
+ map<string, ServerInfo>::const_iterator q = oldServers.find(p->first);
+ if(q == oldServers.end())
+ {
+ messages.push_back("server `" + p->first + "': added");
+ }
+ else if(isServerUpdated(p->second, q->second))
+ {
+ if(isServerUpdated(p->second, q->second, true)) // Ignore properties
+ {
+ messages.push_back("server `" + p->first + "': updated (restart required)");
+ }
+ else
+ {
+ messages.push_back("server `" + p->first + "': properties updated (no restart required)");
+ }
+ }
+ }
+
+ out << "application `" << origApp.descriptor.name << "'";
+ out << sb;
+ sort(messages.begin(), messages.end());
+ for(vector<string>::const_iterator r = messages.begin(); r != messages.end(); ++r)
+ {
+ out << nl << *r;
+ }
+ out << eb;
+ }
+ else
+ {
+ newAppHelper.printDiff(out, oldAppHelper);
+ }
out << nl;
}
catch(const Ice::Exception& ex)
@@ -521,8 +593,28 @@ Parser::diffApplication(const list<string>& args)
}
void
-Parser::updateApplication(const list<string>& args)
+Parser::updateApplication(const list<string>& origArgs)
{
+ list<string> copyArgs = origArgs;
+ copyArgs.push_front("icegridadmin");
+
+ IceUtilInternal::Options opts;
+ opts.addOpt("n", "no-restart");
+ vector<string> args;
+ try
+ {
+ for(list<string>::const_iterator p = copyArgs.begin(); p != copyArgs.end(); ++p)
+ {
+ args.push_back(*p);
+ }
+ args = opts.parse(args);
+ }
+ catch(const IceUtilInternal::BadOptException& e)
+ {
+ error(e.reason);
+ return;
+ }
+
if(args.size() < 1)
{
invalidCommand("application update", "requires at least one argument");
@@ -534,8 +626,8 @@ Parser::updateApplication(const list<string>& args)
StringSeq targets;
map<string, string> vars;
- list<string>::const_iterator p = args.begin();
- string desc = *p++;
+ vector<string>::const_iterator p = args.begin();
+ string xml = *p++;
for(; p != args.end(); ++p)
{
@@ -550,7 +642,19 @@ Parser::updateApplication(const list<string>& args)
}
}
- _admin->syncApplication(DescriptorParser::parseDescriptor(desc, targets, vars, _communicator, _admin));
+ ApplicationDescriptor desc = DescriptorParser::parseDescriptor(xml, targets, vars, _communicator, _admin);
+ if(opts.isSet("no-restart"))
+ {
+ _admin->syncApplicationWithoutRestart(desc);
+ }
+ else
+ {
+ _admin->syncApplication(desc);
+ }
+ }
+ catch(const Ice::OperationNotExistException&)
+ {
+ error("registry doesn't support updates without restart");
}
catch(const Ice::Exception& ex)
{
diff --git a/cpp/src/IceGrid/ReplicaSessionManager.cpp b/cpp/src/IceGrid/ReplicaSessionManager.cpp
index 8d478fddc8c..404571b7217 100644
--- a/cpp/src/IceGrid/ReplicaSessionManager.cpp
+++ b/cpp/src/IceGrid/ReplicaSessionManager.cpp
@@ -79,7 +79,7 @@ public:
string failure;
try
{
- _database->updateApplication(update);
+ _database->updateApplication(update, false);
}
catch(const DeploymentException& ex)
{
diff --git a/cpp/src/IceGrid/ServerCache.cpp b/cpp/src/IceGrid/ServerCache.cpp
index d9be593a4af..5d8d8942b29 100644
--- a/cpp/src/IceGrid/ServerCache.cpp
+++ b/cpp/src/IceGrid/ServerCache.cpp
@@ -59,6 +59,45 @@ namespace IceGrid
ServerCache& _serverCache;
const ServerEntryPtr _entry;
};
+
+
+}
+
+CheckUpdateResult::CheckUpdateResult(const string& server,
+ const string& node,
+ bool noRestart,
+ const Ice::AsyncResultPtr& result) :
+ _server(server), _node(node), _noRestart(noRestart), _result(result)
+{
+}
+
+bool
+CheckUpdateResult::getResult()
+{
+ try
+ {
+ return ServerPrx::uncheckedCast(_result->getProxy())->end_checkUpdate(_result);
+ }
+ catch(const DeploymentException& ex)
+ {
+ ostringstream os;
+ os << "check for server `" << _server << "' update failed: " << ex.reason;
+ throw DeploymentException(os.str());
+ }
+ catch(const Ice::OperationNotExistException&)
+ {
+ if(_noRestart)
+ {
+ throw DeploymentException("server `" + _server + "' doesn't support check for updates");
+ }
+ return false;
+ }
+ catch(const Ice::Exception& ex)
+ {
+ ostringstream os;
+ os << ex;
+ throw NodeUnreachableException(_node, os.str());
+ }
}
ServerCache::ServerCache(const Ice::CommunicatorPtr& communicator,
@@ -77,7 +116,7 @@ ServerCache::ServerCache(const Ice::CommunicatorPtr& communicator,
}
ServerEntryPtr
-ServerCache::add(const ServerInfo& info)
+ServerCache::add(const ServerInfo& info, bool noRestart)
{
Lock sync(*this);
@@ -87,7 +126,7 @@ ServerCache::add(const ServerInfo& info)
entry = new ServerEntry(*this, info.descriptor->id);
addImpl(info.descriptor->id, entry);
}
- entry->update(info);
+ entry->update(info, noRestart);
_nodeCache.get(info.node, true)->addServer(entry);
forEachCommunicator(AddCommunicator(*this, entry, info.application))(info.descriptor);
@@ -211,7 +250,8 @@ ServerEntry::ServerEntry(ServerCache& cache, const string& id) :
_activationTimeout(-1),
_deactivationTimeout(-1),
_synchronizing(false),
- _updated(false)
+ _updated(false),
+ _noRestart(false)
{
}
@@ -273,7 +313,7 @@ ServerEntry::addSyncCallback(const SynchronizationCallbackPtr& callback)
}
void
-ServerEntry::update(const ServerInfo& info)
+ServerEntry::update(const ServerInfo& info, bool noRestart)
{
Lock sync(*this);
@@ -295,6 +335,7 @@ ServerEntry::update(const ServerInfo& info)
}
_load = descriptor;
+ _noRestart = noRestart;
_loaded.reset(0);
_allocatable = info.descriptor->allocatable;
if(info.descriptor->activation == "session")
@@ -528,6 +569,7 @@ ServerEntry::syncImpl()
SessionIPtr session;
ServerInfo destroy;
int timeout = -1;
+ bool noRestart;
{
Lock sync(*this);
@@ -554,6 +596,7 @@ ServerEntry::syncImpl()
load = *_load;
session = _session;
timeout = _deactivationTimeout; // loadServer might block to deactivate the previous server.
+ noRestart = _noRestart;
}
else
{
@@ -578,7 +621,7 @@ ServerEntry::syncImpl()
{
try
{
- _cache.getNodeCache().get(load.node)->loadServer(this, load, session, timeout);
+ _cache.getNodeCache().get(load.node)->loadServer(this, load, session, timeout, noRestart);
}
catch(NodeNotExistException&)
{
@@ -692,6 +735,7 @@ ServerEntry::loadCallback(const ServerPrx& proxy, const AdapterPrxDict& adpts, i
ServerInfo destroy;
int timeout = -1;
bool synced = false;
+ bool noRestart;
{
Lock sync(*this);
@@ -726,6 +770,7 @@ ServerEntry::loadCallback(const ServerPrx& proxy, const AdapterPrxDict& adpts, i
else if(_load.get())
{
load = *_load;
+ noRestart = _noRestart;
session = _session;
timeout = _deactivationTimeout; // loadServer might block to deactivate the previous server.
}
@@ -754,7 +799,7 @@ ServerEntry::loadCallback(const ServerPrx& proxy, const AdapterPrxDict& adpts, i
{
try
{
- _cache.getNodeCache().get(load.node)->loadServer(this, load, session, timeout);
+ _cache.getNodeCache().get(load.node)->loadServer(this, load, session, timeout, noRestart);
}
catch(NodeNotExistException&)
{
@@ -767,6 +812,7 @@ void
ServerEntry::destroyCallback()
{
ServerInfo load;
+ bool noRestart;
SessionIPtr session;
{
@@ -787,6 +833,7 @@ ServerEntry::destroyCallback()
{
_updated = false;
load = *_load;
+ noRestart = _noRestart;
session = _session;
}
}
@@ -795,7 +842,7 @@ ServerEntry::destroyCallback()
{
try
{
- _cache.getNodeCache().get(load.node)->loadServer(this, load, session, -1);
+ _cache.getNodeCache().get(load.node)->loadServer(this, load, session, -1, noRestart);
}
catch(NodeNotExistException&)
{
@@ -814,6 +861,7 @@ ServerEntry::exception(const Ice::Exception& ex)
{
ServerInfo load;
SessionIPtr session;
+ bool noRestart;
bool remove = false;
int timeout = -1;
@@ -836,6 +884,7 @@ ServerEntry::exception(const Ice::Exception& ex)
_destroy.reset(0);
_updated = false;
load = *_load.get();
+ noRestart = _noRestart;
session = _session;
timeout = _deactivationTimeout; // loadServer might block to deactivate the previous server.
}
@@ -845,7 +894,7 @@ ServerEntry::exception(const Ice::Exception& ex)
{
try
{
- _cache.getNodeCache().get(load.node)->loadServer(this, load, session, timeout);
+ _cache.getNodeCache().get(load.node)->loadServer(this, load, session, timeout, noRestart);
}
catch(NodeNotExistException&)
{
@@ -876,6 +925,60 @@ ServerEntry::canRemove()
return !_loaded.get() && !_load.get() && !_destroy.get();
}
+CheckUpdateResultPtr
+ServerEntry::checkUpdate(const ServerInfo& info, bool noRestart)
+{
+ SessionIPtr session;
+ {
+ Lock sync(*this);
+ if(!_loaded.get() && !_load.get())
+ {
+ throw ServerNotExistException();
+ }
+
+ ServerInfo oldInfo = _loaded.get() ? *_loaded : *_load;
+ if(noRestart && info.node != oldInfo.node)
+ {
+ throw DeploymentException("server `" + _id + "' is moved to another node");
+ }
+
+ session = _session;
+ }
+
+ NodeEntryPtr node;
+ try
+ {
+ node = _cache.getNodeCache().get(info.node);
+ }
+ catch(NodeNotExistException&)
+ {
+ throw NodeUnreachableException(info.node, "node is not active");
+ }
+
+ ServerPrx server;
+ try
+ {
+ server = getProxy(true);
+ }
+ catch(const DeploymentException&)
+ {
+ if(noRestart)
+ {
+ // If the server can't be loaded and no restart is required, we throw
+ // to indicate that the server update can't be checked.
+ throw;
+ }
+ else
+ {
+ // Otherwise, we do as if the update is valid.
+ return 0;
+ }
+ }
+
+ InternalServerDescriptorPtr desc = node->getInternalServerDescriptor(info, session);
+ return new CheckUpdateResult(_id, info.node, noRestart, server->begin_checkUpdate(desc, noRestart));
+
+}
void
ServerEntry::allocated(const SessionIPtr& session)
diff --git a/cpp/src/IceGrid/ServerCache.h b/cpp/src/IceGrid/ServerCache.h
index f1db17fa9b6..866ba3652aa 100644
--- a/cpp/src/IceGrid/ServerCache.h
+++ b/cpp/src/IceGrid/ServerCache.h
@@ -29,6 +29,28 @@ class NodeCache;
class NodeEntry;
typedef IceUtil::Handle<NodeEntry> NodeEntryPtr;
+class CheckServerResult;
+typedef IceUtil::Handle<CheckServerResult> CheckServerResultPtr;
+
+class CheckUpdateResult : public IceUtil::Shared
+{
+public:
+
+ CheckUpdateResult(const std::string&, const std::string&, bool, const Ice::AsyncResultPtr&);
+
+ bool getResult();
+
+ const std::string& getServer() { return _server; }
+
+private:
+
+ const std::string _server;
+ const std::string _node;
+ const bool _noRestart;
+ const Ice::AsyncResultPtr _result;
+};
+typedef IceUtil::Handle<CheckUpdateResult> CheckUpdateResultPtr;
+
class ServerEntry : public Allocatable
{
public:
@@ -50,7 +72,8 @@ public:
bool addSyncCallback(const SynchronizationCallbackPtr&);
- void update(const ServerInfo&);
+ void update(const ServerInfo&, bool);
+
void destroy();
ServerInfo getInfo(bool = false) const;
@@ -65,6 +88,7 @@ public:
float getLoad(LoadSample) const;
bool canRemove();
+ CheckUpdateResultPtr checkUpdate(const ServerInfo&, bool);
bool isDestroyed();
void loadCallback(const ServerPrx&, const AdapterPrxDict&, int, int);
@@ -96,6 +120,7 @@ private:
bool _synchronizing;
bool _updated;
+ bool _noRestart;
std::auto_ptr<Ice::Exception> _exception;
std::vector<SynchronizationCallbackPtr> _callbacks;
@@ -114,7 +139,7 @@ public:
ServerCache(const Ice::CommunicatorPtr&, const std::string&, NodeCache&, AdapterCache&, ObjectCache&, AllocatableObjectCache&);
- ServerEntryPtr add(const ServerInfo&);
+ ServerEntryPtr add(const ServerInfo&, bool);
ServerEntryPtr get(const std::string&) const;
bool has(const std::string&) const;
ServerEntryPtr remove(const std::string&, bool = true);
diff --git a/cpp/src/IceGrid/ServerI.cpp b/cpp/src/IceGrid/ServerI.cpp
index 4db7ef92f78..ae530bc5cdb 100755
--- a/cpp/src/IceGrid/ServerI.cpp
+++ b/cpp/src/IceGrid/ServerI.cpp
@@ -121,12 +121,16 @@ chownRecursive(const string& path, uid_t uid, gid_t gid)
#endif
static bool
-descriptorWithoutRevisionEqual(const InternalServerDescriptorPtr& lhs, const InternalServerDescriptorPtr& rhs)
+descriptorUpdated(const InternalServerDescriptorPtr& lhs, const InternalServerDescriptorPtr& rhs, bool noProps = false)
{
+ if(lhs->uuid == rhs->uuid && lhs->revision == rhs->revision)
+ {
+ return false;
+ }
+
if(lhs->id != rhs->id ||
lhs->application != rhs->application ||
lhs->uuid != rhs->uuid ||
-// lhs->revision != rhs->revision ||
lhs->sessionId != rhs->sessionId ||
lhs->exe != rhs->exe ||
lhs->pwd != rhs->pwd ||
@@ -140,25 +144,25 @@ descriptorWithoutRevisionEqual(const InternalServerDescriptorPtr& lhs, const Int
lhs->envs != rhs->envs ||
lhs->logs != rhs->logs)
{
- return false;
+ return true;
}
if((!lhs->distrib && rhs->distrib) || (lhs->distrib && !rhs->distrib))
{
- return false;
+ return true;
}
else if(lhs->distrib && rhs->distrib)
{
if(lhs->distrib->icepatch != rhs->distrib->icepatch ||
lhs->distrib->directories != rhs->distrib->directories)
{
- return false;
+ return true;
}
}
if(lhs->adapters.size() != rhs->adapters.size())
{
- return false;
+ return true;
}
else
{
@@ -167,14 +171,14 @@ descriptorWithoutRevisionEqual(const InternalServerDescriptorPtr& lhs, const Int
{
if((*p)->id != (*q)->id || (*p)->serverLifetime != (*q)->serverLifetime)
{
- return false;
+ return true;
}
}
}
if(lhs->dbEnvs.size() != rhs->dbEnvs.size())
{
- return false;
+ return true;
}
else
{
@@ -183,17 +187,40 @@ descriptorWithoutRevisionEqual(const InternalServerDescriptorPtr& lhs, const Int
{
if((*p)->name != (*q)->name || (*p)->properties != (*q)->properties)
{
- return false;
+ return true;
}
}
}
- if(lhs->properties != rhs->properties)
+ if(!noProps && lhs->properties != rhs->properties)
{
- return false;
+ return true;
}
- return true;
+ return false;
+}
+
+Ice::PropertyDict
+toPropertyDict(const PropertyDescriptorSeq& seq)
+{
+ Ice::PropertyDict props;
+ for(PropertyDescriptorSeq::const_iterator q = seq.begin(); q != seq.end(); ++q)
+ {
+ if(q->value.empty() && q->name.find('#') == 0)
+ {
+ continue; // Ignore comments.
+ }
+
+ if(q->value.empty())
+ {
+ props.erase(q->name);
+ }
+ else
+ {
+ props[q->name] = q->value;
+ }
+ }
+ return props;
}
class CommandTimeoutTimerTask : public IceUtil::TimerTask
@@ -248,6 +275,109 @@ private:
const TraceLevelsPtr _traceLevels;
};
+class ResetPropertiesCB : public IceUtil::Shared
+{
+public:
+
+ ResetPropertiesCB(const ServerIPtr& server,
+ const Ice::ObjectPrx admin,
+ const InternalServerDescriptorPtr& desc,
+ const InternalServerDescriptorPtr& old,
+ const TraceLevelsPtr& traceLevels) :
+ _server(server),
+ _admin(admin),
+ _desc(desc),
+ _traceLevels(traceLevels),
+ _properties(server->getProperties(desc)),
+ _oldProperties(server->getProperties(old)),
+ _p(_properties.begin())
+ {
+ }
+
+ void
+ execute()
+ {
+ assert(_p != _properties.end());
+ next();
+ }
+
+private:
+
+ void
+ next()
+ {
+ while(_p != _properties.end() && _p->second == _oldProperties[_p->first])
+ {
+ ++_p;
+ }
+ if(_p == _properties.end())
+ {
+ _server->updateRuntimePropertiesCallback(_desc);
+ return;
+ }
+
+ Ice::PropertyDict oldProps = toPropertyDict(_oldProperties[_p->first]);
+ Ice::PropertyDict props = toPropertyDict(_p->second);
+ for(Ice::PropertyDict::const_iterator q = oldProps.begin(); q != oldProps.end(); ++q)
+ {
+ if(props.find(q->first) == props.end())
+ {
+ props[q->first] = "";
+ }
+ }
+
+ string facet;
+ if(_p->first == "config")
+ {
+ facet = "Properties";
+ if(_traceLevels->server > 1)
+ {
+ const string id = _server->getId();
+ Ice::Trace out(_traceLevels->logger, _traceLevels->serverCat);
+ out << "updating runtime properties for server `" << id << "'";
+ }
+ }
+ else
+ {
+ assert(_p->first.find("config_") == 0);
+ const string service = _p->first.substr(7);
+ facet = "IceBox.Service." + service + ".Properties";
+ if(_traceLevels->server > 1)
+ {
+ const string id = _server->getId();
+ Ice::Trace out(_traceLevels->logger, _traceLevels->serverCat);
+ out << "updating runtime properties for service `" << service << "' from server `" + id + "'";
+ }
+ }
+
+ //
+ // Increment the iterator *before* invoking setProperties_async to avoid a
+ // race condition.
+ //
+ ++_p;
+
+ Ice::PropertiesAdminPrx p = Ice::PropertiesAdminPrx::uncheckedCast(_admin, facet);
+ p->begin_setProperties(props, Ice::newCallback_PropertiesAdmin_setProperties(this,
+ &ResetPropertiesCB::next,
+ &ResetPropertiesCB::exception));
+ }
+
+ void
+ exception(const Ice::Exception& ex)
+ {
+ _server->updateRuntimePropertiesCallback(ex, _desc);
+ }
+
+ const ServerIPtr _server;
+ const Ice::ObjectPrx _admin;
+ const InternalServerDescriptorPtr _desc;
+ const TraceLevelsPtr _traceLevels;
+ const PropertyDescriptorSeqDict _properties;
+ PropertyDescriptorSeqDict _oldProperties;
+ PropertyDescriptorSeqDict::const_iterator _p;
+};
+typedef IceUtil::Handle<ResetPropertiesCB> ResetPropertiesCBPtr;
+
struct EnvironmentEval : std::unary_function<string, string>
{
@@ -275,7 +405,8 @@ struct EnvironmentEval : std::unary_function<string, string>
break;
}
string variable = v.substr(beg + 1, end - beg - 1);
- DWORD ret = GetEnvironmentVariableW(IceUtil::stringToWstring(variable).c_str(), &buf[0], static_cast<DWORD>(buf.size()));
+ DWORD ret = GetEnvironmentVariableW(IceUtil::stringToWstring(variable).c_str(), &buf[0],
+ static_cast<DWORD>(buf.size()));
string valstr = (ret > 0 && ret < buf.size()) ? IceUtil::wstringToString(&buf[0]) : string("");
v.replace(beg, end - beg + 1, valstr);
beg += valstr.size();
@@ -354,8 +485,10 @@ TimedServerCommand::stopTimer()
}
}
-LoadCommand::LoadCommand(const ServerIPtr& server) :
- ServerCommand(server)
+LoadCommand::LoadCommand(const ServerIPtr& server,
+ const InternalServerDescriptorPtr& runtime,
+ const TraceLevelsPtr& traceLevels) :
+ ServerCommand(server), _runtime(runtime), _updating(false), _traceLevels(traceLevels)
{
}
@@ -403,12 +536,50 @@ LoadCommand::addCallback(const AMD_Node_loadServerPtr& amdCB)
}
void
+LoadCommand::startRuntimePropertiesUpdate(const Ice::ObjectPrx& process)
+{
+ if(_updating)
+ {
+ return;
+ }
+ assert(_desc != _runtime);
+ _updating = true;
+
+ ResetPropertiesCBPtr cb = new ResetPropertiesCB(_server, process, _desc, _runtime, _traceLevels);
+ cb->execute();
+}
+
+bool
+LoadCommand::finishRuntimePropertiesUpdate(const InternalServerDescriptorPtr& runtime, const Ice::ObjectPrx& process)
+{
+ _updating = false;
+ _runtime = runtime; // The new runtime server descriptor.
+
+ if(_traceLevels->server > 0)
+ {
+ Ice::Trace out(_traceLevels->logger, _traceLevels->serverCat);
+ out << "updated runtime properties for server `" << _server->getId() << "'";
+ }
+
+ if(_desc != _runtime)
+ {
+ startRuntimePropertiesUpdate(process);
+ return false;
+ }
+ else
+ {
+ return true;
+ }
+}
+
+void
LoadCommand::failed(const Ice::Exception& ex)
{
for(vector<AMD_Node_loadServerPtr>::const_iterator p = _loadCB.begin(); p != _loadCB.end(); ++p)
{
(*p)->ice_exception(ex);
}
+ _loadCB.clear();
}
void
@@ -418,6 +589,7 @@ LoadCommand::finished(const ServerPrx& proxy, const AdapterPrxDict& adapters, in
{
(*p)->ice_response(proxy, adapters, at, dt);
}
+ _loadCB.clear();
}
DestroyCommand::DestroyCommand(const ServerIPtr& server, bool loadFailure, bool clearDir) :
@@ -659,7 +831,7 @@ ServerI::ServerI(const NodeIPtr& node, const ServerPrx& proxy, const string& ser
_disableOnFailure(0),
_state(ServerI::Inactive),
_activation(ServerI::Disabled),
- _failureTime(IceUtil::Time::now(IceUtil::Time::Monotonic)), // Ensure that _activation gets initialized in updateImpl().
+ _failureTime(IceUtil::Time::now(IceUtil::Time::Monotonic)), // Ensure that _activation is init. in updateImpl().
_pid(0)
{
assert(_node->getActivator());
@@ -1040,7 +1212,8 @@ ServerI::start(ServerActivation activation, const AMD_Server_startPtr& amdCB)
}
ServerCommandPtr
-ServerI::load(const AMD_Node_loadServerPtr& amdCB, const InternalServerDescriptorPtr& desc, const string& replicaName)
+ServerI::load(const AMD_Node_loadServerPtr& amdCB, const InternalServerDescriptorPtr& desc, const string& replicaName,
+ bool noRestart)
{
Lock sync(*this);
checkDestroyed();
@@ -1056,12 +1229,10 @@ ServerI::load(const AMD_Node_loadServerPtr& amdCB, const InternalServerDescripto
// we don't re-load the server. We just return the server
// proxy and the proxies of its adapters.
//
- if(_desc &&
- (replicaName != "Master" || _desc->sessionId == desc->sessionId) &&
- ((_desc->uuid == desc->uuid && _desc->revision == desc->revision) ||
- descriptorWithoutRevisionEqual(_desc, desc)))
+ InternalServerDescriptorPtr d = _load ? _load->getInternalServerDescriptor() : _desc;
+ if(d && (replicaName != "Master" || d->sessionId == desc->sessionId) && !descriptorUpdated(d, desc))
{
- if(_desc->revision != desc->revision)
+ if(d->revision != desc->revision)
{
updateRevision(desc->uuid, desc->revision);
}
@@ -1078,13 +1249,27 @@ ServerI::load(const AMD_Node_loadServerPtr& amdCB, const InternalServerDescripto
return 0;
}
- if(!StopCommand::isStopped(_state) && !_stop)
+ if(!StopCommand::isStopped(_state) && !_stop) // Server is running and no stop is scheduled
{
- _stop = new StopCommand(this, _node->getTimer(), _deactivationTimeout);
+ assert(_desc);
+ if(noRestart)
+ {
+ //
+ // If the server is not inactive, we have to make sure the update doesn't require
+ // a restart. If it requires a restart, we throw. Otherwise we update its properties
+ // now.
+ //
+ checkNoRestart(desc);
+ }
+ else
+ {
+ _stop = new StopCommand(this, _node->getTimer(), _deactivationTimeout);
+ }
}
+
if(!_load)
{
- _load = new LoadCommand(this);
+ _load = new LoadCommand(this, _desc, _node->getTraceLevels());
}
_load->setUpdate(desc, _destroy);
if(_destroy && _state != Destroying)
@@ -1092,13 +1277,64 @@ ServerI::load(const AMD_Node_loadServerPtr& amdCB, const InternalServerDescripto
_destroy->finished();
_destroy = 0;
}
+
if(amdCB)
{
_load->addCallback(amdCB);
}
+
+ if(!_stop && _state == Active) // Must be done after adding the AMD callback.
+ {
+ updateRevision(desc->uuid, desc->revision);
+ _load->startRuntimePropertiesUpdate(_process);
+ }
return nextCommand();
}
+bool
+ServerI::checkUpdate(const InternalServerDescriptorPtr& desc, bool noRestart, const Ice::Current&)
+{
+ Lock sync(*this);
+ checkDestroyed();
+
+ if(!_desc)
+ {
+ throw DeploymentException("server not loaded");
+ }
+
+ InternalServerDescriptorPtr d = _load ? _load->getInternalServerDescriptor() : _desc;
+ if(!descriptorUpdated(d, desc))
+ {
+ return StopCommand::isStopped(_state);
+ }
+
+ if(noRestart)
+ {
+ checkNoRestart(desc);
+ }
+
+ try
+ {
+ checkAndUpdateUser(desc, false); // false = don't update the user, just check.
+ }
+ catch(const Ice::Exception& ex)
+ {
+ ostringstream os;
+ os << ex;
+ throw DeploymentException(os.str());
+ }
+ catch(const string& msg)
+ {
+ throw DeploymentException(msg);
+ }
+ catch(const char* msg)
+ {
+ throw DeploymentException(msg);
+ }
+
+ return StopCommand::isStopped(_state);
+}
+
ServerCommandPtr
ServerI::destroy(const AMD_Node_destroyServerPtr& amdCB, const string& uuid, int revision, const string& replicaName)
{
@@ -1785,6 +2021,12 @@ ServerI::update()
_node->removeServer(this, oldDescriptor->application);
_node->addServer(this, _desc->application);
}
+
+ if(_node->getTraceLevels()->server > 0)
+ {
+ Ice::Trace out(_node->getTraceLevels()->logger, _node->getTraceLevels()->serverCat);
+ out << "updated configuration for server `" << _id << "'";
+ }
}
else
{
@@ -1948,116 +2190,7 @@ ServerI::updateImpl(const InternalServerDescriptorPtr& descriptor)
_timerTask = 0;
}
-#ifndef _WIN32
- _uid = getuid();
- _gid = getgid();
-#endif
-
- //
- // Don't change the user if the server has the session activation
- // mode and if it's not currently owned by a session.
- //
- string user;
- if(_desc->activation != "session" || !_desc->sessionId.empty())
- {
- user = _desc->user;
-#ifndef _WIN32
- //
- // Check if the node is running as root, if that's the case we
- // make sure that a user is set for the process.
- //
- if(_uid == 0 && user.empty())
- {
- //
- // If no user is configured and if this server is owned by
- // a session we set the user to the session id, otherwise
- // we set it to "nobody".
- //
- user = !_desc->sessionId.empty() ? _desc->sessionId : "nobody";
- }
-#endif
- }
-
- if(!user.empty())
- {
- UserAccountMapperPrx mapper = _node->getUserAccountMapper();
- if(mapper)
- {
- try
- {
- user = mapper->getUserAccount(user);
- }
- catch(const UserAccountNotFoundException&)
- {
- throw "couldn't find user account for user `" + user + "'";
- }
- catch(const Ice::LocalException& ex)
- {
- ostringstream os;
- os << "unexpected exception while trying to find user account for user `" << user << "':\n" << ex;
- throw os.str();
- }
- }
-
-#ifdef _WIN32
- //
- // Windows doesn't support running processes under another
- // account (at least not easily, see the CreateProcessAsUser
- // documentation). So if a user is specified, we just check
- // that the node is running under the same user account as the
- // one which is specified.
- //
- vector<char> buf(256);
- buf.resize(256);
- DWORD size = static_cast<DWORD>(buf.size());
- bool success = GetUserName(&buf[0], &size);
- if(!success && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
- {
- buf.resize(size);
- success = GetUserName(&buf[0], &size);
- }
- if(!success)
- {
- Ice::SyscallException ex(__FILE__, __LINE__);
- ex.error = IceInternal::getSystemErrno();
- throw ex;
- }
- if(user != string(&buf[0]))
- {
- throw "couldn't load server under user account `" + user + "': feature not supported on Windows";
- }
-#else
- //
- // Get the uid/gid associated with the given user.
- //
- struct passwd* pw = getpwnam(user.c_str());
- if(!pw)
- {
- throw "unknown user account `" + user + "'";
- }
-
- //
- // If the node isn't running as root and if the uid of the
- // configured user is different from the uid of the userr
- // running the node we throw, a regular user can't run a
- // process as another user.
- //
- if(_uid != 0 && pw->pw_uid != _uid)
- {
- throw "node has insufficient privileges to load server under user account `" + user + "'";
- }
-
-
- if(pw->pw_uid == 0 &&
- _node->getCommunicator()->getProperties()->getPropertyAsInt("IceGrid.Node.AllowRunningServersAsRoot") == 0)
- {
- throw "running server as `root' is not allowed";
- }
-
- _uid = pw->pw_uid;
- _gid = pw->pw_gid;
-#endif
- }
+ checkAndUpdateUser(_desc, true); // we pass true to update _uid/_gid.
istringstream at(_desc->activationTimeout);
if(!(at >> _activationTimeout) || !at.eof() || _activationTimeout == 0)
@@ -2088,58 +2221,10 @@ ServerI::updateImpl(const InternalServerDescriptorPtr& descriptor)
}
sort(_logs.begin(), _logs.begin());
- //
- // Copy the descriptor properties. We shouldn't modify the
- // descriptor since it's used for the comparison when the server
- // needs to be updated.
- //
- PropertyDescriptorSeqDict properties = _desc->properties;
+ PropertyDescriptorSeqDict properties = getProperties(_desc);
PropertyDescriptorSeq& props = properties["config"];
-
- //
- // Cache the path of the stderr/stdout file, first check if the
- // node OutputDir property is set and then we check the server
- // configuration file for the Ice.StdErr and Ice.StdOut
- // properties.
- //
_stdErrFile = getProperty(props, "Ice.StdErr");
_stdOutFile = getProperty(props, "Ice.StdOut");
- string outputDir = _node->getOutputDir();
- if(!outputDir.empty())
- {
- if(_stdErrFile.empty())
- {
- _stdErrFile = outputDir + "/" + _id + (_node->getRedirectErrToOut() ? ".out" : ".err");
- props.push_back(createProperty("Ice.StdErr", _stdErrFile));
- }
- if(_stdOutFile.empty())
- {
- _stdOutFile = outputDir + "/" + _id + ".out";
- props.push_back(createProperty("Ice.StdOut", _stdOutFile));
- }
- }
-
- //
- // Add the locator proxy property and the node properties override
- //
- {
- const PropertyDescriptorSeq& overrides = _node->getPropertiesOverride();
- for(PropertyDescriptorSeqDict::iterator p = properties.begin(); p != properties.end(); ++p)
- {
- if(getProperty(p->second, "Ice.Default.Locator").empty())
- {
- p->second.push_back(
- createProperty("Ice.Default.Locator",
- _node->getCommunicator()->getProperties()->getProperty("Ice.Default.Locator")));
- }
-
- if(!overrides.empty())
- {
- p->second.push_back(createProperty("# Node properties override"));
- p->second.insert(p->second.end(), overrides.begin(), overrides.end());
- }
- }
- }
//
// If the server is a session server and it wasn't udpated but
@@ -2298,7 +2383,12 @@ ServerI::checkRevision(const string& replicaName, const string& uuid, int revisi
string descUUID;
int descRevision;
- if(_desc)
+ if(_load)
+ {
+ descUUID = _load->getInternalServerDescriptor()->uuid;
+ descRevision = _load->getInternalServerDescriptor()->revision;
+ }
+ else if(_desc)
{
descUUID = _desc->uuid;
descRevision = _desc->revision;
@@ -2338,11 +2428,157 @@ ServerI::checkRevision(const string& replicaName, const string& uuid, int revisi
}
void
+ServerI::checkNoRestart(const InternalServerDescriptorPtr& desc)
+{
+ assert(_desc);
+
+ if(_desc->sessionId != desc->sessionId)
+ {
+ throw DeploymentException("server allocated by another session");
+ }
+
+ if(descriptorUpdated(_desc, desc, true)) // true = ignore properties
+ {
+ throw DeploymentException("update requires server to be stopped");
+ }
+}
+
+void
+ServerI::checkAndUpdateUser(const InternalServerDescriptorPtr& desc, bool update)
+{
+#ifndef _WIN32
+ uid_t uid = getuid();
+ uid_t gid = getgid();
+#endif
+
+ //
+ // Don't change the user if the server has the session activation
+ // mode and if it's not currently owned by a session.
+ //
+ string user;
+ if(desc->activation != "session" || !desc->sessionId.empty())
+ {
+ user = desc->user;
+#ifndef _WIN32
+ //
+ // Check if the node is running as root, if that's the case we
+ // make sure that a user is set for the process.
+ //
+ if(uid == 0 && user.empty())
+ {
+ //
+ // If no user is configured and if this server is owned by
+ // a session we set the user to the session id, otherwise
+ // we set it to "nobody".
+ //
+ user = !desc->sessionId.empty() ? desc->sessionId : "nobody";
+ }
+#endif
+ }
+
+ if(!user.empty())
+ {
+ UserAccountMapperPrx mapper = _node->getUserAccountMapper();
+ if(mapper)
+ {
+ try
+ {
+ user = mapper->getUserAccount(user);
+ }
+ catch(const UserAccountNotFoundException&)
+ {
+ throw "couldn't find user account for user `" + user + "'";
+ }
+ catch(const Ice::LocalException& ex)
+ {
+ ostringstream os;
+ os << "unexpected exception while trying to find user account for user `" << user << "':\n" << ex;
+ throw os.str();
+ }
+ }
+
+#ifdef _WIN32
+ //
+ // Windows doesn't support running processes under another
+ // account (at least not easily, see the CreateProcessAsUser
+ // documentation). So if a user is specified, we just check
+ // that the node is running under the same user account as the
+ // one which is specified.
+ //
+ vector<char> buf(256);
+ buf.resize(256);
+ DWORD size = static_cast<DWORD>(buf.size());
+ bool success = GetUserName(&buf[0], &size);
+ if(!success && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
+ {
+ buf.resize(size);
+ success = GetUserName(&buf[0], &size);
+ }
+ if(!success)
+ {
+ Ice::SyscallException ex(__FILE__, __LINE__);
+ ex.error = IceInternal::getSystemErrno();
+ throw ex;
+ }
+ if(user != string(&buf[0]))
+ {
+ throw "couldn't load server under user account `" + user + "': feature not supported on Windows";
+ }
+ }
+#else
+ //
+ // Get the uid/gid associated with the given user.
+ //
+ struct passwd* pw = getpwnam(user.c_str());
+ if(!pw)
+ {
+ throw "unknown user account `" + user + "'";
+ }
+
+ //
+ // If the node isn't running as root and if the uid of the
+ // configured user is different from the uid of the userr
+ // running the node we throw, a regular user can't run a
+ // process as another user.
+ //
+ if(uid != 0 && pw->pw_uid != uid)
+ {
+ throw "node has insufficient privileges to load server under user account `" + user + "'";
+ }
+
+
+ if(pw->pw_uid == 0 &&
+ _node->getCommunicator()->getProperties()->getPropertyAsInt("IceGrid.Node.AllowRunningServersAsRoot") == 0)
+ {
+ throw "running server as `root' is not allowed";
+ }
+
+ if(update)
+ {
+ _uid = pw->pw_uid;
+ _gid = pw->pw_gid;
+ }
+ }
+ else if(update)
+ {
+ _uid = uid;
+ _gid = gid;
+ }
+#endif
+}
+
+void
ServerI::updateRevision(const string& uuid, int revision)
{
_desc->uuid = uuid;
_desc->revision = revision;
+ if(_load)
+ {
+ _load->getInternalServerDescriptor()->uuid = uuid;
+ _load->getInternalServerDescriptor()->revision = revision;
+ }
+
string idFilePath = _serverDir + "/revision";
IceUtilInternal::ofstream os(idFilePath); // idFilePath is a UTF-8 string
if(os.good())
@@ -2355,6 +2591,41 @@ ServerI::updateRevision(const string& uuid, int revision)
}
}
+void
+ServerI::updateRuntimePropertiesCallback(const InternalServerDescriptorPtr& desc)
+{
+ Lock sync(*this);
+ if(_state != Active || !_load)
+ {
+ return;
+ }
+
+ if(_load->finishRuntimePropertiesUpdate(desc, _process))
+ {
+ AdapterPrxDict adapters;
+ for(ServerAdapterDict::const_iterator p = _adapters.begin(); p != _adapters.end(); ++p)
+ {
+ adapters.insert(make_pair(p->first, p->second->getProxy()));
+ }
+ _load->finished(_this, adapters, _activationTimeout, _deactivationTimeout);
+ }
+}
+
+void
+ServerI::updateRuntimePropertiesCallback(const Ice::Exception& ex, const InternalServerDescriptorPtr& desc)
+{
+ Lock sync(*this);
+ if(_state != Active || !_load)
+ {
+ return;
+ }
+
+ if(_load->finishRuntimePropertiesUpdate(desc, _process))
+ {
+ _load->failed(ex);
+ }
+}
+
bool
ServerI::checkActivation()
{
@@ -2469,7 +2740,6 @@ ServerI::setStateNoSync(InternalServerState st, const std::string& reason)
//
InternalServerState previous = _state;
_state = st;
-
//
// Check if some commands are done.
@@ -2617,6 +2887,14 @@ ServerI::setStateNoSync(InternalServerState st, const std::string& reason)
}
}
}
+ else if(_state == Active && _load)
+ {
+ //
+ // If there's a pending load command, it's time to update the
+ // runtime properties of the server now that it's active.
+ //
+ _load->startRuntimePropertiesUpdate(_process);
+ }
//
// Don't send the server update if the state didn't change or if
@@ -2641,8 +2919,11 @@ ServerI::setStateNoSync(InternalServerState st, const std::string& reason)
}
else if(_state == ServerI::Inactive)
{
- Ice::Trace out(_node->getTraceLevels()->logger, _node->getTraceLevels()->serverCat);
- out << "changed server `" << _id << "' state to `Inactive'";
+ if(_node->getTraceLevels()->server != 2 && !(previous == ServerI::Loading || previous == ServerI::Patching))
+ {
+ Ice::Trace out(_node->getTraceLevels()->logger, _node->getTraceLevels()->serverCat);
+ out << "changed server `" << _id << "' state to `Inactive'";
+ }
}
else if(_state == ServerI::Destroyed)
{
@@ -2819,3 +3100,59 @@ ServerI::getFilePath(const string& filename) const
}
}
+PropertyDescriptorSeqDict
+ServerI::getProperties(const InternalServerDescriptorPtr& desc)
+{
+ //
+ // Copy the descriptor properties.
+ //
+ PropertyDescriptorSeqDict properties = desc->properties;
+ PropertyDescriptorSeq& props = properties["config"];
+
+ //
+ // Cache the path of the stderr/stdout file, first check if the
+ // node OutputDir property is set and then we check the server
+ // configuration file for the Ice.StdErr and Ice.StdOut
+ // properties.
+ //
+ string stdErrFile = getProperty(props, "Ice.StdErr");
+ string stdOutFile = getProperty(props, "Ice.StdOut");
+ string outputDir = _node->getOutputDir();
+ if(!outputDir.empty())
+ {
+ if(stdErrFile.empty())
+ {
+ stdErrFile = outputDir + "/" + _id + (_node->getRedirectErrToOut() ? ".out" : ".err");
+ props.push_back(createProperty("Ice.StdErr", stdErrFile));
+ }
+ if(stdOutFile.empty())
+ {
+ stdOutFile = outputDir + "/" + _id + ".out";
+ props.push_back(createProperty("Ice.StdOut", stdOutFile));
+ }
+ }
+
+ //
+ // Add the locator proxy property and the node properties override
+ //
+ {
+ const PropertyDescriptorSeq& overrides = _node->getPropertiesOverride();
+ for(PropertyDescriptorSeqDict::iterator p = properties.begin(); p != properties.end(); ++p)
+ {
+ if(getProperty(p->second, "Ice.Default.Locator").empty())
+ {
+ p->second.push_back(
+ createProperty("Ice.Default.Locator",
+ _node->getCommunicator()->getProperties()->getProperty("Ice.Default.Locator")));
+ }
+
+ if(!overrides.empty())
+ {
+ p->second.push_back(createProperty("# Node properties override"));
+ p->second.insert(p->second.end(), overrides.begin(), overrides.end());
+ }
+ }
+ }
+
+ return properties;
+}
diff --git a/cpp/src/IceGrid/ServerI.h b/cpp/src/IceGrid/ServerI.h
index e40cd51c877..b86d611bf7a 100644
--- a/cpp/src/IceGrid/ServerI.h
+++ b/cpp/src/IceGrid/ServerI.h
@@ -94,7 +94,8 @@ public:
bool dependsOnApplicationDistrib() const;
void start(ServerActivation, const AMD_Server_startPtr& = AMD_Server_startPtr());
- ServerCommandPtr load(const AMD_Node_loadServerPtr&, const InternalServerDescriptorPtr&, const std::string&);
+ ServerCommandPtr load(const AMD_Node_loadServerPtr&, const InternalServerDescriptorPtr&, const std::string&, bool);
+ bool checkUpdate(const InternalServerDescriptorPtr&, bool, const Ice::Current&);
ServerCommandPtr destroy(const AMD_Node_destroyServerPtr&, const std::string&, int, const std::string&);
bool startPatch(bool);
bool waitForPatch();
@@ -117,10 +118,17 @@ public:
//
Ice::ObjectPrx getProcess() const;
+ PropertyDescriptorSeqDict getProperties(const InternalServerDescriptorPtr&);
+
+ void updateRuntimePropertiesCallback(const InternalServerDescriptorPtr&);
+ void updateRuntimePropertiesCallback(const Ice::Exception&, const InternalServerDescriptorPtr&);
+
private:
void updateImpl(const InternalServerDescriptorPtr&);
void checkRevision(const std::string&, const std::string&, int) const;
+ void checkNoRestart(const InternalServerDescriptorPtr&);
+ void checkAndUpdateUser(const InternalServerDescriptorPtr&, bool);
void updateRevision(const std::string&, int);
bool checkActivation();
void checkDestroyed() const;
@@ -299,7 +307,7 @@ class LoadCommand : public ServerCommand
{
public:
- LoadCommand(const ServerIPtr&);
+ LoadCommand(const ServerIPtr&, const InternalServerDescriptorPtr&, const TraceLevelsPtr&);
bool canExecute(ServerI::InternalServerState);
ServerI::InternalServerState nextState();
@@ -309,6 +317,8 @@ public:
bool clearDir() const;
InternalServerDescriptorPtr getInternalServerDescriptor() const;
void addCallback(const AMD_Node_loadServerPtr&);
+ void startRuntimePropertiesUpdate(const Ice::ObjectPrx&);
+ bool finishRuntimePropertiesUpdate(const InternalServerDescriptorPtr&, const Ice::ObjectPrx&);
void failed(const Ice::Exception&);
void finished(const ServerPrx&, const AdapterPrxDict&, int, int);
@@ -317,6 +327,9 @@ private:
std::vector<AMD_Node_loadServerPtr> _loadCB;
bool _clearDir;
InternalServerDescriptorPtr _desc;
+ InternalServerDescriptorPtr _runtime;
+ bool _updating;
+ TraceLevelsPtr _traceLevels;
std::auto_ptr<DeploymentException> _exception;
};