Dynamic Logging & the CORBA Notification Service
by Tarak Modi


Listing One
// domain, type, event name
EventType type = new EventType ("example", "test");
FixedEventHeader fixed = new FixedEventHeader (type, "event");

// variable header, NV Pairs
// Let's add a priority QoS
Property variable[] = new Property[1];
variable[0] = new Property ();
variable[0].name = Priority.value;
variable[0].value = orb.create_any ();
variable[0].value.insert_short ((short) 3);

// Filterable data, NV Pairs
// Remember these are user defined and can be anything.
Property filterable[] = new Property[1];
filterable[0] = new Property ();
filterable[0].name = "eventnumber";
filterable[0].value = orb.create_any ();
filterable[0].value.insert_long ((long)11);

// Event Data
org.omg.CORBA.Any data = orb.create_any ();
data.insert_string("Hello World");

// We have finished creating all the distinct pieces
// Now let's create a structured event
StructuredEvent event = new StructuredEvent ();
event.header = new EventHeader (fixed, variable);
event.filterable_data = filterable;
event.remainder_of_body = data;

Listing Two
// This is the class that applications use for logging messages.
import org.omg.CosNotification.*;
import org.omg.CosNotifyComm.*;
import org.omg.CosNotifyChannelAdmin.*;
public class Tracer extends _StructuredPushSupplierImplBase
{
    private StructuredProxyPushConsumer sp;
    private boolean required = false;
    private org.omg.CORBA.ORB orb = null;

