
                      OSIMIS CHANGES IN ICM RELEASE 4.0

This document outlines the changes in the ICM OSIMIS release 4.0 mainly
since the release 3.3. There is similar information for changes from
3.0/3.2 to 3.3. Emphasis is placed to the non backwards-compatible changes.
Important additions are also mentioned but this document does NOT serve
as a manual for those.

This document should be read very carefully before converting previous
code to work under 4.0 and its guidelines should be followed to the letter.
Please take also into account the list of common errors compiled at the
end of this document - this list reflects other people's experiences in
converting code.



PEPY -> PEPSY CONVERSION
------------------------

OSIMIS uses now pepsy only and not a mixture of pepy/pepsy as before.
See the document pepsy.txt for details. The only necessary non backwards
compatible API change is that the type_SMI_StringList structure in SmiAsn.h
is now called StringListVal according to the OSIMIS naming conversion
for hand-crafted structures that correspond to ASN.1 types.
Its string member is now called string instead of IA5String.



ATTRIBUTES
----------

A number of new attributes were introduced:

SimpleNameType, RealList, IA5String, GraphicString, PrintableString,
IA5StringList, GraphicStringList, PrintableStringList,
AttributeIdList, ObjectInstanceList, Scope

The String and StringList attributes still exist but they now default
to GraphicString and GraphicStringList respectively. You are encouraged
to use the exact type (Graphic, Printable, IA5) for string syntaxes
in GDMO definitions rather than using String and StringList.
Note that you will need to change your oidtable.at to replace the
String and StringList syntaxes with GraphicString and GraphicStringList
respectively. Bear im mind that GraphicString is a more restricted character
set than IA5String. In particular, the '_' (underscore) and '"' (double quote)
characters are not supported, please use '-' (hyphen) and ''' (single quote)
instead.

All the naming attributes of DMI objects are now of type SimpleNameType.
If for any reason you access the systemId, discriminatorId and scannerId,
you have to treat them as SimpleNameType. You may look at methods
to manipulate the latter in h/SimpleNameType.h.



A Attr::_getelem virtual method for list syntaxes was added. This
and the existing Attr::_getnext one are encapsulated by the public
methods Attr::getElem and Attr::getNext which can be used to walk
through the elements of a list attribute in C++ style:

    void* cur = NULLVD; // NULLVD signifies the beginning

    while (cur = intList->getNext(cur)) {
        int* elem = (int*) intList->getElem(cur);
        printf("int is %d\n", *elem);
    }

instead of the C-style used before (still valid):

    IntegerListVal* cur = (IntegerListVal*) intList->getval();

    while (cur) {
	int elem = cur->integer;
        // do something with elem
        cur = cur->next;
    }


Now all the Structure/Definition of Management Information Syntaxes (SMI/DMI)
are in the directory $(TOP)/agent/smi in the library libsmisntx.a,
including the C++ attribute classes which were previously in libgms.a .
This means that managing applications can now use the exact
syntax type rather than using AnyType which requires access to oidtables:

    // exctract from $(TOP)/examples/odp/OdpTestClnt.cc
    // that prepares the action arguments for the RMIB access API:

    if (argc == 2)      // 1 number - sqrt service asked
        actionArg = new AVA("calcSqrt", new Real(atof(argv[1])));
    else {              // > 1 numbers - meanStdDev service asked
        RealList* realList = new RealList;
        for (register int i = 1; i < argc; i++)
            realList->addval(atof(argv[i]));
        actionArg = new AVA("calcMeanStdDev", realList);
    }



ACTION INFORMATION / RESULT
---------------------------

Actions of OSIMIS managed objects can now have different syntaxes
for information and result. This was possible before only by creating
a new syntax that was the untagged CHOICE of the two others.
See the document pepsy.txt for details of the new facility for actions.



GDMO COMPILER
-------------

Access to managed object attributes is now supported by special
compiler produced methods that return the exact type, so using
the attribute array and casting back is not needed any more.
For example, setting the value for the uxObj1 nUsers attribute can be now:

    nUsers() -> setreal(nusers);

instead of (dangerous and not elegant back-casting):

    ((Gauge*) _attrs[I_nUsers]) -> setreal(nusers);

The produced inline methods have the name of the attribute as
in the GDMO definition (see also the gmsapi.txt document).


In trying to reduce the size of executables, the GDMO compiler produces
now only forward references for C++ attributes/actions in <mo>.h
while the relevant header files are included only in <mo>.cc .
That way, other code that includes <mo>.h but does not need to access
a particular attribute does not link inline methods of the latter
as static symbols. This means though that if you need access to a
particular attribute you will need to include its header file
e.g. "IntegerList.h" in your code.

In converting old code you may receive compile time errors about
"incomplete class definition" which means that your .cc file needs
to include a missing header file.



GMS API
-------

VERY IMPORTANT, all the polymorphic GMS methods have now a different
API for better error reporting (arbitrary error parameters) and future
support for atomicity and asynchronous object operations.
Read very carefully the gmsapi.txt document and also look at example
code to convert you objects. It should be rather easy as the additional
parameters are not going to be used. Be careful though to do the changes
to the method interface pedantically: as if you forget one of the new
arguments your code will compile with g++ without warnings and then
it will NOT execute polymorphically. The ATT CC 2.1 compiler at least
gives a warning of "method hiding virtual one".


The triggerAttributeValueChange and triggerStateChange object management
notifications of Top can now be invoked from outside an object if needed
by taking a char* (notification name) first argument instead of the
two integers (notifId, classLevel) which may be unknown "outside" the class.

The oldAttributeValue optional argument of those notifications is now
of type void* and NOT PE as before (non backwards compatible change).
The GMS is now responsible for freeing this value and NOT the user.
The (optional) old value should be copied before the new value is set.
An example from the monitor metric objects (monitorMetric class):

    void* val;
    if (_pmoObserved == NULLMO ||
            (val = forceGet(_pmoObserved, _oidObservedAttribute)) == NULLVD) {
        void* oldStateVal = scanner::operationalState()->copy();
        scanner::operationalState() -> set(os_disabled);
        triggerStateChange(I_operationalState, scanner::_level, oldStateVal);

        advise (NULL, "Error: NULLMO in monitorMetric::updateDerivedGauge()\n");
        return;
    }


Some of the MIB access methods of the MO class (e.g. getMO,
getSubordinates etc.) take now an additional argument of AVA*& type.
This is simply a pointer that may be set to an AVA object containing
an error type and possibly relevant information if the MIB access fails.
This may only take place if "refreshing" the MIT involves a remote
operation to a loosely coupled resource, in which case the communication
may be broken, the loosely coupled resource may have crashed etc.
If there is no such possibility or even if there is and the user of the
access method is not interested to know of the failure, this parameter can
be simply set to NULLAVA. It could have been made optional but
the ATT C++ 2.1 compiler did complain that it was
"too complex an argument to be optional"!


When an object is created at initialisation time,
through a resource operation or through a CMIS M-CREATE, its logic (code)
has now the means to distinguish of what type of creation it is
and to act accordingly if needed so. The following enumerated type
is defined in GenericMO.h and a pointer to it is passed to <mo>::createRR
through the optional void* argument:

typedef enum
{
    ct_undefined,
    ct_initialisation,
    ct_managementOperation,
    ct_resourceOperation

} CreationType;

a. ct_initialisation is passed during the MIB initialisation
b. ct_managementOperation is passed during creation through CMIS

In the case of a creation because of resource operation it is the
user's code that creates the MO e.g.

    CreationType crType = ct_resourceOperation;
    tpConn = (transportConnection*)
                        transportConnection::create(str2rdn(id), _tpEntity);
    tpConn -> createRR(&crType);

In that case the user should pass ct_resourceOperation if the managed
object's create behaviour needs it.



MO DELETIONS
------------

When managed objects are deleted through the management interface,
the deletion of the selected objects after scoping and filtering
takes place in post-order so that the MIT integrity is maintained.
For example, if a deletion with wholeSubtree scope is sent to object
A of the subtree below, the selection of objects is in pre-order i.e.
                         A B C D E F
while the deletions and received linked replies (assuming all are deletable)
are in post-order i.e.
                         F E D C B A

                             A
                           /   \
                          B     C
                              / | \
                             D  E  F

Sometimes it may be necessary to model a situation where an object has
to delete its subordinates in a special order. For example, C may create
upon its own creation D, E, F while it should delete them as E, F, D.

This may be modeled by making the class(es) whose instances are D, E, F
non-deletable while associating to the class whose instance is C
the "DELETES-SUBORDINATE-OBJECTS" property.


In OSIMIS versions before 4.0, control over
the order of deletion of an object's subordinates was not possible.
This was because the GMS used to delete the subordinates by checking
the name bindings before it called the deleteRR method of the containing
object. In the example above, D, E, F would be deleted in F, E, D order
before C "knew" about it. Obviously this does not give enough control
to the implementor to realise arbitrary deletion policies.

In version 4.0 this has been fixed.
Now, the deleteRR methods of a subtree to be deleted are called in
pre-order fashion. This means an object may delete any of its subordinates
in arbitrary order. In the above MIT schema, if a deletion
request was sent to C whose behaviour was to delete it subordinates
in the special order mentioned above, the sequence of events would be:

C -> deleteRR();
        // this calls (user's code)
        E -> deleteRR(); delete E;
        F -> deleteRR(); delete F;
        D -> deleteRR(); delete D;
delete C;


If C's deletion behaviour had nothing to do with its subordinates
i.e. instance C does not care of the order, the sequence of events would be:

// deleteRR calls in pre-order
C -> deleteRR();
D -> deleteRR();
E -> deleteRR();
F -> deleteRR();
// actual deletions in post-order (tree integrity)
delete F;
delete E;
delete D;
delete C;



RMIB API
--------

This was simply enhanced to allow the user of the services of an RMIBAgent
instance if the association to the remote application is broken.
This is effected through the RMIBAgent methods

    int    notifyBrokenAssociation (RMIBManager*);
    int    cancelCallbacks (RMIBManager*);

and the RMIBManager callback:

    virtual int brokenAssociation (RMIBAgent*);


Also now the RMIBAgent Get method has a boolean optional argument
to signify the return of replies one-by-one (not assembling service).
A unique integer is returned by the Get method and can be used
as the token to effect a CMIS CancelGet. Single replies are returned
to the CMISManager through the method

    virtual int singleGetResult (CMISObject*, RMIBAgent*);

the last one being an empty result with the id of that sequence.



LOCATION TRANSPARENCY
---------------------

This was enhanced at UCL to be able to access single-instance
agents without having to pass the host name. All the programs
in $(TOP)/manager/general have been modified to take the two
first arguments as (example):

maction ODPTEST kinou -i simpleStatsId=test -a sqrt=2  or
maction -S ODPTEST -i simpleStatsId=test -a sqrt=2

The first is a version without location transparency while
the second uses location transparency to find where ODPTEST runs
(and not only if it is up and running only). The -S stands for -Single .

Single instanced agents should initialise the CMISAgent object in the
main program by passing the optional singleInstanceAgent boolean
argument as True (default being False) - you may look at
$(TOP)/examples/odp/OdpTestSrv.cc .



ODP EXAMPLE
-----------

OSIMIS contains now a simple ODP-like example with a ODPTEST server
applications containing a simpleStats class that provides simple
statistical services (square root and mean/standard deviation).
You may consult the odpexample.txt document ans also look in
$(TOP)/examples/odp .



SIMULATED TIME
--------------

The simulated time support service was updated to relay "upwards"
the time change event report in a management hierarchy. You may see
the document simtime.txt and study the examples in $(TOP)/simtime/example .



SECURITY
--------

The MIDAS security extensions have been included in this release
but OSISEC and the QUIPU DSA for public key access are needed.
More information on this feature will be supplied later.



ATTRIBUTE COMPILER
------------------

This has also been included but its use is discouraged as the code
it produces is still buggy and also does not compile with ATT CC 2.1 .



NON-FUNCTIONAL CHANGES
----------------------

Access to oidtables uses now a much better hashing function which
increases performance while the maximum size limitation for both OIDs
and syntaxes has now been lifted.

OSIMIS applications are now substantially
smaller at run-time due to a number of optimisations.

Finally, the top part of $(TOP)/CONFIG.make contains a configuration
facility through which whole components can be left out at compile time
without the need to modify Makefiles.



CHANGES FOR NON-GDMO COMPILER PRODUCED CLASSES (FULLY HAND-WRITTEN)
-------------------------------------------------------------------

Classes that were written by hand for version 3.0 can still work
as far as they are updated according to the changes described above.

There are though two additional requirements for those classes
which are taken care by the GDMO compiler for others:

a. in <class>::initialiseClass the parent class should be set using
   the MOClassInfo::setParent method. An example (class Log):

    /* set parent class (meta-class tree) */
    _info.setParent(Top::getClassInfo());

b. in <class>::initialiseClass, the create/mcreate methods should
   be set accordingly (the mcreate one only if CMIS creation is allowed).
   An example (class Log):

    _info.setCreate(Log::create);
    _info.setMCreate(Log::cmisCreate);



GENERAL ADVISE BASED ON PAST EXPERIENCE

If you have variables whose name is the same as an MO attribute
(no problem in version 3.3), you better change it to avoid conflict
with the attribute access methods declared by the GDMO compiler.
 
You need to get the parameter list for all the polymorphic GMS API methods
( createRR, deleteRR, get, set, action, buildReport and refreshSubordinate(s) )
exactly right when you declare/define them.
If your declaration/definition to these methods is consistent but
not the same as the virtual method in the MO class, then your application
will build ok but your methods will not get called so your agent
will run but will not work properly (the ATT CC compiler gives a
"...hides virtual method" warning but g++ stays moot).
 
Don't forget the comments above about the changes to the default syntax
for String and StringList. If you ignore them, you may find problems
relating to the particular characters used in IA5String but not supported
by the standard GraphicString. Note also that you will need to change
IA5String to GraphicString in oidtable.at (the GDMO compiler guides you
through the produced oidtable.tmp).

