Reconnection_Registry.cpp

Go to the documentation of this file.
00001 // -*- C++ -*-
00002 
00003 /**
00004  *  @file Reconnection_Registry.cpp
00005  *
00006  *  $Id: Reconnection_Registry.cpp 76626 2007-01-26 13:50:03Z elliott_c $
00007  *
00008  *  @author Dale Wilson <wilson_d@ociweb.com>
00009  */
00010 #include "orbsvcs/Notify/Reconnection_Registry.h"
00011 
00012 #include "tao/debug.h"
00013 #include "orbsvcs/Notify/Properties.h"
00014 #include "orbsvcs/Notify/Topology_Saver.h"
00015 #include "ace/Vector_T.h"
00016 //#define DEBUG_LEVEL 10
00017 #ifndef DEBUG_LEVEL
00018 # define DEBUG_LEVEL TAO_debug_level
00019 #endif
00020 
00021 
00022 TAO_BEGIN_VERSIONED_NAMESPACE_DECL
00023 
00024 namespace TAO_Notify
00025 {
00026   const char REGISTRY_TYPE[] = "reconnect_registry";
00027   const char RECONNECT_ID[] = "ReconnectId";
00028   const char RECONNECT_IOR[] = "IOR";
00029   const char REGISTRY_CALLBACK_TYPE[] = "reconnect_callback";
00030 
00031   Reconnection_Registry::Reconnection_Registry (Topology_Parent & parent)
00032     : highest_id_(0)
00033   {
00034     // not the best technique, here.  Take advantage of "protected"
00035     Topology_Object::topology_parent_ = &parent;
00036   }
00037 
00038   Reconnection_Registry::~Reconnection_Registry ()
00039   {
00040   }
00041 
00042   //////////////////////////
00043   // During normal operation
00044 
00045   NotifyExt::ReconnectionRegistry::ReconnectionID
00046   Reconnection_Registry::register_callback (
00047     NotifyExt::ReconnectionCallback_ptr callback)
00048   {
00049     //@@todo DO WE NEED THREAD SAFENESS?
00050     NotifyExt::ReconnectionRegistry::ReconnectionID next_id = ++highest_id_;
00051 
00052     if (DEBUG_LEVEL > 0)
00053     {
00054       ACE_DEBUG ((LM_DEBUG,
00055         ACE_TEXT ("(%P|%t) Reconnect registry: registering %d\n"),
00056         static_cast<int> (next_id)
00057         ));
00058     }
00059     TAO_Notify_Properties* properties = TAO_Notify_PROPERTIES::instance();
00060     CORBA::ORB_var orb = properties->orb ();
00061 
00062     CORBA::String_var cior = orb->object_to_string (callback);
00063     ACE_CString ior(cior.in ());
00064     if ( 0 != reconnection_registry_.bind (next_id, ior))
00065     {
00066       //todo throw something;
00067     }
00068     this->self_change ();
00069 
00070     return next_id;
00071   }
00072 
00073   void
00074   Reconnection_Registry::unregister_callback (NotifyExt::ReconnectionRegistry::ReconnectionID id)
00075   {
00076     if (DEBUG_LEVEL > 0)
00077     {
00078       ACE_DEBUG ((LM_DEBUG,
00079         ACE_TEXT ("(%P|%t) Reconnect registry: unregistering %d\n"),
00080         static_cast<int> (id)
00081         ));
00082     }
00083     if ( 0 != reconnection_registry_.unbind (id))
00084     {
00085       //@@todo  throw something
00086     }
00087     this->self_change ();
00088   }
00089 
00090   CORBA::Boolean
00091   Reconnection_Registry::is_alive (void)
00092   {
00093     return CORBA::Boolean(1);
00094   }
00095 
00096   //////////////////////
00097   // During topology save
00098 
00099   void
00100   Reconnection_Registry::save_persistent (Topology_Saver& saver)
00101   {
00102     bool change = this->self_changed_;
00103     this->self_changed_ = false;
00104     this->children_changed_ = false;
00105 
00106     NVPList attrs;
00107     //@@todo: bool want_all_children =
00108       saver.begin_object (0, REGISTRY_TYPE, attrs, change);
00109 
00110     Reconnection_Registry_Type::ENTRY *entry;
00111     for (Reconnection_Registry_Type::ITERATOR iter (this->reconnection_registry_);
00112       iter.next (entry);
00113       iter.advance ())
00114     {
00115       NVPList cattrs;
00116       if (DEBUG_LEVEL > 0)
00117       {
00118         ACE_DEBUG ((LM_DEBUG,
00119           ACE_TEXT ("(%P|%t) Reconnect registry: saving %d\n"),
00120           static_cast<int> (entry->ext_id_)
00121           ));
00122       }
00123       cattrs.push_back(NVP(RECONNECT_ID, entry->ext_id_));
00124       cattrs.push_back(NVP(RECONNECT_IOR, entry->int_id_));
00125       saver.begin_object (entry->ext_id_, REGISTRY_CALLBACK_TYPE, cattrs, true);
00126       saver.end_object (entry->ext_id_, REGISTRY_CALLBACK_TYPE);
00127     }
00128 // todo:
00129 //    for all deleted children
00130 //    {
00131 //      saver.delete_child(child_type, child_id);
00132 //    }
00133     saver.end_object (0, REGISTRY_TYPE);
00134   }
00135 
00136   ///////////////////////////////////////
00137   // During reload of persistent topology
00138 
00139   Topology_Object*
00140   Reconnection_Registry::load_child (const ACE_CString & type,
00141         CORBA::Long,
00142         const NVPList& attrs)
00143   {
00144     if (type == REGISTRY_CALLBACK_TYPE)
00145     {
00146       NotifyExt::ReconnectionRegistry::ReconnectionID id;
00147       ACE_CString ior;
00148       if (attrs.load (RECONNECT_ID, id) && attrs.load (RECONNECT_IOR, ior))
00149       {
00150         if (id > highest_id_)
00151         {
00152           highest_id_ = id;
00153 
00154           if (DEBUG_LEVEL > 0)
00155           {
00156             ACE_DEBUG ((LM_DEBUG,
00157               ACE_TEXT ("(%P|%t) Reconnect registry: reloading %d\n"),
00158               static_cast<int> (id)
00159               ));
00160           }
00161         }
00162         if ( 0 != reconnection_registry_.bind (id, ior))
00163         {
00164           //@@todo - throw something;
00165         }
00166       }
00167       else
00168       {
00169         ACE_ERROR ((LM_ERROR,
00170           ACE_TEXT ("(%P|%t) Reconnect registry: missing attribute\n")
00171           ));
00172       }
00173     }
00174     return this;
00175   }
00176 
00177   void
00178   Reconnection_Registry::send_reconnect (CosNotifyChannelAdmin::EventChannelFactory_ptr dest_factory)
00179   {
00180     TAO_Notify_Properties* properties = TAO_Notify_PROPERTIES::instance();
00181     CORBA::ORB_var orb = properties->orb ();
00182     ACE_Vector <NotifyExt::ReconnectionRegistry::ReconnectionID> bad_ids;
00183 
00184     Reconnection_Registry_Type::ENTRY *entry;
00185     for (Reconnection_Registry_Type::ITERATOR iter (this->reconnection_registry_);
00186       iter.next (entry);
00187       iter.advance ())
00188     {
00189       try
00190       {
00191         if (DEBUG_LEVEL > 0)
00192         {
00193           ACE_DEBUG ((LM_DEBUG,
00194             ACE_TEXT ("(%P|%t) Reconnection Registry: Sending reconnection to client %d\n"),
00195               static_cast<int> (entry->ext_id_)
00196             ));
00197         }
00198         ACE_CString & ior = entry->int_id_;
00199         CORBA::Object_var obj = orb->string_to_object (ior.c_str ());
00200         NotifyExt::ReconnectionCallback_var callback =
00201           NotifyExt::ReconnectionCallback::_narrow (obj.in ());
00202         if (!CORBA::is_nil (callback.in ()))
00203         {
00204           callback->reconnect (dest_factory);
00205         }
00206         else
00207         {
00208           ACE_DEBUG ((LM_DEBUG,
00209             ACE_TEXT ("(%P|%t) Reconnection Registry: Can't resolve reconnection client's IOR %d\n"),
00210               static_cast<int> (entry->ext_id_)
00211             ));
00212 
00213           //throw this entry away but you've got an iterator so be careful
00214           bad_ids.push_back (entry->ext_id_);
00215         }
00216       }
00217       catch (const CORBA::Exception&)
00218       {
00219         ACE_DEBUG ((LM_DEBUG,
00220           ACE_TEXT ("(%P|%t) Reconnection Registry: Exception sending reconnection to client -- discarding registry entry\n")
00221           ));
00222         //throw this entry away but you've got an iterator so be careful
00223         bad_ids.push_back (entry->ext_id_);
00224         //@@todo : we might want to check for retryable exceptions, but for now...
00225       }
00226     }
00227     size_t bad_count = bad_ids.size ();
00228     for (size_t nbad = 0; nbad < bad_count; ++nbad)
00229     {
00230       this->reconnection_registry_.unbind (bad_ids[nbad]);
00231     }
00232   }
00233 
00234   void
00235   Reconnection_Registry::release (void)
00236   {
00237     delete this;
00238     //@@ inform factory
00239   }
00240 
00241 } // namespace TAO_Notify
00242 
00243 TAO_END_VERSIONED_NAMESPACE_DECL

Generated on Sun Jan 27 15:39:59 2008 for TAO_CosNotification by doxygen 1.3.6