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 2013/05/29 19:40:44 UTC

[06/35] Updated libprocess to use '3rdparty' instead of 'third_party'.

http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/bc531d3c/third_party/libprocess/3rdparty/stout/include/stout/format.hpp
----------------------------------------------------------------------
diff --git a/third_party/libprocess/3rdparty/stout/include/stout/format.hpp b/third_party/libprocess/3rdparty/stout/include/stout/format.hpp
new file mode 100644
index 0000000..71b5986
--- /dev/null
+++ b/third_party/libprocess/3rdparty/stout/include/stout/format.hpp
@@ -0,0 +1,343 @@
+#ifndef __STOUT_FORMAT_HPP__
+#define __STOUT_FORMAT_HPP__
+
+#include <stdarg.h> // For 'va_list', 'va_start', 'va_end'.
+#include <stdio.h> // For 'vasprintf'.
+
+#include <string>
+
+#include <tr1/type_traits> // For 'is_pod'.
+
+#include "error.hpp"
+#include "try.hpp"
+#include "stringify.hpp"
+
+
+// The 'strings::format' functions produces strings based on the
+// printf family of functions. Except, unlike the printf family of
+// functions, the 'strings::format' routines attempt to "stringify"
+// any arguments that are not POD types (i.e., "plain old data":
+// primitives, pointers, certain structs/classes and unions,
+// etc). This enables passing structs/classes to 'strings::format'
+// provided there is a definition/specialization of 'ostream::operator
+// <<' available for that type. Note that the '%s' format specifier is
+// expected for each argument that gets stringified. A specialization
+// for std::string is also provided so that std::string::c_str is not
+// necessary (but again, '%s' is expected as the format specifier).
+
+namespace strings {
+namespace internal {
+
+Try<std::string> format(const std::string& fmt, va_list args);
+Try<std::string> format(const std::string& fmt, ...);
+
+template <typename T, bool b>
+struct stringify;
+
+} // namespace internal {
+
+
+#if __cplusplus >= 201103L
+template <typename ...T>
+Try<std::string> format(const std::string& s, const T& ...t)
+{
+  return internal::format(
+      s,
+      internal::stringify<T, !std::is_pod<T>::value>(t).get()...);
+}
+#else
+template <typename T1>
+Try<std::string> format(const std::string& s,
+                        const T1& t1)
+{
+  return internal::format(
+      s,
+      internal::stringify<T1, !std::tr1::is_pod<T1>::value>(t1).get());
+}
+
+
+template <typename T1,
+          typename T2>
+Try<std::string> format(const std::string& s,
+                        const T1& t1,
+                        const T2& t2)
+{
+  return internal::format(
+      s,
+      internal::stringify<T1, !std::tr1::is_pod<T1>::value>(t1).get(),
+      internal::stringify<T2, !std::tr1::is_pod<T1>::value>(t2).get());
+}
+
+
+template <typename T1,
+          typename T2,
+          typename T3>
+Try<std::string> format(const std::string& s,
+                        const T1& t1,
+                        const T2& t2,
+                        const T3& t3)
+{
+  return internal::format(
+      s,
+      internal::stringify<T1, !std::tr1::is_pod<T1>::value>(t1).get(),
+      internal::stringify<T2, !std::tr1::is_pod<T2>::value>(t2).get(),
+      internal::stringify<T3, !std::tr1::is_pod<T3>::value>(t3).get());
+}
+
+
+template <typename T1,
+          typename T2,
+          typename T3,
+          typename T4>
+Try<std::string> format(const std::string& s,
+                        const T1& t1,
+                        const T2& t2,
+                        const T3& t3,
+                        const T4& t4)
+{
+  return internal::format(
+      s,
+      internal::stringify<T1, !std::tr1::is_pod<T1>::value>(t1).get(),
+      internal::stringify<T2, !std::tr1::is_pod<T2>::value>(t2).get(),
+      internal::stringify<T3, !std::tr1::is_pod<T3>::value>(t3).get(),
+      internal::stringify<T4, !std::tr1::is_pod<T4>::value>(t4).get());
+}
+
+
+template <typename T1,
+          typename T2,
+          typename T3,
+          typename T4,
+          typename T5>
+Try<std::string> format(const std::string& s,
+                        const T1& t1,
+                        const T2& t2,
+                        const T3& t3,
+                        const T4& t4,
+                        const T5& t5)
+{
+  return internal::format(
+      s,
+      internal::stringify<T1, !std::tr1::is_pod<T1>::value>(t1).get(),
+      internal::stringify<T2, !std::tr1::is_pod<T2>::value>(t2).get(),
+      internal::stringify<T3, !std::tr1::is_pod<T3>::value>(t3).get(),
+      internal::stringify<T4, !std::tr1::is_pod<T4>::value>(t4).get(),
+      internal::stringify<T5, !std::tr1::is_pod<T5>::value>(t5).get());
+}
+
+
+template <typename T1,
+          typename T2,
+          typename T3,
+          typename T4,
+          typename T5,
+          typename T6>
+Try<std::string> format(const std::string& s,
+                        const T1& t1,
+                        const T2& t2,
+                        const T3& t3,
+                        const T4& t4,
+                        const T5& t5,
+                        const T6& t6)
+{
+  return internal::format(
+      s,
+      internal::stringify<T1, !std::tr1::is_pod<T1>::value>(t1).get(),
+      internal::stringify<T2, !std::tr1::is_pod<T2>::value>(t2).get(),
+      internal::stringify<T3, !std::tr1::is_pod<T3>::value>(t3).get(),
+      internal::stringify<T4, !std::tr1::is_pod<T4>::value>(t4).get(),
+      internal::stringify<T5, !std::tr1::is_pod<T5>::value>(t5).get(),
+      internal::stringify<T6, !std::tr1::is_pod<T6>::value>(t6).get());
+}
+
+
+template <typename T1,
+          typename T2,
+          typename T3,
+          typename T4,
+          typename T5,
+          typename T6,
+          typename T7>
+Try<std::string> format(const std::string& s,
+                        const T1& t1,
+                        const T2& t2,
+                        const T3& t3,
+                        const T4& t4,
+                        const T5& t5,
+                        const T6& t6,
+                        const T7& t7)
+{
+  return internal::format(
+      s,
+      internal::stringify<T1, !std::tr1::is_pod<T1>::value>(t1).get(),
+      internal::stringify<T2, !std::tr1::is_pod<T2>::value>(t2).get(),
+      internal::stringify<T3, !std::tr1::is_pod<T3>::value>(t3).get(),
+      internal::stringify<T4, !std::tr1::is_pod<T4>::value>(t4).get(),
+      internal::stringify<T5, !std::tr1::is_pod<T5>::value>(t5).get(),
+      internal::stringify<T6, !std::tr1::is_pod<T6>::value>(t6).get(),
+      internal::stringify<T7, !std::tr1::is_pod<T7>::value>(t7).get());
+}
+
+
+template <typename T1,
+          typename T2,
+          typename T3,
+          typename T4,
+          typename T5,
+          typename T6,
+          typename T7,
+          typename T8>
+Try<std::string> format(const std::string& s,
+                        const T1& t1,
+                        const T2& t2,
+                        const T3& t3,
+                        const T4& t4,
+                        const T5& t5,
+                        const T6& t6,
+                        const T7& t7,
+                        const T8& t8)
+{
+  return internal::format(
+      s,
+      internal::stringify<T1, !std::tr1::is_pod<T1>::value>(t1).get(),
+      internal::stringify<T2, !std::tr1::is_pod<T2>::value>(t2).get(),
+      internal::stringify<T3, !std::tr1::is_pod<T3>::value>(t3).get(),
+      internal::stringify<T4, !std::tr1::is_pod<T4>::value>(t4).get(),
+      internal::stringify<T5, !std::tr1::is_pod<T5>::value>(t5).get(),
+      internal::stringify<T6, !std::tr1::is_pod<T6>::value>(t6).get(),
+      internal::stringify<T7, !std::tr1::is_pod<T7>::value>(t7).get(),
+      internal::stringify<T8, !std::tr1::is_pod<T8>::value>(t8).get());
+}
+
+
+template <typename T1,
+          typename T2,
+          typename T3,
+          typename T4,
+          typename T5,
+          typename T6,
+          typename T7,
+          typename T8,
+          typename T9>
+Try<std::string> format(const std::string& s,
+                        const T1& t1,
+                        const T2& t2,
+                        const T3& t3,
+                        const T4& t4,
+                        const T5& t5,
+                        const T6& t6,
+                        const T7& t7,
+                        const T8& t8,
+                        const T9& t9)
+{
+  return internal::format(
+      s,
+      internal::stringify<T1, !std::tr1::is_pod<T1>::value>(t1).get(),
+      internal::stringify<T2, !std::tr1::is_pod<T2>::value>(t2).get(),
+      internal::stringify<T3, !std::tr1::is_pod<T3>::value>(t3).get(),
+      internal::stringify<T4, !std::tr1::is_pod<T4>::value>(t4).get(),
+      internal::stringify<T5, !std::tr1::is_pod<T5>::value>(t5).get(),
+      internal::stringify<T6, !std::tr1::is_pod<T6>::value>(t6).get(),
+      internal::stringify<T7, !std::tr1::is_pod<T7>::value>(t7).get(),
+      internal::stringify<T8, !std::tr1::is_pod<T8>::value>(t8).get(),
+      internal::stringify<T9, !std::tr1::is_pod<T9>::value>(t9).get());
+}
+
+
+template <typename T1,
+          typename T2,
+          typename T3,
+          typename T4,
+          typename T5,
+          typename T6,
+          typename T7,
+          typename T8,
+          typename T9,
+          typename T10>
+Try<std::string> format(const std::string& s,
+                        const T1& t1,
+                        const T2& t2,
+                        const T3& t3,
+                        const T4& t4,
+                        const T5& t5,
+                        const T6& t6,
+                        const T7& t7,
+                        const T8& t8,
+                        const T9& t9,
+                        const T10& t10)
+{
+  return internal::format(
+      s,
+      internal::stringify<T1, !std::tr1::is_pod<T1>::value>(t1).get(),
+      internal::stringify<T2, !std::tr1::is_pod<T2>::value>(t2).get(),
+      internal::stringify<T3, !std::tr1::is_pod<T3>::value>(t3).get(),
+      internal::stringify<T4, !std::tr1::is_pod<T4>::value>(t4).get(),
+      internal::stringify<T5, !std::tr1::is_pod<T5>::value>(t5).get(),
+      internal::stringify<T6, !std::tr1::is_pod<T6>::value>(t6).get(),
+      internal::stringify<T7, !std::tr1::is_pod<T7>::value>(t7).get(),
+      internal::stringify<T8, !std::tr1::is_pod<T8>::value>(t8).get(),
+      internal::stringify<T9, !std::tr1::is_pod<T9>::value>(t9).get(),
+      internal::stringify<T10, !std::tr1::is_pod<T10>::value>(t10).get());
+}
+#endif // __cplusplus >= 201103L
+
+
+namespace internal {
+
+inline Try<std::string> format(const std::string& fmt, va_list args)
+{
+  char* temp;
+  if (vasprintf(&temp, fmt.c_str(), args) == -1) {
+    // Note that temp is undefined, so we do not need to call free.
+    return Error("Failed to format '" + fmt + "' (possibly out of memory)");
+  }
+  std::string result(temp);
+  free(temp);
+  return result;
+}
+
+
+inline Try<std::string> format(const std::string& fmt, ...)
+{
+  va_list args;
+  va_start(args, fmt);
+  const Try<std::string>& result = format(fmt, args);
+  va_end(args);
+  return result;
+}
+
+
+template <typename T>
+struct stringify<T, false>
+{
+  stringify(const T& _t) : t(_t) {}
+  const T& get() { return t; }
+  const T& t;
+};
+
+
+template <typename T>
+struct stringify<T, true>
+{
+  stringify(const T& _t) : s(::stringify(_t)) {}
+  const char* get() { return s.c_str(); }
+
+  // NOTE: We need to do the copy here, because the temporary returned by
+  // ::stringify() doesn't outlive the get() call inside strings::format().
+  // TODO(vinod): Figure out a fix for using const ref here.
+  const std::string s;
+};
+
+
+template <>
+struct stringify<std::string, true>
+{
+  stringify(const std::string& _s) : s(_s) {}
+  const char* get() { return s.c_str(); }
+  const std::string& s;
+};
+
+} // namespace internal {
+} // namespace strings {
+
+#endif // __STOUT_FORMAT_HPP__

