好多不懂的。。。mlgbd
对象适配器
一个通信器含有一个或更多对象适配器。对象适配器处在Ice run time
和服务器之间的界线上,负有这样一些责任:一个通信器含有一个或更多对象适配器。对象适配器处在Ice run time
和服务器之间的界线上,负有这样一些责任:
• 它把Ice对象映射到到来请求的servant,并把请求分派给每个servant中的
应用代码(也就是说,对象适配器实现了一个向上调用接口,把Ice
run time 与服务器中的应用代码连接在一起)。
• 它协助进行生命周期操作,使得Ice对象和servant在创建和销毁时不会出
现竞争状况。
• 它提供一个或更多传输端点。客户通过这些端点访问适配器所提供的Ice
对象(创建没有端点的对象适配器也是可能的。这样的适配器被用于
双向回调——参见第24 章)。
每个对象适配器都有一个或更多servant,对Ice 对象进行体现;同时还
有一个或更多传输端点。如果对象适配器拥有的传输端点不止一个,所有
向该适配器作了注册的servant 可以在任何一个端点上响应到来的请求。换
句话说,如果对象适配器有多个传输端点,这些端点代表的是通往同一组
对象的不同通信路径(例如,通过不同的传输机制)。
每个对象适配器都只属于一个通信器(但一个通信器可以有多个对象
适配器)。
每个对象适配器可以非强制性地拥有自己的线程池,你可以通过
<adapter-name>.ThreadPool.Size 属性来使用这个特性(参见附录
C)。如果使用了这个特性,在分派针对该适配器的客户调用时,使用的是
适配器的线程池中的线程,而不会使用通信器的服务器线程池中的线程。
活动Servant 映射表 :
每个对象适配器都维护有一个叫作活动servant 映射表(active servant
map)的数据结构。 活动servant 映射表(简称为ASM)是一个查找表,用
于把对象标识映射到servant:在C++ 里,查找值是智能指针,指向对应的
servant 在内存中的位置;
当客户把操作调用发给服务器时,请求的目标是特定的传输端点。传输端
点隐含地标识了请求所针对的对象适配器(因为同一个端点只能绑定到一
个对象适配器)
客户藉以发送请求的代理含有对应的对象的标识,客户
端run time 会在线路上随调用一起发送这个对象标识。对象适配器继而使
用这个对象标识、在它的ASM 中查找正确的servant,把调用分派给它
经由代理、把请求关联到正确的servant 的过程叫作绑定。图16.1 的例
子所描述的是直接绑定 :传输端点是嵌在代理中的
如果在适配器的ASM 中,客户请求所包含的对象标识没有对应的条
目,适配器就会把ObjectNotExistException 返回给客户
对象适配器接口 :
对象适配器是本地接口
module Ice {
local interface ObjectAdapter {
string getName();
Communicator getCommunicator();
Object* add(Object servant, Identity id);
Object* addWithUUID(Object servant);
void remove(Identity id);
void activate();
void hold();
void waitForHold();
void deactivate();
void waitForDeactivate();
// ...
};
};
• getName 操作返回适配器的名字,这个名字是在调用Communicator::createObjectAdapter 或Communicator::createObjectAdapter-WithEndpoints 时传入的。
• getCommunicator 操作返回先前用于创建该适配器的通信器。注意,在ObjectAdapter 接口中还有其他操作;我们将在本章余下的各个部分讨论这些操作。
对象适配器提供了一些操作,用于管理servant 激活和解除激活:
Servant 激活与解除激活
术语servant 激活指的是,向Ice run time 告知某个Ice 对象的servant 的
存在。如果你激活一个servant,在图16.1 所示的活动servant 映射表中就会
增加一个条目。看待servant 激活的另一种方式是,把它看成是在“Ice 对
象的标识”与“对应的用编程语言编写的、负责为该Ice 对象处理请求的
servant”之间创建链接。一旦Ice run time 知道了这个链接,它就可以把到
来的请求分派给正确的servant。如果没有这样的链接,也就是说,在ASM
中没有对应的条目,针对该标识的到来请求就会引发
ObjectNotExistException。一旦servant 被激活,我们就认为它体现了对应
的Ice 对象。
与之相反的操作叫作servant 解除激活。如果你解除某个servant 的激
活,就会从ASM 中移除针对特定标识的一个条目。 自此以后,针对该标识
的到来请求就不会再分派给servant,并且会引发
ObjectNotExistException。
这些操作的行为是:
• add add 操作把一个具有指定标识的servant 增加到ASM中。一旦add 被调用,请求就会分派给这个servant。返回值是这个servant 所体现的Ice对象的代理。这个代理嵌有传给add 的标识。
注意,通过不同的标识多次激活同一个servant,这是可能的。在这
种情况下,同一个servant 将体现多个Ice 对象。我们将在16.7.2 节更详
细地探索这个特性的影响。
• addWithUUID addWithUUID 操作的行为和add 操作一样,但你不需要为servant 提供标识。addWithUUID 会生成一个UUID (参见[14]),作为对应的Ice 对
象的标识。你可以调用返回的代理的ice_getIdentity 操作,取得生成的标识。addWithUUID 可用于创建临时对象的标识,比如短期存在的对象
• remove remove 操作中断标识与其servant 之间的关联,从ASM 中移除对应的条目。一旦servant 解除了激活,新到来的针对已移除标识的请求会引
发ObjectNotExistException。当remove 被调用时,正在servant 中执行的请求可以正常完成。一旦servant 的最后一个请求完成,对象适配器就会丢弃它的智能指针这时,如果你不再持有指向这个servant 的引用或智能指针,它就可以被销毁实际效果就是,一旦解除了激活的servant 空闲下来,它就会被销毁。如果你解除对象适配器的激活,将会隐含地调用它的活动servants 的remove 操作
对象适配器具有以下处理状态(processing state):
适配器状态
• 扣留状态(holding)
在这种状态下,适配器的任何到来的请求都会被“扣留”,也就是
说,不会被分派给servant。
在使用TCP/IP (及其他面向流的协议)当被调用时,如果适配器处
在扣留状态,服务器端run time 就会停止从对应的传输端点读取数据。
此外,它也不接受客户发送的连接请求。这意味着,如果客户向处在扣
留状态的适配器发送请求,客户最终会收到TimeoutException 或
ConnectTimeoutException (除非在定时器超时之前,适配器变成了活
动状态)。
在使用UDP 时,如果客户请求到达处在扣留状态的适配器,请求将
被丢弃。
刚创建的适配器都处在扣留状态。这意味着,在你让适配器变成活
动状态之前,请求不会被分派。
• 活动状态
在这种状态下,适配器会接受到来的请求,把它们分派给servant。
新创建的适配器一开始处在扣留状态。只要你让适配器变成活动状态,
它就会开始分派请求。
你可以随意在活动和扣留状态之间转换。
• 不活动
在这种状态下,适配器在概念上已经被销毁(或处在销毁过程
中)。解除适配器的激活会销毁与该适配器相关联的所有传输端点。当
适配器变成不活动状态时,仍在执行的请求可以完成,但适配器不会再
接受新的请求(发出新请求的客户会收到异常)。一旦适配器解除了激
活,你不能再在同一进程中重新激活它。
ObjectAdapter 接口提供了一些操作,允许你改变适配器状态,或者等
待状态改变完成:
• activate
activate 操作让适配器变成活动状态。激活已经处在活动状态的适
配器没有任何效果。一旦activate 被调用, Ice run time 就会开始把请
求分派给适配器的servants。
• hold
hold 操作让适配器变成扣留状态。在调用hold 之后到达的请求都会
像第373 页所说的那样被扣留。在hold 被调用时正在执行的请求可以
正常完成。注意, hold 会立即返回,不会等待正在执行的请求完成。
• waitForHold
waitForHold 操作挂起发出调用的线程,直到适配器迁移到扣留状态
为止,也就是说,直到正在执行的所有请求完成为止。你可以从多个线
程调用waitForHold,也可以在适配器处在活动状态时调用
waitForHold。如果适配器处在不活动状态,对它调用waitForHold 不会
做任何事情,并且会立即返回。
• deactivate 操作让适配器变成不活动状态。在调用deactivate 之后
到达的请求会被拒绝,但正在执行的请求可以完成。一旦适配器处在不
活动状态,它不能再被重新激活。如果适配器处在不活动状态,对它调
用activate、hold、waitForHold,或deactivate 没有任何效果。一
旦变得空闲,与该适配器相关联的任何servants 都会被销毁。注意,
deactivate 会立即返回,不会等待正在执行的请求完成。
• waitForDeactivate
waitForDeactivate 操作挂起发出调用的线程,直到适配器迁移到不
活动状态为止,也就是说,直到所有正在执行的线程完成、所有的传输
端点关闭、所有相关联的servants 销毁为止。你可以从多个线程调用
waitForDeactivate,也可以在适配器处在活动或扣留状态时调用
waitForDeactivate。如果适配器处在不活动状态,对它调用wait-
ForDeactivate 不会做任何事情,并且会立即返回。