[asterisk-scf-commits] asterisk-scf/integration/logger.git branch "master" updated.

Commits to the Asterisk SCF project code repositories asterisk-scf-commits at lists.digium.com
Fri Sep 24 15:40:14 CDT 2010


branch "master" has been updated
       via  bc8098b6d7474d80bb183c02acd0af6b30202a61 (commit)
      from  2ced70031ce47fa1f4618107207b186cf0580b3a (commit)

Summary of changes:
 client/src/CMakeLists.txt            |    2 +
 client/src/IceConfigurator.cpp       |  124 ++++++++++++++++++++++++++++++++++
 client/src/IceConfigurator.h         |   45 ++++++++++++
 client/src/Logger.cpp                |   19 ++++-
 client/src/LoggerFactory.cpp         |   20 ++++++
 client/src/logger.h                  |   10 +++
 client/test/CMakeLists.txt           |    1 +
 client/test/IceConfigurator-test.cpp |   75 ++++++++++++++++++++
 ice/LoggerIf.ice                     |   10 ++--
 server/config/logging-server.conf    |    3 +
 server/src/CMakeLists.txt            |    2 +
 server/src/LoggingServer.cpp         |   23 +++++--
 server/src/LoggingServer.h           |    4 +-
 server/src/main.cpp                  |   52 ++++++++++++++-
 14 files changed, 373 insertions(+), 17 deletions(-)
 create mode 100644 client/src/IceConfigurator.cpp
 create mode 100644 client/src/IceConfigurator.h
 create mode 100644 client/test/IceConfigurator-test.cpp


- Log -----------------------------------------------------------------
commit bc8098b6d7474d80bb183c02acd0af6b30202a61
Author: David M. Lee <dlee at digium.com>
Date:   Fri Sep 24 15:37:46 2010 -0500

    Server config being pushed to clients.

diff --git a/client/src/CMakeLists.txt b/client/src/CMakeLists.txt
index 8115598..c97df57 100644
--- a/client/src/CMakeLists.txt
+++ b/client/src/CMakeLists.txt
@@ -13,9 +13,11 @@ include_directories(../../common)
 hydra_component_add_file(logging-client Logger.cpp)
 hydra_component_add_file(logging-client LoggerFactory.cpp)
 hydra_component_add_file(logging-client LogOut.cpp)
+hydra_component_add_file(logging-client IceConfigurator.cpp)
 hydra_component_add_file(logging-client IceLogger.cpp)
 hydra_component_add_file(logging-client OstreamLogger.cpp)
 hydra_component_add_file(logging-client logger.h)
+hydra_component_add_file(logging-client IceConfigurator.h)
 hydra_component_add_file(logging-client LogOut.h)
 
 hydra_component_add_slice(logging-client LoggerIf)
