2 The software in this package is distributed under the GNU General
3 Public License version 2 (with a special exception described below).
5 A copy of GNU General Public License (GPL) is included in this distribution,
6 in the file COPYING.GPL.
8 As a special exception, if other files instantiate templates or use macros
9 or inline functions from this file, or you compile this file and link it
10 with other works to produce a work based on this file, this file
11 does not by itself cause the resulting work to be covered
12 by the GNU General Public License.
14 However the source code for this file must still be made available
15 in accordance with section (3) of the GNU General Public License.
17 This exception does not invalidate any other reasons why a work based
18 on this file might be covered by the GNU General Public License.
22 * @author Reinhard Pfau
24 * @copyright © Copyright 2008 by Intra2net AG
27 #include "i2n_global_config.hpp"
33 #include <filefunc.hxx>
34 #include <stringfunc.hxx>
35 #include <i2n_configdata.hpp>
36 #include <i2n_configfile.hpp>
37 #include <logfunc.hpp>
38 #include <tracefunc.hpp>
46 #define DOUT(msg) std::cout << msg << std::endl
48 #define DOUT(msg) do {} while (0)
63 } // eo namespace Detail
71 Logger::PartLogger& module_logger()
73 static Logger::PartLogger _logger(HERE);
75 } // eo module_logger()
79 std::string config_file_name;
81 ConfigData config_data;
90 : public Detail::Thing
93 const std::string& section,
94 const std::string& key,
95 const Detail::FeedFunction& feed,
96 const Detail::FeedFunction2& feed2);
100 Detail::FeedFunction m_feed;
101 Detail::FeedFunction2 m_feed2;
102 std::string m_section;
104 }; // eo struct HideOut
106 typedef boost::shared_ptr< HideOut > HideOutPtr;
110 : public GroupedKeyValueData<
118 virtual ~HideOutMap();
122 static int Instances;
123 }; // eo class HideOutMap
125 int HideOutMap::Instances= 0;
127 HideOutMap::HideOutMap()
129 DOUT("HideOutMap::HideOutMap()");
131 } // eo HideOutMap::HideOutMap()
134 HideOutMap::~HideOutMap()
136 DOUT("HideOutMap::~HideOutMap()");
138 } // eo HideOutMap::~HideOutMap()
141 HideOutMap& hideout_map()
143 static HideOutMap the_hideout_map;
144 DOUT("hideout_map()");
145 return the_hideout_map;
146 } // eo hideout_map()
149 // implementation of HideOut:
153 const std::string& section,
154 const std::string& key,
155 const Detail::FeedFunction& feed,
156 const Detail::FeedFunction2& feed2)
162 hideout_map()[section][key]+= this;
163 } // eo HideOut::HideOut(const FeedFunction&)
169 if (HideOutMap::Instances)
171 hideout_map()[m_section].removeValue(m_key,this);
173 } // eo HideOut::~HideOut()
183 * @brief distributes (new) values to the active config variables.
184 * @param old_config_data reference to the old config data (for determining the deltas).
185 * @return @a true if new values could be converted without an error.
187 bool feedEm( ConfigData& old_config_data )
191 HideOutMap::KeyListType section_list;
192 hideout_map().getKeys(section_list);
193 for(HideOutMap::KeyListType::const_iterator section_it = section_list.begin();
194 section_it != section_list.end();
197 std::string section( *section_it );
198 DOUT("process section \"" << section << "\"");
199 HideOutMap::GroupDataType::KeyListType key_list;
200 hideout_map()[section].getKeys(key_list);
201 for(HideOutMap::GroupDataType::KeyListType::const_iterator key_it= key_list.begin();
202 key_it != key_list.end();
205 std::string key( *key_it );
206 DOUT("process key \"" << key << "\"");
207 bool has_new_data= config_data.hasKey(section, key);
208 bool has_old_data= old_config_data.hasKey(section, key);
209 if (not has_new_data and not has_old_data)
211 // we don't have data and we didn't had data... well, nothing to do:
217 DOUT("has (new) data");
219 config_data[section].getValues(key, values);
220 std::string value( config_data[section][key] );
223 StringList old_values;
224 old_config_data[section].getValues(key, old_values);
225 if (values == old_values)
227 // value didn't change, so we can skip this case.
228 DOUT("data is same as before");
232 // at this point we need to publish (new or changed) value:
233 HideOutMap::GroupDataType::ValueListType func_list;
234 hideout_map()[section].getValues(key, func_list);
235 for(HideOutMap::GroupDataType::ValueListType::iterator func_it= func_list.begin();
236 func_it != func_list.end();
239 DOUT(" feed iteration");
240 if (not (*func_it)) //paranoia
244 if ( (*func_it)->m_feed)
246 if ( not (*func_it)->m_feed( value ) )
248 module_logger().error() << "unable to publish [" <<section << "]"
249 << " \"" << key << "\" : \"" << value << "\""
255 if ( (*func_it)->m_feed2)
257 if ( not (*func_it)->m_feed2( values ) )
259 module_logger().error() << "unable to publish [" <<section << "]"
260 << " \"" << key << "\" : ...\"" << value << "\""
266 module_logger().error() << "no feeder";
270 // at this point we don't have (new) data, but we had old data...
272 DOUT("had old data");
275 // at this point we need to publish (vanished) value:
276 HideOutMap::GroupDataType::ValueListType func_list;
277 hideout_map()[section].getValues(key, func_list);
278 for(HideOutMap::GroupDataType::ValueListType::iterator func_it= func_list.begin();
279 func_it != func_list.end();
282 DOUT(" feed iteration");
283 if (not (*func_it)) //paranoia
287 if ( (*func_it)->m_feed)
289 //TODO reset the data (to initial value) somehow?
290 // for now; we just keep the last value...
293 if ( (*func_it)->m_feed2)
295 if ( not (*func_it)->m_feed2( values ) )
297 module_logger().error() << "unable to publish [" <<section << "]"
298 << " \"" << key << "\" : <empty> "
304 module_logger().error() << "no feeder";
311 } // eo feedEm(ConfigData&,ConfigData&)
319 } // eo namespace <anonymous>
322 /************************************************************************\
323 \************************************************************************/
331 const std::string& section,
332 const std::string& key,
333 const FeedFunction& feed)
335 DOUT("seymor(\"" << section << "\", \"" << key << "\",FeedFunction)");
336 FlowerShop result( new HideOut( section, key, feed, 0 ) );
337 if (not config_data.empty())
339 if (config_data.hasKey(section, key))
341 feed( config_data[section][key] );
345 } // eo seymour(const std::string&,const std::string&,const FeedFunction&)
349 const std::string& section,
350 const std::string& key,
351 const FeedFunction2& feed)
353 DOUT("seymor(\"" << section << "\", \"" << key << "\",FeedFunction2)");
354 FlowerShop result( new HideOut( section, key, 0, feed ) );
355 if (not config_data.empty())
357 if (config_data.hasKey(section, key))
360 config_data[section].getValues(key, values);
365 } // eo seymour(const std::string&,const std::string&,const FeedFunction2&)
368 FlowerShop seymour(FlowerShop shop, const FeedFunction& feed)
372 // no shop; no coordinates; no useful stuff to do...
375 HideOutPtr ptr = boost::dynamic_pointer_cast< HideOut >(shop);
378 // again, no coordinates...
381 FlowerShop result( new HideOut( ptr->m_section, ptr->m_key, feed, 0 ) );
382 if (not config_data.empty())
384 if (config_data.hasKey(ptr->m_section, ptr->m_key))
386 feed( config_data[ptr->m_section][ptr->m_key] );
390 } // eo seymour(FlowerShop,const FeedFunction&)
393 FlowerShop seymour(FlowerShop shop, const FeedFunction2& feed)
397 // no shop; no coordinates; no useful stuff to do...
400 HideOutPtr ptr = boost::dynamic_pointer_cast< HideOut >(shop);
403 // again, no coordinates...
406 FlowerShop result( new HideOut( ptr->m_section, ptr->m_key, 0, feed ) );
407 if (not config_data.empty())
409 if (config_data.hasKey(ptr->m_section, ptr->m_key))
412 config_data[ptr->m_section].getValues(ptr->m_key, values);
417 } // eo seymour(FlowerShop,const FeedFunction&)
420 } // eo namespace Detail
425 * @brief reloads the configuration from the last (known) config file.
426 * @return @a true if config was succesfully reloaded.
430 ConfigData old_config_data;
431 ConfigData new_config_data;
432 if (config_file_name.empty())
436 bool loaded= load_ini_config_file(config_file_name, new_config_data);
437 bool publish_successful= true;
440 module_logger().debug() << "new_config_data.empty(): " << new_config_data.empty();
442 old_config_data.swap( config_data );
443 // and install the new data
444 new_config_data.swap( config_data );
446 // react on the config: publish the values:
447 publish_successful = feedEm( old_config_data );
449 return loaded and publish_successful;
456 * @brief sets the path of the config file and loads it.
457 * @param path the path to the config file.
458 * @return @a true iff the config could be loaded and all values pushed into their config vars.
460 bool set_config_file(const std::string& path)
462 if (not config_file_name.empty())
465 // a new config file.. well... why not?
468 if (not stat or not stat.is_regular_file())
472 config_file_name= path;
474 } // eo set_config_file(const std::string&)
478 * @brief returns the current config file path.
479 * @return the current path.
481 std::string get_config_file()
483 return config_file_name;
484 } // eo get_config_file()
487 } // eo namespace config
489 } // eo namespace I2n