Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | Related Pages | Examples

ColCOWS_NodeServant.cc

00001 //===========================================================================//
00002 //    
00003 //    Description: Implementation of ColCOWS Node interface 
00004 //    Filename: colcows/ColCOWS_NodeServant.cc
00005 //    Authors: Michael Dussere and Aurélien Esnard
00006 //    
00007 //===========================================================================//
00008 //    
00009 //    Copyright (C) 2003 INRIA and CNRS
00010 //    
00011 //    This library is free software; you can redistribute it and/or
00012 //    modify it under the terms of the GNU Lesser General Public
00013 //    License as published by the Free Software Foundation; either
00014 //    version 2.1 of the License, or (at your option) any later version.
00015 //    
00016 //    This library is distributed in the hope that it will be useful,
00017 //    but WITHOUT ANY WARRANTY; without even the implied warranty of
00018 //    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00019 //    Lesser General Public License for more details.
00020 //    
00021 //    You should have received a copy of the GNU Lesser General Public
00022 //    License along with this library; if not, write to the Free Software
00023 //    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00024 //    
00025 //===========================================================================//
00026 
00027 
00028 #include "ColCOWS_NodeServant.hh"
00029 #include "ColCOWS_Node.hh"
00030 
00031 using namespace std;
00032 
00033 __COLCOWS_BEGIN__
00034 
00035 //! max resolve retry (sec)
00036 const unsigned int  RESOLVE_RETRY = 15;
00037 
00038 //! max register retry (sec)
00039 const unsigned int  REGISTER_RETRY = 15;
00040 
00041 
00042 //===========================================================================//
00043 //                       collective node class                               //
00044 //===========================================================================//
00045 
00046 
00047 //===========================================================================//
00048 
00049 NodeServant::NodeServant()
00050 {
00051   COLCOWS_IN_DEBUG();
00052 
00053   _my_node           = new IdlNodeDesc;
00054   _local_workspace   = new IdlWorkspaceDesc;
00055   _father_node       = new IdlNodeDesc;
00056   _children_nodes    = new IdlNodeDescSeq;
00057   _remote_workspaces   = new IdlWorkspaceDescSeq;
00058 
00059   pthread_mutex_init(&_children_mut, NULL);
00060   pthread_mutex_init(&_activation_mut, NULL);
00061   pthread_cond_init(&_activation_cond, NULL);
00062 
00063   _ready = false;
00064   _auto_activation = false;
00065   _current_num_connection = NOT_CONNECTED;
00066 
00067   COLCOWS_OUT_DEBUG();
00068   return;
00069 }
00070 
00071 //===========================================================================//
00072 
00073 NodeServant::~NodeServant()
00074 {
00075   COLCOWS_IN_DEBUG();
00076 
00077   try {
00078     
00079     // deactivate (etherealize, wait for completion)
00080     if(! CORBA::is_nil( _colcows_pman ) ) {
00081       COLCOWS_DEBUG( dblTest, "Deactivate ColCOWS POA Manager");
00082       _colcows_pman->deactivate(true,true);
00083     }
00084     // unbind obj_ref with objname to the name service
00085     if(! CORBA::is_nil( _naming_ctxt ) ) {
00086       COLCOWS_DEBUG( dblTest, "Unbind ColCOWS from Naming Service");
00087 
00088       CosNaming::Name objectName;
00089       objectName.length(1);
00090       objectName[0].id   = CORBA::string_dup(_local_workspace->ws_id);   // string copied
00091       objectName[0].kind = CORBA::string_dup(_local_workspace->ws_kind);  // string copied
00092       
00093       try {
00094         _naming_ctxt->unbind(objectName);
00095       }
00096       catch(CosNaming::NamingContext::NotFound& ex) {
00097         // OK
00098       }
00099     }
00100   }
00101   catch( ... ) {
00102     cerr << "Service required is invalid [does not exist]." << endl;
00103   }
00104 
00105   pthread_mutex_destroy(&_children_mut);
00106   pthread_mutex_destroy(&_activation_mut);
00107   pthread_cond_destroy(&_activation_cond);
00108 
00109   COLCOWS_OUT_DEBUG();
00110   return;
00111 }
00112 
00113 //===========================================================================//
00114 NodeServant * NodeServant::New(const char* ws_id, 
00115                                const char* ws_kind, 
00116                                const char* node_kind, 
00117                                unsigned long num_node, 
00118                                unsigned long max_descendant, 
00119                                unsigned long nb_nodes,
00120                                unsigned long num_father,
00121                                CORBA::ORB_ptr orbp) 
00122 {
00123   COLCOWS_IN_DEBUG();
00124 
00125   NodeServant * new_node_servant = new NodeServant;
00126   new_node_servant->lockChildrenMutex();
00127   new_node_servant->lockActivationMutex();
00128 
00129   try {
00130     CORBA::Object_var obj_ref;
00131 
00132     // verify if the reference on the ORB is not nil
00133     COLCOWS_ASSERT( ( !CORBA::is_nil( orbp ) ), "Got a nil ORB pointer.");
00134 
00135     new_node_servant->_orbp = orbp;
00136 
00137     // Obtain a reference of the root POA
00138     COLCOWS_DEBUG( dblTest, "Obtain a reference of the root POA");
00139     obj_ref = orbp->resolve_initial_references("RootPOA");
00140     new_node_servant->_root_poa = PortableServer::POA::_narrow(obj_ref);
00141 
00142     // Build ColCOWS POA unique name
00143     stringstream colcows_poa_name (stringstream::in | stringstream::out);
00144     colcows_poa_name << "ColCOWSPOA" << "_" << ws_id << "_" << ws_kind ;
00145  
00146     try {
00147       // Create the ColCOWS POA
00148       COLCOWS_DEBUG( dblTest, "Create the ColCOWS POA");
00149 
00150       CORBA::PolicyList policies;
00151       policies.length(1);
00152       policies[0] = new_node_servant->_root_poa->create_lifespan_policy( PortableServer::PERSISTENT );
00153 
00154       new_node_servant->_colcows_poa = new_node_servant->_root_poa->create_POA(  colcows_poa_name.str().c_str(), 
00155                                                                                  PortableServer::POAManager::_nil(),
00156                                                                                  policies );
00157     }
00158     catch ( ... ) {
00159       COLCOWS_DEBUG( dblTest, "Failed to create ColCOWS POA"  << ", let' s try to find it ...");
00160     }
00161     
00162     if( CORBA::is_nil( new_node_servant->_colcows_poa ) ) {
00163       // Obtain a reference of the ColCOWS POA
00164       COLCOWS_DEBUG( dblTest, "Find the reference of the ColCOWS POA");
00165      
00166       new_node_servant->_colcows_poa = new_node_servant->_root_poa->find_POA(colcows_poa_name.str().c_str(), false );     
00167     }
00168 
00169     COLCOWS_DEBUG( dblTest, "Activate new node servant in ColCOWS POA");
00170     new_node_servant->_colcows_poa->activate_object( new_node_servant );
00171 
00172     COLCOWS_DEBUG( dblTest, "Get ColCOWS POA Manager");
00173     new_node_servant->_colcows_pman = new_node_servant->_colcows_poa->the_POAManager( );
00174 
00175     COLCOWS_DEBUG( dblTest, "Activate ColCOWS POA Manager");
00176     new_node_servant->_colcows_pman->activate();
00177 
00178     // Obtain a reference of the name service:
00179     COLCOWS_DEBUG( dblTest, "Obtain a reference of the Naming Service");
00180     try {
00181       obj_ref = orbp->resolve_initial_references("NameService");
00182       new_node_servant->_naming_ctxt = CosNaming::NamingContext::_narrow(obj_ref);
00183     }
00184     catch ( ... ) {
00185       COLCOWS_ERROR( "Failed to resolve NameService");
00186     }
00187     COLCOWS_DEBUG( dblTest, "Naming Service resolved!");
00188     COLCOWS_ASSERT( !(CORBA::is_nil( new_node_servant->_naming_ctxt )), "Failed to narrow the root naming context.");
00189 
00190     new_node_servant->_my_node->node_kind       = CORBA::string_dup(node_kind);
00191     new_node_servant->_my_node->num_node        = num_node;
00192     new_node_servant->_my_node->max_descendant  = max_descendant;
00193     new_node_servant->_my_node->activated       = false;
00194     new_node_servant->_my_node->node_ref        = new_node_servant->_this();
00195 
00196     new_node_servant->_local_workspace->ws_id             = CORBA::string_dup(ws_id);
00197     new_node_servant->_local_workspace->ws_kind           = CORBA::string_dup(ws_kind);
00198     new_node_servant->_local_workspace->nb_nodes         = nb_nodes;
00199     new_node_servant->_local_workspace->activated        = false;
00200   
00201 
00202     if (num_node == 0) {
00203 
00204       try {   
00205         // bind obj_ref with objname to the name service
00206         CosNaming::Name objectName;
00207         objectName.length(1);
00208         objectName[0].id   = CORBA::string_dup(ws_id);   // string copied
00209         objectName[0].kind = CORBA::string_dup(ws_kind);  // string copied
00210     
00211         try {
00212           new_node_servant->_naming_ctxt->bind(objectName, new_node_servant->_this());
00213         }
00214         catch(CosNaming::NamingContext::AlreadyBound& ex) {
00215           COLCOWS_DEBUG( dblMajor, "Proxy must do a rebind on the Naming Service." );
00216           new_node_servant->_naming_ctxt->rebind(objectName, new_node_servant->_this());
00217         }
00218 
00219       }
00220       catch(...) {
00221         COLCOWS_ERROR( "Cannot bind root proxy in the naming service." );
00222       }
00223 
00224       COLCOWS_DEBUG( dblTest, "Object bind in the Naming Service!");
00225 
00226       new_node_servant->_local_workspace->enter_node_ref  = new_node_servant->_this();
00227 
00228       new_node_servant->_registred_to_father = true;
00229     }
00230     else {
00231 
00232       COLCOWS_DEBUG( dblTest, "Try to resolve object from the Naming Service");
00233       unsigned long retry = RESOLVE_RETRY;
00234 
00235       // Resolve the name to an object reference.
00236       CosNaming::Name name;
00237       name.length(1);
00238       name[0].id   = (const char*) CORBA::string_dup(ws_id);   // string copied 
00239       name[0].kind = (const char*) CORBA::string_dup(ws_kind);  // string copied 
00240 
00241       while ( true ) {
00242         try { 
00243           obj_ref = new_node_servant->_naming_ctxt->resolve(name);
00244 
00245           if (( CORBA::is_nil( obj_ref ) == false ) && ( obj_ref->_non_existent() == false )) break; // success
00246               
00247         }
00248         catch(CosNaming::NamingContext::NotFound& ex) {
00249           COLCOWS_DEBUG( dblWarning, "reference on  " << ws_id << ":" << ws_kind <<" not found in naming service" );
00250         }
00251         catch(CORBA::TRANSIENT& ex) {
00252           COLCOWS_DEBUG( dblWarning, "reference on  " << ws_id << ":" << ws_kind <<" raise TRANSIENT exception" );
00253         }
00254         
00255         if ( --retry > 0) {
00256           // keep trying ...
00257           COLCOWS_DEBUG( dblWarning, "Keep trying " << retry << " chances left ..." );
00258           sleep(1);
00259         }
00260         else {
00261           COLCOWS_ERROR( "Cannot resolve reference on  " << ws_id << ":" << ws_kind <<" (no more retry)" );
00262         }
00263       }
00264 
00265       COLCOWS_DEBUG( dblTest, "Object resolved from the Naming Service!");
00266 
00267       new_node_servant->_local_workspace->enter_node_ref  = ColCOWS::NodeInterface::_narrow(obj_ref);
00268 
00269       COLCOWS_ASSERT( !(CORBA::is_nil(new_node_servant->_local_workspace->enter_node_ref)), 
00270                       "Failed to narrow the enter node .");
00271 
00272       COLCOWS_ASSERT( (num_father < num_node), "Father num is greater than node num"); 
00273       new_node_servant->_father_node->num_node = num_father;      
00274       new_node_servant->_registred_to_father = false;
00275 
00276       // no retry to avoid troubles in sequential cases...
00277       new_node_servant->registerToFather( );
00278     }
00279 
00280   }
00281   catch ( ... ) { 
00282     COLCOWS_DEBUG( dblException, "Got a ColCOWS exception  in constructor" );
00283     delete new_node_servant;
00284     throw;
00285   }
00286 
00287   new_node_servant->unlockChildrenMutex();
00288   new_node_servant->unlockActivationMutex();
00289 
00290   COLCOWS_OUT_DEBUG();
00291   return new_node_servant;
00292 }
00293 
00294 //===========================================================================//
00295 
00296 bool NodeServant::registerToFather( unsigned long max_retry ) 
00297 {  
00298   COLCOWS_IN_DEBUG();
00299 
00300   unsigned long num_father = _father_node->num_node;
00301 
00302   while (_registred_to_father == false) {
00303     COLCOWS_DEBUG( dblTest,"in while, ( max_retry =  " << max_retry << " )");
00304 
00305     try {
00306 
00307       // Must use an intermediate to avoid the blanking of _father_node ...
00308       IdlNodeDesc_var node_desc = new IdlNodeDesc;
00309       _local_workspace->enter_node_ref->getNode( num_father, node_desc.out());
00310       _father_node = node_desc;
00311 
00312       if (!(CORBA::is_nil(_father_node->node_ref)) && !(_father_node->node_ref->_non_existent())) 
00313         {
00314           
00315           _father_node->node_ref->setChildNode(_my_node.in()); 
00316           
00317           _registred_to_father = true;
00318         }
00319 
00320     }
00321     catch (CorbaException & e) { 
00322       if (e.kind == cstNotReadyException) {
00323         COLCOWS_DEBUG( dblException, "Got a NotReady exception when trying to register to father(set child wsnode).");
00324       }
00325       else {
00326         COLCOWS_DEBUG( dblException, "Got a ColCOWS exception  when trying to register to father(set child wsnode).");
00327         throw;
00328       }
00329     }
00330     catch(CORBA::TRANSIENT& ex) {
00331       COLCOWS_DEBUG( dblException, "Got a TRANSIENT exception  when trying to register to father(set child wsnode).");
00332     }
00333     catch(CORBA::COMM_FAILURE& ex) {
00334       COLCOWS_ERROR( "Got a COMM_FAILURE exception  when trying to register to father(set child wsnode).");
00335     }
00336     catch (const CORBA::SystemException & e) { 
00337       COLCOWS_ERROR( "Got a CORBA exception  when trying to register to father(set child wsnode).");
00338     }
00339     catch ( ... ) { 
00340       COLCOWS_ERROR( "Got an unknown exception  when trying to register to father(set child wsnode).");
00341     }
00342 
00343     if ((max_retry > 0) && (_registred_to_father == false)) {
00344       sleep(1);
00345       COLCOWS_DEBUG( dblWarning, "retrying registration.");
00346       max_retry --;
00347     }
00348     else
00349       break;
00350     
00351   }
00352 
00353   COLCOWS_OUT_DEBUG();
00354   return _registred_to_father;
00355 }
00356 
00357 //===========================================================================//
00358 
00359 void NodeServant::activate( ) 
00360 {  
00361   COLCOWS_IN_DEBUG();
00362 
00363   COLCOWS_ASSERT( (!_my_node->activated), "Workspace Node is already activated." );
00364 
00365   pthread_mutex_lock(&_activation_mut); 
00366   pthread_mutex_lock(&_children_mut);
00367 
00368   COLCOWS_ASSERT( registerToFather( REGISTER_RETRY ), "Cannot register the Workspace to his father." );
00369 
00370   // check if the activated children cover all my descendants
00371   unsigned long nb_descendants_activated = 0;
00372   for (unsigned long i = 0; ((i < _children_nodes->length()) && (_children_nodes[i].activated)); i++) {
00373     nb_descendants_activated += _children_nodes[i].max_descendant - _children_nodes[i].num_node + 1;
00374   }
00375 
00376   pthread_mutex_unlock(&_children_mut);
00377 
00378   bool ready_for_activation = (nb_descendants_activated == _my_node->max_descendant - _my_node->num_node);
00379 
00380   COLCOWS_DEBUG(dblAccessory, "nb descendants activated " << nb_descendants_activated << " on " << ( _my_node->max_descendant - _my_node->num_node ) );
00381   COLCOWS_DEBUG(dblAccessory, "Is ready for activation ? " << ready_for_activation );
00382 
00383   // cannot be activated ...
00384   if (ready_for_activation == false) {
00385     
00386     COLCOWS_DEBUG(dblAccessory, "set auto_activation");
00387     _auto_activation = true;
00388 
00389   }
00390   else{ 
00391 
00392     _colcows_node->updateIdl(_my_node);
00393 
00394     COLCOWS_DEBUG(dblAccessory, "Node is activated");
00395     _my_node->activated = true;
00396   
00397     // reinitialize auto activation
00398     _auto_activation = false;
00399 
00400     // prepare the temporary image of this node with its children
00401     IdlNodeDesc_var wsnode = new IdlNodeDesc((const IdlNodeDesc) _my_node); // deep copy
00402 
00403     unsigned long current_child = wsnode->num_node + 1;
00404     unsigned long order_num_child = 0;
00405     wsnode->children_seq.length( _children_nodes->length() );
00406 
00407     while (current_child <= wsnode->max_descendant) {
00408 
00409       COLCOWS_ASSERT( (order_num_child < _children_nodes->length()), "Reaching the end of _children_nodes sequence.");
00410 
00411       unsigned long num_child;
00412       for (num_child = 0; 
00413            (   (num_child < _children_nodes->length()) 
00414                && (_children_nodes[num_child].num_node != current_child)) ; 
00415            num_child++) { }
00416 
00417       // if node not registred among the childs
00418       COLCOWS_ASSERT( (num_child != _children_nodes->length()), "There is a hole in the descendants.");
00419 
00420       IdlNodeDesc_var child_node = new IdlNodeDesc((const IdlNodeDesc) _children_nodes[num_child]); // deep copy
00421 
00422       wsnode->children_seq[order_num_child] = child_node;
00423 
00424       current_child =  _children_nodes[num_child].max_descendant + 1;
00425       order_num_child ++;
00426 
00427     } 
00428 
00429     // forward the activation to the father node if any
00430     if (_my_node->num_node != 0) {
00431 
00432       // Forwarding the activation to the father
00433       COLCOWS_DEBUG(dblAccessory, "Forwarding the activation to the father" );
00434       _father_node->node_ref->setChildNode(wsnode.in());
00435 
00436     }
00437     // The root propagate an image of the whole workspace to its children
00438     else {
00439 
00440       _local_workspace->activated = true;
00441       _local_workspace->enter_node = wsnode;
00442 
00443       unsigned long nb_children = _children_nodes->length();
00444 
00445       for (unsigned long j = 0; j < nb_children ; j++) 
00446         _children_nodes[j].node_ref->setWorkspace(_local_workspace.in());
00447 
00448       // signal activation on thre root... setWorkspace will do the same on the children
00449       _colcows_node->onActivation( _local_workspace );
00450     }
00451   }  
00452 
00453   pthread_mutex_unlock(&_activation_mut); 
00454 
00455   COLCOWS_OUT_DEBUG();
00456   return ;
00457 }
00458 
00459 //===========================================================================//
00460 
00461 void NodeServant::deactivate( ) 
00462 {  
00463   COLCOWS_IN_DEBUG();
00464 
00465   pthread_mutex_lock(&_activation_mut); 
00466 
00467   // reinitialize auto activation
00468   _auto_activation = false;
00469 
00470   _my_node->activated = false;
00471   
00472   // forward the activation to the father node if any
00473   if (_my_node->num_node != 0) {
00474     COLCOWS_DEBUG( dblAccessory, "forward the activation to the father node if any.");    
00475   
00476     _father_node->node_ref->setChildNode(_my_node.in());
00477   }
00478   // The root propagate the deactivation of the WS to its children
00479   else {
00480     COLCOWS_DEBUG( dblAccessory, "The root propagate the deactivation of the WS to its children");    
00481     _local_workspace->activated = false;
00482     
00483     IdlNodeDesc_var wsnode = new IdlNodeDesc((const IdlNodeDesc) _my_node); // deep copy
00484     _local_workspace->enter_node = wsnode;
00485 
00486     // forward
00487     unsigned long nb_children = _children_nodes->length();
00488     for (unsigned long j = 0; j < nb_children; j++) {
00489       _children_nodes[j].node_ref->setWorkspace(_local_workspace);
00490     }
00491 
00492       // signal deactivation on thre root... setWorkspace will do the same on the children
00493     _colcows_node->onDeactivation( _local_workspace );
00494   }
00495 
00496   pthread_mutex_unlock(&_activation_mut); 
00497 
00498   COLCOWS_OUT_DEBUG();
00499   return ;
00500 }
00501 
00502 //===========================================================================//
00503 
00504 unsigned long NodeServant::connect( const std::string & ws_id, const std::string & ws_kind, const std::string & nameservice_str )
00505 {
00506   COLCOWS_IN_DEBUG();
00507 
00508   COLCOWS_ASSERT( ( _my_node->num_node == 0 ), "Only the proxy can connect" );
00509   COLCOWS_ASSERT( ( getNumConnection(ws_id.c_str(), ws_kind.c_str()) == NOT_CONNECTED ), "Already connected" );
00510   COLCOWS_ASSERT( isReady(), "Workspace not ready for connection" );
00511 
00512   CosNaming::NamingContext_var naming_ctxt;
00513   if ( !nameservice_str.empty() ) 
00514     {
00515       // Obtain a reference of the name service:
00516       COLCOWS_DEBUG( dblTest, "Obtain a reference of the Naming Service");
00517       try {
00518         CORBA::Object_var obj_ref;
00519         obj_ref = _orbp->string_to_object( nameservice_str.c_str() );
00520         naming_ctxt = CosNaming::NamingContext::_narrow(obj_ref);
00521       }
00522       catch ( ... ) {
00523         THROW_CORBA_EXCEPTION( cstCorbaException, "Failed to resolve NameService");
00524       }
00525     }
00526   else 
00527     {
00528       naming_ctxt = _naming_ctxt;
00529     }
00530 
00531   // find the reference in the naming service
00532   CORBA::Object_var obj_ref;
00533   
00534   unsigned long retry = RESOLVE_RETRY;
00535   
00536   // Resolve the name to an object reference.
00537   CosNaming::Name name;
00538   name.length(1);
00539   name[0].id   = (const char*) CORBA::string_dup(ws_id.c_str());   // string copied 
00540   name[0].kind = (const char*) CORBA::string_dup(ws_kind.c_str());  // string copied 
00541   
00542   while ( true ) {
00543     try { 
00544         obj_ref = naming_ctxt->resolve(name);
00545         
00546         if (( CORBA::is_nil( obj_ref ) == false ) && ( obj_ref->_non_existent() == false )) break; // success
00547         
00548     }
00549     catch(CosNaming::NamingContext::NotFound& ex) {
00550       COLCOWS_DEBUG( dblWarning, "reference on  " << ws_id << ":" << ws_kind <<" not found in naming service" );
00551     }
00552     catch(CORBA::TRANSIENT& ex) {
00553       COLCOWS_DEBUG( dblWarning, "reference on  " << ws_id << ":" << ws_kind <<" raise TRANSIENT exception" );
00554     }
00555         
00556     if ( --retry > 0) {
00557       // keep trying ...
00558       COLCOWS_DEBUG( dblWarning, "Keep trying " << retry << " chances left ..." );
00559       sleep(1);
00560     }
00561     else {
00562       THROW_CORBA_EXCEPTION( cstCorbaException, 
00563                              "Cannot resolve reference on  " << ws_id << ":" << ws_kind <<" (no more retry)");
00564     }
00565   }
00566 
00567   NodeInterface_var remote_node_servant = ColCOWS::NodeInterface::_narrow(obj_ref);
00568   
00569   _current_num_connection++;
00570   
00571   remote_node_servant->getCommonNumConnection( (CORBA::ULong&)_current_num_connection ); 
00572   // remote_node_servant->getCommonNumConnection( _current_num_connection ); // pb with it64 !!!
00573   
00574   // exchange the descriptions
00575   
00576   IdlWorkspaceDesc_var remote_workspace ; //= new IdlWorkspaceDesc;
00577   remote_node_servant->getWorkspace(remote_workspace.out());
00578   
00579   bool initiator = false;
00580   remote_node_servant->setRemoteWorkspace( _current_num_connection, _local_workspace.in(), initiator );
00581   
00582   initiator = true;
00583   _local_workspace->enter_node_ref->setRemoteWorkspace( _current_num_connection, remote_workspace.in(), initiator );    
00584     
00585   COLCOWS_OUT_DEBUG();
00586   return getNumConnection(ws_id.c_str(), ws_kind.c_str());
00587 }
00588 
00589 //===========================================================================//
00590 
00591 //! disconnect a remote workspace
00592 void NodeServant::disconnect( unsigned long num_connection ) 
00593 {
00594   COLCOWS_IN_DEBUG();
00595 
00596   COLCOWS_ASSERT( isConnected(num_connection), "Not connected" );
00597   long num_ws = indexConnection(num_connection);
00598   COLCOWS_ASSERT( num_ws != -1 , "Incoherent index value" );
00599 
00600   _remote_workspaces[num_ws].enter_node_ref->releaseRemoteWorkspace( num_connection );
00601   _local_workspace->enter_node_ref->releaseRemoteWorkspace( num_connection );   
00602     
00603   COLCOWS_OUT_DEBUG();
00604   return ; 
00605 }
00606 
00607 //===========================================================================//
00608 
00609 //! disconnect a remote workspace
00610 void NodeServant::disconnectAll( ) 
00611 {
00612   COLCOWS_IN_DEBUG();
00613 
00614   long num_ws; // not unsigned because of the test : num_ws < 0
00615   unsigned long nb_ws = _remote_workspaces->length();
00616 
00617   for (num_ws = nb_ws - 1 ; num_ws >= 0; num_ws--) // disconnect from the end of the sequence
00618     {
00619       unsigned long num_connection = _remote_workspaces[num_ws].num_connection;
00620       
00621       _remote_workspaces[num_ws].enter_node_ref->releaseRemoteWorkspace( num_connection );
00622         _local_workspace->enter_node_ref->releaseRemoteWorkspace( num_connection );
00623     }   
00624   
00625   
00626   COLCOWS_OUT_DEBUG();
00627   return ;
00628 }
00629 
00630 //===========================================================================//
00631 //===========               public corba interface                ===========//
00632 //===========================================================================//
00633 
00634 //===========================================================================//
00635 
00636 //! get a node description 
00637 void NodeServant::getNode(CORBA::ULong num_node, IdlNodeDesc_out node) throw (CorbaException) 
00638   
00639 {
00640   COLCOWS_IN_DEBUG();
00641 __BEGIN_REDIRECT_ALL_EXCEPTIONS_TO_CORBA__
00642 
00643   // Invalid node number
00644   COLCOWS_ASSERT( (num_node >= 0), "Invalid node number");
00645 
00646   // It 's me !!!
00647   if (num_node == _my_node->num_node){
00648     node = new IdlNodeDesc((const IdlNodeDesc) _my_node); //deep copy
00649   }
00650   // It 's one of my descendants
00651   else if ((num_node > _my_node->num_node) && (num_node <= _my_node->max_descendant))  {
00652     unsigned long num_child;
00653     // looking for a node holding the same branch of the hierarchy
00654     for (num_child = 0;
00655          (   (num_child < _children_nodes->length())
00656              && (   (num_node < _children_nodes[num_child].num_node)
00657                     || (num_node > _children_nodes[num_child].max_descendant)  )  ); 
00658          num_child ++){}
00659  
00660     // if node not registred among the childs
00661     COLCOWS_ASSERT( (num_child != _children_nodes->length()), "Node " << num_node << " is not hold by any registred child.");
00662 
00663     // if it's one of my child and if I 've got an active description
00664     if ((num_node == _children_nodes[num_child].num_node) && _children_nodes[num_child].activated) {
00665       node = new IdlNodeDesc((const IdlNodeDesc) _children_nodes[num_child]); //deep copy      
00666     }
00667     // if I 've got a valid reference on the child holding this node
00668     else if ( !CORBA::is_nil(_children_nodes[num_child].node_ref)) {
00669       _children_nodes[num_child].node_ref->getNode(num_node, node);
00670     }
00671     else {
00672       THROW_CORBA_EXCEPTION( cstNotReadyException, "Node " << num_node << " is not hold by any registred child." );
00673     }
00674 
00675   }
00676   // It 's not one of my descendants, ask my father
00677   else if ((num_node < _my_node->num_node) || (num_node > _my_node->max_descendant))  {
00678     _father_node->node_ref->getNode(num_node, node);
00679   }    
00680   // It 's not one of my descendants
00681   else {
00682     COLCOWS_ERROR( "Unexpected case !!!" );
00683   }
00684 
00685 __END_REDIRECT_ALL_EXCEPTIONS_TO_CORBA__ 
00686   COLCOWS_OUT_DEBUG();
00687   return ;
00688 }
00689 
00690 //===========================================================================//
00691 
00692 //! set a node description 
00693 void NodeServant::setChildNode(const IdlNodeDesc& node) throw (CorbaException) 
00694   
00695 {
00696   COLCOWS_IN_DEBUG();
00697 __BEGIN_REDIRECT_ALL_EXCEPTIONS_TO_CORBA__
00698 
00699   COLCOWS_DEBUG( dblAccessory,"Set child " << node.num_node << " on node " << _my_node->num_node);
00700 
00701   COLCOWS_ASSERT( ((node.max_descendant <= _my_node->max_descendant)&&(node.num_node > _my_node->num_node)),
00702                   "Node " << node.num_node << " is not one of my descendants" );
00703 
00704   pthread_mutex_lock(&_children_mut);
00705 
00706   unsigned long num_child;
00707   bool trigger_activation = false;
00708   bool trigger_deactivation = false;
00709 
00710   // looking for a node holding the same branch of the hierarchy
00711   for (num_child = 0;
00712        (   (num_child < _children_nodes->length())
00713            && (   (node.num_node != _children_nodes[num_child].num_node)
00714                   || (node.max_descendant != _children_nodes[num_child].max_descendant)  )  ); 
00715        num_child ++){}
00716 
00717 
00718   // if node not registred among the childs
00719   if(num_child == _children_nodes->length()) {
00720 
00721     // verif if can be inserted among the children 
00722     for (num_child = 0;
00723          (   (num_child < _children_nodes->length())
00724              && (   (node.max_descendant < _children_nodes[num_child].num_node)
00725                     || (node.num_node > _children_nodes[num_child].max_descendant)  )  ); 
00726          num_child ++){}
00727 
00728     // node can't be inserted
00729     COLCOWS_ASSERT( (num_child >= _children_nodes->length()),"Node " << num_child << " can't be inserted" );
00730 
00731     // create new entry child desc tab
00732     _children_nodes->length(num_child+1);
00733    
00734     if (node.activated) {
00735       COLCOWS_DEBUG( dblAccessory, "Child " << node.num_node << " has been added (activated)" );
00736       trigger_activation = true;
00737     }
00738     else {
00739       COLCOWS_DEBUG( dblAccessory, "Child " << node.num_node << " has been added (not activated)" );
00740     }
00741   }
00742   // if node is already registred among the childs
00743   else {
00744     if      ((! _children_nodes[num_child].activated) && (  node.activated)) {
00745       COLCOWS_DEBUG( dblAccessory, "Child " << node.num_node << " is now activated" );
00746       trigger_activation = true;
00747     }
00748     else if ((  _children_nodes[num_child].activated) && (! node.activated)) {
00749       COLCOWS_DEBUG( dblAccessory, "Child " << node.num_node << " is no more activated" );
00750       trigger_deactivation = true;
00751     }
00752     else if ((  _children_nodes[num_child].activated) && (  node.activated)) {
00753       COLCOWS_ERROR( "Child " << node.num_node << " already activated" );
00754     }
00755   }
00756 
00757   // set child node description
00758   IdlNodeDesc_var node_tmp = new IdlNodeDesc((const IdlNodeDesc) node); // deep copy
00759   _children_nodes[num_child] = node_tmp;
00760     
00761   pthread_mutex_unlock(&_children_mut);
00762 
00763     if ((trigger_activation) && (! _my_node->activated) && (_auto_activation == true))
00764       activate();
00765     else if ((trigger_deactivation) && (_my_node->activated))
00766       deactivate();
00767 
00768 __END_REDIRECT_ALL_EXCEPTIONS_TO_CORBA__ 
00769   COLCOWS_OUT_DEBUG();
00770   return ;
00771 
00772 }
00773 
00774 //===========================================================================//
00775 
00776 CORBA::Boolean NodeServant::isActivated() throw (CorbaException) 
00777   
00778 {
00779   COLCOWS_IN_DEBUG();
00780 
00781   COLCOWS_OUT_DEBUG();
00782   return _local_workspace->activated;
00783 }
00784 
00785 //===========================================================================//
00786 
00787 CORBA::Boolean NodeServant::isReady() throw (CorbaException) 
00788   
00789 {
00790   COLCOWS_IN_DEBUG();
00791 
00792   COLCOWS_OUT_DEBUG();
00793   //! \todo return _ready insteed ...
00794   return _local_workspace->activated;
00795 }
00796 
00797 //===========================================================================//
00798 
00799 long NodeServant::indexConnection( CORBA::ULong num_connection )  
00800 {
00801   COLCOWS_IN_DEBUG();
00802 
00803   long index = -1;  
00804 
00805   unsigned long num_ws;
00806   for (num_ws = 0; num_ws < _remote_workspaces->length(); num_ws++)
00807     {
00808       if ( num_connection = _remote_workspaces[num_ws].num_connection )
00809         {
00810           index = num_ws;
00811           break;
00812         }
00813     }   
00814 
00815   COLCOWS_OUT_DEBUG();
00816   return index;
00817 }
00818 
00819 //===========================================================================//
00820 
00821 CORBA::Boolean NodeServant::isConnected( CORBA::ULong num_connection ) throw (CorbaException) 
00822   
00823 {
00824   COLCOWS_IN_DEBUG();
00825 
00826   COLCOWS_OUT_DEBUG();
00827   return (indexConnection(num_connection) != -1 );
00828 }
00829 
00830 //===========================================================================//
00831 
00832 //! test if the collective node id is connected
00833 CORBA::ULong NodeServant::getNumConnection( const char* ws_id, const char * ws_kind ) throw (CorbaException)
00834 {
00835   COLCOWS_IN_DEBUG();
00836 
00837   CORBA::ULong num_connection = NOT_CONNECTED;  
00838 
00839 __BEGIN_REDIRECT_ALL_EXCEPTIONS_TO_CORBA__
00840 
00841   unsigned long num_ws;
00842   for (num_ws = 0; num_ws < _remote_workspaces->length(); num_ws++)
00843     {
00844       if (   (strcmp(ws_id,_remote_workspaces[num_ws].ws_id) == 0) 
00845              && (strcmp(ws_kind,_remote_workspaces[num_ws].ws_kind) == 0))
00846         {
00847           num_connection = _remote_workspaces[num_ws].num_connection;
00848           break;
00849         }
00850     }   
00851 
00852 __END_REDIRECT_ALL_EXCEPTIONS_TO_CORBA__ 
00853   COLCOWS_OUT_DEBUG();
00854   return num_connection;
00855 }
00856 
00857 //===========================================================================//
00858 
00859 void NodeServant::getCommonNumConnection( CORBA::ULong & num_connection ) throw (CorbaException) 
00860 {
00861   COLCOWS_IN_DEBUG();
00862 __BEGIN_REDIRECT_ALL_EXCEPTIONS_TO_CORBA__
00863 
00864   COLCOWS_ASSERT( ( _my_node->num_node == 0 ), "Only the proxy can assign a new number of connection" );
00865 
00866   if (_my_node->num_node == 0) {
00867 
00868     if ( num_connection <= _current_num_connection) {
00869       ++_current_num_connection; 
00870       num_connection = _current_num_connection;
00871       COLCOWS_DEBUG( dblAccessory, "num_connection = " << num_connection);
00872     }
00873     else {
00874       _current_num_connection = num_connection;
00875       COLCOWS_DEBUG( dblAccessory, "num_connection = " << num_connection);
00876     }
00877  
00878   }
00879   else {
00880     COLCOWS_DEBUG( dblWarning, "Should not call getNewNumConnection on a non-root node ..." );
00881     return;
00882   }
00883 
00884 __END_REDIRECT_ALL_EXCEPTIONS_TO_CORBA__ 
00885   COLCOWS_OUT_DEBUG();
00886   return;
00887 }
00888 
00889 //===========================================================================//
00890     
00891 //! get the workspace description [public]
00892 void NodeServant::getWorkspace(IdlWorkspaceDesc_out ws_desc) throw (CorbaException) 
00893 {
00894   COLCOWS_IN_DEBUG();
00895 __BEGIN_REDIRECT_ALL_EXCEPTIONS_TO_CORBA__
00896 
00897   COLCOWS_ASSERT((_local_workspace->activated ), "Node is not activated" );
00898  
00899   ws_desc = new IdlWorkspaceDesc((const IdlWorkspaceDesc)_local_workspace); //deep copy
00900 
00901 __END_REDIRECT_ALL_EXCEPTIONS_TO_CORBA__ 
00902   COLCOWS_OUT_DEBUG();
00903   return ;
00904 }
00905 
00906 //===========================================================================//
00907     
00908 //! set the workspace description [public]
00909 void NodeServant::setWorkspace(const IdlWorkspaceDesc& ws_desc)
00910 {
00911   COLCOWS_IN_DEBUG();
00912 __BEGIN_REDIRECT_ALL_EXCEPTIONS_TO_CORBA__
00913 
00914   bool new_activation=false;
00915   bool new_deactivation=false;
00916 
00917   if ((! _local_workspace->activated) && (  ws_desc.activated))       { new_activation=true; }
00918   else if ((  _local_workspace->activated) && (! ws_desc.activated))  { new_deactivation=true; }
00919   else if ((! _local_workspace->activated) && (!  ws_desc.activated)) { }
00920   else // =>(( _local_workspace->activated) && ( ws_desc.activated))  
00921     { COLCOWS_ERROR( "Workspace already activated" ); }
00922 
00923   // register description
00924   _local_workspace = new IdlWorkspaceDesc((const IdlWorkspaceDesc) ws_desc); // deep copy
00925 
00926 
00927   // forward
00928   unsigned long nb_children = _children_nodes->length();
00929   for (unsigned long j = 0; j < nb_children; j++) {
00930     _children_nodes[j].node_ref->setWorkspace(ws_desc);
00931   }
00932 
00933   // execute appropriate treatment
00934   if ( new_activation == true )
00935     _colcows_node->onActivation( _local_workspace );
00936   else if ( new_deactivation == true )
00937     _colcows_node->onDeactivation( _local_workspace );
00938 
00939 __END_REDIRECT_ALL_EXCEPTIONS_TO_CORBA__ 
00940   COLCOWS_OUT_DEBUG();
00941   return ;
00942 }
00943 
00944 //===========================================================================//
00945     
00946 //! get the remote workspace description [public]
00947 void NodeServant::getRemoteWorkspace(CORBA::ULong num_connection, IdlWorkspaceDesc_out ws_desc) throw (CorbaException)
00948 {
00949   COLCOWS_IN_DEBUG();
00950 __BEGIN_REDIRECT_ALL_EXCEPTIONS_TO_CORBA__
00951 
00952   bool is_local = false;
00953 
00954   unsigned long num_ws;
00955   for (num_ws = 0; num_ws < _remote_workspaces->length(); num_ws++)
00956     {
00957       if ( _remote_workspaces[num_ws].num_connection == num_connection )
00958         {
00959           ws_desc = new IdlWorkspaceDesc ((const IdlWorkspaceDesc)_remote_workspaces[num_ws]); // deep copy
00960           is_local = true;
00961           break;
00962         }
00963     }
00964 
00965   // if the description is here
00966   if (is_local == true) {
00967     // there is nothing more to do ...
00968   }
00969   else {
00970     COLCOWS_ERROR( "Remote Workspace is not connected." );
00971   }
00972 
00973 __END_REDIRECT_ALL_EXCEPTIONS_TO_CORBA__ 
00974   COLCOWS_OUT_DEBUG();
00975   return ;
00976 }
00977 
00978 //===========================================================================//
00979     
00980 //! set the remote workspace description [public]
00981 void NodeServant::setRemoteWorkspace( CORBA::ULong num_connection, 
00982                                       const IdlWorkspaceDesc& ws_desc,
00983                                       CORBA::Boolean connection_initiator)
00984 {
00985   COLCOWS_IN_DEBUG();
00986 __BEGIN_REDIRECT_ALL_EXCEPTIONS_TO_CORBA__
00987 
00988   unsigned long num_ws;
00989   for (num_ws = 0; num_ws < _remote_workspaces->length(); num_ws++)
00990     {
00991       if ( _remote_workspaces[num_ws].num_connection == num_connection )
00992         {
00993           break;
00994         }
00995     }
00996 
00997   COLCOWS_ASSERT( (num_ws == _remote_workspaces->length()), 
00998                   "The connection already exists." );
00999 
01000   _remote_workspaces->length(num_ws+1);
01001 
01002   IdlWorkspaceDesc_var new_ws_desc = new IdlWorkspaceDesc ((const IdlWorkspaceDesc) ws_desc); // deep copy
01003   new_ws_desc->num_connection = num_connection;
01004   _remote_workspaces[num_ws] = new_ws_desc;
01005 
01006   // send event "on Connection"
01007   _colcows_node->onConnection( num_connection, new_ws_desc, connection_initiator );
01008 
01009   unsigned long nb_children = _children_nodes->length();
01010 
01011   for (unsigned long j = 0; j < nb_children; j++) {
01012     _children_nodes[j].node_ref->setRemoteWorkspace(num_connection, new_ws_desc, connection_initiator);
01013   }
01014 
01015 __END_REDIRECT_ALL_EXCEPTIONS_TO_CORBA__ 
01016   COLCOWS_OUT_DEBUG();
01017   return ;
01018 }
01019     
01020 //===========================================================================//
01021     
01022 //! set the remote workspace description [public]
01023 void NodeServant::releaseRemoteWorkspace(CORBA::ULong num_connection )
01024 {
01025   COLCOWS_IN_DEBUG();
01026 __BEGIN_REDIRECT_ALL_EXCEPTIONS_TO_CORBA__
01027 
01028   unsigned long num_ws;
01029   unsigned long nb_ws =  _remote_workspaces->length();
01030   for (num_ws = 0; num_ws < nb_ws; num_ws++)
01031     {
01032       if ( _remote_workspaces[num_ws].num_connection == num_connection )
01033         {
01034           break;
01035         }
01036     }
01037 
01038   if (num_ws != nb_ws) {
01039 
01040     if (num_ws != nb_ws - 1) {
01041       // I don't think this operation need a deep copy ...
01042       _remote_workspaces[num_ws] = _remote_workspaces[nb_ws - 1];
01043     }
01044 
01045     _remote_workspaces->length(nb_ws-1);
01046 
01047     // send event "on disconnection"
01048     _colcows_node->onDisconnection( num_connection );
01049 
01050     unsigned long nb_children = _children_nodes->length();
01051 
01052     // forward to children 
01053     for (unsigned long j = 0; j < nb_children; j++) {
01054       _children_nodes[j].node_ref->releaseRemoteWorkspace(num_connection);
01055     }
01056 
01057   }
01058   else
01059     COLCOWS_ASSERT( dblWarning, "Cannot find connection ..." 
01060                     << "The connection " << num_connection << " may have been already disconnected." );
01061 
01062 
01063 __END_REDIRECT_ALL_EXCEPTIONS_TO_CORBA__ 
01064   COLCOWS_OUT_DEBUG();
01065   return ;
01066 }
01067     
01068 //===========================================================================//
01069 
01070 void NodeServant::printself(ostream & stream) const 
01071 {
01072   stream << "IdlNodeDesc : "          << _my_node         << endl;
01073   stream << "IdlWorkspaceDesc : "     << _local_workspace   << endl;
01074   stream << "IdlWorkspaceDescSeq : "  << _remote_workspaces << endl;
01075 }
01076 
01077 //===========================================================================//
01078 
01079 ostream& operator <<(ostream& stream, const NodeServant & _this)
01080 {
01081   stream << "Node {" << flush; 
01082   _this.printself(stream);
01083   stream << "}" << flush;
01084   return stream;
01085 }
01086 
01087 //! standard output stream operators
01088 //===========================================================================//
01089 
01090 std::ostream& operator <<(std::ostream& stream, const IdlWorkspaceDesc& wsdesc)
01091 {
01092   stream << endl;
01093   stream << "( ws_id : "       << wsdesc.ws_id      << flush;
01094   stream << endl;
01095   stream << "( ws_kind : "     << wsdesc.ws_kind    << flush;
01096   stream << endl;
01097   stream << ", nb_nodes : "   << wsdesc.nb_nodes  << flush;
01098   stream << endl;
01099   stream << ", activated : "  << wsdesc.activated << flush;
01100   stream << endl;
01101   stream << ", enter_node_ref : " << "..."            << flush;
01102   stream << " )" << flush; 
01103   return stream;
01104 }
01105 
01106 //===========================================================================//
01107 
01108 std::ostream& operator <<(std::ostream& stream, const IdlWorkspaceDescSeq& wsdesc_seq)
01109 {
01110   stream << "{" << flush;
01111   for (unsigned long i = 0; i < wsdesc_seq.length(); i++) {
01112     stream << endl;
01113     stream << " " << wsdesc_seq[i] << flush;   
01114   }
01115   stream << " }" << flush;
01116   return stream;
01117 }
01118 
01119 //===========================================================================//
01120 
01121 std::ostream& operator <<(std::ostream& stream, const IdlNodeDesc& wsnode)
01122 {
01123   stream << endl << "(" << flush;
01124   stream << "  node_kind : "       << wsnode.node_kind      << flush;
01125   stream << endl;   
01126   stream << ", num_node : "  << wsnode.num_node << flush;
01127   stream << endl;
01128   stream << ", max_descendant : "  << wsnode.max_descendant << flush;
01129   stream << endl;
01130   stream << ", activated : "       << wsnode.activated      << flush;
01131   stream << endl;
01132   stream << ", node : "            << "..."                 << flush;
01133   stream << endl;
01134   stream << ", ref_seq : "         << wsnode.ref_seq        << flush;
01135   stream << " )" << flush; 
01136   return stream;
01137 }
01138 
01139 //===========================================================================//
01140 
01141 std::ostream& operator <<(std::ostream& stream, const IdlNodeDescSeq& wsnode_seq)
01142 {
01143   stream << "{" << flush;
01144   for (unsigned long i = 0; i < wsnode_seq.length(); i++) {
01145     stream << endl;    
01146     stream << " " << wsnode_seq[i] << flush;   
01147   }
01148   stream << " }" << flush;
01149   return stream;
01150 }
01151 
01152 //===========================================================================//
01153 
01154 std::ostream& operator <<(std::ostream& stream, const IdlObjectDesc& ref)
01155 {
01156   //  stream << "( num_node : " << ref.num_node << flush;
01157   stream << "( obj_id : "          << ref.obj_id          << flush;
01158   stream << ", obj_kind : "        << ref.obj_kind        << flush;
01159   stream << ", obj_ref : "         << "..."              << flush;
01160   stream << " )" << flush;   
01161   return stream;
01162 }
01163 
01164 //===========================================================================//
01165 
01166 std::ostream& operator <<(std::ostream& stream, const IdlObjectDescSeq& ref_seq)
01167 {
01168    stream << "{" << flush;
01169   for (unsigned long i = 0; i < ref_seq.length(); i++)
01170     stream << " " << ref_seq[i] << flush;   
01171   stream << " }" << flush;
01172   return stream;
01173 }
01174 
01175 //===========================================================================//
01176 
01177 __COLCOWS_END__
01178 
01179 // EOF

Generated on Tue Jun 21 12:55:56 2005 for ColCOWS by  doxygen 1.4.1