http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/bc531d3c/third_party/libprocess/3rdparty/stout/include/stout/fs.hpp
----------------------------------------------------------------------
diff --git a/third_party/libprocess/3rdparty/stout/include/stout/fs.hpp b/third_party/libprocess/3rdparty/stout/include/stout/fs.hpp
new file mode 100644
index 0000000..c1a05b5
--- /dev/null
+++ b/third_party/libprocess/3rdparty/stout/include/stout/fs.hpp
@@ -0,0 +1,53 @@
+#ifndef __STOUT_FS_HPP__
+#define __STOUT_FS_HPP__
+
+#include <unistd.h> // For symlink.
+
+#include <sys/statvfs.h>
+
+#include <string>
+
+#include "bytes.hpp"
+#include "error.hpp"
+#include "nothing.hpp"
+#include "try.hpp"
+
+// TODO(bmahler): Migrate the appropriate 'os' namespace funtions here.
+namespace fs {
+
+// Returns the total available disk size in bytes.
+inline Try<Bytes> available(const std::string& path = "/")
+{
+  struct statvfs buf;
+  if (::statvfs(path.c_str(), &buf) < 0) {
+    return ErrnoError();
+  }
+  return Bytes(buf.f_bavail * buf.f_frsize);
+}
+
+
+// Returns relative disk usage of the file system that the given path
+// is mounted at.
+inline Try<double> usage(const std::string& path = "/")
+{
+  struct statvfs buf;
+  if (statvfs(path.c_str(), &buf) < 0) {
+    return ErrnoError("Error invoking statvfs on '" + path + "'");
+  }
+  return (double) (buf.f_blocks - buf.f_bfree) / buf.f_blocks;
+}
+
+
+inline Try<Nothing> symlink(
+    const std::string& original,
+    const std::string& link)
+{
+  if (::symlink(original.c_str(), link.c_str()) < 0) {
+    return ErrnoError();
+  }
+  return Nothing();
+}
+
+} // namespace fs {
+
+#endif // __STOUT_FS_HPP__

http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/bc531d3c/third_party/libprocess/3rdparty/stout/include/stout/gtest.hpp
----------------------------------------------------------------------
diff --git a/third_party/libprocess/3rdparty/stout/include/stout/gtest.hpp b/third_party/libprocess/3rdparty/stout/include/stout/gtest.hpp
new file mode 100644
index 0000000..3c34124
--- /dev/null
+++ b/third_party/libprocess/3rdparty/stout/include/stout/gtest.hpp
@@ -0,0 +1,122 @@
+#ifndef __STOUT_GTEST_HPP__
+#define __STOUT_GTEST_HPP__
+
+#include <gtest/gtest.h>
+
+#include <string>
+
+#include <stout/option.hpp>
+#include <stout/result.hpp>
+#include <stout/try.hpp>
+
+
+template <typename T>
+::testing::AssertionResult AssertSome(
+    const char* expr,
+    const Option<T>& actual)
+{
+  if (actual.isNone()) {
+    return ::testing::AssertionFailure()
+      << expr << " is NONE";
+  }
+
+  return ::testing::AssertionSuccess();
+}
+
+
+template <typename T>
+::testing::AssertionResult AssertSome(
+    const char* expr,
+    const Try<T>& actual)
+{
+  if (actual.isError()) {
+    return ::testing::AssertionFailure()
+      << expr << ": " << actual.error();
+  }
+
+  return ::testing::AssertionSuccess();
+}
+
+
+template <typename T>
+::testing::AssertionResult AssertSome(
+    const char* expr,
+    const Result<T>& actual)
+{
+  if (actual.isNone()) {
+    return ::testing::AssertionFailure()
+      << expr << " is NONE";
+  } else if (actual.isError()) {
+    return ::testing::AssertionFailure()
+      << expr << ": " << actual.error();
+  }
+
+  return ::testing::AssertionSuccess();
+}
+
+
+template <typename T1, typename T2>
+::testing::AssertionResult AssertSomeEq(
+    const char* expectedExpr,
+    const char* actualExpr,
+    const T1& expected,
+    const T2& actual) // Duck typing!
+{
+  const ::testing::AssertionResult result = AssertSome(actualExpr, actual);
+
+  if (result) {
+    if (expected == actual.get()) {
+      return ::testing::AssertionSuccess();
+    } else {
+      return ::testing::AssertionFailure()
+        << "Value of: (" << actualExpr << ").get()\n"
+        << "  Actual: " << ::testing::PrintToString(actual.get()) << "\n"
+        << "Expected: " << expectedExpr << "\n"
+        << "Which is: " << ::testing::PrintToString(expected);
+    }
+  }
+
+  return result;
+}
+
+
+#define ASSERT_SOME(actual)                     \
+  ASSERT_PRED_FORMAT1(AssertSome, actual)
+
+
+#define EXPECT_SOME(actual)                     \
+  EXPECT_PRED_FORMAT1(AssertSome, actual)
+
+
+#define ASSERT_SOME_EQ(expected, actual)                \
+  ASSERT_PRED_FORMAT2(AssertSomeEq, expected, actual)
+
+
+#define EXPECT_SOME_EQ(expected, actual)                \
+  EXPECT_PRED_FORMAT2(AssertSomeEq, expected, actual)
+
+
+#define ASSERT_SOME_TRUE(actual)                        \
+  ASSERT_PRED_FORMAT2(AssertSomeEq, true, actual)
+
+
+#define EXPECT_SOME_TRUE(actual)                        \
+  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())
+
+
+#define EXPECT_ERROR(actual)                    \
+  EXPECT_TRUE(actual.isError())
+
+#endif // __STOUT_GTEST_HPP__

http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/bc531d3c/third_party/libprocess/3rdparty/stout/include/stout/gzip.hpp
----------------------------------------------------------------------
diff --git a/third_party/libprocess/3rdparty/stout/include/stout/gzip.hpp b/third_party/libprocess/3rdparty/stout/include/stout/gzip.hpp
new file mode 100644
index 0000000..ef36f1b
--- /dev/null
+++ b/third_party/libprocess/3rdparty/stout/include/stout/gzip.hpp
@@ -0,0 +1,149 @@
+#ifndef __STOUT_GZIP_HPP__
+#define __STOUT_GZIP_HPP__
+
+#ifdef HAVE_LIBZ
+#include <zlib.h>
+#endif
+
+#include <string>
+
+#include "error.hpp"
+#include "try.hpp"
+
+// Compression utilities.
+// TODO(bmahler): Provide streaming compression / decompression as well.
+namespace gzip {
+
+// We use a 16KB buffer with zlib compression / decompression.
+#define GZIP_BUFFER_SIZE 16384
+
+// Returns a gzip compressed version of the provided string.
+// The compression level should be within the range [-1, 9].
+// See zlib.h:
+//   #define Z_NO_COMPRESSION         0
+//   #define Z_BEST_SPEED             1
+//   #define Z_BEST_COMPRESSION       9
+//   #define Z_DEFAULT_COMPRESSION  (-1)
+inline Try<std::string> compress(
+    const std::string& decompressed,
+#ifdef HAVE_LIBZ
+    int level = Z_DEFAULT_COMPRESSION)
+#else
+    int level = -1)
+#endif
+{
+#ifndef HAVE_LIBZ
+  return Error("libz is not available");
+#else
+  // Verify the level is within range.
+  if (!(level == Z_DEFAULT_COMPRESSION ||
+      (level >= Z_NO_COMPRESSION && level <= Z_BEST_COMPRESSION))) {
+    return Error("Invalid compression level: " + level);
+  }
+
+  z_stream_s stream;
+  stream.next_in =
+    const_cast<Bytef*>(reinterpret_cast<const Bytef*>(decompressed.data()));
+  stream.avail_in = decompressed.length();
+  stream.zalloc = Z_NULL;
+  stream.zfree = Z_NULL;
+  stream.opaque = Z_NULL;
+
+  int code = deflateInit2(
+      &stream,
+      level,          // Compression level.
+      Z_DEFLATED,     // Compression method.
+      MAX_WBITS + 16, // Zlib magic for gzip compression / decompression.
+      8,              // Default memLevel value.
+      Z_DEFAULT_STRATEGY);
+
+  if (code != Z_OK) {
+    return Error("Failed to initialize zlib: " + std::string(stream.msg));
+  }
+
+  // Build up the compressed result.
+  Bytef buffer[GZIP_BUFFER_SIZE];
+  std::string result = "";
+  do {
+    stream.next_out = buffer;
+    stream.avail_out = GZIP_BUFFER_SIZE;
+    code = deflate(&stream, stream.avail_in > 0 ? Z_NO_FLUSH : Z_FINISH);
+
+    if (code != Z_OK && code != Z_STREAM_END) {
+      Error error(std::string(stream.msg));
+      deflateEnd(&stream);
+      return error;
+    }
+
+    // Consume output and reset the buffer.
+    result.append(
+        reinterpret_cast<char*>(buffer),
+        GZIP_BUFFER_SIZE - stream.avail_out);
+    stream.next_out = buffer;
+    stream.avail_out = GZIP_BUFFER_SIZE;
+  } while (code != Z_STREAM_END);
+
+  code = deflateEnd(&stream);
+  if (code != Z_OK) {
+    return Error("Failed to clean up zlib: " + std::string(stream.msg));
+  }
+  return result;
+#endif // HAVE_LIBZ
+}
+
+
+// Returns a gzip decompressed version of the provided string.
+inline Try<std::string> decompress(const std::string& compressed)
+{
+#ifndef HAVE_LIBZ
+  return Error("libz is not available");
+#else
+  z_stream_s stream;
+  stream.next_in =
+    const_cast<Bytef*>(reinterpret_cast<const Bytef*>(compressed.data()));
+  stream.avail_in = compressed.length();
+  stream.zalloc = Z_NULL;
+  stream.zfree = Z_NULL;
+  stream.opaque = Z_NULL;
+
+  int code = inflateInit2(
+      &stream,
+      MAX_WBITS + 16); // Zlib magic for gzip compression / decompression.
+
+  if (code != Z_OK) {
+    return Error("Failed to initialize zlib: " + std::string(stream.msg));
+  }
+
+  // Build up the decompressed result.
+  Bytef buffer[GZIP_BUFFER_SIZE];
+  std::string result = "";
+  do {
+    stream.next_out = buffer;
+    stream.avail_out = GZIP_BUFFER_SIZE;
+    code = inflate(&stream, stream.avail_in > 0 ? Z_NO_FLUSH : Z_FINISH);
+
+    if (code != Z_OK && code != Z_STREAM_END) {
+      Error error(std::string(stream.msg));
+      inflateEnd(&stream);
+      return error;
+    }
+
+    // Consume output and reset the buffer.
+    result.append(
+        reinterpret_cast<char*>(buffer),
+        GZIP_BUFFER_SIZE - stream.avail_out);
+    stream.next_out = buffer;
+    stream.avail_out = GZIP_BUFFER_SIZE;
+  } while (code != Z_STREAM_END);
+
+  code = inflateEnd(&stream);
+  if (code != Z_OK) {
+    return Error("Failed to clean up zlib: " + std::string(stream.msg));
+  }
+  return result;
+#endif // HAVE_LIBZ
+}
+
+} // namespace gzip {
+
+#endif // __STOUT_GZIP_HPP__

