diff --git a/src/json_workload.cpp b/src/json_workload.cpp index 0bc0a9ba2e1a3a436a9536727a9bb149c7679413..3fac657f74dfd8bb95df39fd7602963cd82cd35b 100644 --- a/src/json_workload.cpp +++ b/src/json_workload.cpp @@ -32,6 +32,16 @@ Session::Session( jobs = list<const Job *>(); } +Session::~Session() +{ + for (const Job *job : jobs){ + delete job; + } + jobs.clear(); + preceding_sessions.clear(); + following_sessions.clear(); +} + Workload::~Workload() { deallocate(); @@ -174,6 +184,7 @@ Job *Workload::job_from_json_object(const Value &object) return j; } + bool JobComparator::operator()(const Job *j1, const Job *j2) const { PPK_ASSERT_ERROR(j1->id.find('!') != string::npos, @@ -187,7 +198,11 @@ bool JobComparator::operator()(const Job *j1, const Job *j2) const if (id1.length() == id2.length()) /* same length: lexicographic order */ return id1 < id2; return id1.length() < id2.length(); +} +bool JobComparator::operator()(Job j1, Job j2) const +{ + return JobComparator::operator()(&j1, &j2); } bool SessionComparator::operator()(const Session *s1, const Session *s2) const @@ -423,7 +438,7 @@ Job *Parser::job_from_json_object(string user_name, const Value &object) return j; } -string Parser::json_description_string_from_job(Job *job) +string Parser::json_description_string_from_job(const Job *job) { PPK_ASSERT_ERROR(job->id != "", "A job must have the field 'id'."); PPK_ASSERT_ERROR( diff --git a/src/json_workload.hpp b/src/json_workload.hpp index 4e587b152ee76e83a9fd89cd0fcba8703e91776c..d7e8fca93ade62be7336dd6f358338490f6987ad 100644 --- a/src/json_workload.hpp +++ b/src/json_workload.hpp @@ -13,7 +13,7 @@ #include <utility> struct JobAlloc; -struct Session; +class Session; #define DATE_NEVER -1.0 #define DATE_UNKNOWN -2.0 @@ -53,6 +53,7 @@ struct JobAlloc struct JobComparator { bool operator()(const Job *j1, const Job *j2) const; + bool operator()(Job j1, Job j2) const; }; struct Profile @@ -62,8 +63,12 @@ struct Profile std::string description; }; -struct Session +class Session { +public: + Session(unsigned int id, double first_submit_time, unsigned int nb_jobs); + ~Session(); + unsigned int id; double original_first_submit_time; /* the submit time of the first job in this @@ -76,7 +81,6 @@ struct Session std::map<Session *, double> preceding_sessions; /* pair (Session, t_time) */ std::set<Session *> following_sessions; - Session(unsigned int id, double first_submit_time, unsigned int nb_jobs); }; struct SessionComparator @@ -126,7 +130,7 @@ struct Parser static Job *job_from_json_object( const std::string user_name, const rapidjson::Value &object); // with format 'user-name!jobID' - static std::string json_description_string_from_job(Job *job); + static std::string json_description_string_from_job(const Job *job); static Session *session_from_json_object(const std::string user_name, const rapidjson::Value &object, std::list<unsigned int> *prec_sessions, std::list<double> *tt_after_prec_sessions); diff --git a/src/scheds/HARD_DEFINED_VAR.hpp b/src/scheds/HARD_DEFINED_VAR.hpp index f8115b5c77374bf6c7fc5c7bbdd3ccae6e5227b7..eac0f44b8a4d9a1cc6a85ccddc22743b855ef88a 100644 --- a/src/scheds/HARD_DEFINED_VAR.hpp +++ b/src/scheds/HARD_DEFINED_VAR.hpp @@ -2,4 +2,6 @@ #define NB_CORE_PER_MACHINE 16 #define INITIAL_MACHINE_STATE AWAKE #define PSTATE_AWAKE 0 -#define PSTATE_ASLEEP 1 \ No newline at end of file +#define PSTATE_ASLEEP 1 + +#define EPSILON 0.00001 /* For float rounding issues */ \ No newline at end of file diff --git a/src/scheds/bin_packing.cpp b/src/scheds/bin_packing.cpp index dc11ac6feb0f3edd268a05c525d5e525aacb3a13..bd8bb146be70ad39830075cd9c1f4a4f7bbb5767 100644 --- a/src/scheds/bin_packing.cpp +++ b/src/scheds/bin_packing.cpp @@ -37,6 +37,9 @@ BinPacking::BinPacking(Workload *workload, SchedulingDecision *decision, BinPacking::~BinPacking() { + for (auto host : listofHosts) + delete host; + listofHosts.clear(); } std::string BinPacking::hosts_to_string(std::list<SortableHost *> listofHosts) diff --git a/src/scheds/bin_packing_energy.cpp b/src/scheds/bin_packing_energy.cpp index 9617841d2be773878a8ff9ee984db0351497d7b7..e98405c279a8e936b558865be5a0c1eefe436f89 100644 --- a/src/scheds/bin_packing_energy.cpp +++ b/src/scheds/bin_packing_energy.cpp @@ -65,6 +65,9 @@ BinPackingEnergy::BinPackingEnergy(Workload *workload, BinPackingEnergy::~BinPackingEnergy() { + for (auto host : listofHosts) + delete host; + listofHosts.clear(); } std::string BinPackingEnergy::machine_state_to_string( diff --git a/src/users/broker.cpp b/src/users/broker.cpp index 0430cc926412a562bde3d9f5b1f7de1849560575..f325bfa90be79a06f64e610a8d4f5917239cde0a 100644 --- a/src/users/broker.cpp +++ b/src/users/broker.cpp @@ -8,6 +8,7 @@ #include "../pempek_assert.hpp" #include "rapidjson/rapidjson.h" #include <loguru.hpp> +#include <memory> using namespace rapidjson; Broker::Broker(rapidjson::Document *user_description_file) @@ -15,6 +16,16 @@ Broker::Broker(rapidjson::Document *user_description_file) /* Parse description file and call constructor for each user */ if (!user_description_file->ObjectEmpty()) { + if (user_description_file->HasMember("core_limit_per_user")) + { + PPK_ASSERT_ERROR( + (*user_description_file)["core_limit_per_user"].IsInt(), + "Invalid user_description file: field " + "'core_limit_per_user' should be an int."); + core_limit_per_user + = (*user_description_file)["core_limit_per_user"].GetInt(); + // otherwise, initialized at std::numeric_limits<int>::max() + } if (user_description_file->HasMember("dm_window")) { const Value &dm_param = (*user_description_file)["dm_window"]; @@ -143,8 +154,7 @@ Broker::~Broker() { delete it.second; } - for (auto itr = dynamic_jobs.begin(); itr != dynamic_jobs.end(); itr++) - delete itr->second; + dynamic_jobs.clear(); users_to_wake.clear(); } @@ -155,10 +165,10 @@ double Broker::next_submission(double date) const } void Broker::jobs_to_submit( - double date, list<Job *> &jobs, list<Profile *> &profiles) + double date, list<Job> &jobs, list<const Profile *> &profiles) { - jobs = list<Job *>(); - profiles = list<Profile *>(); + jobs = list<Job>(); + profiles = list<const Profile *>(); User *user = user_queue.front(); double planned_date_submission = user->next_submission(); @@ -171,15 +181,25 @@ void Broker::jobs_to_submit( while (planned_date_submission == user->next_submission()) { user_queue.pop_front(); - list<Job *> user_jobs; - list<Profile *> user_profiles; + unsigned int nb_core_requested = 0; + list<shared_ptr<Job>> user_jobs; + list<const Profile *> user_profiles; user->jobs_to_submit(date, user_jobs, user_profiles); - for (Job *job : user_jobs) + for (shared_ptr<Job> job : user_jobs) { - jobs.push_back(job); - dynamic_jobs[job->id] = job; - job->status = WAITING; + nb_core_requested = nb_core_requested + job->nb_requested_resources; + + if (nb_core_requested > core_limit_per_user) + { + job->status = KILLED; + } + else + { + jobs.push_back(*job); + dynamic_jobs[job->id] = job; + job->status = WAITING; + } } profiles.splice(profiles.end(), user_profiles); @@ -231,7 +251,7 @@ void Broker::update_status_if_dyn_job( { string user_name = job_id.substr(0, job_id.find('!')); User *user = users[user_name]; - Job *current_job = it->second; + shared_ptr<Job> current_job = it->second; switch (status) { @@ -250,7 +270,7 @@ void Broker::update_status_if_dyn_job( /* Add potentially interested user to the map of users to wake up */ if (users_to_wake.find(user) == users_to_wake.end()) - users_to_wake.emplace(user, list<Job *>()); + users_to_wake.emplace(user, list<shared_ptr<Job>>()); /* ..and keep track of its recently ended jobs */ users_to_wake[user].push_back(current_job); @@ -265,7 +285,7 @@ void Broker::update_status_if_dyn_job( /* Add potentially interested user to the map of users to wake up */ if (users_to_wake.find(user) == users_to_wake.end()) - users_to_wake.emplace(user, list<Job *>()); + users_to_wake.emplace(user, list<shared_ptr<Job>>()); /* ..and keep track of its recently ended jobs */ users_to_wake[user].push_back(current_job); diff --git a/src/users/broker.hpp b/src/users/broker.hpp index 88d4de90d80eddeeb862064cfea39554db80ca68..cbb389debad61982e76d7df8082a14d30b594ef8 100644 --- a/src/users/broker.hpp +++ b/src/users/broker.hpp @@ -34,7 +34,7 @@ public: * @param[out] profiles The list of profiles used by the jobs, if new. */ void jobs_to_submit( - double date, list<Job *> &jobs, list<Profile *> &profiles); + double date, list<Job> &jobs, list<const Profile *> &profiles); /** * @brief Ackowledge the latest execution-related activity and forward the @@ -48,10 +48,11 @@ public: private: map<string, User *> users; + unsigned int core_limit_per_user = std::numeric_limits<int>::max(); list<User *> user_queue; - map<string, Job *> dynamic_jobs = map<string, Job *>(); - map<User *, list<Job *>> users_to_wake - = map<User *, list<Job *>>(); + map<string, shared_ptr<Job>> dynamic_jobs = map<string, shared_ptr<Job>>(); + map<User *, list<shared_ptr<Job>>> users_to_wake + = map<User *, list<shared_ptr<Job>>>(); private: /* Deterministic generation of seeds for users that use randomness */ diff --git a/src/users/dynscheduler.cpp b/src/users/dynscheduler.cpp index 2e2f3e01ee93c34aa437e5f0701751f33c3b0d1d..8ff436c4d834a786ef2c0fe8ed086737f6954f40 100644 --- a/src/users/dynscheduler.cpp +++ b/src/users/dynscheduler.cpp @@ -41,16 +41,6 @@ void DynScheduler::on_simulation_start( /* Check for optional parameters */ if (!_variant_options->ObjectEmpty()) { - if (_variant_options->HasMember("core_limit_per_user")) - { - PPK_ASSERT_ERROR( - (*_variant_options)["core_limit_per_user"].IsInt(), - "Invalid user_description file: field " - "'core_limit_per_user' should be an int."); - core_limit_per_user - = (*_variant_options)["core_limit_per_user"].GetInt(); - // otherwise, initialized at std::numeric_limits<int>::max() - } if (_variant_options->HasMember("log_user_stats") && (*_variant_options)["log_user_stats"].GetBool()) { @@ -148,53 +138,46 @@ void DynScheduler::end_broker(double date) void DynScheduler::submit_broker_jobs(double date) { - std::list<Job *> jobs; - std::list<Profile *> profiles; + std::list<Job> jobs; + std::list<const Profile *> profiles; broker->jobs_to_submit(date, jobs, profiles); - if (!profiles.empty()) + if (!profiles.empty()) { dyn_register_profiles(profiles, date); + + /* Profiles won't be used anymore, free memory */ + for (const Profile *profile : profiles){ + delete profile; + } + } dyn_submit(jobs, date); } -void DynScheduler::dyn_submit(std::list<Job *> jobs, double date) +void DynScheduler::dyn_submit(std::list<Job> jobs, double date) { - std::map<std::string, int> core_per_user; - - for (Job *current_job : jobs) + for (Job current_job : jobs) { - std::string fullID = current_job->id; + std::string fullID = current_job.id; PPK_ASSERT_ERROR(fullID.find('!') != std::string::npos, - "Dynamicaly submitted jobs should have the format " + "Dynamically submitted jobs should have the format " "'user_name!jobID'."); std::string user_name = fullID.substr(0, fullID.find('!')); fullID.erase(0, fullID.find('!') + 1); std::string jobID = fullID; + std::string job_description + = Parser::json_description_string_from_job(¤t_job); + std::string empty_profile_description + = std::string(); // has already been sent - // REFAC: move to broker - core_per_user[user_name] - = core_per_user[user_name] + current_job->nb_requested_resources; + /* Register the job to batsim */ + _decision->add_submit_job(user_name, jobID, current_job.profile, + job_description, empty_profile_description, date, true); - if (core_per_user[user_name] > core_limit_per_user) - { - current_job->status = KILLED; - } - else - { - std::string job_description - = Parser::json_description_string_from_job(current_job); - std::string empty_profile_description - = std::string(); // has already been sent - - /* Register the job to batsim */ - _decision->add_submit_job(user_name, jobID, current_job->profile, - job_description, empty_profile_description, date, true); - } } } void DynScheduler::dyn_register_profiles( - std::list<Profile *> profiles, double date) + std::list<const Profile *> profiles, double date) { for (auto profile : profiles) { diff --git a/src/users/dynscheduler.hpp b/src/users/dynscheduler.hpp index 677282a80c3c1cb82cc04f16660e02b5d1bda34c..602f72e376d6bae164d6066c539f7c05fe7f4db8 100644 --- a/src/users/dynscheduler.hpp +++ b/src/users/dynscheduler.hpp @@ -53,12 +53,12 @@ protected: /** * Dynamically registers to batsim the job `jobs` to submit. */ - void dyn_submit(std::list<Job *> jobs, double date); + void dyn_submit(std::list<Job> jobs, double date); /** * Registers to batsim the profiles that will be used by the broker. */ - void dyn_register_profiles(std::list<Profile *> profiles, double date); + void dyn_register_profiles(std::list<const Profile *> profiles, double date); protected: bool broker_enabled = false; @@ -67,6 +67,5 @@ protected: bool next_submission_has_changed = false; private: - int core_limit_per_user = std::numeric_limits<int>::max(); std::string log_folder = ""; }; \ No newline at end of file diff --git a/src/users/user.cpp b/src/users/user.cpp index 6d38e6bc168b0283e26916a66990dc674493816b..495094dc1a7b98584ffb13eba0185d0e6e7b5947 100644 --- a/src/users/user.cpp +++ b/src/users/user.cpp @@ -21,7 +21,7 @@ int *User::get_dm_stat() return stat; } -void User::wake_on_feedback(double date, std::list<Job *> &ended_jobs) +void User::wake_on_feedback(double date, std::list<shared_ptr<Job>> &ended_jobs) { return; } diff --git a/src/users/user.hpp b/src/users/user.hpp index d5feb399c5da551166ba392bde425cc39664ef27..7f7f151d450ca1496914eb7b93af5c663b207c16 100644 --- a/src/users/user.hpp +++ b/src/users/user.hpp @@ -4,9 +4,12 @@ #include "rapidjson/document.h" #include <list> #include <string> +#include <memory> #include "scheds/HARD_DEFINED_VAR.hpp" +using namespace std; + class User { public: @@ -30,17 +33,17 @@ public: * @param[out] profiles The list of profiles used by the jobs, if new. */ virtual void jobs_to_submit( - double date, std::list<Job *> &jobs, std::list<Profile *> &profiles) + double date, list<shared_ptr<Job>> &jobs, list<const Profile *> &profiles) = 0; /* For demand response users only: */ virtual int *get_dm_stat(); /* For users reacting to feedback: */ - virtual void wake_on_feedback(double date, std::list<Job *> &ended_jobs); + virtual void wake_on_feedback(double date, list<shared_ptr<Job>> &ended_jobs); public: - std::string user_name; + string user_name; protected: double date_of_next_submission; diff --git a/src/users/user_feedback.cpp b/src/users/user_feedback.cpp index bdf922ea03d2459a11b7ad7d2d52598b33e645f2..515f62b5050a046dce1ae512f738f9d903bc4dc3 100644 --- a/src/users/user_feedback.cpp +++ b/src/users/user_feedback.cpp @@ -5,8 +5,6 @@ #include <limits> #include <string> -#define EPS 0.00001 - /* FeedbackUser */ void FeedbackUser::init_FeedbackUser( std::string name, const rapidjson::Value ¶m) @@ -82,13 +80,13 @@ void FeedbackUser::update_date_next_sub() } void FeedbackUser::jobs_to_submit( - double date, std::list<Job *> &jobs, std::list<Profile *> &profiles) + double date, std::list<shared_ptr<Job>> &jobs, std::list<const Profile *> &profiles) { - jobs = std::list<Job *>(); - profiles = std::list<Profile *>(); + jobs = std::list<shared_ptr<Job>>(); + profiles = std::list<const Profile *>(); /* Add the free sessions starting now to the list of active sessions */ - while (!free_sessions.empty() && free_sessions.top()->start_time < date + EPS) + while (!free_sessions.empty() && free_sessions.top()->start_time < date + EPSILON) { active_sessions.push_back(free_sessions.top()); free_sessions.pop(); @@ -110,9 +108,9 @@ void FeedbackUser::jobs_to_submit( double offset = active_sess->start_time; while (!job_list->empty() - && job_list->front()->submission_time + offset < date + EPS) + && job_list->front()->submission_time + offset < date + EPSILON) { - Job *job = new Job(*job_list->front()); // Cast const Job * -> Job * + shared_ptr<Job> job = shared_ptr<Job>(new Job(*job_list->front())); // Cast const Job * -> shared_ptr<Job> Profile *job_profile = new Profile(); /* Handle the job according to the user behavior. */ @@ -150,10 +148,10 @@ void FeedbackUser::jobs_to_submit( update_date_next_sub(); } -void FeedbackUser::wake_on_feedback(double date, std::list<Job *> &ended_jobs) +void FeedbackUser::wake_on_feedback(double date, std::list<shared_ptr<Job>> &ended_jobs) { /* Propagate the info and close finished sessions */ - for (Job *j : ended_jobs) + for (shared_ptr<Job>j : ended_jobs) { j->session->unfinished_jobs--; PPK_ASSERT_ERROR(ongoing_job_counter > 0, @@ -208,7 +206,7 @@ void FBUserThinkTimeOnly::close_session(double date, Session *finished_session) delete finished_session; } -bool FBUserThinkTimeOnly::handle_job(double date, Job *job, Profile *profile) +bool FBUserThinkTimeOnly::handle_job(double date, shared_ptr<Job>job, Profile *profile) { Parser::profile_from_duration( profile, job->profile, user_name, platform_computing_speed); diff --git a/src/users/user_feedback.hpp b/src/users/user_feedback.hpp index 4a60ae0a15747daa0d6f9fcbb8e4a529d5b95336..311dc0439d42a6bc1128501c00e0c9d34ccb5606 100644 --- a/src/users/user_feedback.hpp +++ b/src/users/user_feedback.hpp @@ -17,8 +17,8 @@ public: virtual ~FeedbackUser(); double next_submission(); virtual void jobs_to_submit( - double date, std::list<Job *> &jobs, std::list<Profile *> &profiles); - virtual void wake_on_feedback(double date, std::list<Job *> &ended_jobs); + double date, std::list<shared_ptr<Job>> &jobs, std::list<const Profile *> &profiles); + virtual void wake_on_feedback(double date, std::list<shared_ptr<Job>> &ended_jobs); protected: /** @@ -44,7 +44,7 @@ protected: * depending on the user behavior and returns if it should still be executed * now. */ - virtual bool handle_job(double date, Job *job, Profile *profile) = 0; + virtual bool handle_job(double date, shared_ptr<Job>job, Profile *profile) = 0; protected: std::string input_json; @@ -80,5 +80,5 @@ public: protected: void close_session(double date, Session *finished_session); - bool handle_job(double date, Job *job, Profile *profile); + bool handle_job(double date, shared_ptr<Job> job, Profile *profile); }; \ No newline at end of file diff --git a/src/users/user_model.cpp b/src/users/user_model.cpp index 17c0457893fc2c8bc6b66ec974d7ea3a5106cb44..f8c53525dd067b880de2ff55ccb4f4862cb25dd4 100644 --- a/src/users/user_model.cpp +++ b/src/users/user_model.cpp @@ -39,12 +39,12 @@ DichoIntersubmitTimeUser::~DichoIntersubmitTimeUser() } void DichoIntersubmitTimeUser::jobs_to_submit( - double date, std::list<Job *> &jobs, std::list<Profile *> &profiles) + double date, std::list<shared_ptr<Job>> &jobs, std::list<const Profile *> &profiles) { - jobs = std::list<Job *>(); + jobs = std::list<shared_ptr<Job>>(); /* The last job is still running */ - if (last_job_submitted != nullptr + if (last_job_submitted && (last_job_submitted->status == WAITING || last_job_submitted->status == RUNNING)) { @@ -55,7 +55,7 @@ void DichoIntersubmitTimeUser::jobs_to_submit( else { /* First job submitted by this user */ - if (last_job_submitted == nullptr) + if (!last_job_submitted) { delay_between_sumbit = delay_sup; // initial delay profiles = job_profiles_used(); @@ -65,10 +65,10 @@ void DichoIntersubmitTimeUser::jobs_to_submit( { delay_sup = std::ceil(date - last_job_submitted->submission_time); delay_between_sumbit = (delay_sup + delay_inf) / 2; - profiles = std::list<Profile *>(); // already submitted before + profiles = std::list<const Profile *>(); // already submitted before } - Job *job = new Job(); + shared_ptr<Job>job = shared_ptr<Job>(new Job()); job->id = user_name + "!" + std::to_string(job_id++); job->profile = "100_sec"; job->submission_time = date; @@ -88,9 +88,9 @@ void DichoIntersubmitTimeUser::jobs_to_submit( date_of_next_submission = DATE_NEVER; } -std::list<Profile *> DichoIntersubmitTimeUser::job_profiles_used() +std::list<const Profile *> DichoIntersubmitTimeUser::job_profiles_used() { - std::list<Profile *> profiles; + std::list<const Profile *> profiles; Profile *profile0 = new Profile(); profile0->workload_name = user_name; @@ -142,22 +142,36 @@ RoutineGreedyUser::~RoutineGreedyUser() { } -bool RoutineGreedyUser::all_jobs_finished_successfully() const +bool RoutineGreedyUser::previous_jobs_succedded() { - for (const Job *job : last_jobs_submitted) + bool res = true; + for (auto iter = last_jobs_submitted.begin(); + iter != last_jobs_submitted.end();) { - if (job->status == WAITING || job->status == RUNNING - || job->status == KILLED) - return false; + shared_ptr<Job> job = *iter; + + switch (job->status) { + case WAITING: + case RUNNING: + res = false; + iter++; + break; + case KILLED: + res = false; + iter = last_jobs_submitted.erase(iter); + break; + case FINISHED: + iter = last_jobs_submitted.erase(iter); + } } - return true; + return res; } void RoutineGreedyUser::jobs_to_submit( - double date, std::list<Job *> &jobs, std::list<Profile *> &profiles) + double date, std::list<shared_ptr<Job>> &jobs, std::list<const Profile *> &profiles) { - jobs = std::list<Job *>(); - profiles = std::list<Profile *>(); + jobs = std::list<shared_ptr<Job>>(); + profiles = std::list<const Profile *>(); /* First call: just submit the initial amount of jobs */ if (first_submit) @@ -167,7 +181,7 @@ void RoutineGreedyUser::jobs_to_submit( } /* All job finished: submit twice as many jobs */ - else if (all_jobs_finished_successfully()) + else if (previous_jobs_succedded()) nb_jobs_to_submit = (nb_jobs_to_submit == 0) ? 1 : nb_jobs_to_submit * 2; @@ -175,10 +189,9 @@ void RoutineGreedyUser::jobs_to_submit( else nb_jobs_to_submit /= 2; - last_jobs_submitted.clear(); for (int i = 0; i < nb_jobs_to_submit; i++) { - Job *job = new Job(); + shared_ptr<Job> job = shared_ptr<Job>(new Job()); job->id = user_name + "!" + std::to_string(job_id++); job->profile = "100_sec"; job->submission_time = date; @@ -198,9 +211,9 @@ void RoutineGreedyUser::jobs_to_submit( date_of_next_submission = DATE_NEVER; } -std::list<Profile *> RoutineGreedyUser::job_profiles_used() +std::list<const Profile *> RoutineGreedyUser::job_profiles_used() { - std::list<Profile *> profiles; + std::list<const Profile *> profiles; Profile *profile0 = new Profile(); profile0->workload_name = user_name; @@ -246,9 +259,9 @@ ThinkTimeUser::~ThinkTimeUser() } void ThinkTimeUser::jobs_to_submit( - double date, std::list<Job *> &jobs, std::list<Profile *> &profiles) + double date, std::list<shared_ptr<Job>> &jobs, std::list<const Profile *> &profiles) { - jobs = std::list<Job *>(); + jobs = std::list<shared_ptr<Job>>(); /* Stop condition reached */ if (date > end_submit) @@ -258,9 +271,15 @@ void ThinkTimeUser::jobs_to_submit( else { /* First job submitted by this user */ - if (last_job_submitted == nullptr) + if (!last_job_submitted) profiles = job_profiles_used(); - Job *job = new Job(); + else{ + PPK_ASSERT_ERROR(last_job_submitted->status == FINISHED + || last_job_submitted->status == KILLED, + "ThinkTimeUser %s called to submit, but her last job did not finish", user_name.c_str()); + } + + shared_ptr<Job> job = shared_ptr<Job>(new Job()); job->id = user_name + "!" + std::to_string(job_id++); job->profile = "100_sec"; job->submission_time = date; @@ -271,13 +290,13 @@ void ThinkTimeUser::jobs_to_submit( jobs.push_back(job); /* Date of next submission unknown for now... */ - date_of_next_submission = -2.0; + date_of_next_submission = DATE_UNKNOWN; } } -std::list<Profile *> ThinkTimeUser::job_profiles_used() +std::list<const Profile *> ThinkTimeUser::job_profiles_used() { - std::list<Profile *> profiles; + std::list<const Profile *> profiles; Profile *profile0 = new Profile(); profile0->workload_name = user_name; @@ -291,7 +310,7 @@ std::list<Profile *> ThinkTimeUser::job_profiles_used() return profiles; } -void ThinkTimeUser::wake_on_feedback(double date, std::list<Job *> &ended_jobs) +void ThinkTimeUser::wake_on_feedback(double date, std::list<shared_ptr<Job>> &ended_jobs) { /* The user has been awakened: her last job terminated */ PPK_ASSERT_ERROR(last_job_submitted->status == KILLED diff --git a/src/users/user_model.hpp b/src/users/user_model.hpp index f593986bf86a7ddb6014f0885799dc4860d2e971..7ad4663919a175df5b89059e68f437018eedb4e9 100644 --- a/src/users/user_model.hpp +++ b/src/users/user_model.hpp @@ -9,23 +9,23 @@ class DichoIntersubmitTimeUser : public User { public: - DichoIntersubmitTimeUser(std::string name, double date_first_submit, + DichoIntersubmitTimeUser(string name, double date_first_submit, double date_end_submit, double initial_delay); - DichoIntersubmitTimeUser(std::string name, const rapidjson::Value ¶m); + DichoIntersubmitTimeUser(string name, const rapidjson::Value ¶m); ~DichoIntersubmitTimeUser(); double next_submission(); void jobs_to_submit( - double date, std::list<Job *> &jobs, std::list<Profile *> &profiles); + double date, list<shared_ptr<Job>> &jobs, list<const Profile *> &profiles); protected: - std::list<Profile *> job_profiles_used(); + list<const Profile *> job_profiles_used(); private: double delay_inf = 0; double delay_sup; double delay_between_sumbit; int job_id = 0; - const Job *last_job_submitted = nullptr; + shared_ptr<Job> last_job_submitted; }; /** @@ -37,17 +37,17 @@ private: class RoutineGreedyUser : public User { public: - RoutineGreedyUser(std::string name, double date_first_submit, + RoutineGreedyUser(string name, double date_first_submit, double date_end_submit, double delay_between_sumbit, int initial_nb_job); - RoutineGreedyUser(std::string name, const rapidjson::Value ¶m); + RoutineGreedyUser(string name, const rapidjson::Value ¶m); ~RoutineGreedyUser(); double next_submission(); void jobs_to_submit( - double date, std::list<Job *> &jobs, std::list<Profile *> &profiles); + double date, list<shared_ptr<Job>> &jobs, list<const Profile *> &profiles); protected: - std::list<Profile *> job_profiles_used(); + list<const Profile *> job_profiles_used(); private: double delay_between_sumbit; @@ -55,8 +55,10 @@ private: bool first_submit = true; int job_id = 0; - std::list<const Job *> last_jobs_submitted; - bool all_jobs_finished_successfully() const; + list<shared_ptr<Job>> last_jobs_submitted; + /* Return true if all the jobs previously submitted by the user finished + * successfully. Also delete the finished jobs. */ + bool previous_jobs_succedded(); }; /** @@ -69,20 +71,20 @@ private: class ThinkTimeUser : public User { public: - ThinkTimeUser(std::string name, double date_first_submit, + ThinkTimeUser(string name, double date_first_submit, double date_end_submit, double think_time); - ThinkTimeUser(std::string name, const rapidjson::Value ¶m); + ThinkTimeUser(string name, const rapidjson::Value ¶m); ~ThinkTimeUser(); double next_submission(); void jobs_to_submit( - double date, std::list<Job *> &jobs, std::list<Profile *> &profiles); - void wake_on_feedback(double date, std::list<Job *> &ended_jobs); + double date, list<shared_ptr<Job>> &jobs, list<const Profile *> &profiles); + void wake_on_feedback(double date, list<shared_ptr<Job>> &ended_jobs); protected: - std::list<Profile *> job_profiles_used(); + list<const Profile *> job_profiles_used(); private: double think_time; int job_id = 0; - Job *last_job_submitted = nullptr; + shared_ptr<Job> last_job_submitted; }; \ No newline at end of file diff --git a/src/users/user_replay.cpp b/src/users/user_replay.cpp index 878d8240c62441e1f2448790041392e3d88b04ee..7ccb4208d4ed75abc7f573becfc193c4dace636f 100644 --- a/src/users/user_replay.cpp +++ b/src/users/user_replay.cpp @@ -35,25 +35,25 @@ ReplayUser::~ReplayUser() } void ReplayUser::jobs_to_submit( - double date, std::list<Job *> &jobs, std::list<Profile *> &profiles) + double date, std::list<shared_ptr<Job>> &jobs, std::list<const Profile *> &profiles) { - jobs = std::list<Job *>(); - profiles = std::list<Profile *>(); + jobs = std::list<shared_ptr<Job>>(); + profiles = std::list<const Profile *>(); PPK_ASSERT_ERROR(!original_trace->is_empty(), "User %s has been called to sumbit but her job queue is empty", user_name.c_str()); - PPK_ASSERT_ERROR(original_trace->first_job()->submission_time <= date, - "First job in user %s's queue has greater sumbmission time than " - "current date", - user_name.c_str()); + PPK_ASSERT_ERROR(original_trace->first_job()->submission_time < date + EPSILON, + "First job in user %s's queue has greater sumbmission time (%f) than " + "current date (%f)", + user_name.c_str(), original_trace->first_job()->submission_time, date); /* Submit all jobs that have same submit time */ while (!original_trace->is_empty() - && original_trace->first_job()->submission_time <= date) + && original_trace->first_job()->submission_time < date + EPSILON) { /* Cast const Job * into Job * */ - Job *job = new Job(*original_trace->first_job()); + shared_ptr<Job> job = shared_ptr<Job>(new Job(*original_trace->first_job())); Profile *job_profile = new Profile(); /* Handle the job according to the user behavior. */ @@ -100,12 +100,12 @@ ReplayUserRigid::~ReplayUserRigid() } void ReplayUserRigid::jobs_to_submit( - double date, std::list<Job *> &jobs, std::list<Profile *> &profiles) + double date, std::list<shared_ptr<Job>> &jobs, std::list<const Profile *> &profiles) { ReplayUser::jobs_to_submit(date, jobs, profiles); } -bool ReplayUserRigid::handle_job(double date, Job *job, Profile *profile) +bool ReplayUserRigid::handle_job(double date, shared_ptr<Job>job, Profile *profile) { /* Just generate the corresponding profile */ Parser::profile_from_duration(profile, job->profile, user_name, platform_computing_speed); @@ -121,7 +121,7 @@ bool ReplayUserRigid::handle_job(double date, Job *job, Profile *profile) } /* ReplayUserReconfig */ -bool ReplayUserReconfig::handle_job(double date, Job *job, Profile *profile) +bool ReplayUserReconfig::handle_job(double date, shared_ptr<Job>job, Profile *profile) { int orig_nb_core = job->nb_requested_resources; @@ -204,7 +204,7 @@ ReplayUserReconfig::~ReplayUserReconfig() } void ReplayUserReconfig::jobs_to_submit( - double date, std::list<Job *> &jobs, std::list<Profile *> &profiles) + double date, std::list<shared_ptr<Job>> &jobs, std::list<const Profile *> &profiles) { ReplayUser::jobs_to_submit(date, jobs, profiles); } @@ -253,7 +253,7 @@ DMUserReconfig::~DMUserReconfig() } void DMUserReconfig::jobs_to_submit( - double date, std::list<Job *> &jobs, std::list<Profile *> &profiles) + double date, std::list<shared_ptr<Job>> &jobs, std::list<const Profile *> &profiles) { ReplayUser::jobs_to_submit(date, jobs, profiles); } @@ -271,7 +271,7 @@ DMUserDegrad::~DMUserDegrad() } void DMUserDegrad::jobs_to_submit( - double date, std::list<Job *> &jobs, std::list<Profile *> &profiles) + double date, std::list<shared_ptr<Job>> &jobs, std::list<const Profile *> &profiles) { ReplayUser::jobs_to_submit(date, jobs, profiles); } @@ -289,7 +289,7 @@ DMUserRenonce::~DMUserRenonce() } void DMUserRenonce::jobs_to_submit( - double date, std::list<Job *> &jobs, std::list<Profile *> &profiles) + double date, std::list<shared_ptr<Job>> &jobs, std::list<const Profile *> &profiles) { ReplayUser::jobs_to_submit(date, jobs, profiles); } @@ -307,12 +307,12 @@ DMUserDelay::~DMUserDelay() } void DMUserDelay::jobs_to_submit( - double date, std::list<Job *> &jobs, std::list<Profile *> &profiles) + double date, std::list<shared_ptr<Job>> &jobs, std::list<const Profile *> &profiles) { ReplayUser::jobs_to_submit(date, jobs, profiles); } -bool DMUserReconfig::handle_job(double date, Job *job, Profile *profile) +bool DMUserReconfig::handle_job(double date, shared_ptr<Job>job, Profile *profile) { if (dm_window->date_in_dm_window(date)) { @@ -356,7 +356,7 @@ bool DMUserReconfig::handle_job(double date, Job *job, Profile *profile) return true; } -bool DMUserDegrad::handle_job(double date, Job *job, Profile *profile) +bool DMUserDegrad::handle_job(double date, shared_ptr<Job>job, Profile *profile) { if (dm_window->date_in_dm_window(date)) { @@ -390,7 +390,7 @@ bool DMUserDegrad::handle_job(double date, Job *job, Profile *profile) return true; } -bool DMUserRenonce::handle_job(double date, Job *job, Profile *profile) +bool DMUserRenonce::handle_job(double date, shared_ptr<Job>job, Profile *profile) { if (dm_window->date_in_dm_window(date)) { @@ -411,7 +411,7 @@ bool DMUserRenonce::handle_job(double date, Job *job, Profile *profile) return true; } -bool DMUserDelay::handle_job(double date, Job *job, Profile *profile) +bool DMUserDelay::handle_job(double date, shared_ptr<Job>job, Profile *profile) { if (dm_window->date_in_dm_window(date)) { @@ -425,7 +425,8 @@ bool DMUserDelay::handle_job(double date, Job *job, Profile *profile) /* Put job back in the queue and sort */ SortableJobOrder::UpdateInformation update_info(0); - original_trace->insert_job(job); + Job *j = new Job(); *j = *job; + original_trace->insert_job(j); original_trace->sort_queue(&update_info); /* Return "Do not execute now" */ diff --git a/src/users/user_replay.hpp b/src/users/user_replay.hpp index 55b80f25497ce17c2ef6ee70a2625b7e6c27c48a..2be3beb4102898651060114a0aa041ed7393f943 100644 --- a/src/users/user_replay.hpp +++ b/src/users/user_replay.hpp @@ -24,7 +24,7 @@ public: virtual ~ReplayUser(); double next_submission(); virtual void jobs_to_submit( - double date, std::list<Job *> &jobs, std::list<Profile *> &profiles); + double date, std::list<shared_ptr<Job>> &jobs, std::list<const Profile *> &profiles); protected: /** @@ -38,7 +38,7 @@ protected: * A job is read in the original trace. Handle it depending on the user * behavior and returns if it should still be executed now. */ - virtual bool handle_job(double date, Job *job, Profile *profile) = 0; + virtual bool handle_job(double date, shared_ptr<Job>job, Profile *profile) = 0; virtual int *get_dm_stat(); protected: @@ -63,10 +63,10 @@ public: ~ReplayUserRigid(); double next_submission(); void jobs_to_submit( - double date, std::list<Job *> &jobs, std::list<Profile *> &profiles); + double date, std::list<shared_ptr<Job>> &jobs, std::list<const Profile *> &profiles); protected: - bool handle_job(double date, Job *job, Profile *profile); + bool handle_job(double date, shared_ptr<Job>job, Profile *profile); }; /** @@ -84,13 +84,13 @@ public: ~ReplayUserReconfig(); double next_submission(); void jobs_to_submit( - double date, std::list<Job *> &jobs, std::list<Profile *> &profiles); + double date, std::list<shared_ptr<Job>> &jobs, std::list<const Profile *> &profiles); protected: /** Draw a random variable according to the proportions given by * big_medium_little and reconfigure the number of cores requested * accordingly. */ - bool handle_job(double date, Job *job, Profile *profile); + bool handle_job(double date, shared_ptr<Job>job, Profile *profile); private: double big, medium, little; @@ -127,10 +127,10 @@ public: ~DMUserReconfig(); double next_submission(); void jobs_to_submit( - double date, std::list<Job *> &jobs, std::list<Profile *> &profiles); + double date, std::list<shared_ptr<Job>> &jobs, std::list<const Profile *> &profiles); protected: - bool handle_job(double date, Job *job, Profile *profile); + bool handle_job(double date, shared_ptr<Job>job, Profile *profile); double alpha = 1.0; // for the speedup model }; @@ -146,10 +146,10 @@ public: ~DMUserDegrad(); double next_submission(); void jobs_to_submit( - double date, std::list<Job *> &jobs, std::list<Profile *> &profiles); + double date, std::list<shared_ptr<Job>> &jobs, std::list<const Profile *> &profiles); protected: - bool handle_job(double date, Job *job, Profile *profile); + bool handle_job(double date, shared_ptr<Job>job, Profile *profile); }; /** @@ -164,10 +164,10 @@ public: ~DMUserRenonce(); double next_submission(); void jobs_to_submit( - double date, std::list<Job *> &jobs, std::list<Profile *> &profiles); + double date, std::list<shared_ptr<Job>> &jobs, std::list<const Profile *> &profiles); protected: - bool handle_job(double date, Job *job, Profile *profile); + bool handle_job(double date, shared_ptr<Job>job, Profile *profile); }; /** @@ -182,8 +182,8 @@ public: ~DMUserDelay(); double next_submission(); void jobs_to_submit( - double date, std::list<Job *> &jobs, std::list<Profile *> &profiles); + double date, std::list<shared_ptr<Job>> &jobs, std::list<const Profile *> &profiles); protected: - bool handle_job(double date, Job *job, Profile *profile); + bool handle_job(double date, shared_ptr<Job>job, Profile *profile); }; \ No newline at end of file