mesos-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From b...@apache.org
Subject svn commit: r1413863 [1/2] - in /incubator/mesos/branches/0.11.0/src: linux/cgroups.cpp linux/cgroups.hpp slave/cgroups_isolation_module.cpp tests/assert.hpp tests/cgroups_tests.cpp
Date Mon, 26 Nov 2012 21:24:05 GMT
Author: benh
Date: Mon Nov 26 21:24:04 2012
New Revision: 1413863

URL: http://svn.apache.org/viewvc?rev=1413863&view=rev
Log:
Replaced some names in cgroups and updated some return values to be
Try<bool> instead of Try<Nothing>.

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

Modified:
    incubator/mesos/branches/0.11.0/src/linux/cgroups.cpp
    incubator/mesos/branches/0.11.0/src/linux/cgroups.hpp
    incubator/mesos/branches/0.11.0/src/slave/cgroups_isolation_module.cpp
    incubator/mesos/branches/0.11.0/src/tests/assert.hpp
    incubator/mesos/branches/0.11.0/src/tests/cgroups_tests.cpp

Modified: incubator/mesos/branches/0.11.0/src/linux/cgroups.cpp
URL: http://svn.apache.org/viewvc/incubator/mesos/branches/0.11.0/src/linux/cgroups.cpp?rev=1413863&r1=1413862&r2=1413863&view=diff
==============================================================================
--- incubator/mesos/branches/0.11.0/src/linux/cgroups.cpp (original)
+++ incubator/mesos/branches/0.11.0/src/linux/cgroups.cpp Mon Nov 26 21:24:04 2012
@@ -53,8 +53,6 @@
 #include "linux/fs.hpp"
 #include "linux/proc.hpp"
 
-// TODO(bmahler): Change all unnecessary Future<bool>'s to Future<Nothing>'s.
-
 using namespace process;
 
 // TODO(benh): Move linux/fs.hpp out of 'mesos- namespace.
@@ -197,30 +195,30 @@ static Try<Nothing> cloneCpusetCpusMems(
     const string& parentCgroup,
     const string& childCgroup)
 {
-  Try<string> cpus = readControl(hierarchy, parentCgroup, "cpuset.cpus");
+  Try<string> cpus = cgroups::read(hierarchy, parentCgroup, "cpuset.cpus");
   if (cpus.isError()) {
     return Try<Nothing>::error(
-        "Failed to read cpuset.cpus: " + cpus.error());
+        "Failed to read control 'cpuset.cpus': " + cpus.error());
   }
 
-  Try<string> mems = readControl(hierarchy, parentCgroup, "cpuset.mems");
+  Try<string> mems = cgroups::read(hierarchy, parentCgroup, "cpuset.mems");
   if (mems.isError()) {
     return Try<Nothing>::error(
-        "Failed to read cpuset.mems: " + mems.error());
+        "Failed to read control 'cpuset.mems': " + mems.error());
   }
 
-  Try<Nothing> write =
-    writeControl(hierarchy, childCgroup, "cpuset.cpus", cpus.get());
+  Try<Nothing> write = cgroups::write(
+      hierarchy, childCgroup, "cpuset.cpus", cpus.get());
   if (write.isError()) {
     return Try<Nothing>::error(
-        "Failed to write cpuset.cpus: " + write.error());
+        "Failed to write control 'cpuset.cpus': " + write.error());
   }
 
-  write =
-    writeControl(hierarchy, childCgroup, "cpuset.mems", mems.get());
+  write = cgroups::write(
+      hierarchy, childCgroup, "cpuset.mems", mems.get());
   if (write.isError()) {
     return Try<Nothing>::error(
-        "Failed to write cpuset.mems: " + write.error());
+        "Failed to write control 'cpuset.mems': " + write.error());
   }
 
   return Nothing();