http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/bc531d3c/third_party/libprocess/3rdparty/stout/include/stout/hashmap.hpp
----------------------------------------------------------------------
diff --git a/third_party/libprocess/3rdparty/stout/include/stout/hashmap.hpp b/third_party/libprocess/3rdparty/stout/include/stout/hashmap.hpp
new file mode 100644
index 0000000..796cb50
--- /dev/null
+++ b/third_party/libprocess/3rdparty/stout/include/stout/hashmap.hpp
@@ -0,0 +1,102 @@
+#ifndef __STOUT_HASHMAP_HPP__
+#define __STOUT_HASHMAP_HPP__
+
+#include <boost/get_pointer.hpp>
+#include <boost/unordered_map.hpp>
+
+#include "hashset.hpp"
+#include "foreach.hpp"
+#include "none.hpp"
+#include "option.hpp"
+
+
+// Provides a hash map via Boost's 'unordered_map'. For most intensive
+// purposes this could be accomplished with a templated typedef, but
+// those don't exist (until C++-11). Also, doing it this way allows us
+// to add functionality, or better naming of existing functionality,
+// etc.
+
+template <typename Key, typename Value>
+class hashmap : public boost::unordered_map<Key, Value>
+{
+public:
+  // An explicit default constructor is needed so
+  // 'const hashmap<T> map;' is not an error.
+  hashmap() {}
+
+  // Checks whether this map contains a binding for a key.
+  bool contains(const Key& key) const
+  {
+    return boost::unordered_map<Key, Value>::count(key) > 0;
+  }
+
+  // Checks whether there exists a bound value in this map.
+  bool containsValue(const Value& v) const
+  {
+    foreachvalue (const Value& value, *this) {
+      if (value == v) {
+        return true;
+      }
+    }
+  }
+
+  // Returns an Option for the binding to the key.
+  Option<Value> get(const Key& key) const
+  {
+    typedef typename boost::unordered_map<Key, Value>::const_iterator
+        const_iterator;
+    const_iterator it = boost::unordered_map<Key, Value>::find(key);
+    if (it == boost::unordered_map<Key, Value>::end()) {
+      return None();
+    }
+    return it->second;
+  }
+
+  // Returns the set of keys in this map.
+  hashset<Key> keys() const
+  {
+    hashset<Key> result;
+    foreachkey (const Key& key, *this) {
+      result.insert(key);
+    }
+    return result;
+  }
+
+  // Returns the set of values in this map.
+  hashset<Value> values() const
+  {
+    hashset<Value> result;
+    foreachvalue (const Value& value, *this) {
+      result.insert(value);
+    }
+    return result;
+  }
+
+  // Checks whether there exists a value in this map that returns the
+  // a result equal to 'r' when the specified method is invoked.
+  template <typename R, typename T>
+  bool existsValue(R (T::*method)(), R r) const
+  {
+    foreachvalue (const Value& value, *this) {
+      const T* t = boost::get_pointer(value);
+      if (t->*method() == r) {
+        return true;
+      }
+    }
+  }
+
+  // Checks whether there exists a value in this map whose specified
+  // member is equal to 'r'.
+  template <typename R, typename T>
+  bool existsValue(R (T::*member), R r) const
+  {
+    foreachvalue (const Value& value, *this) {
+      const T* t = boost::get_pointer(value);
+      if (t->*member == r) {
+        return true;
+      }
+    }
+  }
+};
+
+#endif // __STOUT_HASHMAP_HPP__

http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/bc531d3c/third_party/libprocess/3rdparty/stout/include/stout/hashset.hpp
----------------------------------------------------------------------
diff --git a/third_party/libprocess/3rdparty/stout/include/stout/hashset.hpp b/third_party/libprocess/3rdparty/stout/include/stout/hashset.hpp
new file mode 100644
index 0000000..f584545
--- /dev/null
+++ b/third_party/libprocess/3rdparty/stout/include/stout/hashset.hpp
@@ -0,0 +1,57 @@
+#ifndef __STOUT_HASHSET_HPP__
+#define __STOUT_HASHSET_HPP__
+
+#include <boost/get_pointer.hpp>
+#include <boost/unordered_set.hpp>
+
+#include "foreach.hpp"
+
+
+// Provides a hash set via Boost's 'unordered_set'. For most intensive
+// purposes this could be accomplished with a templated typedef, but
+// those don't exist (until C++-11). Also, doing it this way allows us
+// to add functionality, or better naming of existing functionality,
+// etc.
+
+template <typename Elem>
+class hashset : public boost::unordered_set<Elem>
+{
+public:
+  // An explicit default constructor is needed so
+  // 'const hashset<T> map;' is not an error.
+  hashset() {}
+
+  // Checks whether this map contains a binding for a key.
+  bool contains(const Elem& elem) const
+  {
+    return boost::unordered_set<Elem>::count(elem) > 0;
+  }
+
+  // Checks whether there exists a value in this set that returns the
+  // a result equal to 'r' when the specified method is invoked.
+  template <typename R, typename T>
+  bool exists(R (T::*method)(), R r) const
+  {
+    foreach (const Elem& elem, *this) {
+      const T* t = boost::get_pointer(elem);
+      if (t->*method() == r) {
+        return true;
+      }
+    }
+  }
+
+  // Checks whether there exists an element in this set whose
+  // specified member is equal to 'r'.
+  template <typename R, typename T>
+  bool exists(R (T::*member), R r) const
+  {
+    foreach (const Elem& elem, *this) {
+      const T* t = boost::get_pointer(elem);
+      if (t->*member == r) {
+        return true;
+      }
+    }
+  }
+};
+
+#endif // __STOUT_HASHSET_HPP__

http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/bc531d3c/third_party/libprocess/3rdparty/stout/include/stout/json.hpp
----------------------------------------------------------------------
diff --git a/third_party/libprocess/3rdparty/stout/include/stout/json.hpp b/third_party/libprocess/3rdparty/stout/include/stout/json.hpp
new file mode 100644
index 0000000..e2cd4f2
--- /dev/null
+++ b/third_party/libprocess/3rdparty/stout/include/stout/json.hpp
@@ -0,0 +1,202 @@
+#ifndef __STOUT_JSON__
+#define __STOUT_JSON__
+
+#include <iomanip>
+#include <iostream>
+#include <list>
+#include <map>
+#include <string>
+
+#include <boost/variant.hpp>
+
+#include <stout/foreach.hpp>
+
+// TODO(jsirois): Implement parsing that constructs JSON objects.
+
+
+namespace JSON {
+
+// Implementation of the JavaScript Object Notation (JSON) grammar
+// using boost::variant. We explicitly define each "type" of the
+// grammar, including 'true' (json::True), 'false' (json::False), and
+// 'null' (json::Null), for clarity and also because boost::variant
+// "picks" the wrong type when we try and use std::string, long (or
+// int), double (or float), and bool all in the same variant (while it
+// does work with explicit casts, it seemed bad style to force people
+// to put those casts in place). We could have avoided using
+// json::String or json::Number and just used std::string and double
+// respectively, but we choose to include them for completeness
+// (although, this does pay a 2x cost when compiling thanks to all the
+// extra template instantiations).
+
+struct String;
+struct Number;
+struct Object;
+struct Array;
+struct True;
+struct False;
+struct Null;
+
+
+typedef boost::variant<boost::recursive_wrapper<String>,
+                       boost::recursive_wrapper<Number>,
+                       boost::recursive_wrapper<Object>,
+                       boost::recursive_wrapper<Array>,
+                       boost::recursive_wrapper<True>,
+                       boost::recursive_wrapper<False>,
+                       boost::recursive_wrapper<Null> > Value;
+
+
+struct String
+{
+  String() {}
+  String(const char* _value) : value(_value) {}
+  String(const std::string& _value) : value(_value) {}
+  std::string value;
+};
+
+
+struct Number
+{
+  Number() {}
+  Number(double _value) : value(_value) {}
+  double value;
+};
+
+
+struct Object
+{
+  std::map<std::string, Value> values;
+};
+
+
+struct Array
+{
+  std::list<Value> values;
+};
+
+
+struct True {};
+
+
+struct False {};
+
+
+struct Null {};
+
+
+// Implementation of rendering JSON objects built above using standard
+// C++ output streams. The visitor pattern is used thanks to to build
+// a "renderer" with boost::static_visitor and two top-level render
+// routines are provided for rendering JSON objects and arrays.
+
+struct Renderer : boost::static_visitor<>
+{
+  Renderer(std::ostream& _out) : out(_out) {}
+
+  void operator () (const String& string) const
+  {
+    // TODO(benh): This escaping DOES NOT handle unicode, it encodes as ASCII.
+    // See RFC4627 for the JSON string specificiation.
+    out << "\"";
+    foreach (unsigned char c, string.value) {
+      switch (c) {
+        case '"':  out << "\\\""; break;
+        case '\\': out << "\\\\"; break;
+        case '/':  out << "\\/";  break;
+        case '\b': out << "\\b";  break;
+        case '\f': out << "\\f";  break;
+        case '\n': out << "\\n";  break;
+        case '\r': out << "\\r";  break;
+        case '\t': out << "\\t";  break;
+        default:
+          // See RFC4627 for these ranges.
+          if ((c >= 0x20 && c <= 0x21) ||
+              (c >= 0x23 && c <= 0x5B) ||
+              (c >= 0x5D && c < 0x7F)) {
+            out << c;
+          } else {
+            // NOTE: We also escape all bytes > 0x7F since they imply more than
+            // 1 byte in UTF-8. This is why we don't escape UTF-8 properly.
+            // See RFC4627 for the escaping format: \uXXXX (X is a hex digit).
+            // Each byte here will be of the form: \u00XX (this is why we need
+            // setw and the cast to unsigned int).
+            out << "\\u" << std::setfill('0') << std::setw(4)
+                << std::hex << std::uppercase << (unsigned int) c;
+          }
+          break;
+      }
+    }
+    out << "\"";
+  }
+
+  void operator () (const Number& number) const
+  {
+    out.precision(10);
+    out << number.value;
+  }
+
+  void operator () (const Object& object) const
+  {
+    out << "{";
+    std::map<std::string, Value>::const_iterator iterator;
+    iterator = object.values.begin();
+    while (iterator != object.values.end()) {
+      out << "\"" << (*iterator).first << "\":";
+      boost::apply_visitor(Renderer(out), (*iterator).second);
+      if (++iterator != object.values.end()) {
+        out << ",";
+      }
+    }
+    out << "}";
+  }
+
+  void operator () (const Array& array) const
+  {
+    out << "[";
+    std::list<Value>::const_iterator iterator;
+    iterator = array.values.begin();
+    while (iterator != array.values.end()) {
+      boost::apply_visitor(Renderer(out), *iterator);
+      if (++iterator != array.values.end()) {
+        out << ",";
+      }
+    }
+    out << "]";
+  }
+
+  void operator () (const True&) const
+  {
+    out << "true";
+  }
+
+  void operator () (const False&) const
+  {
+    out << "false";
+  }
+
+  void operator () (const Null&) const
+  {
+    out << "null";
+  }
+
+private:
+  std::ostream& out;
+};
+
+
+inline void render(std::ostream& out, const Value& value)
+{
+  boost::apply_visitor(Renderer(out), value);
+}
+
+
+inline std::ostream& operator<<(std::ostream& out, const JSON::Value& value)
+{
+  JSON::render(out, value);
+  return out;
+}
+
+} // namespace JSON {
+
+#endif // __STOUT_JSON__

