You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mesos.apache.org by be...@apache.org on 2012/11/26 22:16:55 UTC

svn commit: r1413850 - in /incubator/mesos/trunk: src/linux/proc.cpp src/linux/proc.hpp src/tests/proc_tests.cpp third_party/libprocess/include/stout/stringify.hpp third_party/libprocess/include/stout/strings.hpp

Author: benh
Date: Mon Nov 26 21:16:53 2012
New Revision: 1413850

URL: http://svn.apache.org/viewvc?rev=1413850&view=rev
Log:
Added a proc::cpus function for getting back information about the
CPUs on a machine.

Review: https://reviews.apache.org/r/8059

Modified:
    incubator/mesos/trunk/src/linux/proc.cpp
    incubator/mesos/trunk/src/linux/proc.hpp
    incubator/mesos/trunk/src/tests/proc_tests.cpp
    incubator/mesos/trunk/third_party/libprocess/include/stout/stringify.hpp
    incubator/mesos/trunk/third_party/libprocess/include/stout/strings.hpp

Modified: incubator/mesos/trunk/src/linux/proc.cpp
URL: http://svn.apache.org/viewvc/incubator/mesos/trunk/src/linux/proc.cpp?rev=1413850&r1=1413849&r2=1413850&view=diff
==============================================================================
--- incubator/mesos/trunk/src/linux/proc.cpp (original)
+++ incubator/mesos/trunk/src/linux/proc.cpp Mon Nov 26 21:16:53 2012
@@ -1,18 +1,25 @@
 #include <sys/types.h> // For pid_t.
 
 #include <fstream>
+#include <list>
 #include <set>
 #include <string>
+#include <vector>
 
+#include <stout/foreach.hpp>
 #include <stout/numify.hpp>
+#include <stout/option.hpp>
 #include <stout/os.hpp>
+#include <stout/strings.hpp>
 #include <stout/try.hpp>
 
 #include "linux/proc.hpp"
 
 using std::ifstream;
+using std::list;
 using std::set;
 using std::string;
