diff options
author | Benoit Foucher <benoit@zeroc.com> | 2007-06-12 15:42:23 +0200 |
---|---|---|
committer | Benoit Foucher <benoit@zeroc.com> | 2007-06-12 15:42:23 +0200 |
commit | 607a0c7f320dacb590d0816ab0b121a2b6c784e7 (patch) | |
tree | c576a0ab9e31b1e57f66c4a85c457331e1889230 /cpp | |
parent | Support for Sun Studio 12 (CC 5.9) (diff) | |
download | ice-607a0c7f320dacb590d0816ab0b121a2b6c784e7.tar.bz2 ice-607a0c7f320dacb590d0816ab0b121a2b6c784e7.tar.xz ice-607a0c7f320dacb590d0816ab0b121a2b6c784e7.zip |
Fixed bug 2220
Diffstat (limited to 'cpp')
-rw-r--r-- | cpp/CHANGES | 5 | ||||
-rw-r--r-- | cpp/src/IceGrid/AdapterCache.cpp | 36 | ||||
-rw-r--r-- | cpp/src/IceGrid/AdapterCache.h | 1 | ||||
-rw-r--r-- | cpp/src/IceGrid/Database.cpp | 101 | ||||
-rw-r--r-- | cpp/src/IceGrid/Database.h | 3 | ||||
-rw-r--r-- | cpp/src/IceGrid/DescriptorHelper.cpp | 90 | ||||
-rw-r--r-- | cpp/src/IceGrid/DescriptorHelper.h | 6 | ||||
-rw-r--r-- | cpp/test/IceGrid/replicaGroup/AllTests.cpp | 151 |
8 files changed, 380 insertions, 13 deletions
diff --git a/cpp/CHANGES b/cpp/CHANGES index 52926d60a6e..1a9d6f785e5 100644 --- a/cpp/CHANGES +++ b/cpp/CHANGES @@ -1,6 +1,10 @@ Changes since version 3.2.X (binary incompabible) ------------------------------------------------- +- IceGrid now allows defining an object adapter with a replica group + from an other IceGrid application than the one where the object + adapter is defined. + - Added a new method to the ObjectAdapter interface named refreshPublishedEndpoints(). This method is meant to be used to update the published endpoints after change in the available local @@ -2752,3 +2756,4 @@ Changes since version 1.0.0 - Several other changes that make Ice for C++ more portable. - Updated SSL test certificates. The old ones have expired. + diff --git a/cpp/src/IceGrid/AdapterCache.cpp b/cpp/src/IceGrid/AdapterCache.cpp index a16d205c425..e3bf7562803 100644 --- a/cpp/src/IceGrid/AdapterCache.cpp +++ b/cpp/src/IceGrid/AdapterCache.cpp @@ -93,7 +93,11 @@ AdapterCache::addServerAdapter(const AdapterDescriptor& desc, const ServerEntryP if(!desc.replicaGroupId.empty()) { ReplicaGroupEntryPtr repEntry = ReplicaGroupEntryPtr::dynamicCast(getImpl(desc.replicaGroupId)); - assert(repEntry); + if(!repEntry) + { + Ice::Error out(_communicator->getLogger()); + out << "can't add adapter `" << desc.id << "' to unknown replica group `" << desc.replicaGroupId << "'"; + } repEntry->addReplica(desc.id, entry); } } @@ -142,7 +146,11 @@ AdapterCache::removeServerAdapter(const string& id) if(!replicaGroupId.empty()) { ReplicaGroupEntryPtr repEntry = ReplicaGroupEntryPtr::dynamicCast(getImpl(replicaGroupId)); - assert(repEntry); + if(!repEntry) + { + Ice::Error out(_communicator->getLogger()); + out << "can't remove adapter `" << id << "' from unknown replica group `" << replicaGroupId << "'"; + } repEntry->removeReplica(id); } } @@ -483,6 +491,10 @@ ReplicaGroupEntry::getLeastLoadedNodeLoad(LoadSample loadSample) const AdapterInfoSeq ReplicaGroupEntry::getAdapterInfo() const { + // + // This method is called with the database locked so we're sure + // that no new adapters will be added or removed concurrently. + // vector<ServerAdapterEntryPtr> replicas; { Lock sync(*this); @@ -498,3 +510,23 @@ ReplicaGroupEntry::getAdapterInfo() const } return infos; } + +bool +ReplicaGroupEntry::hasAdaptersFromOtherApplications() const +{ + vector<ServerAdapterEntryPtr> replicas; + { + Lock sync(*this); + replicas = _replicas; + } + + AdapterInfoSeq infos; + for(vector<ServerAdapterEntryPtr>::const_iterator p = replicas.begin(); p != replicas.end(); ++p) + { + if((*p)->getApplication() != _application) + { + return true; + } + } + return false; +} diff --git a/cpp/src/IceGrid/AdapterCache.h b/cpp/src/IceGrid/AdapterCache.h index 451b434f2b4..cddd18b7f72 100644 --- a/cpp/src/IceGrid/AdapterCache.h +++ b/cpp/src/IceGrid/AdapterCache.h @@ -97,6 +97,7 @@ public: void removeReplica(const std::string&); void update(const LoadBalancingPolicyPtr&); + bool hasAdaptersFromOtherApplications() const; private: diff --git a/cpp/src/IceGrid/Database.cpp b/cpp/src/IceGrid/Database.cpp index 264580a1236..6281eaa1c0f 100644 --- a/cpp/src/IceGrid/Database.cpp +++ b/cpp/src/IceGrid/Database.cpp @@ -487,13 +487,21 @@ Database::removeApplication(const string& name, AdminSessionI* session) throw ApplicationNotExistException(name); } + bool init = false; try { ApplicationHelper helper(_communicator, p->second.descriptor); + init = true; + checkForRemove(helper); unload(helper, entries); } catch(const DeploymentException&) { + if(init) + { + throw; + } + // // For some reasons the application became invalid. If // it's invalid, it's most likely not loaded either. So we @@ -1216,6 +1224,11 @@ Database::checkForAddition(const ApplicationHelper& app) for_each(serverIds.begin(), serverIds.end(), objFunc(*this, &Database::checkServerForAddition)); for_each(adapterIds.begin(), adapterIds.end(), objFunc(*this, &Database::checkAdapterForAddition)); for_each(objectIds.begin(), objectIds.end(), objFunc(*this, &Database::checkObjectForAddition)); + + set<string> repGrps; + set<string> adptRepGrps; + app.getReplicaGroups(repGrps, adptRepGrps); + for_each(adptRepGrps.begin(), adptRepGrps.end(), objFunc(*this, &Database::checkReplicaGroupExists)); } void @@ -1233,12 +1246,45 @@ Database::checkForUpdate(const ApplicationHelper& origApp, const ApplicationHelp for_each(addedSvrs.begin(), addedSvrs.end(), objFunc(*this, &Database::checkServerForAddition)); Ice::StringSeq addedAdpts; - set_difference(newAdpts.begin(), newAdpts.end(), oldAdpts.begin(), oldAdpts.end(), set_inserter(addedAdpts)); + set_difference(newAdpts.begin(), newAdpts.end(), oldAdpts.begin(), oldAdpts.end(), back_inserter(addedAdpts)); for_each(addedAdpts.begin(), addedAdpts.end(), objFunc(*this, &Database::checkAdapterForAddition)); vector<Ice::Identity> addedObjs; - set_difference(newObjs.begin(), newObjs.end(), oldObjs.begin(), oldObjs.end(), set_inserter(addedObjs)); + set_difference(newObjs.begin(), newObjs.end(), oldObjs.begin(), oldObjs.end(), back_inserter(addedObjs)); for_each(addedObjs.begin(), addedObjs.end(), objFunc(*this, &Database::checkObjectForAddition)); + + set<string> oldRepGrps, newRepGrps; + set<string> oldAdptRepGrps, newAdptRepGrps; + origApp.getReplicaGroups(oldRepGrps, oldAdptRepGrps); + newApp.getReplicaGroups(newRepGrps, newAdptRepGrps); + + set<string> rmRepGrps; + set_difference(oldRepGrps.begin(), oldRepGrps.end(), newRepGrps.begin(),newRepGrps.end(), set_inserter(rmRepGrps)); + for_each(rmRepGrps.begin(), rmRepGrps.end(), objFunc(*this, &Database::checkReplicaGroupForRemove)); + + set<string> addedAdptRepGrps; + set_difference(newAdptRepGrps.begin(),newAdptRepGrps.end(), oldAdptRepGrps.begin(), oldAdptRepGrps.end(), + set_inserter(addedAdptRepGrps)); + for_each(addedAdptRepGrps.begin(), addedAdptRepGrps.end(), objFunc(*this, &Database::checkReplicaGroupExists)); + + vector<string> invalidAdptRepGrps; + set_intersection(rmRepGrps.begin(), rmRepGrps.end(), newAdptRepGrps.begin(), newAdptRepGrps.end(), + back_inserter(invalidAdptRepGrps)); + if(!invalidAdptRepGrps.empty()) + { + DeploymentException ex; + ex.reason = "couldn't find replica group `" + invalidAdptRepGrps.front() + "'"; + throw ex; + } +} + +void +Database::checkForRemove(const ApplicationHelper& app) +{ + set<string> replicaGroups; + set<string> adapterReplicaGroups; + app.getReplicaGroups(replicaGroups, adapterReplicaGroups); + for_each(replicaGroups.begin(), replicaGroups.end(), objFunc(*this, &Database::checkReplicaGroupForRemove)); } void @@ -1279,6 +1325,57 @@ Database::checkObjectForAddition(const Ice::Identity& objectId) } void +Database::checkReplicaGroupExists(const string& replicaGroup) +{ + ReplicaGroupEntryPtr entry; + try + { + entry = ReplicaGroupEntryPtr::dynamicCast(_adapterCache.get(replicaGroup)); + } + catch(const AdapterNotExistException&) + { + } + + if(!entry) + { + DeploymentException ex; + ex.reason = "couldn't find replica group `" + replicaGroup + "'"; + throw ex; + } +} + +void +Database::checkReplicaGroupForRemove(const string& replicaGroup) +{ + ReplicaGroupEntryPtr entry; + try + { + entry = ReplicaGroupEntryPtr::dynamicCast(_adapterCache.get(replicaGroup)); + } + catch(const AdapterNotExistException&) + { + } + + if(!entry) + { + // + // This would indicate an inconsistency with the cache and + // database. We don't print an error, it will be printed + // when the application is actually removed. + // + return; + } + + if(entry->hasAdaptersFromOtherApplications()) + { + DeploymentException ex; + ex.reason = "couldn't remove application because the replica group `" + replicaGroup + + "' is used by object adapters from other applications."; + throw ex; + } +} + +void Database::load(const ApplicationHelper& app, ServerEntrySeq& entries, const string& uuid, int revision) { const NodeDescriptorDict& nodes = app.getInstance().nodes; diff --git a/cpp/src/IceGrid/Database.h b/cpp/src/IceGrid/Database.h index a02bbe02eb2..bee84509cee 100644 --- a/cpp/src/IceGrid/Database.h +++ b/cpp/src/IceGrid/Database.h @@ -124,10 +124,13 @@ private: void checkForAddition(const ApplicationHelper&); void checkForUpdate(const ApplicationHelper&, const ApplicationHelper&); + void checkForRemove(const ApplicationHelper&); void checkServerForAddition(const std::string&); void checkAdapterForAddition(const std::string&); void checkObjectForAddition(const Ice::Identity&); + void checkReplicaGroupExists(const std::string&); + void checkReplicaGroupForRemove(const std::string&); void load(const ApplicationHelper&, ServerEntrySeq&, const std::string&, int); void unload(const ApplicationHelper&, ServerEntrySeq&); diff --git a/cpp/src/IceGrid/DescriptorHelper.cpp b/cpp/src/IceGrid/DescriptorHelper.cpp index 57a5b0c5641..c41aa5c04de 100644 --- a/cpp/src/IceGrid/DescriptorHelper.cpp +++ b/cpp/src/IceGrid/DescriptorHelper.cpp @@ -977,6 +977,18 @@ CommunicatorHelper::getIds(multiset<string>& adapterIds, multiset<Ice::Identity> } } +void +CommunicatorHelper::getReplicaGroups(set<string>& replicaGroups) const +{ + for(AdapterDescriptorSeq::const_iterator p = _desc->adapters.begin(); p != _desc->adapters.end(); ++p) + { + if(!p->replicaGroupId.empty()) + { + replicaGroups.insert(p->replicaGroupId); + } + } +} + void CommunicatorHelper::instantiateImpl(const CommunicatorDescriptorPtr& instance, const Resolver& resolve) const { @@ -992,10 +1004,18 @@ CommunicatorHelper::instantiateImpl(const CommunicatorDescriptorPtr& instance, c adapter.registerProcess = p->registerProcess; adapter.serverLifetime = p->serverLifetime; adapter.replicaGroupId = resolve.asId(p->replicaGroupId, "object adapter replica group id", true); - if(!adapter.replicaGroupId.empty() && !resolve.hasReplicaGroup(adapter.replicaGroupId)) - { - resolve.exception("unknown replica group `" + adapter.replicaGroupId + "'"); - } + + // + // Don't check for unknown replica groups here. This check is + // instead done by the database before the application is + // added. It's legal for an OA to refer to a replica group + // from another application. + // + //if(!adapter.replicaGroupId.empty() && !resolve.hasReplicaGroup(adapter.replicaGroupId)) + //{ + //resolve.exception("unknown replica group `" + adapter.replicaGroupId + "'"); + //} + adapter.priority = resolve.asInt(p->priority, "object adapter priority"); adapter.objects = resolve(p->objects, "well-known"); adapter.allocatables = resolve(p->allocatables, "allocatable"); @@ -1505,6 +1525,16 @@ IceBoxHelper::getIds(multiset<string>& adapterIds, multiset<Ice::Identity>& obje } void +IceBoxHelper::getReplicaGroups(set<string>& replicaGroups) const +{ + CommunicatorHelper::getReplicaGroups(replicaGroups); + for(vector<ServiceInstanceHelper>::const_iterator p = _services.begin(); p != _services.end(); ++p) + { + p->getReplicaGroups(replicaGroups); + } +} + +void IceBoxHelper::print(const Ice::CommunicatorPtr& communicator, Output& out) const { print(communicator, out, ServerInfo()); @@ -1694,6 +1724,13 @@ ServiceInstanceHelper::getIds(multiset<string>& adapterIds, multiset<Ice::Identi } void +ServiceInstanceHelper::getReplicaGroups(set<string>& replicaGroups) const +{ + assert(_service.getDescriptor()); + _service.getReplicaGroups(replicaGroups); +} + +void ServiceInstanceHelper::print(const Ice::CommunicatorPtr& communicator, Output& out) const { if(_service.getDescriptor()) @@ -1875,6 +1912,13 @@ ServerInstanceHelper::getIds(multiset<string>& adapterIds, multiset<Ice::Identit _serverInstance->getIds(adapterIds, objectIds); } +void +ServerInstanceHelper::getReplicaGroups(set<string>& replicaGroups) const +{ + assert(_serverInstance); + _serverInstance->getReplicaGroups(replicaGroups); +} + NodeHelper::NodeHelper(const string& name, const NodeDescriptor& descriptor, const Resolver& appResolve, @@ -2137,6 +2181,21 @@ NodeHelper::getIds(multiset<string>& serverIds, multiset<string>& adapterIds, mu } } +void +NodeHelper::getReplicaGroups(set<string>& replicaGroups) const +{ + assert(_instantiated); + ServerInstanceHelperDict::const_iterator p; + for(p = _serverInstances.begin(); p != _serverInstances.end(); ++p) + { + p->second.getReplicaGroups(replicaGroups); + } + for(p = _servers.begin(); p != _servers.end(); ++p) + { + p->second.getReplicaGroups(replicaGroups); + } +} + const NodeDescriptor& NodeHelper::getDefinition() const { @@ -2700,6 +2759,29 @@ ApplicationHelper::getIds(set<string>& serverIds, set<string>& adapterIds, set<I copy(oIds.begin(), oIds.end(), inserter(objectIds, objectIds.begin())); } +void +ApplicationHelper::getReplicaGroups(set<string>& replicaGroups, set<string>& adapterReplicaGroups) const +{ + ReplicaGroupDescriptorSeq::const_iterator r; + for(r = _def.replicaGroups.begin(); r != _def.replicaGroups.end(); ++r) + { + replicaGroups.insert(r->id); + } + + set<string> allAdapterReplicaGroups; + for(NodeHelperDict::const_iterator p = _nodes.begin(); p != _nodes.end(); ++p) + { + p->second.getReplicaGroups(allAdapterReplicaGroups); + } + + // + // Only return references to replica groups which don't belong to + // this application. + // + set_difference(allAdapterReplicaGroups.begin(), allAdapterReplicaGroups.end(), + replicaGroups.begin(), replicaGroups.end(), set_inserter(adapterReplicaGroups)); +} + const ApplicationDescriptor& ApplicationHelper::getDefinition() const { diff --git a/cpp/src/IceGrid/DescriptorHelper.h b/cpp/src/IceGrid/DescriptorHelper.h index cbc9da7ce60..e222940686c 100644 --- a/cpp/src/IceGrid/DescriptorHelper.h +++ b/cpp/src/IceGrid/DescriptorHelper.h @@ -90,6 +90,7 @@ public: bool operator!=(const CommunicatorHelper&) const; virtual void getIds(std::multiset<std::string>&, std::multiset<Ice::Identity>&) const; + virtual void getReplicaGroups(std::set<std::string>&) const; void print(const Ice::CommunicatorPtr&, IceUtil::Output&) const; @@ -184,6 +185,7 @@ public: ServiceInstanceDescriptor instantiate(const Resolver&, const PropertySetDescriptorDict&) const; void getIds(std::multiset<std::string>&, std::multiset<Ice::Identity>&) const; + void getReplicaGroups(std::set<std::string>&) const; void print(const Ice::CommunicatorPtr&, IceUtil::Output&) const; @@ -208,6 +210,7 @@ public: const PropertySetDescriptorDict&) const; virtual void getIds(std::multiset<std::string>&, std::multiset<Ice::Identity>&) const; + virtual void getReplicaGroups(std::set<std::string>&) const; void print(const Ice::CommunicatorPtr&, IceUtil::Output&) const; void print(const Ice::CommunicatorPtr&, IceUtil::Output&, const ServerInfo&) const; @@ -243,6 +246,7 @@ public: ServerDescriptorPtr getServerInstance() const; void getIds(std::multiset<std::string>&, std::multiset<Ice::Identity>&) const; + void getReplicaGroups(std::set<std::string>&) const; private: @@ -270,6 +274,7 @@ public: NodeDescriptor update(const NodeUpdateDescriptor&, const Resolver&) const; void getIds(std::multiset<std::string>&, std::multiset<std::string>&, std::multiset<Ice::Identity>&) const; + void getReplicaGroups(std::set<std::string>&) const; const NodeDescriptor& getDefinition() const; const NodeDescriptor& getInstance() const; void getServerInfos(const std::string&, const std::string&, int, std::map<std::string, ServerInfo>&) const; @@ -304,6 +309,7 @@ public: ApplicationDescriptor instantiateServer(const std::string&, const ServerInstanceDescriptor&) const; void getIds(std::set<std::string>&, std::set<std::string>&, std::set<Ice::Identity>&) const; + void getReplicaGroups(std::set<std::string>&, std::set<std::string>&) const; const ApplicationDescriptor& getDefinition() const; const ApplicationDescriptor& getInstance() const; void getDistributions(DistributionDescriptor&, std::vector<std::string>&,const std::string& = std::string()) const; diff --git a/cpp/test/IceGrid/replicaGroup/AllTests.cpp b/cpp/test/IceGrid/replicaGroup/AllTests.cpp index 5e101fbf023..1bef85f3b3d 100644 --- a/cpp/test/IceGrid/replicaGroup/AllTests.cpp +++ b/cpp/test/IceGrid/replicaGroup/AllTests.cpp @@ -73,7 +73,8 @@ private: typedef IceUtil::Handle<SessionKeepAliveThread> SessionKeepAliveThreadPtr; void -instantiateServer(const AdminPrx& admin, const string& templ, const string& node, const map<string, string>& params) +instantiateServer(const AdminPrx& admin, const string& templ, const string& node, const map<string, string>& params, + const string& application = string("Test")) { ServerInstanceDescriptor desc; desc._cpp_template = templ; @@ -82,17 +83,22 @@ instantiateServer(const AdminPrx& admin, const string& templ, const string& node nodeUpdate.name = node; nodeUpdate.serverInstances.push_back(desc); ApplicationUpdateDescriptor update; - update.name = "Test"; + update.name = application; update.nodes.push_back(nodeUpdate); try { admin->updateApplication(update); } - catch(DeploymentException& ex) + catch(const DeploymentException& ex) { cerr << ex.reason << endl; test(false); } + catch(const Ice::LocalException& ex) + { + cerr << ex << endl; + test(false); + } } void @@ -114,11 +120,13 @@ removeServer(const AdminPrx& admin, const string& id) test(false); } + ServerInfo info = admin->getServerInfo(id); + NodeUpdateDescriptor nodeUpdate; - nodeUpdate.name = "localnode"; + nodeUpdate.name = info.node; nodeUpdate.removeServers.push_back(id); ApplicationUpdateDescriptor update; - update.name = "Test"; + update.name = info.application; update.nodes.push_back(nodeUpdate); try { @@ -593,6 +601,139 @@ allTests(const Ice::CommunicatorPtr& comm) }; cout << "ok" << endl; + cout << "testing replica group from different applications... " << flush; + { + map<string, string> params; + params["replicaGroup"] = "Random"; + params["id"] = "Server1"; + instantiateServer(admin, "Server", "localnode", params); + + ApplicationUpdateDescriptor update; + update.name = "Test"; + update.removeReplicaGroups.push_back("Random"); + try + { + admin->updateApplication(update); + test(false); + } + catch(const DeploymentException&) + { + // The Random replica goup is used by Server1! + } + + // + // Add an application Test1 without replica groups and a + // server that uses the Random replica group. + // + ApplicationInfo app = admin->getApplicationInfo("Test"); + app.descriptor.name = "Test1"; + app.descriptor.replicaGroups.clear(); + app.descriptor.nodes.clear(); + try + { + admin->addApplication(app.descriptor); + } + catch(const DeploymentException& ex) + { + cerr << ex << endl; + test(false); + } + params["id"] = "Server2"; + instantiateServer(admin, "Server", "localnode", params, "Test1"); + + try + { + admin->removeApplication("Test"); + test(false); + } + catch(const DeploymentException&) + { + // Test has a replica group referenced by the Test1 application. + } + + TestIntfPrx obj = TestIntfPrx::uncheckedCast(comm->stringToProxy("Random")); + obj = TestIntfPrx::uncheckedCast(obj->ice_locatorCacheTimeout(0)); + obj = TestIntfPrx::uncheckedCast(obj->ice_connectionCached(false)); + set<string> replicaIds; + replicaIds.insert("Server1.ReplicatedAdapter"); + replicaIds.insert("Server2.ReplicatedAdapter"); + while(!replicaIds.empty()) + { + try + { + replicaIds.erase(obj->getReplicaId()); + } + catch(const Ice::LocalException& ex) + { + cerr << ex << endl; + test(false); + } + } + + removeServer(admin, "Server2"); + removeServer(admin, "Server1"); + + ReplicaGroupDescriptor replicaGroup; + replicaGroup.id = "ReplicatedAdapterFromTest1"; + replicaGroup.loadBalancing = new RandomLoadBalancingPolicy(); + replicaGroup.loadBalancing->nReplicas = "0"; + update = ApplicationUpdateDescriptor(); + update.name = "Test1"; + update.replicaGroups.push_back(replicaGroup); + + try + { + admin->updateApplication(update); + } + catch(const DeploymentException& ex) + { + cerr << ex.reason << endl; + test(false); + } + + params["replicaGroup"] = "ReplicatedAdapterFromTest1"; + params["id"] = "Server1"; + instantiateServer(admin, "Server", "localnode", params); + + try + { + admin->removeApplication("Test1"); + test(false); + } + catch(const DeploymentException&) + { + // ReplicatedAdapterFromTest1 used by server from Test + } + + update = ApplicationUpdateDescriptor(); + update.name = "Test1"; + update.removeReplicaGroups.push_back("ReplicatedAdapterFromTest1"); + try + { + admin->updateApplication(update); + test(false); + } + catch(const DeploymentException&) + { + // ReplicatedAdapterFromTest1 used by server from Test + } + + removeServer(admin, "Server1"); + + try + { + admin->updateApplication(update); + } + catch(const DeploymentException& ex) + { + cerr << ex << endl; + test(false); + } + + admin->removeApplication("Test1"); + }; + cout << "ok" << endl; + keepAlive->destroy(); keepAlive->getThreadControl().join(); keepAlive = 0; |