http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/bc531d3c/third_party/libprocess/3rdparty/stout/include/stout/lambda.hpp
----------------------------------------------------------------------
diff --git a/third_party/libprocess/3rdparty/stout/include/stout/lambda.hpp b/third_party/libprocess/3rdparty/stout/include/stout/lambda.hpp
new file mode 100644
index 0000000..d493353
--- /dev/null
+++ b/third_party/libprocess/3rdparty/stout/include/stout/lambda.hpp
@@ -0,0 +1,14 @@
+#ifndef __STOUT_LAMBDA_HPP__
+#define __STOUT_LAMBDA_HPP__
+
+#include <tr1/functional>
+
+namespace lambda {
+
+using std::tr1::bind;
+using std::tr1::function;
+using namespace std::tr1::placeholders;
+
+} // namespace lambda {
+
+#endif // __STOUT_LAMBDA_HPP__

http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/bc531d3c/third_party/libprocess/3rdparty/stout/include/stout/multihashmap.hpp
----------------------------------------------------------------------
diff --git a/third_party/libprocess/3rdparty/stout/include/stout/multihashmap.hpp b/third_party/libprocess/3rdparty/stout/include/stout/multihashmap.hpp
new file mode 100644
index 0000000..10e49dc
--- /dev/null
+++ b/third_party/libprocess/3rdparty/stout/include/stout/multihashmap.hpp
@@ -0,0 +1,109 @@
+#ifndef __STOUT_MULTIHASHMAP_HPP__
+#define __STOUT_MULTIHASHMAP_HPP__
+
+#include <algorithm> // For find.
+#include <list>
+#include <set>
+#include <utility>
+
+#include <boost/unordered_map.hpp>
+
+
+// Implementation of a hash multimap via Boost's 'unordered_multimap'
+// but with a better interface. The rationale for creating this is
+// that the std::multimap interface is painful to use (requires lots
+// of iterator garbage, as well as the use of 'equal_range' which
+// makes for cluttered code).
+template <typename K, typename V>
+class multihashmap : public boost::unordered_multimap<K, V>
+{
+public:
+  void put(const K& key, const V& value);
+  std::list<V> get(const K& key) const;
+  std::set<K> keys() const;
+  bool remove(const K& key);
+  bool remove(const K& key, const V& value);
+  bool contains(const K& key) const;
+  bool contains(const K& key, const V& value) const;
+};
+
+
+template <typename K, typename V>
+void multihashmap<K, V>::put(const K& key, const V& value)
+{
+  boost::unordered_multimap<K, V>::insert(std::pair<K, V>(key, value));
+}
+
+
+template <typename K, typename V>
+std::list<V> multihashmap<K, V>::get(const K& key) const
+{
+  std::list<V> values; // Values to return.
+
+  std::pair<typename boost::unordered_multimap<K, V>::const_iterator,
+    typename boost::unordered_multimap<K, V>::const_iterator> range;
+
+  range = boost::unordered_multimap<K, V>::equal_range(key);
+
+  typename boost::unordered_multimap<K, V>::const_iterator i;
+  for (i = range.first; i != range.second; ++i) {
+    values.push_back(i->second);
+  }
+
+  return values;
+}
+
+
+template <typename K, typename V>
+std::set<K> multihashmap<K, V>::keys() const
+{
+  std::set<K> keys;
+  foreachkey (const K& key, *this) {
+    keys.insert(key);
+  }
+  return keys;
+}
+
+
+template <typename K, typename V>
+bool multihashmap<K, V>::remove(const K& key)
+{
+  return boost::unordered_multimap<K, V>::erase(key) > 0;
+}
+
+
+template <typename K, typename V>
+bool multihashmap<K, V>::remove(const K& key, const V& value)
+{
+  std::pair<typename boost::unordered_multimap<K, V>::iterator,
+    typename boost::unordered_multimap<K, V>::iterator> range;
+
+  range = boost::unordered_multimap<K, V>::equal_range(key);
+
+  typename boost::unordered_multimap<K, V>::iterator i;
+  for (i = range.first; i != range.second; ++i) {
+    if (i->second == value) {
+      boost::unordered_multimap<K, V>::erase(i);
+      return true;
+    }
+  }
+
+  return false;
+}
+
+
+template <typename K, typename V>
+bool multihashmap<K, V>::contains(const K& key) const
+{
+  return multihashmap<K, V>::count(key) > 0;
+}
+
+
+template <typename K, typename V>
+bool multihashmap<K, V>::contains(const K& key, const V& value) const
+{
+  const std::list<V>& values = get(key);
+  return std::find(values.begin(), values.end(), value) != values.end();
+}
+
+#endif // __STOUT_MULTIHASHMAP_HPP__

http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/bc531d3c/third_party/libprocess/3rdparty/stout/include/stout/multimap.hpp
----------------------------------------------------------------------
diff --git a/third_party/libprocess/3rdparty/stout/include/stout/multimap.hpp b/third_party/libprocess/3rdparty/stout/include/stout/multimap.hpp
new file mode 100644
index 0000000..187ad79
--- /dev/null
+++ b/third_party/libprocess/3rdparty/stout/include/stout/multimap.hpp
@@ -0,0 +1,107 @@
+#ifndef __STOUT_MULTIMAP_HPP__
+#define __STOUT_MULTIMAP_HPP__
+
+#include <algorithm>
+#include <list>
+#include <map>
+#include <set>
+#include <utility>
+
+// Implementation of a multimap via std::multimap but with a better
+// interface. The rationale for creating this is that the
+// std::multimap interface is painful to use (requires lots of
+// iterator garbage, as well as the use of 'equal_range' which makes
+// for cluttered code).
+template <typename K, typename V>
+class Multimap : public std::multimap<K, V>
+{
+public:
+  void put(const K& key, const V& value);
+  std::list<V> get(const K& key) const;
+  std::set<K> keys() const;
+  bool remove(const K& key);
+  bool remove(const K& key, const V& value);
+  bool contains(const K& key) const;
+  bool contains(const K& key, const V& value) const;
+};
+
+
+template <typename K, typename V>
+void Multimap<K, V>::put(const K& key, const V& value)
+{
+  std::multimap<K, V>::insert(std::pair<K, V>(key, value));
+}
+
+
+template <typename K, typename V>
+std::list<V> Multimap<K, V>::get(const K& key) const
+{
+  std::list<V> values; // Values to return.
+
+  std::pair<typename std::multimap<K, V>::const_iterator,
+    typename std::multimap<K, V>::const_iterator> range;
+
+  range = std::multimap<K, V>::equal_range(key);
+
+  typename std::multimap<K, V>::const_iterator i;
+  for (i = range.first; i != range.second; ++i) {
+    values.push_back(i->second);
+  }
+
+  return values;
+}
+
+
+template <typename K, typename V>
+std::set<K> Multimap<K, V>::keys() const
+{
+  std::set<K> keys;
+  foreachkey (const K& key, *this) {
+    keys.insert(key);
+  }
+  return keys;
+}
+
+
+template <typename K, typename V>
+bool Multimap<K, V>::remove(const K& key)
+{
+  return std::multimap<K, V>::erase(key) > 0;
+}
+
+
+template <typename K, typename V>
+bool Multimap<K, V>::remove(const K& key, const V& value)
+{
+  std::pair<typename std::multimap<K, V>::iterator,
+    typename std::multimap<K, V>::iterator> range;
+
+  range = std::multimap<K, V>::equal_range(key);
+
+  typename std::multimap<K, V>::iterator i;
+  for (i = range.first; i != range.second; ++i) {
+    if (i->second == value) {
+      std::multimap<K, V>::erase(i);
+      return true;
+    }
+  }
+
+  return false;
+}
+
+
+template <typename K, typename V>
+bool Multimap<K, V>::contains(const K& key) const
+{
+  return std::multimap<K, V>::count(key) > 0;
+}
+
+
+template <typename K, typename V>
+bool Multimap<K, V>::contains(const K& key, const V& value) const
+{
+  const std::list<V>& values = get(key);
+  return std::find(values.begin(), values.end(), value) != values.end();
+}
+
+#endif // __STOUT_MULTIMAP_HPP__

