Fawkes API Fawkes Development Version
|
00001 00002 /*************************************************************************** 00003 * multi_copy.cpp - Fawkes WorldModel Multi Interface Copy Fuser 00004 * 00005 * Created: Tue Jan 13 11:58:33 2009 00006 * Copyright 2006-2009 Tim Niemueller [www.niemueller.de] 00007 * 00008 ****************************************************************************/ 00009 00010 /* This program is free software; you can redistribute it and/or modify 00011 * it under the terms of the GNU General Public License as published by 00012 * the Free Software Foundation; either version 2 of the License, or 00013 * (at your option) any later version. 00014 * 00015 * This program is distributed in the hope that it will be useful, 00016 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00017 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00018 * GNU Library General Public License for more details. 00019 * 00020 * Read the full text in the LICENSE.GPL file in the doc directory. 00021 */ 00022 00023 #include "multi_copy.h" 00024 00025 #include <core/threading/mutex_locker.h> 00026 #include <blackboard/blackboard.h> 00027 #include <interface/interface.h> 00028 #include <core/exceptions/system.h> 00029 00030 #include <cstdlib> 00031 #include <cstring> 00032 #include <cstdio> 00033 00034 using namespace fawkes; 00035 00036 /** @class WorldModelMultiCopyFuser "multi_copy.h" 00037 * Multi interface copy fuser. 00038 * This fuser simply copies the data of a number of interfaces to another set 00039 * (of the same size) of interfaces. 00040 * The source interfaces are given as pattern with shell wildcards like * and ?. 00041 * The destination IDs is a pattern that contains exactly one "%u". This is 00042 * replaced with a running number for the destination interfaces. The fuser 00043 * registers as an observer and opens any newly created interfaces that match 00044 * the given pattern and creates a write with the ID like the given format for it. 00045 * It accounts for the case where pattern and format are similar and avoids opening 00046 * it's own interfaces causing an infinite loop. Interfaces are never closed. 00047 * @author Tim Niemueller 00048 */ 00049 00050 /** Constructor. 00051 * @param blackboard BlackBoard 00052 * @param type interface type of both interfaces 00053 * @param from_id_pattern pattern for ID of the interfaces to copy from 00054 * @param to_id_format format for ID of the interfaces to copy to 00055 */ 00056 WorldModelMultiCopyFuser::WorldModelMultiCopyFuser(fawkes::BlackBoard *blackboard, 00057 const char *type, 00058 const char *from_id_pattern, 00059 const char *to_id_format) 00060 { 00061 __blackboard = blackboard; 00062 __from_id_pattern = from_id_pattern; 00063 __to_id_format = to_id_format; 00064 00065 std::string::size_type loc = 0; 00066 loc = __to_id_format.find("%"); 00067 if ( (loc == std::string::npos) || 00068 (__to_id_format.find("%", loc+1) != std::string::npos) || 00069 (__to_id_format.find("%u") == std::string::npos) ) { 00070 throw Exception("to_id_format ('%s') must contain exactly one occurrence of %%u", to_id_format); 00071 } 00072 00073 std::list<Interface *> exifs; 00074 try { 00075 exifs = blackboard->open_multiple_for_reading(type, from_id_pattern); 00076 unsigned int u = 0; 00077 for (std::list<Interface *>::iterator i = exifs.begin(); i != exifs.end(); ++i) { 00078 char *tid; 00079 if (asprintf(&tid, to_id_format, ++u) != -1) { 00080 std::string sid = tid; 00081 free(tid); 00082 Interface *to_if = blackboard->open_for_writing(type, sid.c_str()); 00083 __ifmap[*i] = to_if; 00084 } else { 00085 throw OutOfMemoryException("Could not create interface ID, out of memory"); 00086 } 00087 } 00088 } catch (Exception &e) { 00089 for (std::list<Interface *>::iterator i = exifs.begin(); i != exifs.end(); ++i) { 00090 blackboard->close(*i); 00091 } 00092 for (__imi = __ifmap.begin(); __imi != __ifmap.end(); ++__imi) { 00093 blackboard->close(__imi->second); 00094 } 00095 throw; 00096 } 00097 00098 bbio_add_observed_create(type, from_id_pattern); 00099 blackboard->register_observer(this, BlackBoard::BBIO_FLAG_CREATED); 00100 } 00101 00102 00103 /** Destructor. */ 00104 WorldModelMultiCopyFuser::~WorldModelMultiCopyFuser() 00105 { 00106 __blackboard->unregister_observer(this); 00107 00108 __ifmap.lock(); 00109 for (__imi = __ifmap.begin(); __imi != __ifmap.end(); ++__imi) { 00110 __blackboard->close(__imi->first); 00111 __blackboard->close(__imi->second); 00112 } 00113 __ifmap.clear(); 00114 __ifmap.unlock(); 00115 } 00116 00117 00118 void 00119 WorldModelMultiCopyFuser::bb_interface_created(const char *type, const char *id) throw() 00120 { 00121 unsigned int u; 00122 if (sscanf(id, __to_id_format.c_str(), &u) == 1) { 00123 // it's our own writing instance, ignore 00124 return; 00125 } 00126 00127 char *tid; 00128 u = __ifmap.size(); 00129 if (asprintf(&tid, __to_id_format.c_str(), u) == -1) { 00130 printf("Could not create ID string, asprintf() ran out of memory"); 00131 return; 00132 } 00133 std::string sid = tid; 00134 free(tid); 00135 00136 Interface *from_if = NULL; 00137 Interface *to_if = NULL; 00138 00139 try { 00140 from_if = __blackboard->open_for_reading(type, id); 00141 to_if = __blackboard->open_for_writing(type, sid.c_str()); 00142 00143 __ifmap.lock(); 00144 __ifmap[from_if] = to_if; 00145 __ifmap.unlock(); 00146 } catch (Exception &e) { 00147 __blackboard->close(from_if); 00148 __blackboard->close(to_if); 00149 e.print_trace(); 00150 } 00151 } 00152 00153 00154 void 00155 WorldModelMultiCopyFuser::fuse() 00156 { 00157 MutexLocker lock(__ifmap.mutex()); 00158 for (__imi = __ifmap.begin(); __imi != __ifmap.end(); ++__imi) { 00159 if (__imi->first->has_writer()) { 00160 __imi->first->read(); 00161 __imi->second->copy_values(__imi->first); 00162 __imi->second->write(); 00163 } 00164 } 00165 }