Fawkes API  Fawkes Development Version
qa_bb_remote.cpp
1 
2 /***************************************************************************
3  * qa_bb_remote.cpp - BlackBoard remote access QA
4  *
5  * Created: Mon Mar 03 17:31:18 2008
6  * Copyright 2006-2008 Tim Niemueller [www.niemueller.de]
7  *
8  ****************************************************************************/
9 
10 /* This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version. A runtime exception applies to
14  * this software (see LICENSE.GPL_WRE file mentioned below for details).
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19  * GNU Library General Public License for more details.
20  *
21  * Read the full text in the LICENSE.GPL_WRE file in the doc directory.
22  */
23 
24 
25 /// @cond QA
26 
27 #include <blackboard/local.h>
28 #include <blackboard/remote.h>
29 #include <blackboard/exceptions.h>
30 #include <blackboard/bbconfig.h>
31 #include <blackboard/interface_listener.h>
32 
33 #include <interfaces/TestInterface.h>
34 
35 #include <interface/interface_info.h>
36 #include <core/exceptions/system.h>
37 #include <netcomm/fawkes/client.h>
38 #include <netcomm/fawkes/server_thread.h>
39 #include <utils/time/time.h>
40 
41 #include <signal.h>
42 #include <cstdlib>
43 #include <cstring>
44 #include <cstdio>
45 
46 #include <iostream>
47 #include <vector>
48 
49 using namespace std;
50 using namespace fawkes;
51 
52 
53 bool quit = false;
54 
55 void
56 signal_handler(int signum)
57 {
58  quit = true;
59 }
60 
61 
62 #define NUM_CHUNKS 5
63 
64 void
65 test_messaging(TestInterface *ti_reader, TestInterface *ti_writer)
66 {
67  while (! quit) {
68  int expval = ti_reader->test_int() + 1;
70  unsigned int msgid = ti_reader->msgq_enqueue(m);
71  printf("Sent with message ID %u\n", msgid);
72 
73  if ( ti_writer->msgq_size() > 1 ) {
74  cout << "Error, more than one message! flushing." << endl;
75  ti_writer->msgq_flush();
76  }
77 
78  usleep(100000);
79 
80  if ( ti_writer->msgq_first() != NULL ) {
82  TestInterface::SetTestStringMessage *msg = ti_writer->msgq_first(msg);
83  printf("Received message of ID %u, Message improperly detected to be a SetTestStringMessage\n", msg->id());
84  }
85  if ( ti_writer->msgq_first_is<TestInterface::SetTestIntMessage>() ) {
87  printf("Received message with ID %u (enqueue time: %s)\n", m2->id(), m2->time_enqueued()->str());
88  ti_writer->set_test_int( m2->test_int() );
89  try {
90  ti_writer->write();
91  } catch (InterfaceWriteDeniedException &e) {
92  cout << "BUG: caught write denied exception" << endl;
93  e.print_trace();
94  }
95  ti_writer->msgq_pop();
96  } else {
97  cout << "Illegal message '" << ti_writer->msgq_first()->type() << "' type received" << endl;
98  }
99 
100  usleep(100000);
101 
102  //cout << "Reading value from reader interface.. " << flush;
103  ti_reader->read();
104  int val = ti_reader->test_int();
105  if ( val == expval ) {
106  //cout << " success, value is " << ti_reader->test_int() << " as expected" << endl;
107  } else {
108  cout << " failure, value is " << ti_reader->test_int() << ", expected "
109  << expval << endl;
110  }
111  } else {
112  printf("No message in queue, if network test this means the message was dropped\n");
113  }
114 
115  usleep(10);
116  }
117 }
118 
120 {
121 public:
123  fawkes::Interface *writer,
124  fawkes::BlackBoard *reader_bb,
125  fawkes::BlackBoard *writer_bb)
126  : BlackBoardInterfaceListener("SyncInterfaceListener(%s-%s)", writer->uid(), reader->id())
127  {
128  __reader = reader;
129  __writer = writer;
130  __reader_bb = reader_bb;
131  __writer_bb = writer_bb;
132 
133  bbil_add_data_interface(__reader);
134  bbil_add_message_interface(__writer);
135 
136  __reader_bb->register_listener(this);
137  __writer_bb->register_listener(this);
138  }
139 
140 
141  /** Destructor. */
143  {
144  __reader_bb->unregister_listener(this);
145  __writer_bb->unregister_listener(this);
146  }
147 
148 
149  bool
150  bb_interface_message_received(Interface *interface,
151  Message *message) throw()
152  {
153  try {
154  if ( interface == __writer ) {
155  printf("%s: Forwarding message\n", bbil_name());
156  Message *m = message->clone();
157  m->set_hops(message->hops());
158  m->ref();
159  __reader->msgq_enqueue(m);
160  message->set_id(m->id());
161  m->unref();
162  return false;
163  } else {
164  // Don't know why we were called, let 'em enqueue
165  printf("%s: Message received for unknown interface\n", bbil_name());
166  return true;
167  }
168  } catch (Exception &e) {
169  printf("%s: Exception when message received\n", bbil_name());
170  e.print_trace();
171  return false;
172  }
173  }
174 
175 
176  void
177  bb_interface_data_changed(Interface *interface) throw()
178  {
179  try {
180  if ( interface == __reader ) {
181  //__logger->log_debug(bbil_name(), "Copying data");
182  __reader->read();
183  __writer->copy_values(__reader);
184  __writer->write();
185  } else {
186  // Don't know why we were called, let 'em enqueue
187  printf("%s: Data changed for unknown interface", bbil_name());
188  }
189  } catch (Exception &e) {
190  printf("%s: Exception when data changed\n", bbil_name());
191  e.print_trace();
192  }
193  }
194 
195  private:
196  fawkes::Interface *__writer;
197  fawkes::Interface *__reader;
198 
199  fawkes::BlackBoard *__writer_bb;
200  fawkes::BlackBoard *__reader_bb;
201 
202 };
203 
204 
205 int
206 main(int argc, char **argv)
207 {
208  signal(SIGINT, signal_handler);
209 
210  LocalBlackBoard *llbb = new LocalBlackBoard(BLACKBOARD_MEMSIZE);
211  BlackBoard *lbb = llbb;
212 
214  fns->start();
215 
216  llbb->start_nethandler(fns);
217 
218  BlackBoard *rbb = new RemoteBlackBoard("localhost", 1910);
219 
220  InterfaceInfoList *infl = rbb->list_all();
221  for (InterfaceInfoList::iterator i = infl->begin(); i != infl->end(); ++i) {
222  const unsigned char *hash = (*i).hash();
223  char phash[__INTERFACE_HASH_SIZE * 2 + 1];
224  memset(phash, 0, sizeof(phash));
225  for (unsigned int j = 0; j < __INTERFACE_HASH_SIZE; ++j) {
226  sprintf(&phash[j * 2], "%02x", hash[j]);
227  }
228  printf("%s::%s (%s), w:%i r:%u s:%u\n",
229  (*i).type(), (*i).id(), phash, (*i).has_writer(),
230  (*i).num_readers(), (*i).serial());
231  }
232  delete infl;
233 
234  //TestInterface *ti_writer;
235  TestInterface *ti_reader;
236  TestInterface *ti_writer;
237  try {
238  cout << "Opening interfaces.. " << flush;
239  ti_writer = rbb->open_for_writing<TestInterface>("SomeID");
240  ti_reader = rbb->open_for_reading<TestInterface>("SomeID");
241  cout << "success, "
242  << "writer hash=" << ti_writer->hash_printable()
243  << " reader hash=" << ti_reader->hash_printable()
244  << endl;
245  } catch (Exception &e) {
246  cout << "failed! Aborting" << endl;
247  e.print_trace();
248  exit(1);
249  }
250 
251  try {
252  cout << "Trying to open second writer.. " << flush;
253  TestInterface *ti_writer_two;
254  ti_writer_two = rbb->open_for_writing<TestInterface>("SomeID");
255  rbb->close(ti_writer_two);
256  cout << "BUG: Detection of second writer did NOT work!" << endl;
257  exit(2);
258  } catch (BlackBoardWriterActiveException &e) {
259  cout << "exception caught as expected, detected and prevented second writer!" << endl;
260  }
261 
262  try {
263  cout << "Trying to open third writer.. " << flush;
264  TestInterface *ti_writer_three;
265  ti_writer_three = rbb->open_for_writing<TestInterface>("AnotherID");
266  cout << "No exception as expected, different ID ok!" << endl;
267  rbb->close(ti_writer_three);
268  } catch (BlackBoardWriterActiveException &e) {
269  cout << "BUG: Third writer with different ID detected as another writer!" << endl;
270  exit(3);
271  }
272 
273  cout << endl << endl
274  << "Running data tests ==================================================" << endl;
275 
276  cout << "Writing initial value ("
277  << TestInterface::TEST_CONSTANT << ") into interface as TestInt" << endl;
278  ti_writer->set_test_int( TestInterface::TEST_CONSTANT );
279  try {
280  ti_writer->write();
281  } catch (InterfaceWriteDeniedException &e) {
282  cout << "BUG: caught write denied exception" << endl;
283  e.print_trace();
284  }
285 
286  cout << "Giving some time to have value processed" << endl;
287  usleep(100000);
288 
289  cout << "Reading value from reader interface.. " << flush;
290  ti_reader->read();
291  int val = ti_reader->test_int();
292  if ( val == TestInterface::TEST_CONSTANT ) {
293  cout << " success, value is " << ti_reader->test_int() << " as expected" << endl;
294  } else {
295  cout << " failure, value is " << ti_reader->test_int() << ", expected "
296  << TestInterface::TEST_CONSTANT << endl;
297  }
298 
299  cout << "Closing interfaces.. " << flush;
300  try {
301  rbb->close(ti_reader);
302  rbb->close(ti_writer);
303  cout << "done" << endl;
304  } catch (Exception &e) {
305  cout << "failed" << endl;
306  e.print_trace();
307  }
308 
309  cout << endl << endl << "Starting MESSAGING tests" << endl
310  << "Press Ctrl-C to continue with next test" << endl << endl;
311 
312  ti_writer = lbb->open_for_writing<TestInterface>("Messaging");
313  ti_reader = rbb->open_for_reading<TestInterface>("Messaging");
314 
315  printf("Writer serial: %u shifted: %u\n", ti_writer->serial(), ti_writer->serial() << 16);
316  printf("Reader serial: %u shifted: %u\n", ti_reader->serial(), ti_reader->serial() << 16);
317 
318  test_messaging(ti_reader, ti_writer);
319 
320  rbb->close(ti_reader);
321  lbb->close(ti_writer);
322 
323  cout << endl << endl << "Starting MESSAGING tests, doing repeater scenario" << endl
324  << "Press Ctrl-C to continue with next test" << endl << endl;
325  quit = false;
326 
327  delete rbb;
328 
329  LocalBlackBoard *repllbb = new LocalBlackBoard(BLACKBOARD_MEMSIZE);
330 
332  repfns->start();
333 
334  repllbb->start_nethandler(repfns);
335 
336  BlackBoard *rep_rbb = new RemoteBlackBoard("localhost", 1911);
337  rbb = new RemoteBlackBoard("localhost", 1911);
338 
339  TestInterface *rep_reader;
340  TestInterface *rep_writer;
341 
342  ti_writer = rbb->open_for_writing<TestInterface>("Messaging");
343  ti_reader = lbb->open_for_reading<TestInterface>("Messaging");
344 
345  rep_reader = rep_rbb->open_for_reading<TestInterface>("Messaging");
346  rep_writer = lbb->open_for_writing<TestInterface>("Messaging");
347 
348  printf("Writer serial: %u shifted: %u\n", ti_writer->serial(), ti_writer->serial() << 16);
349  printf("Reader serial: %u shifted: %u\n", ti_reader->serial(), ti_reader->serial() << 16);
350 
351  SyncInterfaceListener *sil = new SyncInterfaceListener(rep_reader, rep_writer, rep_rbb, lbb);
352 
353  test_messaging(ti_reader, ti_writer);
354 
355  delete sil;
356  lbb->close(ti_reader);
357  rbb->close(ti_writer);
358  rep_rbb->close(rep_reader);
359  lbb->close(rep_writer);
360  delete repllbb;
361  delete rep_rbb;
362 
363  cout << "Tests done" << endl;
364 
365  delete rbb;
366  delete llbb;
367  delete fns;
368 }
369 
370 
371 /// @endcond
const Time * time_enqueued() const
Get time when message was enqueued.
Definition: message.cpp:265
Base class for all messages passed through interfaces in Fawkes BlackBoard.
Definition: message.h:44
unsigned int id() const
Get message ID.
Definition: message.cpp:197
const char * str(bool utc=false) const
Output function.
Definition: time.cpp:872
void unref()
Decrement reference count and conditionally delete this instance.
Definition: refcount.cpp:99
Fawkes library namespace.
int32_t test_int() const
Get test_int value.
STL namespace.
Local BlackBoard.
Definition: local.h:44
void write()
Write from local copy into BlackBoard memory.
Definition: interface.cpp:500
Base class for all Fawkes BlackBoard interfaces.
Definition: interface.h:79
unsigned int msgq_size()
Get size of message queue.
Definition: interface.cpp:1032
void set_test_int(const int32_t new_test_int)
Set test_int value.
void msgq_pop()
Erase first message from queue.
Definition: interface.cpp:1193
virtual void start_nethandler(FawkesNetworkHub *hub)
Start network handler.
Definition: local.cpp:209
Interface information list.
Base class for exceptions in Fawkes.
Definition: exception.h:36
Message * msgq_first()
Get the first message from the message queue.
Definition: interface.cpp:1180
unsigned short serial() const
Get instance serial of interface.
Definition: interface.cpp:697
void read()
Read from BlackBoard into local copy.
Definition: interface.cpp:477
virtual Message * clone() const
Clone this message.
void ref()
Increment reference count.
Definition: refcount.cpp:70
SetTestIntMessage Fawkes BlackBoard Interface Message.
Definition: TestInterface.h:68
bool msgq_first_is()
Check if first message has desired type.
Definition: interface.h:314
unsigned int msgq_enqueue(Message *message)
Enqueue message at end of queue.
Definition: interface.cpp:903
void print_trace()
Prints trace to stderr.
Definition: exception.cpp:619
virtual InterfaceInfoList * list_all()=0
Get list of all currently existing interfaces.
Remote BlackBoard.
Definition: remote.h:48
int32_t test_int() const
Get test_int value.
virtual Interface * open_for_reading(const char *interface_type, const char *identifier, const char *owner=NULL)=0
Open interface for reading.
void msgq_flush()
Flush all messages.
Definition: interface.cpp:1064
The BlackBoard abstract class.
Definition: blackboard.h:48
Thrown if a writer is already active on an interface that writing has been requested for...
Definition: exceptions.h:121
SetTestStringMessage Fawkes BlackBoard Interface Message.
Definition: TestInterface.h:94
This exception is thrown if a write has been attempted on a read-only interface.
Definition: interface.h:54
void set_hops(unsigned int hops)
Set number of hops.
Definition: message.cpp:227
Fawkes Network Thread.
Definition: server_thread.h:46
virtual Interface * open_for_writing(const char *interface_type, const char *identifier, const char *owner=NULL)=0
Open interface for writing.
const char * type() const
Get message type.
Definition: message.cpp:378
BlackBoard interface listener.
Synchronize two interfaces.
Definition: sync_listener.h:33
void start(bool wait=true)
Call this method to start the thread.
Definition: thread.cpp:511
TestInterface Fawkes BlackBoard Interface.
Definition: TestInterface.h:33
const char * hash_printable() const
Get printable interface hash.
Definition: interface.cpp:304
virtual void close(Interface *interface)=0
Close interface.