http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/bc531d3c/third_party/libprocess/3rdparty/stout/include/stout/net.hpp
----------------------------------------------------------------------
diff --git a/third_party/libprocess/3rdparty/stout/include/stout/net.hpp b/third_party/libprocess/3rdparty/stout/include/stout/net.hpp
new file mode 100644
index 0000000..1c5f88a
--- /dev/null
+++ b/third_party/libprocess/3rdparty/stout/include/stout/net.hpp
@@ -0,0 +1,102 @@
+#ifndef __STOUT_NET_HPP__
+#define __STOUT_NET_HPP__
+
+#include <netdb.h>
+#include <stdio.h>
+
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+
+#ifdef HAVE_LIBCURL
+#include <curl/curl.h>
+#endif
+
+#include <string>
+
+#include "error.hpp"
+#include "os.hpp"
+#include "try.hpp"
+
+
+// Network utilities.
+namespace net {
+
+// Returns the HTTP response code resulting from attempting to download the
+// specified HTTP or FTP URL into a file at the specified path.
+inline Try<int> download(const std::string& url, const std::string& path)
+{
+#ifndef HAVE_LIBCURL
+  return Error("libcurl is not available");
+#else
+  Try<int> fd = os::open(
+      path, O_CREAT | O_WRONLY, S_IRUSR | S_IWUSR | S_IRGRP | S_IRWXO);
+
+  if (fd.isError()) {
+    return Error(fd.error());
+  }
+
+  curl_global_init(CURL_GLOBAL_ALL);
+  CURL* curl = curl_easy_init();
+
+  if (curl == NULL) {
+    curl_easy_cleanup(curl);
+    os::close(fd.get());
+    return Error("Failed to initialize libcurl");
+  }
+
+  curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
+  curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, NULL);
+
+  FILE* file = fdopen(fd.get(), "w");
+  if (file == NULL) {
+    return ErrnoError("Failed to open file handle of '" + path + "'");
+  }
+  curl_easy_setopt(curl, CURLOPT_WRITEDATA, file);
+
+  CURLcode curlErrorCode = curl_easy_perform(curl);
+  if (curlErrorCode != 0) {
+    curl_easy_cleanup(curl);
+    fclose(file);
+    return Error(curl_easy_strerror(curlErrorCode));
+  }
+
+  long code;
+  curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &code);
+  curl_easy_cleanup(curl);
+
+  if (fclose(file) != 0) {
+    return ErrnoError("Failed to close file handle of '" + path + "'");
+  }
+
+  return Try<int>::some(code);
+#endif // HAVE_LIBCURL
+}
+
+// Returns a Try of the hostname for the provided IP. If the hostname cannot
+// be resolved, then a string version of the IP address is returned.
+inline Try<std::string> getHostname(uint32_t ip)
+{
+  sockaddr_in addr;
+  memset(&addr, 0, sizeof(addr));
+  addr.sin_family = AF_INET;
+  addr.sin_addr.s_addr = ip;
+
+  char hostname[MAXHOSTNAMELEN];
+  if (getnameinfo(
+      (sockaddr*)&addr,
+      sizeof(addr),
+      hostname,
+      MAXHOSTNAMELEN,
+      NULL,
+      0,
+      0) != 0) {
+    return ErrnoError();
+  }
+
+  return std::string(hostname);
+}
+
+} // namespace net {
+
+#endif // __STOUT_NET_HPP__

http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/bc531d3c/third_party/libprocess/3rdparty/stout/include/stout/none.hpp
----------------------------------------------------------------------
diff --git a/third_party/libprocess/3rdparty/stout/include/stout/none.hpp b/third_party/libprocess/3rdparty/stout/include/stout/none.hpp
new file mode 100644
index 0000000..ea8e0f5
--- /dev/null
+++ b/third_party/libprocess/3rdparty/stout/include/stout/none.hpp
@@ -0,0 +1,56 @@
+#ifndef __STOUT_NONE_HPP__
+#define __STOUT_NONE_HPP__
+
+#include "option.hpp"
+#include "result.hpp"
+
+// A "none" type that is implicitly convertible to an Option<T> and
+// Result<T> for any T (effectively "syntactic sugar" to make code
+// more readable). The implementation uses cast operators to perform
+// the conversions instead of adding constructors to Option/Result
+// directly. Performance shouldn't be an issue given that an instance
+// of None has no virtual functions and no fields.
+
+class None
+{
+public:
+  template <typename T>
+  operator Option<T> () const
+  {
+    return Option<T>::none();
+  }
+
+  // Give the compiler some help for nested Option<T>. For example,
+  // enable converting None to a Try<Option<T>>. Note that this will
+  // bind to the innermost Option<T>.
+  template <template <typename> class S, typename T>
+  operator S<Option<T> > () const
+  {
+    return S<Option<T> >(Option<T>::none());
+  }
+
+  template <typename T>
+  operator Result<T> () const
+  {
+    return Result<T>::none();
+  }
+
+  // Give the compiler some help for nested Result<T>. For example,
+  // enable converting None to a Try<Result<T>>. Note that this will
+  // bind to the innermost Result<T>.
+  template <template <typename> class S, typename T>
+  operator S<Result<T> > () const
+  {
+    return S<Result<T> >(Result<T>::none());
+  }
+
+  // Give the compiler some more help to disambiguate the above cast
+  // operators from Result<Option<T>>.
+  template <typename T>
+  operator Result<Option<T> > () const
+  {
+    return Result<Option<T> >::none();
+  }
+};
+
+#endif // __STOUT_NONE_HPP__

http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/bc531d3c/third_party/libprocess/3rdparty/stout/include/stout/nothing.hpp
----------------------------------------------------------------------
diff --git a/third_party/libprocess/3rdparty/stout/include/stout/nothing.hpp b/third_party/libprocess/3rdparty/stout/include/stout/nothing.hpp
new file mode 100644
index 0000000..c11a010
--- /dev/null
+++ b/third_party/libprocess/3rdparty/stout/include/stout/nothing.hpp
@@ -0,0 +1,6 @@
+#ifndef __NOTHING_HPP__
+#define __NOTHING_HPP__
+
+struct Nothing {};
+
+#endif // __NOTHING_HPP__

http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/bc531d3c/third_party/libprocess/3rdparty/stout/include/stout/numify.hpp
----------------------------------------------------------------------
diff --git a/third_party/libprocess/3rdparty/stout/include/stout/numify.hpp b/third_party/libprocess/3rdparty/stout/include/stout/numify.hpp
new file mode 100644
index 0000000..d23e238
--- /dev/null
+++ b/third_party/libprocess/3rdparty/stout/include/stout/numify.hpp
@@ -0,0 +1,40 @@
+#ifndef __STOUT_NUMIFY_HPP__
+#define __STOUT_NUMIFY_HPP__
+
+#include <string>
+
+#include <boost/lexical_cast.hpp>
+
+#include "error.hpp"
+#include "none.hpp"
+#include "option.hpp"
+#include "result.hpp"
+#include "try.hpp"
+
+template <typename T>
+Try<T> numify(const std::string& s)
+{
+  try {
+    return boost::lexical_cast<T>(s);
+  } catch (const boost::bad_lexical_cast&) {
+    return Error("Failed to convert '" + s + "' to number");
+  }
+}
+
+
+template <typename T>
+Result<T> numify(const Option<std::string>& s)
+{
+  if (s.isSome()) {
+    Try<T> t = numify<T>(s.get());
+    if (t.isSome()) {
+      return t.get();
+    } else if (t.isError()) {
+      return Error(t.error());
+    }
+  }
+
+  return None();
+}
+
+#endif // __STOUT_NUMIFY_HPP__

http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/bc531d3c/third_party/libprocess/3rdparty/stout/include/stout/option.hpp
----------------------------------------------------------------------
diff --git a/third_party/libprocess/3rdparty/stout/include/stout/option.hpp b/third_party/libprocess/3rdparty/stout/include/stout/option.hpp
new file mode 100644
index 0000000..f991ae8
--- /dev/null
+++ b/third_party/libprocess/3rdparty/stout/include/stout/option.hpp
@@ -0,0 +1,85 @@
+#ifndef __STOUT_OPTION_HPP__
+#define __STOUT_OPTION_HPP__
+
+#include <assert.h>
+
+template <typename T>
+class Option
+{
+public:
+  static Option<T> none()
+  {
+    return Option<T>(NONE);
+  }
+
+  static Option<T> some(const T& t)
+  {
+    return Option<T>(SOME, new T(t));
+  }
+
+  Option() : state(NONE), t(NULL) {}
+
+  Option(const T& _t) : state(SOME), t(new T(_t)) {}
+
+  Option(const Option<T>& that)
+  {
+    state = that.state;
+    if (that.t != NULL) {
+      t = new T(*that.t);
+    } else {
+      t = NULL;
+    }
+  }
+
+  ~Option()
+  {
+    delete t;
+  }
+
+  Option<T>& operator = (const Option<T>& that)
+  {
+    if (this != &that) {
+      delete t;
+      state = that.state;
+      if (that.t != NULL) {
+        t = new T(*that.t);
+      } else {
+        t = NULL;
+      }
+    }
+
+    return *this;
+  }
+
+  bool operator == (const Option<T>& that) const
+  {
+    return (state == NONE && that.state == NONE) ||
+      (state == SOME && that.state == SOME && *t == *that.t);
+  }
+
+  bool operator != (const Option<T>& that) const
+  {
+    return !operator == (that);
+  }
+
+  bool isSome() const { return state == SOME; }
+  bool isNone() const { return state == NONE; }
+
+  T get() const { assert(state == SOME); return *t; }
+
+  T get(const T& _t) const { return state == NONE ? _t : *t; }
+
+private:
+  enum State {
+    SOME,
+    NONE,
+  };
+
+  Option(State _state, T* _t = NULL)
+    : state(_state), t(_t) {}
+
+  State state;
+  T* t;
+};
+
+#endif // __STOUT_OPTION_HPP__

