Документ взят из кэша поисковой машины. Адрес
оригинального документа
: http://rtm-cs.sinp.msu.ru/manual/mico/doc/node40.html
Дата изменения: Mon Jun 7 21:54:58 1999 Дата индексирования: Mon Oct 1 21:22:04 2012 Кодировка: |
In the last section we saw two cases where an object had to be ``moved'' between two different instances of a server:
In all these cases the state of the moved object has to be saved before and restored after moving. Because the BOA has no information about the internal state of an object the user has to provide code for saving and restoring. However, the BOA offers you some support methods.
Saving is done in the _save_object()
method of the object
implementation. If you do not provide this method for an object,
_save_object()
from the base class will be used, which will cause
the object to be treated as transient (i.e., it will not be restored
later). Let us again consider the account example. The internal
state of an account object consists of the current balance. Here is how to
save the state:
1: // account_server3.cc
2:
3: #include "account.h"
4: #include <iostream.h>
5: #include <fstream.h>
6:
7: class Account_impl : virtual public Account_skel {
8: CORBA::Long _current_balance;
9: public:
10: ...
11: virtual CORBA::Boolean _save_object ()
12: {
13: ofstream out (_ident());
14: out << _current_balance;
15: return TRUE;
16: }
17: };
Pretty simple, eh? We just open a file and write the balance into it. The
only noteworthy thing is the file name, which is obtained by using the
_ident()
method. The returned string is guaranteed to be unique
among all objects managed by a single BOA daemon. If you use multiple
BOA daemons or use persistent servers that do not register with the BOA
you have to make sure no name clashes occur. One way to do this is to
create a new directory where all the files are created, in our example
/tmp/account/
would be appropriate. Another way to distinguish
different instances (objects) of on interface (class) is to use
BOA::ReferenceData
. See demo/boa/account2
for an example.
Restoring the state takes a bit more code. You need to subclass the
abstract baseclass CORBA::BOAObjectRestorer
providing an
implementation for the restore()
method:
1: // account_server3.cc
2:
3: class AccountLoader : public CORBA::BOAObjectRestorer {
4: public:
5: CORBA::Boolean restore (CORBA::Object_ptr obj)
6: {
7: if (!strcmp (obj->_repoid(), "IDL:Account:1.0")) {
8: new Account_impl (obj);
9: return TRUE;
10: }
11: // dont know about such objects
12: return FALSE;
14: }
15: };
restore()
receives an object reference for the object that has to
be restored. We use the _repoid()
method to find out the
repository id of the object to be restored. If it is equal to the
repository id of account objects ("IDL:Account:1.0"
) we can go on
with restoring, otherwise we just return FALSE
indicating that
we cannot restore the object.
Restoring the object is now just a matter of calling a special
Account_impl
constructor which we still have to define:
1: // account_server3.cc
2:
3: class Account_impl : virtual public Account_skel {
4: CORBA::Long _current_balance;
5: public:
6: ...
7: Account_impl (CORBA::Object_ptr obj)
8: : Account_skel (obj)
9: {
10: ifstream in (obj->_ident());
11: in >> _current_balance;
12: }
13: };
The constructor is basically the counterpart to _save_object()
.
It uses _ident()
to obtain the identification string of the
object to be restored, opens the associated file and reads in the
current balance. Note the invocation of the base class constructor in
line 8, which is very important. If you forget this line the code will
still compile but will give you strange results, because the default
Account_skel
constructor will be used, which is an error.
Note that we have omitted error handling for the ease of exposition.
Usually one would check if the file exists and its contents are valid.
If an error is detected you should make
AccountLoader::restore()
return
FALSE
.
Now what is left to do is to create an instance of the
AccountLoader
class. Note that you have to create at least
one such instance before you do ORB and BOA initialization,
because restoring can already occur during BOA initialization. Of
course you can create serveral different BOAObjectRestorer
subclasses each of which handles special kinds of objects. When an
object has to be restored the restore()
methods of the existing
restorer objects are called until eventually one returns TRUE
.
Note that you should not create new objects if any objects are being
restored, because otherwise you would get an infinitely growing number
of objects over time. The BOA method restoring()
returns
TRUE
if objects are being restored, FALSE
otherwise.
Here is the main()
function:
1: // account_server3.cc
2:
3: int main (int argc, char *argv[])
4: {
5: // create loader *before* BOA initialization
6: AccountLoader loader;
7:
8: CORBA::ORB_var orb = CORBA::ORB_init (argc, argv, "mico-local-orb");
9: CORBA::BOA_var boa = orb->BOA_init (argc, argv, "mico-local-boa");
10:
11: if (!boa->restoring()) {
12: // create new objects only if not restoring
13: new Account_impl;
14: }
15: boa->impl_is_ready (CORBA::ImplementationDef::_nil());
16: orb->run ();
17: return 0;
18: }
In an unshared or per method server you would call
boa->obj_is_ready (CORBA::Object::_nil(), CORBA::ImplementationDef::_nil());
instead of impl_is_ready()
. The sources for a complete example
can be found in demo/boa/account2
.
Sometimes it is handy to know when saving of objects can occur. But you cannot rely on this being the only occurences of object saving:
_save_object()
method return FALSE
or do not provide a
_save_object()
method at all. The object will then be treated as
transient (i.e., it will not outlive the process it was created in).
deactivate_obj()
on an object in an unshared or
per method server saving is done during the call to deactivate_obj()
.
Objects saved this way will not be saved again at server exit
according to 1.
deactivate_impl()
in a shared or persistent server
saving of all currently activate objects is done during the call to
deactivate_impl()
.
Objects saved this way will not be saved again at server exit
according to 1.
change_implementation()
, see section 4.3.6 for details.
Objects saved this way will not be saved again at server exit
according to 1.
Note that it is quite likely that invocations on objects will occure
after a call to deactivate_obj()
, deactivate_impl()
, or
change_implementation()
because the server has to execute all
(buffered) invocations that arrived up until your call to one of the
above mentioned methods. So your code must be prepared to handle this.
Although the actual code for saving and restoring the state of an account object are two-liners each real world applications often require complex code for making objects persistent. Therefore the OMG has specified the Persistent Object Service (POS), an implementation of which is not yet provided by MICO.