Version: 8.3.0
yacsSrv.cxx
Go to the documentation of this file.
1 // Copyright (C) 2006-2016 CEA/DEN, EDF R&D
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19 
20 #include <Python.h>
21 #include <yacs.hh>
22 #include "RuntimeSALOME.hxx"
23 #include "Proc.hxx"
24 #include "Exception.hxx"
25 #include "Executor.hxx"
26 #include "Dispatcher.hxx"
27 #include "parsers.hxx"
28 
29 #include <iostream>
30 #include <sstream>
31 #include <set>
32 
33 //#define _DEVDEBUG_
34 #include "YacsTrace.hxx"
35 
36 using namespace std;
37 
39 CORBA::ORB_ptr orb;
40 YACS_ORB::YACS_Gen_var myyacsref;
41 
43 {
44 public:
45  void dispatch(YACS::ENGINE::Node* object, const std::string& event)
46  {
47  std::cerr << "dispatch " << object->getNumId() << std::endl;
48  typedef std::set<YACS_ORB::Observer_ptr>::iterator jt;
49  std::pair<int,std::string> key(object->getNumId(),event);
50  for(jt iter=_observers[key].begin();iter!=_observers[key].end();iter++)
51  {
52  (*iter)->notifyObserver((CORBA::Long)object->getNumId(),event.c_str());
53  }
54  }
55 
56  void addObserver(YACS_ORB::Observer_ptr observer,int numid, const std::string& event)
57  {
58  _observers[std::pair<int,std::string>(numid,event)].insert(YACS_ORB::Observer::_duplicate(observer));
59  // printObservers();
60  }
61 protected:
62  std::map< std::pair<int,std::string> , std::set<YACS_ORB::Observer_ptr> > _observers;
63 };
64 
65 class Yacs_i : public POA_YACS_ORB::YACS_Gen,
66  public PortableServer::RefCountServantBase
67 {
68 public:
69  inline Yacs_i() {}
70  virtual ~Yacs_i() {}
71  YACS_ORB::Proc_ptr Load(const char* xmlFile);
72  void Run(YACS_ORB::Proc_ptr p);
73  void addObserver(YACS_ORB::Observer_ptr observer, CORBA::Long numid,const char* event);
74 };
75 
76 class Proc_i : public POA_YACS_ORB::Proc,
77  public PortableServer::RefCountServantBase
78 {
79 public:
80  inline Proc_i(YACS::ENGINE::Proc* p) {_proc=p;};
81  virtual ~Proc_i() {};
82  virtual void RunW();
83  CORBA::Long getState(CORBA::Long numid);
84  char * getXMLState(CORBA::Long numid);
85  void getIds(YACS_ORB::longArray_out numids,YACS_ORB::stringArray_out names);
86 protected:
89 };
90 
92 {
93  _executor.RunW(_proc,0);
94 }
95 
96 CORBA::Long Proc_i::getState(CORBA::Long numid)
97 {
98  if(YACS::ENGINE::Node::idMap.count(numid) == 0)
99  {
100  std::cerr << "Unknown node id " << numid << std::endl;
101  return (CORBA::Long)-1;
102  }
104  CORBA::Long state=node->getEffectiveState();
105  return state;
106 }
107 
108 char * Proc_i::getXMLState(CORBA::Long numid)
109 {
110  if(YACS::ENGINE::Node::idMap.count(numid) == 0)
111  {
112  std::cerr << "Unknown node id " << numid << std::endl;
113  return "<state>unknown</state>";
114  }
116  std::stringstream msg;
117  msg << "<state>" << node->getEffectiveState() << "</state>";
118  msg << "<name>" << node->getQualifiedName() << "</name>";
119  msg << "<id>" << numid << "</id>";
120  return CORBA::string_dup(msg.str().c_str());
121 }
122 
123 void Proc_i::getIds(YACS_ORB::longArray_out numids,YACS_ORB::stringArray_out names)
124 {
125  std::list<YACS::ENGINE::Node *> nodes=_proc->getAllRecursiveNodes();
126  int len=nodes.size();
127  names=new YACS_ORB::stringArray;
128  numids=new YACS_ORB::longArray;
129  names->length(len);
130  numids->length(len);
131  int i=0;
132  for(list<YACS::ENGINE::Node *>::const_iterator iter=nodes.begin();iter!=nodes.end();iter++,i++)
133  {
134  (*names)[i]=CORBA::string_dup((*iter)->getQualifiedName().c_str());
135  (*numids)[i]=(*iter)->getNumId();
136  }
137 }
138 
139 YACS_ORB::Proc_ptr Yacs_i::Load(const char* xmlFile)
140 {
141  YACS::ENGINE::Proc* proc=loader->load(xmlFile);
142  Proc_i* p=new Proc_i(proc);
143  YACS_ORB::Proc_ptr pp = p->_this();
144  return pp;
145 }
146 
147 void Yacs_i::addObserver(YACS_ORB::Observer_ptr observer, CORBA::Long numid,const char* event)
148 {
149  ((MyDispatcher*)YACS::ENGINE::Dispatcher::getDispatcher())->addObserver(observer,numid,event);
150 }
151 
152 void Yacs_i::Run(YACS_ORB::Proc_ptr p)
153 {
154  Proc_i *servant=dynamic_cast<Proc_i *> (PortableServer::POA::_the_root_poa()->reference_to_servant(p));
155  servant->RunW();
156 }
157 
158 static CORBA::Boolean bindObjectToName(CORBA::ORB_ptr, CORBA::Object_ptr,const char*);
159 static ostream& operator<<(ostream& os, const CORBA::Exception& e);
160 
161 int main(int argc, char** argv)
162 {
165  MyDispatcher* disp=new MyDispatcher();
167 
168  try
169  {
170  orb = CORBA::ORB_init(argc, argv);
171 
172  {
173  CORBA::Object_var obj = orb->resolve_initial_references("RootPOA");
174  PortableServer::POA_var root_poa = PortableServer::POA::_narrow(obj);
175  // POA manager
176  PortableServer::POAManager_var poa_man = root_poa->the_POAManager();
177  poa_man->activate();
178 
179  // Create and activate servant
180  Yacs_i* myyacs = new Yacs_i();
181  // Obtain a reference to the object, and print it out as a
182  // stringified IOR.
183  obj = myyacs->_this();
184  CORBA::String_var sior(orb->object_to_string(obj));
185  DEBTRACE("'" << (char*)sior << "'");
186  myyacsref = YACS_ORB::YACS_Gen::_narrow(obj);
187 
188  if( !bindObjectToName(orb, myyacsref,"Yacs") ) return 1;
189 
190  // Decrement the reference count of the object implementation, so
191  // that it will be properly cleaned up when the POA has determined
192  // that it is no longer needed.
193  myyacs->_remove_ref();
194  }
195  orb->run();
196  }
197  catch(CORBA::SystemException&) {
198  DEBTRACE("Caught CORBA::SystemException.");
199  }
200  catch(CORBA::Exception& ex) {
201  DEBTRACE("Caught CORBA::Exception." << ex);
202  }
203  catch(omniORB::fatalException& fe) {
204  DEBTRACE("Caught omniORB::fatalException:");
205  DEBTRACE(" file: " << fe.file());
206  DEBTRACE(" line: " << fe.line());
207  DEBTRACE(" mesg: " << fe.errmsg());
208  }
209  catch(...) {
210  DEBTRACE("Caught unknown exception." );
211  }
212 
213  return 0;
214 }
215 
216 
218 
219 static CORBA::Boolean
220 bindObjectToName(CORBA::ORB_ptr orb, CORBA::Object_ptr objref,const char *name)
221 {
222  CosNaming::NamingContext_var rootContext;
223 
224  try {
225  // Obtain a reference to the root context of the Name service:
226  CORBA::Object_var obj;
227  obj = orb->resolve_initial_references("NameService");
228 
229  // Narrow the reference returned.
230  rootContext = CosNaming::NamingContext::_narrow(obj);
231  if( CORBA::is_nil(rootContext) ) {
232  DEBTRACE("Failed to narrow the root naming context.");
233  return 0;
234  }
235  }
236  catch(CORBA::ORB::InvalidName& ex) {
237  // This should not happen!
238  DEBTRACE("Service required is invalid [does not exist]." );
239  return 0;
240  }
241 
242  try {
243  // Bind a context called "test" to the root context:
244 
245  CosNaming::Name contextName;
246  contextName.length(1);
247  contextName[0].id = (const char*) "test"; // string copied
248  contextName[0].kind = (const char*) "my_context"; // string copied
249  // Note on kind: The kind field is used to indicate the type
250  // of the object. This is to avoid conventions such as that used
251  // by files (name.type -- e.g. test.ps = postscript etc.)
252 
253  CosNaming::NamingContext_var testContext;
254  try {
255  // Bind the context to root.
256  testContext = rootContext->bind_new_context(contextName);
257  }
258  catch(CosNaming::NamingContext::AlreadyBound& ex) {
259  // If the context already exists, this exception will be raised.
260  // In this case, just resolve the name and assign testContext
261  // to the object returned:
262  CORBA::Object_var obj;
263  obj = rootContext->resolve(contextName);
264  testContext = CosNaming::NamingContext::_narrow(obj);
265  if( CORBA::is_nil(testContext) ) {
266  DEBTRACE("Failed to narrow naming context.");
267  return 0;
268  }
269  }
270 
271  // Bind objref with name name to the testContext:
272  CosNaming::Name objectName;
273  objectName.length(1);
274  objectName[0].id = name; // string copied
275  objectName[0].kind = (const char*) "Object"; // string copied
276 
277  try {
278  testContext->bind(objectName, objref);
279  }
280  catch(CosNaming::NamingContext::AlreadyBound& ex) {
281  testContext->rebind(objectName, objref);
282  }
283  }
284  catch(CORBA::COMM_FAILURE& ex) {
285  DEBTRACE("Caught system exception COMM_FAILURE -- unable to contact the "
286  << "naming service.");
287  return 0;
288  }
289  catch(CORBA::SystemException&) {
290  DEBTRACE("Caught a CORBA::SystemException while using the naming service.");
291  return 0;
292  }
293 
294  return 1;
295 }
296 
297 static ostream& operator<<(ostream& os, const CORBA::Exception& e)
298 {
299  CORBA::Any tmp;
300  tmp<<= e;
301  CORBA::TypeCode_var tc = tmp.type();
302  const char *p = tc->name();
303  if ( *p != '\0' ) {
304  os<<p;
305  }
306  else {
307  os << tc->id();
308  }
309  return os;
310 }