3 * @author Reinhard Pfau \<Reinhard.Pfau@intra2net.com\>
5 * @copyright © Copyright 2008 by Intra2net AG
7 * @contact info@intra2net.com
10 #include "i2n_global_config.hpp"
16 #include <filefunc.hxx>
17 #include <stringfunc.hxx>
18 #include <i2n_configdata.hpp>
19 #include <i2n_configfile.hpp>
20 #include <logfunc.hpp>
21 #include <tracefunc.hpp>
29 #define DOUT(msg) std::cout << msg << std::endl
31 #define DOUT(msg) do {} while (0)
46 } // eo namespace Detail
54 Logger::PartLogger& module_logger()
56 static Logger::PartLogger _logger(HERE);
58 } // eo module_logger()
62 std::string config_file_name;
64 ConfigData config_data;
73 : public Detail::Thing
76 const std::string& section,
77 const std::string& key,
78 const Detail::FeedFunction& feed,
79 const Detail::FeedFunction2& feed2);
83 Detail::FeedFunction m_feed;
84 Detail::FeedFunction2 m_feed2;
85 std::string m_section;
87 }; // eo struct HideOut
89 typedef boost::shared_ptr< HideOut > HideOutPtr;
93 : public GroupedKeyValueData<
101 virtual ~HideOutMap();
105 static int Instances;
106 }; // eo class HideOutMap
108 int HideOutMap::Instances= 0;
110 HideOutMap::HideOutMap()
112 DOUT("HideOutMap::HideOutMap()");
114 } // eo HideOutMap::HideOutMap()
117 HideOutMap::~HideOutMap()
119 DOUT("HideOutMap::~HideOutMap()");
121 } // eo HideOutMap::~HideOutMap()
124 HideOutMap& hideout_map()
126 static HideOutMap the_hideout_map;
127 DOUT("hideout_map()");
128 return the_hideout_map;
129 } // eo hideout_map()
132 // implementation of HideOut:
136 const std::string& section,
137 const std::string& key,
138 const Detail::FeedFunction& feed,
139 const Detail::FeedFunction2& feed2)
145 hideout_map()[section][key]+= this;
146 } // eo HideOut::HideOut(const FeedFunction&)
152 if (HideOutMap::Instances)
154 hideout_map()[m_section].removeValue(m_key,this);
156 } // eo HideOut::~HideOut()
166 * @brief distributes (new) values to the active config variables.
167 * @param old_config_data reference to the old config data (for determining the deltas).
168 * @return @a true if new values could be converted without an error.
170 bool feedEm( ConfigData& old_config_data )
174 HideOutMap::KeyListType section_list;
175 hideout_map().getKeys(section_list);
176 for(HideOutMap::KeyListType::const_iterator section_it = section_list.begin();
177 section_it != section_list.end();
180 std::string section( *section_it );
181 DOUT("process section \"" << section << "\"");
182 HideOutMap::GroupDataType::KeyListType key_list;
183 hideout_map()[section].getKeys(key_list);
184 for(HideOutMap::GroupDataType::KeyListType::const_iterator key_it= key_list.begin();
185 key_it != key_list.end();
188 std::string key( *key_it );
189 DOUT("process key \"" << key << "\"");
190 bool has_new_data= config_data.hasKey(section, key);
191 bool has_old_data= old_config_data.hasKey(section, key);
192 if (not has_new_data and not has_old_data)
194 // we don't have data and we didn't had data... well, nothing to do:
200 DOUT("has (new) data");
202 config_data[section].getValues(key, values);
203 std::string value( config_data[section][key] );
206 StringList old_values;
207 old_config_data[section].getValues(key, old_values);
208 if (values == old_values)
210 // value didn't change, so we can skip this case.
211 DOUT("data is same as before");
215 // at this point we need to publish (new or changed) value:
216 HideOutMap::GroupDataType::ValueListType func_list;
217 hideout_map()[section].getValues(key, func_list);
218 for(HideOutMap::GroupDataType::ValueListType::iterator func_it= func_list.begin();
219 func_it != func_list.end();
222 DOUT(" feed iteration");
223 if (not (*func_it)) //paranoia
227 if ( (*func_it)->m_feed)
229 if ( not (*func_it)->m_feed( value ) )
231 module_logger().error() << "unable to publish [" <<section << "]"
232 << " \"" << key << "\" : \"" << value << "\""
238 if ( (*func_it)->m_feed2)
240 if ( not (*func_it)->m_feed2( values ) )
242 module_logger().error() << "unable to publish [" <<section << "]"
243 << " \"" << key << "\" : ...\"" << value << "\""
249 module_logger().error() << "no feeder";
253 // at this point we don't have (new) data, but we had old data...
255 DOUT("had old data");
258 // at this point we need to publish (vanished) value:
259 HideOutMap::GroupDataType::ValueListType func_list;
260 hideout_map()[section].getValues(key, func_list);
261 for(HideOutMap::GroupDataType::ValueListType::iterator func_it= func_list.begin();
262 func_it != func_list.end();
265 DOUT(" feed iteration");
266 if (not (*func_it)) //paranoia
270 if ( (*func_it)->m_feed)
272 //TODO reset the data (to initial value) somehow?
273 // for now; we just keep the last value...
276 if ( (*func_it)->m_feed2)
278 if ( not (*func_it)->m_feed2( values ) )
280 module_logger().error() << "unable to publish [" <<section << "]"
281 << " \"" << key << "\" : <empty> "
287 module_logger().error() << "no feeder";
294 } // eo feedEm(ConfigData&,ConfigData&)
302 } // eo namespace <anonymous>
305 /************************************************************************\
306 \************************************************************************/
314 const std::string& section,
315 const std::string& key,
316 const FeedFunction& feed)
318 DOUT("seymor(\"" << section << "\", \"" << key << "\",FeedFunction)");
319 FlowerShop result( new HideOut( section, key, feed, 0 ) );
320 if (not config_data.empty())
322 if (config_data.hasKey(section, key))
324 feed( config_data[section][key] );
328 } // eo seymour(const std::string&,const std::string&,const FeedFunction&)
332 const std::string& section,
333 const std::string& key,
334 const FeedFunction2& feed)
336 DOUT("seymor(\"" << section << "\", \"" << key << "\",FeedFunction2)");
337 FlowerShop result( new HideOut( section, key, 0, feed ) );
338 if (not config_data.empty())
340 if (config_data.hasKey(section, key))
343 config_data[section].getValues(key, values);
348 } // eo seymour(const std::string&,const std::string&,const FeedFunction2&)
351 FlowerShop seymour(FlowerShop shop, const FeedFunction& feed)
355 // no shop; no coordinates; no useful stuff to do...
358 HideOutPtr ptr = boost::shared_dynamic_cast< HideOut >(shop);
361 // again, no coordinates...
364 FlowerShop result( new HideOut( ptr->m_section, ptr->m_key, feed, 0 ) );
365 if (not config_data.empty())
367 if (config_data.hasKey(ptr->m_section, ptr->m_key))
369 feed( config_data[ptr->m_section][ptr->m_key] );
373 } // eo seymour(FlowerShop,const FeedFunction&)
376 FlowerShop seymour(FlowerShop shop, const FeedFunction2& feed)
380 // no shop; no coordinates; no useful stuff to do...
383 HideOutPtr ptr = boost::shared_dynamic_cast< HideOut >(shop);
386 // again, no coordinates...
389 FlowerShop result( new HideOut( ptr->m_section, ptr->m_key, 0, feed ) );
390 if (not config_data.empty())
392 if (config_data.hasKey(ptr->m_section, ptr->m_key))
395 config_data[ptr->m_section].getValues(ptr->m_key, values);
400 } // eo seymour(FlowerShop,const FeedFunction&)
403 } // eo namespace Detail
408 * @brief reloads the configuration from the last (known) config file.
409 * @return @a true if config was succesfully reloaded.
413 ConfigData old_config_data;
414 ConfigData new_config_data;
415 if (config_file_name.empty())
419 bool loaded= load_ini_config_file(config_file_name, new_config_data);
420 bool publish_successful= true;
423 module_logger().debug() << "new_config_data.empty(): " << new_config_data.empty();
425 old_config_data.swap( config_data );
426 // and install the new data
427 new_config_data.swap( config_data );
429 // react on the config: publish the values:
430 publish_successful = feedEm( old_config_data );
432 return loaded and publish_successful;
439 * @brief sets the path of the config file and loads it.
440 * @param path the path to the config file.
441 * @return @a true iff the config could be loaded and all values pushed into their config vars.
443 bool set_config_file(const std::string& path)
445 if (not config_file_name.empty())
448 // a new config file.. well... why not?
451 if (not stat or not stat.is_regular_file())
455 config_file_name= path;
457 } // eo set_config_file(const std::string&)
461 * @brief returns the current config file path.
462 * @return the current path.
464 std::string get_config_file()
466 return config_file_name;
467 } // eo get_config_file()
470 } // eo namespace config
472 } // eo namespace I2n