diff --git a/client/src/IceConfigurator.cpp b/client/src/IceConfigurator.cpp
new file mode 100644
index 0000000..50aff27
--- /dev/null
+++ b/client/src/IceConfigurator.cpp
@@ -0,0 +1,124 @@
+/*
+ * Asterisk Scalable Communications Framework
+ *
+ * Copyright (C) 2010 -- Digium, Inc.
+ *
+ * All rights reserved.
+ */
+
+#include <Ice/Ice.h>
+#include <IceStorm/IceStorm.h>
+
+#include "IceConfigurator.h"
+
+using namespace AsteriskSCF::System::Logging;
+
+namespace
+{
+/**
+ * For sorting SourceConfiguration's.
+ * @param lhs Left hand side.
+ * @param rhs Right hand side.
+ * @return True, if lhs < rhs.
+ */
+bool operator<(SourceConfiguration const &lhs, SourceConfiguration const &rhs)
+{
+   return lhs.name < rhs.name;
+}
+}
+
+void IceConfigurator::configured(Configuration const &logConfiguration,
+   Ice::Current const &)
+{
+   return configured(logConfiguration);
+}
+
+void IceConfigurator::configured(Configuration const &logConfiguration)
+{
+   std::vector<std::string> oldConfig = factory.getLoggerNames();
+   SourceConfigurationSeq newConfig = logConfiguration.sourceSettings;
+
+   // processing is easier if lists are sorted
+   std::sort(oldConfig.begin(), oldConfig.end());
+   std::sort(newConfig.begin(), newConfig.end());
+
+   SourceConfigurationSeq::const_iterator newConfigIter =
+      logConfiguration.sourceSettings.begin();
+   std::vector<std::string>::const_iterator oldConfigIter = oldConfig.begin();
+
+   while (newConfigIter != logConfiguration.sourceSettings.end()
+      || oldConfigIter != oldConfig.end())
+   {
+      int cmp;
+
+      if (newConfigIter == logConfiguration.sourceSettings.end())
+      {
+         // we ran out of new config; unset the rest of the old config
+         // new[end] < old
+         cmp = 1;
+      }
+      else if (oldConfigIter == oldConfig.end())
+      {
+         // we ran out of the old config; set rest of the new config
+         // new > old[end]
+         cmp = -1;
+      }
+      else
+      {
+         // compare the names
+         cmp = newConfigIter->name.compare(*oldConfigIter);
+      }
+
+      if (cmp < 0)
+      {
+         // apply a new config
+         factory.getLogger(newConfigIter->name).setLevel(
+            newConfigIter->logLevel);
+         ++newConfigIter;
+      }
+      else if (cmp == 0)
+      {
+         // change an old config
+         factory.getLogger(newConfigIter->name).setLevel(
+            newConfigIter->logLevel);
+         ++newConfigIter;
+         ++oldConfigIter;
+      }
+      else // if (cmp > 0)
+      {
+         factory.getLogger(*oldConfigIter).unsetLevel();
+         ++oldConfigIter;
+      }
+   }
+}
+
+IceConfiguratorPtr AsteriskSCF::System::Logging::createIceConfigurator(
+Ice::ObjectAdapterPtr adapter, LoggerFactory &factory)
+{
+Ice::CommunicatorPtr communicator = adapter->getCommunicator();
+
+try
+{
+   IceStorm::TopicManagerPrx topicManager =
+      IceStorm::TopicManagerPrx::checkedCast(communicator->propertyToProxy(
+         "TopicManager.Proxy"));
+
+   if (topicManager)
+   {
+      IceStorm::TopicPrx topic = topicManager->retrieve(
+         ServerConfigurationTopic);
+      IceConfiguratorPtr r = new IceConfigurator(factory);
+      Ice::ObjectPrx proxy = adapter->addWithUUID(r)->ice_oneway();
+      topic->subscribeAndGetPublisher(IceStorm::QoS(), proxy);
+      adapter->activate();
+      return r;
+   }
+}
+catch (std::exception const &e)
+{
+   std::clog << "Error registering with IceStorm: " << e.what() << '\n';
+}
+
+std::clog << "IceStorm not available.  Cannot listen to config events.\n";
+return IceConfiguratorPtr();
+}
diff --git a/client/src/IceConfigurator.h b/client/src/IceConfigurator.h
new file mode 100644
index 0000000..9b584a0
--- /dev/null
+++ b/client/src/IceConfigurator.h
@@ -0,0 +1,45 @@
+/*
+ * Asterisk Scalable Communications Framework
+ *
+ * Copyright (C) 2010 -- Digium, Inc.
+ *
+ * All rights reserved.
+ */
+
+#pragma once
+
+#include "logger.h"
+
+namespace AsteriskSCF
+{
+namespace System
+{
+namespace Logging
+{
+
+/**
+ * Listens for configuration events from the server, and updates the
+ * Logger appropriately.
+ */
+class IceConfigurator : public ServerConfigurationListener
+{
+public:
+   IceConfigurator(LoggerFactory &factory) :
+      factory(factory)
+   {
+   }
+
+   void configured(Configuration const &logConfiguration, Ice::Current const &);
+   void configured(Configuration const &logConfiguration);
+private:
+   LoggerFactory &factory;
+};
+
+typedef IceUtil::Handle<IceConfigurator> IceConfiguratorPtr;
+
+IceConfiguratorPtr createIceConfigurator(Ice::ObjectAdapterPtr adapter,
+   LoggerFactory &factory);
+
+} // Logging
+} // System
+} // AsteriskSCF
diff --git a/client/src/Logger.cpp b/client/src/Logger.cpp
index a058d7a..bbe2d6a 100644
--- a/client/src/Logger.cpp
+++ b/client/src/Logger.cpp
@@ -52,15 +52,14 @@ void LogBuf::sendBuffer()
    out.logs(name, logLevel, message);
 }
 