+using std::vector;
 
 namespace mesos {
 namespace internal {
@@ -39,6 +46,73 @@ Try<set<pid_t> > pids()
 }
 
 
+Try<list<CPU> > cpus()
+{
+  list<CPU> results;
+
+  ifstream file("/proc/cpuinfo");
+
+  if (!file.is_open()) {
+    return Try<list<CPU> >::error("Failed to open /proc/cpuinfo");
+  }
+
+  // Placeholders as we parse the file.
+  Option<unsigned int> id;
+  Option<unsigned int> core;
+  Option<unsigned int> socket;
+
+  string line;
+  while (getline(file, line)) {
+    if (line.find("processor") == 0 ||
+        line.find("physical id") == 0 ||
+        line.find("core id") == 0) {
+      // Get out and parse the value.
+      vector<string> tokens = strings::tokenize(line, ": ");
+      CHECK(tokens.size() >= 2) << stringify(tokens);
+      Try<unsigned int> value = numify<unsigned int>(tokens.back());
+      if (value.isError()) {
+        return Try<list<CPU> >::error(value.error());
+      }
+
+      // Now save the value.
+      if (line.find("processor") == 0) {
+        if (id.isSome()) {
+          return Try<list<CPU> >::error("Unexpected format of /proc/cpuinfo");
+        }
+        id = value.get();
+      } else if (line.find("physical id") == 0) {
+        if (socket.isSome()) {
+          return Try<list<CPU> >::error("Unexpected format of /proc/cpuinfo");
+        }
+        socket = value.get();
+      } else if (line.find("core id") == 0) {
+        if (core.isSome()) {
+          return Try<list<CPU> >::error("Unexpected format of /proc/cpuinfo");
+        }
+        core = value.get();
+      }
+
+      // And finally create a CPU if we have enough information.
+      if (id.isSome() && core.isSome() && socket.isSome()) {
+        results.push_back(CPU(id.get(), core.get(), socket.get()));
+        id = Option<unsigned int>::none();
+        core = Option<unsigned int>::none();
+        socket = Option<unsigned int>::none();
+      }
+    }
+  }
+
+  if (file.fail() && !file.eof()) {
+    file.close();
+    return Try<list<CPU> >::error("Failed to read /proc/cpuinfo");
+  }
+
+  file.close();
+
+  return results;
+}
+
+
 Try<SystemStatistics> stat()
 {
   unsigned long long btime = 0;
@@ -49,23 +123,26 @@ Try<SystemStatistics> stat()
     return Try<SystemStatistics>::error("Failed to open /proc/stat");
   }
 
-  while (!file.eof()) {
-    string line;
-    getline(file, line);
-    if (file.fail() && !file.eof()) {
-      file.close();
-      return Try<SystemStatistics>::error("Failed to read /proc/stat");
-    } else if (line.find("btime ") == 0) {
+  string line;
+  while (getline(file, line)) {
+    if (line.find("btime ") == 0) {
       Try<unsigned long long> number =
         numify<unsigned long long>(line.substr(6));
       if (number.isSome()) {
         btime = number.get();
       } else {
-        return Try<SystemStatistics>::error(number.error());
+        return Try<SystemStatistics>::error(
+            "Failed to parse /proc/stat: " + number.error());
       }
+      break;
     }
   }
 
+  if (file.fail() && !file.eof()) {
+    file.close();
+    return Try<SystemStatistics>::error("Failed to read /proc/stat");
+  }
+
   file.close();
 
   return SystemStatistics(btime);

Modified: incubator/mesos/trunk/src/linux/proc.hpp
URL: http://svn.apache.org/viewvc/incubator/mesos/trunk/src/linux/proc.hpp?rev=1413850&r1=1413849&r2=1413850&view=diff
==============================================================================
--- incubator/mesos/trunk/src/linux/proc.hpp (original)
+++ incubator/mesos/trunk/src/linux/proc.hpp Mon Nov 26 21:16:53 2012
@@ -21,6 +21,7 @@
 
 #include <sys/types.h> // For pid_t.
 
+#include <list>
 #include <set>
 #include <string>
 
@@ -31,6 +32,7 @@ namespace internal {
 namespace proc {
 
 // Forward declarations.
+struct CPU;
 struct SystemStatistics;
 struct ProcessStatistics;
 
@@ -38,6 +40,9 @@ struct ProcessStatistics;
 // Reads from /proc and returns a list of all running processes.
 Try<std::set<pid_t> > pids();
 
+// Reads from /proc/cpuinfo and returns a list of CPUs.
+Try<std::list<CPU> > cpus();
+
 // Returns the system statistics from /proc/stat.
 Try<SystemStatistics> stat();
 
@@ -45,6 +50,19 @@ Try<SystemStatistics> stat();
 Try<ProcessStatistics> stat(pid_t pid);
 
 
+// Representation of a processor (really an execution unit since this
+// captures "hardware threads" as well) modeled after /proc/cpuinfo.
+struct CPU
+{
+  CPU(unsigned int _id, unsigned int _core, unsigned int _socket)
+    : id(_id), core(_core), socket(_socket) {}
+
+  const unsigned int id; // "processor"
+  const unsigned int core; // "core id"
+  const unsigned int socket; // "physical id"
+};
+
+
 // Snapshot of a system (modeled after /proc/stat).
 struct SystemStatistics
 {

Modified: incubator/mesos/trunk/src/tests/proc_tests.cpp
URL: http://svn.apache.org/viewvc/incubator/mesos/trunk/src/tests/proc_tests.cpp?rev=1413850&r1=1413849&r2=1413850&view=diff
==============================================================================
--- incubator/mesos/trunk/src/tests/proc_tests.cpp (original)
+++ incubator/mesos/trunk/src/tests/proc_tests.cpp Mon Nov 26 21:16:53 2012
@@ -31,6 +31,7 @@
 using namespace mesos;
 using namespace mesos::internal;
 
+using proc::CPU;
 using proc::SystemStatistics;
 using proc::ProcessStatistics;
 
@@ -48,6 +49,15 @@ TEST(ProcTest, Pids)
 }
 
 
+TEST(ProcTest, Cpus)
+{
+  Try<std::list<CPU> > cpus = proc::cpus();
+
+  ASSERT_SOME(cpus);
+  EXPECT_LE(1u, cpus.get().size());
+}
+
+
 TEST(ProcTest, SystemStatistics)
 {
   Try<SystemStatistics> statistics = proc::stat();

Modified: incubator/mesos/trunk/third_party/libprocess/include/stout/stringify.hpp
URL: http://svn.apache.org/viewvc/incubator/mesos/trunk/third_party/libprocess/include/stout/stringify.hpp?rev=1413850&r1=1413849&r2=1413850&view=diff
==============================================================================
--- incubator/mesos/trunk/third_party/libprocess/include/stout/stringify.hpp (original)
+++ incubator/mesos/trunk/third_party/libprocess/include/stout/stringify.hpp Mon Nov 26 21:16:53 2012
@@ -9,6 +9,7 @@
 #include <set>
 #include <sstream> // For 'std::ostringstream'.
 #include <string>
+#include <vector>
 
 
 template <typename T>
@@ -65,6 +66,23 @@ std::string stringify(const std::list<T>
 }
 
 
+template <typename T>
+std::string stringify(const std::vector<T>& vector)
+{
+  std::ostringstream out;
+  out << "[ ";
+  typename std::vector<T>::const_iterator iterator = vector.begin();
+  while (iterator != vector.end()) {
+    out << stringify(*iterator);
+    if (++iterator != vector.end()) {
+      out << ", ";
+    }
+  }
+  out << " ]";
+  return out.str();
+}
+
+
 template <typename K, typename V>
 std::string stringify(const std::map<K, V>& map)
 {

Modified: incubator/mesos/trunk/third_party/libprocess/include/stout/strings.hpp
URL: http://svn.apache.org/viewvc/incubator/mesos/trunk/third_party/libprocess/include/stout/strings.hpp?rev=1413850&r1=1413849&r2=1413850&view=diff
==============================================================================
--- incubator/mesos/trunk/third_party/libprocess/include/stout/strings.hpp (original)
+++ incubator/mesos/trunk/third_party/libprocess/include/stout/strings.hpp Mon Nov 26 21:16:53 2012
@@ -8,6 +8,7 @@
 
 #include "foreach.hpp"
 #include "format.hpp"
+#include "stringify.hpp"
 
 namespace strings {
 
@@ -172,9 +173,12 @@ template <typename Iterable>
 inline std::string join(const std::string& separator, const Iterable& i)
 {
   std::string result;
-  typename Iterable::const_iterator iterator;
-  for (iterator = i.begin(); iterator != i.end(); ++iterator) {
-    result += separator + *iterator;
+  typename Iterable::const_iterator iterator = i.begin();
+  while (iterator != i.end()) {
+    result += stringify(*iterator);
+    if (++iterator != i.end()) {
+      result += separator;
+    }
   }
   return result;
 }