@@ -238,25 +236,28 @@ static Try<Nothing> cloneCpusetCpusMems(
 // @param   cgroup      Path to the cgroup relative to the hierarchy root.
 // @return  Some if the operation succeeds.
 //          Error if the operation fails.
-static Try<Nothing> createCgroup(const string& hierarchy, const string& cgroup)
+static Try<Nothing> create(const string& hierarchy, const string& cgroup)
 {
   string path = path::join(hierarchy, cgroup);
-
-  // Do NOT recursively create cgroups.
-  Try<Nothing> mkdir = os::mkdir(path, false);
+  Try<Nothing> mkdir = os::mkdir(path, false); // Do NOT create recursively.
   if (mkdir.isError()) {
     return Try<Nothing>::error(
-        "Failed to create cgroup at '" + path + "': " + mkdir.error());
+        "Failed to create directory at " + path + ": " + mkdir.error());
   }
 
   // Now clone 'cpuset.cpus' and 'cpuset.mems' if the 'cpuset'
   // subsystem is attached to the hierarchy.
-  if (checkHierarchy(hierarchy, "cpuset").isSome()) {
+  Try<set<string> > attached = cgroups::subsystems(hierarchy);
+  if (attached.isError()) {
+    return Try<Nothing>::error(
+        "Failed to determine if hierarchy has the 'cpuset' "
+        "subsystem attached: " + attached.error());
+  } else if (attached.get().count("cpuset") > 0) {
     Try<string> parent = os::dirname(path::join("/", cgroup));
     if (parent.isError()) {
       return Try<Nothing>::error(
-          "Failed to determine parent cgroup of '" + cgroup + "': " +
-          parent.error());
+          "Failed to determine parent cgroup of " + cgroup +
+          ": " + parent.error());
     }
     return cloneCpusetCpusMems(hierarchy, parent.get(), cgroup);
   }
@@ -275,7 +276,7 @@ static Try<Nothing> createCgroup(const s
 // @param   cgroup      Path to the cgroup relative to the hierarchy root.
 // @return  Some if the operation succeeds.
 //          Error if the operation fails.
-static Try<Nothing> removeCgroup(const string& hierarchy, const string& cgroup)
+static Try<Nothing> remove(const string& hierarchy, const string& cgroup)
 {
   string path = path::join(hierarchy, cgroup);
 
@@ -299,7 +300,7 @@ static Try<Nothing> removeCgroup(const s
 // @param   cgroup      Path to the cgroup relative to the hierarchy root.
 // @param   control     Name of the control file.
 // @return  The value read from the control file.
-static Try<string> readControl(
+static Try<string> read(
     const string& hierarchy,
     const string& cgroup,
     const string& control)
@@ -336,7 +337,7 @@ static Try<string> readControl(
 // @param   value       Value to be written.
 // @return  Some if the operation succeeds.
 //          Error if the operation fails.
-static Try<Nothing> writeControl(
+static Try<Nothing> write(
     const string& hierarchy,
     const string& cgroup,
     const string& control,
@@ -365,6 +366,40 @@ static Try<Nothing> writeControl(
 } // namespace internal {
 
 
+// Returns some error string if either (a) hierarchy is not mounted,
+// (b) cgroup does not exist, or (c) control file does not exist.
+static Option<string> verify(
+    const string& hierarchy,
+    const string& cgroup = "",
+    const string& control = "")
+{
+  Try<bool> mounted = cgroups::mounted(hierarchy);
+  if (mounted.isError()) {
+    return Option<string>::some(
+        "Failed to determine if the hierarchy at " + hierarchy +
+        " is mounted: " + mounted.error());
+  } else if (!mounted.get()) {
+    return Option<string>::some(hierarchy + " is not mounted");
+  }
+
+  if (cgroup != "") {
+    if (!os::exists(path::join(hierarchy, cgroup))) {
+      return Option<string>::some(cgroup + " does not exist");
+    }
+  }
+
+  if (control != "") {
+    CHECK(cgroup != "");
+    if (!os::exists(path::join(hierarchy, cgroup, control))) {
+      return Option<string>::some(
+          "'" + control + "' does not exist (is subsystem attached?)");
+    }
+  }
+
+  return Option<string>::none();
+}
+
+
 bool enabled()
 {
   return os::exists("/proc/cgroups");
@@ -384,7 +419,9 @@ Try<set<string> > hierarchies()
     if (entry.type == "cgroup") {
       Try<string> realpath = os::realpath(entry.dir);
       if (realpath.isError()) {
-        return Try<set<string> >::error(realpath.error());
+        return Try<set<string> >::error(
+            "Failed to determine canonical path of " + entry.dir +
+            ": " + realpath.error());
       }
       results.insert(realpath.get());
     }
@@ -396,13 +433,8 @@ Try<set<string> > hierarchies()
 
 Try<bool> enabled(const string& subsystems)
 {
-  vector<string> names = strings::tokenize(subsystems, ",");
-  if (names.empty()) {
-    return Try<bool>::error("No subsystem is specified");
-  }
-
-  Try<map<string, internal::SubsystemInfo> >
-    infosResult = internal::subsystems();
+  Try<map<string, internal::SubsystemInfo> > infosResult =
+    internal::subsystems();
   if (infosResult.isError()) {
     return Try<bool>::error(infosResult.error());
   }
@@ -410,13 +442,13 @@ Try<bool> enabled(const string& subsyste
   map<string, internal::SubsystemInfo> infos = infosResult.get();
   bool disabled = false;  // Whether some subsystems are not enabled.
 
-  foreach (const string& name, names) {
-    if (infos.find(name) == infos.end()) {
-      return Try<bool>::error("Subsystem " + name + " not found");
+  foreach (const string& subsystem, strings::tokenize(subsystems, ",")) {
+    if (infos.find(subsystem) == infos.end()) {
+      return Try<bool>::error("'" + subsystem + "' not found");
     }
-    if (!infos[name].enabled) {
+    if (!infos[subsystem].enabled) {
       // Here, we don't return false immediately because we want to return
-      // error if any of the given subsystems contain an invalid name.
+      // error if any of the given subsystems is missing.
       disabled = true;
     }
   }
@@ -427,13 +459,8 @@ Try<bool> enabled(const string& subsyste
 
 Try<bool> busy(const string& subsystems)
 {
-  vector<string> names = strings::tokenize(subsystems, ",");
-  if (names.empty()) {
-    return Try<bool>::error("No subsystem is specified");
-  }
-
-  Try<map<string, internal::SubsystemInfo> >
-    infosResult = internal::subsystems();
+  Try<map<string, internal::SubsystemInfo> > infosResult =
+    internal::subsystems();
   if (infosResult.isError()) {
     return Try<bool>::error(infosResult.error());
   }
@@ -441,13 +468,13 @@ Try<bool> busy(const string& subsystems)
   map<string, internal::SubsystemInfo> infos = infosResult.get();
   bool busy = false;
 
-  foreach (const string& name, names) {
-    if (infos.find(name) == infos.end()) {
-      return Try<bool>::error("Subsystem " + name + " not found");
+  foreach (const string& subsystem, strings::tokenize(subsystems, ",")) {
+    if (infos.find(subsystem) == infos.end()) {
+      return Try<bool>::error("'" + subsystem + "' not found");
     }
-    if (infos[name].hierarchy != 0) {
+    if (infos[subsystem].hierarchy != 0) {
       // Here, we don't return false immediately because we want to return
-      // error if any of the given subsystems contain an invalid name.
+      // error if any of the given subsystems is missing.
       busy = true;
     }
   }
@@ -479,13 +506,16 @@ Try<set<string> > subsystems(const strin
   // We compare the canonicalized absolute paths.
   Try<string> hierarchyAbsPath = os::realpath(hierarchy);
   if (hierarchyAbsPath.isError()) {
-    return Try<set<string> >::error(hierarchyAbsPath.error());
+    return Try<set<string> >::error(
+        "Failed to determine canonical path of " + hierarchy +
+        ": " + hierarchyAbsPath.error());
   }
 
   // Read currently mounted file systems from /proc/mounts.
   Try<fs::MountTable> table = fs::MountTable::read("/proc/mounts");
   if (table.isError()) {
-    return Try<set<string> >::error(table.error());
+    return Try<set<string> >::error(
+        "Failed to read mount table: " + table.error());
   }
 
   // Check if hierarchy is a mount point of type cgroup.
@@ -494,7 +524,9 @@ Try<set<string> > subsystems(const strin
     if (entry.type == "cgroup") {
       Try<string> dirAbsPath = os::realpath(entry.dir);
       if (dirAbsPath.isError()) {
-        return Try<set<string> >::error(dirAbsPath.error());
+        return Try<set<string> >::error(
+        "Failed to determine canonical path of " + entry.dir +
+        ": " + dirAbsPath.error());
       }
 
       // Seems that a directory can be mounted more than once. Previous mounts
@@ -530,53 +562,56 @@ Try<set<string> > subsystems(const strin
 }
 
 
-Try<Nothing> createHierarchy(const string& hierarchy, const string& subsystems)
+Try<Nothing> mount(const string& hierarchy, const string& subsystems)
 {
   if (os::exists(hierarchy)) {
     return Try<Nothing>::error(
         hierarchy + " already exists in the file system");
   }
 
-  // Make sure all subsystems are enabled.
-  Try<bool> enabledResult = enabled(subsystems);
-  if (enabledResult.isError()) {
-    return Try<Nothing>::error(enabledResult.error());
-  } else if (!enabledResult.get()) {
-    return Try<Nothing>::error("Some subsystems are not enabled");
-  }
+  // Make sure all subsystems are enabled and not busy.
+  foreach (const string& subsystem, strings::tokenize(subsystems, ",")) {
+    Try<bool> result = enabled(subsystem);
+    if (result.isError()) {
+      return Try<Nothing>::error(result.error());
+    } else if (!result.get()) {
+      return Try<Nothing>::error(
+          "'" + subsystem + "' is not enabled by the kernel");
+    }
 
-  // Make sure none of the subsystems are busy.
-  Try<bool> busyResult = busy(subsystems);
-  if (busyResult.isError()) {
-    return Try<Nothing>::error(busyResult.error());
-  } else if (busyResult.get()) {
-    return Try<Nothing>::error("Some subsystems are currently busy");
+    result = busy(subsystem);
+    if (result.isError()) {
+      return Try<Nothing>::error(result.error());
+    } else if (result.get()) {
+      return Try<Nothing>::error(
+          "'" + subsystem + "' is already attached to another hierarchy");
+    }
   }
 
   // Create the directory for the hierarchy.
   Try<Nothing> mkdir = os::mkdir(hierarchy);
   if (mkdir.isError()) {
     return Try<Nothing>::error(
-        "Failed to create " + hierarchy + ": " + mkdir.error());
+        "Failed to mkdir " + hierarchy + ": " + mkdir.error());
   }
 
   // Mount the virtual file system (attach subsystems).
-  Try<Nothing> mountResult = internal::mount(hierarchy, subsystems);
-  if (mountResult.isError()) {
-    // Ignore success or failure of rmdir.
+  Try<Nothing> result = internal::mount(hierarchy, subsystems);
+  if (result.isError()) {
+    // Do a best effort rmdir of hierarchy (ignoring success or failure).
     os::rmdir(hierarchy);
-    return mountResult;
+    return result;
   }
 
   return Nothing();
 }
 
 
-Try<Nothing> removeHierarchy(const string& hierarchy)
+Try<Nothing> unmount(const string& hierarchy)
 {
-  Try<Nothing> check = checkHierarchy(hierarchy);
-  if (check.isError()) {
-    return check;
+  Option<string> error = verify(hierarchy);
+  if (error.isSome()) {
+    return Try<Nothing>::error(error.get());
   }
 
   Try<Nothing> unmount = internal::unmount(hierarchy);
@@ -586,164 +621,121 @@ Try<Nothing> removeHierarchy(const strin
 
   Try<Nothing> rmdir = os::rmdir(hierarchy);
   if (rmdir.isError()) {
-    return Try<Nothing>::error("Failed to rmdir " + hierarchy + rmdir.error());
+    return Try<Nothing>::error(
+        "Failed to remove directory at " + hierarchy + ": " + rmdir.error());
   }
 
   return Nothing();
 }
 
 
-Try<Nothing> checkHierarchy(const string& hierarchy)
+Try<bool> mounted(const string& hierarchy, const string& subsystems)
 {
-  Try<set<string> > names = subsystems(hierarchy);
-  if (names.isError()) {
-    return Try<Nothing>::error(names.error());
+  if (!os::exists(hierarchy)) {
+    return false;
   }
 
-  return Nothing();
-}
+  // We compare canonicalized absolute paths.
+  Try<string> realpath = os::realpath(hierarchy);
+  if (realpath.isError()) {
+    return Try<bool>::error(
+        "Failed to determine canonical path of " + hierarchy +
+        ": " + realpath.error());
+  }
 
+  Try<set<string> > hierarchies = cgroups::hierarchies();
+  if (hierarchies.isError()) {
+    return Try<bool>::error(
+        "Failed to get mounted hierarchies: " + hierarchies.error());
+  }
 
-Try<Nothing> checkHierarchy(const string& hierarchy, const string& subsystems)
-{
-  // Check if subsystems are enabled in the system.
-  Try<bool> enabledResult = enabled(subsystems);
-  if (enabledResult.isError()) {
-    return Try<Nothing>::error(enabledResult.error());
-  } else if (!enabledResult.get()) {
-    return Try<Nothing>::error("Some subsystems are not enabled");
+  if (hierarchies.get().count(realpath.get()) == 0) {
+    return false;
   }
 
-  Try<set<string> > namesResult = cgroups::subsystems(hierarchy);
-  if (namesResult.isError()) {
-    return Try<Nothing>::error(namesResult.error());
+  // Now make sure all the specified subsytems are attached.
+  Try<set<string> > attached = cgroups::subsystems(hierarchy);
+  if (attached.isError()) {
+    return Try<bool>::error(
+        "Failed to get subsystems attached to hierarchy " +
+        hierarchy + ": " + attached.error());
   }
 
-  set<string> names = namesResult.get();
-  foreach (const string& name, strings::tokenize(subsystems, ",")) {
-    if (names.find(name) == names.end()) {
-      return Try<Nothing>::error(
-          "Subsystem " + name + " is not found or enabled");
+  foreach (const string& subsystem, strings::tokenize(subsystems, ",")) {
+    if (attached.get().count(subsystem) == 0) {
+      return false;
     }
   }
 
-  return Nothing();
+  return true;
 }
 
 
-Try<Nothing> createCgroup(const string& hierarchy, const string& cgroup)
+Try<Nothing> create(const string& hierarchy, const string& cgroup)
 {
-  Try<Nothing> check = checkHierarchy(hierarchy);
-  if (check.isError()) {
-    return check;
+  Option<string> error = verify(hierarchy);
+  if (error.isSome()) {
+    return Try<Nothing>::error(error.get());
   }
 
-  return internal::createCgroup(hierarchy, cgroup);
+  return internal::create(hierarchy, cgroup);
 }
 
 
-Try<Nothing> removeCgroup(const string& hierarchy, const string& cgroup)
+Try<Nothing> remove(const string& hierarchy, const string& cgroup)
 {
-  Try<Nothing> check = checkCgroup(hierarchy, cgroup);
-  if (check.isError()) {
-    return check;
+  Option<string> error = verify(hierarchy, cgroup);
+  if (error.isSome()) {
+    return Try<Nothing>::error(error.get());
   }
 
-  Try<vector<string> > cgroups = getCgroups(hierarchy, cgroup);
+  Try<vector<string> > cgroups = cgroups::get(hierarchy, cgroup);
   if (cgroups.isError()) {
-    return Try<Nothing>::error(cgroups.error());
+    return Try<Nothing>::error(
+        "Failed to get nested cgroups: " + cgroups.error());
   }
 
   if (!cgroups.get().empty()) {
-    return Try<Nothing>::error("Sub-cgroups exist in " + cgroup);
+    return Try<Nothing>::error("Nested cgroups exist");
   }
 
-  return internal::removeCgroup(hierarchy, cgroup);
+  return internal::remove(hierarchy, cgroup);
 }
 
 
-Try<Nothing> checkCgroup(const string& hierarchy, const string& cgroup)
+Try<bool> exists(const string& hierarchy, const string& cgroup)
 {
-  Try<Nothing> check = checkHierarchy(hierarchy);
-  if (check.isError()) {
-    return check;
+  Option<string> error = verify(hierarchy);
+  if (error.isSome()) {
+    return Try<bool>::error(error.get());
   }
 
-  string path = path::join(hierarchy, cgroup);
-  if (!os::exists(path)) {
-    return Try<Nothing>::error("Cgroup " + cgroup + " is not valid");
-  }
-
-  return Nothing();
+  return os::exists(path::join(hierarchy, cgroup));
 }
 
 
-Try<string> readControl(
-    const string& hierarchy,
-    const string& cgroup,
-    const string& control)
-{
-  Try<Nothing> check = checkControl(hierarchy, cgroup, control);
-  if (check.isError()) {
-    return Try<string>::error(check.error());
-  }
-
-  return internal::readControl(hierarchy, cgroup, control);
-}
-
-
-Try<Nothing> writeControl(
-    const string& hierarchy,
-    const string& cgroup,
-    const string& control,
-    const string& value)
-{
-  Try<Nothing> check = checkControl(hierarchy, cgroup, control);
-  if (check.isError()) {
-    return check;
-  }
-
-  return internal::writeControl(hierarchy, cgroup, control, value);
-}
-
-
-Try<Nothing> checkControl(
-    const string& hierarchy,
-    const string& cgroup,
-    const string& control)
-{
-  Try<Nothing> check = checkCgroup(hierarchy, cgroup);
-  if (check.isError()) {
-    return check;
-  }
-
-  string path = path::join(hierarchy, cgroup, control);
-  if (!os::exists(path)) {
-    return Try<Nothing>::error("Control file " + path + " does not exist");
-  }
-
-  return Nothing();
-}
-
-
-Try<vector<string> > getCgroups(const string& hierarchy, const string& cgroup)
+Try<vector<string> > get(const string& hierarchy, const string& cgroup)
 {
-  Try<Nothing> check = checkCgroup(hierarchy, cgroup);
-  if (check.isError()) {
-    return Try<vector<string> >::error(check.error());
+  Option<string> error = verify(hierarchy, cgroup);
+  if (error.isSome()) {
+    return Try<vector<string> >::error(error.get());
   }
 
   Try<string> hierarchyAbsPath = os::realpath(hierarchy);
   if (hierarchyAbsPath.isError()) {
-    return Try<vector<string> >::error(hierarchyAbsPath.error());
+    return Try<vector<string> >::error(
+        "Failed to determine canonical path of " + hierarchy +
+        ": " + hierarchyAbsPath.error());
   }
 
   Try<string> destAbsPath = os::realpath(path::join(hierarchy, cgroup));
   if (destAbsPath.isError()) {
-    return Try<vector<string> >::error(destAbsPath.error());
+    return Try<vector<string> >::error(
+        "Failed to determine canonical path of " +
+        path::join(hierarchy, cgroup) + ": " + destAbsPath.error());
   }
 
-  char* paths[] = {const_cast<char*>(destAbsPath.get().c_str()), NULL};
+  char* paths[] = { const_cast<char*>(destAbsPath.get().c_str()), NULL };
 
   FTS* tree = fts_open(paths, FTS_NOCHDIR, NULL);
   if (tree == NULL) {
@@ -769,31 +761,95 @@ Try<vector<string> > getCgroups(const st
 
   if (errno != 0) {
     return Try<vector<string> >::error(
-        "Failed to read a node during the walk: " +
-          string(strerror(errno)));
+        "Failed to read a node during the walk: " + string(strerror(errno)));
   }
 
   if (fts_close(tree) != 0) {
     return Try<vector<string> >::error(
-        "Failed to stop a file system walk: " +
-          string(strerror(errno)));
+        "Failed to stop a file system walk: " + string(strerror(errno)));
   }
 
   return cgroups;
 }
 
 
-Try<set<pid_t> > getTasks(const string& hierarchy, const string& cgroup)
+Try<Nothing> kill(
+    const string& hierarchy,
+    const string& cgroup,
+    int signal)
 {
-  Try<Nothing> check = checkCgroup(hierarchy, cgroup);
-  if (check.isError()) {
-    return Try<set<pid_t> >::error(check.error());
+  Option<string> error = verify(hierarchy, cgroup);
+  if (error.isSome()) {
+    return Try<Nothing>::error(error.get());
+  }
+
+  Try<set<pid_t> > pids = tasks(hierarchy, cgroup);
+  if (pids.isError()) {
+    return Try<Nothing>::error(
+        "Failed to get tasks of cgroup: " + pids.error());
+  }
+
+  foreach (pid_t pid, pids.get()) {
+    if (::kill(pid, signal) == -1) {
+      return Try<Nothing>::error(
+          "Failed to send " + string(strsignal(signal)) + " to process " +
+          stringify(pid) + ": " + strerror(errno));
+    }
   }
 
-  // Read from the control file.
-  Try<string> value = internal::readControl(hierarchy, cgroup, "tasks");
+  return Nothing();
+}
+
+
+Try<string> read(
+    const string& hierarchy,
+    const string& cgroup,
+    const string& control)
+{
+  Option<string> error = verify(hierarchy, cgroup, control);
+  if (error.isSome()) {
+    return Try<string>::error(error.get());
+  }
+
+  return internal::read(hierarchy, cgroup, control);
+}
+
+
+Try<Nothing> write(
+    const string& hierarchy,
+    const string& cgroup,
+    const string& control,
+    const string& value)
+{
+  Option<string> error = verify(hierarchy, cgroup, control);
+  if (error.isSome()) {
+    return Try<Nothing>::error(error.get());
+  }
+
+  return internal::write(hierarchy, cgroup, control, value);
+}
+
+
+Try<bool> exists(
+    const string& hierarchy,
+    const string& cgroup,
+    const string& control)
+{
+  Option<string> error = verify(hierarchy, cgroup);
+  if (error.isSome()) {
+    return Try<bool>::error(error.get());
+  }
+
+  return os::exists(path::join(hierarchy, cgroup, control));
+}
+
+
+Try<set<pid_t> > tasks(const string& hierarchy, const string& cgroup)
+{
+  Try<string> value = cgroups::read(hierarchy, cgroup, "tasks");
   if (value.isError()) {
-    return Try<set<pid_t> >::error(value.error());
+    return Try<set<pid_t> >::error(
+        "Failed to read cgroups control 'tasks': " + value.error());
   }
 
   // Parse the value read from the control file.
@@ -817,17 +873,9 @@ Try<set<pid_t> > getTasks(const string& 
 }
 
 
-Try<Nothing> assignTask(const string& hierarchy, const string& cgroup, pid_t pid)
+Try<Nothing> assign(const string& hierarchy, const string& cgroup, pid_t pid)
 {
-  Try<Nothing> check = checkCgroup(hierarchy, cgroup);
-  if (check.isError()) {
-    return check;
-  }
-
-  return internal::writeControl(hierarchy,
-                                cgroup,
-                                "tasks",
-                                stringify(pid));
+  return cgroups::write(hierarchy, cgroup, "tasks", stringify(pid));
 }
 
 
@@ -882,15 +930,15 @@ static int eventfd(unsigned int initval,
 // will create an eventfd and write appropriate control file to correlate the
 // eventfd with a type of event so that users can start polling on the eventfd
 // to get notified. It returns the eventfd (file descriptor) if the notifier has
-// been successfully opened. This function assumes all the parameters are valid.
-// The eventfd is set to be non-blocking.
+// been successfully registered. This function assumes all the parameters are
+// valid. The eventfd is set to be non-blocking.
 // @param   hierarchy   Path to the hierarchy root.
 // @param   cgroup      Path to the cgroup relative to the hierarchy root.
 // @param   control     Name of the control file.
 // @param   args        Control specific arguments.
 // @return  The eventfd if the operation succeeds.
 //          Error if the operation fails.
-static Try<int> openNotifier(
+static Try<int> registerNotifier(
     const string& hierarchy,
     const string& cgroup,
     const string& control,
@@ -899,7 +947,7 @@ static Try<int> openNotifier(
   int efd = internal::eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK);
   if (efd < 0) {
     return Try<int>::error(
-        "Create eventfd failed: " + string(strerror(errno)));
+        "Failed to create an eventfd: " + string(strerror(errno)));
   }
 
   // Open the control file.
@@ -907,7 +955,7 @@ static Try<int> openNotifier(
   Try<int> cfd = os::open(path, O_RDWR);
   if (cfd.isError()) {
     os::close(efd);
-    return Try<int>::error(cfd.error());
+    return Try<int>::error("Failed to open " + path + ": " + cfd.error());
   }
 
   // Write the event control file (cgroup.event_control).
@@ -916,14 +964,13 @@ static Try<int> openNotifier(
   if (args.isSome()) {
     out << " " << args.get();
   }
-  Try<Nothing> write = internal::writeControl(hierarchy,
-                                              cgroup,
-                                              "cgroup.event_control",
-                                              out.str());
+  Try<Nothing> write = internal::write(
+      hierarchy, cgroup, "cgroup.event_control", out.str());
   if (write.isError()) {
     os::close(efd);
     os::close(cfd.get());
-    return Try<int>::error(write.error());
+    return Try<int>::error(
+        "Failed to write control 'cgroup.event_control': " + write.error());
   }
 
   os::close(cfd.get());
@@ -932,11 +979,11 @@ static Try<int> openNotifier(
 }
 
 
-// Close a notifier. The parameter fd is the eventfd returned by openNotifier.
-// @param   fd      The eventfd returned by openNotifier.
+// Unregister a notifier.
+// @param   fd      The eventfd returned by registerNotifier.
 // @return  Some if the operation succeeds.
 //          Error if the operation fails.
-static Try<Nothing> closeNotifier(int fd)
+static Try<Nothing> unregisterNotifier(int fd)
 {
   return os::close(fd);
 }
@@ -969,15 +1016,15 @@ protected:
     promise.future().onDiscarded(lambda::bind(
         static_cast<void (*)(const UPID&, bool)>(terminate), self(), true));
 
-    // Open the event file.
-    Try<int> fd = internal::openNotifier(hierarchy, cgroup, control, args);
+    // Register an eventfd "notifier" for the given control.
+    Try<int> fd = internal::registerNotifier(hierarchy, cgroup, control, args);
     if (fd.isError()) {
-      promise.fail(fd.error());
+      promise.fail("Failed to register notification eventfd: " + fd.error());
       terminate(self());
       return;
     }
 
-    // Remember the opened event file.
+    // Remember the opened event file descriptor.
     eventfd = fd.get();
 
     // Perform nonblocking read on the event file. The nonblocking read will
@@ -993,12 +1040,11 @@ protected:
     // Discard the nonblocking read.
     reading.discard();
 
-    // Close the eventfd if needed.
+    // Unregister the eventfd if needed.
     if (eventfd.isSome()) {
-      Try<Nothing> close = internal::closeNotifier(eventfd.get());
-      if (close.isError()) {
-        LOG(ERROR) << "Closing eventfd " << eventfd.get()
-                   << " failed: " << close.error();
+      Try<Nothing> unregister = internal::unregisterNotifier(eventfd.get());
+      if (unregister.isError()) {
+        LOG(ERROR) << "Failed to unregistering eventfd: " << unregister.error();
       }
     }
   }
@@ -1031,10 +1077,10 @@ private:
     terminate(self());
   }
 
-  string hierarchy;
-  string cgroup;
-  string control;
-  Option<string> args;
+  const string hierarchy;
+  const string cgroup;
+  const string control;
+  const Option<string> args;
   Promise<uint64_t> promise;
   Future<size_t> reading;
   Option<int> eventfd;  // The eventfd if opened.
@@ -1044,15 +1090,15 @@ private:
 } // namespace internal {
 
 
-Future<uint64_t> listenEvent(
+Future<uint64_t> listen(
     const string& hierarchy,
     const string& cgroup,
     const string& control,
     const Option<string>& args)
 {
-  Try<Nothing> check = checkControl(hierarchy, cgroup, control);
-  if (check.isError()) {
-    return Future<uint64_t>::failed(check.error());
+  Option<string> error = verify(hierarchy, cgroup, control);
+  if (error.isSome()) {
+    return Future<uint64_t>::failed(error.get());
   }
 
   internal::EventListener* listener =
@@ -1093,33 +1139,27 @@ protected:
     promise.future().onDiscarded(lambda::bind(
         static_cast<void (*)(const UPID&, bool)>(terminate), self(), true));
 
-    if (interval < Seconds(0)) {
-      promise.fail("Invalid interval: " + stringify(interval));
-      terminate(self());
-      return;
-    }
+    CHECK(interval >= Seconds(0));
 
     // Start the action.
+    CHECK(action == "FREEZE" || action == "THAW");
     if (action == "FREEZE") {
       freeze();
     } else if (action == "THAW") {
       thaw();
-    } else {
-      promise.fail("Invalid action: " + action);
-      terminate(self());
     }
   }
 
 private:
   void freeze()
   {
-    LOG(INFO) << "Attempting to freeze cgroup '" << cgroup << "'";
+    LOG(INFO) << "Trying to freeze cgroup " << path::join(hierarchy, cgroup);
 
-    Try<Nothing> result =
-      internal::writeControl(hierarchy, cgroup, "freezer.state", "FROZEN");
+    Try<Nothing> write = internal::write(
+        hierarchy, cgroup, "freezer.state", "FROZEN");
 
-    if (result.isError()) {
-      promise.fail(result.error());
+    if (write.isError()) {
+      promise.fail("Failed to write control 'freezer.state': " + write.error());
       terminate(self());
     } else {
       watchFrozen();
@@ -1128,13 +1168,13 @@ private:
 
   void thaw()
   {
-    LOG(INFO) << "Attempting to thaw cgroup '" << cgroup << "'";
+    LOG(INFO) << "Trying to thaw cgroup " << path::join(hierarchy, cgroup);
 
-    Try<Nothing> result =
-      internal::writeControl(hierarchy, cgroup, "freezer.state", "THAWED");
+    Try<Nothing> write = internal::write(
+        hierarchy, cgroup, "freezer.state", "THAWED");
 
-    if (result.isError()) {
-      promise.fail(result.error());
+    if (write.isError()) {
+      promise.fail("Failed to write control 'freezer.state': " + write.error());
       terminate(self());
     } else {
       watchThawed();
@@ -1143,18 +1183,17 @@ private:
 
   void watchFrozen(unsigned int attempt = 0)
   {
-    Try<string> state =
-      internal::readControl(hierarchy, cgroup, "freezer.state");
+    Try<string> state = internal::read(hierarchy, cgroup, "freezer.state");
 
     if (state.isError()) {
-      promise.fail(state.error());
+      promise.fail("Failed to read control 'freezer.state': " + state.error());
       terminate(self());
       return;
     }
 
     if (strings::trim(state.get()) == "FROZEN") {
-      LOG(INFO) << "Successfully froze cgroup '" << cgroup << "' after "
-                << attempt + 1 << " attempts.";
+      LOG(INFO) << "Successfully froze cgroup " << path::join(hierarchy, cgroup)
+                << " after " << attempt + 1 << " attempts";
       promise.set(true);
       terminate(self());
       return;
@@ -1168,9 +1207,9 @@ private:
       // make sure that the freezer can finish.
       // TODO(jieyu): This code can be removed in the future as the newer
       // version of the kernel solves this problem (e.g. Linux-3.2.0).
-      Try<set<pid_t> > pids = getTasks(hierarchy, cgroup);
+      Try<set<pid_t> > pids = tasks(hierarchy, cgroup);
       if (pids.isError()) {
-        promise.fail(pids.error());
+        promise.fail("Failed to get tasks of cgroup: " + pids.error());
         terminate(self());
         return;
       }
@@ -1181,7 +1220,7 @@ private:
       foreach (pid_t pid, pids.get()) {
         Try<proc::ProcessStatistics> stat = proc::stat(pid);
         if (stat.isError()) {
-          promise.fail(pids.error());
+          promise.fail("Failed to get process statistics: " + stat.error());
           terminate(self());
           return;
         }
@@ -1190,7 +1229,9 @@ private:
         if (stat.get().state == 'T') {
           // Send a SIGCONT signal to the process.
           if (::kill(pid, SIGCONT) == -1) {
-            promise.fail(strerror(errno));
+            promise.fail(
+                "Failed to send SIGCONT to process " + stringify(pid) +
+                ": " + string(strerror(errno)));
             terminate(self());
             return;
           }
@@ -1198,19 +1239,20 @@ private:
       }
 
       if (attempt > retries) {
-        LOG(WARNING) << "Unable to freeze cgroup '" << cgroup
-                     << "' within " << retries + 1 << " attempts";
+        LOG(WARNING) << "Unable to freeze " << path::join(hierarchy, cgroup)
+                     << " within " << retries + 1 << " attempts";
         promise.set(false);
         terminate(self());
         return;
       }
 
       // Retry the freezing operation.
-      Try<Nothing> result =
-        internal::writeControl(hierarchy, cgroup, "freezer.state", "FROZEN");
+      Try<Nothing> write = internal::write(
+          hierarchy, cgroup, "freezer.state", "FROZEN");
 
-      if (result.isError()) {
-        promise.fail(result.error());
+      if (write.isError()) {
+        promise.fail(
+            "Failed to write control 'freezer.state': " + write.error());
         terminate(self());
         return;
       }
@@ -1224,17 +1266,16 @@ private:
 
   void watchThawed()
   {
-    Try<string> state =
-      internal::readControl(hierarchy, cgroup, "freezer.state");
+    Try<string> state = internal::read(hierarchy, cgroup, "freezer.state");
 
     if (state.isError()) {
-      promise.fail(state.error());
+      promise.fail("Failed to read control 'freezer.state': " + state.error());
       terminate(self());
       return;
     }
 
     if (strings::trim(state.get()) == "THAWED") {
-      LOG(INFO) << "Successfully thawed cgroup '" << cgroup << "'";
+      LOG(INFO) << "Successfully thawed " << path::join(hierarchy, cgroup);
       promise.set(true);
       terminate(self());
     } else if (strings::trim(state.get()) == "FROZEN") {
@@ -1253,27 +1294,29 @@ private:
   Promise<bool> promise;
 };
 
-
 } // namespace internal {
 
 
-Future<bool> freezeCgroup(
+Future<bool> freeze(
     const string& hierarchy,
     const string& cgroup,
     const Duration& interval,
     unsigned int retries)
 {
-  Try<Nothing> check = checkControl(hierarchy, cgroup, "freezer.state");
-  if (check.isError()) {
-    return Future<bool>::failed(check.error());
+  Option<string> error = verify(hierarchy, cgroup, "freezer.state");
+  if (error.isSome()) {
+    return Future<bool>::failed(error.get());
+  }
+
+  if (interval < Seconds(0)) {
+    return Future<bool>::failed("Interval should be non-negative");
   }
 
   // Check the current freezer state.
-  Try<string> state = internal::readControl(hierarchy,
-                                                 cgroup,
-                                                 "freezer.state");
+  Try<string> state = internal::read(hierarchy, cgroup, "freezer.state");
   if (state.isError()) {
-    return Future<bool>::failed(state.error());
+    return Future<bool>::failed(
+        "Failed to read control 'freezer.state': " + state.error());
   } else if (strings::trim(state.get()) == "FROZEN") {
     // Immediately return success.
     return true;
@@ -1287,22 +1330,25 @@ Future<bool> freezeCgroup(
 }
 
 
-Future<bool> thawCgroup(
+Future<bool> thaw(
     const string& hierarchy,
     const string& cgroup,
     const Duration& interval)
 {
-  Try<Nothing> check = checkControl(hierarchy, cgroup, "freezer.state");
-  if (check.isError()) {
-    return Future<bool>::failed(check.error());
+  Option<string> error = verify(hierarchy, cgroup, "freezer.state");
+  if (error.isSome()) {
+    return Future<bool>::failed(error.get());
+  }
+
+  if (interval < Seconds(0)) {
+    return Future<bool>::failed("Interval should be non-negative");
   }
 
   // Check the current freezer state.
-  Try<string> state = internal::readControl(hierarchy,
-                                                 cgroup,
-                                                 "freezer.state");
+  Try<string> state = internal::read(hierarchy, cgroup, "freezer.state");
   if (state.isError()) {
-    return Future<bool>::failed(state.error());
+    return Future<bool>::failed(
+        "Failed to read control 'freezer.state': " + state.error());
   } else if (strings::trim(state.get()) == "THAWED") {
     // Immediately return success.
     return true;
@@ -1347,11 +1393,7 @@ protected:
     promise.future().onDiscarded(lambda::bind(
         static_cast<void (*)(const UPID&, bool)>(terminate), self(), true));
 
-    if (interval < Seconds(0)) {
-      promise.fail("Invalid interval: " + stringify(interval));
-      terminate(self());
-      return;
-    }
+    CHECK(interval >= Seconds(0));
 
     check();
   }
@@ -1359,14 +1401,14 @@ protected:
 private:
   void check(unsigned int attempt = 0)
   {
-    Try<string> state = internal::readControl(hierarchy, cgroup, "tasks");
-    if (state.isError()) {
-      promise.fail(state.error());
+    Try<set<pid_t> > pids = tasks(hierarchy, cgroup);
+    if (pids.isError()) {
+      promise.fail("Failed to get tasks of cgroup: " + pids.error());
       terminate(self());
       return;
     }
 
-    if (strings::trim(state.get()).empty()) {
+    if (pids.get().empty()) {
       promise.set(true);
       terminate(self());
       return;
@@ -1413,11 +1455,7 @@ protected:
     promise.future().onDiscarded(lambda::bind(
           static_cast<void (*)(const UPID&, bool)>(terminate), self(), true));
 
-    if (interval < Seconds(0)) {
-      promise.fail("Invalid interval: " + stringify(interval));
-      terminate(self());
-      return;
-    }
+    CHECK(interval >= Seconds(0));
 
     killTasks();
   }
@@ -1434,9 +1472,9 @@ private:
   void killTasks() {
     lambda::function<Future<bool>(const bool&)>
       funcFreeze = defer(self(), &Self::freeze);
-    lambda::function<Future<bool>(const bool&)>
+    lambda::function<Future<Nothing>(const bool&)>
       funcKill = defer(self(), &Self::kill);
-    lambda::function<Future<bool>(const bool&)>
+    lambda::function<Future<bool>(const Nothing&)>
       funcThaw = defer(self(), &Self::thaw);
     lambda::function<Future<bool>(const bool&)>
       funcEmpty = defer(self(), &Self::empty);
@@ -1456,29 +1494,21 @@ private:
 
   Future<bool> freeze()
   {
-    return freezeCgroup(hierarchy, cgroup, interval);
+    return cgroups::freeze(hierarchy, cgroup, interval);
   }
 
-  Future<bool> kill()
+  Future<Nothing> kill()
   {
-    Try<set<pid_t> > tasks = getTasks(hierarchy, cgroup);
-    if (tasks.isError()) {
-      return Future<bool>::failed(tasks.error());
-    } else {
-      foreach (pid_t pid, tasks.get()) {
-        if (::kill(pid, SIGKILL) == -1) {
-          return Future<bool>::failed("Failed to kill process " +
-            stringify(pid) + ": " + strerror(errno));
-        }
-      }
+    Try<Nothing> kill = cgroups::kill(hierarchy, cgroup, SIGKILL);
+    if (kill.isError()) {
+      return Future<Nothing>::failed(kill.error());
     }
-
-    return true;
+    return Nothing();
   }
 
   Future<bool> thaw()
   {
-    return thawCgroup(hierarchy, cgroup, interval);
+    return cgroups::thaw(hierarchy, cgroup, interval);
   }
 
   Future<bool> empty()
@@ -1512,33 +1542,6 @@ private:
   Future<bool> chain; // Used to discard the "chain" of operations.
 };
 
-} // namespace internal {
-
-
-Future<bool> killTasks(
-    const string& hierarchy,
-    const string& cgroup,
-    const Duration& interval)
-{
-  Try<Nothing> freezerCheck = checkHierarchy(hierarchy, "freezer");
-  if (freezerCheck.isError()) {
-    return Future<bool>::failed(freezerCheck.error());
-  }
-
-  Try<Nothing> cgroupCheck = checkCgroup(hierarchy, cgroup);
-  if (cgroupCheck.isError()) {
-    return Future<bool>::failed(cgroupCheck.error());
-  }
-
-  internal::TasksKiller* killer =
-    new internal::TasksKiller(hierarchy, cgroup, interval);
-  Future<bool> future = killer->future();
-  spawn(killer, true);
-  return future;
-}
-
-
-namespace internal {
 
 // The process used to destroy a cgroup.
 class Destroyer : public Process<Destroyer>
@@ -1563,17 +1566,15 @@ protected:
     promise.future().onDiscarded(lambda::bind(
           static_cast<void (*)(const UPID&, bool)>(terminate), self(), true));
 
-    if (interval < Seconds(0)) {
-      promise.fail("Invalid interval: " + stringify(interval));
-      terminate(self());
-      return;
-    }
+    CHECK(interval >= Seconds(0));
 
     // Kill tasks in the given cgroups in parallel. Use collect mechanism to
     // wait until all kill processes finish.
     foreach (const string& cgroup, cgroups) {
-      Future<bool> killer = killTasks(hierarchy, cgroup, interval);
-      killers.push_back(killer);
+      internal::TasksKiller* killer =
+        new internal::TasksKiller(hierarchy, cgroup, interval);
+      killers.push_back(killer->future());
+      spawn(killer, true);
     }
 
     collect(killers)
@@ -1591,22 +1592,22 @@ protected:
 private:
   void killed(const Future<list<bool> >& kill)
   {
+    CHECK(!kill.isPending() && !kill.isDiscarded());
     if (kill.isReady()) {
       remove();
     } else if (kill.isFailed()) {
-      promise.fail(kill.failure());
+      promise.fail("Failed to kill tasks in nested cgroups: " + kill.failure());
       terminate(self());
-    } else {
-      LOG(FATAL) << "Invalid kill state";
     }
   }
 
   void remove()
   {
     foreach (const string& cgroup, cgroups) {
-      Try<Nothing> remove = internal::removeCgroup(hierarchy, cgroup);
+      Try<Nothing> remove = internal::remove(hierarchy, cgroup);
       if (remove.isError()) {
-        promise.fail(remove.error());
+        promise.fail(
+            "Failed to remove cgroup " + cgroup + ": " + remove.error());
         terminate(self());
         return;
       }
@@ -1616,8 +1617,8 @@ private:
     terminate(self());
   }
 
-  string hierarchy;
-  vector<string> cgroups;
+  const string hierarchy;
+  const vector<string> cgroups;
   const Duration interval;
   Promise<bool> promise;
 
@@ -1628,20 +1629,25 @@ private:
 } // namespace internal {
 
 
-Future<bool> destroyCgroup(
+Future<bool> destroy(
     const string& hierarchy,
     const string& cgroup,
     const Duration& interval)
 {
-  Try<Nothing> cgroupCheck = checkCgroup(hierarchy, cgroup);
-  if (cgroupCheck.isError()) {
-    return Future<bool>::failed(cgroupCheck.error());
+  Option<string> error = verify(hierarchy, cgroup, "freezer.state");
+  if (error.isSome()) {
+    return Future<bool>::failed(error.get());
+  }
+
+  if (interval < Seconds(0)) {
+    return Future<bool>::failed("Interval should be non-negative");
   }
 
   // Construct the vector of cgroups to destroy.
-  Try<vector<string> > cgroups = getCgroups(hierarchy, cgroup);
+  Try<vector<string> > cgroups = cgroups::get(hierarchy, cgroup);
   if (cgroups.isError()) {
-    return Future<bool>::failed(cgroups.error());
+    return Future<bool>::failed(
+        "Failed to get nested cgroups: " + cgroups.error());
   }
 
   vector<string> toDestroy = cgroups.get();

Modified: incubator/mesos/branches/0.11.0/src/linux/cgroups.hpp
URL: http://svn.apache.org/viewvc/incubator/mesos/branches/0.11.0/src/linux/cgroups.hpp?rev=1413863&r1=1413862&r2=1413863&view=diff
==============================================================================
--- incubator/mesos/branches/0.11.0/src/linux/cgroups.hpp (original)
+++ incubator/mesos/branches/0.11.0/src/linux/cgroups.hpp Mon Nov 26 21:24:04 2012
@@ -94,46 +94,44 @@ Try<std::set<std::string> > subsystems()
 // whether a hierarchy is indeed a cgroups hierarchy root.
 // @param   hierarchy   Path to the hierarchy root.
 // @return  A set of attached subsystem names.
+//          Error otherwise, (e.g., hierarchy does not exist or is not mounted).
 Try<std::set<std::string> > subsystems(const std::string& hierarchy);
 
 
-// Create an empty hierarchy and attach the given subsystems to it. This
-// function will return error if the path to the hierarchy root already exists.
-// Also, the function will return error if a subsystem in the given subsystem
-// list has already been attached to another hierarchy. On success, the cgroups
-// virtual file system will be mounted with proper subsystems attached.
+// Mount a cgroups hierarchy and attach the given subsystems to
+// it. This function will return error if the path given for the
+// hierarchy already exists.  Also, the function will return error if
+// a subsystem in the given subsystem list has already been attached
+// to another hierarchy. On success, the cgroups virtual file system
+// will be mounted with the proper subsystems attached.
 // @param   hierarchy   Path to the hierarchy root.
 // @param   subsystems  Comma-separated subsystem names.
 // @return  Some if the operation succeeds.
 //          Error if the operation fails.
-Try<Nothing> createHierarchy(const std::string& hierarchy,
-                             const std::string& subsystems);
+Try<Nothing> mount(const std::string& hierarchy, const std::string& subsystems);
 
 
-// Remove a hierarchy and the directory associated with it. This function will
-// return error if the given hierarchy is not valid. Also, it will return error
-// if the given hierarchy has cgroups inside.
+// Unmount a hierarchy and remove the directory associated with
+// it. This function will return error if the given hierarchy is not
+// valid. Also, it will return error if the given hierarchy has
+// any cgroups.
 // @param   hierarchy   Path to the hierarchy root.
 // @return  Some if the operation succeeds.
 //          Error if the operation fails.
-Try<Nothing> removeHierarchy(const std::string& hierarchy);
+Try<Nothing> unmount(const std::string& hierarchy);
 
 
-// Check whether a given directory is a hierarchy root for cgroups.
+// Returns true if the given hierarchy root is mounted as a cgroups
+// virtual file system with the specified subsystems attached.
 // @param   hierarchy   Path to the hierarchy root.
-// @return  Some if the given directory is a hierarchy root.
-//          Error if the check fails.
-Try<Nothing> checkHierarchy(const std::string& hierarchy);
-
-
-// Check whether a given directory is a hierarchy root for cgroups, and whether
-// it has proper subsystems attached.
-// @param   hierarchy   Path to the hierarchy root.
-// @param   subsystems  Comma-separated subsystem names.
-// @return  Some if the check succeeds.
-//          Error if the check fails.
-Try<Nothing> checkHierarchy(const std::string& hierarchy,
-                            const std::string& subsystems);
+// @return  True if the given directory is a hierarchy root and all of the
+//          specified subsystems are attached.
+//          False if the directory is not a hierarchy (or doesn't exist)
+//          or some of the specified subsystems are not attached.
+//          Error if the operation fails.
+Try<bool> mounted(
+    const std::string& hierarchy,
+    const std::string& subsystems = "");
 
 
 // Create a cgroup under a given hierarchy. This function will return error if
@@ -144,8 +142,7 @@ Try<Nothing> checkHierarchy(const std::s
 // @param   cgroup      Path to the cgroup relative to the hierarchy root.
 // @return  Some if the operation succeeds.
 //          Error if the operation fails.
-Try<Nothing> createCgroup(const std::string& hierarchy,
-                          const std::string& cgroup);
+Try<Nothing> create(const std::string& hierarchy, const std::string& cgroup);
 
 
 // Remove a cgroup under a given hierarchy. This function will return error if
@@ -155,18 +152,39 @@ Try<Nothing> createCgroup(const std::str
 // given cgroup, the removal operation will also fail.
 // @param   hierarchy   Path to the hierarchy root.
 // @param   cgroup      Path to the cgroup relative to the hierarchy root.
-Try<Nothing> removeCgroup(const std::string& hierarchy,
-                          const std::string& cgroup);
+Try<Nothing> remove(const std::string& hierarchy, const std::string& cgroup);
 
 
-// Check whether a given cgroup under a given hierarchy is valid. This function
-// will verify both the given hierarchy and the given cgroup.
+// Returns true if the given cgroup under a given hierarchy exists.
 // @param   hierarchy   Path to the hierarchy root.
 // @param   cgroup      Path to the cgroup relative to the hierarchy root.
-// @return  Some if the check succeeds.
-//          Error if the check fails.
-Try<Nothing> checkCgroup(const std::string& hierarchy,
-                         const std::string& cgroup);
+// @return  True if the cgroup exists.
+//          False if the cgroup does not exist.
+//          Error if the operation fails (i.e., hierarchy is not mounted).
+Try<bool> exists(const std::string& hierarchy, const std::string& cgroup);
+
+
+// Return all the cgroups under the given cgroup of a given hierarchy. By
+// default, it returns all the cgroups under the given hierarchy. This function
+// will return error if the given hierarchy is not mounted or the cgroup does
+// not exist. We use a post-order walk here to ease the removal of cgroups.
+// @param   hierarchy   Path to the hierarchy root.
+// @return  A vector of cgroup names.
+Try<std::vector<std::string> > get(
+    const std::string& hierarchy,
+    const std::string& cgroup = "/");
+
+
+// Send the specified signal to all process in a cgroup.
+// @param   hierarchy   Path to the hierarchy root.
+// @param   cgroup      Path to the cgroup relative to the hierarchy root.
+// @param   signal      The signal to send to all tasks within the cgroup.
+// @return  Some on success.
+//          Error if some unexpected happens.
+Try<Nothing> kill(
+    const std::string& hierarchy,
+    const std::string& cgroup,
+    int signal);
 
 
 // Read a control file. Control files are used to monitor and control cgroups.
@@ -178,22 +196,24 @@ Try<Nothing> checkCgroup(const std::stri
 // @param   cgroup      Path to the cgroup relative to the hierarchy root.
 // @param   control     Name of the control file.
 // @return  The value read from the control file.
-Try<std::string> readControl(const std::string& hierarchy,
-                             const std::string& cgroup,
-                             const std::string& control);
+Try<std::string> read(
+    const std::string& hierarchy,
+    const std::string& cgroup,
+    const std::string& control);
 
 
-// Write a control file. Parameter checking is similar to readControl.
+// Write a control file. Parameter checking is similar to read.
 // @param   hierarchy   Path to the hierarchy root.
 // @param   cgroup      Path to the cgroup relative to the hierarchy root.
 // @param   control     Name of the control file.
 // @param   value       Value to be written.
 // @return  Some if the operation succeeds.
 //          Error if the operation fails.
-Try<Nothing> writeControl(const std::string& hierarchy,
-                          const std::string& cgroup,
-                          const std::string& control,
-                          const std::string& value);
+Try<Nothing> write(
+    const std::string& hierarchy,
+    const std::string& cgroup,
+    const std::string& control,
+    const std::string& value);
 
 
 // Check whether a control file is valid under a given cgroup and a given
@@ -205,19 +225,10 @@ Try<Nothing> writeControl(const std::str
 // @param   control     Name of the control file.
 // @return  Some if the check succeeds.
 //          Error if the check fails.
-Try<Nothing> checkControl(const std::string& hierarchy,
-                          const std::string& cgroup,
-                          const std::string& control);
-
-
-// Return all the cgroups under the given cgroup of a given hierarchy. By
-// default, it returns all the cgroups under the given hierarchy. This function
-// will return error if the given hierarchy is not valid.  We use a post-order
-// walk here to ease the removal of cgroups.
-// @param   hierarchy   Path to the hierarchy root.
-// @return  A vector of cgroup names.
-Try<std::vector<std::string> > getCgroups(const std::string& hierarchy,
-                                          const std::string& cgroup = "/");
+Try<bool> exists(
+    const std::string& hierarchy,
+    const std::string& cgroup,
+    const std::string& control);
 
 
 // Return the set of process IDs in a given cgroup under a given hierarchy. It
@@ -225,8 +236,9 @@ Try<std::vector<std::string> > getCgroup
 // @param   hierarchy   Path to the hierarchy root.
 // @param   cgroup      Path to the cgroup relative to the hierarchy root.
 // @return  The set of process ids.
-Try<std::set<pid_t> > getTasks(const std::string& hierarchy,
-                               const std::string& cgroup);
+Try<std::set<pid_t> > tasks(
+    const std::string& hierarchy,
+    const std::string& cgroup);
 
 
 // Assign a given process specified by its pid to a given cgroup. This function
@@ -237,9 +249,10 @@ Try<std::set<pid_t> > getTasks(const std
 // @param   pid         The pid of the given process.
 // @return  Some if the operation succeeds.
 //          Error if the operation fails.
-Try<Nothing> assignTask(const std::string& hierarchy,
-                        const std::string& cgroup,
-                        pid_t pid);
+Try<Nothing> assign(
+    const std::string& hierarchy,
+    const std::string& cgroup,
+    pid_t pid);
 
 
 // Listen on an event notifier and return a future which will become ready when
@@ -252,11 +265,11 @@ Try<Nothing> assignTask(const std::strin
 // @param   args        Control specific arguments.
 // @return  A future which contains the value read from the file when ready.
 //          Error if some unexpected happens.
-process::Future<uint64_t> listenEvent(const std::string& hierarchy,
-                                      const std::string& cgroup,
-                                      const std::string& control,
-                                      const Option<std::string>& args =
-                                        Option<std::string>::none());
+process::Future<uint64_t> listen(
+    const std::string& hierarchy,
+    const std::string& cgroup,
+    const std::string& control,
+    const Option<std::string>& args = Option<std::string>::none());
 
 
 // Freeze all the processes in a given cgroup. We try to use the freezer
@@ -278,10 +291,11 @@ process::Future<uint64_t> listenEvent(co
 // @return  A future which will become true when all processes are frozen, or
 //          false when all retries have occurred unsuccessfully.
 //          Error if some unexpected happens.
-process::Future<bool> freezeCgroup(const std::string& hierarchy,
-                                   const std::string& cgroup,
-                                   const Duration& interval = Seconds(0.1),
-                                   const unsigned int retries = FREEZE_RETRIES);
+process::Future<bool> freeze(
+    const std::string& hierarchy,
+    const std::string& cgroup,
+    const Duration& interval = Seconds(0.1),
+    const unsigned int retries = FREEZE_RETRIES);
 
 
 // Thaw the given cgroup. This is a revert operation of freezeCgroup. It will
@@ -294,28 +308,10 @@ process::Future<bool> freezeCgroup(const
 //                      requests (default: 0.1 seconds).
 // @return  A future which will become ready when all processes are thawed.
 //          Error if some unexpected happens.
-process::Future<bool> thawCgroup(const std::string& hierarchy,
-                                 const std::string& cgroup,
-                                 const Duration& interval = Seconds(0.1));
-
-
-// Atomically kill all tasks in a given cgroup. This function will return a
-// future which will become ready when the operation is successfully done. To
-// atomically kill all tasks in a cgroup, it freezes the cgroup, send SIGKILL
-// signal to all tasks in the cgroup, thaw the cgroup, and finally wait for the
-// tasks file to become empty.  The function will return future failure if error
-// occurs. For example, it will return future failure immediately if the given
-// hierarchy or the given cgroup is not valid, or the freezer subsystem is not
-// available or not properly attached to the given hierarchy.
-// @param   hierarchy   Path to the hierarchy root.
-// @param   cgroup      Path to the cgroup relative to the hierarchy root.
-// @param   interval    The time interval between two state check
-//                      requests (default: 0.1 seconds).
-// @return  A future which will become ready when the operation is done.
-//          Error if some unexpected happens.
-process::Future<bool> killTasks(const std::string& hierarchy,
-                                const std::string& cgroup,
-                                const Duration& interval = Seconds(0.1));
+process::Future<bool> thaw(
+    const std::string& hierarchy,
+    const std::string& cgroup,
+    const Duration& interval = Seconds(0.1));
 
 
 // Destroy a cgroup under a given hierarchy. This function is different from
@@ -331,9 +327,10 @@ process::Future<bool> killTasks(const st
 //                      requests (default: 0.1 seconds).
 // @return  A future which will become ready when the operation is done.
 //          Error if some unexpected happens.
-process::Future<bool> destroyCgroup(const std::string& hierarchy,
-                                    const std::string& cgroup = "/",
-                                    const Duration& interval = Seconds(0.1));
+process::Future<bool> destroy(
+    const std::string& hierarchy,
+    const std::string& cgroup = "/",
+    const Duration& interval = Seconds(0.1));
 
 } // namespace cgroups {
 

Modified: incubator/mesos/branches/0.11.0/src/slave/cgroups_isolation_module.cpp
URL: http://svn.apache.org/viewvc/incubator/mesos/branches/0.11.0/src/slave/cgroups_isolation_module.cpp?rev=1413863&r1=1413862&r2=1413863&view=diff
==============================================================================
--- incubator/mesos/branches/0.11.0/src/slave/cgroups_isolation_module.cpp (original)
+++ incubator/mesos/branches/0.11.0/src/slave/cgroups_isolation_module.cpp Mon Nov 26 21:24:04 2012
@@ -30,6 +30,7 @@
 #include <process/defer.hpp>
 #include <process/dispatch.hpp>
 
+#include <stout/exit.hpp>
 #include <stout/foreach.hpp>
 #include <stout/lambda.hpp>
 #include <stout/numify.hpp>
@@ -95,14 +96,12 @@ void CgroupsIsolationModule::initialize(
 
   // Make sure that cgroups is enabled by the kernel.
   if (!cgroups::enabled()) {
-    std::cerr << "No cgroups support detected on this kernel" << std::endl;
-    abort();
+    EXIT(1) << "No cgroups support detected in this kernel";
   }
 
   // Make sure that we have root permissions.
   if (geteuid() != 0) {
-    std::cerr << "Using cgroups requires root permissions" << std::endl;
-    abort();
+    EXIT(1) << "Using cgroups requires root permissions";
   }
 
   // Configure cgroups hierarchy root path.
@@ -122,90 +121,69 @@ void CgroupsIsolationModule::initialize(
   // 'freezer' subsystem in order to destroy a cgroup.
   subsystems.insert("freezer");
 
-  // Make sure that all the desired subsystems are enabled.
-  foreach (const string& subsystem, subsystems) {
-    Try<bool> enabled = cgroups::enabled(subsystem);
-    if (enabled.isError()) {
-      LOG(FATAL) << "Failed to determine if cgroups subsystem '" << subsystem
-                 << "' is enabled by the kernel: " << enabled.error();
-    } else if (!enabled.get()) {
-      LOG(FATAL) << "Desired cgroups subsystem '" << subsystem
-                 << "' is not enabled by the kernel";
+  // Check if the hierarchy is already mounted, and if not, mount it.
+  Try<bool> mounted = cgroups::mounted(hierarchy);
+  if (mounted.isError()) {
+    LOG(FATAL) << "Failed to determine if " << hierarchy
+               << " is already mounted: " << mounted.error();
+  } else if (mounted.get()) {
+    // Make sure that all the desired subsystems are attached to the
+    // already mounted hierarchy.
+    Try<set<string> > attached = cgroups::subsystems(hierarchy);
+    if (attached.isError()) {
+      LOG(FATAL) << "Failed to determine the attached subsystems "
+                 << "for the cgroup hierarchy at " << hierarchy << ": "
+                 << attached.error();
     }
-  }
-
-  // Prepare the cgroups hierarchy root.
-  if (cgroups::checkHierarchy(hierarchy).isError()) {
-    // The given hierarchy is not a cgroups hierarchy root. We will try to
-    // create a cgroups hierarchy root there.
-    if (os::exists(hierarchy)) {
-      // The path specified by the given hierarchy already exists in the file
-      // system. We try to remove it if it is an empty directory. This will
-      // helps us better deal with slave reboots as we don't need to manually
-      // remove the residue directory after a slave reboot.
-      if (::rmdir(hierarchy.c_str()) < 0) {
-        LOG(FATAL) << "Cannot create cgroups hierarchy root at " << hierarchy
-                   << ". Consider removing it";
-      }
-    }
-
-    // Make sure that all the desired subsystems are not busy so that
-    // we can attach them in the given cgroups hierarchy root.
     foreach (const string& subsystem, subsystems) {
-      Try<bool> busy = cgroups::busy(subsystem);
-      if (busy.isError()) {
-        LOG(FATAL) << "Failed to determine if cgroups subsystem '" << subsystem
-                   << "' is already being used by another hierarchy: "
-                   << busy.error();
-      } else if (busy.get()) {
-        LOG(FATAL) << "Required subsystem '" << subsystem
-                   << "' is already in use";
+      if (attached.get().count(subsystem) == 0) {
+        EXIT(1) << "The cgroups hierarchy at " << hierarchy
+                << " can not be used because it does not have the '"
+                << subsystem << "' subsystem attached";
       }
     }
-
-    // Create the cgroups hierarchy root.
-    Try<Nothing> create =
-      cgroups::createHierarchy(hierarchy, strings::join(",", subsystems));
-    if (create.isError()) {
-      LOG(FATAL) << "Failed to create cgroups hierarchy root at "
-                 << hierarchy << ": " << create.error();
-    }
-  }
-
-  // Make sure that all the desired subsystems are attached (we have
-  // to do this since we might just be reusing an already mounted
-  // hierarchy).
-  foreach (const string& subsystem, subsystems) {
-    Try<Nothing> check = cgroups::checkHierarchy(hierarchy, subsystem);
-    if (check.isError()) {
-      LOG(FATAL) << "Failed to determine if cgroups subsystem '" << subsystem
-                 << "' is attached to hierarchy " << hierarchy << ": "
-                 << check.error();
-    } else {
-      // TODO(benh): Update this code to actually check Try<bool> after
-      // checkHierarchy is replaced.
-    }
+  } else {
+    // Attempt to mount the hierarchy ourselves.
+    if (os::exists(hierarchy)) {
+      // The path specified by the given hierarchy already exists in
+      // the file system. We try to remove it if it is an empty
+      // directory. This will helps us better deal with slave restarts
+      // since we won't need to manually remove the directory.
+      Try<Nothing> rmdir = os::rmdir(hierarchy, false);
+      CHECK(rmdir.isSome())
+        << "Failed to mount cgroups hierarchy at " << hierarchy
+        << " because we could not remove existing directory: " << rmdir.error();
+    }
+
+    // Mount the cgroups hierarchy.
+    Try<Nothing> mount = cgroups::mount(
+        hierarchy, strings::join(",", subsystems));
+    CHECK(mount.isSome())
+      << "Failed to mount cgroups hierarchy at "
+      << hierarchy << ": " << mount.error();
   }
 
   // Create the root "mesos" cgroup if it doesn't exist.
-  if (cgroups::checkCgroup(hierarchy, "mesos").isError()) {
+  Try<bool> exists = cgroups::exists(hierarchy, "mesos");
+  CHECK(exists.isSome())
+    << "Failed to determine if the \"mesos\" cgroup already exists "
+    << "in the hierarchy at " << hierarchy << ": " << exists.error();
+  if (!exists.get()) {
     // No root cgroup exists, create it.
-    Try<Nothing> create = cgroups::createCgroup(hierarchy, "mesos");
+    Try<Nothing> create = cgroups::create(hierarchy, "mesos");
     CHECK(create.isSome())
-      << "Failed to create the \"mesos\" cgroup: "
-      << create.error();
+      << "Failed to create the \"mesos\" cgroup: " << create.error();
   }
 
   // Make sure this kernel supports creating nested cgroups.
-  Try<Nothing> create = cgroups::createCgroup(hierarchy, "mesos/test");
+  Try<Nothing> create = cgroups::create(hierarchy, "mesos/test");
   if (create.isError()) {
-    std::cerr << "Failed to create a nested \"test\" cgroup, your kernel "
-              << "might be too old to use the cgroups isolation module: "
-              << create.error() << std::endl;
-    abort();
+    EXIT(1) << "Failed to create a nested \"test\" cgroup. Your kernel "
+            << "might be too old to use the cgroups isolation module: "
+            << create.error();
   }
 
-  Try<Nothing> remove = cgroups::removeCgroup(hierarchy, "mesos/test");
+  Try<Nothing> remove = cgroups::remove(hierarchy, "mesos/test");
   CHECK(remove.isSome())
     << "Failed to remove the nested \"test\" cgroup:" << remove.error();
 
@@ -216,19 +194,17 @@ void CgroupsIsolationModule::initialize(
   Try<Nothing> cloexec = os::cloexec(fd.get());
   CHECK(cloexec.isSome());
   if (flock(fd.get(), LOCK_EX | LOCK_NB) != 0) {
-    std::cerr << "Another mesos-slave appears to be running!" << std::endl;
-    abort();
+    EXIT(1) << "Another mesos-slave appears to be running!";
   }
 
   // Cleanup any orphaned cgroups created in previous executions (this
   // should be safe because we've been able to acquire the file lock).
-  Try<vector<string> > cgroups = cgroups::getCgroups(hierarchy, "mesos");
+  Try<vector<string> > cgroups = cgroups::get(hierarchy, "mesos");
   CHECK(cgroups.isSome())
-    << "Failed to get nested cgroups of \"mesos\": "
-    << cgroups.error();
+    << "Failed to get nested cgroups of \"mesos\": " << cgroups.error();
   foreach (const string& cgroup, cgroups.get()) {
     LOG(INFO) << "Removing orphaned cgroup '" << cgroup << "'";
-    cgroups::destroyCgroup(hierarchy, cgroup)
+    cgroups::destroy(hierarchy, cgroup)
       .onAny(defer(PID<CgroupsIsolationModule>(this),
                    &CgroupsIsolationModule::destroyWaited,
                    cgroup,
@@ -236,20 +212,20 @@ void CgroupsIsolationModule::initialize(
   }
 
   // Make sure the kernel supports OOM controls.
-  Try<Nothing> check =
-    cgroups::checkControl(hierarchy, "mesos", "memory.oom_control");
-  if (check.isError()) {
-    std::cerr << "Failed to find 'memory.oom_control', your kernel "
-              << "might be too old to use the cgroups isolation module: "
-              << check.error() << std::endl;
-    abort();
+  exists = cgroups::exists(hierarchy, "mesos", "memory.oom_control");
+  CHECK(exists.isSome())
+    << "Failed to determine if 'memory.oom_control' control exists: "
+    << exists.error();
+  if (!exists.get()) {
+    EXIT(1) << "Failed to find 'memory.oom_control', your kernel "
+            << "might be too old to use the cgroups isolation module";
   }
 
   // Disable the OOM killer so that we can capture 'memory.stat'.
-  Try<Nothing> disable =
-    cgroups::writeControl(hierarchy, "mesos", "memory.oom_control", "1");
-  CHECK(disable.isSome())
-    << "Failed to disable OOM killer: " << disable.error();
+  Try<Nothing> write = cgroups::write(
+      hierarchy, "mesos", "memory.oom_control", "1");
+  CHECK(write.isSome())
+    << "Failed to disable OOM killer: " << write.error();
 
   // Configure resource changed handlers. We only add handlers for
   // resources that have the appropriate subsystems attached.
@@ -321,7 +297,7 @@ void CgroupsIsolationModule::launchExecu
   }
 
   // Create a new cgroup for the executor.
-  Try<Nothing> create = cgroups::createCgroup(hierarchy, info->name());
+  Try<Nothing> create = cgroups::create(hierarchy, info->name());
   if (create.isError()) {
     LOG(FATAL) << "Failed to create cgroup for executor " << executorId
                << " of framework " << frameworkId
@@ -356,8 +332,7 @@ void CgroupsIsolationModule::launchExecu
   } else {
     // In child process.
     // Put self into the newly created cgroup.
-    Try<Nothing> assign =
-      cgroups::assignTask(hierarchy, info->name(), ::getpid());
+    Try<Nothing> assign = cgroups::assign(hierarchy, info->name(), ::getpid());
     if (assign.isError()) {
       LOG(FATAL) << "Failed to assign for executor " << executorId
                  << " of framework " << frameworkId
@@ -394,7 +369,7 @@ void CgroupsIsolationModule::killExecuto
   // wait for it to succeed as we don't want to block the isolation module.
   // Instead, we register a callback which will be invoked when its result is
   // ready.
-  cgroups::destroyCgroup(hierarchy, info->name())
+  cgroups::destroy(hierarchy, info->name())
     .onAny(defer(PID<CgroupsIsolationModule>(this),
                  &CgroupsIsolationModule::destroyWaited,
                  info->name(),
@@ -479,9 +454,8 @@ Try<Nothing> CgroupsIsolationModule::cpu
   size_t cpuShares =
     std::max((size_t)(CPU_SHARES_PER_CPU * cpus), MIN_CPU_SHARES);
 
-  Try<Nothing> write = cgroups::writeControl(
+  Try<Nothing> write = cgroups::write(
       hierarchy, info->name(), "cpu.shares", stringify(cpuShares));
-
   if (write.isError()) {
     return Try<Nothing>::error(
         "Failed to update 'cpu.shares': " + write.error());
@@ -523,7 +497,7 @@ Try<Nothing> CgroupsIsolationModule::mem
   string control = "memory.limit_in_bytes";
 
   if (info->pid != -1) {
-    Try<string> read = cgroups::readControl(
+    Try<string> read = cgroups::read(
         hierarchy, info->name(), "memory.limit_in_bytes");
     if (read.isError()) {
       return Try<Nothing>::error(
@@ -538,9 +512,8 @@ Try<Nothing> CgroupsIsolationModule::mem
     }
   }
 
-  Try<Nothing> write = cgroups::writeControl(
+  Try<Nothing> write = cgroups::write(
       hierarchy, info->name(), control, stringify(limitInBytes));
-
   if (write.isError()) {
     return Try<Nothing>::error(
         "Failed to update '" + control + "': " + write.error());
@@ -562,7 +535,7 @@ void CgroupsIsolationModule::oomListen(
   CHECK(info != NULL) << "Cgroup info is not registered";
 
   info->oomNotifier =
-    cgroups::listenEvent(hierarchy, info->name(), "memory.oom_control");
+    cgroups::listen(hierarchy, info->name(), "memory.oom_control");
 
   // If the listening fails immediately, something very wrong happened.
   // Therefore, we report a fatal error here.
@@ -643,20 +616,20 @@ void CgroupsIsolationModule::oom(
   // destroyed the executor's cgroup (in order to assist in debugging).
   ostringstream reason;
 
-  Try<string> read =
-    cgroups::readControl(hierarchy, info->name(), "memory.limit_in_bytes");
+  Try<string> read = cgroups::read(
+      hierarchy, info->name(), "memory.limit_in_bytes");
   if (read.isSome()) {
     reason << "MEMORY LIMIT: " << strings::trim(read.get()) << " bytes\n";
   }
 
   // Output 'memory.usage_in_bytes'.
-  read = cgroups::readControl(hierarchy, info->name(), "memory.usage_in_bytes");
+  read = cgroups::read(hierarchy, info->name(), "memory.usage_in_bytes");
   if (read.isSome()) {
     reason << "MEMORY USAGE: " << strings::trim(read.get()) << " bytes\n";
   }
 
   // Output 'memory.stat' of the cgroup to help with debugging.
-  read = cgroups::readControl(hierarchy, info->name(), "memory.stat");
+  read = cgroups::read(hierarchy, info->name(), "memory.stat");
   if (read.isSome()) {
     reason << "MEMORY STATISTICS: \n" << read.get() << "\n";
   }

Modified: incubator/mesos/branches/0.11.0/src/tests/assert.hpp
URL: http://svn.apache.org/viewvc/incubator/mesos/branches/0.11.0/src/tests/assert.hpp?rev=1413863&r1=1413862&r2=1413863&view=diff
==============================================================================
--- incubator/mesos/branches/0.11.0/src/tests/assert.hpp (original)
+++ incubator/mesos/branches/0.11.0/src/tests/assert.hpp Mon Nov 26 21:24:04 2012
@@ -124,6 +124,14 @@ template <typename T1, typename T2>
   EXPECT_PRED_FORMAT2(AssertSomeEq, true, actual)
 
 
+#define ASSERT_SOME_FALSE(actual)                       \
+  ASSERT_PRED_FORMAT2(AssertSomeEq, false, actual)
+
+
+#define EXPECT_SOME_FALSE(actual)                       \
+  EXPECT_PRED_FORMAT2(AssertSomeEq, false, actual)
+
+
 #define ASSERT_ERROR(actual)                    \
   ASSERT_TRUE(actual.isError())
 



Mime
View raw message