-
 Logger::Logger(std::string const &name, LogOut &out, Level logLevel) :
    parent(0), name(name), out(out), logLevel(logLevel), inheritedLevel(false)
 {
 }
 
 Logger::Logger(Logger const &parent, std::string const &name) :
-   parent(&parent), name(name), out(parent.out), logLevel(Off),
-         inheritedLevel(true)
+   parent(&parent), name(name), out(parent.out), logLevel(Off), inheritedLevel(
+      true)
 {
    // our name must begin w/ parent's name
    assert(name.find(parent.name) == 0);
@@ -139,8 +138,20 @@ Logger &Logger::getChild(std::string const &childName)
    if (child == 0)
    {
       std::string fullName = getName().empty() ? childName : getName() + "."
-            + childName;
+         + childName;
       child = new Logger(*this, fullName);
    }
    return *child;
 }
+
+std::vector<Logger const *> Logger::getChildren() const
+{
+   std::vector<Logger const *> r;
+   for (std::map<std::string, Logger *>::const_iterator i = children.begin(); i
+      != children.end(); ++i)
+   {
+      r.push_back(i->second);
+   }
+   return r;
+}
+
diff --git a/client/src/LoggerFactory.cpp b/client/src/LoggerFactory.cpp
index eb7ad36..9865f3c 100644
--- a/client/src/LoggerFactory.cpp
+++ b/client/src/LoggerFactory.cpp
@@ -66,3 +66,23 @@ Logger &LoggerFactory::getLogger(std::string const &name)
 
    return *logger;
 }
+
+std::vector<std::string> LoggerFactory::getLoggerNames() const
+{
+   std::vector<std::string> r;
+   accumulateLoggerNames(root, r);
+   return r;
+}
+
+void LoggerFactory::accumulateLoggerNames(Logger const &logger, std::vector<
+   std::string> &out)
+{
+   out.push_back(logger.getName());
+   // recurse through the children
+   std::vector<Logger const *> const &children = logger.getChildren();
+   for (std::vector<Logger const *>::const_iterator i = children.begin(); i
+      != children.end(); ++i)
+   {
+      accumulateLoggerNames(**i, out);
+   }
+}
diff --git a/client/src/logger.h b/client/src/logger.h
index 1fdac36..f790e3e 100644
--- a/client/src/logger.h
+++ b/client/src/logger.h
@@ -168,6 +168,7 @@ public:
    }
 
    Logger &getChild(std::string const &childName);
+   std::vector<Logger const *> getChildren() const;
 
    std::string const &getName() const
    {
@@ -242,15 +243,24 @@ public:
     *
     * @param name Name of the Logger to be retrieved.
     * @return Ref to the Logger.
+    * @thread-safe
     */
    Logger &getLogger(std::string const &name);
 
+   /**
+    * Returns a vector of the names of all currently configured Logger's.
+    * @return Vector of Logger names.
+    */
+   std::vector<std::string> getLoggerNames() const;
+
 private:
    /**
     * LogOut for new Logger's.
     */
    LogOut &out;
    Logger root;
+
+   static void accumulateLoggerNames(Logger const &logger, std::vector<std::string> &out);
 };
 
 std::auto_ptr<LogOut> buildOstreamLogger(std::ostream &out);
