Creating an EventChannel without a factory

Help
2005-04-06
2013-04-15
  • HELP! I'm very behind on a very very important project (my university dissertation) and I'm stuck so help with this would be VERY much appreciated. Apologies if I'm being really stupid here. Getting my head around CORBA took forever and I feel like I've finally got the hang of it now (my program can do stuff without crashing!) but omniEvents has me stumped.

    I'm trying to create an EventChannel inside of my program without using a factory or the naming service. I already have a larger server object and a reference to this gets passed to the client earlier on. This server object has a method that passes the EventChannel reference to the client. This should work, right? The problem is I'm having trouble creating the EventChannel in the first place. On the server side, I do this...

    OmniEvents::EventChannel_i* eventc = new OmniEvents::EventChannel_i();

    This line executes okay but when the end of the function is reached, the program crashes. I realise that EventChannels are also omnithreads that need to be executed so I figured that might be the problem. I then added this line...

    eventc->activate(name);

    This line causes the program to crash. I noticed that this method also takes a second PersistNode* argument. I tried creating one of these and passed it as the second argument but that didn't change anything. I'm not sure if I need to use PersistNode? The docs don't really explain what it's for. The error I get from the above line is...

    omniORB: ERROR -- the application attempted to invoke an operation on a nil pseudo-object reference.
    terminate called after throwing an instance of 'CORBA::INV_OBJREF'

     
    • Alex Tingle
      Alex Tingle
      2005-04-06

      Warning: You're trying to do something new. The library is only currently tested to enable people to incorporate a factory into their progrom, not a single channel. It would be a useful feature, but I think some changes will be required.

      First the easy bit:

      EventChannel_i assumes that the OmniEvents::Orb singleton is managing omniORB's orb object:

        OmniEvents::Orb::inst()._orb=CORBA::ORB_init(argc,argv);
        OmniEvents::Orb::inst().resolveInitialReferences();

      PersistNode is basically just a map of key->value pairs (all strings). You can use it to set optional event channel parameters, but you can leave it NULL.

        EventChannel_i* channel( new EventChannel_i() );
        channel->activate("name");
        channel->start();
        return channel->_this(); // return reference to new channel.
        // channel object freed when EventChannel thread stops.

      BUT THIS STILL WON'T WORK!! The EventChannel object will try to log changed to the persistency database (class omniEventsLog) every time anything changes. It's not practical to stop this - the best thing to do is change the helper class WriteLock (omniEventsLog.h) so that it checks that omniEventsLog::theLog is set before trying to do anything - it will have to present a dummy output stream (to /dev/null?) to the caller.

      May I ask why you don't want to use the normal omniEvents server? You can set it up with your channel once and then forget it.

      -Alex

       
    • Hmm that doesn't sound quite as tricky as I might have thought, I'll give that a go. I could use the normal server but this is actually for a multiplayer game and I don't want to make it too complicated for people to set up, even on the server side. It'll be one less port to open up on the firewall for starters.

       
    • Alex Tingle
      Alex Tingle
      2005-04-06

      Right now you can use the library to make a whole EventChannelFactory inside your process. That would share the ORB with your code, so you would only need one port.

      That said, I don't want to discourage you from hacking the WriteLock helper or whatever...

      I don't really like my idea of hacking WriteLock. It has the advantage of only hitting one bit of code, but the disadvantage that it will cause all the writing-out work to be done, and then discarded to a null stream - which feels wasteful. Perhaps a better way, would be to just test for a non-NULL omniEventsLog::theLog each time before calling the output functions. That changes more files, but it's still pretty easy, and makes for a neater result. E.g.

      output(WriteLock().os);

      becomes:

      if(omniEventsLog::exists())
        output(WriteLock().os);

      ...where "exists()" is a new static function in class omniEventsLog:

      static bool exists() { return NULL!=theLog; }

       
    • Well I made the changes that you said, plus a few others. I needed a way to pass my existing ORB and POA to omniEvents so I did this...

      OmniEvents::Orb::inst()._orb = orb;
      OmniEvents::Orb::inst()._RootPOA = poa;
      OmniEvents::Orb::inst().resolveInitialReferences();
      eventc = new OmniEvents::EventChannel_i();
      eventc->activate(name);
      eventc->start();

      ...and modified the resolveInitialReferences method to only create a new POA and Naming Service and so on if one hasn't already been created. This seems to work okay but I had to comment out the POACurrent code because despite the fact that I'm using omniORB4, it couldn't seem to find POACurrent. Strange. That doesn't seem too important though. Despite all these changes, I'm still getting the same error as before! Here's the patch I've come up with so far.