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:01 UTC
[23/35] Renamed 'third_party' to '3rdparty'.
http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/71a01bd9/3rdparty/libprocess/src/statistics.cpp
----------------------------------------------------------------------
diff --git a/3rdparty/libprocess/src/statistics.cpp b/3rdparty/libprocess/src/statistics.cpp
new file mode 100644
index 0000000..d8f5ad1
--- /dev/null
+++ b/3rdparty/libprocess/src/statistics.cpp
@@ -0,0 +1,508 @@
+#include <glog/logging.h>
+
+#include <algorithm>
+#include <list>
+#include <map>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include <process/clock.hpp>
+#include <process/delay.hpp>
+#include <process/dispatch.hpp>
+#include <process/future.hpp>
+#include <process/http.hpp>
+#include <process/process.hpp>
+#include <process/statistics.hpp>
+#include <process/time.hpp>
+
+#include <stout/error.hpp>
+#include <stout/duration.hpp>
+#include <stout/foreach.hpp>
+#include <stout/hashmap.hpp>
+#include <stout/hashset.hpp>
+#include <stout/json.hpp>
+#include <stout/none.hpp>
+#include <stout/numify.hpp>
+#include <stout/option.hpp>
+#include <stout/stringify.hpp>
+#include <stout/strings.hpp>
+
+using namespace process;
+using namespace process::http;
+
+using std::list;
+using std::map;
+using std::string;
+using std::vector;
+
+namespace process {
+
+// This is initialized by process::initialize().
+Statistics* statistics = NULL;
+
+// TODO(bmahler): Move time series related logic into this struct.
+// TODO(bmahler): Investigate using google's btree implementation.
+// This provides better insertion and lookup performance for large
+// containers. This _should_ also provide significant memory
+// savings, especially since:
+// 1. Our insertion order will mostly be in sorted order.
+// 2. Our keys (Seconds) have efficient comparison operators.
+// See: http://code.google.com/p/cpp-btree/
+// http://code.google.com/p/cpp-btree/wiki/UsageInstructions
+struct TimeSeries
+{
+ TimeSeries() : values(), archived(false) {}
+
+ // We use a map instead of a hashmap to store the values because
+ // that way we can retrieve a series in sorted order efficiently.
+ map<Time, double> values;
+ bool archived;
+};
+
+
+class StatisticsProcess : public Process<StatisticsProcess>
+{
+public:
+ StatisticsProcess(const Duration& _window)
+ : ProcessBase("statistics"),
+ window(_window) {}
+
+ virtual ~StatisticsProcess() {}
+
+ // Statistics implementation.
+ map<Time, double> timeseries(
+ const string& context,
+ const string& name,
+ const Option<Time>& start,
+ const Option<Time>& stop);
+
+ Option<double> get(const string& context, const string& name);
+
+ map<string, double> get(const string& context);
+
+ Try<Nothing> meter(
+ const string& context,
+ const string& name,
+ const Owned<meters::Meter>& meter);
+
+ void set(
+ const string& context,
+ const string& name,
+ double value,
+ const Time& time);
+
+ void archive(const string& context, const string& name);
+
+ void increment(const string& context, const string& name);
+
+ void decrement(const string& context, const string& name);
+
+protected:
+ virtual void initialize()
+ {
+ route("/snapshot.json", &StatisticsProcess::snapshot);
+ route("/series.json", &StatisticsProcess::series);
+
+ // Schedule the first truncation.
+ delay(STATISTICS_TRUNCATION_INTERVAL, self(), &StatisticsProcess::truncate);
+ }
+
+private:
+ // Removes values for the specified statistic that occurred outside
+ // the time series window.
+ // NOTE: We always ensure there is at least 1 value left for a statistic,
+ // unless it is archived!
+ // Returns true iff the time series is empty.
+ bool truncate(const string& context, const string& name);
+
+ // Removes values for all statistics that occurred outside the time
+ // series window.
+ // NOTE: Runs periodically every STATISTICS_TRUNCATION_INTERVAL.
+ // NOTE: We always ensure there is at least 1 value left for a statistic,
+ // unless it is archived.
+ void truncate();
+
+ // Returns the a snapshot of all statistics in JSON.
+ Future<Response> snapshot(const Request& request);
+
+ // Returns the time series of a statistic in JSON.
+ Future<Response> series(const Request& request);
+
+ const Duration window;
+
+ // This maps from {context: {name: TimeSeries } }.
+ hashmap<string, hashmap<string, TimeSeries> > statistics;
+
+ // Each statistic can have many meters.
+ // This maps from {context: {name: [meters] } }.
+ hashmap<string, hashmap<string, list<Owned<meters::Meter> > > > meters;
+};
+
+
+Try<Nothing> StatisticsProcess::meter(
+ const string& context,
+ const string& name,
+ const Owned<meters::Meter>& meter)
+{
+ if (meter->name == name) {
+ return Error("Meter name must not match the statistic name");
+ }
+
+ // Check for a duplicate meter.
+ foreachkey (const string& context, meters) {
+ foreachkey (const string& name, meters[context]) {
+ foreach (Owned<meters::Meter>& existing, meters[context][name]) {
+ if (meter->name == existing->name) {
+ return Error("Meter name matched existing meter name");
+ }
+ }
+ }
+ }
+
+ // Add the meter.
+ meters[context][name].push_back(meter);
+
+ return Nothing();
+}
+
+
+map<Time, double> StatisticsProcess::timeseries(
+ const string& context,
+ const string& name,
+ const Option<Time>& start,
+ const Option<Time>& stop)
+{
+ if (!statistics.contains(context) || !statistics[context].contains(name)) {
+ return map<Time, double>();
+ }
+
+ const std::map<Time, double>& values =
+ statistics[context].find(name)->second.values;
+
+ map<Time, double>::const_iterator lower = values.lower_bound(start.isSome()
+ ? start.get() : Time::EPOCH);
+
+ map<Time, double>::const_iterator upper = values.upper_bound(stop.isSome()
+ ? stop.get() : Time::MAX);
+
+ return map<Time, double>(lower, upper);
+}
+
+
+Option<double> StatisticsProcess::get(const string& context, const string& name)
+{
+ if (!statistics.contains(context) ||
+ !statistics[context].contains(name) ||
+ statistics[context][name].values.empty()) {
+ return Option<double>::none();
+ } else {
+ return statistics[context][name].values.rbegin()->second;
+ }
+}
+
+
+map<string, double> StatisticsProcess::get(const string& context)
+{
+ map<string, double> results;
+
+ if (!statistics.contains(context)) {
+ return results;
+ }
+
+ foreachkey (const string& name, statistics[context]) {
+ const map<Time, double>& values = statistics[context][name].values;
+
+ if (!values.empty()) {
+ results[name] = values.rbegin()->second;
+ }
+ }
+
+ return results;
+}
+
+
+void StatisticsProcess::set(
+ const string& context,
+ const string& name,
+ double value,
+ const Time& time)
+{
+ statistics[context][name].values[time] = value; // Update the raw value.
+ statistics[context][name].archived = false; // Unarchive.
+
+ truncate(context, name);
+
+ // Update the metered values, if necessary.
+ if (meters.contains(context) && meters[context].contains(name)) {
+ foreach (Owned<meters::Meter>& meter, meters[context][name]) {
+ const Option<double>& update = meter->update(time, value);
+ statistics[context][meter->name].archived = false; // Unarchive.
+
+ if (update.isSome()) {
+ statistics[context][meter->name].values[time] = update.get();
+ truncate(context, meter->name);
+ }
+ }
+ }
+}
+
+
+void StatisticsProcess::archive(const string& context, const string& name)
+{
+ // Exclude the statistic from the snapshot.
+ statistics[context][name].archived = true;
+
+ // Remove any meters as well.
+ if (meters.contains(context) && meters[context].contains(name)) {
+ foreach (const Owned<meters::Meter>& meter, meters[context][name]) {
+ statistics[context][meter->name].archived = true;
+ }
+ meters[context].erase(name);
+ }
+}
+
+
+void StatisticsProcess::increment(const string& context, const string& name)
+{
+ double value = 0.0;
+ if (!statistics[context][name].values.empty()) {
+ value = statistics[context][name].values.rbegin()->second;
+ }
+ set(context, name, value + 1.0, Clock::now());
+}
+
+
+void StatisticsProcess::decrement(const string& context, const string& name)
+{
+ double value = 0.0;
+ if (!statistics[context][name].values.empty()) {
+ value = statistics[context][name].values.rbegin()->second;
+ }
+ set(context, name, value - 1.0, Clock::now());
+}
+
+
+bool StatisticsProcess::truncate(const string& context, const string& name)
+{
+ CHECK(statistics.contains(context));
+ CHECK(statistics[context].contains(name));
+
+ if (statistics[context][name].values.empty()) {
+ return true; // No truncation is needed, the time series is already empty.
+ }
+
+ map<Time, double>::iterator start =
+ statistics[context][name].values.begin();
+
+ while ((Clock::now() - start->first) > window) {
+ // Always keep at least one value for a statistic, unless it's archived!
+ if (statistics[context][name].values.size() == 1) {
+ if (statistics[context][name].archived) {
+ statistics[context][name].values.clear();
+ }
+ break;
+ }
+
+ statistics[context][name].values.erase(start);
+ start = statistics[context][name].values.begin();
+ }
+
+ return statistics[context][name].values.empty();
+}
+
+
+void StatisticsProcess::truncate()
+{
+ hashmap<string, hashset<string> > empties;
+
+ foreachkey (const string& context, statistics) {
+ foreachkey (const string& name, statistics[context]) {
+ // Keep track of the emptied timeseries.
+ if (truncate(context, name)) {
+ empties[context].insert(name);
+ }
+ }
+ }
+
+ // Remove the empty timeseries.
+ foreachkey (const string& context, empties) {
+ foreach (const string& name, empties[context]) {
+ statistics[context].erase(name);
+ }
+ }
+
+ delay(STATISTICS_TRUNCATION_INTERVAL, self(), &StatisticsProcess::truncate);
+}
+
+
+Future<Response> StatisticsProcess::snapshot(const Request& request)
+{
+ JSON::Array array;
+
+ Option<string> queryContext = request.query.get("context");
+ Option<string> queryName = request.query.get("name");
+
+ foreachkey (const string& context, statistics) {
+ foreachkey (const string& name, statistics[context]) {
+ // Exclude archived and empty time series.
+ if (statistics[context][name].archived ||
+ statistics[context][name].values.empty()) {
+ continue;
+ }
+
+ // Skip statistics that don't match the query, if present.
+ if (queryContext.isSome() && queryContext.get() != context) {
+ continue;
+ } else if (queryName.isSome() && queryName.get() != name) {
+ continue;
+ }
+
+ JSON::Object object;
+ object.values["context"] = context;
+ object.values["name"] = name;
+ object.values["time"] =
+ statistics[context][name].values.rbegin()->first.secs();
+ object.values["value"] =
+ statistics[context][name].values.rbegin()->second;
+ array.values.push_back(object);
+ }
+ }
+
+ return OK(array, request.query.get("jsonp"));
+}
+
+
+Future<Response> StatisticsProcess::series(const Request& request)
+{
+ Option<string> context = request.query.get("context");
+ Option<string> name = request.query.get("name");
+
+ if (!context.isSome()) {
+ return BadRequest("Expected 'context=val' in query.\n");
+ } else if (!name.isSome()) {
+ return BadRequest("Expected 'name=val' in query.\n");
+ }
+
+ Option<Time> start = None();
+ Option<Time> stop = None();
+
+ if (request.query.get("start").isSome()) {
+ Try<double> result = numify<double>(request.query.get("start").get());
+ if (result.isError()) {
+ return BadRequest("Failed to parse 'start': " + result.error());
+ }
+
+ Try<Time> start_ = Time::create(result.get());
+ if (start_.isError()) {
+ return BadRequest("Failed to parse 'start': " + start_.error());
+ }
+ start = start_.get();
+ }
+
+ if (request.query.get("stop").isSome()) {
+ Try<double> result = numify<double>(request.query.get("stop").get());
+ if (result.isError()) {
+ return BadRequest("Failed to parse 'stop': " + result.error());
+ }
+
+ Try<Time> stop_ = Time::create(result.get());
+ if (stop_.isError()) {
+ return BadRequest("Failed to parse 'stop': " + stop_.error());
+ }
+ stop = stop_.get();
+ }
+
+ JSON::Array array;
+
+ const map<Time, double>& values =
+ timeseries(context.get(), name.get(), start, stop);
+
+ foreachpair (const Time& s, double value, values) {
+ JSON::Object object;
+ object.values["time"] = s.secs();
+ object.values["value"] = value;
+ array.values.push_back(object);
+ }
+
+ return OK(array, request.query.get("jsonp"));
+}
+
+
+Statistics::Statistics(const Duration& window)
+{
+ process = new StatisticsProcess(window);
+ spawn(process);
+}
+
+
+Statistics::~Statistics()
+{
+ terminate(process);
+ wait(process);
+}
+
+
+Future<map<Time, double> > Statistics::timeseries(
+ const string& context,
+ const string& name,
+ const Option<Time>& start,
+ const Option<Time>& stop)
+{
+ return dispatch(
+ process, &StatisticsProcess::timeseries, context, name, start, stop);
+}
+
+
+Future<Option<double> > Statistics::get(
+ const string& context,
+ const string& name)
+{
+ return dispatch(process, &StatisticsProcess::get, context, name);
+}
+
+
+Future<map<string, double> > Statistics::get(const string& context)
+{
+ return dispatch(process, &StatisticsProcess::get, context);
+}
+
+
+Future<Try<Nothing> > Statistics::meter(
+ const string& context,
+ const string& name,
+ Owned<meters::Meter> meter)
+{
+
+ return dispatch(process, &StatisticsProcess::meter, context, name, meter);
+}
+
+
+void Statistics::set(
+ const string& context,
+ const string& name,
+ double value,
+ const Time& time)
+{
+ dispatch(process, &StatisticsProcess::set, context, name, value, time);
+}
+
+
+void Statistics::archive(const string& context, const string& name)
+{
+ dispatch(process, &StatisticsProcess::archive, context, name);
+}
+
+
+void Statistics::increment(const string& context, const string& name)
+{
+ dispatch(process, &StatisticsProcess::increment, context, name);
+}
+
+
+void Statistics::decrement(const string& context, const string& name)
+{
+ dispatch(process, &StatisticsProcess::decrement, context, name);
+}
+
+} // namespace process {
http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/71a01bd9/3rdparty/libprocess/src/synchronized.cpp
----------------------------------------------------------------------
diff --git a/3rdparty/libprocess/src/synchronized.cpp b/3rdparty/libprocess/src/synchronized.cpp
new file mode 100644
index 0000000..79b0849
--- /dev/null
+++ b/3rdparty/libprocess/src/synchronized.cpp
@@ -0,0 +1,66 @@
+#include "synchronized.hpp"
+
+using std::string;
+
+
+static string s1;
+static synchronizable(s1);
+
+static string s2;
+static synchronizable(s2) = SYNCHRONIZED_INITIALIZER;
+
+static string s3;
+static synchronizable(s3) = SYNCHRONIZED_INITIALIZER_RECURSIVE;
+
+
+void bar()
+{
+ synchronized(s3) {
+
+ }
+}
+
+
+void foo()
+{
+ synchronized(s3) {
+ bar();
+ }
+}
+
+
+class Foo
+{
+public:
+ Foo()
+ {
+ synchronizer(s) = SYNCHRONIZED_INITIALIZER_RECURSIVE;
+ }
+
+ void foo()
+ {
+ synchronized(s) {
+ synchronized(s) {
+
+ }
+ }
+ }
+
+private:
+ string s;
+ synchronizable(s);
+};
+
+
+int main(int argc, char **argv)
+{
+ synchronizer(s1) = SYNCHRONIZED_INITIALIZER_RECURSIVE;
+ //synchronizer(s2) = SYNCHRONIZED_INITIALIZER;
+
+ //foo();
+
+ Foo f;
+ f.foo();
+
+ return 0;
+}
http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/71a01bd9/3rdparty/libprocess/src/synchronized.hpp
----------------------------------------------------------------------
diff --git a/3rdparty/libprocess/src/synchronized.hpp b/3rdparty/libprocess/src/synchronized.hpp
new file mode 100644
index 0000000..7e0efe2
--- /dev/null
+++ b/3rdparty/libprocess/src/synchronized.hpp
@@ -0,0 +1,104 @@
+#include <pthread.h>
+
+#include <iostream>
+
+
+class Synchronizable
+{
+public:
+ Synchronizable()
+ : initialized(false) {}
+
+ explicit Synchronizable(int _type)
+ : type(_type), initialized(false)
+ {
+ initialize();
+ }
+
+ Synchronizable(const Synchronizable &that)
+ {
+ type = that.type;
+ initialize();
+ }
+
+ Synchronizable & operator = (const Synchronizable &that)
+ {
+ type = that.type;
+ initialize();
+ return *this;
+ }
+
+ void acquire()
+ {
+ if (!initialized) {
+ std::cerr << "synchronizable not initialized" << std::endl;
+ abort();
+ }
+ pthread_mutex_lock(&mutex);
+ }
+
+ void release()
+ {
+ if (!initialized) {
+ std::cerr << "synchronizable not initialized" << std::endl;
+ abort();
+ }
+ pthread_mutex_unlock(&mutex);
+ }
+
+private:
+ void initialize()
+ {
+ if (!initialized) {
+ pthread_mutexattr_t attr;
+ pthread_mutexattr_init(&attr);
+ pthread_mutexattr_settype(&attr, type);
+ pthread_mutex_init(&mutex, &attr);
+ pthread_mutexattr_destroy(&attr);
+ initialized = true;
+ } else {
+ std::cerr << "synchronizable already initialized" << std::endl;
+ abort();
+ }
+ }
+
+ int type;
+ bool initialized;
+ pthread_mutex_t mutex;
+};
+
+
+class Synchronized
+{
+public:
+ Synchronized(Synchronizable *_synchronizable)
+ : synchronizable(_synchronizable)
+ {
+ synchronizable->acquire();
+ }
+
+ ~Synchronized()
+ {
+ synchronizable->release();
+ }
+
+ operator bool () { return true; }
+
+private:
+ Synchronizable *synchronizable;
+};
+
+
+#define synchronized(s) \
+ if (Synchronized __synchronized ## s = Synchronized(&__synchronizable_ ## s))
+
+#define synchronizable(s) \
+ Synchronizable __synchronizable_ ## s
+
+#define synchronizer(s) \
+ (__synchronizable_ ## s)
+
+
+#define SYNCHRONIZED_INITIALIZER Synchronizable(PTHREAD_MUTEX_NORMAL)
+#define SYNCHRONIZED_INITIALIZER_DEBUG Synchronizable(PTHREAD_MUTEX_ERRORCHECK)
+#define SYNCHRONIZED_INITIALIZER_RECURSIVE Synchronizable(PTHREAD_MUTEX_RECURSIVE)
http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/71a01bd9/3rdparty/libprocess/src/test-master.cpp
----------------------------------------------------------------------
diff --git a/3rdparty/libprocess/src/test-master.cpp b/3rdparty/libprocess/src/test-master.cpp
new file mode 100644
index 0000000..23c6e1d
--- /dev/null
+++ b/3rdparty/libprocess/src/test-master.cpp
@@ -0,0 +1,62 @@
+#include <io.hpp>
+#include <tuple.hpp>
+
+#include <string>
+
+#include "test.hpp"
+
+using std::string;
+
+
+using namespace process::tuple;
+
+
+class Master : public Tuple<Process>
+{
+private:
+ int id;
+
+protected:
+ void operator () ()
+ {
+ do {
+ switch (receive()) {
+ case REGISTER: {
+ Out::println("Master received REGISTER");
+
+ string name;
+ unpack<REGISTER>(name);
+
+ Out::println("Registered slave: %s", name.c_str());
+
+ send(from(), pack<OKAY>(id++));
+ break;
+ }
+ case UNREGISTER: {
+ Out::println("Master received UNREGISTER");
+
+ int slave_id;
+ unpack<UNREGISTER>(slave_id);
+
+ Out::println("Unregistered slave id: %d", slave_id);
+
+ send(from(), pack<OKAY>(0));
+ break;
+ }
+ default:
+ Out::println("UNKNOWN MESSAGE RECEIVED");
+ }
+ } while (true);
+ }
+
+public:
+ Master() : id(0) {}
+};
+
+
+int main(int argc, char **argv)
+{
+ PID master = Process::spawn(new Master());
+ Out::println("master: %s", string(master).c_str());
+ Process::wait(master);
+}
http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/71a01bd9/3rdparty/libprocess/src/test-slave.cpp
----------------------------------------------------------------------
diff --git a/3rdparty/libprocess/src/test-slave.cpp b/3rdparty/libprocess/src/test-slave.cpp
new file mode 100644
index 0000000..fe08ce8
--- /dev/null
+++ b/3rdparty/libprocess/src/test-slave.cpp
@@ -0,0 +1,61 @@
+#include <test.hpp>
+
+using namespace process::record;
+
+class Slave : public RecordProcess
+{
+private:
+ PID master;
+ int id;
+
+protected:
+ void operator () ()
+ {
+ send(master, pack<REGISTER>("c3po"));
+
+ switch (receive()) {
+ case OKAY: {
+ std::cout << "slave registered" << std::endl;
+ unpack<OKAY>(id);
+ std::cout << "slave id: " << id << std::endl;
+ break;
+ }
+ default:
+ std::cout << "slave failed to register" << std::endl;
+ break;
+ }
+
+ send(master, pack<UNREGISTER>(id));
+
+ switch (receive()) {
+ case OKAY:
+ std::cout << "slave unregistered" << std::endl;
+ break;
+ default:
+ std::cout << "slave failed to unregister" << std::endl;
+ break;
+ }
+
+ link(master);
+ switch (receive()) {
+ case PROCESS_EXIT:
+ std::cout << "master exited" << std::endl;
+ break;
+ default:
+ std::cout << "unexpected message" << std::endl;
+ break;
+ }
+ }
+
+public:
+ Slave(const PID &_master) : master(_master) {}
+};
+
+
+int main(int argc, char **argv)
+{
+ PID master = make_pid(argv[1]);
+ PID slave = Process::spawn(new Slave(master));
+ std::cout << "slave is at " << slave << std::endl;
+ Process::wait(slave);
+}
http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/71a01bd9/3rdparty/libprocess/src/tests/decoder_tests.cpp
----------------------------------------------------------------------
diff --git a/3rdparty/libprocess/src/tests/decoder_tests.cpp b/3rdparty/libprocess/src/tests/decoder_tests.cpp
new file mode 100644
index 0000000..04ca3ff
--- /dev/null
+++ b/3rdparty/libprocess/src/tests/decoder_tests.cpp
@@ -0,0 +1,128 @@
+#include <gmock/gmock.h>
+
+#include <deque>
+#include <string>
+
+#include <process/socket.hpp>
+
+#include <stout/gtest.hpp>
+
+#include "decoder.hpp"
+
+using namespace process;
+using namespace process::http;
+
+using std::deque;
+using std::string;
+
+
+TEST(Decoder, Request)
+{
+ DataDecoder decoder = DataDecoder(Socket());
+
+ const string& data =
+ "GET /path/file.json?key1=value1&key2=value2#fragment HTTP/1.1\r\n"
+ "Host: localhost\r\n"
+ "Connection: close\r\n"
+ "Accept-Encoding: compress, gzip\r\n"
+ "\r\n";
+
+ deque<Request*> requests = decoder.decode(data.data(), data.length());
+ ASSERT_FALSE(decoder.failed());
+ ASSERT_EQ(1, requests.size());
+
+ Request* request = requests[0];
+ EXPECT_EQ("GET", request->method);
+ EXPECT_EQ("/path/file.json", request->path);
+ EXPECT_EQ("/path/file.json?key1=value1&key2=value2#fragment", request->url);
+ EXPECT_EQ("fragment", request->fragment);
+ EXPECT_TRUE(request->body.empty());
+ EXPECT_FALSE(request->keepAlive);
+
+ EXPECT_EQ(3, request->headers.size());
+ EXPECT_SOME_EQ("localhost", request->headers.get("Host"));
+ EXPECT_SOME_EQ("close", request->headers.get("Connection"));
+ EXPECT_SOME_EQ("compress, gzip", request->headers.get("Accept-Encoding"));
+
+ EXPECT_EQ(2, request->query.size());
+ EXPECT_SOME_EQ("value1", request->query.get("key1"));
+ EXPECT_SOME_EQ("value2", request->query.get("key2"));
+
+ delete request;
+}
+
+
+TEST(Decoder, RequestHeaderContinuation)
+{
+ DataDecoder decoder = DataDecoder(Socket());
+
+ const string& data =
+ "GET /path/file.json HTTP/1.1\r\n"
+ "Host: localhost\r\n"
+ "Connection: close\r\n"
+ "Accept-Encoding: compress,"
+ " gzip\r\n"
+ "\r\n";
+
+ deque<Request*> requests = decoder.decode(data.data(), data.length());
+ ASSERT_FALSE(decoder.failed());
+ ASSERT_EQ(1, requests.size());
+
+ Request* request = requests[0];
+ EXPECT_SOME_EQ("compress, gzip",
+ request->headers.get("Accept-Encoding"));
+ delete request;
+}
+
+
+// This is expected to fail for now, see my TODO(bmahler) on http::Request.
+TEST(Decoder, DISABLED_RequestHeaderCaseInsensitive)
+{
+ DataDecoder decoder = DataDecoder(Socket());
+
+ const string& data =
+ "GET /path/file.json HTTP/1.1\r\n"
+ "Host: localhost\r\n"
+ "cOnnECtioN: close\r\n"
+ "accept-ENCODING: compress, gzip\r\n"
+ "\r\n";
+
+ deque<Request*> requests = decoder.decode(data.data(), data.length());
+ ASSERT_FALSE(decoder.failed());
+ ASSERT_EQ(1, requests.size());
+
+ Request* request = requests[0];
+ EXPECT_FALSE(request->keepAlive);
+
+ EXPECT_SOME_EQ("compress, gzip", request->headers.get("Accept-Encoding"));
+
+ delete request;
+}
+
+
+TEST(Decoder, Response)
+{
+ ResponseDecoder decoder;
+
+ const string& data =
+ "HTTP/1.1 200 OK\r\n"
+ "Date: Fri, 31 Dec 1999 23:59:59 GMT\r\n"
+ "Content-Type: text/plain\r\n"
+ "Content-Length: 2\r\n"
+ "\r\n"
+ "hi";
+
+ deque<Response*> requests = decoder.decode(data.data(), data.length());
+ ASSERT_FALSE(decoder.failed());
+ ASSERT_EQ(1, requests.size());
+
+ Response* response = requests[0];
+
+ EXPECT_EQ("200 OK", response->status);
+ EXPECT_EQ(Response::BODY, response->type);
+ EXPECT_EQ("hi", response->body);
+
+ EXPECT_EQ(3, response->headers.size());
+
+ delete response;
+}
http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/71a01bd9/3rdparty/libprocess/src/tests/encoder_tests.cpp
----------------------------------------------------------------------
diff --git a/3rdparty/libprocess/src/tests/encoder_tests.cpp b/3rdparty/libprocess/src/tests/encoder_tests.cpp
new file mode 100644
index 0000000..fccb865
--- /dev/null
+++ b/3rdparty/libprocess/src/tests/encoder_tests.cpp
@@ -0,0 +1,92 @@
+#include <gmock/gmock.h>
+
+#include <deque>
+#include <string>
+#include <vector>
+
+#include <process/http.hpp>
+#include <process/socket.hpp>
+
+#include <stout/gtest.hpp>
+
+#include "encoder.hpp"
+#include "decoder.hpp"
+
+using namespace process;
+using namespace process::http;
+
+using std::deque;
+using std::string;
+using std::vector;
+
+
+TEST(Encoder, Response)
+{
+ Request request;
+ const OK& response("body");
+
+ // Encode the response.
+ const string& encoded = HttpResponseEncoder::encode(response, request);
+
+ // Now decode it back, and verify the encoding was correct.
+ ResponseDecoder decoder;
+ deque<Response*> responses = decoder.decode(encoded.data(), encoded.length());
+ ASSERT_FALSE(decoder.failed());
+ ASSERT_EQ(1, responses.size());
+
+ Response* decoded = responses[0];
+ EXPECT_EQ("200 OK", decoded->status);
+ EXPECT_EQ("body", decoded->body);
+
+ // Encoding should have inserted the 'Date' and 'Content-Length' headers.
+ EXPECT_EQ(2, decoded->headers.size());
+ EXPECT_TRUE(decoded->headers.contains("Date"));
+ EXPECT_SOME_EQ(
+ stringify(response.body.size()),
+ decoded->headers.get("Content-Length"));
+}
+
+
+TEST(Encoder, AcceptableEncodings)
+{
+ // Create requests that do not accept gzip encoding.
+ vector<Request> requests(7);
+ requests[0].headers["Accept-Encoding"] = "gzip;q=0.0,*";
+ requests[1].headers["Accept-Encoding"] = "compress";
+ requests[2].headers["Accept-Encoding"] = "compress, gzip;q=0.0";
+ requests[3].headers["Accept-Encoding"] = "*, gzip;q=0.0";
+ requests[4].headers["Accept-Encoding"] = "*;q=0.0, compress";
+ requests[5].headers["Accept-Encoding"] = "\n compress";
+ requests[6].headers["Accept-Encoding"] = "compress,\tgzip;q=0.0";
+
+ foreach (const Request& request, requests) {
+ EXPECT_FALSE(request.accepts("gzip"))
+ << "Gzip encoding is unacceptable for 'Accept-Encoding: "
+ << request.headers.get("Accept-Encoding").get() << "'";
+ }
+
+ // Create requests that accept gzip encoding.
+ vector<Request> gzipRequests(12);
+
+ // Using q values.
+ gzipRequests[0].headers["Accept-Encoding"] = "gzip;q=0.1,*";
+ gzipRequests[1].headers["Accept-Encoding"] = "compress, gzip;q=0.1";
+ gzipRequests[2].headers["Accept-Encoding"] = "*, gzip;q=0.5";
+ gzipRequests[3].headers["Accept-Encoding"] = "*;q=0.9, compress";
+ gzipRequests[4].headers["Accept-Encoding"] = "compress,\tgzip;q=0.1";
+
+ // No q values.
+ gzipRequests[5].headers["Accept-Encoding"] = "gzip";
+ gzipRequests[6].headers["Accept-Encoding"] = "compress, gzip";
+ gzipRequests[7].headers["Accept-Encoding"] = "*";
+ gzipRequests[8].headers["Accept-Encoding"] = "*, compress";
+ gzipRequests[9].headers["Accept-Encoding"] = "\n gzip";
+ gzipRequests[10].headers["Accept-Encoding"] = "compress,\tgzip";
+ gzipRequests[11].headers["Accept-Encoding"] = "gzip";
+
+ foreach (const Request& gzipRequest, gzipRequests) {
+ EXPECT_TRUE(gzipRequest.accepts("gzip"))
+ << "Gzip encoding is acceptable for 'Accept-Encoding: "
+ << gzipRequest.headers.get("Accept-Encoding").get() << "'";
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/71a01bd9/3rdparty/libprocess/src/tests/http_tests.cpp
----------------------------------------------------------------------
diff --git a/3rdparty/libprocess/src/tests/http_tests.cpp b/3rdparty/libprocess/src/tests/http_tests.cpp
new file mode 100644
index 0000000..f677267
--- /dev/null
+++ b/3rdparty/libprocess/src/tests/http_tests.cpp
@@ -0,0 +1,133 @@
+#include <arpa/inet.h>
+
+#include <gmock/gmock.h>
+
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+
+#include <string>
+
+#include <process/future.hpp>
+#include <process/gmock.hpp>
+#include <process/gtest.hpp>
+#include <process/http.hpp>
+#include <process/io.hpp>
+
+#include <stout/gtest.hpp>
+#include <stout/nothing.hpp>
+#include <stout/os.hpp>
+
+#include "encoder.hpp"
+
+using namespace process;
+
+using testing::_;
+using testing::Assign;
+using testing::DoAll;
+using testing::Return;
+
+
+class HttpProcess : public Process<HttpProcess>
+{
+public:
+ HttpProcess()
+ {
+ route("/body", &HttpProcess::body);
+ route("/pipe", &HttpProcess::pipe);
+ }
+
+ MOCK_METHOD1(body, Future<http::Response>(const http::Request&));
+ MOCK_METHOD1(pipe, Future<http::Response>(const http::Request&));
+};
+
+
+TEST(HTTP, Endpoints)
+{
+ ASSERT_TRUE(GTEST_IS_THREADSAFE);
+
+ HttpProcess process;
+
+ spawn(process);
+
+ // First hit '/body' (using explicit sockets and HTTP/1.0).
+ int s = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
+
+ ASSERT_LE(0, s);
+
+ sockaddr_in addr;
+ memset(&addr, 0, sizeof(addr));
+ addr.sin_family = PF_INET;
+ addr.sin_port = htons(process.self().port);
+ addr.sin_addr.s_addr = process.self().ip;
+
+ ASSERT_EQ(0, connect(s, (sockaddr*) &addr, sizeof(addr)));
+
+ std::ostringstream out;
+ out << "GET /" << process.self().id << "/body"
+ << " HTTP/1.0\r\n"
+ << "Connection: Keep-Alive\r\n"
+ << "\r\n";
+
+ const std::string& data = out.str();
+
+ EXPECT_CALL(process, body(_))
+ .WillOnce(Return(http::OK()));
+
+ ASSERT_SOME(os::write(s, data));
+
+ std::string response = "HTTP/1.1 200 OK";
+
+ char temp[response.size()];
+ ASSERT_LT(0, ::read(s, temp, response.size()));
+ ASSERT_EQ(response, std::string(temp, response.size()));
+
+ ASSERT_EQ(0, close(s));
+
+ // Now hit '/pipe' (by using http::get).
+ int pipes[2];
+ ASSERT_NE(-1, ::pipe(pipes));
+
+ http::OK ok;
+ ok.type = http::Response::PIPE;
+ ok.pipe = pipes[0];
+
+ Future<Nothing> pipe;
+ EXPECT_CALL(process, pipe(_))
+ .WillOnce(DoAll(FutureSatisfy(&pipe),
+ Return(ok)));
+
+ Future<http::Response> future = http::get(process.self(), "pipe");
+
+ AWAIT_READY(pipe);
+
+ ASSERT_SOME(os::write(pipes[1], "Hello World\n"));
+ ASSERT_SOME(os::close(pipes[1]));
+
+ AWAIT_READY(future);
+ ASSERT_EQ(http::statuses[200], future.get().status);
+ ASSERT_EQ("chunked", future.get().headers["Transfer-Encoding"]);
+ ASSERT_EQ("Hello World\n", future.get().body);
+
+ terminate(process);
+ wait(process);
+}
+
+
+TEST(HTTP, Encode)
+{
+ std::string unencoded = "a$&+,/:;=?@ \"<>#%{}|\\^~[]`\x19\x80\xFF";
+ unencoded += std::string("\x00", 1); // Add a null byte to the end.
+
+ std::string encoded = http::encode(unencoded);
+
+ EXPECT_EQ("a%24%26%2B%2C%2F%3A%3B%3D%3F%40%20%22%3C%3E%23"
+ "%25%7B%7D%7C%5C%5E%7E%5B%5D%60%19%80%FF%00",
+ encoded);
+
+ EXPECT_SOME_EQ(unencoded, http::decode(encoded));
+
+ EXPECT_ERROR(http::decode("%"));
+ EXPECT_ERROR(http::decode("%1"));
+ EXPECT_ERROR(http::decode("%;1"));
+ EXPECT_ERROR(http::decode("%1;"));
+}
http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/71a01bd9/3rdparty/libprocess/src/tests/io_tests.cpp
----------------------------------------------------------------------
diff --git a/3rdparty/libprocess/src/tests/io_tests.cpp b/3rdparty/libprocess/src/tests/io_tests.cpp
new file mode 100644
index 0000000..288fa83
--- /dev/null
+++ b/3rdparty/libprocess/src/tests/io_tests.cpp
@@ -0,0 +1,162 @@
+#include <gmock/gmock.h>
+
+#include <string>
+
+#include <process/future.hpp>
+#include <process/gtest.hpp>
+#include <process/io.hpp>
+
+#include <stout/gtest.hpp>
+#include <stout/os.hpp>
+
+#include "encoder.hpp"
+
+using namespace process;
+
+using std::string;
+
+
+TEST(IO, Poll)
+{
+ ASSERT_TRUE(GTEST_IS_THREADSAFE);
+
+ int pipes[2];
+ pipe(pipes);
+
+ Future<short> future = io::poll(pipes[0], io::READ);
+
+ EXPECT_FALSE(future.isReady());
+
+ ASSERT_EQ(3, write(pipes[1], "hi", 3));
+
+ AWAIT_EXPECT_EQ(io::READ, future);
+
+ close(pipes[0]);
+ close(pipes[1]);
+}
+
+
+TEST(IO, Read)
+{
+ ASSERT_TRUE(GTEST_IS_THREADSAFE);
+
+ int pipes[2];
+ char data[3];
+
+ // Create a blocking pipe.
+ ASSERT_NE(-1, ::pipe(pipes));
+
+ // Test on a blocking file descriptor.
+ AWAIT_EXPECT_FAILED(io::read(pipes[0], data, 3));
+
+ close(pipes[0]);
+ close(pipes[1]);
+
+ // Test on a closed file descriptor.
+ AWAIT_EXPECT_FAILED(io::read(pipes[0], data, 3));
+
+ // Create a nonblocking pipe.
+ ASSERT_NE(-1, ::pipe(pipes));
+ ASSERT_SOME(os::nonblock(pipes[0]));
+ ASSERT_SOME(os::nonblock(pipes[1]));
+
+ // Test reading nothing.
+ AWAIT_EXPECT_FAILED(io::read(pipes[0], data, 0));
+
+ // Test successful read.
+ Future<size_t> future = io::read(pipes[0], data, 3);
+ ASSERT_FALSE(future.isReady());
+
+ ASSERT_EQ(2, write(pipes[1], "hi", 2));
+
+ AWAIT_ASSERT_EQ(2u, future);
+ EXPECT_EQ('h', data[0]);
+ EXPECT_EQ('i', data[1]);
+
+ // Test cancellation.
+ future = io::read(pipes[0], data, 1);
+ ASSERT_FALSE(future.isReady());
+
+ future.discard();
+
+ ASSERT_EQ(3, write(pipes[1], "omg", 3));
+
+ AWAIT_ASSERT_EQ(3u, io::read(pipes[0], data, 3));
+ EXPECT_EQ('o', data[0]);
+ EXPECT_EQ('m', data[1]);
+ EXPECT_EQ('g', data[2]);
+
+ // Test read EOF.
+ future = io::read(pipes[0], data, 3);
+ ASSERT_FALSE(future.isReady());
+
+ close(pipes[1]);
+
+ AWAIT_ASSERT_EQ(0u, future);
+
+ close(pipes[0]);
+}
+
+
+TEST(IO, BufferedRead)
+{
+ // 128 Bytes.
+ string data =
+ "This data is much larger than BUFFERED_READ_SIZE, which means it will "
+ "trigger multiple buffered async reads as a result.........";
+ ASSERT_EQ(128u, data.size());
+
+ // Keep doubling the data size until we're guaranteed to trigger at least
+ // 3 buffered async reads.
+ while (data.length() < 3 * io::BUFFERED_READ_SIZE) {
+ data.append(data);
+ }
+
+ // First read from a file.
+ ASSERT_SOME(os::write("file", data));
+
+ Try<int> fd = os::open("file", O_RDONLY);
+ ASSERT_SOME(fd);
+
+ // Read from blocking fd.
+ AWAIT_EXPECT_FAILED(io::read(fd.get()));
+
+ // Read from non-blocking fd.
+ ASSERT_TRUE(os::nonblock(fd.get()).isSome());
+ AWAIT_EXPECT_EQ(data, io::read(fd.get()));
+
+ os::close(fd.get());
+
+ // Now read from pipes.
+ int pipes[2];
+
+ // Create a blocking pipe.
+ ASSERT_NE(-1, ::pipe(pipes));
+
+ // Test on a blocking pipe.
+ AWAIT_EXPECT_FAILED(io::read(pipes[0]));
+
+ close(pipes[0]);
+ close(pipes[1]);
+
+ // Test on a closed pipe.
+ AWAIT_EXPECT_FAILED(io::read(pipes[0]));
+
+ // Create a nonblocking pipe for reading.
+ ASSERT_NE(-1, ::pipe(pipes));
+ ASSERT_SOME(os::nonblock(pipes[0]));
+
+ // Test a successful read from the pipe.
+ Future<string> future = io::read(pipes[0]);
+
+ // At first, the future will not be ready until we write to and
+ // close the pipe.
+ ASSERT_FALSE(future.isReady());
+
+ ASSERT_SOME(os::write(pipes[1], data));
+ close(pipes[1]);
+
+ AWAIT_EXPECT_EQ(data, future);
+
+ close(pipes[0]);
+}
http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/71a01bd9/3rdparty/libprocess/src/tests/main.cpp
----------------------------------------------------------------------
diff --git a/3rdparty/libprocess/src/tests/main.cpp b/3rdparty/libprocess/src/tests/main.cpp
new file mode 100644
index 0000000..6c672b4
--- /dev/null
+++ b/3rdparty/libprocess/src/tests/main.cpp
@@ -0,0 +1,25 @@
+#include <gtest/gtest.h>
+
+#include <gmock/gmock.h>
+
+#include <process/gmock.hpp>
+#include <process/gtest.hpp>
+#include <process/process.hpp>
+
+int main(int argc, char** argv)
+{
+ // Initialize Google Mock/Test.
+ testing::InitGoogleMock(&argc, argv);
+
+ // Initialize libprocess.
+ process::initialize();
+
+ // Add the libprocess test event listeners.
+ ::testing::TestEventListeners& listeners =
+ ::testing::UnitTest::GetInstance()->listeners();
+
+ listeners.Append(process::ClockTestEventListener::instance());
+ listeners.Append(process::FilterTestEventListener::instance());
+
+ return RUN_ALL_TESTS();
+}
http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/71a01bd9/3rdparty/libprocess/src/tests/process_tests.cpp
----------------------------------------------------------------------
diff --git a/3rdparty/libprocess/src/tests/process_tests.cpp b/3rdparty/libprocess/src/tests/process_tests.cpp
new file mode 100644
index 0000000..dc5c671
--- /dev/null
+++ b/3rdparty/libprocess/src/tests/process_tests.cpp
@@ -0,0 +1,1143 @@
+#include <arpa/inet.h>
+
+#include <gmock/gmock.h>
+
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+
+#include <string>
+#include <sstream>
+
+#include <process/async.hpp>
+#include <process/collect.hpp>
+#include <process/clock.hpp>
+#include <process/defer.hpp>
+#include <process/delay.hpp>
+#include <process/dispatch.hpp>
+#include <process/executor.hpp>
+#include <process/filter.hpp>
+#include <process/future.hpp>
+#include <process/gc.hpp>
+#include <process/gmock.hpp>
+#include <process/gtest.hpp>
+#include <process/process.hpp>
+#include <process/run.hpp>
+#include <process/thread.hpp>
+#include <process/time.hpp>
+
+#include <stout/duration.hpp>
+#include <stout/nothing.hpp>
+#include <stout/os.hpp>
+#include <stout/stringify.hpp>
+
+#include "encoder.hpp"
+
+using namespace process;
+
+using testing::_;
+using testing::Assign;
+using testing::DoAll;
+using testing::Return;
+using testing::ReturnArg;
+
+// TODO(bmahler): Move tests into their own files as appropriate.
+
+TEST(Process, thread)
+{
+ ThreadLocal<ProcessBase>* _process_ = new ThreadLocal<ProcessBase>();
+
+ ProcessBase* process = new ProcessBase();
+
+ ASSERT_TRUE(*(_process_) == NULL);
+
+ (*_process_) = process;
+
+ ASSERT_TRUE(*(_process_) == process);
+ ASSERT_FALSE(*(_process_) == NULL);
+
+ (*_process_) = NULL;
+
+ ASSERT_TRUE(*(_process_) == NULL);
+
+ delete process;
+ delete _process_;
+}
+
+
+TEST(Process, event)
+{
+ Event* event = new TerminateEvent(UPID());
+ EXPECT_FALSE(event->is<MessageEvent>());
+ EXPECT_FALSE(event->is<ExitedEvent>());
+ EXPECT_TRUE(event->is<TerminateEvent>());
+ delete event;
+}
+
+
+TEST(Process, future)
+{
+ Promise<bool> promise;
+ promise.set(true);
+ ASSERT_TRUE(promise.future().isReady());
+ EXPECT_TRUE(promise.future().get());
+}
+
+
+TEST(Process, associate)
+{
+ Promise<bool> promise1;
+ Future<bool> future1(true);
+ promise1.associate(future1);
+ ASSERT_TRUE(promise1.future().isReady());
+ EXPECT_TRUE(promise1.future().get());
+
+ Promise<bool> promise2;
+ Future<bool> future2;
+ promise2.associate(future2);
+ future2.discard();
+ ASSERT_TRUE(promise2.future().isDiscarded());
+
+ Promise<bool> promise3;
+ Promise<bool> promise4;
+ promise3.associate(promise4.future());
+ promise4.fail("associate");
+ ASSERT_TRUE(promise3.future().isFailed());
+ EXPECT_EQ("associate", promise3.future().failure());
+}
+
+
+void onAny(const Future<bool>& future, bool* b)
+{
+ ASSERT_TRUE(future.isReady());
+ *b = future.get();
+}
+
+
+TEST(Process, onAny)
+{
+ bool b = false;
+ Future<bool>(true)
+ .onAny(std::tr1::bind(&onAny, std::tr1::placeholders::_1, &b));
+ EXPECT_TRUE(b);
+}
+
+
+Future<std::string> itoa1(int* const& i)
+{
+ std::ostringstream out;
+ out << *i;
+ return out.str();
+}
+
+
+std::string itoa2(int* const& i)
+{
+ std::ostringstream out;
+ out << *i;
+ return out.str();
+}
+
+
+TEST(Process, then)
+{
+ Promise<int*> promise;
+
+ int i = 42;
+
+ promise.set(&i);
+
+ Future<std::string> future = promise.future()
+ .then(std::tr1::bind(&itoa1, std::tr1::placeholders::_1));
+
+ ASSERT_TRUE(future.isReady());
+ EXPECT_EQ("42", future.get());
+
+ future = promise.future()
+ .then(std::tr1::bind(&itoa2, std::tr1::placeholders::_1));
+
+ ASSERT_TRUE(future.isReady());
+ EXPECT_EQ("42", future.get());
+}
+
+
+Future<bool> readyFuture()
+{
+ return true;
+}
+
+
+Future<bool> failedFuture()
+{
+ return Future<bool>::failed("The value is not positive (or zero)");
+}
+
+
+Future<bool> pendingFuture(Future<bool>* future)
+{
+ return *future; // Keep it pending.
+}
+
+
+Future<std::string> second(const bool& b)
+{
+ return b ? std::string("true") : std::string("false");
+}
+
+
+Future<std::string> third(const std::string& s)
+{
+ return s;
+}
+
+
+TEST(Process, chain)
+{
+ Promise<int*> promise;
+
+ Future<std::string> s = readyFuture()
+ .then(std::tr1::bind(&second, std::tr1::placeholders::_1))
+ .then(std::tr1::bind(&third, std::tr1::placeholders::_1));
+
+ s.await();
+
+ ASSERT_TRUE(s.isReady());
+ EXPECT_EQ("true", s.get());
+
+ s = failedFuture()
+ .then(std::tr1::bind(&second, std::tr1::placeholders::_1))
+ .then(std::tr1::bind(&third, std::tr1::placeholders::_1));
+
+ s.await();
+
+ ASSERT_TRUE(s.isFailed());
+
+ Future<bool> future;
+
+ s = pendingFuture(&future)
+ .then(std::tr1::bind(&second, std::tr1::placeholders::_1))
+ .then(std::tr1::bind(&third, std::tr1::placeholders::_1));
+
+ ASSERT_TRUE(s.isPending());
+ ASSERT_TRUE(future.isPending());
+
+ s.discard();
+
+ future.await();
+
+ ASSERT_TRUE(future.isDiscarded());
+}
+
+
+class SpawnProcess : public Process<SpawnProcess>
+{
+public:
+ MOCK_METHOD0(initialize, void(void));
+ MOCK_METHOD0(finalize, void(void));
+};
+
+
+TEST(Process, spawn)
+{
+ ASSERT_TRUE(GTEST_IS_THREADSAFE);
+
+ SpawnProcess process;
+
+ EXPECT_CALL(process, initialize())
+ .Times(1);
+
+ EXPECT_CALL(process, finalize())
+ .Times(1);
+
+ PID<SpawnProcess> pid = spawn(process);
+
+ ASSERT_FALSE(!pid);
+
+ ASSERT_FALSE(wait(pid, Seconds(0)));
+
+ terminate(pid);
+ wait(pid);
+}
+
+
+class DispatchProcess : public Process<DispatchProcess>
+{
+public:
+ MOCK_METHOD0(func0, void(void));
+ MOCK_METHOD1(func1, bool(bool));
+ MOCK_METHOD1(func2, Future<bool>(bool));
+ MOCK_METHOD1(func3, int(int));
+ MOCK_METHOD2(func4, Future<bool>(bool, int));
+};
+
+
+TEST(Process, dispatch)
+{
+ ASSERT_TRUE(GTEST_IS_THREADSAFE);
+
+ DispatchProcess process;
+
+ EXPECT_CALL(process, func0())
+ .Times(1);
+
+ EXPECT_CALL(process, func1(_))
+ .WillOnce(ReturnArg<0>());
+
+ EXPECT_CALL(process, func2(_))
+ .WillOnce(ReturnArg<0>());
+
+ PID<DispatchProcess> pid = spawn(&process);
+
+ ASSERT_FALSE(!pid);
+
+ dispatch(pid, &DispatchProcess::func0);
+
+ Future<bool> future;
+
+ future = dispatch(pid, &DispatchProcess::func1, true);
+
+ EXPECT_TRUE(future.get());
+
+ future = dispatch(pid, &DispatchProcess::func2, true);
+
+ EXPECT_TRUE(future.get());
+
+ terminate(pid);
+ wait(pid);
+}
+
+
+TEST(Process, defer1)
+{
+ ASSERT_TRUE(GTEST_IS_THREADSAFE);
+
+ DispatchProcess process;
+
+ EXPECT_CALL(process, func0())
+ .Times(1);
+
+ EXPECT_CALL(process, func1(_))
+ .WillOnce(ReturnArg<0>());
+
+ EXPECT_CALL(process, func2(_))
+ .WillOnce(ReturnArg<0>());
+
+ EXPECT_CALL(process, func4(_, _))
+ .WillRepeatedly(ReturnArg<0>());
+
+ PID<DispatchProcess> pid = spawn(&process);
+
+ ASSERT_FALSE(!pid);
+
+ {
+ Deferred<void(void)> func0 =
+ defer(pid, &DispatchProcess::func0);
+ func0();
+ }
+
+ Future<bool> future;
+
+ {
+ Deferred<Future<bool>(void)> func1 =
+ defer(pid, &DispatchProcess::func1, true);
+ future = func1();
+ EXPECT_TRUE(future.get());
+ }
+
+ {
+ Deferred<Future<bool>(void)> func2 =
+ defer(pid, &DispatchProcess::func2, true);
+ future = func2();
+ EXPECT_TRUE(future.get());
+ }
+
+ {
+ Deferred<Future<bool>(void)> func4 =
+ defer(pid, &DispatchProcess::func4, true, 42);
+ future = func4();
+ EXPECT_TRUE(future.get());
+ }
+
+ {
+ Deferred<Future<bool>(bool)> func4 =
+ defer(pid, &DispatchProcess::func4, std::tr1::placeholders::_1, 42);
+ future = func4(false);
+ EXPECT_FALSE(future.get());
+ }
+
+ {
+ Deferred<Future<bool>(int)> func4 =
+ defer(pid, &DispatchProcess::func4, true, std::tr1::placeholders::_1);
+ future = func4(42);
+ EXPECT_TRUE(future.get());
+ }
+
+ // Only take const &!
+
+ terminate(pid);
+ wait(pid);
+}
+
+
+class DeferProcess : public Process<DeferProcess>
+{
+public:
+ Future<std::string> func1(const Future<int>& f)
+ {
+ return f.then(defer(self(), &Self::_func1, std::tr1::placeholders::_1));
+ }
+
+ Future<std::string> func2(const Future<int>& f)
+ {
+ return f.then(defer(self(), &Self::_func2));
+ }
+
+private:
+ Future<std::string> _func1(int i)
+ {
+ return stringify(i);
+ }
+
+ Future<std::string> _func2()
+ {
+ return std::string("42");
+ }
+};
+
+
+TEST(Process, defer2)
+{
+ ASSERT_TRUE(GTEST_IS_THREADSAFE);
+
+ DeferProcess process;
+
+ PID<DeferProcess> pid = spawn(process);
+
+ Future<std::string> f = dispatch(pid, &DeferProcess::func1, 41);
+
+ f.await();
+
+ ASSERT_TRUE(f.isReady());
+ EXPECT_EQ("41", f.get());
+
+ f = dispatch(pid, &DeferProcess::func2, 41);
+
+ f.await();
+
+ ASSERT_TRUE(f.isReady());
+ EXPECT_EQ("42", f.get());
+
+ terminate(pid);
+ wait(pid);
+}
+
+
+template <typename T>
+void set(T* t1, const T& t2)
+{
+ *t1 = t2;
+}
+
+
+TEST(Process, defer3)
+{
+ ASSERT_TRUE(GTEST_IS_THREADSAFE);
+
+ volatile bool bool1 = false;
+ volatile bool bool2 = false;
+
+ Deferred<void(bool)> set1 =
+ defer(std::tr1::function<void(bool)>(
+ std::tr1::bind(&set<volatile bool>,
+ &bool1,
+ std::tr1::placeholders::_1)));
+
+ set1(true);
+
+ Deferred<void(bool)> set2 =
+ defer(std::tr1::function<void(bool)>(
+ std::tr1::bind(&set<volatile bool>,
+ &bool2,
+ std::tr1::placeholders::_1)));
+
+ set2(true);
+
+ while (!bool1);
+ while (!bool2);
+}
+
+
+class HandlersProcess : public Process<HandlersProcess>
+{
+public:
+ HandlersProcess()
+ {
+ install("func", &HandlersProcess::func);
+ }
+
+ MOCK_METHOD2(func, void(const UPID&, const std::string&));
+};
+
+
+TEST(Process, handlers)
+{
+ ASSERT_TRUE(GTEST_IS_THREADSAFE);
+
+ HandlersProcess process;
+
+ EXPECT_CALL(process, func(_, _))
+ .Times(1);
+
+ PID<HandlersProcess> pid = spawn(&process);
+
+ ASSERT_FALSE(!pid);
+
+ post(pid, "func");
+
+ terminate(pid, false);
+ wait(pid);
+}
+
+
+// Tests EXPECT_MESSAGE and EXPECT_DISPATCH and in particular that an
+// event can get dropped before being processed.
+TEST(Process, expect)
+{
+ ASSERT_TRUE(GTEST_IS_THREADSAFE);
+
+ HandlersProcess process;
+
+ EXPECT_CALL(process, func(_, _))
+ .Times(0);
+
+ PID<HandlersProcess> pid = spawn(&process);
+
+ ASSERT_FALSE(!pid);
+
+ Future<Message> message = DROP_MESSAGE("func", _, _);
+
+ post(pid, "func");
+
+ AWAIT_EXPECT_READY(message);
+
+ Future<Nothing> func = DROP_DISPATCH(pid, &HandlersProcess::func);
+
+ dispatch(pid, &HandlersProcess::func, pid, "");
+
+ AWAIT_EXPECT_READY(func);
+
+ terminate(pid, false);
+ wait(pid);
+}
+
+
+// Tests the FutureArg<N> action.
+TEST(Process, action)
+{
+ ASSERT_TRUE(GTEST_IS_THREADSAFE);
+
+ HandlersProcess process;
+
+ PID<HandlersProcess> pid = spawn(&process);
+
+ ASSERT_FALSE(!pid);
+
+ Future<std::string> future1;
+ Future<Nothing> future2;
+ EXPECT_CALL(process, func(_, _))
+ .WillOnce(FutureArg<1>(&future1))
+ .WillOnce(FutureSatisfy(&future2));
+
+ dispatch(pid, &HandlersProcess::func, pid, "hello world");
+
+ AWAIT_EXPECT_EQ("hello world", future1);
+
+ EXPECT_TRUE(future2.isPending());
+
+ dispatch(pid, &HandlersProcess::func, pid, "hello world");
+
+ AWAIT_EXPECT_READY(future2);
+
+ terminate(pid, false);
+ wait(pid);
+}
+
+
+class BaseProcess : public Process<BaseProcess>
+{
+public:
+ virtual void func() = 0;
+ MOCK_METHOD0(foo, void());
+};
+
+
+class DerivedProcess : public BaseProcess
+{
+public:
+ DerivedProcess() {}
+ MOCK_METHOD0(func, void());
+};
+
+
+TEST(Process, inheritance)
+{
+ ASSERT_TRUE(GTEST_IS_THREADSAFE);
+
+ DerivedProcess process;
+
+ EXPECT_CALL(process, func())
+ .Times(2);
+
+ EXPECT_CALL(process, foo())
+ .Times(1);
+
+ PID<DerivedProcess> pid1 = spawn(&process);
+
+ ASSERT_FALSE(!pid1);
+
+ dispatch(pid1, &DerivedProcess::func);
+
+ PID<BaseProcess> pid2(process);
+ PID<BaseProcess> pid3 = pid1;
+
+ ASSERT_EQ(pid2, pid3);
+
+ dispatch(pid3, &BaseProcess::func);
+ dispatch(pid3, &BaseProcess::foo);
+
+ terminate(pid1, false);
+ wait(pid1);
+}
+
+
+TEST(Process, thunk)
+{
+ ASSERT_TRUE(GTEST_IS_THREADSAFE);
+
+ struct Thunk
+ {
+ static int run(int i)
+ {
+ return i;
+ }
+
+ static int run(int i, int j)
+ {
+ return run(i + j);
+ }
+ };
+
+ int result = run(&Thunk::run, 21, 21).get();
+
+ EXPECT_EQ(42, result);
+}
+
+
+class DelegatorProcess : public Process<DelegatorProcess>
+{
+public:
+ DelegatorProcess(const UPID& delegatee)
+ {
+ delegate("func", delegatee);
+ }
+};
+
+
+class DelegateeProcess : public Process<DelegateeProcess>
+{
+public:
+ DelegateeProcess()
+ {
+ install("func", &DelegateeProcess::func);
+ }
+
+ MOCK_METHOD2(func, void(const UPID&, const std::string&));
+};
+
+
+TEST(Process, delegate)
+{
+ ASSERT_TRUE(GTEST_IS_THREADSAFE);
+
+ DelegateeProcess delegatee;
+ DelegatorProcess delegator(delegatee.self());
+
+ EXPECT_CALL(delegatee, func(_, _))
+ .Times(1);
+
+ spawn(&delegator);
+ spawn(&delegatee);
+
+ post(delegator.self(), "func");
+
+ terminate(delegator, false);
+ wait(delegator);
+
+ terminate(delegatee, false);
+ wait(delegatee);
+}
+
+
+class TimeoutProcess : public Process<TimeoutProcess>
+{
+public:
+ MOCK_METHOD0(timeout, void());
+};
+
+
+TEST(Process, delay)
+{
+ ASSERT_TRUE(GTEST_IS_THREADSAFE);
+
+ Clock::pause();
+
+ volatile bool timeoutCalled = false;
+
+ TimeoutProcess process;
+
+ EXPECT_CALL(process, timeout())
+ .WillOnce(Assign(&timeoutCalled, true));
+
+ spawn(process);
+
+ delay(Seconds(5), process.self(), &TimeoutProcess::timeout);
+
+ Clock::advance(Seconds(5));
+
+ while (!timeoutCalled);
+
+ terminate(process);
+ wait(process);
+
+ Clock::resume();
+}
+
+
+class OrderProcess : public Process<OrderProcess>
+{
+public:
+ void order(const PID<TimeoutProcess>& pid)
+ {
+ // TODO(benh): Add a test which uses 'send' instead of dispatch.
+ dispatch(pid, &TimeoutProcess::timeout);
+ }
+};
+
+
+TEST(Process, order)
+{
+ ASSERT_TRUE(GTEST_IS_THREADSAFE);
+
+ Clock::pause();
+
+ TimeoutProcess process1;
+
+ volatile bool timeoutCalled = false;
+
+ EXPECT_CALL(process1, timeout())
+ .WillOnce(Assign(&timeoutCalled, true));
+
+ spawn(process1);
+
+ Time now = Clock::now(&process1);
+
+ Seconds seconds(1);
+
+ Clock::advance(Seconds(1));
+
+ EXPECT_EQ(now, Clock::now(&process1));
+
+ OrderProcess process2;
+ spawn(process2);
+
+ dispatch(process2, &OrderProcess::order, process1.self());
+
+ while (!timeoutCalled);
+
+ EXPECT_EQ(now + seconds, Clock::now(&process1));
+
+ terminate(process1);
+ wait(process1);
+
+ terminate(process2);
+ wait(process2);
+
+ Clock::resume();
+}
+
+
+class DonateProcess : public Process<DonateProcess>
+{
+public:
+ void donate()
+ {
+ DonateProcess process;
+ spawn(process);
+ terminate(process);
+ wait(process);
+ }
+};
+
+
+TEST(Process, donate)
+{
+ ASSERT_TRUE(GTEST_IS_THREADSAFE);
+
+ DonateProcess process;
+ spawn(process);
+
+ dispatch(process, &DonateProcess::donate);
+
+ terminate(process, false);
+ wait(process);
+}
+
+
+class ExitedProcess : public Process<ExitedProcess>
+{
+public:
+ ExitedProcess(const UPID& pid) { link(pid); }
+
+ MOCK_METHOD1(exited, void(const UPID&));
+};
+
+
+TEST(Process, exited)
+{
+ ASSERT_TRUE(GTEST_IS_THREADSAFE);
+
+ UPID pid = spawn(new ProcessBase(), true);
+
+ ExitedProcess process(pid);
+
+ volatile bool exitedCalled = false;
+
+ EXPECT_CALL(process, exited(pid))
+ .WillOnce(Assign(&exitedCalled, true));
+
+ spawn(process);
+
+ terminate(pid);
+
+ while (!exitedCalled);
+
+ terminate(process);
+ wait(process);
+}
+
+
+TEST(Process, select)
+{
+ ASSERT_TRUE(GTEST_IS_THREADSAFE);
+
+ Promise<int> promise1;
+ Promise<int> promise2;
+ Promise<int> promise3;
+ Promise<int> promise4;
+
+ std::set<Future<int> > futures;
+ futures.insert(promise1.future());
+ futures.insert(promise2.future());
+ futures.insert(promise3.future());
+ futures.insert(promise4.future());
+
+ promise1.set(42);
+
+ Future<Future<int> > future = select(futures);
+
+ EXPECT_TRUE(future.await());
+ EXPECT_TRUE(future.isReady());
+ EXPECT_TRUE(future.get().isReady());
+ EXPECT_EQ(42, future.get().get());
+}
+
+
+TEST(Process, collect)
+{
+ ASSERT_TRUE(GTEST_IS_THREADSAFE);
+
+ Promise<int> promise1;
+ Promise<int> promise2;
+ Promise<int> promise3;
+ Promise<int> promise4;
+
+ std::list<Future<int> > futures;
+ futures.push_back(promise1.future());
+ futures.push_back(promise2.future());
+ futures.push_back(promise3.future());
+ futures.push_back(promise4.future());
+
+ promise1.set(1);
+ promise2.set(2);
+ promise3.set(3);
+ promise4.set(4);
+
+ Future<std::list<int> > future = collect(futures);
+
+ EXPECT_TRUE(future.await());
+ EXPECT_TRUE(future.isReady());
+
+ std::list<int> values;
+ values.push_back(1);
+ values.push_back(2);
+ values.push_back(3);
+ values.push_back(4);
+
+ EXPECT_EQ(values, future.get());
+}
+
+
+class SettleProcess : public Process<SettleProcess>
+{
+public:
+ SettleProcess() : calledDispatch(false) {}
+
+ virtual void initialize()
+ {
+ os::sleep(Milliseconds(10));
+ delay(Seconds(0), self(), &SettleProcess::afterDelay);
+ }
+
+ void afterDelay()
+ {
+ dispatch(self(), &SettleProcess::afterDispatch);
+ os::sleep(Milliseconds(10));
+ TimeoutProcess timeoutProcess;
+ spawn(timeoutProcess);
+ terminate(timeoutProcess);
+ wait(timeoutProcess);
+ }
+
+ void afterDispatch()
+ {
+ os::sleep(Milliseconds(10));
+ calledDispatch = true;
+ }
+
+ volatile bool calledDispatch;
+};
+
+
+TEST(Process, settle)
+{
+ ASSERT_TRUE(GTEST_IS_THREADSAFE);
+
+ Clock::pause();
+ SettleProcess process;
+ spawn(process);
+ Clock::settle();
+ ASSERT_TRUE(process.calledDispatch);
+ terminate(process);
+ wait(process);
+ Clock::resume();
+}
+
+
+TEST(Process, pid)
+{
+ ASSERT_TRUE(GTEST_IS_THREADSAFE);
+
+ TimeoutProcess process;
+
+ PID<TimeoutProcess> pid = process;
+}
+
+
+class Listener1 : public Process<Listener1>
+{
+public:
+ virtual void event1() = 0;
+};
+
+
+class Listener2 : public Process<Listener2>
+{
+public:
+ virtual void event2() = 0;
+};
+
+
+class MultipleListenerProcess
+ : public Process<MultipleListenerProcess>,
+ public Listener1,
+ public Listener2
+{
+public:
+ MOCK_METHOD0(event1, void());
+ MOCK_METHOD0(event2, void());
+};
+
+
+TEST(Process, listener)
+{
+ ASSERT_TRUE(GTEST_IS_THREADSAFE);
+
+ MultipleListenerProcess process;
+
+ EXPECT_CALL(process, event1())
+ .Times(1);
+
+ EXPECT_CALL(process, event2())
+ .Times(1);
+
+ spawn(process);
+
+ dispatch(PID<Listener1>(process), &Listener1::event1);
+ dispatch(PID<Listener2>(process), &Listener2::event2);
+
+ terminate(process, false);
+ wait(process);
+}
+
+
+class EventReceiver
+{
+public:
+ MOCK_METHOD1(event1, void(int));
+ MOCK_METHOD1(event2, void(const std::string&));
+};
+
+
+TEST(Process, executor)
+{
+ ASSERT_TRUE(GTEST_IS_THREADSAFE);
+
+ volatile bool event1Called = false;
+ volatile bool event2Called = false;
+
+ EventReceiver receiver;
+
+ EXPECT_CALL(receiver, event1(42))
+ .WillOnce(Assign(&event1Called, true));
+
+ EXPECT_CALL(receiver, event2("event2"))
+ .WillOnce(Assign(&event2Called, true));
+
+ Executor executor;
+
+ Deferred<void(int)> event1 =
+ executor.defer(std::tr1::bind(&EventReceiver::event1,
+ &receiver,
+ std::tr1::placeholders::_1));
+
+ event1(42);
+
+ Deferred<void(const std::string&)> event2 =
+ executor.defer(std::tr1::bind(&EventReceiver::event2,
+ &receiver,
+ std::tr1::placeholders::_1));
+
+ event2("event2");
+
+ while (!event1Called);
+ while (!event2Called);
+}
+
+
+class RemoteProcess : public Process<RemoteProcess>
+{
+public:
+ RemoteProcess()
+ {
+ install("handler", &RemoteProcess::handler);
+ }
+
+ MOCK_METHOD2(handler, void(const UPID&, const std::string&));
+};
+
+
+TEST(Process, remote)
+{
+ ASSERT_TRUE(GTEST_IS_THREADSAFE);
+
+ RemoteProcess process;
+
+ volatile bool handlerCalled = false;
+
+ EXPECT_CALL(process, handler(_, _))
+ .WillOnce(Assign(&handlerCalled, true));
+
+ spawn(process);
+
+ int s = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
+
+ ASSERT_LE(0, s);
+
+ sockaddr_in addr;
+ memset(&addr, 0, sizeof(addr));
+ addr.sin_family = PF_INET;
+ addr.sin_port = htons(process.self().port);
+ addr.sin_addr.s_addr = process.self().ip;
+
+ ASSERT_EQ(0, connect(s, (sockaddr*) &addr, sizeof(addr)));
+
+ Message message;
+ message.name = "handler";
+ message.from = UPID();
+ message.to = process.self();
+
+ const std::string& data = MessageEncoder::encode(&message);
+
+ ASSERT_EQ(data.size(), write(s, data.data(), data.size()));
+
+ ASSERT_EQ(0, close(s));
+
+ while (!handlerCalled);
+
+ terminate(process);
+ wait(process);
+}
+
+
+int foo()
+{
+ return 1;
+}
+
+int foo1(int a)
+{
+ return a;
+}
+
+
+int foo2(int a, int b)
+{
+ return a + b;
+}
+
+
+int foo3(int a, int b, int c)
+{
+ return a + b + c;
+}
+
+
+int foo4(int a, int b, int c, int d)
+{
+ return a + b + c + d;
+}
+
+
+void bar(int a)
+{
+ return;
+}
+
+
+TEST(Process, async)
+{
+ ASSERT_TRUE(GTEST_IS_THREADSAFE);
+
+ // Non-void functions with different no.of args.
+ EXPECT_EQ(1, async(&foo).get());
+ EXPECT_EQ(10, async(&foo1, 10).get());
+ EXPECT_EQ(30, async(&foo2, 10, 20).get());
+ EXPECT_EQ(60, async(&foo3, 10, 20, 30).get());
+ EXPECT_EQ(100, async(&foo4, 10, 20, 30, 40).get());
+
+ // Non-void function with a complex arg.
+ int i = 42;
+ EXPECT_EQ("42", async(&itoa2, &i).get());
+
+ // Non-void function that returns a future.
+ EXPECT_EQ("42", async(&itoa1, &i).get().get());
+}
http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/71a01bd9/3rdparty/libprocess/src/tests/statistics_tests.cpp
----------------------------------------------------------------------
diff --git a/3rdparty/libprocess/src/tests/statistics_tests.cpp b/3rdparty/libprocess/src/tests/statistics_tests.cpp
new file mode 100644
index 0000000..8695f45
--- /dev/null
+++ b/3rdparty/libprocess/src/tests/statistics_tests.cpp
@@ -0,0 +1,184 @@
+#include <gmock/gmock.h>
+
+#include <map>
+
+#include <process/clock.hpp>
+#include <process/future.hpp>
+#include <process/gtest.hpp>
+#include <process/statistics.hpp>
+#include <process/time.hpp>
+
+#include <stout/duration.hpp>
+
+using namespace process;
+
+using std::map;
+
+
+TEST(Statistics, set)
+{
+ Statistics statistics(Days(1));
+
+ // Set one using Clock::now() implicitly.
+ statistics.set("test", "statistic", 3.0);
+
+ // Set one using Clock::now() explicitly.
+ Time now = Clock::now();
+ statistics.set("test", "statistic", 4.0, now);
+
+ Future<map<Time, double> > values =
+ statistics.timeseries("test", "statistic");
+
+ AWAIT_ASSERT_READY(values);
+
+ EXPECT_EQ(2, values.get().size());
+
+ EXPECT_GE(Clock::now(), values.get().begin()->first);
+ EXPECT_DOUBLE_EQ(3.0, values.get().begin()->second);
+
+ EXPECT_EQ(1, values.get().count(now));
+ EXPECT_DOUBLE_EQ(4.0, values.get()[now]);
+}
+
+
+TEST(Statistics, truncate)
+{
+ Clock::pause();
+
+ Statistics statistics(Days(1));
+
+ statistics.set("test", "statistic", 3.0);
+
+ Future<map<Time, double> > values =
+ statistics.timeseries("test", "statistic");
+
+ AWAIT_ASSERT_READY(values);
+
+ EXPECT_EQ(1, values.get().size());
+ EXPECT_GE(Clock::now(), values.get().begin()->first);
+ EXPECT_DOUBLE_EQ(3.0, values.get().begin()->second);
+
+ Clock::advance(Days(1) + Seconds(1));
+ Clock::settle();
+
+ statistics.increment("test", "statistic");
+
+ values = statistics.timeseries("test", "statistic");
+
+ AWAIT_ASSERT_READY(values);
+
+ EXPECT_EQ(1, values.get().size());
+ EXPECT_GE(Clock::now(), values.get().begin()->first);
+ EXPECT_DOUBLE_EQ(4.0, values.get().begin()->second);
+
+ Clock::resume();
+}
+
+
+TEST(Statistics, meter) {
+ Statistics statistics(Days(1));
+
+ // Set up a meter, and ensure it captures the expected time rate.
+ Future<Try<Nothing> > meter =
+ statistics.meter("test", "statistic", new meters::TimeRate("metered"));
+
+ AWAIT_ASSERT_READY(meter);
+
+ ASSERT_TRUE(meter.get().isSome());
+
+ Time now = Clock::now();
+ statistics.set("test", "statistic", 1.0, now);
+ statistics.set("test", "statistic", 2.0, Time(now + Seconds(1)));
+ statistics.set("test", "statistic", 4.0, Time(now + Seconds(2)));
+
+ // Check the raw statistic values.
+ Future<map<Time, double> > values =
+ statistics.timeseries("test", "statistic");
+
+ AWAIT_ASSERT_READY(values);
+
+ EXPECT_EQ(3, values.get().size());
+ EXPECT_EQ(1, values.get().count(now));
+ EXPECT_EQ(1, values.get().count(Time(now + Seconds(1))));
+ EXPECT_EQ(1, values.get().count(Time(now + Seconds(2))));
+
+ EXPECT_EQ(1.0, values.get()[now]);
+ EXPECT_EQ(2.0, values.get()[Time(now + Seconds(1))]);
+ EXPECT_EQ(4.0, values.get()[Time(now + Seconds(2))]);
+
+ // Now check the metered values.
+ values = statistics.timeseries("test", "metered");
+
+ AWAIT_ASSERT_READY(values);
+
+ EXPECT_EQ(2, values.get().size());
+ EXPECT_EQ(1, values.get().count(Time(now + Seconds(1))));
+ EXPECT_EQ(1, values.get().count(Time(now + Seconds(2))));
+
+ EXPECT_EQ(0., values.get()[now]);
+ EXPECT_EQ(1.0, values.get()[Time(now + Seconds(1))]); // 100%.
+ EXPECT_EQ(2.0, values.get()[Time(now + Seconds(2))]); // 200%.
+}
+
+
+TEST(Statistics, archive)
+{
+ Clock::pause();
+
+ Statistics statistics(Seconds(10));
+
+ // Create a meter and a statistic for archival.
+ // Set up a meter, and ensure it captures the expected time rate.
+ Future<Try<Nothing> > meter =
+ statistics.meter("test", "statistic", new meters::TimeRate("metered"));
+
+ AWAIT_ASSERT_READY(meter);
+
+ ASSERT_TRUE(meter.get().isSome());
+
+ Time now = Clock::now();
+ statistics.set("test", "statistic", 1.0, now);
+ statistics.set("test", "statistic", 2.0, Time(now + Seconds(1)));
+
+ // Archive and ensure the following:
+ // 1. The statistic will no longer be part of the snapshot.
+ // 2. Any meters associated with this statistic will be removed.
+ // 3. However, the time series will be retained until the window expiration.
+ statistics.archive("test", "statistic");
+
+ // TODO(bmahler): Wait for JSON parsing to verify number 1.
+
+ // Ensure the raw time series is present.
+ Future<map<Time, double> > values =
+ statistics.timeseries("test", "statistic");
+ AWAIT_ASSERT_READY(values);
+ EXPECT_FALSE(values.get().empty());
+
+ // Ensure the metered timeseries is present.
+ values = statistics.timeseries("test", "metered");
+ AWAIT_ASSERT_READY(values);
+ EXPECT_FALSE(values.get().empty());
+
+ // Expire the window and ensure the statistics were removed.
+ Clock::advance(STATISTICS_TRUNCATION_INTERVAL);
+ Clock::settle();
+
+ // Ensure the raw statistics are gone.
+ values = statistics.timeseries("test", "statistic");
+ AWAIT_ASSERT_READY(values);
+ EXPECT_TRUE(values.get().empty());
+
+ // Ensure the metered statistics are gone.
+ values = statistics.timeseries("test", "metered");
+ AWAIT_ASSERT_READY(values);
+ EXPECT_TRUE(values.get().empty());
+
+ // Reactivate the statistic, and make sure the meter is still missing.
+ statistics.set("test", "statistic", 1.0, now);
+
+ values = statistics.timeseries("test", "metered");
+ AWAIT_ASSERT_READY(values);
+ EXPECT_TRUE(values.get().empty());
+
+ Clock::resume();
+}
http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/71a01bd9/3rdparty/libprocess/src/tests/time_tests.cpp
----------------------------------------------------------------------
diff --git a/3rdparty/libprocess/src/tests/time_tests.cpp b/3rdparty/libprocess/src/tests/time_tests.cpp
new file mode 100644
index 0000000..a25827e
--- /dev/null
+++ b/3rdparty/libprocess/src/tests/time_tests.cpp
@@ -0,0 +1,46 @@
+#include <gtest/gtest.h>
+
+#include <gmock/gmock.h>
+
+#include <process/clock.hpp>
+#include <process/time.hpp>
+
+#include <stout/duration.hpp>
+#include <stout/gtest.hpp>
+#include <stout/os.hpp>
+
+using namespace process;
+
+
+TEST(TimeTest, Arithmetic)
+{
+ Time t = Time::EPOCH + Weeks(1000);
+ t -= Weeks(1);
+ EXPECT_EQ(Time::EPOCH + Weeks(999), t);
+
+ t += Weeks(2);
+ EXPECT_EQ(Time::EPOCH + Weeks(1001), t);
+
+ EXPECT_EQ(t, Time::EPOCH + Weeks(1000) + Weeks(1));
+ EXPECT_EQ(t, Time::EPOCH + Weeks(1002) - Weeks(1));
+
+ EXPECT_EQ(Weeks(1), (Time::EPOCH + Weeks(1000)) - (Time::EPOCH + Weeks(999)));
+}
+
+
+TEST(TimeTest, Now)
+{
+ Time t1 = Clock::now();
+ os::sleep(Microseconds(10));
+ ASSERT_LT(Microseconds(10), Clock::now() - t1);
+}
+
+
+TEST(TimeTest, Output)
+{
+ EXPECT_EQ("1989-03-02 00:00:00+00:00", stringify(Time::EPOCH + Weeks(1000)));
+ EXPECT_EQ("1989-03-02 00:00:00.000000001+00:00",
+ stringify(Time::EPOCH + Weeks(1000) + Nanoseconds(1)));
+ EXPECT_EQ("1989-03-02 00:00:00.000001000+00:00",
+ stringify(Time::EPOCH + Weeks(1000) + Microseconds(1)));
+}
http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/71a01bd9/3rdparty/libprocess/src/timer.cpp
----------------------------------------------------------------------
diff --git a/3rdparty/libprocess/src/timer.cpp b/3rdparty/libprocess/src/timer.cpp
new file mode 100644
index 0000000..63c5ac1
--- /dev/null
+++ b/3rdparty/libprocess/src/timer.cpp
@@ -0,0 +1,56 @@
+#include <process/timer.hpp>
+
+#include "timeout.hpp"
+
+namespace process {
+
+class TimerProcess : public Process<TimerProcess>
+{
+public:
+ TimerProcess(double _secs,
+ const UPID& _pid,
+ std::tr1::function<void(ProcessBase*)>* _dispatcher)
+ : secs(_secs), pid(_pid), dispatcher(_dispatcher) {}
+
+protected:
+ virtual void operator () ()
+ {
+ if (receive(secs) == TIMEOUT) {
+ internal::dispatch(pid, dispatcher);
+ } else {
+ delete dispatcher;
+ }
+ }
+
+private:
+ const double secs;
+ const UPID pid;
+ std::tr1::function<void(ProcessBase*)>* dispatcher;
+};
+
+
+static void dispatch()
+
+
+Timer::Timer(double secs,
+ const UPID& pid,
+ std::tr1::function<void(ProcessBase*)>* dispatcher)
+{
+ timer = spawn(new TimerProcess(secs, pid, dispatcher), true);
+}
+
+
+Timer::~Timer()
+{
+ // NOTE: Do not terminate the timer! Some users will simply ignore
+ // saving the timer because they never want to cancel, thus
+ // we can not terminate it here!
+}
+
+
+void Timer::cancel()
+{
+ timeouts::cancel(timeout);
+}
+
+} // namespace process {
http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/71a01bd9/3rdparty/libprocess/src/timer.hpp
----------------------------------------------------------------------
diff --git a/3rdparty/libprocess/src/timer.hpp b/3rdparty/libprocess/src/timer.hpp
new file mode 100644
index 0000000..443b5a0
--- /dev/null
+++ b/3rdparty/libprocess/src/timer.hpp
@@ -0,0 +1,125 @@
+#ifndef TIMER_HPP
+#define TIMER_HPP
+
+#include <ctime>
+#include <iostream>
+#include <iomanip>
+
+class timer
+{
+ friend std::ostream& operator<<(std::ostream& os, timer& t);
+
+private:
+ bool running;
+ clock_t start_clock;
+ time_t start_time;
+ double acc_time;
+
+ double elapsed_time();
+
+public:
+ // 'running' is initially false. A timer needs to be explicitly started
+ // using 'start' or 'restart'
+ timer() : running(false), start_clock(0), start_time(0), acc_time(0) { }
+
+ void start(const char* msg = 0);
+ void restart(const char* msg = 0);
+ void stop(const char* msg = 0);
+ void check(const char* msg = 0);
+
+}; // class timer
+
+//===========================================================================
+// Return the total time that the timer has been in the "running"
+// state since it was first "started" or last "restarted". For
+// "short" time periods (less than an hour), the actual cpu time
+// used is reported instead of the elapsed time.
+
+inline double timer::elapsed_time()
+{
+ time_t acc_sec = time(0) - start_time;
+ if (acc_sec < 3600)
+ return (clock() - start_clock) / (1.0 * CLOCKS_PER_SEC);
+ else
+ return (1.0 * acc_sec);
+
+} // timer::elapsed_time
+
+//===========================================================================
+// Start a timer. If it is already running, let it continue running.
+// Print an optional message.
+
+inline void timer::start(const char* msg)
+{
+ // Print an optional message, something like "Starting timer t";
+ if (msg) std::cout << msg << std::endl;
+
+ // Return immediately if the timer is already running
+ if (running) return;
+
+ // Set timer status to running and set the start time
+ running = true;
+ start_clock = clock();
+ start_time = time(0);
+
+} // timer::start
+
+//===========================================================================
+// Turn the timer off and start it again from 0. Print an optional message.
+
+inline void timer::restart(const char* msg)
+{
+ // Print an optional message, something like "Restarting timer t";
+ if (msg) std::cout << msg << std::endl;
+
+ // Set timer status to running, reset accumulated time, and set start time
+ running = true;
+ acc_time = 0;
+ start_clock = clock();
+ start_time = time(0);
+
+} // timer::restart
+
+//===========================================================================
+// Stop the timer and print an optional message.
+
+inline void timer::stop(const char* msg)
+{
+ // Print an optional message, something like "Stopping timer t";
+ if (msg) std::cout << msg << std::endl;
+
+ // Compute accumulated running time and set timer status to not running
+ if (running) acc_time += elapsed_time();
+ running = false;
+
+} // timer::stop
+
+//===========================================================================
+// Print out an optional message followed by the current timer timing.
+
+inline void timer::check(const char* msg)
+{
+ // Print an optional message, something like "Checking timer t";
+ if (msg) std::cout << msg << " : ";
+
+ std::cout << "Elapsed time [" << std::setiosflags(std::ios::fixed)
+ << std::setprecision(2)
+ << acc_time + (running ? elapsed_time() : 0) << "] seconds\n";
+
+} // timer::check
+
+//===========================================================================
+// Allow timers to be printed to ostreams using the syntax 'os << t'
+// for an ostream 'os' and a timer 't'. For example, "cout << t" will
+// print out the total amount of time 't' has been "running".
+
+inline std::ostream& operator<<(std::ostream& os, timer& t)
+{
+ os << std::setprecision(2) << std::setiosflags(std::ios::fixed)
+ << t.acc_time + (t.running ? t.elapsed_time() : 0);
+ return os;
+}
+
+//===========================================================================
+
+#endif /* TIMER_HPP */
http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/71a01bd9/3rdparty/versions.am
----------------------------------------------------------------------
diff --git a/3rdparty/versions.am b/3rdparty/versions.am
new file mode 100644
index 0000000..5932e1f
--- /dev/null
+++ b/3rdparty/versions.am
@@ -0,0 +1,24 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License
+
+# This automake utility file is included from 3rdparty/Makefile.am
+# and src/Makefile.am, so we can update the version numbers of
+# third-party packages in exactly one place. For now, however, we
+# still need to update version numbers in src/python/setup.py.in too!
+
+BOTO_VERSION = 2.0b2
+DISTRIBUTE_VERSION = 0.6.26
+ZOOKEEPER_VERSION = 3.3.4
http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/71a01bd9/3rdparty/zookeeper-3.3.4.tar.gz
----------------------------------------------------------------------
diff --git a/3rdparty/zookeeper-3.3.4.tar.gz b/3rdparty/zookeeper-3.3.4.tar.gz
new file mode 100644
index 0000000..09d4924
Binary files /dev/null and b/3rdparty/zookeeper-3.3.4.tar.gz differ
http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/71a01bd9/LICENSE
----------------------------------------------------------------------
diff --git a/LICENSE b/LICENSE
index 6d9ab63..180e48a 100644
--- a/LICENSE
+++ b/LICENSE
@@ -211,8 +211,8 @@ subcomponents is subject to the terms and conditions of the following
licenses.
======================================================================
-For the Boost header files (third_party/boost-1.37.0.tar.gz and
-third_party/libprocess/third_party/boost-1.37.0.tar.gz):
+For the Boost header files
+(3rdparty/libprocess/3rdparty/boost-1.37.0.tar.gz):
======================================================================
Boost Software License - Version 1.0 - August 17th, 2003
@@ -241,7 +241,7 @@ DEALINGS IN THE SOFTWARE.
======================================================================
-For boto (third_party/boto-2.0b2.zip):
+For boto (3rdparty/boto-2.0b2.zip):
======================================================================
Permission is hereby granted, free of charge, to any person obtaining a
@@ -265,7 +265,7 @@ IN THE SOFTWARE.
======================================================================
-For distribute-0.6.26 (third_party/distribute-0.6.26.tar.gz):
+For distribute-0.6.26 (3rdparty/distribute-0.6.26.tar.gz):
======================================================================
PYTHON SOFTWARE FOUNDATION LICENSE VERSION 2
@@ -319,8 +319,7 @@ Agreement.
======================================================================
-For glog-0.3.1 (third_party/glog-0.3.1.tar.gz and
-third_party/libprocess/third_party/glog-0.3.1.tar.gz):
+For glog-0.3.1 (3rdparty/libprocess/3rdparty/glog-0.3.1.tar.gz):
======================================================================
Copyright (c) 2008, Google Inc.
@@ -391,8 +390,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
======================================================================
-For gmock-1.6.0 (third_party/gmock-1.6.0.tar.gz and
-third_party/libprocess/third_party/gmock-1.6.0.tar.gz):
+For gmock-1.6.0 (3rdparty/libprocess/3rdparty/gmock-1.6.0.tar.gz):
======================================================================
Copyright 2008, Google Inc.
@@ -426,7 +424,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
======================================================================
-For leveldb (third_party/leveldb.tar.gz):
+For leveldb (3rdparty/leveldb.tar.gz):
======================================================================
Copyright (c) 2011 The LevelDB Authors. All rights reserved.
@@ -459,7 +457,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
======================================================================
-For protobuf-2.3.0 (third_party/protobuf-2.3.0.tar.gz):
+For protobuf-2.3.0
+(3rdparty/libprocess/3rdparty/protobuf-2.3.0.tar.gz):
======================================================================
Copyright 2008, Google Inc.
@@ -498,7 +497,7 @@ support library is itself covered by the above license.
======================================================================
-For libev-3.8 (third_party/libprocess/third_party/libev.tar.gz):
+For libev-3.8 (3rdparty/libprocess/3rdparty/libev.tar.gz):
======================================================================
All files in libev are Copyright (C)2007,2008,2009 Marc Alexander Lehmann.
@@ -541,7 +540,7 @@ file under either the BSD or the GPL.
======================================================================
For http-parser
-(third_party/libprocess/third_party/ry-http-parser-1c3624a.tar.gz):
+(3rdparty/libprocess/3rdparty/ry-http-parser-1c3624a.tar.gz):
======================================================================
Copyright 2009,2010 Ryan Dahl <ry...@tinyclouds.org>
http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/71a01bd9/Makefile.am
----------------------------------------------------------------------
diff --git a/Makefile.am b/Makefile.am
index 3374da4..8e7a32f 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -18,7 +18,7 @@ ACLOCAL_AMFLAGS = -I m4
AUTOMAKE_OPTIONS = foreign
-SUBDIRS = . third_party src ec2 hadoop
+SUBDIRS = . 3rdparty src ec2 hadoop
EXTRA_DIST =
http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/71a01bd9/bootstrap
----------------------------------------------------------------------
diff --git a/bootstrap b/bootstrap
index cefc2ab..fe542a0 100755
--- a/bootstrap
+++ b/bootstrap
@@ -10,7 +10,7 @@ fi
# Note that we don't use '--no-recursive' becuase older versions of
# autoconf/autoreconf bail with that option. Unfortunately this means
-# that we'll modify a lot of files in third_party/libprocess, but that
+# that we'll modify a lot of files in 3rdparty/libprocess, but that
# may change in the future.
autoreconf --install -Wall --verbose "${@}"
http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/71a01bd9/configure.ac
----------------------------------------------------------------------
diff --git a/configure.ac b/configure.ac
index c3b5a05..e76f775 100644
--- a/configure.ac
+++ b/configure.ac
@@ -51,15 +51,15 @@ LT_OUTPUT
AS_IF([test "x${ac_cv_env_CFLAGS_set}" = "x"], [CFLAGS="-g"])
AS_IF([test "x${ac_cv_env_CXXFLAGS_set}" = "x"], [CXXFLAGS="-g"])
-# Save the configure arguments so we can pass them to any third_party
+# Save the configure arguments so we can pass them to any third-party
# libraries that we might run configure on (see
-# third_party/Makefile.am). One downside of our strategy for shipping
-# and building third_party libraries is that we can't expose options
-# from nested third_party configure scripts.
+# 3rdparty/Makefile.am). One downside of our strategy for shipping and
+# building third-party libraries is that we can't expose options from
+# nested third-party configure scripts.
CONFIGURE_ARGS="$ac_configure_args"
AC_SUBST(CONFIGURE_ARGS)
-# Force configured third_party libraries (currently only libprocess)
+# Force configured third-party libraries (currently only libprocess)
# to only build a static library with position independent code so
# that we can produce a final shared library which includes everything
# necessary (and only install that).
@@ -74,13 +74,13 @@ ac_configure_args="$ac_configure_args_post"
AC_CONFIG_COMMANDS_PRE([ac_configure_args="$ac_configure_args_pre"])
AC_CONFIG_COMMANDS_POST([ac_configure_args="$ac_configure_args_post"])
-AC_CONFIG_SUBDIRS([third_party/libprocess])
+AC_CONFIG_SUBDIRS([3rdparty/libprocess])
AC_CONFIG_FILES([Makefile])
AC_CONFIG_FILES([ec2/Makefile])
AC_CONFIG_FILES([hadoop/Makefile])
AC_CONFIG_FILES([src/Makefile])
-AC_CONFIG_FILES([third_party/Makefile])
+AC_CONFIG_FILES([3rdparty/Makefile])
AC_CONFIG_FILES([bin/mesos-build-env.sh])
AC_CONFIG_FILES([bin/mesos-local.sh], [chmod +x bin/mesos-local.sh])
http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/71a01bd9/src/Makefile.am
----------------------------------------------------------------------
diff --git a/src/Makefile.am b/src/Makefile.am
index 738c18f..a91daae 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -19,21 +19,21 @@
# master/http.cpp and slave/http.cpp.
AUTOMAKE_OPTIONS = subdir-objects
-include ../third_party/versions.am
-include ../third_party/libprocess/third_party/versions.am
+include ../3rdparty/versions.am
+include ../3rdparty/libprocess/3rdparty/versions.am
# TODO(charles): Move these into an included automakefile and have
# them include $(top_builddir) as appropriate.
-DISTRIBUTE = third_party/distribute-$(DISTRIBUTE_VERSION)
-LEVELDB = third_party/leveldb
-ZOOKEEPER = third_party/zookeeper-$(ZOOKEEPER_VERSION)/src/c
-LIBPROCESS = third_party/libprocess
-STOUT = $(LIBPROCESS)/third_party/stout
-BOOST = $(LIBPROCESS)/third_party/boost-$(BOOST_VERSION)
-GLOG = $(LIBPROCESS)/third_party/glog-$(GLOG_VERSION)
-GMOCK = $(LIBPROCESS)/third_party/gmock-$(GMOCK_VERSION)
+DISTRIBUTE = 3rdparty/distribute-$(DISTRIBUTE_VERSION)
+LEVELDB = 3rdparty/leveldb
+ZOOKEEPER = 3rdparty/zookeeper-$(ZOOKEEPER_VERSION)/src/c
+LIBPROCESS = 3rdparty/libprocess
+STOUT = $(LIBPROCESS)/3rdparty/stout
+BOOST = $(LIBPROCESS)/3rdparty/boost-$(BOOST_VERSION)
+GLOG = $(LIBPROCESS)/3rdparty/glog-$(GLOG_VERSION)
+GMOCK = $(LIBPROCESS)/3rdparty/gmock-$(GMOCK_VERSION)
GTEST = $(GMOCK)/gtest
-PROTOBUF = $(LIBPROCESS)/third_party/protobuf-$(PROTOBUF_VERSION)
+PROTOBUF = $(LIBPROCESS)/3rdparty/protobuf-$(PROTOBUF_VERSION)
# Unfortunatley, 'pkglibexecdir' and 'pkglocalstatedir' are not set
@@ -100,7 +100,7 @@ endif
# README: we build the Mesos library out of a collection of
# convenience libraries (that is, libraries that do not get installed
# but we can use as building blocks to vary compile flags as necessary
-# and then aggregate into final archives): libmesos_no_third_party.la
+# and then aggregate into final archives): libmesos_no_3rdparty.la
# libbuild.la, liblog.la, libjava.la.
# First, let's define necessary protocol buffer files.
@@ -155,14 +155,14 @@ $(PYTHON_PROTOS): $(MESOS_PROTO)
# exclude third party libraries so setuptools/distribute can build a
# self-contained Python library and statically link in the third party
# libraries themselves.
-noinst_LTLIBRARIES += libmesos_no_third_party.la
+noinst_LTLIBRARIES += libmesos_no_3rdparty.la
-nodist_libmesos_no_third_party_la_SOURCES = \
+nodist_libmesos_no_3rdparty_la_SOURCES = \
$(CXX_PROTOS) \
$(MESSAGES_PROTOS) \
$(REGISTRY_PROTOS)
-libmesos_no_third_party_la_SOURCES = \
+libmesos_no_3rdparty_la_SOURCES = \
sched/sched.cpp \
local/local.cpp \
master/constants.cpp \
@@ -203,16 +203,16 @@ pkginclude_HEADERS = $(top_srcdir)/include/mesos/executor.hpp \
nodist_pkginclude_HEADERS = ../include/mesos/mesos.hpp mesos.pb.h
if OS_LINUX
- libmesos_no_third_party_la_SOURCES += slave/cgroups_isolator.cpp
- libmesos_no_third_party_la_SOURCES += linux/cgroups.cpp
- libmesos_no_third_party_la_SOURCES += linux/fs.cpp
+ libmesos_no_3rdparty_la_SOURCES += slave/cgroups_isolator.cpp
+ libmesos_no_3rdparty_la_SOURCES += linux/cgroups.cpp
+ libmesos_no_3rdparty_la_SOURCES += linux/fs.cpp
else
EXTRA_DIST += slave/cgroups_isolator.cpp
EXTRA_DIST += linux/cgroups.cpp
EXTRA_DIST += linux/fs.cpp
endif
-libmesos_no_third_party_la_SOURCES += common/attributes.hpp \
+libmesos_no_3rdparty_la_SOURCES += common/attributes.hpp \
common/build.hpp common/date_utils.hpp common/factory.hpp \
common/protobuf_utils.hpp \
common/lock.hpp common/resources.hpp common/process_utils.hpp \
@@ -244,9 +244,9 @@ libmesos_no_third_party_la_SOURCES += common/attributes.hpp \
zookeeper/group.hpp zookeeper/watcher.hpp \
zookeeper/zookeeper.hpp zookeeper/url.hpp
-libmesos_no_third_party_la_CPPFLAGS = $(MESOS_CPPFLAGS)
+libmesos_no_3rdparty_la_CPPFLAGS = $(MESOS_CPPFLAGS)
-libmesos_no_third_party_la_LIBADD = # Initialized to enable using +=.
+libmesos_no_3rdparty_la_LIBADD = # Initialized to enable using +=.
# Convenience library that *always* gets rebuilt to ensure accurate info.
noinst_LTLIBRARIES += libbuild.la
@@ -265,7 +265,7 @@ BUILD_FLAGS = $(echo $(MESOS_CPPFLAGS) $(CPPFLAGS) | sed 's/\"/\\\"/g') \
libbuild_la_CPPFLAGS += -DBUILD_FLAGS="\"$$BUILD_FLAGS\""
-libmesos_no_third_party_la_LIBADD += libbuild.la
+libmesos_no_3rdparty_la_LIBADD += libbuild.la
# Convenience library for building the replicated log in order to
@@ -277,7 +277,7 @@ liblog_la_SOURCES += log/coordinator.hpp log/replica.hpp log/log.hpp \
nodist_liblog_la_SOURCES = $(LOG_PROTOS)
liblog_la_CPPFLAGS = -I../$(LEVELDB)/include $(MESOS_CPPFLAGS)
-libmesos_no_third_party_la_LIBADD += liblog.la
+libmesos_no_3rdparty_la_LIBADD += liblog.la
# Convenience library for building "state" abstraction in order to
@@ -295,7 +295,7 @@ libstate_la_SOURCES += \
nodist_libstate_la_SOURCES = $(STATE_PROTOS)
libstate_la_CPPFLAGS = -I../$(LEVELDB)/include $(MESOS_CPPFLAGS)
-libmesos_no_third_party_la_LIBADD += libstate.la
+libmesos_no_3rdparty_la_LIBADD += libstate.la
# The final result!
lib_LTLIBRARIES += libmesos.la
@@ -309,7 +309,7 @@ libmesos_la_LDFLAGS = -release $(PACKAGE_VERSION) -shared
libmesos_la_LIBTOOLFLAGS = --tag=CXX
# Add the convenience library.
-libmesos_la_LIBADD = libmesos_no_third_party.la
+libmesos_la_LIBADD = libmesos_no_3rdparty.la
# For non-convenience libraries we need to link them in to make the shared
# library each time. (Currently, we don't support platforms where this is not
@@ -319,7 +319,7 @@ libmesos_la_LIBADD += ../$(GLOG)/libglog.la
# We need to directly include the leveldb library in order to avoid
# the installed libmesos.la file to include leveldb in
-# 'dependency_libs' (via '-L../third_party/leveldb -lleveldb').
+# 'dependency_libs' (via '-L../3rdparty/leveldb -lleveldb').
libmesos_la_LIBADD += ../$(LEVELDB)/libleveldb.a
if WITH_INCLUDED_ZOOKEEPER
@@ -395,7 +395,7 @@ nobase_dist_webui_DATA += \
# Need to distribute/install webui images.
nobase_dist_webui_DATA += webui/master/static/loading.gif
-# Need to distribute/install third_party javascript.
+# Need to distribute/install third-party javascript.
nobase_dist_webui_DATA += \
webui/master/static/angular-1.0.0rc8.js \
webui/master/static/angular-1.0.0rc8.min.js \
@@ -520,7 +520,7 @@ if HAS_JAVA
# Protocol buffers JAR.
PROTOBUF_JAR = ../protobuf-$(PROTOBUF_VERSION).jar
-# TODO(charles): Move into third_party/Makefile.am.
+# TODO(charles): Move into 3rdparty/Makefile.am.
$(PROTOBUF_JAR): # TODO(charles): Specify dependencies for the jar.
@echo "Building protobuf-$(PROTOBUF_VERSION).jar ..."
$(MKDIR_P) ../$(PROTOBUF)/java/src/main/java
@@ -591,7 +591,7 @@ libjava_la_DEPENDENCIES = $(MESOS_PROTO)
libjava_la_LIBADD = $(JAVA_LDFLAGS)
-# We don't add libjava.la to libmesos_no_third_party.la so we don't
+# We don't add libjava.la to libmesos_no_3rdparty.la so we don't
# include the JNI bindings in the Python egg (but we might want to
# reconsider this in the future). We also need to add the JAVA_LDFLAGS
# to libmesos.la so on Linux we set the rpath for libmesos.so.
@@ -700,8 +700,8 @@ $(PROTOBUF_EGG):
CLEANFILES += $(PROTOBUF_EGG)
-# This builds a Python egg against libmesos_no_third_party.a that is
-# self-contained. It currently depends on the libraries in third_party
+# This builds a Python egg against libmesos_no_3rdparty.a that is
+# self-contained. It currently depends on the libraries in 3rdparty
# being built as .a's. (If this is changed, the setup.py will need to
# be edited).
@@ -718,7 +718,7 @@ CLEANFILES += $(PROTOBUF_EGG)
MESOS_EGG = python/dist/mesos-$(PACKAGE_VERSION)$(PYTHON_EGG_POSTFIX).egg
$(MESOS_EGG): python/setup.py $(srcdir)/python/src/mesos.py \
- $(PYTHON_PROTOS) libmesos_no_third_party.la \
+ $(PYTHON_PROTOS) libmesos_no_3rdparty.la \
$(PROTOBUF_EGG)
@echo "Building Mesos Python egg ..."
@if test "$(top_srcdir)" != "$(top_builddir)"; then \
@@ -823,7 +823,7 @@ mesos_tests_CPPFLAGS += -DBUILD_DIR=\"$(abs_top_builddir)\"
mesos_tests_CPPFLAGS += -I../$(GTEST)/include
mesos_tests_CPPFLAGS += -I../$(GMOCK)/include
-mesos_tests_LDADD = ../$(LIBPROCESS)/third_party/libgmock.la libmesos.la
+mesos_tests_LDADD = ../$(LIBPROCESS)/3rdparty/libgmock.la libmesos.la
mesos_tests_DEPENDENCIES = # Initialized to allow += below.