    public Tracer(org.omg.CORBA.ORB orb) throws TraceException
    {
            // save the orb reference for later
            this.orb = orb;
        initialize();
    }
    // shutdown this instance of tracer
    public void destroy()
     {
        // delegate to finalize()
        finalize();
        sp = null;
    }
    public void finalize()
    {
        // Disconnect from the channel if we need to.
        if(sp != null)
        sp.disconnect_structured_push_consumer();
    }
    // not implemented
    public void disconnect_structured_push_supplier ()
    {
    }
    // This is where Tracer gets its "smarts" from. This function is called 
    // any time the aggregate of event subscribed to on the channel.
    public void subscription_change (EventType added[], EventType removed[])
    {
        //System.out.println("Received Subscription change...");
        for( int i = 0; i < added.length; i++ )
        {
            if( added[i].domain_name.equals ("Tracer") &&
                added[i].type_name.equals ("") )
            {
                //System.out.println("Turning events on...");
                // Synchronize to serialize the "required" flag access
                synchronized(this)
                {
                    required = true;
                }
                break;
            }
        }
        for( int i = 0; i < removed.length; i++ )
        {
            if( removed[i].domain_name.equals ("Tracer") &&
                removed[i].type_name.equals ("") )
           {
                //System.out.println("Turning events off...");
                // Synchronize to serialize the "required" flag access
                synchronized(this)
                {
                    required = false;
                }
                break;
            }

        }
    }
    // Synchronize to serialize the "required" flag access
    synchronized public boolean on()
    {
        return required;
     }
    // This method takes the message and tracelevel parameters and
    // constructs a structured event.
    public void trace(String msg, int tracelevel) throws TraceException
    {
            if(sp == null)
        {
            throw new TraceException("Error: No connection");
        }
        boolean req = on();
        // If anyone is interested in these events the
        // required flag would be true.
        if( req )
        {
                //System.out.println("Logging message: " + msg);
            EventType type = new EventType ("Tracer", "");
            FixedEventHeader fixed = new FixedEventHeader (type, "event");
            // variable header, NV Pairs
            Property variable[] = new Property[0];
            // Filterable data, NV Pairs
            // Use the tracelevel here
            Property filterable[] = new Property[1];
            filterable[0] = new Property ();
            filterable[0].name = "tracelevel";
            filterable[0].value = orb.create_any ();
            filterable[0].value.insert_long(tracelevel);
            // Event Data
            org.omg.CORBA.Any data = orb.create_any ();
            data.insert_string(msg);
            // Put everything together...
            StructuredEvent event = new StructuredEvent ();
            event.header = new EventHeader (fixed, variable);
            event.filterable_data = filterable;
            event.remainder_of_body = data;
            try
            {
                // Off the event goes...
                sp.push_structured_event(event);
            }
           catch(org.omg.CosEventComm.Disconnected e)
            {
                throw new TraceException("Error: Reconnect required");
            }
        }
    }
    /////////////////////////
    // Private Methods...
    /////////////////////////
    private void initialize() throws TraceException
    {
            EventChannel channel = getChannel();
        connect(channel);
    }
    private EventChannel getChannel() throws TraceException
    {
             // Get a reference to the notification service
        org.omg.CORBA.Object obj = null;
        try
        {
            obj = orb.resolve_initial_references("NotificationService");

        }
        catch( org.omg.CORBA.ORBPackage.InvalidName ex )
        {
            throw new TraceException("Error: Failed to 
                                        resolve Notification Service");
        }
        // Get the event channel factory from the service
        EventChannelFactory factory = EventChannelFactoryHelper.narrow(obj);
        // Get the event channel from the factory
        EventChannel channel = null;
        try
        {
            channel = factory.get_event_channel(0);
        }
        catch(ChannelNotFound ex)
        {
            // Channel is not found, let's create a new one...
            // Create a channel with no QoS or admin properties.
            Property[] qosProp = new Property[0];
            Property[] admProp = new Property[0];
            org.omg.CORBA.IntHolder id = new org.omg.CORBA.IntHolder ();

            try
            {
                channel = factory.create_channel(qosProp, admProp, id);
            }
            catch( UnsupportedQoS exc )
            {
            }
            catch( UnsupportedAdmin exc )
            {
            }
        }

        return channel;
        }
   private void connect(EventChannel channel) throws TraceException
    {
        // Get the default supplier admin object for this channel
        SupplierAdmin admin = channel.default_supplier_admin ();
        // Now ask the admin for a reference to a push consumer proxy
        ClientType ctype = ClientType.STRUCTURED_EVENT;
        org.omg.CORBA.IntHolder pid = new org.omg.CORBA.IntHolder ();
        ProxyConsumer proxy = null;
        try
        {
            proxy = admin.obtain_notification_push_consumer (ctype, pid);
        }
        catch( AdminLimitExceeded ex )
        {
            throw new TraceException("Error: Max number of proxies exceeded");
        }
         sp = StructuredProxyPushConsumerHelper.narrow (proxy);
        try
        {
            // connect to the channel
            sp.connect_structured_push_supplier(this);
            // Inital "smarts"
            // See if any TracerMons are there listening for Tracer events
            EventType types[] =
sp.obtain_subscription_types(org.omg.CosNotifyChannelAdmin.ObtainInfoMode.ALL_NOW_UPDATES_ON);
            //System.out.println("Total events being 
                                         subscribed to = " + types.length);
            for( int i=0; i<types.length; i++ )
            {
                if( types[i].domain_name.equals("Tracer") 
                                         && types[i].type_name.equals("") )
                {
                    //System.out.println("Turning events on...");
                    required = true;
                    break;
                }
            }
            // Tell the channel which events I publish...
            NotifyPublish publisher = NotifyPublishHelper.narrow (proxy);
            EventType added[] = new EventType[1];
            added[0] = new EventType ("Tracer", "");
            EventType removed[] = new EventType[0];
            publisher.offer_change(added, removed);
        }
        catch( org.omg.CosEventChannelAdmin.AlreadyConnected ex )
        {
            throw new TraceException("Error: Unexpected 
                                     exception [AlreadyConnected]");
        }
        catch( org.omg.CosNotifyComm.InvalidEventType ex1 )
        {
            throw new TraceException("Error: Unexpected 
                                     Exception [InvalidEventType]");
        }
    }
}

Listing Three
// Exception raised by the Tracer class in case of an error.
public class TraceException extends java.lang.Exception
{
    String message = null;
    public TraceException(String msg)
    {
    message = msg;
    }
    public String getMessage()
    {
    return message;
    }
}





6