diff --git a/client/test/CMakeLists.txt b/client/test/CMakeLists.txt
index 4ea9102..b4c198b 100644
--- a/client/test/CMakeLists.txt
+++ b/client/test/CMakeLists.txt
@@ -14,6 +14,7 @@ include_directories(../../common)
 hydra_component_add_file(logging-client-test Logger-test.cpp)
 hydra_component_add_file(logging-client-test LoggerFactory-test.cpp)
 hydra_component_add_file(logging-client-test LogBuf-test.cpp)
+hydra_component_add_file(logging-client-test IceConfigurator-test.cpp)
 hydra_component_add_file(logging-client-test client-test.cpp)
 
 hydra_component_add_boost_libraries(logging-client-test unit_test_framework)
diff --git a/client/test/IceConfigurator-test.cpp b/client/test/IceConfigurator-test.cpp
new file mode 100644
index 0000000..d612959
--- /dev/null
+++ b/client/test/IceConfigurator-test.cpp
@@ -0,0 +1,75 @@
+/*
+ * Asterisk Scalable Communications Framework
+ *
+ * Copyright (C) 2010 -- Digium, Inc.
+ *
+ * All rights reserved.
+ */
+
+
+#include <boost/test/unit_test.hpp>
+
+#include "ExpectedLogOut.h"
+#include "IceConfigurator.h"
+
+using namespace AsteriskSCF::System::Logging;
+
+namespace
+{
+void addConfig(Configuration &cfg, std::string const &name, Level logLevel)
+{
+   SourceConfiguration sourceConfig = {};
+   sourceConfig.name = name;
+   sourceConfig.logLevel = logLevel;
+
+   cfg.sourceSettings.push_back(sourceConfig);
+}
+}
+
+BOOST_AUTO_TEST_SUITE(IceConfiguratorTest)
+
+BOOST_AUTO_TEST_CASE(test_simple)
+{
+   ExpectedLogOut out("");
+   LoggerFactory factory(out);
+   IceConfigurator uut(factory);
+
+   Configuration cfg;
+   addConfig(cfg, "", Error);
+   addConfig(cfg, "AsteriskSCF", Info);
+   addConfig(cfg, "AsteriskSCF.Core", Debug);
+   addConfig(cfg, "AsteriskSCF.Media", Off);
+
+   uut.configured(cfg);
+
+   BOOST_CHECK_EQUAL(Error, factory.getLogger("").getEffectiveLevel());
+   BOOST_CHECK_EQUAL(Info, factory.getLogger("AsteriskSCF").getEffectiveLevel());
+   BOOST_CHECK_EQUAL(Debug, factory.getLogger("AsteriskSCF.Core").getEffectiveLevel());
+   BOOST_CHECK_EQUAL(Off, factory.getLogger("AsteriskSCF.Media").getEffectiveLevel());
+}
+
+
+BOOST_AUTO_TEST_CASE(test_reset)
+{
+   ExpectedLogOut out("");
+   LoggerFactory factory(out);
+   IceConfigurator uut(factory);
+
+   Configuration cfg;
+   addConfig(cfg, "", Error);
+   addConfig(cfg, "AsteriskSCF", Info);
+   addConfig(cfg, "AsteriskSCF.Core", Debug);
+   addConfig(cfg, "AsteriskSCF.Media", Off);
+   uut.configured(cfg);
+
+   cfg.sourceSettings.clear();
+   addConfig(cfg, "", Critical);
+   uut.configured(cfg);
+
+   BOOST_CHECK_EQUAL(Critical, factory.getLogger("").getEffectiveLevel());
+   BOOST_CHECK_EQUAL(Critical, factory.getLogger("AsteriskSCF").getEffectiveLevel());
+   BOOST_CHECK_EQUAL(Critical, factory.getLogger("AsteriskSCF.Core").getEffectiveLevel());
+   BOOST_CHECK_EQUAL(Critical, factory.getLogger("AsteriskSCF.Media").getEffectiveLevel());
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/ice/LoggerIf.ice b/ice/LoggerIf.ice
index 939adf1..2e38815 100644
--- a/ice/LoggerIf.ice
+++ b/ice/LoggerIf.ice
@@ -24,6 +24,10 @@ const string LoggingServerCategory = "LoggingServer";
  * ServiceLocator.
  */
 const string LoggingServerGuid = "LoggingServer";
+/**
+ * Topic name for configuration updates.
+ */
+const string ServerConfigurationTopic = "AsteriskSCF.System.Logging.config";
 
 /**
  * Warning levels, inspired by syslog.
@@ -96,17 +100,13 @@ interface LoggingServer
    idempotent Configuration getConfiguration();
 };
 
-/**
- * Topic name for configuration updates.
- */
-const string ServerConfigurationTopic = "AsteriskSCF.System.Logging.config";
 
 /**
  * Topic interface for notification of Configuration changes.
  */
 interface ServerConfigurationListener
 {
-   void configured(LoggingServer *server, Configuration logConfiguration);
+   void configured(Configuration logConfiguration);
 };
 
 }; // Logging
