diff options
author | Benoit Foucher <benoit@zeroc.com> | 2006-06-09 09:56:37 +0000 |
---|---|---|
committer | Benoit Foucher <benoit@zeroc.com> | 2006-06-09 09:56:37 +0000 |
commit | a6d51aa0ea13510e4eca6b9646be5ae1d917aa3f (patch) | |
tree | 4bc2e711e1fc32ecb7943fb3c7c6d94226c47507 | |
parent | properties updates (diff) | |
download | ice-a6d51aa0ea13510e4eca6b9646be5ae1d917aa3f.tar.bz2 ice-a6d51aa0ea13510e4eca6b9646be5ae1d917aa3f.tar.xz ice-a6d51aa0ea13510e4eca6b9646be5ae1d917aa3f.zip |
Added support for allocatable objects.
21 files changed, 637 insertions, 357 deletions
diff --git a/cpp/demo/IceGrid/allocate/application-multiple.xml b/cpp/demo/IceGrid/allocate/application-multiple.xml index 3a7dc481cea..7e5ea863bdd 100644 --- a/cpp/demo/IceGrid/allocate/application-multiple.xml +++ b/cpp/demo/IceGrid/allocate/application-multiple.xml @@ -17,7 +17,7 @@ <parameter name="index"/> <server id="AllocateServer-${index}" exe="./server" activation="on-demand"> <adapter name="Hello" endpoints="tcp" register-process="true"> - <object identity="hello-${index}" type="::Demo::Hello"/> + <allocatable identity="hello-${index}" type="::Demo::Hello"/> </adapter> <property name="Identity" value="hello-${index}"/> </server> diff --git a/cpp/demo/IceGrid/allocate/application-single.xml b/cpp/demo/IceGrid/allocate/application-single.xml index 70fb67398a7..e2d2d6f4c61 100644 --- a/cpp/demo/IceGrid/allocate/application-single.xml +++ b/cpp/demo/IceGrid/allocate/application-single.xml @@ -16,7 +16,7 @@ <node name="localhost"> <server id="AllocateServer" exe="./server" activation="on-demand"> <adapter name="Hello" endpoints="tcp" register-process="true"> - <object identity="hello" type="::Demo::Hello"/> + <allocatable identity="hello" type="::Demo::Hello"/> </adapter> <property name="Identity" value="hello"/> </server> diff --git a/cpp/demo/IceGrid/sessionActivation/application.xml b/cpp/demo/IceGrid/sessionActivation/application.xml index 617a1bfdedc..1d049c45b35 100644 --- a/cpp/demo/IceGrid/sessionActivation/application.xml +++ b/cpp/demo/IceGrid/sessionActivation/application.xml @@ -16,7 +16,7 @@ <node name="localhost"> <server id="SessionServer" exe="./server" activation="session"> <adapter name="Hello" endpoints="tcp" register-process="true"> - <object identity="hello" type="::Demo::Hello"/> + <allocatable identity="hello"/> </adapter> <property name="Identity" value="hello"/> </server> diff --git a/cpp/slice/IceGrid/Descriptor.ice b/cpp/slice/IceGrid/Descriptor.ice index 7b658893832..18f938e3678 100644 --- a/cpp/slice/IceGrid/Descriptor.ice +++ b/cpp/slice/IceGrid/Descriptor.ice @@ -134,10 +134,17 @@ struct AdapterDescriptor /** * - * The object descriptors associated to this object adapter. + * The well-known object descriptors associated to this object adapter. * **/ ObjectDescriptorSeq objects; + + /** + * + * The allocatable object descriptors associated to this object adapter. + * + **/ + ObjectDescriptorSeq allocatables; }; /** diff --git a/cpp/src/IceGrid/AllocatableObjectCache.cpp b/cpp/src/IceGrid/AllocatableObjectCache.cpp new file mode 100644 index 00000000000..78bac949bbf --- /dev/null +++ b/cpp/src/IceGrid/AllocatableObjectCache.cpp @@ -0,0 +1,352 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2006 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/Random.h> +#include <Ice/Communicator.h> +#include <Ice/LoggerUtil.h> +#include <Ice/LocalException.h> +#include <IceGrid/AllocatableObjectCache.h> +#include <IceGrid/SessionI.h> + +using namespace std; +using namespace IceGrid; + +pointer_to_unary_function<int, int> AllocatableObjectCache::_rand(IceUtil::random); + +namespace IceGrid +{ + +struct AllocatableObjectEntryCI : binary_function<AllocatableObjectEntryPtr&, AllocatableObjectEntryPtr&, bool> +{ + + bool + operator()(const AllocatableObjectEntryPtr& lhs, const AllocatableObjectEntryPtr& rhs) + { + return ::Ice::proxyIdentityLess(lhs->getProxy(), rhs->getProxy()); + } +}; + +}; + +AllocatableObjectCache::TypeEntry::TypeEntry() +{ +} + +void +AllocatableObjectCache::TypeEntry::add(const AllocatableObjectEntryPtr& obj) +{ + // + // No mutex protection here, this is called with the cache locked. + // + _objects.insert(lower_bound(_objects.begin(), _objects.end(), obj, AllocatableObjectEntryCI()), obj); + if(!_requests.empty()) + { + canTryAllocate(obj, false); + } +} + +bool +AllocatableObjectCache::TypeEntry::remove(const AllocatableObjectEntryPtr& obj) +{ + // + // No mutex protection here, this is called with the cache locked. + // + vector<AllocatableObjectEntryPtr>::iterator q; + q = lower_bound(_objects.begin(), _objects.end(), obj, AllocatableObjectEntryCI()); + assert(q->get() == obj.get()); + _objects.erase(q); + + if(!_requests.empty() && _objects.empty()) + { + for(list<ObjectAllocationRequestPtr>::const_iterator p = _requests.begin(); p != _requests.end(); ++p) + { + (*p)->cancel(AllocationException("no allocatable objects with type `" + obj->getType() + "' registered")); + } + } + return _objects.empty(); +} + +void +AllocatableObjectCache::TypeEntry::addAllocationRequest(const ObjectAllocationRequestPtr& request) +{ + // + // No mutex protection here, this is called with the cache locked. + // + if(request->pending()) + { + _requests.push_back(request); + } +} + +bool +AllocatableObjectCache::TypeEntry::canTryAllocate(const AllocatableObjectEntryPtr& entry, bool fromRelease) +{ + // + // No mutex protection here, this is called with the cache locked. + // + list<ObjectAllocationRequestPtr>::iterator p = _requests.begin(); + while(p != _requests.end()) + { + AllocationRequestPtr request = *p; + try + { + if(request->isCanceled()) // If the request has been canceled, we just remove it. + { + p = _requests.erase(p); + } + else if(entry->tryAllocate(request, fromRelease)) + { + p = _requests.erase(p); + return true; // The request successfully allocated the entry! + } + else if(entry->getSession()) // If entry is allocated, we're done + { + return false; + } + else + { + ++p; + } + } + catch(const SessionDestroyedException&) + { + p = _requests.erase(p); + } + } + return false; +} + +AllocatableObjectCache::AllocatableObjectCache(const Ice::CommunicatorPtr& communicator) : + _communicator(communicator) +{ +} + +void +AllocatableObjectCache::add(const ObjectInfo& info, const AllocatablePtr& parent) +{ + const Ice::Identity& id = info.proxy->ice_getIdentity(); + + Lock sync(*this); + assert(!getImpl(id)); + + AllocatableObjectEntryPtr entry = new AllocatableObjectEntry(*this, info, parent); + addImpl(id, entry); + + map<string, TypeEntry>::iterator p = _types.find(entry->getType()); + if(p == _types.end()) + { + p = _types.insert(p, map<string, TypeEntry>::value_type(entry->getType(), TypeEntry())); + } + p->second.add(entry); + + if(_traceLevels && _traceLevels->object > 0) + { + Ice::Trace out(_traceLevels->logger, _traceLevels->objectCat); + out << "added allocatable object `" << _communicator->identityToString(id) << "'"; + } +} + +AllocatableObjectEntryPtr +AllocatableObjectCache::get(const Ice::Identity& id) const +{ + Lock sync(*this); + AllocatableObjectEntryPtr entry = getImpl(id); + if(!entry) + { + throw ObjectNotRegisteredException(id); + } + return entry; +} + +AllocatableObjectEntryPtr +AllocatableObjectCache::remove(const Ice::Identity& id) +{ + Lock sync(*this); + AllocatableObjectEntryPtr entry = removeImpl(id); + assert(entry); + + map<string, TypeEntry>::iterator p = _types.find(entry->getType()); + assert(p != _types.end()); + if(p->second.remove(entry)) + { + _types.erase(p); + } + + if(_traceLevels && _traceLevels->object > 0) + { + Ice::Trace out(_traceLevels->logger, _traceLevels->objectCat); + out << "removed allocatable object `" << _communicator->identityToString(id) << "'"; + } + + return entry; +} + +void +AllocatableObjectCache::allocateByType(const string& type, const ObjectAllocationRequestPtr& request) +{ + Lock sync(*this); + map<string, TypeEntry>::iterator p = _types.find(type); + if(p == _types.end()) + { + throw AllocationException("no allocatable objects with type `" + type + "' registered"); + } + + vector<AllocatableObjectEntryPtr> objects = p->second.getObjects(); + random_shuffle(objects.begin(), objects.end(), _rand); // TODO: OPTIMIZE + try + { + for(vector<AllocatableObjectEntryPtr>::const_iterator q = objects.begin(); q != objects.end(); ++q) + { + if((*q)->tryAllocate(request)) + { + return; + } + } + } + catch(const SessionDestroyedException&) + { + return; + } + + p->second.addAllocationRequest(request); +} + +bool +AllocatableObjectCache::canTryAllocate(const AllocatableObjectEntryPtr& entry) +{ + // + // Notify the type entry that an object was released. + // + Lock sync(*this); + map<string, TypeEntry>::iterator p = _types.find(entry->getType()); + if(p == _types.end()) + { + return false; + } + return p->second.canTryAllocate(entry, true); +} + +AllocatableObjectEntry::AllocatableObjectEntry(AllocatableObjectCache& cache, + const ObjectInfo& info, + const AllocatablePtr& parent) : + Allocatable(true, parent), + _cache(cache), + _info(info), + _destroyed(false) +{ +} + +Ice::ObjectPrx +AllocatableObjectEntry::getProxy() const +{ + return _info.proxy; +} + +string +AllocatableObjectEntry::getType() const +{ + return _info.type; +} + +bool +AllocatableObjectEntry::canRemove() +{ + return true; +} + +void +AllocatableObjectEntry::allocated(const SessionIPtr& session) +{ + // + // Add the object allocation to the session. The object will be + // released once the session is destroyed. + // + session->addAllocation(this); + + TraceLevelsPtr traceLevels = _cache.getTraceLevels(); + if(traceLevels && traceLevels->object > 1) + { + Ice::Trace out(traceLevels->logger, traceLevels->objectCat); + out << "object `" << _info.proxy << "' allocated by `" << session->getId() << "' (" << _count << ")"; + } + + Glacier2::SessionControlPrx ctl = session->getSessionControl(); + if(ctl) + { + try + { + Ice::IdentitySeq seq(1); + seq.push_back(_info.proxy->ice_getIdentity()); + ctl->identities()->add(seq); + } + catch(const Ice::ObjectNotExistException&) + { + } + } +} + +void +AllocatableObjectEntry::released(const SessionIPtr& session) +{ + // + // Remove the object allocation from the session. + // + session->removeAllocation(this); + + Glacier2::SessionControlPrx ctl = session->getSessionControl(); + if(ctl) + { + try + { + Ice::IdentitySeq seq(1); + seq.push_back(_info.proxy->ice_getIdentity()); + ctl->identities()->remove(seq); + } + catch(const Ice::ObjectNotExistException&) + { + } + } + + TraceLevelsPtr traceLevels = _cache.getTraceLevels(); + if(traceLevels && traceLevels->object > 1) + { + Ice::Trace out(traceLevels->logger, traceLevels->objectCat); + out << "object `" << _info.proxy << "' released by `" << session->getId() << "' (" << _count << ")"; + } +} + +void +AllocatableObjectEntry::destroy() +{ + SessionIPtr session; + { + Lock sync(*this); + _destroyed = true; + session = _session; + } + release(session); +} + +void +AllocatableObjectEntry::checkAllocatable() +{ + if(_destroyed) + { + throw ObjectNotRegisteredException(_info.proxy->ice_getIdentity()); + } + + Allocatable::checkAllocatable(); +} + +bool +AllocatableObjectEntry::canTryAllocate() +{ + return _cache.canTryAllocate(this); +} + diff --git a/cpp/src/IceGrid/AllocatableObjectCache.h b/cpp/src/IceGrid/AllocatableObjectCache.h new file mode 100644 index 00000000000..3c906fc77c7 --- /dev/null +++ b/cpp/src/IceGrid/AllocatableObjectCache.h @@ -0,0 +1,121 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2006 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_GRID_ALLOCATABLEOBJECTCACHE_H +#define ICE_GRID_ALLOCATABLEOBJECTCACHE_H + +#include <IceUtil/Mutex.h> +#include <Ice/CommunicatorF.h> +#include <IceGrid/Cache.h> +#include <IceGrid/Admin.h> +#include <IceGrid/Allocatable.h> + +namespace IceGrid +{ + +class AllocatableObjectCache; + +class AllocatableObjectEntry : public Allocatable +{ +public: + + AllocatableObjectEntry(AllocatableObjectCache&, const ObjectInfo&, const AllocatablePtr&); + Ice::ObjectPrx getProxy() const; + std::string getType() const; + + bool canRemove(); + + virtual void allocated(const SessionIPtr&); + virtual void released(const SessionIPtr&); + virtual bool canTryAllocate(); + + void destroy(); + virtual void checkAllocatable(); + +private: + + AllocatableObjectCache& _cache; + const ObjectInfo _info; + bool _destroyed; +}; +typedef IceUtil::Handle<AllocatableObjectEntry> AllocatableObjectEntryPtr; + +class ObjectAllocationRequest : public AllocationRequest +{ +public: + + ObjectAllocationRequest(const SessionIPtr& session) : AllocationRequest(session) { } + + virtual void response(const Ice::ObjectPrx&) = 0; + virtual void exception(const AllocationException&) = 0; + +private: + + virtual bool allocated(const AllocatablePtr& allocatable, const SessionIPtr& session) + { + response(AllocatableObjectEntryPtr::dynamicCast(allocatable)->getProxy()); + return true; + } + + virtual void canceled(const AllocationException& ex) + { + exception(ex); + } +}; +typedef IceUtil::Handle<ObjectAllocationRequest> ObjectAllocationRequestPtr; + +class AdapterCache; + +class AllocatableObjectCache : public Cache<Ice::Identity, AllocatableObjectEntry> +{ +public: + + AllocatableObjectCache(const Ice::CommunicatorPtr&); + + void add(const ObjectInfo&, const AllocatablePtr&); + AllocatableObjectEntryPtr get(const Ice::Identity&) const; + AllocatableObjectEntryPtr remove(const Ice::Identity&); + + void allocateByType(const std::string&, const ObjectAllocationRequestPtr&); + bool canTryAllocate(const AllocatableObjectEntryPtr&); + + const Ice::CommunicatorPtr& getCommunicator() const { return _communicator; } + +private: + + class TypeEntry + { + public: + + TypeEntry(); + + void add(const AllocatableObjectEntryPtr&); + bool remove(const AllocatableObjectEntryPtr&); + + void addAllocationRequest(const ObjectAllocationRequestPtr&); + bool canTryAllocate(const AllocatableObjectEntryPtr&, bool); + + const std::vector<AllocatableObjectEntryPtr>& getObjects() const { return _objects; } + + private: + + std::vector<AllocatableObjectEntryPtr> _objects; + std::list<ObjectAllocationRequestPtr> _requests; + }; + + const Ice::CommunicatorPtr _communicator; + std::map<std::string, TypeEntry> _types; + std::map<std::string, std::vector<Ice::Identity> > _allocatablesByType; + + static std::pointer_to_unary_function<int, int> _rand; +}; + +}; + +#endif diff --git a/cpp/src/IceGrid/Database.cpp b/cpp/src/IceGrid/Database.cpp index 4a2be700876..9b478a19b2e 100644 --- a/cpp/src/IceGrid/Database.cpp +++ b/cpp/src/IceGrid/Database.cpp @@ -120,8 +120,9 @@ Database::Database(const Ice::ObjectAdapterPtr& adapter, _instanceName(instanceName), _traceLevels(traceLevels), _nodeCache(_communicator, nodeSessionTimeout), - _objectCache(_communicator, _adapterCache), - _serverCache(_communicator, _nodeCache, _adapterCache, _objectCache), + _objectCache(_communicator), + _allocatableObjectCache(_communicator), + _serverCache(_communicator, _nodeCache, _adapterCache, _objectCache, _allocatableObjectCache), _connection(Freeze::createConnection(adapter->getCommunicator(), envName)), _descriptors(_connection, _descriptorDbName), _objects(_connection, _objectDbName), @@ -150,6 +151,7 @@ Database::Database(const Ice::ObjectAdapterPtr& adapter, _nodeCache.setTraceLevels(_traceLevels); _adapterCache.setTraceLevels(_traceLevels); _objectCache.setTraceLevels(_traceLevels); + _allocatableObjectCache.setTraceLevels(_traceLevels); // // Register a default servant to manage manually registered object adapters. @@ -1019,19 +1021,19 @@ Database::updateObject(const Ice::ObjectPrx& proxy) void Database::allocateObject(const Ice::Identity& id, const ObjectAllocationRequestPtr& request) { - _objectCache.get(id)->allocate(request); + _allocatableObjectCache.get(id)->allocate(request); } void Database::allocateObjectByType(const string& type, const ObjectAllocationRequestPtr& request) { - _objectCache.allocateByType(type, request); + _allocatableObjectCache.allocateByType(type, request); } void Database::releaseObject(const Ice::Identity& id, const SessionIPtr& session) { - _objectCache.get(id)->release(session); + _allocatableObjectCache.get(id)->release(session); } Ice::ObjectPrx @@ -1228,7 +1230,9 @@ Database::checkAdapterForAddition(const string& id) void Database::checkObjectForAddition(const Ice::Identity& objectId) { - if(_objectCache.has(objectId) || _objects.find(objectId) != _objects.end()) + if(_objectCache.has(objectId) + || _allocatableObjectCache.has(objectId) + || _objects.find(objectId) != _objects.end()) { DeploymentException ex; ex.reason = "object `" + _communicator->identityToString(objectId) + "' is already registered"; @@ -1256,7 +1260,7 @@ Database::load(const ApplicationHelper& app, ServerEntrySeq& entries) ObjectInfo info; info.type = o->type; info.proxy = _communicator->stringToProxy(_communicator->identityToString(o->id) + "@" + r->id); - _objectCache.add(info, application, false, 0); // Not allocatable + _objectCache.add(info, application); } } @@ -1394,7 +1398,7 @@ Database::reload(const ApplicationHelper& oldApp, const ApplicationHelper& newAp ObjectInfo info; info.type = o->type; info.proxy = _communicator->stringToProxy(_communicator->identityToString(o->id) + "@" + r->id); - _objectCache.add(info, application, false, 0); // Not allocatable + _objectCache.add(info, application); } } diff --git a/cpp/src/IceGrid/Database.h b/cpp/src/IceGrid/Database.h index e4d76add5a1..eac64784f6d 100644 --- a/cpp/src/IceGrid/Database.h +++ b/cpp/src/IceGrid/Database.h @@ -22,6 +22,7 @@ #include <IceGrid/ServerCache.h> #include <IceGrid/NodeCache.h> #include <IceGrid/ObjectCache.h> +#include <IceGrid/AllocatableObjectCache.h> #include <IceGrid/AdapterCache.h> namespace IceGrid @@ -138,6 +139,7 @@ private: NodeCache _nodeCache; AdapterCache _adapterCache; ObjectCache _objectCache; + AllocatableObjectCache _allocatableObjectCache; ServerCache _serverCache; RegistryObserverPrx _registryObserver; diff --git a/cpp/src/IceGrid/DescriptorBuilder.cpp b/cpp/src/IceGrid/DescriptorBuilder.cpp index 8a8687f28a1..1a33cdd0c87 100644 --- a/cpp/src/IceGrid/DescriptorBuilder.cpp +++ b/cpp/src/IceGrid/DescriptorBuilder.cpp @@ -618,6 +618,15 @@ CommunicatorDescriptorBuilder::addObject(const XmlAttributesHelper& attrs) } void +CommunicatorDescriptorBuilder::addAllocatable(const XmlAttributesHelper& attrs) +{ + ObjectDescriptor object; + object.type = attrs("type", ""); + object.id = _communicator->stringToIdentity(attrs("identity")); + _descriptor->adapters.back().allocatables.push_back(object); +} + +void CommunicatorDescriptorBuilder::addDbEnv(const XmlAttributesHelper& attrs) { DbEnvDescriptor desc; diff --git a/cpp/src/IceGrid/DescriptorBuilder.h b/cpp/src/IceGrid/DescriptorBuilder.h index e34f6a79432..5e7267338f3 100644 --- a/cpp/src/IceGrid/DescriptorBuilder.h +++ b/cpp/src/IceGrid/DescriptorBuilder.h @@ -207,6 +207,7 @@ public: virtual void addAdapter(const XmlAttributesHelper&); virtual void setAdapterDescription(const std::string&); virtual void addObject(const XmlAttributesHelper&); + virtual void addAllocatable(const XmlAttributesHelper&); virtual void addDbEnv(const XmlAttributesHelper&); virtual void addDbEnvProperty(const XmlAttributesHelper&); virtual void setDbEnvDescription(const std::string&); diff --git a/cpp/src/IceGrid/DescriptorHelper.cpp b/cpp/src/IceGrid/DescriptorHelper.cpp index a91396db68b..73e8b5a0b1a 100644 --- a/cpp/src/IceGrid/DescriptorHelper.cpp +++ b/cpp/src/IceGrid/DescriptorHelper.cpp @@ -454,14 +454,14 @@ Resolver::operator()(const PropertySetDescriptorDict& propertySets) const } ObjectDescriptorSeq -Resolver::operator()(const ObjectDescriptorSeq& objects) const +Resolver::operator()(const ObjectDescriptorSeq& objects, const string& type) const { ObjectDescriptorSeq result; for(ObjectDescriptorSeq::const_iterator q = objects.begin(); q != objects.end(); ++q) { ObjectDescriptor obj; - obj.type = operator()(q->type, "object type"); - obj.id = operator()(q->id, "object identity"); + obj.type = operator()(q->type, type + " object type"); + obj.id = operator()(q->id, type + " object identity"); result.push_back(obj); } return result; @@ -878,10 +878,18 @@ CommunicatorHelper::getIds(multiset<string>& adapterIds, multiset<Ice::Identity> { adapterIds.insert(p->id); } - for(ObjectDescriptorSeq::const_iterator q = p->objects.begin(); q != p->objects.end(); ++q) + + set<Ice::Identity> ids; + ObjectDescriptorSeq::const_iterator q; + for(q = p->objects.begin(); q != p->objects.end(); ++q) + { + ids.insert(q->id); + } + for(q = p->allocatables.begin(); q != p->allocatables.end(); ++q) { - objectIds.insert(q->id); + ids.insert(q->id); } + objectIds.insert(ids.begin(), ids.end()); } } @@ -904,7 +912,8 @@ CommunicatorHelper::instantiateImpl(const CommunicatorDescriptorPtr& instance, c { resolve.exception("unknown replica group `" + adapter.replicaGroupId + "'"); } - adapter.objects = resolve(p->objects); + adapter.objects = resolve(p->objects, "well-known"); + adapter.allocatables = resolve(p->allocatables, "allocatable"); instance->adapters.push_back(adapter); // @@ -1003,9 +1012,21 @@ CommunicatorHelper::printObjectAdapter(Output& out, const AdapterDescriptor& ada } out << nl << "register process = `" << (adapter.registerProcess ? "true" : "false") << "'"; out << nl << "wait for activation = `" << (adapter.waitForActivation ? "true" : "false") << "'"; - for(ObjectDescriptorSeq::const_iterator p = adapter.objects.begin(); p != adapter.objects.end(); ++p) + ObjectDescriptorSeq::const_iterator p; + for(p = adapter.objects.begin(); p != adapter.objects.end(); ++p) + { + out << nl << "well-known object"; + if(!p->type.empty()) + { + out << sb; + out << nl << "identity = `" << _communicator->identityToString(p->id) << "' "; + out << nl << "type = `" << p->type << "'"; + out << eb; + } + } + for(p = adapter.allocatables.begin(); p != adapter.allocatables.end(); ++p) { - out << nl << "object"; + out << nl << "allocatable"; if(!p->type.empty()) { out << sb; @@ -2230,7 +2251,7 @@ ApplicationHelper::ApplicationHelper(const Ice::CommunicatorPtr& communicator, c ReplicaGroupDescriptor desc; desc.id = r->id; desc.description = resolve(r->description, "replica group description"); - desc.objects = resolve(r->objects); + desc.objects = resolve(r->objects, "well-known"); if(r->loadBalancing) { diff --git a/cpp/src/IceGrid/DescriptorHelper.h b/cpp/src/IceGrid/DescriptorHelper.h index b68c996c4d9..13715163c72 100644 --- a/cpp/src/IceGrid/DescriptorHelper.h +++ b/cpp/src/IceGrid/DescriptorHelper.h @@ -31,7 +31,7 @@ public: DistributionDescriptor operator()(const DistributionDescriptor&) const; PropertyDescriptorSeq operator()(const PropertyDescriptorSeq&, const std::string& = std::string("property")) const; PropertySetDescriptorDict operator()(const PropertySetDescriptorDict&) const; - ObjectDescriptorSeq operator()(const ObjectDescriptorSeq&) const; + ObjectDescriptorSeq operator()(const ObjectDescriptorSeq&, const std::string&) const; Ice::Identity operator()(const Ice::Identity&, const std::string&) const; PropertySetDescriptor operator()(const PropertySetDescriptor&) const; diff --git a/cpp/src/IceGrid/DescriptorParser.cpp b/cpp/src/IceGrid/DescriptorParser.cpp index e192a1ce380..8e7768b23d7 100644 --- a/cpp/src/IceGrid/DescriptorParser.cpp +++ b/cpp/src/IceGrid/DescriptorParser.cpp @@ -72,6 +72,7 @@ private: bool _isTopLevel; bool _inAdapter; + bool _inReplicaGroup; bool _inDbEnv; bool _inDistrib; }; @@ -85,6 +86,7 @@ DescriptorHandler::DescriptorHandler(const string& filename, const Ice::Communic _currentCommunicator(0), _isTopLevel(true), _inAdapter(false), + _inReplicaGroup(false), _inDbEnv(false) { } @@ -296,11 +298,11 @@ DescriptorHandler::startElement(const string& name, const IceXML::Attributes& at error("the <replica-group> element can only be a child of a <application> element"); } _currentApplication->addReplicaGroup(attributes); - _inAdapter = true; + _inReplicaGroup = true; } else if(name == "load-balancing") { - if(!_inAdapter || _currentServer.get()) + if(!_inReplicaGroup) { error("the <load-balancing> element can only be a child of a <replica-group> element"); } @@ -387,11 +389,11 @@ DescriptorHandler::startElement(const string& name, const IceXML::Attributes& at } else if(name == "object") { - if(!_inAdapter) + if(!_inAdapter && !_inReplicaGroup) { error("the <object> element can only be a child of an <adapter> or <replica-group> element"); } - if(!_currentCommunicator) + if(_inReplicaGroup) { _currentApplication->addObject(attributes); } @@ -400,6 +402,14 @@ DescriptorHandler::startElement(const string& name, const IceXML::Attributes& at _currentCommunicator->addObject(attributes); } } + else if(name == "allocatable") + { + if(!_inAdapter) + { + error("the <allocatable> element can only be a child of an <adapter>"); + } + _currentCommunicator->addAllocatable(attributes); + } else if(name == "distrib") { if(!_currentApplication.get() && (!_currentServer.get() || _currentServer.get() != _currentCommunicator)) @@ -590,14 +600,11 @@ DescriptorHandler::endElement(const string& name, int line, int column) { if(_inAdapter) { - if(_currentCommunicator) - { - _currentCommunicator->setAdapterDescription(elementValue()); - } - else - { - _currentApplication->setReplicaGroupDescription(elementValue()); - } + _currentCommunicator->setAdapterDescription(elementValue()); + } + else if(_inReplicaGroup) + { + _currentApplication->setReplicaGroupDescription(elementValue()); } else if(_inDbEnv) { @@ -658,7 +665,7 @@ DescriptorHandler::endElement(const string& name, int line, int column) } else if(name == "replica-group") { - _inAdapter = false; + _inReplicaGroup = false; } else if(name == "dbenv") { diff --git a/cpp/src/IceGrid/Makefile b/cpp/src/IceGrid/Makefile index 55e0babf1b1..ac1efca9084 100644 --- a/cpp/src/IceGrid/Makefile +++ b/cpp/src/IceGrid/Makefile @@ -61,6 +61,7 @@ REGISTRY_OBJS = RegistryI.o \ Allocatable.o \ AdapterCache.o \ ObjectCache.o \ + AllocatableObjectCache.o \ ServerCache.o \ NodeCache.o \ LocatorI.o \ diff --git a/cpp/src/IceGrid/ObjectCache.cpp b/cpp/src/IceGrid/ObjectCache.cpp index 29132c8c221..c2b58f08833 100644 --- a/cpp/src/IceGrid/ObjectCache.cpp +++ b/cpp/src/IceGrid/ObjectCache.cpp @@ -44,7 +44,7 @@ struct ObjectLoadCI : binary_function<pair<Ice::ObjectPrx, float>&, pair<Ice::Ob }; -ObjectCache::TypeEntry::TypeEntry() : _allocatablesCount(0) +ObjectCache::TypeEntry::TypeEntry() { } @@ -55,12 +55,6 @@ ObjectCache::TypeEntry::add(const ObjectEntryPtr& obj) // No mutex protection here, this is called with the cache locked. // _objects.insert(lower_bound(_objects.begin(), _objects.end(), obj, ObjectEntryCI()), obj); - _allocatablesCount += obj->isAllocatable() ? 1 : 0; - - if(!_requests.empty()) - { - canTryAllocate(obj, false); - } } bool @@ -69,93 +63,25 @@ ObjectCache::TypeEntry::remove(const ObjectEntryPtr& obj) // // No mutex protection here, this is called with the cache locked. // - _allocatablesCount -= obj->isAllocatable() ? 1 : 0; vector<ObjectEntryPtr>::iterator q = lower_bound(_objects.begin(), _objects.end(), obj, ObjectEntryCI()); assert(q->get() == obj.get()); _objects.erase(q); - - if(!_requests.empty() && !_allocatablesCount) - { - for(list<ObjectAllocationRequestPtr>::const_iterator p = _requests.begin(); p != _requests.end(); ++p) - { - (*p)->cancel(AllocationException("no allocatable objects with type `" + obj->getType() + "' registered")); - } - } return _objects.empty(); } -void -ObjectCache::TypeEntry::addAllocationRequest(const ObjectAllocationRequestPtr& request) -{ - // - // No mutex protection here, this is called with the cache locked. - // - assert(_allocatablesCount); - if(request->pending()) - { - _requests.push_back(request); - } -} - -bool -ObjectCache::TypeEntry::canTryAllocate(const ObjectEntryPtr& entry, bool fromRelease) -{ - // - // No mutex protection here, this is called with the cache locked. - // - list<ObjectAllocationRequestPtr>::iterator p = _requests.begin(); - while(p != _requests.end()) - { - AllocationRequestPtr request = *p; - try - { - if(request->isCanceled()) // If the request has been canceled, we just remove it. - { - p = _requests.erase(p); - } - else if(entry->tryAllocate(request, fromRelease)) - { - p = _requests.erase(p); - return true; // The request successfully allocated the entry! - } - else if(entry->getSession()) // If entry is allocated, we're done - { - return false; - } - else - { - ++p; - } - } - catch(const SessionDestroyedException&) - { - p = _requests.erase(p); - } - } - return false; -} - -bool -ObjectCache::TypeEntry::hasAllocatables() const -{ - return _allocatablesCount; -} - -ObjectCache::ObjectCache(const Ice::CommunicatorPtr& communicator, AdapterCache& adapterCache) : - _communicator(communicator), - _adapterCache(adapterCache) +ObjectCache::ObjectCache(const Ice::CommunicatorPtr& communicator) : _communicator(communicator) { } void -ObjectCache::add(const ObjectInfo& info, const string& application, bool allocatable, const AllocatablePtr& parent) +ObjectCache::add(const ObjectInfo& info, const string& application) { const Ice::Identity& id = info.proxy->ice_getIdentity(); Lock sync(*this); assert(!getImpl(id)); - ObjectEntryPtr entry = new ObjectEntry(*this, info, application, allocatable, parent); + ObjectEntryPtr entry = new ObjectEntry(*this, info, application); addImpl(id, entry); map<string, TypeEntry>::iterator p = _types.find(entry->getType()); @@ -207,51 +133,6 @@ ObjectCache::remove(const Ice::Identity& id) return entry; } -void -ObjectCache::allocateByType(const string& type, const ObjectAllocationRequestPtr& request) -{ - Lock sync(*this); - map<string, TypeEntry>::iterator p = _types.find(type); - if(p == _types.end() || !p->second.hasAllocatables()) - { - throw AllocationException("no allocatable objects with type `" + type + "' registered"); - } - - vector<ObjectEntryPtr> objects = p->second.getObjects(); - random_shuffle(objects.begin(), objects.end(), _rand); // TODO: OPTIMIZE - try - { - for(vector<ObjectEntryPtr>::const_iterator q = objects.begin(); q != objects.end(); ++q) - { - if((*q)->tryAllocate(request)) - { - return; - } - } - } - catch(const SessionDestroyedException&) - { - return; - } - - p->second.addAllocationRequest(request); -} - -bool -ObjectCache::canTryAllocate(const ObjectEntryPtr& entry) -{ - // - // Notify the type entry that an object was released. - // - Lock sync(*this); - map<string, TypeEntry>::iterator p = _types.find(entry->getType()); - if(p == _types.end()) - { - return false; - } - return p->second.canTryAllocate(entry, true); -} - Ice::ObjectProxySeq ObjectCache::getObjectsByType(const string& type) { @@ -304,16 +185,10 @@ ObjectCache::getAllByType(const string& type) return infos; } -ObjectEntry::ObjectEntry(ObjectCache& cache, - const ObjectInfo& info, - const string& application, - bool allocatable, - const AllocatablePtr& parent) : - Allocatable(allocatable, parent), +ObjectEntry::ObjectEntry(ObjectCache& cache, const ObjectInfo& info, const string& application) : _cache(cache), _info(info), - _application(application), - _destroyed(false) + _application(application) { } @@ -347,97 +222,3 @@ ObjectEntry::canRemove() return true; } -void -ObjectEntry::allocated(const SessionIPtr& session) -{ - // - // Add the object allocation to the session. The object will be - // released once the session is destroyed. - // - session->addAllocation(this); - - TraceLevelsPtr traceLevels = _cache.getTraceLevels(); - if(traceLevels && traceLevels->object > 1) - { - Ice::Trace out(traceLevels->logger, traceLevels->objectCat); - const Ice::Identity id = _info.proxy->ice_getIdentity(); - out << "object `" << _cache.communicator()->identityToString(id) << "' allocated by `" << session->getId() - << "' (" << _count << ")"; - } - - Glacier2::SessionControlPrx ctl = session->getSessionControl(); - if(ctl) - { - try - { - Ice::IdentitySeq seq(1); - seq.push_back(_info.proxy->ice_getIdentity()); - ctl->identities()->add(seq); - } - catch(const Ice::ObjectNotExistException&) - { - } - } -} - -void -ObjectEntry::released(const SessionIPtr& session) -{ - // - // Remove the object allocation from the session. - // - session->removeAllocation(this); - - Glacier2::SessionControlPrx ctl = session->getSessionControl(); - if(ctl) - { - try - { - Ice::IdentitySeq seq(1); - seq.push_back(_info.proxy->ice_getIdentity()); - ctl->identities()->remove(seq); - } - catch(const Ice::ObjectNotExistException&) - { - } - } - - TraceLevelsPtr traceLevels = _cache.getTraceLevels(); - if(traceLevels && traceLevels->object > 1) - { - Ice::Trace out(traceLevels->logger, traceLevels->objectCat); - const Ice::Identity id = _info.proxy->ice_getIdentity(); - out << "object `" << _cache.communicator()->identityToString(id) << "' released by `" << session->getId() - << "' (" << _count << ")"; - } -} - -void -ObjectEntry::destroy() -{ - SessionIPtr session; - { - Lock sync(*this); - _destroyed = true; - session = _session; - } - release(session); -} - -void -ObjectEntry::checkAllocatable() -{ - if(_destroyed) - { - throw ObjectNotRegisteredException(_info.proxy->ice_getIdentity()); - } - - Allocatable::checkAllocatable(); -} - -bool -ObjectEntry::canTryAllocate() -{ - return _cache.canTryAllocate(this); -} - diff --git a/cpp/src/IceGrid/ObjectCache.h b/cpp/src/IceGrid/ObjectCache.h index 079bfaf9465..fa2d9c92e93 100644 --- a/cpp/src/IceGrid/ObjectCache.h +++ b/cpp/src/IceGrid/ObjectCache.h @@ -11,26 +11,20 @@ #define ICE_GRID_OBJECTCACHE_H #include <IceUtil/Mutex.h> -#include <IceUtil/Shared.h> #include <Ice/CommunicatorF.h> #include <IceGrid/Cache.h> #include <IceGrid/Internal.h> -#include <IceGrid/Query.h> -#include <IceGrid/Allocatable.h> namespace IceGrid { class ObjectCache; -class ServerEntry; -typedef IceUtil::Handle<ServerEntry> ServerEntryPtr; - -class ObjectEntry : public Allocatable +class ObjectEntry : public IceUtil::Shared { public: - ObjectEntry(ObjectCache&, const ObjectInfo&, const std::string&, bool, const AllocatablePtr&); + ObjectEntry(ObjectCache&, const ObjectInfo&, const std::string&); Ice::ObjectPrx getProxy() const; std::string getType() const; std::string getApplication() const; @@ -38,66 +32,29 @@ public: bool canRemove(); - virtual void allocated(const SessionIPtr&); - virtual void released(const SessionIPtr&); - virtual bool canTryAllocate(); - - void destroy(); - virtual void checkAllocatable(); - private: ObjectCache& _cache; const ObjectInfo _info; const std::string _application; - bool _destroyed; }; typedef IceUtil::Handle<ObjectEntry> ObjectEntryPtr; -class ObjectAllocationRequest : public AllocationRequest -{ -public: - - ObjectAllocationRequest(const SessionIPtr& session) : AllocationRequest(session) { } - - virtual void response(const Ice::ObjectPrx&) = 0; - virtual void exception(const AllocationException&) = 0; - -private: - - virtual bool allocated(const AllocatablePtr& allocatable, const SessionIPtr& session) - { - response(ObjectEntryPtr::dynamicCast(allocatable)->getObjectInfo().proxy); - return true; - } - - virtual void canceled(const AllocationException& ex) - { - exception(ex); - } -}; -typedef IceUtil::Handle<ObjectAllocationRequest> ObjectAllocationRequestPtr; - -class AdapterCache; - class ObjectCache : public Cache<Ice::Identity, ObjectEntry> { public: - ObjectCache(const Ice::CommunicatorPtr&, AdapterCache&); + ObjectCache(const Ice::CommunicatorPtr&); - void add(const ObjectInfo&, const std::string&, bool, const AllocatablePtr&); + void add(const ObjectInfo&, const std::string&); ObjectEntryPtr get(const Ice::Identity&) const; ObjectEntryPtr remove(const Ice::Identity&); - void allocateByType(const std::string&, const ObjectAllocationRequestPtr&); - bool canTryAllocate(const ObjectEntryPtr&); - Ice::ObjectProxySeq getObjectsByType(const std::string&); ObjectInfoSeq getAll(const std::string&); ObjectInfoSeq getAllByType(const std::string&); - const Ice::CommunicatorPtr& communicator() const { return _communicator; } + const Ice::CommunicatorPtr& getCommunicator() const { return _communicator; } private: @@ -110,24 +67,15 @@ private: void add(const ObjectEntryPtr&); bool remove(const ObjectEntryPtr&); - void addAllocationRequest(const ObjectAllocationRequestPtr&); - bool canTryAllocate(const ObjectEntryPtr&, bool); - const std::vector<ObjectEntryPtr>& getObjects() const { return _objects; } - bool hasAllocatables() const; private: std::vector<ObjectEntryPtr> _objects; - std::list<ObjectAllocationRequestPtr> _requests; - int _allocatablesCount; }; - Ice::CommunicatorPtr _communicator; - AdapterCache& _adapterCache; - + const Ice::CommunicatorPtr _communicator; std::map<std::string, TypeEntry> _types; - std::map<std::string, std::vector<Ice::Identity> > _allocatablesByType; static std::pointer_to_unary_function<int, int> _rand; }; diff --git a/cpp/src/IceGrid/ServerCache.cpp b/cpp/src/IceGrid/ServerCache.cpp index 00a9e21f072..03ec1fdc3d5 100644 --- a/cpp/src/IceGrid/ServerCache.cpp +++ b/cpp/src/IceGrid/ServerCache.cpp @@ -14,6 +14,7 @@ #include <IceGrid/NodeCache.h> #include <IceGrid/AdapterCache.h> #include <IceGrid/ObjectCache.h> +#include <IceGrid/AllocatableObjectCache.h> #include <IceGrid/SessionI.h> #include <IceGrid/DescriptorHelper.h> @@ -61,11 +62,13 @@ namespace IceGrid ServerCache::ServerCache(const Ice::CommunicatorPtr& communicator, NodeCache& nodeCache, AdapterCache& adapterCache, - ObjectCache& objectCache) : + ObjectCache& objectCache, + AllocatableObjectCache& allocatableObjectCache) : _communicator(communicator), _nodeCache(nodeCache), _adapterCache(adapterCache), - _objectCache(objectCache) + _objectCache(objectCache), + _allocatableObjectCache(allocatableObjectCache) { } @@ -154,25 +157,24 @@ ServerCache::addCommunicator(const CommunicatorDescriptorPtr& comm, const Server const string application = server->getApplication(); for(AdapterDescriptorSeq::const_iterator q = comm->adapters.begin() ; q != comm->adapters.end(); ++q) { - if(!q->id.empty()) + assert(!q->id.empty()); + _adapterCache.addServerAdapter(q->id, q->replicaGroupId, server); + + ObjectDescriptorSeq::const_iterator r; + for(r = q->objects.begin(); r != q->objects.end(); ++r) { - _adapterCache.addServerAdapter(q->id, q->replicaGroupId, server); + ObjectInfo info; + info.type = r->type; + info.proxy = _communicator->stringToProxy(_communicator->identityToString(r->id) + "@" + q->id); + _objectCache.add(info, application); } - for(ObjectDescriptorSeq::const_iterator r = q->objects.begin(); r != q->objects.end(); ++r) + for(r = q->allocatables.begin(); r != q->allocatables.end(); ++r) { ObjectInfo info; info.type = r->type; - if(q->id.empty()) - { - const string edpts = IceGrid::getProperty(comm->propertySet.properties, q->name + ".Endpoints"); - info.proxy = _communicator->stringToProxy(_communicator->identityToString(r->id) + ":" + edpts); - } - else - { - info.proxy = _communicator->stringToProxy(_communicator->identityToString(r->id) + "@" + q->id); - } - _objectCache.add(info, application, true, server); + info.proxy = _communicator->stringToProxy(_communicator->identityToString(r->id) + "@" + q->id); + _allocatableObjectCache.add(info, server); } } } @@ -182,14 +184,16 @@ ServerCache::removeCommunicator(const CommunicatorDescriptorPtr& comm, const Ser { for(AdapterDescriptorSeq::const_iterator q = comm->adapters.begin() ; q != comm->adapters.end(); ++q) { - for(ObjectDescriptorSeq::const_iterator r = q->objects.begin(); r != q->objects.end(); ++r) + ObjectDescriptorSeq::const_iterator r; + for(r = q->objects.begin(); r != q->objects.end(); ++r) { _objectCache.remove(r->id); } - if(!q->id.empty()) + for(r = q->allocatables.begin(); r != q->allocatables.end(); ++r) { - _adapterCache.removeServerAdapter(q->id); + _allocatableObjectCache.remove(r->id); } + _adapterCache.removeServerAdapter(q->id); } } diff --git a/cpp/src/IceGrid/ServerCache.h b/cpp/src/IceGrid/ServerCache.h index 47837584468..48a3515b084 100644 --- a/cpp/src/IceGrid/ServerCache.h +++ b/cpp/src/IceGrid/ServerCache.h @@ -14,15 +14,17 @@ #include <IceUtil/Shared.h> #include <IceGrid/Descriptor.h> #include <IceGrid/Internal.h> +#include <IceGrid/Query.h> #include <IceGrid/Allocatable.h> #include <IceGrid/Cache.h> -#include <IceGrid/AdapterCache.h> namespace IceGrid { class ServerCache; class ObjectCache; +class AdapterCache; +class AllocatableObjectCache; class NodeCache; class NodeEntry; @@ -86,7 +88,7 @@ class ServerCache : public CacheByString<ServerEntry> { public: - ServerCache(const Ice::CommunicatorPtr&, NodeCache&, AdapterCache&, ObjectCache&); + ServerCache(const Ice::CommunicatorPtr&, NodeCache&, AdapterCache&, ObjectCache&, AllocatableObjectCache&); ServerEntryPtr add(const ServerInfo&); ServerEntryPtr get(const std::string&) const; @@ -110,6 +112,7 @@ private: NodeCache& _nodeCache; AdapterCache& _adapterCache; ObjectCache& _objectCache; + AllocatableObjectCache& _allocatableObjectCache; }; }; diff --git a/cpp/test/IceGrid/activation/application.xml b/cpp/test/IceGrid/activation/application.xml index f827361cd8f..e5e79e19a07 100644 --- a/cpp/test/IceGrid/activation/application.xml +++ b/cpp/test/IceGrid/activation/application.xml @@ -11,6 +11,7 @@ activation="${activation}" activation-timeout="4" deactivation-timeout="3"> <adapter name="TestAdapter" endpoints="default" register-process="true"> <object identity="${server}" type="Test"/> + <allocatable identity="${server}" type="Test"/> </adapter> <property name="ActivationDelay" value="${activation-delay}"/> <property name="DeactivationDelay" value="${deactivation-delay}"/> diff --git a/cpp/test/IceGrid/allocation/AllTests.cpp b/cpp/test/IceGrid/allocation/AllTests.cpp index b9331e9329d..6f2db328b9d 100644 --- a/cpp/test/IceGrid/allocation/AllTests.cpp +++ b/cpp/test/IceGrid/allocation/AllTests.cpp @@ -388,7 +388,12 @@ allTests(const Ice::CommunicatorPtr& communicator) } catch(const AllocationException&) { + test(false); } + catch(const ObjectNotRegisteredException&) + { + } + try { session2->allocateObjectById(communicator->stringToIdentity("nonallocatable")); @@ -396,7 +401,12 @@ allTests(const Ice::CommunicatorPtr& communicator) } catch(const AllocationException&) { + test(false); } + catch(const ObjectNotRegisteredException&) + { + } + try { session1->releaseObject(communicator->stringToIdentity("nonallocatable")); @@ -404,7 +414,12 @@ allTests(const Ice::CommunicatorPtr& communicator) } catch(const AllocationException&) { + test(false); } + catch(const ObjectNotRegisteredException&) + { + } + try { session2->releaseObject(communicator->stringToIdentity("nonallocatable")); @@ -412,6 +427,10 @@ allTests(const Ice::CommunicatorPtr& communicator) } catch(const AllocationException&) { + test(false); + } + catch(const ObjectNotRegisteredException&) + { } session1->allocateObjectById(allocatable); diff --git a/cpp/test/IceGrid/allocation/application.xml b/cpp/test/IceGrid/allocation/application.xml index 05ff652f748..a520ab4deb3 100644 --- a/cpp/test/IceGrid/allocation/application.xml +++ b/cpp/test/IceGrid/allocation/application.xml @@ -2,11 +2,6 @@ <application name="Test"> - <replica-group id="Test"> - <object identity="nonallocatable" type="::Test"/> - <object identity="nonallocatable2" type="::NotAllocatable"/> - </replica-group> - <server-template id="Glacier2"> <parameter name="id"/> <parameter name="endpoints"/> @@ -35,51 +30,55 @@ <server id="ObjectAllocation" exe="${test.dir}/server" activation="on-demand" pwd="."> <adapter name="Server" endpoints="default"> - <object identity="allocatable" type="::Test"/> - <object identity="allocatablebis" type="::TestBis"/> + <allocatable identity="allocatable" type="::Test"/> + <allocatable identity="allocatablebis" type="::TestBis"/> + + <object identity="nonallocatable" type="::Test"/> + <object identity="nonallocatable2" type="::NotAllocatable"/> </adapter> </server> <server id="ServerAllocation" exe="${test.dir}/server" activation="on-demand" pwd="." allocatable="true"> <adapter name="Server" endpoints="default" id="ServerAlloc"> - <object identity="allocatable3" type="::TestServer1"/> - <object identity="allocatable4" type="::TestServer2"/> + <allocatable identity="allocatable3" type="::TestServer1"/> + <allocatable identity="allocatable4" type="::TestServer2"/> + <object identity="allocatable4"/> - <object identity="allocatable31" type="::TestMultipleByServer"/> - <object identity="allocatable41" type="::TestMultipleByServer"/> + <allocatable identity="allocatable31" type="::TestMultipleByServer"/> + <allocatable identity="allocatable41" type="::TestMultipleByServer"/> </adapter> </server> <server id="ServerAllocation-1" exe="${test.dir}/server" activation="on-demand" pwd="." allocatable="true"> <adapter name="Server" endpoints="default"> - <object identity="allocatable5" type="::TestMultipleServer"/> + <allocatable identity="allocatable5" type="::TestMultipleServer"/> </adapter> </server> <server id="ServerAllocation-2" exe="${test.dir}/server" activation="on-demand" pwd="." allocatable="true"> <adapter name="Server" endpoints="default"> - <object identity="allocatable6" type="::TestMultipleServer"/> + <allocatable identity="allocatable6" type="::TestMultipleServer"/> </adapter> </server> <server id="ServerStress-1" exe="${test.dir}/server" activation="on-demand" pwd="."> <adapter name="Server" endpoints="default"> - <object identity="stress-1" type="::StressTest"/> - <object identity="stress-2" type="::StressTest"/> + <allocatable identity="stress-1" type="::StressTest"/> + <allocatable identity="stress-2" type="::StressTest"/> </adapter> </server> <server id="ServerStress-2" exe="${test.dir}/server" activation="on-demand" pwd="." allocatable="true"> <adapter name="Server" endpoints="default"> - <object identity="stress-3" type="::StressTest"/> - <object identity="stress-4" type="::StressTest"/> + <allocatable identity="stress-3" type="::StressTest"/> + <allocatable identity="stress-4" type="::StressTest"/> </adapter> </server> <server id="ServerStress-3" exe="${test.dir}/server" activation="on-demand" pwd="." allocatable="true"> <adapter name="Server" endpoints="default"> - <object identity="stress-5" type="::StressTest"/> - <object identity="stress-6" type="::StressTest"/> + <allocatable identity="stress-5" type="::StressTest"/> + <allocatable identity="stress-6" type="::StressTest"/> </adapter> </server> |