From eb209c165d705753a2b4698af874e08b20c87497 Mon Sep 17 00:00:00 2001 From: "Zhu, Yongsheng" Date: Tue, 22 Sep 2009 14:46:35 +0800 Subject: [PATCH] syncevo-dbus-server: implement getConfig/setConfig 1) Implement these 2 APIs according to dbus api description 2) Add test for GetConfig/SetConfig --- src/syncevo-dbus-server.cpp | 135 +++++++++++++++++++++++++++++++-- src/syncevo/FileConfigNode.cpp | 1 + test/dbus-server-config.py | 93 +++++++++++++++++++++++ 3 files changed, 222 insertions(+), 7 deletions(-) create mode 100755 test/dbus-server-config.py diff --git a/src/syncevo-dbus-server.cpp b/src/syncevo-dbus-server.cpp index 04a45a92..8b8a1bb6 100644 --- a/src/syncevo-dbus-server.cpp +++ b/src/syncevo-dbus-server.cpp @@ -27,6 +27,7 @@ #include #include #include +#include #include #include @@ -476,7 +477,7 @@ class Session : public DBusObjectHelper, void detach(const Caller_t &caller); - void setConfig(bool update, bool clear, bool temporary, + void setConfig(bool update, bool temporary, const ReadOperations::Config_t &config); void getStatus(std::string &status, @@ -725,8 +726,57 @@ ReadOperations::ReadOperations(const std::string &config_name) : void ReadOperations::getConfig(bool getTemplate, Config_t &config) { - // TODO - throw std::runtime_error("not implemented"); + if(m_configName.empty()) { + throw std::runtime_error("Template name must be given"); + } + map localConfigs; + boost::shared_ptr syncConfig; + /** get server template */ + if(getTemplate) { + syncConfig = SyncConfig::createServerTemplate(m_configName); + if(!syncConfig.get()) { + throw std::runtime_error("No template '" + m_configName + "' found"); + } + } else { ///< get a matching server configuration + boost::shared_ptr from; + syncConfig.reset(new SyncConfig(m_configName)); + /* if config does not exist, create from template */ + if (!syncConfig->exists()) { + from = SyncConfig::createServerTemplate(m_configName); + if(!from.get()) { + throw runtime_error("No server or template '" + m_configName + "' found"); + } + syncConfig->copy(*from, NULL); + } + } + + /** get sync properties and their values */ + ConfigPropertyRegistry &syncRegistry = SyncConfig::getRegistry(); + BOOST_FOREACH(const ConfigProperty *prop, syncRegistry) { + bool isDefault = false; + string value = prop->getProperty(syncConfig->getConfigNode(), &isDefault); + if(!isDefault) { + localConfigs.insert(pair(prop->getName(), value)); + } + } + + config.insert(pair >("", localConfigs)); + + /* get configurations from sources */ + list sources = syncConfig->getSyncSources(); + BOOST_FOREACH(const string &name, sources) { + localConfigs.clear(); + SyncSourceNodes sourceNodes = syncConfig->getSyncSourceNodes(name); + ConfigPropertyRegistry &sourceRegistry = SyncSourceConfig::getRegistry(); + BOOST_FOREACH(const ConfigProperty *prop, sourceRegistry) { + bool isDefault = false; + string value = prop->getProperty(*sourceNodes.m_configNode, &isDefault); + if(!isDefault) { + localConfigs.insert(pair(prop->getName(), value)); + } + } + config.insert(pair >( "source/" + name, localConfigs)); + } } void ReadOperations::getReports(uint32_t start, uint32_t count, @@ -788,7 +838,28 @@ void Session::detach(const Caller_t &caller) client->detach(this); } -void Session::setConfig(bool update, bool clear, bool temporary, +static void setSyncFilters(const ReadOperations::Config_t &config,FilterConfigNode::ConfigFilter &syncFilter,std::map &sourceFilters) +{ + ReadOperations::Config_t::const_iterator it; + for (it = config.begin(); it != config.end(); it++) { + map::const_iterator sit; + if(it->first.empty()) { + for (sit = it->second.begin(); sit != it->second.end(); sit++) { + syncFilter.insert(*sit); + } + } else { + string name = it->first; + if(name.find("source/") == 0) { + name = name.substr(7); ///> 7 is the length of "source/" + FilterConfigNode::ConfigFilter &sourceFilter = sourceFilters[name]; + for (sit = it->second.begin(); sit != it->second.end(); sit++) { + sourceFilter.insert(*sit); + } + } + } + } +} +void Session::setConfig(bool update, bool temporary, const ReadOperations::Config_t &config) { if (!m_active) { @@ -797,8 +868,58 @@ void Session::setConfig(bool update, bool clear, bool temporary, if (m_sync) { throw std::runtime_error("sync started, cannot change configuration at this time"); } - // TODO - throw std::runtime_error("not implemented yet"); + if(m_configName.empty()) { + throw std::runtime_error("Template name must be given"); + } + if (!update && temporary) { + throw std::runtime_error("Clearing existing configuration and temporary configuration changes which only affects the duration of the session are mutually exclusive"); + } + + /** check whether we need remove the entire configuration */ + if(!update) { + boost::shared_ptr syncConfig(new SyncConfig(m_configName)); + if(syncConfig.get()) { + syncConfig->remove(); + } + if(config.empty()) { + return; + } + } + if(temporary) { + setSyncFilters(config, m_syncFilter, m_sourceFilters); + } else { + FilterConfigNode::ConfigFilter syncFilter; + std::map sourceFilters; + setSyncFilters(config, syncFilter, sourceFilters); + /* need to save configurations */ + boost::shared_ptr from(new SyncConfig(m_configName)); + /* if it is clear mode and config does not exist, create from template */ + if(update && !from->exists()) { + from = SyncConfig::createServerTemplate(m_configName); + if (!from.get()) { + from = SyncConfig::createServerTemplate(string("default")); + } + } + /** generate new sources in the config map */ + for (ReadOperations::Config_t::const_iterator it = config.begin(); it != config.end(); ++it) { + string sourceName = it->first; + if(sourceName.find("source/") == 0) { + sourceName = sourceName.substr(7); ///> 7 is the length of "source/" + from->getSyncSourceNodes(sourceName); + } + } + /* apply user settings */ + from->setConfigFilter(true, "", syncFilter); + map::iterator it; + for ( it = sourceFilters.begin(); it != sourceFilters.end(); it++ ) { + from->setConfigFilter(false, it->first, it->second); + } + boost::shared_ptr syncConfig(new DBusSync(m_configName, *this)); + syncConfig->copy(*from, NULL); + + syncConfig->preFlush(*syncConfig); + syncConfig->flush(); + } } void Session::initServer(SharedBuffer data, const std::string &messageType) @@ -969,7 +1090,7 @@ void Session::activate() typeof(&ReadOperations::getConfig), &ReadOperations::getConfig> ("GetConfig"), makeMethodEntry ("SetConfig"), diff --git a/src/syncevo/FileConfigNode.cpp b/src/syncevo/FileConfigNode.cpp index fa6ac646..59431895 100644 --- a/src/syncevo/FileConfigNode.cpp +++ b/src/syncevo/FileConfigNode.cpp @@ -418,6 +418,7 @@ void HashFileConfigNode::setProperty(const string &property, /** we don't support property comments here. Also, we ignore comment*/ if (defValue && *defValue == newvalue) { + removeProperty(property); return; } map::iterator it = m_props.find(property); diff --git a/test/dbus-server-config.py b/test/dbus-server-config.py new file mode 100755 index 00000000..3c539a76 --- /dev/null +++ b/test/dbus-server-config.py @@ -0,0 +1,93 @@ +#! /usr/bin/python + +'''Get config/reports and set config. +Usage: dbus-server-sync [--getconfig | --config | --reports] [config options] + - configuration name +''' + +import dbus +from dbus.mainloop.glib import DBusGMainLoop +import gobject +import sys + +DBusGMainLoop(set_as_default=True) + +bus = dbus.SessionBus() + +object = dbus.Interface(bus.get_object('org.syncevolution', + '/org/syncevolution/Server'), + 'org.syncevolution.Server') + +loop = gobject.MainLoop() + +sessionpath = None +def SessionChanged(object, ready): + print "SessionChanged:", object, ready + if sessionpath == object: + loop.quit() + +bus.add_signal_receiver(SessionChanged, + 'SessionChanged', + 'org.syncevolution.Server', + 'org.syncevolution', + None, + byte_arrays=True) + +dummysessionpath = object.StartSession("") +sessionpath = object.StartSession(sys.argv[1]) + +# detach from dummy session so that real session can run +session = dbus.Interface(bus.get_object('org.syncevolution', + dummysessionpath), + 'org.syncevolution.Session') +session.Detach() +session = dbus.Interface(bus.get_object('org.syncevolution', + sessionpath), + 'org.syncevolution.Session') +if sys.argv[2] == "--getconfig": + print 'Get Config:' + dict = session.GetConfig(0) + for name, value in dict.items(): + print 'name: [', name, ']' + for config, confvalue in value.items(): + print '\t', config, ' = ', confvalue +elif sys.argv[2] == "--config": + print 'Set Config:' + i = 3; + length = len(sys.argv) + dict = {} + update = 1 + temporary = 0 + while i < length: + if sys.argv[i] == "--clear": + update = 0 + i = i + 1 + continue + elif sys.argv[i] == "--temp": + temporary = 1 + i = i + 1 + continue + elif sys.argv[i].startswith('-z'): + l1 = sys.argv[i].split('=') + if len(l1) == 2: + name = 'source/' + l1[1] + elif sys.argv[i].startswith('-y'): + name = '' + + l2 = sys.argv[i+1].split('=') + idict = {} + if dict.has_key(name): + idict = dict[name] + idict[l2[0]] = l2[1] + else: + idict[l2[0]] = l2[1] + dict[name] = idict + i = i+2 + + print dict + session.SetConfig(update, temporary, dict) + session.Sync("", {}) +elif sys.argv[2] == "--reports": + dict = session.GetReports(0, 10) + print '' +