IceGrid provides a resource allocation facility that coordinates access to the objects and servers of an IceGrid application. To allocate a resource for exclusive use, a client must first establish a session by authenticating itself with the IceGrid registry or a Glacier2 router, after which the client may reserve objects and servers that the application indicates are allocatable. The client should release the resource when it is no longer needed, otherwise IceGrid reclaims it when the client's session terminates or expires due to inactivity.
An allocatable server offers at least one allocatable object. The server is considered to be allocated when its first allocatable object is claimed, and is not released until all of its allocated objects are released. While the server is allocated by a client, no other clients can allocate its objects.
On this page:
A client must create an IceGrid session before it can allocate objects. If you have configured a Glacier2 router to use IceGrid's session managers, the client's router session satisfies this requirement.
In the absence of Glacier2, an IceGrid client invokes createSession
or createSessionFromSecureConnection
on IceGrid's Registry
interface to create a session:
{zcode:slice} module IceGrid { exception PermissionDeniedException { string reason; }; interface Registry { Session* createSession(string userId, string password) throws PermissionDeniedException; Session* createSessionFromSecureConnection() throws PermissionDeniedException; idempotent int getSessionTimeout(); }; }; {zcode} |
The createSession
operation expects a username and password and returns a session proxy if the client is allowed to create a session. By default, IceGrid does not allow the creation of sessions. You must define the registry property IceGrid.Registry.PermissionsVerifier
with the proxy of a permissions verifier object to enable session creation with createSession
.
The createSessionFromSecureConnection
operation does not require a username and password because it uses the credentials supplied by an SSL connection to authenticate the client. As with createSession
, you must enable session creation by configuring the proxy of a permissions verifier object so that clients can use createSessionFromSecureConnection
to create a session. In this case, the property is IceGrid.Registry.SSLPermissionsVerifier
.
To create a session, the client obtains the registry proxy by converting the well-known proxy string "IceGrid/Registry"
to a proxy object with the communicator, downcasts the proxy to the IceGrid::Registry
interface, and invokes on one of the operations. The sample code below demonstrates how to do it in C++; the code will look very similar in other language mappings.
{zcode:cpp} Ice::ObjectPrx base = communicator->stringToProxy("IceGrid/Registry"); IceGrid::RegistryPrx registry = IceGrid::RegistryPrx::checkedCast(base); string username = ...; string password = ...; IceGrid::SessionPrx session; try { session = registry->createSession(username, password); } catch (const IceGrid::PermissionDeniedException & ex) { cout << "permission denied:\n" << ex.reason << endl; } {zcode} |
The identity of the registry object may change based on its configuration settings. |
After creating the session, the client must keep it alive by periodically invoking its keepAlive
operation. The session expires if the client does not invoke keepAlive
within the configured timeout period, which can be obtained by calling the getSessionTimeout
operation on the Registry
interface.
If a session times out, or if the client explicitly terminates the session by invoking its destroy
operation, IceGrid automatically releases all objects allocated using that session.
As described above, you must configure the IceGrid registry with the proxy of at least one permissions verifier object to enable session creation:
IceGrid.Registry.PermissionsVerifier
Glacier2::PermissionsVerifier
. Defining this property allows clients to create sessions using createSession
.IceGrid.Registry.SSLPermissionsVerifier
Glacier2::SSLPermissionsVerifier
. Defining this property allows clients to create sessions using createSessionFromSecureConnection
.IceGrid supplies built-in permissions verifier objects:
{zcode} IceGrid.Registry.PermissionsVerifier=<instance-name>/NullPermissionsVerifier {zcode} |
{zcode} IceGrid.Registry.SSLPermissionsVerifier=<instance-name>/NullSSLPermissionsVerifier {zcode} |
IceGrid.Registry.CryptPasswords
with the pathname of the password file. Note that this property is ignored if you specify the proxy of a permissions verifier object using IceGrid.Registry.PermissionsVerifier
.You can also implement your own permissions verifier object.
A client allocates objects using the session proxy returned from createSession
or createSessionFromSecureConnection
. The proxy supports the Session
interface shown below:
{zcode:slice} module IceGrid { exception ObjectNotRegisteredException { Ice::Identity id; }; exception AllocationException { string reason; }; exception AllocationTimeoutException extends AllocationException { }; interface Session extends Glacier2::Session { idempotent void keepAlive(); Object* allocateObjectById(Ice::Identity id) throws ObjectNotRegisteredException, AllocationException; Object* allocateObjectByType(string type) throws AllocationException; void releaseObject(Ice::Identity id) throws ObjectNotRegisteredException, AllocationException; idempotent void setAllocationTimeout(int timeout); }; }; {zcode} |
The client is responsible for keeping the session alive by periodically invoking keepAlive
, as discussed earlier.
The allocateObjectById
operation allocates and returns the proxy for the allocatable object with the given identity. If no allocatable object with the given identity is registered, the client receives ObjectNotRegisteredException
. If the object cannot be allocated, the client receives AllocationException
. An allocation attempt can fail for the following reasons:
The allocateObjectByType
operation allocates and returns a proxy for an allocatable object registered with the given type. If more than one allocatable object is registered with the given type, the registry selects one at random. The client receives AllocationException
if no objects with the given type could be allocated. An allocation attempt can fail for the following reasons:
The releaseObject
operation releases an object allocated by the session. The client receives ObjectNotRegisteredException
if no allocatable object is registered with the given identity and AllocationException
if the object is not allocated by the session. Upon session destruction, IceGrid automatically releases all allocated objects.
The setAllocationTimeout
operation configures the timeout used by the allocation operations. If no allocatable objects are available when the client invokes allocateObjectById
or allocateObjectByType
, IceGrid waits for the specified timeout period for an allocatable object to become available. If the timeout expires, the client receives AllocationTimeoutException
.
A client does not need to explicitly allocate a server. If a server is allocatable, IceGrid implicitly allocates it to the first client that claims one of the server's allocatable objects. Likewise, IceGrid releases the server when all of its allocatable objects are released.
Server allocation is useful in two situations:
session
activation mode, in which the server is activated on demand when allocated by a client and deactivated upon release.IceGrid's resource allocation facility allows clients to coordinate access to objects and servers but does not place any restrictions on client invocations to allocated objects; any client that has a proxy for an allocated object could conceivably invoke an operation on it. IceGrid assumes that clients are cooperating with each other and respecting allocation semantics.
To prevent unauthorized clients from invoking operations on an allocated object or server, you can use IceSSL or Glacier2:
IceSSL.TrustOnly.Server
or IceSSL.TrustOnly.Server.AdapterName
. For example, if you configure a server with the session activation mode, you can set one of the IceSSL.TrustOnly
properties to the ${session.id
}
variable, which is substituted with the session ID when the server is activated for the session. If the IceGrid session was created from a secure connection, the session ID will be the distinguished name associated with the secure connection, which effectively restricts access to the server or one of its adapters to the client that established the session with IceGrid.Allocatable objects are registered using a descriptor that is similar to well-known object descriptors. Allocatable objects cannot be replicated and therefore can only be specified within an object adapter descriptor.
Servers can be specified as allocatable by setting the server descriptor's allocatable
attribute.
As an example, the following application defines an allocatable server and an allocatable object:
{zcode:xml} <icegrid> <application name="Ripper"> <node name="Node1"> <server id="EncoderServer" exe="/opt/ripper/bin/server" activation="on-demand" allocatable="true"> <adapter name="EncoderAdapter" id="EncoderAdapter" endpoints="tcp"> <allocatable identity="EncoderFactory" type="::Ripper::MP3EncoderFactory"/> </adapter> </server> </node> </application> </icegrid> {zcode} |
We can use the allocation facility in our MP3 encoder factory to coordinate access to the MP3 encoder factories. First we need to modify the descriptors to define an allocatable object:
{zcode:xml} <icegrid> <application name="Ripper"> <server-template id="EncoderServerTemplate"> <parameter name="index"/> <server id="EncoderServer${index}" exe="/opt/ripper/bin/server" activation="on-demand"> <adapter name="EncoderAdapter" endpoints="tcp"> <allocatable identity="EncoderFactory${index}" type="::Ripper::MP3EncoderFactory"/> </adapter> </server> </server-template> <node name="Node1"> <server-instance template="EncoderServerTemplate" index="1"/> </node> <node name="Node2"> <server-instance template="EncoderServerTemplate" index="2"/> </node> </application> </icegrid> {zcode} |
Next, the client needs to create a session and allocate a factory:
{zcode:cpp} Ice::ObjectPrx obj = session->allocateObjectByType(Ripper::MP3EncoderFactory::ice_staticId()); try { Ripper::MP3EncoderPrx encoder = factory->createEncoder(); // Use the encoder to encode a file ... } catch (const Ice::LocalException & ex) { // There was a problem with the encoding, we catch the // exception to make sure we release the factory. } session->releaseObject(obj->ice_getIdentity()); {zcode} |
It is important to release an allocated object when it is no longer needed so that other clients may use it. If you forget to release an object, it remains allocated until the session is destroyed.