diff --git a/server/config/logging-server.conf b/server/config/logging-server.conf
index faf6ba4..a601ad9 100644
--- a/server/config/logging-server.conf
+++ b/server/config/logging-server.conf
@@ -6,6 +6,9 @@ AsteriskSCF.LoggingService.Endpoints=default
 # A proxy to the service locator management service
 ServiceLocatorManagement.Proxy=LocatorServiceManagement:tcp -p 4422
 
+# A proxy to the IceStorm topic manager
+TopicManager.Proxy=HydraIceStorm/TopicManager:default -p 10000
+
 # Log levels
 AsteriskSCF.Logging.logger=Error
 AsteriskSCF.Logging.logger.AsteriskSCF=Info
\ No newline at end of file
diff --git a/server/src/CMakeLists.txt b/server/src/CMakeLists.txt
index 3df642d..fb49ccb 100644
--- a/server/src/CMakeLists.txt
+++ b/server/src/CMakeLists.txt
@@ -16,6 +16,8 @@ hydra_component_add_slice(logging-service ServiceLocatorIf)
 hydra_component_add_file(logging-service LoggingServer.cpp)
 hydra_component_add_file(logging-service main.cpp)
 
+hydra_add_ice_libraries(IceStorm)
+
 hydra_component_build_standalone(logging-service)
 
 hydra_component_install(logging-service RUNTIME bin "Logging Service" System)