http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/bc531d3c/third_party/libprocess/3rdparty/stout/include/stout/os.hpp
----------------------------------------------------------------------
diff --git a/third_party/libprocess/3rdparty/stout/include/stout/os.hpp b/third_party/libprocess/3rdparty/stout/include/stout/os.hpp
new file mode 100644
index 0000000..28a08cc
--- /dev/null
+++ b/third_party/libprocess/3rdparty/stout/include/stout/os.hpp
@@ -0,0 +1,1081 @@
+#ifndef __STOUT_OS_HPP__
+#define __STOUT_OS_HPP__
+
+#ifdef __APPLE__
+#include <crt_externs.h> // For _NSGetEnviron().
+#endif
+#include <dirent.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <fts.h>
+#include <glob.h>
+#include <libgen.h>
+#include <limits.h>
+#include <netdb.h>
+#include <pwd.h>
+#include <signal.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <glog/logging.h>
+
+#ifdef __linux__
+#include <linux/version.h>
+#endif
+
+#include <sys/stat.h>
+#include <sys/statvfs.h>
+#ifdef __APPLE__
+#include <sys/sysctl.h>
+#endif
+#ifdef __linux__
+#include <sys/sysinfo.h>
+#endif
+#include <sys/types.h>
+#include <sys/utsname.h>
+
+#include <list>
+#include <set>
+#include <sstream>
+#include <string>
+
+#include "bytes.hpp"
+#include "duration.hpp"
+#include "error.hpp"
+#include "foreach.hpp"
+#include "none.hpp"
+#include "nothing.hpp"
+#include "path.hpp"
+#include "result.hpp"
+#include "strings.hpp"
+#include "try.hpp"
+
+#ifdef __APPLE__
+// Assigning the result pointer to ret silences an unused var warning.
+#define gethostbyname2_r(name, af, ret, buf, buflen, result, h_errnop)  \
+  ({ (void)ret; *(result) = gethostbyname2(name, af); 0; })
+#endif // __APPLE__
+
+// Need to declare 'environ' pointer for non OS X platforms.
+#ifndef __APPLE__
+extern char** environ;
+#endif
+
+namespace os {
+
+inline char** environ()
+{
+  // Accessing the list of environment variables is platform-specific.
+  // On OS X, the 'environ' symbol isn't visible to shared libraries,
+  // so we must use the _NSGetEnviron() function (see 'man environ' on
+  // OS X). On other platforms, it's fine to access 'environ' from
+  // shared libraries.
+#ifdef __APPLE__
+  return *_NSGetEnviron();
+#endif
+  return ::environ;
+}
+
+
+// Checks if the specified key is in the environment variables.
+inline bool hasenv(const std::string& key)
+{
+  char* value = ::getenv(key.c_str());
+
+  return value != NULL;
+}
+
+// Looks in the environment variables for the specified key and
+// returns a string representation of it's value. If 'expected' is
+// true (default) and no environment variable matching key is found,
+// this function will exit the process.
+inline std::string getenv(const std::string& key, bool expected = true)
+{
+  char* value = ::getenv(key.c_str());
+
+  if (expected && value == NULL) {
+    LOG(FATAL) << "Expecting '" << key << "' in environment variables";
+  }
+
+  if (value != NULL) {
+    return std::string(value);
+  }
+
+  return std::string();
+}
+
+
+// Sets the value associated with the specified key in the set of
+// environment variables.
+inline void setenv(const std::string& key,
+                   const std::string& value,
+                   bool overwrite = true)
+{
+  ::setenv(key.c_str(), value.c_str(), overwrite ? 1 : 0);
+}
+
+
+// Unsets the value associated with the specified key in the set of
+// environment variables.
+inline void unsetenv(const std::string& key)
+{
+  ::unsetenv(key.c_str());
+}
+
+
+inline Try<bool> access(const std::string& path, int how)
+{
+  if (::access(path.c_str(), how) < 0) {
+    if (errno == EACCES) {
+      return false;
+    } else {
+      return ErrnoError();
+    }
+  }
+  return true;
+}
+
+
+inline Try<int> open(const std::string& path, int oflag, mode_t mode = 0)
+{
+  int fd = ::open(path.c_str(), oflag, mode);
+
+  if (fd < 0) {
+    return ErrnoError();
+  }
+
+  return fd;
+}
+
+
+inline Try<Nothing> close(int fd)
+{
+  if (::close(fd) != 0) {
+    return ErrnoError();
+  }
+
+  return Nothing();
+}
+
+
+inline Try<Nothing> cloexec(int fd)
+{
+  int flags = ::fcntl(fd, F_GETFD);
+
+  if (flags == -1) {
+    return ErrnoError();
+  }
+
+  if (::fcntl(fd, F_SETFD, flags | FD_CLOEXEC) == -1) {
+    return ErrnoError();
+  }
+
+  return Nothing();
+}
+
+
+inline Try<Nothing> nonblock(int fd)
+{
+  int flags = ::fcntl(fd, F_GETFL);
+
+  if (flags == -1) {
+    return ErrnoError();
+  }
+
+  if (::fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1) {
+    return ErrnoError();
+  }
+
+  return Nothing();
+}
+
+
+inline Try<bool> isNonblock(int fd)
+{
+  int flags = ::fcntl(fd, F_GETFL);
+
+  if (flags == -1) {
+    return ErrnoError();
+  }
+
+  return (flags & O_NONBLOCK) != 0;
+}
+
+
+inline Try<Nothing> touch(const std::string& path)
+{
+  Try<int> fd =
+    open(path, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IRWXO);
+
+  if (fd.isError()) {
+    return Error("Failed to open file '" + path + "'");
+  }
+
+  // TODO(benh): Is opening/closing sufficient to have the same
+  // semantics as the touch utility (i.e., doesn't the utility change
+  // the modified date)?
+  return close(fd.get());
+}
+
+
+// Creates a temporary file using the specified path template. The
+// template may be any path with _6_ `Xs' appended to it, for example
+// /tmp/temp.XXXXXX. The trailing `Xs' are replaced with a unique
+// alphanumeric combination.
+inline Try<std::string> mktemp(const std::string& path = "/tmp/XXXXXX")
+{
+  char* temp = new char[path.size() + 1];
+  int fd = ::mkstemp(::strcpy(temp, path.c_str()));
+
+  if (fd < 0) {
+    delete temp;
+    return ErrnoError();
+  }
+
+  // We ignore the return value of close(). This is because users
+  // calling this function are interested in the return value of
+  // mkstemp(). Also an unsuccessful close() doesn't affect the file.
+  os::close(fd);
+
+  std::string result(temp);
+  delete temp;
+  return result;
+}
+
+
+// Write out the string to the file at the current fd position.
+inline Try<Nothing> write(int fd, const std::string& message)
+{
+  size_t offset = 0;
+
+  while (offset < message.length()) {
+    ssize_t length =
+      ::write(fd, message.data() + offset, message.length() - offset);
+
+    if (length < 0) {
+      // TODO(benh): Handle a non-blocking fd? (EAGAIN, EWOULDBLOCK)
+      if (errno == EINTR) {
+        continue;
+      }
+      return ErrnoError();
+    }
+
+    offset += length;
+  }
+
+  return Nothing();
+}
+
+
+// A wrapper function that wraps the above write() with
+// open and closing the file.
+inline Try<Nothing> write(const std::string& path, const std::string& message)
+{
+  Try<int> fd = os::open(path, O_WRONLY | O_CREAT | O_TRUNC,
+                         S_IRUSR | S_IWUSR | S_IRGRP | S_IRWXO);
+  if (fd.isError()) {
+    return ErrnoError("Failed to open file '" + path + "'");
+  }
+
+  Try<Nothing> result = write(fd.get(), message);
+
+  // We ignore the return value of close(). This is because users
+  // calling this function are interested in the return value of
+  // write(). Also an unsuccessful close() doesn't affect the write.
+  os::close(fd.get());
+
+  return result;
+}
+
+
+// Reads 'size' bytes from a file from its current offset.
+// If EOF is encountered before reading size bytes, then the offset
+// is restored and none is returned.
+inline Result<std::string> read(int fd, size_t size)
+{
+  // Save the current offset.
+  off_t current = lseek(fd, 0, SEEK_CUR);
+  if (current == -1) {
+    return ErrnoError("Failed to lseek to SEEK_CUR");
+  }
+
+  char* buffer = new char[size];
+  size_t offset = 0;
+
+  while (offset < size) {
+    ssize_t length = ::read(fd, buffer + offset, size - offset);
+
+    if (length < 0) {
+      // TODO(bmahler): Handle a non-blocking fd? (EAGAIN, EWOULDBLOCK)
+      if (errno == EINTR) {
+        continue;
+      }
+      // Attempt to restore the original offset.
+      lseek(fd, current, SEEK_SET);
+      return ErrnoError();
+    } else if (length == 0) {
+      // Reached EOF before expected! Restore the offset.
+      lseek(fd, current, SEEK_SET);
+      return None();
+    }
+
+    offset += length;
+  }
+
+  return std::string(buffer, size);
+}
+
+
+// Returns the contents of the file starting from its current offset.
+// If an error occurs, this will attempt to recover the file offset.
+inline Try<std::string> read(int fd)
+{
+  // Save the current offset.
+  off_t current = lseek(fd, 0, SEEK_CUR);
+  if (current == -1) {
+    return ErrnoError("Failed to lseek to SEEK_CUR");
+  }
+
+  // Get the size of the file from the offset.
+  off_t size = lseek(fd, current, SEEK_END);
+  if (size == -1) {
+    return ErrnoError("Failed to lseek to SEEK_END");
+  }
+
+  // Restore the offset.
+  if (lseek(fd, current, SEEK_SET) == -1) {
+    return ErrnoError("Failed to lseek with SEEK_SET");
+  }
+
+  Result<std::string> result = read(fd, size);
+  if (result.isNone()) {
+    // Hit EOF before reading size bytes.
+    return Error("The file size was modified while reading");
+  } else if (result.isError()) {
+    return Error(result.error());
+  }
+
+  return result.get();
+}
+
+
+// A wrapper function that wraps the above read() with
+// open and closing the file.
+inline Try<std::string> read(const std::string& path)
+{
+  Try<int> fd =
+    os::open(path, O_RDONLY, S_IRUSR | S_IWUSR | S_IRGRP | S_IRWXO);
+
+  if (fd.isError()) {
+    return Error("Failed to open file '" + path + "'");
+  }
+
+  Try<std::string> result = read(fd.get());
+
+  // NOTE: We ignore the return value of close(). This is because users calling
+  // this function are interested in the return value of read(). Also an
+  // unsuccessful close() doesn't affect the read.
+  os::close(fd.get());
+
+  return result;
+}
+
+
+inline Try<Nothing> rm(const std::string& path)
+{
+  if (::remove(path.c_str()) != 0) {
+    return ErrnoError();
+  }
+
+  return Nothing();
+}
+
+
+inline Try<std::string> basename(const std::string& path)
+{
+  char* temp = new char[path.size() + 1];
+  char* result = ::basename(::strcpy(temp, path.c_str()));
+  if (result == NULL) {
+    delete temp;
+    return ErrnoError();
+  }
+
+  std::string s(result);
+  delete temp;
+  return s;
+}
+
+
+inline Try<std::string> dirname(const std::string& path)
+{
+  char* temp = new char[path.size() + 1];
+  char* result = ::dirname(::strcpy(temp, path.c_str()));
+  if (result == NULL) {
+    delete temp;
+    return ErrnoError();
+  }
+
+  std::string s(result);
+  delete temp;
+  return s;
+}
+
+
+inline Try<std::string> realpath(const std::string& path)
+{
+  char temp[PATH_MAX];
+  if (::realpath(path.c_str(), temp) == NULL) {
+    return ErrnoError();
+  }
+  return std::string(temp);
+}
+
+
+inline bool isdir(const std::string& path)
+{
+  struct stat s;
+
+  if (::stat(path.c_str(), &s) < 0) {
+    return false;
+  }
+  return S_ISDIR(s.st_mode);
+}
+
+
+inline bool isfile(const std::string& path)
+{
+  struct stat s;
+
+  if (::stat(path.c_str(), &s) < 0) {
+    return false;
+  }
+  return S_ISREG(s.st_mode);
+}
+
+
+inline bool islink(const std::string& path)
+{
+  struct stat s;
+
+  if (::lstat(path.c_str(), &s) < 0) {
+    return false;
+  }
+  return S_ISLNK(s.st_mode);
+}
+
+
+inline bool exists(const std::string& path)
+{
+  struct stat s;
+
+  if (::lstat(path.c_str(), &s) < 0) {
+    return false;
+  }
+  return true;
+}
+
+
+// TODO(benh): Put this in the 'paths' or 'files' or 'fs' namespace.
+inline Try<long> mtime(const std::string& path)
+{
+  struct stat s;
+
+  if (::lstat(path.c_str(), &s) < 0) {
+    return ErrnoError("Error invoking stat for '" + path + "'");
+  }
+
+  return s.st_mtime;
+}
+
+
+inline Try<Nothing> mkdir(const std::string& directory, bool recursive = true)
+{
+  if (!recursive) {
+    if (::mkdir(directory.c_str(), 0755) < 0) {
+      return ErrnoError();
+    }
+  } else {
+    std::vector<std::string> tokens = strings::tokenize(directory, "/");
+    std::string path = "";
+
+    // We got an absolute path, so keep the leading slash.
+    if (directory.find_first_of("/") == 0) {
+      path = "/";
+    }
+
+    foreach (const std::string& token, tokens) {
+      path += token;
+      if (::mkdir(path.c_str(), 0755) < 0 && errno != EEXIST) {
+        return ErrnoError();
+      }
+      path += "/";
+    }
+  }
+
+  return Nothing();
+}
+
+// Creates a temporary directory using the specified path
+// template. The template may be any path with _6_ `Xs' appended to
+// it, for example /tmp/temp.XXXXXX. The trailing `Xs' are replaced
+// with a unique alphanumeric combination.
+inline Try<std::string> mkdtemp(const std::string& path = "/tmp/XXXXXX")
+{
+  char* temp = new char[path.size() + 1];
+  if (::mkdtemp(::strcpy(temp, path.c_str())) != NULL) {
+    std::string result(temp);
+    delete temp;
+    return result;
+  } else {
+    delete temp;
+    return ErrnoError();
+  }
+}
+
+// By default, recursively deletes a directory akin to: 'rm -r'. If the
+// programmer sets recursive to false, it deletes a directory akin to: 'rmdir'.
+// Note that this function expects an absolute path.
+inline Try<Nothing> rmdir(const std::string& directory, bool recursive = true)
+{
+  if (!recursive) {
+    if (::rmdir(directory.c_str()) < 0) {
+      return ErrnoError();
+    }
+  } else {
+    char* paths[] = {const_cast<char*>(directory.c_str()), NULL};
+
+    FTS* tree = fts_open(paths, FTS_NOCHDIR, NULL);
+    if (tree == NULL) {
+      return ErrnoError();
+    }
+
+    FTSENT* node;
+    while ((node = fts_read(tree)) != NULL) {
+      switch (node->fts_info) {
+        case FTS_DP:
+          if (::rmdir(node->fts_path) < 0 && errno != ENOENT) {
+            return ErrnoError();
+          }
+          break;
+        case FTS_F:
+        case FTS_SL:
+          if (::unlink(node->fts_path) < 0 && errno != ENOENT) {
+            return ErrnoError();
+          }
+          break;
+        default:
+          break;
+      }
+    }
+
+    if (errno != 0) {
+      return ErrnoError();
+    }
+
+    if (fts_close(tree) < 0) {
+      return ErrnoError();
+    }
+  }
+
+  return Nothing();
+}
+
+
+inline int system(const std::string& command)
+{
+  return ::system(command.c_str());
+}
+
+
+// TODO(bmahler): Clean these bool functions to return Try<Nothing>.
+// Changes the specified path's user and group ownership to that of
+// the specified user..
+inline Try<Nothing> chown(
+    const std::string& user,
+    const std::string& path,
+    bool recursive = true)
+{
+  passwd* passwd;
+  if ((passwd = ::getpwnam(user.c_str())) == NULL) {
+    return ErrnoError("Failed to get user information for '" + user + "'");
+  }
+
+  if (recursive) {
+    // TODO(bmahler): Consider walking the file tree instead. We would need
+    // to be careful to not miss dotfiles.
+    std::string command = "chown -R " + stringify(passwd->pw_uid) + ':' +
+      stringify(passwd->pw_gid) + " '" + path + "'";
+
+    int status = os::system(command);
+    if (status != 0) {
+      return ErrnoError(
+          "Failed to execute '" + command +
+          "' (exit status: " + stringify(status) + ")");
+    }
+  } else {
+    if (::chown(path.c_str(), passwd->pw_uid, passwd->pw_gid) < 0) {
+      return ErrnoError();
+    }
+  }
+
+  return Nothing();
+}
+
+
+inline bool chmod(const std::string& path, int mode)
+{
+  if (::chmod(path.c_str(), mode) < 0) {
+    PLOG(ERROR) << "Failed to changed the mode of the path '" << path << "'";
+    return false;
+  }
+
+  return true;
+}
+
+
+inline bool chdir(const std::string& directory)
+{
+  if (::chdir(directory.c_str()) < 0) {
+    PLOG(ERROR) << "Failed to change directory";
+    return false;
+  }
+
+  return true;
+}
+
+
+inline bool su(const std::string& user)
+{
+  passwd* passwd;
+  if ((passwd = ::getpwnam(user.c_str())) == NULL) {
+    PLOG(ERROR) << "Failed to get user information for '"
+                << user << "', getpwnam";
+    return false;
+  }
+
+  if (::setgid(passwd->pw_gid) < 0) {
+    PLOG(ERROR) << "Failed to set group id, setgid";
+    return false;
+  }
+
+  if (::setuid(passwd->pw_uid) < 0) {
+    PLOG(ERROR) << "Failed to set user id, setuid";
+    return false;
+  }
+
+  return true;
+}
+
+
+inline std::string getcwd()
+{
+  size_t size = 100;
+
+  while (true) {
+    char* temp = new char[size];
+    if (::getcwd(temp, size) == temp) {
+      std::string result(temp);
+      delete[] temp;
+      return result;
+    } else {
+      if (errno != ERANGE) {
+        delete[] temp;
+        return std::string();
+      }
+      size *= 2;
+      delete[] temp;
+    }
+  }
+
+  return std::string();
+}
+
+
+// TODO(bmahler): Wrap with a Try.
+inline std::list<std::string> ls(const std::string& directory)
+{
+  std::list<std::string> result;
+
+  DIR* dir = opendir(directory.c_str());
+
+  if (dir == NULL) {
+    return std::list<std::string>();
+  }
+
+  // Calculate the size for a "directory entry".
+  long name_max = fpathconf(dirfd(dir), _PC_NAME_MAX);
+
+  // If we don't get a valid size, check NAME_MAX, but fall back on
+  // 255 in the worst case ... Danger, Will Robinson!
+  if (name_max == -1) {
+    name_max = (NAME_MAX > 255) ? NAME_MAX : 255;
+  }
+
+  size_t name_end =
+    (size_t) offsetof(dirent, d_name) + name_max + 1;
+
+  size_t size = (name_end > sizeof(dirent)
+    ? name_end
+    : sizeof(dirent));
+
+  dirent* temp = (dirent*) malloc(size);
+
+  if (temp == NULL) {
+    free(temp);
+    closedir(dir);
+    return std::list<std::string>();
+  }
+
+  struct dirent* entry;
+
+  int error;
+
+  while ((error = readdir_r(dir, temp, &entry)) == 0 && entry != NULL) {
+    if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) {
+      continue;
+    }
+    result.push_back(entry->d_name);
+  }
+
+  free(temp);
+  closedir(dir);
+
+  if (error != 0) {
+    return std::list<std::string>();
+  }
+
+  return result;
+}
+
+
+// Return the list of file paths that match the given pattern by recursively
+// searching the given directory. A match is successful if the pattern is a
+// substring of the file name.
+// NOTE: Directory path should not end with '/'.
+// NOTE: Symbolic links are not followed.
+// TODO(vinod): Support regular expressions for pattern.
+// TODO(vinod): Consider using ftw or a non-recursive approach.
+inline Try<std::list<std::string> > find(
+    const std::string& directory,
+    const std::string& pattern)
+{
+  std::list<std::string> results;
+
+  if (!isdir(directory)) {
+    return Error("'" + directory + "' is not a directory");
+  }
+
+  foreach (const std::string& entry, ls(directory)) {
+    std::string path = path::join(directory, entry);
+    // If it's a directory, recurse.
+    if (isdir(path) && !islink(path)) {
+      Try<std::list<std::string> > matches = find(path, pattern);
+      if (matches.isError()) {
+        return matches;
+      }
+      foreach (const std::string& match, matches.get()) {
+        results.push_back(match);
+      }
+    } else {
+      if (entry.find(pattern) != std::string::npos) {
+        results.push_back(path); // Matched the file pattern!
+      }
+    }
+  }
+
+  return results;
+}
+
+
+inline std::string user()
+{
+  passwd* passwd;
+  if ((passwd = getpwuid(getuid())) == NULL) {
+    LOG(FATAL) << "Failed to get username information";
+  }
+
+  return passwd->pw_name;
+}
+
+
+inline Try<std::string> hostname()
+{
+  char host[512];
+
+  if (gethostname(host, sizeof(host)) < 0) {
+    return ErrnoError();
+  }
+
+  // Allocate temporary buffer for gethostbyname2_r.
+  size_t length = 1024;
+  char* temp = new char[length];
+
+  struct hostent he, *hep = NULL;
+  int result = 0;
+  int herrno = 0;
+
+  while ((result = gethostbyname2_r(host, AF_INET, &he, temp,
+                                    length, &hep, &herrno)) == ERANGE) {
+    // Enlarge the buffer.
+    delete[] temp;
+    length *= 2;
+    temp = new char[length];
+  }
+
+  if (result != 0 || hep == NULL) {
+    delete[] temp;
+    return Error(hstrerror(herrno));
+  }
+
+  std::string hostname = hep->h_name;
+  delete[] temp;
+  return Try<std::string>::some(hostname);
+}
+
+
+// Runs a shell command formatted with varargs and return the return value
+// of the command. Optionally, the output is returned via an argument.
+// TODO(vinod): Pass an istream object that can provide input to the command.
+inline Try<int> shell(std::ostream* os, const std::string& fmt, ...)
+{
+  va_list args;
+  va_start(args, fmt);
+
+  const Try<std::string>& cmdline = strings::internal::format(fmt, args);
+
+  va_end(args);
+
+  if (cmdline.isError()) {
+    return Error(cmdline.error());
+  }
+
+  FILE* file;
+
+  if ((file = popen(cmdline.get().c_str(), "r")) == NULL) {
+    return Error("Failed to run '" + cmdline.get() + "'");
+  }
+
+  char line[1024];
+  // NOTE(vinod): Ideally the if and while loops should be interchanged. But
+  // we get a broken pipe error if we don't read the output and simply close.
+  while (fgets(line, sizeof(line), file) != NULL) {
+    if (os != NULL) {
+      *os << line ;
+    }
+  }
+
+  if (ferror(file) != 0) {
+    ErrnoError error("Error reading output of '" + cmdline.get() + "'");
+    pclose(file); // Ignoring result since we already have an error.
+    return error;
+  }
+
+  int status;
+  if ((status = pclose(file)) == -1) {
+    return Error("Failed to get status of '" + cmdline.get() + "'");
+  }
+
+  return status;
+}
+
+
+// Suspends execution for the given duration.
+inline Try<Nothing> sleep(const Duration& duration)
+{
+  timespec remaining;
+  remaining.tv_sec = static_cast<long>(duration.secs());
+  remaining.tv_nsec =
+    static_cast<long>((duration - Seconds(remaining.tv_sec)).ns());
+
+  while (nanosleep(&remaining, &remaining) == -1) {
+    if (errno == EINTR) {
+      continue;
+    } else {
+      return ErrnoError();
+    }
+  }
+
+  return Nothing();
+}
+
+
+// Creates a tar 'archive' with gzip compression, of the given 'path'.
+inline Try<Nothing> tar(const std::string& path, const std::string& archive)
+{
+  Try<int> status =
+    shell(NULL, "tar -czf %s %s", archive.c_str(), path.c_str());
+
+  if (status.isError()) {
+    return Error("Failed to archive " + path + ": " + status.error());
+  } else if (status.get() != 0) {
+    return Error("Non-zero exit status when archiving " + path +
+                 ": " + stringify(status.get()));
+  }
+
+  return Nothing();
+}
+
+
+// Returns the list of files that match the given (shell) pattern.
+inline Try<std::list<std::string> > glob(const std::string& pattern)
+{
+  glob_t g;
+  int status = ::glob(pattern.c_str(), GLOB_NOSORT, NULL, &g);
+
+  std::list<std::string> result;
+
+  if (status != 0) {
+    if (status == GLOB_NOMATCH) {
+      return result; // Empty list.
+    } else {
+      return ErrnoError();
+    }
+  }
+
+  for (size_t i = 0; i < g.gl_pathc; ++i) {
+    result.push_back(g.gl_pathv[i]);
+  }
+
+  globfree(&g); // Best-effort free of dynamically allocated memory.
+
+  return result;
+}
+
+
+// Returns the total number of cpus (cores).
+inline Try<long> cpus()
+{
+  long cpus = sysconf(_SC_NPROCESSORS_ONLN);
+
+  if (cpus < 0) {
+    return ErrnoError();
+  }
+  return cpus;
+}
+
+
+// Returns the total size of main memory.
+inline Try<Bytes> memory()
+{
+#ifdef __linux__
+  struct sysinfo info;
+  if (sysinfo(&info) != 0) {
+    return ErrnoError();
+  }
+# if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 3, 23)
+  return Bytes(info.totalram * info.mem_unit);
+# else
+  return Bytes(info.totalram);
+# endif
+#elif defined __APPLE__
+  const size_t NAME_SIZE = 2;
+  int name[NAME_SIZE];
+  name[0] = CTL_HW;
+  name[1] = HW_MEMSIZE;
+
+  int64_t memory;
+  size_t length = sizeof(memory);
+
+  if (sysctl(name, NAME_SIZE, &memory, &length, NULL, 0) < 0) {
+    return ErrnoError("Failed to get sysctl of HW_MEMSIZE");
+  }
+  return Bytes(memory);
+#else
+  return Error("Cannot determine the size of main memory");
+#endif
+}
+
+
+// The structure returned by uname describing the currently running system.
+struct UTSInfo
+{
+  std::string sysname;    // Operating system name (e.g. Linux).
+  std::string nodename;   // Network name of this machine.
+  std::string release;    // Release level of the operating system.
+  std::string version;    // Version level of the operating system.
+  std::string machine;    // Machine hardware platform.
+};
+
+
+// Return the system information.
+inline Try<UTSInfo> uname()
+{
+  struct utsname name;
+
+  if (::uname(&name) < 0) {
+    return ErrnoError();
+  }
+
+  UTSInfo info;
+  info.sysname = name.sysname;
+  info.nodename = name.nodename;
+  info.release = name.release;
+  info.version = name.version;
+  info.machine = name.machine;
+  return info;
+}
+
+
+// Return the operating system name (e.g. Linux).
+inline Try<std::string> sysname()
+{
+  Try<UTSInfo> info = uname();
+  if (info.isError()) {
+    return Error(info.error());
+  }
+
+  return info.get().sysname;
+}
+
+
+// The OS release level.
+struct Release
+{
+  int version;
+  int major;
+  int minor;
+};
+
+
+// Return the OS release numbers.
+inline Try<Release> release()
+{
+  Try<UTSInfo> info = uname();
+  if (info.isError()) {
+    return Error(info.error());
+  }
+
+  Release r;
+  if (::sscanf(
+          info.get().release.c_str(),
+          "%d.%d.%d",
+          &r.version,
+          &r.major,
+          &r.minor) != 3) {
+    return Error("Failed to parse: " + info.get().release);
+  }
+
+  return r;
+}
+
+
+inline Try<bool> alive(pid_t pid)
+{
+  CHECK(pid > 0);
+
+  if (::kill(pid, 0) == 0) {
+    return true;
+  }
+
+  if (errno == ESRCH) {
+    return false;
+  }
+
+  return Try<bool>::error(strerror(errno));
+}
+
+} // namespace os {
+
+#endif // __STOUT_OS_HPP__

