summaryrefslogtreecommitdiff
path: root/cpp
diff options
context:
space:
mode:
Diffstat (limited to 'cpp')
-rwxr-xr-xcpp/include/IcePatch2/ClientUtil.h2
-rw-r--r--cpp/slice/IceGrid/Admin.ice15
-rw-r--r--cpp/slice/IceGrid/Descriptor.ice20
-rw-r--r--cpp/src/IceGrid/AdminI.cpp18
-rw-r--r--cpp/src/IceGrid/AdminI.h1
-rw-r--r--cpp/src/IceGrid/DescriptorBuilder.cpp15
-rw-r--r--cpp/src/IceGrid/DescriptorBuilder.h2
-rw-r--r--cpp/src/IceGrid/DescriptorHelper.cpp28
-rw-r--r--cpp/src/IceGrid/DescriptorParser.cpp22
-rw-r--r--cpp/src/IceGrid/Grammar.y5
-rw-r--r--cpp/src/IceGrid/Internal.ice8
-rw-r--r--cpp/src/IceGrid/NodeI.cpp259
-rw-r--r--cpp/src/IceGrid/NodeI.h13
-rw-r--r--cpp/src/IceGrid/Parser.cpp22
-rw-r--r--cpp/src/IceGrid/Parser.h1
-rw-r--r--cpp/src/IceGrid/Scanner.l4
-rw-r--r--cpp/src/IceGrid/ServerI.cpp129
-rw-r--r--cpp/src/IceGrid/ServerI.h11
-rw-r--r--cpp/src/IceGrid/TraceLevels.cpp3
-rw-r--r--cpp/src/IceGrid/TraceLevels.h3
-rwxr-xr-xcpp/src/IcePatch2/ClientUtil.cpp121
21 files changed, 613 insertions, 89 deletions
diff --git a/cpp/include/IcePatch2/ClientUtil.h b/cpp/include/IcePatch2/ClientUtil.h
index 9a6385d25f6..9d46a1e6ad2 100755
--- a/cpp/include/IcePatch2/ClientUtil.h
+++ b/cpp/include/IcePatch2/ClientUtil.h
@@ -47,6 +47,7 @@ class ICE_PATCH2_API Patcher : public IceUtil::Shared
public:
Patcher(const Ice::CommunicatorPtr&, const PatcherFeedbackPtr&);
+ Patcher(const FileServerPrx&, const PatcherFeedbackPtr&, const std::string&, bool, Ice::Int, Ice::Int);
virtual ~Patcher();
//
@@ -68,6 +69,7 @@ public:
private:
+ void init(const FileServerPrx&);
bool removeFiles(const FileInfoSeq&);
bool updateFiles(const FileInfoSeq&);
bool updateFilesInternal(const FileInfoSeq&, const DecompressorPtr&);
diff --git a/cpp/slice/IceGrid/Admin.ice b/cpp/slice/IceGrid/Admin.ice
index 897d3feb7ae..c446eaa75a2 100644
--- a/cpp/slice/IceGrid/Admin.ice
+++ b/cpp/slice/IceGrid/Admin.ice
@@ -294,6 +294,21 @@ interface Admin
void stopServer(string id)
throws ServerNotExistException, NodeUnreachableException;
+ /**
+ *
+ * Patch a server.
+ *
+ * @param id The id of the server.
+ *
+ * @throws ServerNotExistException Raised if the server is not
+ * found.
+ *
+ * @throws NodeUnreachableException Raised if the node could not be
+ * reached.
+ *
+ **/
+ void patchServer(string id)
+ throws ServerNotExistException, NodeUnreachableException;
/**
*
diff --git a/cpp/slice/IceGrid/Descriptor.ice b/cpp/slice/IceGrid/Descriptor.ice
index 59abb9db591..0c432d837b8 100644
--- a/cpp/slice/IceGrid/Descriptor.ice
+++ b/cpp/slice/IceGrid/Descriptor.ice
@@ -185,6 +185,19 @@ class CommunicatorDescriptor
string description;
};
+struct PatchDescriptor
+{
+ /** The proxy of the IcePatch2 server. */
+ string proxy;
+
+ /** The destination directory. */
+ string destination;
+
+ /** The source directories. */
+ Ice::StringSeq sources;
+};
+sequence<PatchDescriptor> PatchDescriptorSeq;
+
/**
*
* An &Ice; server descriptor.
@@ -250,6 +263,13 @@ class ServerDescriptor extends CommunicatorDescriptor
*
**/
string deactivationTimeout;
+
+ /**
+ *
+ * The patch descriptors.
+ *
+ **/
+ PatchDescriptorSeq patchs;
};
dictionary<string, ServerDescriptor> ServerDescriptorDict;
["java:type:java.util.LinkedList"] sequence<ServerDescriptor> ServerDescriptorSeq;
diff --git a/cpp/src/IceGrid/AdminI.cpp b/cpp/src/IceGrid/AdminI.cpp
index 5aaf9bb8077..e5f5f056844 100644
--- a/cpp/src/IceGrid/AdminI.cpp
+++ b/cpp/src/IceGrid/AdminI.cpp
@@ -160,6 +160,24 @@ AdminI::stopServer(const string& id, const Current&)
}
void
+AdminI::patchServer(const string& id, const Current&)
+{
+ ServerPrx server = _database->getServer(id);
+ try
+ {
+ server->patch();
+ }
+ catch(const Ice::ObjectNotExistException&)
+ {
+ throw ServerNotExistException();
+ }
+ catch(const Ice::LocalException&)
+ {
+ throw NodeUnreachableException();
+ }
+}
+
+void
AdminI::sendSignal(const string& id, const string& signal, const Current&)
{
ServerPrx server = _database->getServer(id);
diff --git a/cpp/src/IceGrid/AdminI.h b/cpp/src/IceGrid/AdminI.h
index 1cd62509607..c294946dbe4 100644
--- a/cpp/src/IceGrid/AdminI.h
+++ b/cpp/src/IceGrid/AdminI.h
@@ -37,6 +37,7 @@ public:
virtual Ice::Int getServerPid(const ::std::string&, const Ice::Current&) const;
virtual bool startServer(const ::std::string&, const Ice::Current&);
virtual void stopServer(const ::std::string&, const Ice::Current&);
+ virtual void patchServer(const ::std::string&, const Ice::Current&);
virtual void sendSignal(const ::std::string&, const ::std::string&, const Ice::Current&);
virtual void writeMessage(const ::std::string&, const ::std::string&, Ice::Int, const Ice::Current&);
virtual Ice::StringSeq getAllServerIds(const Ice::Current&) const;
diff --git a/cpp/src/IceGrid/DescriptorBuilder.cpp b/cpp/src/IceGrid/DescriptorBuilder.cpp
index ed6a80fa6db..9e7d1397ca2 100644
--- a/cpp/src/IceGrid/DescriptorBuilder.cpp
+++ b/cpp/src/IceGrid/DescriptorBuilder.cpp
@@ -437,6 +437,21 @@ ServerDescriptorBuilder::addServiceInstance(const XmlAttributesHelper& desc)
throw "<service-instance> element can only be a child of an <icebox> element";
}
+void
+ServerDescriptorBuilder::addPatch(const XmlAttributesHelper& attrs)
+{
+ PatchDescriptor desc;
+ desc.proxy = attrs("proxy", "");
+ desc.destination = attrs("destination", "");
+ _descriptor->patchs.push_back(desc);
+}
+
+void
+ServerDescriptorBuilder::addPatchDirectory(const string& directory)
+{
+ _descriptor->patchs.back().sources.push_back(directory);
+}
+
IceBoxDescriptorBuilder::IceBoxDescriptorBuilder(const XmlAttributesHelper& attrs)
{
init(new IceBoxDescriptor(), attrs);
diff --git a/cpp/src/IceGrid/DescriptorBuilder.h b/cpp/src/IceGrid/DescriptorBuilder.h
index f992646a590..3bcb8c7498d 100644
--- a/cpp/src/IceGrid/DescriptorBuilder.h
+++ b/cpp/src/IceGrid/DescriptorBuilder.h
@@ -159,6 +159,8 @@ public:
virtual void addEnv(const std::string&);
virtual void addService(const ServiceDescriptorPtr&);
virtual void addServiceInstance(const XmlAttributesHelper&);
+ virtual void addPatch(const XmlAttributesHelper&);
+ virtual void addPatchDirectory(const std::string&);
const ServerDescriptorPtr& getDescriptor() const { return _descriptor; }
diff --git a/cpp/src/IceGrid/DescriptorHelper.cpp b/cpp/src/IceGrid/DescriptorHelper.cpp
index 435ca1d1f12..69c60462dcf 100644
--- a/cpp/src/IceGrid/DescriptorHelper.cpp
+++ b/cpp/src/IceGrid/DescriptorHelper.cpp
@@ -747,6 +747,12 @@ ServerHelper::operator==(const ServerHelper& helper) const
return false;
}
+ if(set<PatchDescriptor>(_desc->patchs.begin(), _desc->patchs.end()) !=
+ set<PatchDescriptor>(helper._desc->patchs.begin(), helper._desc->patchs.end()))
+ {
+ return false;
+ }
+
return true;
}
@@ -779,6 +785,17 @@ ServerHelper::instantiateImpl(const ServerDescriptorPtr& instance, const Resolve
{
instance->envs.push_back(resolve(*p, "environment variable"));
}
+ for(PatchDescriptorSeq::const_iterator p = _desc->patchs.begin(); p != _desc->patchs.end(); ++p)
+ {
+ PatchDescriptor patch;
+ patch.destination = resolve(p->destination, "patch destination directory");
+ patch.proxy = resolve(p->proxy, "patch server proxy");
+ for(Ice::StringSeq::const_iterator q = p->sources.begin(); q != p->sources.end(); ++q)
+ {
+ patch.sources.push_back(resolve(*q, "patch source directory"));
+ }
+ instance->patchs.push_back(patch);
+ }
}
ServerDescriptorPtr
@@ -837,6 +854,17 @@ ServerHelper::printImpl(Output& out, const string& application, const string& no
{
out << nl << "envs = '" << toString(_desc->envs) << "'";
}
+ if(!_desc->patchs.empty())
+ {
+ for(PatchDescriptorSeq::const_iterator p = _desc->patchs.begin(); p != _desc->patchs.end(); ++p)
+ {
+ out << nl << "patch `" << p->destination << "'";
+ out << sb;
+ out << nl << "proxy = '" << p->proxy << "'";
+ out << nl << "sources = " << toString(p->sources);
+ out << eb;
+ }
+ }
CommunicatorHelper::print(out);
}
diff --git a/cpp/src/IceGrid/DescriptorParser.cpp b/cpp/src/IceGrid/DescriptorParser.cpp
index e1f27c1df2b..cb6925fe067 100644
--- a/cpp/src/IceGrid/DescriptorParser.cpp
+++ b/cpp/src/IceGrid/DescriptorParser.cpp
@@ -68,6 +68,7 @@ private:
bool _isTopLevel;
bool _inAdapter;
bool _inDbEnv;
+ bool _inPatch;
};
}
@@ -324,6 +325,15 @@ DescriptorHandler::startElement(const string& name, const IceXML::Attributes& at
_currentCommunicator->addObject(attributes);
}
}
+ else if(name == "patch")
+ {
+ if(!_currentServer.get() || _currentServer.get() != _currentCommunicator)
+ {
+ error("the <patch> element can only be a child of a <server> or <icebox> element");
+ }
+ _currentServer->addPatch(attrs);
+ _inPatch = true;
+ }
else if(name == "dbenv")
{
if(!_currentCommunicator)
@@ -449,6 +459,14 @@ DescriptorHandler::endElement(const string& name, int line, int column)
}
_currentServer->addEnv(elementValue());
}
+ else if(name == "directory")
+ {
+ if(!_inPatch)
+ {
+ error("the <directory> element can only be a child of a <patch> element");
+ }
+ _currentServer->addPatchDirectory(elementValue());
+ }
else if(name == "adapter")
{
_inAdapter = false;
@@ -461,6 +479,10 @@ DescriptorHandler::endElement(const string& name, int line, int column)
{
_inDbEnv = false;
}
+ else if(name == "patch")
+ {
+ _inPatch = false;
+ }
_elements.pop();
}
diff --git a/cpp/src/IceGrid/Grammar.y b/cpp/src/IceGrid/Grammar.y
index 3d320e914c6..6ee5920cf62 100644
--- a/cpp/src/IceGrid/Grammar.y
+++ b/cpp/src/IceGrid/Grammar.y
@@ -48,6 +48,7 @@ yyerror(const char* s)
%token ICE_GRID_STRING
%token ICE_GRID_START
%token ICE_GRID_STOP
+%token ICE_GRID_PATCH
%token ICE_GRID_SIGNAL
%token ICE_GRID_STDOUT
%token ICE_GRID_STDERR
@@ -170,6 +171,10 @@ command
{
parser->stopServer($3);
}
+| ICE_GRID_SERVER ICE_GRID_PATCH strings ';'
+{
+ parser->patchServer($3);
+}
| ICE_GRID_SERVER ICE_GRID_SIGNAL strings ';'
{
parser->signalServer($3);
diff --git a/cpp/src/IceGrid/Internal.ice b/cpp/src/IceGrid/Internal.ice
index 56ae9960be8..67fd3000f6c 100644
--- a/cpp/src/IceGrid/Internal.ice
+++ b/cpp/src/IceGrid/Internal.ice
@@ -131,6 +131,14 @@ interface Server
/**
*
+ * Patch a server. This methods does nothing if the server has no
+ * data to patch.
+ *
+ **/
+ void patch();
+
+ /**
+ *
* Send signal to the server
*
**/
diff --git a/cpp/src/IceGrid/NodeI.cpp b/cpp/src/IceGrid/NodeI.cpp
index 6e423f5ec69..ddcc4859fed 100644
--- a/cpp/src/IceGrid/NodeI.cpp
+++ b/cpp/src/IceGrid/NodeI.cpp
@@ -10,6 +10,7 @@
#include <Ice/Ice.h>
#include <Ice/ProtocolPluginFacade.h> // Just to get the hostname
#include <IcePatch2/Util.h>
+#include <IcePatch2/ClientUtil.h>
#include <IceGrid/NodeI.h>
#include <IceGrid/Activator.h>
#include <IceGrid/ServerI.h>
@@ -21,6 +22,151 @@ using namespace std;
using namespace IcePatch2;
using namespace IceGrid;
+class LogPatcherFeedback : public PatcherFeedback
+{
+public:
+
+ LogPatcherFeedback(const TraceLevelsPtr& traceLevels) :
+ _traceLevels(traceLevels),
+ _startedPatch(false),
+ _lastProgress(0)
+ {
+ }
+
+ void
+ setPatchingPath(const string& path)
+ {
+ _path = path;
+ _startedPatch = false;
+ _lastProgress = 0;
+ }
+
+ virtual bool
+ noFileSummary(const string& reason)
+ {
+ if(_traceLevels->patch > 0)
+ {
+ Ice::Trace out(_traceLevels->logger, _traceLevels->patchCat);
+ out << "Can't load summary file (will perform a thorough patch):\n" << reason;
+ }
+ return true;
+ }
+
+ virtual bool
+ checksumStart()
+ {
+ if(_traceLevels->patch > 0)
+ {
+ Ice::Trace out(_traceLevels->logger, _traceLevels->patchCat);
+ out << "Started checksum calculation";
+ }
+ return true;
+ }
+
+ virtual bool
+ checksumProgress(const string& path)
+ {
+ if(_traceLevels->patch > 2)
+ {
+ Ice::Trace out(_traceLevels->logger, _traceLevels->patchCat);
+ out << "Calculating checksum for " << getBasename(path);
+ }
+ return true;
+ }
+
+ virtual bool
+ checksumEnd()
+ {
+ if(_traceLevels->patch > 0)
+ {
+ Ice::Trace out(_traceLevels->logger, _traceLevels->patchCat);
+ out << "Finished checksum calculation";
+ }
+ return true;
+ }
+
+ virtual bool
+ fileListStart()
+ {
+ if(_traceLevels->patch > 0)
+ {
+ Ice::Trace out(_traceLevels->logger, _traceLevels->patchCat);
+ out << "Getting list of file to patch";
+ }
+ return true;
+ }
+
+ virtual bool
+ fileListProgress(Ice::Int percent)
+ {
+ return true;
+ }
+
+ virtual bool
+ fileListEnd()
+ {
+ if(_traceLevels->patch > 0)
+ {
+ Ice::Trace out(_traceLevels->logger, _traceLevels->patchCat);
+ out << "Getting list of file to patch completed";
+ }
+ return true;
+ }
+
+ virtual bool
+ patchStart(const string& path, Ice::Long size, Ice::Long totalProgress, Ice::Long totalSize)
+ {
+ if(_traceLevels->patch > 1 && totalSize > (1024 * 1024))
+ {
+ int progress = static_cast<int>(static_cast<double>(totalProgress) / totalSize * 100.0);
+ progress /= 5;
+ progress *= 5;
+ if(progress != _lastProgress)
+ {
+ _lastProgress = progress;
+ Ice::Trace out(_traceLevels->logger, _traceLevels->patchCat);
+ out << (_path.empty() ? "Downloaded " : (_path + ": downloaded " ));
+ out << progress << "% (" << totalProgress << '/' << totalSize << ')';
+ }
+ }
+ else if(_traceLevels->patch > 0)
+ {
+ if(!_startedPatch)
+ {
+ Ice::Trace out(_traceLevels->logger, _traceLevels->patchCat);
+ int roundedSize = totalSize / 1024;
+ if(roundedSize == 0 && totalSize > 0)
+ {
+ roundedSize = 1;
+ }
+ out << (_path.empty() ? "Downloading " : (_path + ": downloading " )) << roundedSize << "KB";
+ _startedPatch = true;
+ }
+ }
+
+ return true;
+ }
+
+ virtual bool
+ patchProgress(Ice::Long progress, Ice::Long size, Ice::Long totalProgress, Ice::Long totalSize)
+ {
+ return true;
+ }
+
+ virtual bool
+ patchEnd()
+ {
+ return true;
+ }
+
+private:
+
+ const TraceLevelsPtr _traceLevels;
+ bool _startedPatch;
+ int _lastProgress;
+ string _path;
+};
+
NodeI::NodeI(const Ice::ObjectAdapterPtr& adapter,
const ActivatorPtr& activator,
const WaitQueuePtr& waitQueue,
@@ -67,6 +213,15 @@ NodeI::loadServer(const ServerDescriptorPtr& desc,
current.adapter->add(servant, id);
}
proxy->load(desc, adapters, activationTimeout, deactivationTimeout);
+
+ for(PatchDescriptorSeq::const_iterator p = desc->patchs.begin(); p != desc->patchs.end(); ++p)
+ {
+ PatchDirectory& patch = _directories[p->destination];
+ patch.proxy = _adapter->getCommunicator()->stringToProxy(p->proxy);
+ patch.directories.insert(p->sources.begin(), p->sources.end());
+ patch.servers.insert(ServerIPtr::dynamicCast(servant));
+ }
+
return proxy;
}
@@ -80,7 +235,8 @@ NodeI::destroyServer(const string& name, const Ice::Current& current)
id.category = "IceGridServer";
id.name = name;
- if(!current.adapter->find(id))
+ Ice::ObjectPtr servant = current.adapter->find(id);
+ if(!servant)
{
try
{
@@ -97,7 +253,21 @@ NodeI::destroyServer(const string& name, const Ice::Current& current)
ServerPrx proxy = ServerPrx::uncheckedCast(current.adapter->createProxy(id));
try
{
+ ServerDescriptorPtr desc = proxy->getDescriptor();
proxy->destroy();
+ for(PatchDescriptorSeq::const_iterator p = desc->patchs.begin(); p != desc->patchs.end(); ++p)
+ {
+ PatchDirectory& patch = _directories[p->destination];
+ for(Ice::StringSeq::const_iterator q = p->sources.begin(); q != p->sources.end(); ++q)
+ {
+ patch.directories.erase(*q);
+ }
+ patch.servers.erase(ServerIPtr::dynamicCast(servant));
+ if(patch.servers.empty())
+ {
+ _directories.erase(p->destination);
+ }
+ }
}
catch(const Ice::LocalException&)
{
@@ -123,6 +293,93 @@ NodeI::shutdown(const Ice::Current&) const
_activator->shutdown();
}
+void
+NodeI::patch(const ServerIPtr& server, const string& directory) const
+{
+ Lock sync(*this);
+ map<string, PatchDirectory>::const_iterator p = _directories.find(directory);
+ assert(p != _directories.end());
+
+ const PatchDirectory& patch = p->second;
+
+ for(set<ServerIPtr>::const_iterator p = patch.servers.begin(); p != patch.servers.end(); ++p)
+ {
+ if(*p != server)
+ {
+ (*p)->startUpdating();
+ }
+ }
+
+ try
+ {
+ FileServerPrx server = FileServerPrx::checkedCast(patch.proxy);
+ if(!server)
+ {
+ throw "proxy `" + getCommunicator()->proxyToString(patch.proxy) + "' is not a file server.";
+ }
+
+ PatcherFeedbackPtr feedback = new LogPatcherFeedback(_traceLevels);
+ PatcherPtr patcher = new Patcher(server, feedback, directory, false, 100, 0);
+ bool aborted = !patcher->prepare();
+ if(!aborted)
+ {
+ if(patch.directories.empty())
+ {
+ aborted = !patcher->patch("");
+ }
+ else
+ {
+ vector<string> sources;
+ copy(patch.directories.begin(), patch.directories.end(), back_inserter(sources));
+ for(vector<string>::const_iterator p = sources.begin(); p != sources.end(); ++p)
+ {
+ dynamic_cast<LogPatcherFeedback*>(feedback.get())->setPatchingPath(*p);
+ if(!patcher->patch(*p))
+ {
+ aborted = true;
+ break;
+ }
+ }
+ }
+ }
+
+ if(!aborted)
+ {
+ patcher->finish();
+ }
+ }
+ catch(const Ice::LocalException& ex)
+ {
+ ostringstream os;
+ os << "patch for `" + directory + "' failed:\n";
+ os << ex;
+ _traceLevels->logger->warning(os.str());
+ }
+ catch(const string& ex)
+ {
+ _traceLevels->logger->error("patch for `" + directory + "' failed:\n" + ex);
+ }
+ catch(...)
+ {
+ for(set<ServerIPtr>::const_iterator p = patch.servers.begin(); p != patch.servers.end(); ++p)
+ {
+ if(*p != server)
+ {
+ (*p)->finishUpdating();
+ }
+ }
+ throw;
+ }
+
+ for(set<ServerIPtr>::const_iterator p = patch.servers.begin(); p != patch.servers.end(); ++p)
+ {
+ if(*p != server)
+ {
+ (*p)->finishUpdating();
+ }
+ }
+}
+
Ice::CommunicatorPtr
NodeI::getCommunicator() const
{
diff --git a/cpp/src/IceGrid/NodeI.h b/cpp/src/IceGrid/NodeI.h
index 93ae5b6f2f2..2fa191aa4e5 100644
--- a/cpp/src/IceGrid/NodeI.h
+++ b/cpp/src/IceGrid/NodeI.h
@@ -22,6 +22,9 @@ typedef IceUtil::Handle<TraceLevels> TraceLevelsPtr;
class Activator;
typedef IceUtil::Handle<Activator> ActivatorPtr;
+class ServerI;
+typedef IceUtil::Handle<ServerI> ServerIPtr;
+
class NodeI : public Node, public IceUtil::Mutex
{
public:
@@ -36,6 +39,8 @@ public:
virtual std::string getHostname(const Ice::Current& = Ice::Current()) const;
virtual void shutdown(const Ice::Current&) const;
+ virtual void patch(const ServerIPtr&, const std::string&) const;
+
WaitQueuePtr getWaitQueue() const;
Ice::CommunicatorPtr getCommunicator() const;
ActivatorPtr getActivator() const;
@@ -68,6 +73,14 @@ private:
NodeObserverPrx _observer;
IceUtil::Mutex _sessionMutex;
NodeSessionPrx _session;
+
+ struct PatchDirectory
+ {
+ Ice::ObjectPrx proxy;
+ std::multiset<std::string> directories;
+ std::set<ServerIPtr> servers;
+ };
+ std::map<std::string, PatchDirectory> _directories;
};
typedef IceUtil::Handle<NodeI> NodeIPtr;
diff --git a/cpp/src/IceGrid/Parser.cpp b/cpp/src/IceGrid/Parser.cpp
index 37354769302..bf6331999ff 100644
--- a/cpp/src/IceGrid/Parser.cpp
+++ b/cpp/src/IceGrid/Parser.cpp
@@ -89,6 +89,7 @@ Parser::usage()
"server pid ID Get server ID pid.\n"
"server start ID Start server ID.\n"
"server stop ID Stop server ID.\n"
+ "server patch ID Patch server ID.\n"
"server signal ID SIGNAL Send SIGNAL (e.g. SIGTERM or 15) to server ID.\n"
"server stdout ID MESSAGE Write MESSAGE on server ID's stdout.\n"
"server stderr ID MESSAGE Write MESSAGE on server ID's stderr.\n"
@@ -696,6 +697,27 @@ Parser::stopServer(const list<string>& args)
}
void
+Parser::patchServer(const list<string>& args)
+{
+ if(args.size() != 1)
+ {
+ error("`server patch' requires exactly one argument\n(`help' for more info)");
+ return;
+ }
+
+ try
+ {
+ _admin->patchServer(args.front());
+ }
+ catch(const Ice::Exception& ex)
+ {
+ ostringstream s;
+ s << ex;
+ error(s.str());
+ }
+}
+
+void
Parser::signalServer(const list<string>& args)
{
if(args.size() != 2)
diff --git a/cpp/src/IceGrid/Parser.h b/cpp/src/IceGrid/Parser.h
index a07954adc99..b7d0b350083 100644
--- a/cpp/src/IceGrid/Parser.h
+++ b/cpp/src/IceGrid/Parser.h
@@ -86,6 +86,7 @@ public:
void removeServer(const std::list<std::string>&);
void startServer(const std::list<std::string>&);
void stopServer(const std::list<std::string>&);
+ void patchServer(const std::list<std::string>&);
void signalServer(const std::list<std::string>&);
void writeMessage(const std::list<std::string>&, int fd);
void describeServer(const std::list<std::string>&);
diff --git a/cpp/src/IceGrid/Scanner.l b/cpp/src/IceGrid/Scanner.l
index 2eebcafef56..cbe7451d0d0 100644
--- a/cpp/src/IceGrid/Scanner.l
+++ b/cpp/src/IceGrid/Scanner.l
@@ -149,6 +149,10 @@ NL [\n]
return ICE_GRID_START;
}
+"patch" {
+ return ICE_GRID_PATCH;
+}
+
"stop" {
return ICE_GRID_STOP;
}
diff --git a/cpp/src/IceGrid/ServerI.cpp b/cpp/src/IceGrid/ServerI.cpp
index 2d186d58be7..e71c3906201 100644
--- a/cpp/src/IceGrid/ServerI.cpp
+++ b/cpp/src/IceGrid/ServerI.cpp
@@ -86,40 +86,29 @@ void
ServerI::load(const ServerDescriptorPtr& descriptor, StringAdapterPrxDict& adapters, int& activationTimeout,
int& deactivationTimeout, const Ice::Current& current)
{
- while(true)
- {
- {
- Lock sync(*this);
- if(_state == ServerI::Destroying || _state == ServerI::Destroyed)
- {
- Ice::ObjectNotExistException ex(__FILE__,__LINE__);
- ex.id = _this->ice_getIdentity();
- throw ex;
- }
- else if(_state == ServerI::Inactive)
- {
- //
- // If the server is inactive we can update its descriptor and its directory.
- //
- try
- {
- update(descriptor, adapters, activationTimeout, deactivationTimeout, current);
- }
- catch(const string& msg)
- {
- DeploymentException ex;
- ex.reason = msg;
- throw ex;
- }
- return;
- }
- }
+ startUpdating();
- //
- // If the server is active we stop it and try again to update it.
- //
- stop(current);
+ //
+ // If the server is inactive we can update its descriptor and its directory.
+ //
+ try
+ {
+ update(descriptor, adapters, activationTimeout, deactivationTimeout, current);
+ }
+ catch(const string& msg)
+ {
+ finishUpdating();
+ DeploymentException ex;
+ ex.reason = msg;
+ throw ex;
}
+ catch(...)
+ {
+ finishUpdating();
+ throw;
+ }
+
+ finishUpdating();
}
void
@@ -129,7 +118,7 @@ ServerI::start_async(const AMD_Server_startPtr& amdCB, const Ice::Current& curre
}
void
-ServerI::stop(const Ice::Current& current)
+ServerI::stop(const Ice::Current&)
{
while(true)
{
@@ -137,6 +126,7 @@ ServerI::stop(const Ice::Current& current)
switch(_state)
{
case ServerI::Inactive:
+ case ServerI::Updating:
{
return;
}
@@ -165,7 +155,30 @@ ServerI::stop(const Ice::Current& current)
break;
}
- stopInternal(false, current);
+ stopInternal(false);
+}
+
+void
+ServerI::patch(const ::Ice::Current& current)
+{
+ //
+ // Patch the server data.
+ //
+ startUpdating();
+ try
+ {
+ ServerDescriptorPtr desc = getDescriptor(current);
+ for(PatchDescriptorSeq::const_iterator p = desc->patchs.begin(); p != desc->patchs.end(); ++p)
+ {
+ _node->patch(this, p->destination);
+ }
+ }
+ catch(...)
+ {
+ finishUpdating();
+ throw;
+ }
+ finishUpdating();
}
void
@@ -214,6 +227,7 @@ ServerI::destroy(const Ice::Current& current)
}
case ServerI::Activating:
case ServerI::Deactivating:
+ case ServerI::Updating:
{
wait(); // TODO: Timeout?
continue;
@@ -233,7 +247,7 @@ ServerI::destroy(const Ice::Current& current)
if(stop)
{
- stopInternal(true, current);
+ stopInternal(true);
}
//
@@ -280,6 +294,7 @@ ServerI::terminated(const Ice::Current& current)
switch(_state)
{
case ServerI::Inactive:
+ case ServerI::Updating:
{
assert(false);
}
@@ -416,6 +431,7 @@ ServerI::startInternal(ServerActivation act, const AMD_Server_startPtr& amdCB)
}
case ServerI::Activating:
case ServerI::Deactivating:
+ case ServerI::Updating:
{
wait(); // TODO: Timeout?
continue;
@@ -596,6 +612,46 @@ ServerI::addDynamicInfo(ServerDynamicInfoSeq& serverInfos, AdapterDynamicInfoSeq
}
void
+ServerI::startUpdating()
+{
+ while(true)
+ {
+ {
+ Lock sync(*this);
+ if(_state == ServerI::Destroying || _state == ServerI::Destroyed)
+ {
+ Ice::ObjectNotExistException ex(__FILE__,__LINE__);
+ ex.id = _this->ice_getIdentity();
+ throw ex;
+ }
+ else if(_state == ServerI::Updating)
+ {
+ wait(); // Only one update at a time!
+ }
+ else if(_state == ServerI::Inactive)
+ {
+ _state = ServerI::Updating;
+ return;
+ }
+ }
+
+ //
+ // If the server is active we stop it and try again to update it.
+ //
+ stop();
+ }
+}
+
+void
+ServerI::finishUpdating()
+{
+ Lock sync(*this);
+ assert(_state == ServerI::Updating);
+ _state = ServerI::Inactive;
+ notifyAll();
+}
+
+void
ServerI::checkActivation()
{
//assert(locked());
@@ -615,7 +671,7 @@ ServerI::checkActivation()
}
void
-ServerI::stopInternal(bool kill, const Ice::Current& current)
+ServerI::stopInternal(bool kill)
{
Ice::ProcessPrx process;
if(!kill)
@@ -818,6 +874,7 @@ void
ServerI::update(const ServerDescriptorPtr& descriptor, StringAdapterPrxDict& adapters, int& activationTimeout,
int& deactivationTimeout, const Ice::Current& current)
{
+ Lock sync(*this);
_desc = descriptor;
_serverDir = _serversDir + "/" + descriptor->id;
_activation = descriptor->activation == "on-demand" ? OnDemand : Manual;
diff --git a/cpp/src/IceGrid/ServerI.h b/cpp/src/IceGrid/ServerI.h
index ec33397284d..b1ac019b8be 100644
--- a/cpp/src/IceGrid/ServerI.h
+++ b/cpp/src/IceGrid/ServerI.h
@@ -37,7 +37,8 @@ public:
Active,
Deactivating,
Destroying,
- Destroyed
+ Destroyed,
+ Updating
};
ServerI(const NodeIPtr&, const ServerPrx&, const std::string&, const std::string&, int);
@@ -45,7 +46,8 @@ public:
virtual void load(const ServerDescriptorPtr&, StringAdapterPrxDict&, int&, int&, const Ice::Current&);
virtual void start_async(const AMD_Server_startPtr&, const ::Ice::Current&);
- virtual void stop(const ::Ice::Current&);
+ virtual void stop(const ::Ice::Current& = Ice::Current());
+ virtual void patch(const ::Ice::Current&);
virtual void sendSignal(const std::string&, const ::Ice::Current&);
virtual void writeMessage(const std::string&, Ice::Int, const ::Ice::Current&);
virtual void destroy(const ::Ice::Current&);
@@ -65,10 +67,13 @@ public:
void activationFailed(bool);
void addDynamicInfo(ServerDynamicInfoSeq&, AdapterDynamicInfoSeq&) const;
+ void startUpdating();
+ void finishUpdating();
+
private:
void checkActivation();
- void stopInternal(bool, const Ice::Current&);
+ void stopInternal(bool);
void setState(InternalServerState);
void setStateNoSync(InternalServerState);
diff --git a/cpp/src/IceGrid/TraceLevels.cpp b/cpp/src/IceGrid/TraceLevels.cpp
index ec4e913b83b..fa0f2aa90a0 100644
--- a/cpp/src/IceGrid/TraceLevels.cpp
+++ b/cpp/src/IceGrid/TraceLevels.cpp
@@ -26,6 +26,8 @@ TraceLevels::TraceLevels(const Ice::PropertiesPtr& properties, const Ice::Logger
objectCat("Object"),
activator(0),
activatorCat("Activator"),
+ patch(0),
+ patchCat("Patch"),
logger(theLogger)
{
string keyBase = isNode ? "IceGrid.Node.Trace." : "IceGrid.Registry.Trace.";
@@ -35,6 +37,7 @@ TraceLevels::TraceLevels(const Ice::PropertiesPtr& properties, const Ice::Logger
const_cast<int&>(adapter) = properties->getPropertyAsInt(keyBase + adapterCat);
const_cast<int&>(object) = properties->getPropertyAsInt(keyBase + objectCat);
const_cast<int&>(activator) = properties->getPropertyAsInt(keyBase + activatorCat);
+ const_cast<int&>(patch) = properties->getPropertyAsInt(keyBase + patchCat);
}
TraceLevels::~TraceLevels()
diff --git a/cpp/src/IceGrid/TraceLevels.h b/cpp/src/IceGrid/TraceLevels.h
index d462f16a149..4a5b42a482f 100644
--- a/cpp/src/IceGrid/TraceLevels.h
+++ b/cpp/src/IceGrid/TraceLevels.h
@@ -42,6 +42,9 @@ public:
const int activator;
const char* activatorCat;
+ const int patch;
+ const char* patchCat;
+
const Ice::LoggerPtr logger;
};
diff --git a/cpp/src/IcePatch2/ClientUtil.cpp b/cpp/src/IcePatch2/ClientUtil.cpp
index 522fbfdef53..220a03a4056 100755
--- a/cpp/src/IcePatch2/ClientUtil.cpp
+++ b/cpp/src/IcePatch2/ClientUtil.cpp
@@ -147,52 +147,6 @@ IcePatch2::Patcher::Patcher(const CommunicatorPtr& communicator, const PatcherFe
_chunkSize(communicator->getProperties()->getPropertyAsIntWithDefault("IcePatch2.ChunkSize", 100)),
_remove(communicator->getProperties()->getPropertyAsIntWithDefault("IcePatch2.Remove", 1))
{
- if(_dataDir.empty())
- {
- throw string("no data directory specified");
- }
-
- //
- // Make sure that _chunkSize doesn't exceed MessageSizeMax, otherwise
- // it won't work at all.
- //
- int sizeMax = communicator->getProperties()->getPropertyAsIntWithDefault("Ice.MessageSizeMax", 1024);
- if(_chunkSize < 1)
- {
- const_cast<Int&>(_chunkSize) = 1;
- }
- else if(_chunkSize > sizeMax)
- {
- const_cast<Int&>(_chunkSize) = sizeMax;
- }
- if(_chunkSize == sizeMax)
- {
- const_cast<Int&>(_chunkSize) = _chunkSize * 1024 - 512; // Leave some headroom for protocol header.
- }
- else
- {
- const_cast<Int&>(_chunkSize) *= 1024;
- }
-
- if(!isAbsolute(_dataDir))
- {
-#ifdef _WIN32
- char cwd[_MAX_PATH];
- if(_getcwd(cwd, _MAX_PATH) == NULL)
- {
- throw "cannot get the current directory:\n" + lastError();
- }
-#else
- char cwd[PATH_MAX];
- if(getcwd(cwd, PATH_MAX) == NULL)
- {
- throw "cannot get the current directory:\n" + lastError();
- }
-#endif
-
- const_cast<string&>(_dataDir) = simplify(string(cwd) + '/' + _dataDir);
- }
-
PropertiesPtr properties = communicator->getProperties();
const char* endpointsProperty = "IcePatch2.Endpoints";
@@ -206,12 +160,28 @@ IcePatch2::Patcher::Patcher(const CommunicatorPtr& communicator, const PatcherFe
const Identity id = stringToIdentity(properties->getPropertyWithDefault(idProperty, "IcePatch2/server"));
ObjectPrx serverBase = communicator->stringToProxy(identityToString(id) + ':' + endpoints);
- const_cast<FileServerPrx&>(_serverCompress) = FileServerPrx::checkedCast(serverBase->ice_compress(true));
- if(!_serverCompress)
+ FileServerPrx server = FileServerPrx::checkedCast(serverBase);
+ if(!server)
{
throw "proxy `" + identityToString(id) + ':' + endpoints + "' is not a file server.";
}
- const_cast<FileServerPrx&>(_serverNoCompress) = FileServerPrx::checkedCast(_serverCompress->ice_compress(false));
+
+ init(server);
+}
+
+IcePatch2::Patcher::Patcher(const FileServerPrx& server,
+ const PatcherFeedbackPtr& feedback,
+ const string& dataDir,
+ bool thorough,
+ Ice::Int chunkSize,
+ Ice::Int remove) :
+ _feedback(feedback),
+ _dataDir(simplify(dataDir)),
+ _thorough(thorough),
+ _chunkSize(chunkSize),
+ _remove(remove)
+{
+ init(server);
}
IcePatch2::Patcher::~Patcher()
@@ -533,6 +503,59 @@ IcePatch2::Patcher::finish()
saveFileInfoSeq(_dataDir, _localFiles);
}
+void
+IcePatch2::Patcher::init(const FileServerPrx& server)
+{
+ if(_dataDir.empty())
+ {
+ throw string("no data directory specified");
+ }
+
+ //
+ // Make sure that _chunkSize doesn't exceed MessageSizeMax, otherwise
+ // it won't work at all.
+ //
+ int sizeMax = server->ice_communicator()->getProperties()->getPropertyAsIntWithDefault("Ice.MessageSizeMax", 1024);
+ if(_chunkSize < 1)
+ {
+ const_cast<Int&>(_chunkSize) = 1;
+ }
+ else if(_chunkSize > sizeMax)
+ {
+ const_cast<Int&>(_chunkSize) = sizeMax;
+ }
+ if(_chunkSize == sizeMax)
+ {
+ const_cast<Int&>(_chunkSize) = _chunkSize * 1024 - 512; // Leave some headroom for protocol header.
+ }
+ else
+ {
+ const_cast<Int&>(_chunkSize) *= 1024;
+ }
+
+ if(!isAbsolute(_dataDir))
+ {
+#ifdef _WIN32
+ char cwd[_MAX_PATH];
+ if(_getcwd(cwd, _MAX_PATH) == NULL)
+ {
+ throw "cannot get the current directory:\n" + lastError();
+ }
+#else
+ char cwd[PATH_MAX];
+ if(getcwd(cwd, PATH_MAX) == NULL)
+ {
+ throw "cannot get the current directory:\n" + lastError();
+ }
+#endif
+
+ const_cast<string&>(_dataDir) = simplify(string(cwd) + '/' + _dataDir);
+ }
+
+ const_cast<FileServerPrx&>(_serverCompress) = FileServerPrx::uncheckedCast(server->ice_compress(true));
+ const_cast<FileServerPrx&>(_serverNoCompress) = FileServerPrx::uncheckedCast(server->ice_compress(false));
+}
+
bool
IcePatch2::Patcher::removeFiles(const FileInfoSeq& files)
{