diff options
author | Benoit Foucher <benoit@zeroc.com> | 2005-08-19 14:35:34 +0000 |
---|---|---|
committer | Benoit Foucher <benoit@zeroc.com> | 2005-08-19 14:35:34 +0000 |
commit | 03fb156e997f64dd80d695d34c4eaeefc4ca0956 (patch) | |
tree | cb63867223b81f0fd8db37c22e8c5de450a32ae3 /cpp/src | |
parent | bug fix (diff) | |
download | ice-03fb156e997f64dd80d695d34c4eaeefc4ca0956.tar.bz2 ice-03fb156e997f64dd80d695d34c4eaeefc4ca0956.tar.xz ice-03fb156e997f64dd80d695d34c4eaeefc4ca0956.zip |
Added initial IcePatch2 support in IceGrid.
Diffstat (limited to 'cpp/src')
-rw-r--r-- | cpp/src/IceGrid/AdminI.cpp | 18 | ||||
-rw-r--r-- | cpp/src/IceGrid/AdminI.h | 1 | ||||
-rw-r--r-- | cpp/src/IceGrid/DescriptorBuilder.cpp | 15 | ||||
-rw-r--r-- | cpp/src/IceGrid/DescriptorBuilder.h | 2 | ||||
-rw-r--r-- | cpp/src/IceGrid/DescriptorHelper.cpp | 28 | ||||
-rw-r--r-- | cpp/src/IceGrid/DescriptorParser.cpp | 22 | ||||
-rw-r--r-- | cpp/src/IceGrid/Grammar.y | 5 | ||||
-rw-r--r-- | cpp/src/IceGrid/Internal.ice | 8 | ||||
-rw-r--r-- | cpp/src/IceGrid/NodeI.cpp | 259 | ||||
-rw-r--r-- | cpp/src/IceGrid/NodeI.h | 13 | ||||
-rw-r--r-- | cpp/src/IceGrid/Parser.cpp | 22 | ||||
-rw-r--r-- | cpp/src/IceGrid/Parser.h | 1 | ||||
-rw-r--r-- | cpp/src/IceGrid/Scanner.l | 4 | ||||
-rw-r--r-- | cpp/src/IceGrid/ServerI.cpp | 129 | ||||
-rw-r--r-- | cpp/src/IceGrid/ServerI.h | 11 | ||||
-rw-r--r-- | cpp/src/IceGrid/TraceLevels.cpp | 3 | ||||
-rw-r--r-- | cpp/src/IceGrid/TraceLevels.h | 3 | ||||
-rwxr-xr-x | cpp/src/IcePatch2/ClientUtil.cpp | 121 |
18 files changed, 576 insertions, 89 deletions
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) { |