Fawkes API  Fawkes Development Version
multi_copy.cpp
1 
2 /***************************************************************************
3  * multi_copy.cpp - Fawkes WorldModel Multi Interface Copy Fuser
4  *
5  * Created: Tue Jan 13 11:58:33 2009
6  * Copyright 2006-2009 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.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18  * GNU Library General Public License for more details.
19  *
20  * Read the full text in the LICENSE.GPL file in the doc directory.
21  */
22 
23 #include "multi_copy.h"
24 
25 #include <core/threading/mutex_locker.h>
26 #include <blackboard/blackboard.h>
27 #include <interface/interface.h>
28 #include <core/exceptions/system.h>
29 
30 #include <cstdlib>
31 #include <cstring>
32 #include <cstdio>
33 
34 using namespace fawkes;
35 
36 /** @class WorldModelMultiCopyFuser "multi_copy.h"
37  * Multi interface copy fuser.
38  * This fuser simply copies the data of a number of interfaces to another set
39  * (of the same size) of interfaces.
40  * The source interfaces are given as pattern with shell wildcards like * and ?.
41  * The destination IDs is a pattern that contains exactly one "%u". This is
42  * replaced with a running number for the destination interfaces. The fuser
43  * registers as an observer and opens any newly created interfaces that match
44  * the given pattern and creates a write with the ID like the given format for it.
45  * It accounts for the case where pattern and format are similar and avoids opening
46  * it's own interfaces causing an infinite loop. Interfaces are never closed.
47  * @author Tim Niemueller
48  */
49 
50 /** Constructor.
51  * @param blackboard BlackBoard
52  * @param type interface type of both interfaces
53  * @param from_id_pattern pattern for ID of the interfaces to copy from
54  * @param to_id_format format for ID of the interfaces to copy to
55  */
57  const char *type,
58  const char *from_id_pattern,
59  const char *to_id_format)
60 {
61  __blackboard = blackboard;
62  __from_id_pattern = from_id_pattern;
63  __to_id_format = to_id_format;
64 
65  std::string::size_type loc = 0;
66  loc = __to_id_format.find("%");
67  if ( (loc == std::string::npos) ||
68  (__to_id_format.find("%", loc+1) != std::string::npos) ||
69  (__to_id_format.find("%u") == std::string::npos) ) {
70  throw Exception("to_id_format ('%s') must contain exactly one occurrence of %%u", to_id_format);
71  }
72 
73  std::list<Interface *> exifs;
74  try {
75  exifs = blackboard->open_multiple_for_reading(type, from_id_pattern);
76  unsigned int u = 0;
77  for (std::list<Interface *>::iterator i = exifs.begin(); i != exifs.end(); ++i) {
78  char *tid;
79  if (asprintf(&tid, to_id_format, ++u) != -1) {
80  std::string sid = tid;
81  free(tid);
82  Interface *to_if = blackboard->open_for_writing(type, sid.c_str());
83  __ifmap[*i] = to_if;
84  } else {
85  throw OutOfMemoryException("Could not create interface ID, out of memory");
86  }
87  }
88  } catch (Exception &e) {
89  for (std::list<Interface *>::iterator i = exifs.begin(); i != exifs.end(); ++i) {
90  blackboard->close(*i);
91  }
92  for (__imi = __ifmap.begin(); __imi != __ifmap.end(); ++__imi) {
93  blackboard->close(__imi->second);
94  }
95  throw;
96  }
97 
98  bbio_add_observed_create(type, from_id_pattern);
99  blackboard->register_observer(this);
100 }
101 
102 
103 /** Destructor. */
105 {
106  __blackboard->unregister_observer(this);
107 
108  __ifmap.lock();
109  for (__imi = __ifmap.begin(); __imi != __ifmap.end(); ++__imi) {
110  __blackboard->close(__imi->first);
111  __blackboard->close(__imi->second);
112  }
113  __ifmap.clear();
114  __ifmap.unlock();
115 }
116 
117 
118 void
119 WorldModelMultiCopyFuser::bb_interface_created(const char *type, const char *id) throw()
120 {
121  unsigned int u;
122  if (sscanf(id, __to_id_format.c_str(), &u) == 1) {
123  // it's our own writing instance, ignore
124  return;
125  }
126 
127  char *tid;
128  u = __ifmap.size();
129  if (asprintf(&tid, __to_id_format.c_str(), u) == -1) {
130  printf("Could not create ID string, asprintf() ran out of memory");
131  return;
132  }
133  std::string sid = tid;
134  free(tid);
135 
136  Interface *from_if = NULL;
137  Interface *to_if = NULL;
138 
139  try {
140  from_if = __blackboard->open_for_reading(type, id);
141  to_if = __blackboard->open_for_writing(type, sid.c_str());
142 
143  __ifmap.lock();
144  __ifmap[from_if] = to_if;
145  __ifmap.unlock();
146  } catch (Exception &e) {
147  __blackboard->close(from_if);
148  __blackboard->close(to_if);
149  e.print_trace();
150  }
151 }
152 
153 
154 void
156 {
157  MutexLocker lock(__ifmap.mutex());
158  for (__imi = __ifmap.begin(); __imi != __ifmap.end(); ++__imi) {
159  if (__imi->first->has_writer()) {
160  __imi->first->read();
161  __imi->second->copy_values(__imi->first);
162  __imi->second->write();
163  }
164  }
165 }
virtual void register_observer(BlackBoardInterfaceObserver *observer)
Register BB interface observer.
Definition: blackboard.cpp:211
Fawkes library namespace.
Mutex locking helper.
Definition: mutex_locker.h:33
Base class for all Fawkes BlackBoard interfaces.
Definition: interface.h:80
virtual Interface * open_for_writing(const char *interface_type, const char *identifier)=0
Open interface for writing.
~WorldModelMultiCopyFuser()
Destructor.
Definition: multi_copy.cpp:104
Base class for exceptions in Fawkes.
Definition: exception.h:36
virtual void fuse()
The single function that makes fusers work.
Definition: multi_copy.cpp:155
void print_trace()
Prints trace to stderr.
Definition: exception.cpp:619
virtual void bb_interface_created(const char *type, const char *id)
BlackBoard interface created notification.
Definition: multi_copy.cpp:119
The BlackBoard abstract class.
Definition: blackboard.h:49
virtual std::list< Interface * > open_multiple_for_reading(const char *type_pattern, const char *id_pattern="*")=0
Open multiple interfaces for reading.
WorldModelMultiCopyFuser(fawkes::BlackBoard *blackboard, const char *type, const char *from_id_pattern, const char *to_id_format)
Constructor.
Definition: multi_copy.cpp:56
System ran out of memory and desired operation could not be fulfilled.
Definition: system.h:32
virtual void close(Interface *interface)=0
Close interface.