Browse Source

[3793] StatContext implemented.

Tomek Mrugalski 10 years ago
parent
commit
2a599377ea
3 changed files with 183 additions and 3 deletions
  1. 52 0
      src/lib/stats/context.cc
  2. 52 3
      src/lib/stats/context.h
  3. 79 0
      src/lib/stats/tests/context_unittest.cc

+ 52 - 0
src/lib/stats/context.cc

@@ -0,0 +1,52 @@
+// Copyright (C) 2015 Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+// PERFORMANCE OF THIS SOFTWARE.
+
+#include <stats/context.h>
+#include <map>
+
+namespace isc {
+namespace stats {
+
+ObservationPtr StatContext::get(const std::string& name) {
+    std::map<std::string, ObservationPtr>::iterator obs = stats_.find(name);
+    if (obs == stats_.end()) {
+        return (ObservationPtr());
+    } else {
+        return (obs->second);
+    }
+}
+
+void StatContext::add(const ObservationPtr& obs) {
+    std::map<std::string, ObservationPtr>::iterator obs = stats_.find(name);
+    if (obs == stats_.end()) {
+        stats_.insert(make_pair(obs->getName() ,obs));
+    } else {
+        isc_throw(InvalidStatType, "Statistic named " << obs->getName()
+                  << " already exists.");
+    }
+
+}
+
+bool StatContext::del(const std::string& name) {
+    std::map<std::string, ObservationPtr>::iterator obs = stats_.find(name);
+    if (obs == stats_.end()) {
+        return (false);
+    } else {
+        stats_.erase(obs);
+        return (true);
+    }
+}
+
+};
+};

+ 52 - 3
src/lib/stats/context.h

@@ -1,20 +1,69 @@
-
+// Copyright (C) 2015 Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+// PERFORMANCE OF THIS SOFTWARE.
 
 #ifndef CONTEXT_H
 #define CONTEXT_H
 
 #include <stats/observation.h>
 #include <boost/shared_ptr.hpp>
+#include <string>
 
 namespace isc {
 namespace stats {
 
+/// @brief Exception indicating that a given statistic is duplicated.
+class DuplicateStat : public Exception {
+public:
+    DuplicateStat(const char* file, size_t line, const char* what) :
+        isc::Exception(file, line, what) {}
+};
+
+/// @brief Statistics context
+///
+/// Statistics context is essentially a container used to group statistics
+/// related to a given context together. Two examples of such contexts are
+/// all statistics related to a given subnet or all statistics related to a
+/// given network interface.
 class StatContext {
  public:
-    std::map<std::string, ObservationPtr> stats;
+
+    /// @brief attempts to get an observation
+    /// @param name name of the statistic
+    /// @return appropriate Observation object (or NULL)
+    ObservationPtr get(const std::string& name);
+
+    /// @brief Adds a new observation
+    /// @param obs observation to be added
+    /// @throw DuplicateStat if an observation with the same name exists already
+    void add(const ObservationPtr& obs);
+
+    /// @brief Attempts to delete an observation
+    /// @param name name of the observation to be deleted
+    /// @return true if successful, false if no such statistic was found
+    bool del(const std::string& name);
+
+    /// @brief Statistics container
+    ///
+    /// It is public to allow various operations that require iterating over
+    /// all elements. In particular, two operations (setting all stats to 0;
+    /// reporting all stats) will take advantage of this. Alternatively, we
+    /// could make it protected and then return a pointer to it, but that
+    /// would defeat the purpose of the hermetization in the first place.
+    std::map<std::string, ObservationPtr> stats_;
 };
 
- typedef boost::shared_ptr<StatContext> StatContextPtr;
+typedef boost::shared_ptr<StatContext> StatContextPtr;
 
 };
 };

+ 79 - 0
src/lib/stats/tests/context_unittest.cc

@@ -0,0 +1,79 @@
+// Copyright (C) 2015 Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+// PERFORMANCE OF THIS SOFTWARE.
+
+#include <config.h>
+
+#include <stats/context.h>
+#include <gtest/gtest.h>
+
+using namespace isc::stats;
+
+// Basic test that checks get, add, del methods
+TEST(ContextTest, basic) {
+
+    // Let's create a couple observations. Using floating point,
+    // as they're easiest to initialize.
+    ObservationPtr a(new Observation("alpha", 1.11));
+    ObservationPtr b(new Observation("beta", 2.22));
+    ObservationPtr c(new Observation("gamma", 3.33));
+
+    // Context where we will store the observations.
+    StatContext ctx;
+
+    // By default the context does not hold any statistics.
+    EXPECT_EQ(0, ctx.stats_.size());
+    EXPECT_TRUE(ctx.stats_.empty());
+
+    // It should be possible to add 'a' statistic
+    EXPECT_NO_THROW(ctx.add(a));
+
+    // We can't add a duplicate.
+    EXPECT_THROW(ctx.add(a), DuplicateStat);
+
+    // It should be ok to add other statistics
+    EXPECT_NO_THROW(ctx.add(b));
+    EXPECT_NO_THROW(ctx.add(c));
+
+    // By now we should have 3 statistics recorded
+    EXPECT_EQ(3, ctx.stats_.size());
+    EXPECT_FALSE(ctx.stats_.empty());
+
+    // Let's try to retrieve them
+    ObservationPtr from_ctx;
+    EXPECT_NO_THROW(from_ctx = ctx.get("alpha"));
+    ASSERT_TRUE(from_ctx);
+    EXPECT_EQ(a->getJSON()->str(), from_ctx->getJSON()->str());
+
+    EXPECT_NO_THROW(from_ctx = ctx.get("beta"));
+    ASSERT_TRUE(from_ctx);
+    EXPECT_EQ(b->getJSON()->str(), from_ctx->getJSON()->str());
+
+    EXPECT_NO_THROW(from_ctx = ctx.get("gamma"));
+    ASSERT_TRUE(from_ctx);
+    EXPECT_EQ(c->getJSON()->str(), from_ctx->getJSON()->str());
+
+    // Let's try to retrieve non-existing stat
+    EXPECT_NO_THROW(from_ctx = ctx.get("delta"));
+    EXPECT_FALSE(from_ctx);
+
+    // Now delete one of the stats...
+    EXPECT_TRUE(ctx.del("beta"));
+
+    // ... and check that it's really gone.
+    EXPECT_FALSE(ctx.get("beta"));
+
+    // Attempt to delete non-existing stat should fail.
+    EXPECT_FALSE(ctx.del("beta"));
+}
+