http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/bc531d3c/third_party/libprocess/3rdparty/stout/include/stout/owned.hpp
----------------------------------------------------------------------
diff --git a/third_party/libprocess/3rdparty/stout/include/stout/owned.hpp b/third_party/libprocess/3rdparty/stout/include/stout/owned.hpp
new file mode 100644
index 0000000..3433f50
--- /dev/null
+++ b/third_party/libprocess/3rdparty/stout/include/stout/owned.hpp
@@ -0,0 +1,20 @@
+#ifndef __STOUT_OWNED_HPP__
+#define __STOUT_OWNED_HPP__
+
+#include <boost/shared_ptr.hpp>
+
+// Represents a uniquely owned pointer.
+//
+// TODO(bmahler): For now, Owned only provides shared_ptr semantics.
+// When we make the switch to C++11, we will change to provide
+// unique_ptr semantics. Consequently, each usage of Owned that
+// invoked a copy will have to be adjusted to use move semantics.
+template <typename T>
+class Owned : public boost::shared_ptr<T>
+{
+public:
+  Owned(T* t) : boost::shared_ptr<T>(t) {}
+};
+
+
+#endif // __STOUT_OWNED_HPP__

http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/bc531d3c/third_party/libprocess/3rdparty/stout/include/stout/path.hpp
----------------------------------------------------------------------
diff --git a/third_party/libprocess/3rdparty/stout/include/stout/path.hpp b/third_party/libprocess/3rdparty/stout/include/stout/path.hpp
new file mode 100644
index 0000000..fda4e04
--- /dev/null
+++ b/third_party/libprocess/3rdparty/stout/include/stout/path.hpp
@@ -0,0 +1,76 @@
+#ifndef __STOUT_PATH_HPP__
+#define __STOUT_PATH_HPP__
+
+#include <string>
+#include <vector>
+
+#include "strings.hpp"
+
+namespace path {
+
+inline std::string join(const std::string& path1, const std::string& path2)
+{
+  return
+    strings::remove(path1, "/", strings::SUFFIX) + "/" +
+    strings::remove(path2, "/", strings::PREFIX);
+}
+
+
+inline std::string join(
+    const std::string& path1,
+    const std::string& path2,
+    const std::string& path3)
+{
+  return join(path1, join(path2, path3));
+}
+
+
+inline std::string join(
+    const std::string& path1,
+    const std::string& path2,
+    const std::string& path3,
+    const std::string& path4)
+{
+  return join(path1, join(path2, path3, path4));
+}
+
+
+inline std::string join(
+    const std::string& path1,
+    const std::string& path2,
+    const std::string& path3,
+    const std::string& path4,
+    const std::string& path5)
+{
+  return join(path1, join(path2, join(path3, join(path4, path5))));
+}
+
+
+inline std::string join(
+    const std::string& path1,
+    const std::string& path2,
+    const std::string& path3,
+    const std::string& path4,
+    const std::string& path5,
+    const std::string& path6)
+{
+  return join(path1, join(path2, path3, path4, path5, path6));
+}
+
+
+inline std::string join(const std::vector<std::string>& paths)
+{
+  if (paths.empty()) {
+    return "";
+  }
+
+  std::string result = paths[0];
+  for (size_t i = 1; i < paths.size(); ++i) {
+    result = join(result, paths[i]);
+  }
+  return result;
+}
+
+} // namespace path {
+
+#endif // __STOUT_PATH_HPP__

