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:41:08 UTC
[30/35] Renamed 'third_party' to '3rdparty'.
http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/71a01bd9/3rdparty/libprocess/3rdparty/stout/include/stout/flags/loader.hpp
----------------------------------------------------------------------
diff --git a/3rdparty/libprocess/3rdparty/stout/include/stout/flags/loader.hpp b/3rdparty/libprocess/3rdparty/stout/include/stout/flags/loader.hpp
new file mode 100644
index 0000000..e5eaf24
--- /dev/null
+++ b/3rdparty/libprocess/3rdparty/stout/include/stout/flags/loader.hpp
@@ -0,0 +1,109 @@
+#ifndef __STOUT_FLAGS_LOADER_HPP__
+#define __STOUT_FLAGS_LOADER_HPP__
+
+#include <string>
+
+#include <tr1/functional>
+
+#include <stout/error.hpp>
+#include <stout/nothing.hpp>
+#include <stout/option.hpp>
+#include <stout/try.hpp>
+
+#include <stout/flags/parse.hpp>
+
+namespace flags {
+
+// Forward declaration.
+class FlagsBase;
+
+template <typename T>
+struct Loader
+{
+ static Try<Nothing> load(
+ T* flag,
+ const std::tr1::function<Try<T>(const std::string&)>& parse,
+ const std::string& name,
+ const std::string& value)
+ {
+ Try<T> t = parse(value);
+ if (t.isSome()) {
+ *flag = t.get();
+ } else {
+ return Error("Failed to load value '" + value + "': " + t.error());
+ }
+ return Nothing();
+ }
+};
+
+
+template <typename T>
+struct OptionLoader
+{
+ static Try<Nothing> load(
+ Option<T>* flag,
+ const std::tr1::function<Try<T>(const std::string&)>& parse,
+ const std::string& name,
+ const std::string& value)
+ {
+ Try<T> t = parse(value);
+ if (t.isSome()) {
+ *flag = Option<T>::some(t.get());
+ } else {
+ return Error("Failed to load value '" + value + "': " + t.error());
+ }
+ return Nothing();
+ }
+};
+
+
+template <typename F, typename T>
+struct MemberLoader
+{
+ static Try<Nothing> load(
+ FlagsBase* base,
+ T F::*flag,
+ const std::tr1::function<Try<T>(const std::string&)>& parse,
+ const std::string& name,
+ const std::string& value)
+ {
+ F* f = dynamic_cast<F*>(base);
+ if (f != NULL) {
+ Try<T> t = parse(value);
+ if (t.isSome()) {
+ f->*flag = t.get();
+ } else {
+ return Error("Failed to load value '" + value + "': " + t.error());
+ }
+ }
+ return Nothing();
+ }
+};
+
+
+template <typename F, typename T>
+struct OptionMemberLoader
+{
+ static Try<Nothing> load(
+ FlagsBase* base,
+ Option<T> F::*flag,
+ const std::tr1::function<Try<T>(const std::string&)>& parse,
+ const std::string& name,
+ const std::string& value)
+ {
+ F* f = dynamic_cast<F*>(base);
+ if (f != NULL) {
+ Try<T> t = parse(value);
+ if (t.isSome()) {
+ f->*flag = Option<T>::some(t.get());
+ } else {
+ return Error("Failed to load value '" + value + "': " + t.error());
+ }
+ }
+ return Nothing();
+ }
+};
+
+} // namespace flags {
+
+#endif // __STOUT_FLAGS_LOADER_HPP__
http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/71a01bd9/3rdparty/libprocess/3rdparty/stout/include/stout/flags/parse.hpp
----------------------------------------------------------------------
diff --git a/3rdparty/libprocess/3rdparty/stout/include/stout/flags/parse.hpp b/3rdparty/libprocess/3rdparty/stout/include/stout/flags/parse.hpp
new file mode 100644
index 0000000..54eb35c
--- /dev/null
+++ b/3rdparty/libprocess/3rdparty/stout/include/stout/flags/parse.hpp
@@ -0,0 +1,55 @@
+#ifndef __STOUT_FLAGS_PARSE_HPP__
+#define __STOUT_FLAGS_PARSE_HPP__
+
+#include <sstream> // For istringstream.
+#include <string>
+
+#include <tr1/functional>
+
+#include <stout/duration.hpp>
+#include <stout/error.hpp>
+#include <stout/try.hpp>
+
+namespace flags {
+
+template <typename T>
+Try<T> parse(const std::string& value)
+{
+ T t;
+ std::istringstream in(value);
+ in >> t;
+ if (!in.good() && !in.eof()) {
+ return Error("Failed to convert into required type");
+ }
+ return t;
+}
+
+
+template <>
+inline Try<std::string> parse(const std::string& value)
+{
+ return value;
+}
+
+
+template <>
+inline Try<bool> parse(const std::string& value)
+{
+ if (value == "true" || value == "1") {
+ return true;
+ } else if (value == "false" || value == "0") {
+ return false;
+ }
+ return Error("Expecting a boolean (e.g., true or false)");
+}
+
+
+template <>
+inline Try<Duration> parse(const std::string& value)
+{
+ return Duration::parse(value);
+}
+
+} // namespace flags {
+
+#endif // __STOUT_FLAGS_PARSE_HPP__
http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/71a01bd9/3rdparty/libprocess/3rdparty/stout/include/stout/foreach.hpp
----------------------------------------------------------------------
diff --git a/3rdparty/libprocess/3rdparty/stout/include/stout/foreach.hpp b/3rdparty/libprocess/3rdparty/stout/include/stout/foreach.hpp
new file mode 100644
index 0000000..0afe285
--- /dev/null
+++ b/3rdparty/libprocess/3rdparty/stout/include/stout/foreach.hpp
@@ -0,0 +1,51 @@
+#ifndef __STOUT_FOREACH_HPP__
+#define __STOUT_FOREACH_HPP__
+
+#include <boost/foreach.hpp>
+
+#include <boost/tuple/tuple.hpp>
+
+namespace __foreach__ {
+
+// NOTE: This is a copied from Boost
+// (boost/tuple/detail/tuple_basic_no_partial_spec.hpp) because the
+// new 'boost::tuples::ignore' does not work in our 'foreachkey' and
+// 'foreachvalue'.
+struct swallow_assign {
+ template<typename T>
+ swallow_assign const& operator=(const T&) const {
+ return *this;
+ }
+};
+
+swallow_assign const ignore = swallow_assign();
+
+} // namespace __foreach__ {
+
+#define BOOST_FOREACH_PAIR(VARFIRST, VARSECOND, COL) \
+ BOOST_FOREACH_PREAMBLE() \
+ if (boost::foreach_detail_::auto_any_t BOOST_FOREACH_ID(_foreach_col) = BOOST_FOREACH_CONTAIN(COL)) {} else \
+ if (boost::foreach_detail_::auto_any_t BOOST_FOREACH_ID(_foreach_cur) = BOOST_FOREACH_BEGIN(COL)) {} else \
+ if (boost::foreach_detail_::auto_any_t BOOST_FOREACH_ID(_foreach_end) = BOOST_FOREACH_END(COL)) {} else \
+ for (bool BOOST_FOREACH_ID(_foreach_continue) = true, BOOST_FOREACH_ID(_foreach_onetime) = true; \
+ BOOST_FOREACH_ID(_foreach_continue) && !BOOST_FOREACH_DONE(COL); \
+ BOOST_FOREACH_ID(_foreach_continue) ? BOOST_FOREACH_NEXT(COL) : (void)0) \
+ if (boost::foreach_detail_::set_false(BOOST_FOREACH_ID(_foreach_onetime))) {} else \
+ for (VARFIRST = BOOST_FOREACH_DEREF(COL).first; \
+ !BOOST_FOREACH_ID(_foreach_onetime); \
+ BOOST_FOREACH_ID(_foreach_onetime) = true) \
+ if (boost::foreach_detail_::set_false(BOOST_FOREACH_ID(_foreach_continue))) {} else \
+ for (VARSECOND = BOOST_FOREACH_DEREF(COL).second; \
+ !BOOST_FOREACH_ID(_foreach_continue); \
+ BOOST_FOREACH_ID(_foreach_continue) = true)
+
+#define foreach BOOST_FOREACH
+#define foreachpair BOOST_FOREACH_PAIR
+
+#define foreachkey(VAR, COL) \
+ foreachpair (VAR, __foreach__::ignore, COL)
+
+#define foreachvalue(VAR, COL) \
+ foreachpair (__foreach__::ignore, VAR, COL)
+
+#endif // __STOUT_FOREACH_HPP__
http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/71a01bd9/3rdparty/libprocess/3rdparty/stout/include/stout/format.hpp
----------------------------------------------------------------------
diff --git a/3rdparty/libprocess/3rdparty/stout/include/stout/format.hpp b/3rdparty/libprocess/3rdparty/stout/include/stout/format.hpp
new file mode 100644
index 0000000..71b5986
--- /dev/null
+++ b/3rdparty/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/71a01bd9/3rdparty/libprocess/3rdparty/stout/include/stout/fs.hpp
----------------------------------------------------------------------
diff --git a/3rdparty/libprocess/3rdparty/stout/include/stout/fs.hpp b/3rdparty/libprocess/3rdparty/stout/include/stout/fs.hpp
new file mode 100644
index 0000000..c1a05b5
--- /dev/null
+++ b/3rdparty/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/71a01bd9/3rdparty/libprocess/3rdparty/stout/include/stout/gtest.hpp
----------------------------------------------------------------------
diff --git a/3rdparty/libprocess/3rdparty/stout/include/stout/gtest.hpp b/3rdparty/libprocess/3rdparty/stout/include/stout/gtest.hpp
new file mode 100644
index 0000000..3c34124
--- /dev/null
+++ b/3rdparty/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/71a01bd9/3rdparty/libprocess/3rdparty/stout/include/stout/gzip.hpp
----------------------------------------------------------------------
diff --git a/3rdparty/libprocess/3rdparty/stout/include/stout/gzip.hpp b/3rdparty/libprocess/3rdparty/stout/include/stout/gzip.hpp
new file mode 100644
index 0000000..ef36f1b
--- /dev/null
+++ b/3rdparty/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/71a01bd9/3rdparty/libprocess/3rdparty/stout/include/stout/hashmap.hpp
----------------------------------------------------------------------
diff --git a/3rdparty/libprocess/3rdparty/stout/include/stout/hashmap.hpp b/3rdparty/libprocess/3rdparty/stout/include/stout/hashmap.hpp
new file mode 100644
index 0000000..796cb50
--- /dev/null
+++ b/3rdparty/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/71a01bd9/3rdparty/libprocess/3rdparty/stout/include/stout/hashset.hpp
----------------------------------------------------------------------
diff --git a/3rdparty/libprocess/3rdparty/stout/include/stout/hashset.hpp b/3rdparty/libprocess/3rdparty/stout/include/stout/hashset.hpp
new file mode 100644
index 0000000..f584545
--- /dev/null
+++ b/3rdparty/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/71a01bd9/3rdparty/libprocess/3rdparty/stout/include/stout/json.hpp
----------------------------------------------------------------------
diff --git a/3rdparty/libprocess/3rdparty/stout/include/stout/json.hpp b/3rdparty/libprocess/3rdparty/stout/include/stout/json.hpp
new file mode 100644
index 0000000..e2cd4f2
--- /dev/null
+++ b/3rdparty/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/71a01bd9/3rdparty/libprocess/3rdparty/stout/include/stout/lambda.hpp
----------------------------------------------------------------------
diff --git a/3rdparty/libprocess/3rdparty/stout/include/stout/lambda.hpp b/3rdparty/libprocess/3rdparty/stout/include/stout/lambda.hpp
new file mode 100644
index 0000000..d493353
--- /dev/null
+++ b/3rdparty/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/71a01bd9/3rdparty/libprocess/3rdparty/stout/include/stout/multihashmap.hpp
----------------------------------------------------------------------
diff --git a/3rdparty/libprocess/3rdparty/stout/include/stout/multihashmap.hpp b/3rdparty/libprocess/3rdparty/stout/include/stout/multihashmap.hpp
new file mode 100644
index 0000000..10e49dc
--- /dev/null
+++ b/3rdparty/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/71a01bd9/3rdparty/libprocess/3rdparty/stout/include/stout/multimap.hpp
----------------------------------------------------------------------
diff --git a/3rdparty/libprocess/3rdparty/stout/include/stout/multimap.hpp b/3rdparty/libprocess/3rdparty/stout/include/stout/multimap.hpp
new file mode 100644
index 0000000..187ad79
--- /dev/null
+++ b/3rdparty/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/71a01bd9/3rdparty/libprocess/3rdparty/stout/include/stout/net.hpp
----------------------------------------------------------------------
diff --git a/3rdparty/libprocess/3rdparty/stout/include/stout/net.hpp b/3rdparty/libprocess/3rdparty/stout/include/stout/net.hpp
new file mode 100644
index 0000000..1c5f88a
--- /dev/null
+++ b/3rdparty/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/71a01bd9/3rdparty/libprocess/3rdparty/stout/include/stout/none.hpp
----------------------------------------------------------------------
diff --git a/3rdparty/libprocess/3rdparty/stout/include/stout/none.hpp b/3rdparty/libprocess/3rdparty/stout/include/stout/none.hpp
new file mode 100644
index 0000000..ea8e0f5
--- /dev/null
+++ b/3rdparty/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/71a01bd9/3rdparty/libprocess/3rdparty/stout/include/stout/nothing.hpp
----------------------------------------------------------------------
diff --git a/3rdparty/libprocess/3rdparty/stout/include/stout/nothing.hpp b/3rdparty/libprocess/3rdparty/stout/include/stout/nothing.hpp
new file mode 100644
index 0000000..c11a010
--- /dev/null
+++ b/3rdparty/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/71a01bd9/3rdparty/libprocess/3rdparty/stout/include/stout/numify.hpp
----------------------------------------------------------------------
diff --git a/3rdparty/libprocess/3rdparty/stout/include/stout/numify.hpp b/3rdparty/libprocess/3rdparty/stout/include/stout/numify.hpp
new file mode 100644
index 0000000..d23e238
--- /dev/null
+++ b/3rdparty/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/71a01bd9/3rdparty/libprocess/3rdparty/stout/include/stout/option.hpp
----------------------------------------------------------------------
diff --git a/3rdparty/libprocess/3rdparty/stout/include/stout/option.hpp b/3rdparty/libprocess/3rdparty/stout/include/stout/option.hpp
new file mode 100644
index 0000000..f991ae8
--- /dev/null
+++ b/3rdparty/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/71a01bd9/3rdparty/libprocess/3rdparty/stout/include/stout/os.hpp
----------------------------------------------------------------------
diff --git a/3rdparty/libprocess/3rdparty/stout/include/stout/os.hpp b/3rdparty/libprocess/3rdparty/stout/include/stout/os.hpp
new file mode 100644
index 0000000..28a08cc
--- /dev/null
+++ b/3rdparty/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/71a01bd9/3rdparty/libprocess/3rdparty/stout/include/stout/owned.hpp
----------------------------------------------------------------------
diff --git a/3rdparty/libprocess/3rdparty/stout/include/stout/owned.hpp b/3rdparty/libprocess/3rdparty/stout/include/stout/owned.hpp
new file mode 100644
index 0000000..3433f50
--- /dev/null
+++ b/3rdparty/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/71a01bd9/3rdparty/libprocess/3rdparty/stout/include/stout/path.hpp
----------------------------------------------------------------------
diff --git a/3rdparty/libprocess/3rdparty/stout/include/stout/path.hpp b/3rdparty/libprocess/3rdparty/stout/include/stout/path.hpp
new file mode 100644
index 0000000..fda4e04
--- /dev/null
+++ b/3rdparty/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/71a01bd9/3rdparty/libprocess/3rdparty/stout/include/stout/preprocessor.hpp
----------------------------------------------------------------------
diff --git a/3rdparty/libprocess/3rdparty/stout/include/stout/preprocessor.hpp b/3rdparty/libprocess/3rdparty/stout/include/stout/preprocessor.hpp
new file mode 100644
index 0000000..466e16f
--- /dev/null
+++ b/3rdparty/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__