Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members  

CorbaManager.cpp

Go to the documentation of this file.
00001 /***************** <Tweek heading BEGIN do not edit this line> ****************
00002  * Tweek
00003  *
00004  * -----------------------------------------------------------------
00005  * File:          $RCSfile: CorbaManager.cpp,v $
00006  * Date modified: $Date: 2004/03/11 00:47:56 $
00007  * Version:       $Revision: 1.36 $
00008  * -----------------------------------------------------------------
00009  ***************** <Tweek heading END do not edit this line> *****************/
00010 
00011 /*************** <auto-copyright.pl BEGIN do not edit this line> **************
00012  *
00013  * VR Juggler is (C) Copyright 1998-2003 by Iowa State University
00014  *
00015  * Original Authors:
00016  *   Allen Bierbaum, Christopher Just,
00017  *   Patrick Hartling, Kevin Meinert,
00018  *   Carolina Cruz-Neira, Albert Baker
00019  *
00020  * This library is free software; you can redistribute it and/or
00021  * modify it under the terms of the GNU Library General Public
00022  * License as published by the Free Software Foundation; either
00023  * version 2 of the License, or (at your option) any later version.
00024  *
00025  * This library is distributed in the hope that it will be useful,
00026  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00027  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00028  * Library General Public License for more details.
00029  *
00030  * You should have received a copy of the GNU Library General Public
00031  * License along with this library; if not, write to the
00032  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
00033  * Boston, MA 02111-1307, USA.
00034  *
00035  *************** <auto-copyright.pl END do not edit this line> ***************/
00036 
00037 #include <tweek/tweekConfig.h>
00038 
00039 #include <cstdio>
00040 #include <vpr/vpr.h>
00041 //#include <vpr/System.h>
00042 #include <vpr/Util/Debug.h>
00043 #include <vpr/Util/Assert.h>
00044 
00045 #include <tweek/Util/Version.h>
00046 #include <tweek/Util/Debug.h>
00047 #include <tweek/CORBA/SubjectManager.h>
00048 #include <tweek/CORBA/BeanDeliverySubjectImpl.h>
00049 #include <tweek/CORBA/CorbaHelpers.h>
00050 #include <tweek/CORBA/CorbaManager.h>
00051 
00052 
00053 namespace tweek
00054 {
00055 
00056 const std::string CorbaManager::DELIVERY_SUBJECT_NAME("TweekBeanPusher");
00057 
00058 CorbaManager::CorbaManager()
00059    : mAppName("unknown"), mOrbFunctor(NULL), mOrbThread(NULL),
00060      mSubjectManager(NULL), mBeanDeliverySubject(NULL)
00061 {
00062    std::string tweek_ver = getVersionString();
00063 
00064    // Print out the Tweek version information.
00065    vprDEBUG(tweekDBG_CORBA, vprDBG_CRITICAL_LVL)
00066       << std::string(tweek_ver.length() + 14, '=') << std::endl
00067       << vprDEBUG_FLUSH;
00068    vprDEBUG(tweekDBG_CORBA, vprDBG_CRITICAL_LVL)
00069       << clrOutNORM(clrGREEN, "Tweek Server: ") << clrOutNORM(clrGREEN, tweek_ver)
00070       << clrRESET << std::endl << vprDEBUG_FLUSH;
00071    vprDEBUG(tweekDBG_CORBA, vprDBG_CRITICAL_LVL)
00072       << std::string(tweek_ver.length() + 14, '=') << std::endl
00073       << vprDEBUG_FLUSH;
00074 }
00075 
00076 vpr::ReturnStatus CorbaManager::init(const std::string& local_id, int& argc,
00077                                      char** argv, const std::string& nsHost,
00078                                      const vpr::Uint16& nsPort,
00079                                      const std::string& iiopVersion)
00080 {
00081    vpr::ReturnStatus status;
00082 
00083    // Retrieve the application name from argv if argv is non-NULL.
00084    if ( NULL != argv )
00085    {
00086       mAppName = argv[0];
00087    }
00088 
00089    try
00090    {
00091       // Initialize the ORB.
00092       vprDEBUG(tweekDBG_CORBA, vprDBG_STATE_LVL)
00093          << "Initializing ORB (using init string '" << TWEEK_ORB_VER_STRING
00094          << "')\n" << vprDEBUG_FLUSH;
00095       mORB = CORBA::ORB_init(argc, argv, TWEEK_ORB_VER_STRING);
00096 
00097       status = createChildPOA(local_id);
00098 
00099       try
00100       {
00101          // If no Naming Service host is given in the nsHost parameter, we
00102          // will use the initial references method for getting the root
00103          // naming context.
00104          if ( nsHost == std::string("") )
00105          {
00106             mRootContext = tweek::getRootNamingContextByInitRef(mORB);
00107          }
00108          // Otherwise, we will use a corbaloc URI to get the reference to
00109          // the Naming Service.
00110          else
00111          {
00112             // Why isn't this conversion easier to do with std::string?
00113             char nsPort_str[6];
00114             std::sprintf(nsPort_str, "%hu", nsPort);
00115 
00116             std::string ns_uri("corbaloc:iiop:");
00117             ns_uri += iiopVersion;
00118             ns_uri += std::string("@");
00119             ns_uri += nsHost;
00120             ns_uri += std::string(":");
00121             ns_uri += nsPort_str;
00122             ns_uri += std::string("/NameService");
00123 
00124             mRootContext = tweek::getRootNamingContextByURI(mORB, ns_uri);
00125          }
00126 
00127          if ( ! CORBA::is_nil(mRootContext) )
00128          {
00129             mLocalContext = tweek::bindLocalNamingContext(mRootContext,
00130                                                           std::string("tweek"));
00131 
00132             // XXX: Still need to do something with user-specified context...
00133          }
00134       }
00135       catch (CORBA::ORB::InvalidName& ex)
00136       {
00137          boost::ignore_unused_variable_warning(ex);
00138 
00139          // This should not happen!
00140          vprDEBUG(vprDBG_ALL, vprDBG_CRITICAL_LVL)
00141             << "NameService name invalid in CorbaManager::init!\n"
00142             << vprDEBUG_FLUSH;
00143       }
00144 
00145       vprDEBUG(tweekDBG_CORBA, vprDBG_STATE_LVL) << "Starting ORB thread\n"
00146                                                  << vprDEBUG_FLUSH;
00147       mOrbFunctor = new vpr::ThreadRunFunctor<tweek::CorbaManager>(this);
00148       mOrbThread  = new vpr::Thread(mOrbFunctor);
00149    }
00150    catch (CORBA::SystemException& sysEx)
00151    {
00152       status.setCode(vpr::ReturnStatus::Fail);
00153       vprDEBUG(tweekDBG_CORBA, vprDBG_CRITICAL_LVL)
00154          << "Caught CORBA::SystemException during initialization\n"
00155          << vprDEBUG_FLUSH;
00156       vprDEBUG_NEXT(tweekDBG_CORBA, vprDBG_CRITICAL_LVL)
00157          << "Mindor code: " << sysEx.minor() << ", completed: "
00158          << vprDEBUG_FLUSH;
00159 
00160       switch ( sysEx.completed() )
00161       {
00162          case CORBA::COMPLETED_YES:
00163             vprDEBUG_CONT(tweekDBG_CORBA, vprDBG_CRITICAL_LVL)
00164                << "YES" << std::endl << vprDEBUG_FLUSH;
00165             break;
00166          case CORBA::COMPLETED_NO:
00167             vprDEBUG_CONT(tweekDBG_CORBA, vprDBG_CRITICAL_LVL)
00168                << "NO" << std::endl << vprDEBUG_FLUSH;
00169             break;
00170          case CORBA::COMPLETED_MAYBE:
00171             vprDEBUG_CONT(tweekDBG_CORBA, vprDBG_CRITICAL_LVL)
00172                << "MAYBE" << std::endl << vprDEBUG_FLUSH;
00173             break;
00174       }
00175    }
00176    catch (CORBA::Exception&)
00177    {
00178       status.setCode(vpr::ReturnStatus::Fail);
00179       vprDEBUG(tweekDBG_CORBA, vprDBG_CRITICAL_LVL)
00180          << "Caught CORBA::Exception during initialization.\n"
00181          << vprDEBUG_FLUSH;
00182    }
00183    catch (omniORB::fatalException& fe)
00184    {
00185       status.setCode(vpr::ReturnStatus::Fail);
00186       vprDEBUG(tweekDBG_CORBA, vprDBG_CRITICAL_LVL)
00187          << "Caught omniORB::fatalException:\n" << vprDEBUG_FLUSH;
00188       vprDEBUG_NEXT(tweekDBG_CORBA, vprDBG_CRITICAL_LVL)
00189          << "  file: " << fe.file() << std::endl << vprDEBUG_FLUSH;
00190       vprDEBUG_NEXT(tweekDBG_CORBA, vprDBG_CRITICAL_LVL)
00191          << "  line: " << fe.line() << std::endl << vprDEBUG_FLUSH;
00192       vprDEBUG_NEXT(tweekDBG_CORBA, vprDBG_CRITICAL_LVL)
00193          << "  mesg: " << fe.errmsg() << std::endl << vprDEBUG_FLUSH;
00194    }
00195    catch(...)
00196    {
00197       vprDEBUG(tweekDBG_CORBA, vprDBG_CRITICAL_LVL)
00198          << "Caught unknown exception during initialization." << std::endl
00199          << vprDEBUG_FLUSH;
00200    }
00201 
00202    return status;
00203 }
00204 
00205 void CorbaManager::shutdown(bool waitForCompletion)
00206 {
00207    // If the Subject Manager exists, we need to deactivate it, remove it
00208    // from the Naming Service, and free its memory.
00209    if ( NULL != mSubjectManager )
00210    {
00211       if ( NULL != mBeanDeliverySubject )
00212       {
00213          mSubjectManager->unregisterSubject(DELIVERY_SUBJECT_NAME.c_str());
00214          delete mBeanDeliverySubject;
00215       }
00216 
00217       destroySubjectManager();
00218    }
00219 
00220    if ( ! CORBA::is_nil(mRootPOA) )
00221    {
00222       // We want to etherialize objects (destroy registered servants).  This
00223       // will destroy all descendant POAs, so we do not have to worry about
00224       // them at all.
00225       mRootPOA->destroy(true, waitForCompletion);
00226    }
00227 
00228    if ( ! CORBA::is_nil(mORB) )
00229    {
00230       try
00231       {
00232          mORB->shutdown(waitForCompletion);
00233       }
00234       catch (...)
00235       {
00236          vprDEBUG(tweekDBG_CORBA, vprDBG_CRITICAL_LVL)
00237             << "Caught unknown exception during ORB shutdown." << std::endl
00238             << vprDEBUG_FLUSH;
00239       }
00240    }
00241 }
00242 
00243 vpr::ReturnStatus CorbaManager::createSubjectManager()
00244 {
00245    vprASSERT(! CORBA::is_nil(mRootContext) && "No naming service available");
00246    vprASSERT(! CORBA::is_nil(mLocalContext) && "No naming service available");
00247    vpr::ReturnStatus status;
00248 
00249    tweek::SubjectManager_ptr mgr_ptr;
00250 
00251    vprASSERT(mSubjectManager == NULL && "Subject Manager already exists for this CORBA Manager!");
00252    mSubjectManager = new SubjectManagerImpl(*this);
00253    mSubjectManager->setApplicationName(mAppName);
00254 
00255    // Try to activate the given servant with our child POA before anyone tries
00256    // to use it.
00257    try
00258    {
00259       mSubjectManagerId = mChildPOA->activate_object(mSubjectManager);
00260    }
00261    // This will be raised if the IdUniqunessPolicy within our child POA is set
00262    // to UNIQUE_ID.
00263    catch (PortableServer::POA::ServantAlreadyActive& active_ex)
00264    {
00265       boost::ignore_unused_variable_warning(active_ex);
00266       vprDEBUG(tweekDBG_CORBA, vprDBG_WARNING_LVL)
00267          << "WARNING: Servant already active within our POA\n"
00268          << vprDEBUG_FLUSH;
00269    }
00270    catch (PortableServer::POA::WrongPolicy& policy_ex)
00271    {
00272       boost::ignore_unused_variable_warning(policy_ex);
00273       status.setCode(vpr::ReturnStatus::Fail);
00274       vprDEBUG(tweekDBG_CORBA, vprDBG_CRITICAL_LVL)
00275          << "Invalid policy used when activating Subject Manager object\n"
00276          << vprDEBUG_FLUSH;
00277    }
00278 
00279    // Only proceed if we were able to activate an object within the POA.  If
00280    // we couldn't, there is no point in registering anything with the naming
00281    // service.
00282    if ( status.success() )
00283    {
00284       // Try to add the mgr_ptr reference to the bound references known to the
00285       // naming service.
00286       try
00287       {
00288          // Construct the SubjectManager's name using its GUID so that it is
00289          // guaranteed to be unique.
00290          std::string id_str("SubjectManager.");
00291          id_str += mSubjectManager->getGUID().toString();
00292          mSubjectManager->setName(id_str);
00293 
00294          const char* kind = "Object";
00295 
00296          vprDEBUG(tweekDBG_CORBA, vprDBG_VERB_LVL)
00297             << "Subject Manager ID: " << id_str << std::endl << vprDEBUG_FLUSH;
00298 
00299          // This gives us our reference from the POA to the servant that was
00300          // registered above.  This does not perform object activation because
00301          // the object was activated above.
00302          mgr_ptr = mSubjectManager->_this();
00303 
00304          vprASSERT(! CORBA::is_nil(mgr_ptr) && "CORBA object not activated in POA");
00305 
00306          mSubjectManagerName.length(1);
00307          mSubjectManagerName[0].id   = CORBA::string_dup(id_str.c_str());
00308          mSubjectManagerName[0].kind = CORBA::string_dup(kind);
00309 
00310          // Bind the Subject Manager reference and activate the object within
00311          // the POA.  If a Subject Manager is already bound, the exceptoin
00312          // thrown prevents either operation from happening.  This is correct
00313          // since we only want one Subject Manager per address space.
00314          try
00315          {
00316             mLocalContext->bind(mSubjectManagerName, mgr_ptr);
00317 
00318             // Now that everything is set up with the Subject Manager, we can
00319             // register the one Subject that is always around: the default Bean
00320             // Delivery Subject.  This Subject is available for easy delivery
00321             // of new Beans to observers.
00322             try
00323             {
00324                mBeanDeliverySubject = new BeanDeliverySubjectImpl();
00325                mSubjectManager->registerSubject(mBeanDeliverySubject,
00326                                                 DELIVERY_SUBJECT_NAME.c_str());
00327             }
00328             catch (...)
00329             {
00330                delete mBeanDeliverySubject;
00331                vprDEBUG(tweekDBG_CORBA, vprDBG_WARNING_LVL)
00332                   << clrOutNORM(clrYELLOW, "WARNING")
00333                   << ": Failed to register Bean Delivery Subject\n"
00334                   << vprDEBUG_FLUSH;
00335             }
00336          }
00337          catch (CosNaming::NamingContext::AlreadyBound& ex)
00338          {
00339             boost::ignore_unused_variable_warning(ex);
00340             vprDEBUG(vprDBG_ALL, vprDBG_WARNING_LVL)
00341                << "WARNING: Subject manager reference already bound!\n"
00342                << vprDEBUG_FLUSH;
00343          }
00344       }
00345       catch (CORBA::COMM_FAILURE& ex)
00346       {
00347          boost::ignore_unused_variable_warning(ex);
00348          status.setCode(vpr::ReturnStatus::Fail);
00349          vprDEBUG(vprDBG_ALL, vprDBG_WARNING_LVL)
00350             << "Unable to contact the naming service\n" << vprDEBUG_FLUSH;
00351       }
00352       catch (CORBA::SystemException&)
00353       {
00354          status.setCode(vpr::ReturnStatus::Fail);
00355          vprDEBUG(vprDBG_ALL, vprDBG_WARNING_LVL)
00356             << "Caught a CORBA::SystemException while using the naming service"
00357             << std::endl << vprDEBUG_FLUSH;
00358       }
00359    }
00360 
00361    return status;
00362 }
00363 
00364 vpr::ReturnStatus CorbaManager::destroySubjectManager()
00365 {
00366    vpr::ReturnStatus status;
00367 
00368    // Only try to do destruction if there is a servant to destroy.
00369    if ( mSubjectManager != NULL )
00370    {
00371       // This attempts to go through the process of destroying the registered
00372       // Subject Manager servant.  The memory for the servant is only deleted
00373       // if the servant can be deactivated in the POA.
00374       try
00375       {
00376          // First, we deactivate the servant in the POA.
00377          mChildPOA->deactivate_object(mSubjectManagerId);
00378 
00379          // Then we attempt to unbind the reference from the Naming Service.
00380          // Should this fail, the object reference will be invalid because of
00381          // the above step, so deleting the servant's memory should be okay.
00382          try
00383          {
00384             mLocalContext->unbind(mSubjectManagerName);
00385          }
00386          catch (CORBA::ORB::InvalidName& ex)
00387          {
00388             boost::ignore_unused_variable_warning(ex);
00389             vprDEBUG(vprDBG_ALL, vprDBG_WARNING_LVL)
00390                << "WARNING: Invalid name used when trying to unbind "
00391                << "Subject Manager!\n" << vprDEBUG_FLUSH;
00392          }
00393          catch (CosNaming::NamingContext::CannotProceed& ex)
00394          {
00395             boost::ignore_unused_variable_warning(ex);
00396             vprDEBUG(vprDBG_ALL, vprDBG_WARNING_LVL)
00397                << "WARNING: Could not unbind Subject Manager!\n"
00398                << vprDEBUG_FLUSH;
00399          }
00400 
00401          // Finally, we delete the servant's memory.
00402          delete mSubjectManager;
00403          mSubjectManager = NULL;
00404       }
00405       catch (PortableServer::POA::ObjectNotActive& policy_ex)
00406       {
00407          boost::ignore_unused_variable_warning(policy_ex);
00408 
00409          // If the servant is not active in the POA, something may have gone
00410          // wrong in createSubjectManager().  In that case, the memory should
00411          // still be deleted since there is no active object to worry about
00412          // anyway.
00413          delete mSubjectManager;
00414          mSubjectManager = NULL;
00415 
00416          vprDEBUG(tweekDBG_CORBA, vprDBG_WARNING_LVL)
00417             << "WARNING: Coult not deactive Subject Manager: not active in POA\n"
00418             << vprDEBUG_FLUSH;
00419       }
00420       catch (PortableServer::POA::WrongPolicy& policy_ex)
00421       {
00422          boost::ignore_unused_variable_warning(policy_ex);
00423 
00424          status.setCode(vpr::ReturnStatus::Fail);
00425          vprDEBUG(tweekDBG_CORBA, vprDBG_WARNING_LVL)
00426             << "WARNING: Coult not deactive Subject Manager: wrong POA policy\n"
00427             << vprDEBUG_FLUSH;
00428       }
00429    }
00430    else
00431    {
00432       status.setCode(vpr::ReturnStatus::Fail);
00433       vprDEBUG(tweekDBG_CORBA, vprDBG_WARNING_LVL)
00434          << "WARNING: No Subject Manager servant to destroy!\n"
00435          << vprDEBUG_FLUSH;
00436    }
00437 
00438    return status;
00439 }
00440 
00441 // ============================================================================
00442 // Private methods.
00443 // ============================================================================
00444 
00445 vpr::ReturnStatus CorbaManager::createChildPOA(const std::string& local_id)
00446 {
00447    vpr::ReturnStatus status;
00448    CORBA::Object_var obj;
00449    CORBA::PolicyList policy_list;
00450 
00451    // Obtain a reference to the root POA.  The caller will have to catch any
00452    // thrown exceptions.
00453    vprDEBUG(tweekDBG_CORBA, vprDBG_STATE_LVL) << "Requesting Root POA\n"
00454                                               << vprDEBUG_FLUSH;
00455    obj      = mORB->resolve_initial_references("RootPOA");
00456    mRootPOA = PortableServer::POA::_narrow(obj);
00457 
00458    vprASSERT(! CORBA::is_nil(mRootPOA) && "Failed to get Root POA");
00459 
00460    // We want to allow multiple IDs to the same object and retain the
00461    // references.  The latter is required if we wish to do explict activation.
00462    PortableServer::IdUniquenessPolicy_var uniq_policy =
00463       mRootPOA->create_id_uniqueness_policy(PortableServer::MULTIPLE_ID);
00464    PortableServer::ServantRetentionPolicy_var retain_policy =
00465       mRootPOA->create_servant_retention_policy(PortableServer::RETAIN);
00466    PortableServer::ThreadPolicy_var thread_policy =
00467       mRootPOA->create_thread_policy(PortableServer::ORB_CTRL_MODEL);
00468 
00469    policy_list.length(3);
00470    policy_list[0] =
00471       PortableServer::IdUniquenessPolicy::_duplicate(uniq_policy);
00472    policy_list[1] =
00473       PortableServer::ServantRetentionPolicy::_duplicate(retain_policy);
00474    policy_list[2] =
00475       PortableServer::ThreadPolicy::_duplicate(thread_policy);
00476 
00477    std::string poa_name = "tweek_" + local_id;
00478 
00479    try
00480    {
00481       vprDEBUG(tweekDBG_CORBA, vprDBG_STATE_LVL)
00482          << "Creating child of root POA named " << poa_name << std::endl
00483          << vprDEBUG_FLUSH;
00484       mChildPOA = mRootPOA->create_POA(poa_name.c_str(),
00485                                        PortableServer::POAManager::_nil(),
00486                                        policy_list);
00487    }
00488    catch (PortableServer::POA::AdapterAlreadyExists& ex)
00489    {
00490       boost::ignore_unused_variable_warning(ex);
00491       status.setCode(vpr::ReturnStatus::Fail);
00492       vprDEBUG(vprDBG_ALL, vprDBG_WARNING_LVL)
00493          << "WARNING: Child POA named '" << poa_name << "' already exists!\n"
00494          << vprDEBUG_FLUSH;
00495    }
00496    catch (PortableServer::POA::InvalidPolicy& ex)
00497    {
00498       boost::ignore_unused_variable_warning(ex);
00499       status.setCode(vpr::ReturnStatus::Fail);
00500       vprDEBUG(vprDBG_ALL, vprDBG_WARNING_LVL)
00501          << "WARNING: Failed to set IdUniquenessPolicy for child POA\n"
00502          << vprDEBUG_FLUSH;
00503    }
00504 
00505    uniq_policy->destroy();
00506    retain_policy->destroy();
00507 
00508    return status;
00509 }
00510 
00511 void CorbaManager::run()
00512 {
00513    vprDEBUG(tweekDBG_CORBA, vprDBG_STATE_LVL) << "Server is running!\n"
00514                                               << vprDEBUG_FLUSH;
00515 
00516    PortableServer::POAManager_var pman = mChildPOA->the_POAManager();
00517 
00518    pman->activate();
00519    mORB->run();
00520 //   mORB->destroy();
00521 
00522    vprDEBUG(tweekDBG_CORBA, vprDBG_STATE_LVL) << "Server has shut down\n"
00523                                               << vprDEBUG_FLUSH;
00524 }
00525 
00526 } // End of tweek namespace

Generated on Sun May 2 14:41:03 2004 for Tweek by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002