diff --git a/Makefile b/Makefile index c9da691..37875a8 100644 --- a/Makefile +++ b/Makefile @@ -92,7 +92,7 @@ LINKER = g++ COMPILER_FLAGS = -Wall -c -O2 -std=c++11 -fpic -I. -g LINKER_FLAGS = -shared -LINKER_DEPENDENCIES = -lphpcpp -lyothalot +LINKER_DEPENDENCIES = -lphpcpp -lyothalot -lamqpcpp # # Command to remove files, copy files and create directories. diff --git a/extension.cpp b/extension.cpp index 55a9f65..2ec7d3a 100644 --- a/extension.cpp +++ b/extension.cpp @@ -69,6 +69,7 @@ extern "C" { Php::Class raceResult ("RaceResult"); Php::Class stats ("Stats"); Php::Class datastats ("DataStats"); + Php::Class winner ("Winner"); // register writer functions writer.method("emit", &Writer::emit, { @@ -156,8 +157,12 @@ extern "C" { .method("finalizers", &MapReduceResult::finalizers); raceResult.method("started", &RaceResult::started) + .method("finished", &RaceResult::finished) .method("runtime", &RaceResult::runtime) - .method("result", &RaceResult::result); + .method("processes", &RaceResult::processes) + .method("result", &RaceResult::result) + .method("winner", &RaceResult::winner); + // register stats methods stats.method("first", &Stats::first) @@ -174,6 +179,20 @@ extern "C" { datastats.method("files", &DataStats::files) .method("bytes", &DataStats::bytes); + // register winner methods + // register stats methods + winner.method("input", &Winner::input) + .method("output", &Winner::output) + .method("error", &Winner::error) + .method("server", &Winner::server) + .method("pid", &Winner::pid) + .method("signal", &Winner::signal) + .method("exit", &Winner::exit) + .method("started", &Winner::started) + .method("finished", &Winner::finished) + .method("runtime", &Winner::runtime); + + // create the map reduce interface Php::Interface mapreduce("MapReduce"); @@ -214,6 +233,7 @@ extern "C" { ns.add(std::move(raceResult)); ns.add(std::move(stats)); ns.add(std::move(datastats)); + ns.add(std::move(winner)); // add the init method for use on the command line to our namespace, this // will result in `php -r "YothalotInit('mapper');"` diff --git a/raceresult.h b/raceresult.h index ea1c20a..f8feb31 100644 --- a/raceresult.h +++ b/raceresult.h @@ -18,6 +18,7 @@ * Dependencies */ #include "stats.h" +#include "winner.h" /** * Class definition @@ -57,6 +58,15 @@ class RaceResult : public Php::Base { return _json.decimal("started"); } + + /** + * Get the time when the job is finished + * @return Php::Value + */ + Php::Value finished() const + { + return _json.decimal("finished"); + } /** * Get the total runtime @@ -66,6 +76,15 @@ class RaceResult : public Php::Base { return _json.decimal("runtime"); } + + /** + * Get the number of processes during the race + * @return Php::Value + */ + Php::Value processes() const + { + return _json.integer("processes"); + } /** * Get the result, only used for races and regular jobs @@ -76,5 +95,14 @@ class RaceResult : public Php::Base // unserialize the base64 encoded object from stdout return Php::call("unserialize", Php::call("base64_decode", _json.object("winner").c_str("stdout"))); } + + /** + * Get the winner class with all winner statistics + * @return Php::Value + */ + Php::Value winner() + { + return Php::Object("Yothalot\\Winner", new Winner(_json.object("winner"))); + } }; diff --git a/winner.h b/winner.h new file mode 100644 index 0000000..769daa5 --- /dev/null +++ b/winner.h @@ -0,0 +1,147 @@ +/** + * Winner.h + * + * Statistics of the winner of the race job + * + * @author Aljar Meesters + * @copyright Copernica BV 2015 + */ + +/** + * include guard + */ +#pragma once + +/** + * dependencies + */ +#include +#include "json/object.h" + +/** + * class definition + */ +class Winner : public Php::Base +{ +private: + /** + * json that holds the information + * @var JSON::Object + */ + JSON::Object _json; + +public: + /** + * Constructor + * @param json + */ + Winner(const JSON::Object &json) : _json(json) {} + + /** + * input that was send to the winner + * @return Php::Value + */ + Php::Value input() const + { + // Unserialize the result + auto completeObject = std::string(_json.c_str("stdin")); + + // look for the \n\n separator + auto separator = completeObject.find("\n\n"); + + // should exist + if (separator == std::string::npos) throw std::runtime_error("missing separator between serialized data and input data"); + + // we now know where the rest of the data starts + auto data = completeObject.data() + separator + 2; + + // Decode the data + return Php::call("base64_decode" , Php::Value(data)); + + // unserialize the first part of the stdin + // return unserialized(Php::call("unserialize", Php::call("base64_decode", Php::Value(rest.data())))); + } + + /** + * output that was send to stdout by winner + * @return Php::Value + */ + Php::Value output() const + { + // Unserialize the result + return Php::call("unserialize", Php::call("base64_decode", _json.c_str("stdout"))); + + } + + /** + * error that was send to stderr by winner + * @return Php::Value + */ + Php::Value error() const + { + return Php::call("unserialize", Php::call("base64_decode", _json.c_str("stderr"))); + } + + /** + * name of sever on which the winning job ran + * @return Php::Value + */ + Php::Value server() const + { + return _json.c_str("server"); + } + + /** + * Process id of the winner + * @return Php::Value + */ + Php::Value pid() const + { + return _json.integer("pid"); + } + + /** + * Signal if the winner was killed + * @return Php::Value + */ + Php::Value signal() const + { + return _json.integer("signal"); + } + + /** + * Exit code with which the winner exited + * @return Php::Value + */ + Php::Value exit() const + { + return _json.integer("exit"); + } + + /** + * Starting time of the winner + * @return Php::Value + */ + Php::Value started() const + { + return _json.decimal("started"); + } + + /** + * Finishing time of the winner + * @return Php::Value + */ + Php::Value finished() const + { + return _json.decimal("finished"); + } + + /** + * Runtime of the winner + * @return Php::Value + */ + Php::Value runtime() const + { + return _json.decimal("runtime"); + } +};