http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/bc531d3c/third_party/libprocess/3rdparty/stout/include/stout/preprocessor.hpp
----------------------------------------------------------------------
diff --git a/third_party/libprocess/3rdparty/stout/include/stout/preprocessor.hpp b/third_party/libprocess/3rdparty/stout/include/stout/preprocessor.hpp
new file mode 100644
index 0000000..466e16f
--- /dev/null
+++ b/third_party/libprocess/3rdparty/stout/include/stout/preprocessor.hpp
@@ -0,0 +1,29 @@
+#ifndef __PROCESS_PREPROCESSOR_HPP__
+#define __PROCESS_PREPROCESSOR_HPP__
+
+#include <boost/preprocessor/cat.hpp>
+
+#include <boost/preprocessor/arithmetic/inc.hpp>
+
+#include <boost/preprocessor/facilities/intercept.hpp>
+
+#include <boost/preprocessor/repetition/enum_params.hpp>
+#include <boost/preprocessor/repetition/enum_binary_params.hpp>
+#include <boost/preprocessor/repetition/enum_trailing_params.hpp>
+#include <boost/preprocessor/repetition/repeat.hpp>
+#include <boost/preprocessor/repetition/repeat_from_to.hpp>
+
+// Provides aliases to a bunch of preprocessor macros useful for
+// creating template definitions that have varying number of
+// parameters (should be removable with C++-11 variadic templates).
+
+#define CAT BOOST_PP_CAT
+#define INC BOOST_PP_INC
+#define INTERCEPT BOOST_PP_INTERCEPT
+#define ENUM_PARAMS BOOST_PP_ENUM_PARAMS
+#define ENUM_BINARY_PARAMS BOOST_PP_ENUM_BINARY_PARAMS
+#define ENUM_TRAILING_PARAMS BOOST_PP_ENUM_TRAILING_PARAMS
+#define REPEAT BOOST_PP_REPEAT
+#define REPEAT_FROM_TO BOOST_PP_REPEAT_FROM_TO
+
+#endif // __PROCESS_PREPROCESSOR_HPP__