diff --git a/server/src/LoggingServer.cpp b/server/src/LoggingServer.cpp
index f8392c4..f3c72d1 100644
--- a/server/src/LoggingServer.cpp
+++ b/server/src/LoggingServer.cpp
@@ -69,9 +69,17 @@ Level LoggingServerI::getEffectiveLevel(std::string const &name) const
 
 void LoggingServerI::setLevel(std::string const &name, Level level)
 {
-   // thread safety
-   IceUtil::Mutex::Lock sourcesLock(sourcesMutex);
-   sources[name].setLevel(level);
+   {
+      // thread safety.  getConfiguration needs the lock, so we need to release
+      // it prior to that call.
+      IceUtil::Mutex::Lock sourcesLock(sourcesMutex);
+      sources[name].setLevel(level);
+   }
+
+   if (configurationListener)
+   {
+      configurationListener->configured(getConfiguration());
+   }
 }
 
 void LoggingServerI::logs(std::string const &name, Level level,
@@ -95,7 +103,8 @@ Configuration LoggingServerI::getConfiguration() const
    for (Sources::const_reverse_iterator i = sources.rbegin(); i
       != sources.rend(); ++i)
    {
-      SourceConfiguration v = {};
+      SourceConfiguration v =
+      { };
       v.name = i->first;
       v.logLevel = i->second.getLevel();
       r.sourceSettings.push_back(v);
@@ -149,8 +158,12 @@ bool LoggingServerI::isSubpathOf(std::string const &path,
 
 // <prefix>.logger=level
 // <prefix>.logger.<name>=level
-void LoggingServerI::configure(Ice::PropertiesPtr props)
+void LoggingServerI::configure(
+   ServerConfigurationListenerPrx configurationListener,
+   Ice::PropertiesPtr props)
 {
+   this->configurationListener = configurationListener;
+
    Ice::PropertyDict myProps = props->getPropertiesForPrefix(
       LoggingPropertyPrefix);
 
diff --git a/server/src/LoggingServer.h b/server/src/LoggingServer.h
index c7427e9..1c2505f 100644
--- a/server/src/LoggingServer.h
+++ b/server/src/LoggingServer.h
@@ -67,7 +67,7 @@ public:
    Level getEffectiveLevel(std::string const &name) const;
    void setLevel(std::string const &name, Level level);
 
-   void configure(Ice::PropertiesPtr props);
+   void configure(ServerConfigurationListenerPrx configurationListener, Ice::PropertiesPtr props);
 
    static const std::string LoggingPropertyPrefix;
 
@@ -93,6 +93,8 @@ private:
    IceUtil::Mutex sourcesMutex;
    IceUtil::Mutex outputMutex;
    Sources sources;
+
+   ServerConfigurationListenerPrx configurationListener;
 };
 
 } // Logging
diff --git a/server/src/main.cpp b/server/src/main.cpp
index 0b1f494..9abb626 100644
--- a/server/src/main.cpp
+++ b/server/src/main.cpp
@@ -8,6 +8,7 @@
 
 #include <Ice/Properties.h>
 #include <Ice/Service.h>
+#include <IceStorm/IceStorm.h>
 
 #include "Core/Discovery/ServiceLocatorIf.h"
 
@@ -51,7 +52,8 @@ void LoggingServerDaemon::registerWithServiceLocator(
                communicator()->stringToProxy(locatorManagementProxyString));
          serviceManagement = management->addService(serverProxy,
             LoggingServerGuid);
-         ServiceLocatorParamsPtr params = new ServiceLocatorParams(LoggingServerCategory);
+         ServiceLocatorParamsPtr params = new ServiceLocatorParams(
+            LoggingServerCategory);
          serviceManagement->addLocatorParams(params, "");
       }
    }
@@ -84,8 +86,54 @@ bool LoggingServerDaemon::start(int argc, char *argv[], int &status)
 
    adapter = communicator()->createObjectAdapter(AdapterName);
 
+   ServerConfigurationListenerPrx configurationListener;
+
+   try
+   {
+      IceStorm::TopicManagerPrx topicManager =
+         IceStorm::TopicManagerPrx::checkedCast(
+            communicator()->propertyToProxy("TopicManager.Proxy"));
+
+      if (topicManager)
+      {
+         IceStorm::TopicPrx topic;
+         while (!topic)
+         {
+            try
+            {
+               topic = topicManager->retrieve(ServerConfigurationTopic);
+            }
+            catch (IceStorm::NoSuchTopic const &e)
+            {
+               try
+               {
+                  topic = topicManager->create(ServerConfigurationTopic);
+               }
+               catch (IceStorm::TopicExists const &e)
+               {
+                  // we had a race to create the object w/ someone else
+                  // and lost
+               }
+            }
+         }
+         configurationListener = ServerConfigurationListenerPrx::uncheckedCast(
+            topic->getPublisher()->ice_oneway());
+      }
+      else
+      {
+         std::clog
+            << "IceStorm unavailable.  Cannot send configuration updates.\n";
+      }
+   }
+   catch (std::exception const &e)
+   {
+      std::clog << "Failed to contact ServiceLocator: ";
+      std::clog << e.what() << '\n';
+   }
+
    IceUtil::Handle<LoggingServerI> server = new LoggingServerI;
-   server->configure(communicator()->getProperties());
+   server->configure(ServerConfigurationListenerPrx(),
+      communicator()->getProperties());
 
    LoggingServerPrx serverProxy = LoggingServerPrx::uncheckedCast(
       adapter->addWithUUID(server));

-----------------------------------------------------------------------


-- 
asterisk-scf/integration/logger.git



More information about the asterisk-scf-commits mailing list