Stock Distributor implementation for the Stock Quoter Publisher/Subscriber Real-time CORBA Service


Implementation of StockQuoter interface

This interface is used by brokers to get detailed stock information.

The Stock_StockQuoter_i class is generated automatically by the IDL compiler (using the -GI flag), which is a subclass of POA_Stock::StockQuoter class.

Implementing the get_stock_info () member function

  • Call the get_stock_info () function of Stock_Database instance.
  •     Stock::StockInfo *stock = STOCK_DATABASE->get_stock_info (stock_name);
    

    Implementation of StockDistributorHome interface

    This interface is used to register the necessary factories and mappings with the specified orb and create StockDistributor objects.

    The Stock_StockDistributorHome_i class is generated automatically by the IDL compiler (using the -GI flag), which is a subclass of POA_Stock::StockDistributorHome class.

    This class is also a subclass of ACE_Event_Handler, which can be used as an event handler.

    Implementing the Constructor

    The main steps of this function are described as follows:

  • Register this class as an event handler with the ORB to catch ctrl-c from the command line.
  •     if (orb_->orb_core ()->reactor ()->register_handler (SIGINT, this) == -1)
          ACE_DEBUG ((LM_DEBUG, "ERROR: Failed to register as a signal handler: %p\n",
                      "register_handler\n"));
    
  • Register the necessary factories and mappings with the specified orb.
  •     Stock::StockName_init *stockname_factory = new Stock::StockName_init;
        orb->register_value_factory (stockname_factory->tao_repository_id (),
                                     stockname_factory
                                     ACE_ENV_ARG_PARAMETER);
    
        Stock::Cookie_init *cookie_factory = new Stock::Cookie_init;
        orb->register_value_factory (cookie_factory->tao_repository_id (),
                                     cookie_factory
                                     ACE_ENV_ARG_PARAMETER);
    
        Stock_PriorityMapping::register_mapping (orb);
    
  • Initialize the Stock database.
  •     STOCK_DATABASE->activate (THR_NEW_LWP | THR_JOINABLE, 1);
    
  • Create a CORBA::PolicyList for the child POA.
  • This step include several sub-steps:
    1. Get a reference to the RTORB.
    2. Initialize a CORBA::PolicyList object.
    3. Create a SERVER_DECLARED priority model policy and add it into the former CORBA::PolicyList object.
    4. Create a threadpool with lanes for the distributor. Since the brokers have various priorities, create a lane for each priority.
    5. Create a thread pool policy using the former threadpool and add it into the former CORBA::PolicyList object.
    6. Create a child POA using the former CORBA::PolicyList and narrow it to RTPOA.
        CORBA::Object_var obj = orb_->resolve_initial_references ("RTORB");
        RTCORBA::RTORB_var rt_orb = RTCORBA::RTORB::_narrow (obj.in ());
    
        TAO::Utils::PolicyList_Destroyer policies (2);
        policies.length (2);
    
        policies[0] =
          rt_orb->create_priority_model_policy (RTCORBA::SERVER_DECLARED,
                                                Stock::Priority_Mapping::VERY_LOW);
    
        RTCORBA::ThreadpoolLanes lanes (5); lanes.length (5);
    
        for (CORBA::ULong i = 0; i < lanes.length (); ++i)
          {
            lanes[i].lane_priority = static_cast (i);
            lanes[i].static_threads = 5;
            lanes[i].dynamic_threads = 0;
          }
    
        RTCORBA::ThreadpoolId threadpool_id =
          rt_orb->create_threadpool_with_lanes (1024*1024,
                                                lanes,
                                                false, false, 0, 0);
    
        policies[1] = rt_orb->create_threadpool_policy (threadpool_id);
    
        PortableServer::POA_var poa = this->_default_POA ();
        PortableServer::POAManager_var poa_mgr = poa->the_POAManager ();
    
        PortableServer::POA_var child_poa =
          poa->create_POA ("StockDistributor_POA",
                           poa_mgr.in (),
                           policies);
    
        this->rt_poa_ = RTPortableServer::POA::_narrow (child_poa.in ());
    
  • Create the initial distributor reference.
  •     this->create_distributor ();
    

    Implementing the create_distributor () member function

  • Create a new instance of the StockDistributor_i. Then activate it under the located POA. This will cause the object to have the CLIENT_PROPAGATED policies.
  •     StockDistributor_i *servant = new StockDistributor_i (this->rt_poa_.in ());
        PortableServer::ServantBase_var distributor_owner_transfer = servant;
        this->dist_id_ = this->rt_poa_->activate_object (servant);
    

    Implementing the create () member function

  • Get and narrow the StockDistributor object reference and return it.
  •     obj = this->rt_poa_->id_to_reference (this->dist_id_.in ());
        return Stock::StockDistributor::_narrow (obj.in ());
    

    Implementing the handle_signal () member function

  • Get and shutdown the distributor object and the orb used by it.
  •     CORBA::Object_var obj (this->rt_poa_->id_to_reference (this->dist_id_.in ()));
        Stock::StockDistributor_var dist (Stock::StockDistributor::_narrow (obj.in ()));
        dist->shutdown ();
    
        this->orb_->shutdown (true);
    

    Implementation of StockDistributor interface

    This interface is used for Stock Distributor server.

    The Stock_StockDistributor_i class is generated automatically by the IDL compiler (using the -GI flag), which is a subclass of POA_Stock::StockDistributor class.

    Implementing the Constructor

        StockDistributor_i::StockDistributor_i (RTPortableServer::POA_ptr poa)
          : rate_ (3), // Default is 3 seconds (3000 milliseconds).
            active_ (false),
            rt_poa_ (RTPortableServer::POA::_duplicate (poa)),
            orb_ (CORBA::ORB::_duplicate (poa->_get_orb ()))
    
    The "rate_" and "active_" are two private members of the Stock_StockDistributor_i class. They stand for the notification rate and the active state of the StockDistributor object.

    Implementing the subscribe_notifier () member function

    The main steps of this function are described as follows:

  • Get the write thread mutex of the subscriber map.
  • Generate an unique id for the cookie and use it to create a new Cookie object.
  • Insert the StockNameConsumer object and its priority into the StockDistributor object's subscriber map, using the cookie id as the key.
  • Return the Cookie object.
  • Implementing the unsubscribe_notifier () member function

    The main steps of this function are described as follows:

  • Check the value of the Cookie object.
  • Get the write thread mutex of the subscriber map.
  • Search for the Cookie object in the argument in the StockDistributor object's subscriber map.
  • Erase the Cookie object from the StockDistributor object's subscribers' map.
  • Return the StockNameConsumer object which is related to the erased Cookie object.
  • Implementing the provide_quoter_info () member function

  • Get the read thread mutex of the subscriber map.
  • Search for the Cookie object in the argument in the StockDistributor object's subscriber map.
  •     CookieMap::const_iterator iter = this->subscribers_list_.find (ck->cookie_id ());
    
  • Create a new instance of the StockQuoter object and activate it under the former RTPOA with the given priority.
  •     Stock_StockQuoter_i *quoter = new Stock_StockQuoter_i;
        PortableServer::ServantBase_var owner_transfer (quoter);
    
        PortableServer::ObjectId *oid =
          this->rt_poa_->activate_object_with_priority (quoter,
                                                        iter->second.second);
    
        CORBA::Object_var obj = rt_poa_->id_to_reference (*oid);
        Stock::StockQuoter_var quoter_var = ::Stock::StockQuoter::_narrow (obj.in ());
    
  • Return the StockQuoter object reference.
  • Implementing the start () member function

    Set the active state of the StockDistributor object to true and create a thread to publish the stock information to the Stock Broker clients.

    The main steps of this thread function are described as follows:

    While the state of the StockDistributor object is active, continue the following looping:

  • Get the read thread mutex of the subscriber map.
  • Publish the stock information to all the StockNameConsumer objects that have subscribed.
  •     for (Stock_StockDistributor_i::CookieMap::iterator iter = this->subscribers_list_.begin ();
             iter != this->subscribers_list_.end ();
             ++iter)
          {
            try
              {
                // Set the designated priority for current request.
                CORBA::Object_var obj = orb_->resolve_initial_references ("RTCurrent");
                RTCORBA::Current_var rt_current =
                  RTCORBA::Current::_narrow (obj);
    
                rt_current->the_priority (iter->second.second);
    
                // Tell the database to push its information to the
                // , which passes along the CORBA priority
                // in the service_context list of the GIOP message.
                STOCK_DATABASE->publish_stock_info (iter->second.first);
              }
            catch (const CORBA::Exception &ex)
              {
                ACE_PRINT_EXCEPTION (ex, "Stock_StockDistributor_i::svc: ");
              }
          }
    
  • Sleep for the specified amount of seconds given in the notification rate.
  • Implementing the stop () member function

  • Set the active state of StockDistributor object to false.
  • Implementing the shutdown () member function

  • Stop publishing events.
  •     this->stop ();
    
  • Deactivate the StockDistributor object.
  •     ::Stock::StockDistributor_var dist = this->_this ();
        PortableServer::ObjectId_var oid = this->rt_poa_->reference_to_id (dist.in ());
    
        this->rt_poa_->deactivate_object (oid.in ());
    

    Email: shanshan.jiang@vanderbilt.edu