diff --git a/Planner/Array.h b/Planner/Array.h index f1e59f8a..492f57e4 100644 --- a/Planner/Array.h +++ b/Planner/Array.h @@ -1,42 +1,37 @@ +#pragma once + #include #include #include -#pragma once +#include + template class Array { -protected: - long length; - T** elements; +private: + std::vector elements; + public: - Array(){ - length=0; - elements=NULL; + Array() { } + + virtual ~Array() { + for (auto& elem : elements) + delete elem; + elements.clear(); } - virtual ~Array(){ - if (elements !=NULL){ - for (long i=0; i& getElements() const { return elements; } }; \ No newline at end of file diff --git a/Planner/CompilationSupervisor.h b/Planner/CompilationSupervisor.h index ea43ab70..b757451e 100644 --- a/Planner/CompilationSupervisor.h +++ b/Planner/CompilationSupervisor.h @@ -1,20 +1,22 @@ +#pragma once + #include "Supervisor.h" #include "CompilationTask.h" -#pragma once -class CompilationSupervisor: public Supervisor { -public: - CompilationSupervisor(){ - this->init("compilationTasks", 4); + +class CompilationSupervisor : public Supervisor { +public: + CompilationSupervisor() { + this->init("compilationTasks", 4); } - CompilationTask * getTaskById(long task_id){ - for (long i=0; i< length; ++i){ - CompilationTask * task = get(i); - if (task->getId()==task_id) + CompilationTask* getTaskById(long task_id) { + for (long i = 0; i < getLength(); ++i) { + CompilationTask* task = get(i); + if (task->getId() == task_id) return task; } return NULL; } - virtual String getStatePrefix(){ + virtual String getStatePrefix() { return String("Compilation"); - } + } }; \ No newline at end of file diff --git a/Planner/CompilationTask.h b/Planner/CompilationTask.h index ba1fb457..18059a6c 100644 --- a/Planner/CompilationTask.h +++ b/Planner/CompilationTask.h @@ -1,47 +1,51 @@ -#include "Task.h" #pragma once -class CompilationTask: public Task { - String test_id; - String makefile_text; -public: - void setTestId(String * test_id_in){ - test_id = String(test_id_in->getCharArray()); - } - void setMakefileText(String * makefile_text_in){ - makefile_text = String(makefile_text_in->getCharArray(), '|'); - } - virtual void print(){ - printf("id=%ld; maxtime=%d; test_id=%s\n", id, maxtime, - test_id.getCharArray()); - printf("makefile_text=%s\n", makefile_text.getCharArray()); - } - CompilationTask(Text * lines, int offset):Task(lines,offset) { - setTestId(lines->get(offset+2)); - setMakefileText(lines->get(offset+3)); - setState(Waiting); - kernels=1; - } - - virtual void prepareWorkspace(){ - String makeFilePath = String(id)+"/Makefile"; - File makeFileFile = File(makeFilePath, this->makefile_text); - String tests = userWorkspace+"/projects"; - String testPath= tests+"/"+test_id; - String copyCommand = "cp -r " + String::DQuotes(testPath + "/.") + " "+ String::DQuotes(workspace); - system(copyCommand.getCharArray()); - } - virtual String getLaunchScriptText(){ - String modules = userWorkspace+"/modules"; - String starterCall = modules+"/starter"; - String launcherCall = modules+"/launcher"; - return String::DQuotes(starterCall)+" "+ - String::DQuotes(launcherCall)+" "+ - String(maxtime)+" "+ - String::DQuotes("")+" "+ - "make -j -f Makefile"; - } - virtual void analyseResults(){ - String binary = workspace+"/0"; - state = Utils::Exists(binary)? Done:DoneWithErrors; + +#include "Task.h" +#include "Text.h" + +class CompilationTask : public Task { + String test_id; + String makefile_text; +public: + void setTestId(String* test_id_in) { + test_id = String(test_id_in->getCharArray()); + } + void setMakefileText(String* makefile_text_in) { + makefile_text = String(makefile_text_in->getCharArray(), '|'); + } + virtual void print() const { + printf("id=%ld; maxtime=%d; test_id=%s\n", id, maxtime, + test_id.getCharArray()); + printf("makefile_text=%s\n", makefile_text.getCharArray()); + } + + CompilationTask(Text* lines, int offset) :Task(lines, offset) { + setTestId(lines->get(offset + 2)); + setMakefileText(lines->get(offset + 3)); + setState(Waiting); + kernels = 1; + } + + virtual void prepareWorkspace() { + String makeFilePath = String(id) + "/Makefile"; + File makeFileFile = File(makeFilePath, this->makefile_text); + String tests = userWorkspace + "/projects"; + String testPath = tests + "/" + test_id; + String copyCommand = "cp -r " + String::DQuotes(testPath + "/.") + " " + String::DQuotes(workspace); + system(copyCommand.getCharArray()); + } + virtual String getLaunchScriptText() { + String modules = userWorkspace + "/modules"; + String starterCall = modules + "/starter"; + String launcherCall = modules + "/launcher"; + return String::DQuotes(starterCall) + " " + + String::DQuotes(launcherCall) + " " + + String(maxtime) + " " + + String::DQuotes("") + " " + + "make -j -f Makefile"; + } + virtual void analyseResults() { + String binary = workspace + "/0"; + state = Utils::Exists(binary) ? Done : DoneWithErrors; } }; \ No newline at end of file diff --git a/Planner/File.h b/Planner/File.h index 21738214..a93f8925 100644 --- a/Planner/File.h +++ b/Planner/File.h @@ -1,67 +1,70 @@ -#include "Text.h" -#pragma once -class File { - FILE* ptr; -public: - File(String* name) { - ptr = fopen(name->getCharArray(), "r"); - } - File(const char * name) { - ptr = fopen(name, "r"); - } - File(const String& name, const String& text){ - ptr = fopen(name.getCharArray(), "w"); - fprintf(ptr, "%s\n", text.getCharArray()); - } - ~File() { +#pragma once +#include "String.h" +#include "Text.h" + +class File { + FILE* ptr; +public: + File(String* name) { + ptr = fopen(name->getCharArray(), "r"); + } + File(const char* name) { + ptr = fopen(name, "r"); + } + File(const String& name, const String& text) { + ptr = fopen(name.getCharArray(), "w"); + fprintf(ptr, "%s\n", text.getCharArray()); + } + ~File() { Close(); } - void Close(){ - if (ptr != NULL) { - fclose(ptr); - ptr = NULL; - } + void Close() { + if (ptr != NULL) { + fclose(ptr); + ptr = NULL; + } + } + Text* readLines() { + Text* lines = new Text(); + int c; + String* line = NULL; + bool lineStarted = false; + do { + c = fgetc(ptr); + if (lineStarted) { + switch (c) { + case '\r': + break; + case '\n': + case EOF: + lines->add(line); + line = NULL; + lineStarted = false; + break; + default: + line->addChar((char)c); + break; + } + } + else { + switch (c) { + case '\r': + break; + case '\n': + line = new String(); + lines->add(line); + line = NULL; + break; + case EOF: + break; + default: + line = new String(); + line->addChar((char)c); + lineStarted = true; + break; + } + } + } while (c != EOF); + return lines; } - Text* readLines(){ - Text* lines = new Text(); - int c; - String * line = NULL; - bool lineStarted = false; - do { - c = fgetc(ptr); - if (lineStarted){ - switch (c) { - case '\r': - break; - case '\n': - case EOF: - lines->add(line); - line = NULL; - lineStarted = false; - break; - default: - line->addChar((char)c); - break; - } - }else { - switch (c){ - case '\r': - break; - case '\n': - line = new String(); - lines->add(line); - line = NULL; - break; - case EOF: - break; - default: - line = new String(); - line->addChar((char)c); - lineStarted = true; - break; - } - } - }while (c!=EOF); - return lines; - } }; \ No newline at end of file diff --git a/Planner/Global.h b/Planner/Global.h index 965e4836..a3ce0faf 100644 --- a/Planner/Global.h +++ b/Planner/Global.h @@ -1,13 +1,10 @@ +#pragma once + #include "String.h" -#pragma once + String userWorkspace; -#pragma once String packageWorkspace; -#pragma once int maxKernels; -#pragma once int busyKernels; -#pragma once int freeKernels; -#pragma once -String dvm_drv; \ No newline at end of file +String dvm_drv; diff --git a/Planner/Planner.cpp b/Planner/Planner.cpp index 8db4b475..5cf67c90 100644 --- a/Planner/Planner.cpp +++ b/Planner/Planner.cpp @@ -1,18 +1,27 @@ +#define _CRT_SECURE_NO_WARNINGS +using namespace std; + +#if __cplusplus >= 201703L +#include +#else +#include +#endif + #include "CompilationSupervisor.h" #include "RunSupervisor.h" #include "Global.h" -#include #include //https://ru.wikipedia.org/wiki/%D0%A1%D0%B8%D0%B3%D0%BD%D0%B0%D0%BB_(Unix) void hdl(int sig) { - String file_name = "GOT_SIGNAL_AT_"+String(Utils::getAbsoluteTime()); + String file_name = "GOT_SIGNAL_AT_"+ String(Utils::getAbsoluteTime()); FILE * res = fopen(file_name.getCharArray(),"w"); fprintf(res,"%d\n", sig); fclose(res); } -void set_handlers(){ +void set_handlers() { +#ifndef _WIN32 struct sigaction act; memset(&act, 0, sizeof(act)); act.sa_handler = hdl; @@ -73,7 +82,9 @@ void set_handlers(){ sigaction(SIGVTALRM, &act, 0); sigaction(SIGXCPU, &act, 0); sigaction(SIGXFSZ, &act, 0); +#endif } + int main(int argc, char ** argv) { //+ @@ -84,14 +95,25 @@ int main(int argc, char ** argv) maxKernels = atoi(argv[3]); dvm_drv = String(argv[4]); //-- - freeKernels = maxKernels; - busyKernels= 0; - //-- - chdir(packageWorkspace.getCharArray()); + freeKernels = maxKernels; + busyKernels= 0; + //-- + +#if __cplusplus >= 201703L + std::filesystem::current_path(packageWorkspace.getCharArray()); +#else + chdir(packageWorkspace.getCharArray()); +#endif + userWorkspace.println(); packageWorkspace.println(); printf("%d\n", maxKernels); +#ifndef _WIN32 int pid = getpid(); +#else + int pid = _getpid(); +#endif + printf("PID=%d\n", pid); File pidFile("PID", String(pid)); pidFile.Close(); @@ -107,6 +129,6 @@ int main(int argc, char ** argv) RunSupervisor * runSupervisor = new RunSupervisor(compilationSupervisor); printf("%ld\n", runSupervisor->getLength()); runSupervisor->print(); - runSupervisor->Do(); + runSupervisor->DoWithSchedule(maxKernels); return 0; } diff --git a/Planner/RunSupervisor.h b/Planner/RunSupervisor.h index c543a601..527fc343 100644 --- a/Planner/RunSupervisor.h +++ b/Planner/RunSupervisor.h @@ -1,25 +1,28 @@ +#pragma once + #include "CompilationSupervisor.h" #include "RunTask.h" -#pragma once -class RunSupervisor: public Supervisor { -public: - RunSupervisor(CompilationSupervisor * compilationSupervisor){ - this->init("runTasks", 8); + +class RunSupervisor : public Supervisor { +public: + RunSupervisor(CompilationSupervisor* compilationSupervisor) { + this->init("runTasks", 8); //проверить отмененные задачи. - for (long i=0; i< this->length; ++i){ - RunTask * task = this->get(i); - CompilationTask * parent = compilationSupervisor->getTaskById( task->getTestCompilationTaskId()); - task->setState((parent->getState()==Done)?Waiting:Canceled); - task->setParent(parent); + for (long i = 0; i < getLength(); ++i) { + RunTask* task = this->get(i); + CompilationTask* parent = compilationSupervisor->getTaskById(task->getTestCompilationTaskId()); + task->setState((parent->getState() == Done) ? Waiting : Canceled); + task->setParent(parent); printf("id=%ld; parent_id = %ld; state=%s\n", - task->getId(), - task->getParent()->getId(), - task->printState().getCharArray()); - } + task->getId(), + task->getParent()->getId(), + task->printState().getCharArray()); + } } - virtual String getStatePrefix(){ + virtual String getStatePrefix() { return String("Running"); } + /* virtual void Finalize(){ this->state = Archivation; @@ -29,4 +32,4 @@ public: printf("Archivation ended\n"); } */ -}; \ No newline at end of file +}; diff --git a/Planner/RunTask.h b/Planner/RunTask.h index 1120c231..622fc876 100644 --- a/Planner/RunTask.h +++ b/Planner/RunTask.h @@ -1,94 +1,96 @@ +#pragma once + #include "CompilationTask.h" -#pragma once -class RunTask : public Task { - long testcompilationtask_id; - String binary_name; - String matrix; - String environments; - String usr_par; - String args; - CompilationTask* parent; -public: - virtual void print(){ - printf("id=%ld; maxtime=%d; testcompilationtask_id=%ld; matrix=%s; environments=%s; usr_par=%s; args=%s kernels=%d\n", - id, - maxtime, - testcompilationtask_id, - matrix.getCharArray(), - environments.getCharArray(), - usr_par.getCharArray(), - args.getCharArray(), - kernels - ); - } - int setKernels(String * kernels_s){ + +class RunTask : public Task { + long testcompilationtask_id; + String binary_name; + String matrix; + String environments; + String usr_par; + String args; + CompilationTask* parent; +public: + virtual void print() const { + printf("id=%ld; maxtime=%d; testcompilationtask_id=%ld; matrix=%s; environments=%s; usr_par=%s; args=%s kernels=%d\n", + id, + maxtime, + testcompilationtask_id, + matrix.getCharArray(), + environments.getCharArray(), + usr_par.getCharArray(), + args.getCharArray(), + kernels + ); + } + int setKernels(String* kernels_s) { return kernels = atoi(kernels_s->getCharArray()); - } - long setTestCompilationTaskId(String * id_s){ - return testcompilationtask_id=strtol(id_s->getCharArray(), NULL, 10); - } - long getTestCompilationTaskId(){ - return testcompilationtask_id; - } - void setMatrix(String * matrix_in){ - matrix= String (matrix_in->getCharArray()); - } - void setEnvironments(String * environments_in){ - environments= String(environments_in->getCharArray()); - } - void setUsrPar(String * usr_par_in){ - usr_par= String(usr_par_in->getCharArray(),'|'); - } - void setArgs(String * args_in){ - args= String(args_in->getCharArray()); } - void setParent(CompilationTask * parent_in){ - parent = parent_in; - binary_name = "spf_"+ String(id)+"_"+matrix.Replace(' ','_'); - } - CompilationTask * getParent(){ - return parent; - } - RunTask(Text * lines, int offset):Task(lines,offset) { - setTestCompilationTaskId(lines->get(offset+2)); - setMatrix(lines->get(offset+3)); - setEnvironments(lines->get(offset+4)); - setUsrPar(lines->get(offset+5)); - setArgs(lines->get(offset+6)); - setKernels(lines->get(offset+7)); - } - - virtual String getLaunchScriptText(){ - String modules = userWorkspace+"/modules"; - String starterCall = modules+"/starter"; - String launcherCall = modules+"/launcher"; + long setTestCompilationTaskId(String* id_s) { + return testcompilationtask_id = strtol(id_s->getCharArray(), NULL, 10); + } + long getTestCompilationTaskId() { + return testcompilationtask_id; + } + void setMatrix(String* matrix_in) { + matrix = String(matrix_in->getCharArray()); + } + void setEnvironments(String* environments_in) { + environments = String(environments_in->getCharArray()); + } + void setUsrPar(String* usr_par_in) { + usr_par = String(usr_par_in->getCharArray(), '|'); + } + void setArgs(String* args_in) { + args = String(args_in->getCharArray()); + } + void setParent(CompilationTask* parent_in) { + parent = parent_in; + binary_name = "spf_" + String(id) + "_" + matrix.Replace(' ', '_'); + } + CompilationTask* getParent() { + return parent; + } + RunTask(Text* lines, int offset) :Task(lines, offset) { + setTestCompilationTaskId(lines->get(offset + 2)); + setMatrix(lines->get(offset + 3)); + setEnvironments(lines->get(offset + 4)); + setUsrPar(lines->get(offset + 5)); + setArgs(lines->get(offset + 6)); + setKernels(lines->get(offset + 7)); + } + + virtual String getLaunchScriptText() { + String modules = userWorkspace + "/modules"; + String starterCall = modules + "/starter"; + String launcherCall = modules + "/launcher"; //- - String dvm_start = String::DQuotes(dvm_drv) + " run "; - if (!matrix.isEmpty()) - dvm_start = dvm_start+matrix + " "; - dvm_start = dvm_start+ String::DQuotes("./" + binary_name); - if (!args.isEmpty()) - dvm_start = dvm_start+ " " + args; - return String::DQuotes(starterCall)+" "+ - String::DQuotes(launcherCall)+" "+ - String(maxtime)+" "+ - String::DQuotes("killall -SIGKILL " + binary_name)+" "+ - dvm_start; - } - virtual void prepareWorkspace(){ - String binary_src = parent->getWorkspace()+"/0"; - String binary_dst = workspace+"/"+binary_name; - Utils::Copy(binary_src, binary_dst); - if (!usr_par.isEmpty()){ - String parPath = String(id)+"/usr.par"; - File parFile = File(parPath, usr_par); - } - } - virtual String getStartCommand(){ - String res = workspace+"/run"; - if (!environments.isEmpty()) - res = environments+" "+res; - printf("START %ld: %s\n", id, res.getCharArray()); - return res; + String dvm_start = String::DQuotes(dvm_drv) + " run "; + if (!matrix.isEmpty()) + dvm_start = dvm_start + matrix + " "; + dvm_start = dvm_start + String::DQuotes("./" + binary_name); + if (!args.isEmpty()) + dvm_start = dvm_start + " " + args; + return String::DQuotes(starterCall) + " " + + String::DQuotes(launcherCall) + " " + + String(maxtime) + " " + + String::DQuotes("killall -SIGKILL " + binary_name) + " " + + dvm_start; } -}; \ No newline at end of file + virtual void prepareWorkspace() { + String binary_src = parent->getWorkspace() + "/0"; + String binary_dst = workspace + "/" + binary_name; + Utils::Copy(binary_src, binary_dst); + if (!usr_par.isEmpty()) { + String parPath = String(id) + "/usr.par"; + File parFile = File(parPath, usr_par); + } + } + virtual String getStartCommand() { + String res = workspace + "/run"; + if (!environments.isEmpty()) + res = environments + " " + res; + printf("START %ld: %s\n", id, res.getCharArray()); + return res; + } +}; diff --git a/Planner/String.h b/Planner/String.h index ed85121d..f6d6315e 100644 --- a/Planner/String.h +++ b/Planner/String.h @@ -1,220 +1,226 @@ +#pragma once + #include #include #include -#include -#pragma once -class String { - friend String operator+(const String& a, const String& b); - long length; - char* body; -public: - String() { - length = 0; - body = new char[1]; - body[0] = '\0'; - } - - String(const char* s) { - length = strlen(s); - body = new char[length + 1]; - for (long i = 0; i < length; ++i) - body[i] = s[i]; - body[length]='\0'; - } - String(const char* s, char ps) { - length = strlen(s); - body = new char[length + 1]; - for (long i = 0; i < length; ++i){ - body[i] = (s[i]==ps)? '\n': s[i]; - } - body[length]='\0'; - } - ~String() { - if (body != NULL) { - delete[] body; - } - } - void println() const{ - printf("[%s]\n", body); - } - void addChar(char c) { - char* buf = new char[length + 2]; - for (long i = 0; i < length; ++i) { - buf[i] = body[i]; - } - buf[length] = c; - - length++; +#include + +class String { + friend String operator+(const String& a, const String& b); + long length; + char* body; +public: + String() { + length = 0; + body = new char[1]; + body[0] = '\0'; + } + + String(const char* s) { + length = (long)strlen(s); + body = new char[length + 1]; + for (long i = 0; i < length; ++i) + body[i] = s[i]; + body[length] = '\0'; + } + String(const char* s, char ps) { + length = (long)strlen(s); + body = new char[length + 1]; + for (long i = 0; i < length; ++i) { + body[i] = (s[i] == ps) ? '\n' : s[i]; + } + body[length] = '\0'; + } + ~String() { + if (body != NULL) { + delete[] body; + } + } + void println() const { + printf("[%s]\n", body); + } + void addChar(char c) { + char* buf = new char[length + 2]; + for (long i = 0; i < length; ++i) { + buf[i] = body[i]; + } + buf[length] = c; + + length++; //-- - buf[length] = '\0'; - delete[] body; - body = buf; - buf = NULL; - } - char * getCharArray() const{ - return body; - } - - - String (int s){ - length = 0; - body = new char[1]; - body[0] = '\0'; - if (s>=0){ - int s_ = s; - int size = 1; - while (s_>=10){ - s_ = s_/10; - size++; - } - length = size; - body = new char [size+1]; - sprintf(body, "%d", s); - } - } - String (long s){ - length = 0; - body = new char[1]; - body[0] = '\0'; - if (s>=0){ - long s_ = s; - long size = 1; - while (s_>=10){ - s_ = s_/10; - size++; - } - length = size; - body = new char [size+1]; - sprintf(body, "%ld", s); - } - } - - const String& operator=(const String& s){ - if (body != NULL) - delete[] body; - length = s.length; - body = new char[length+1]; - for (long i=0; i= 0) { + int s_ = s; + int size = 1; + while (s_ >= 10) { + s_ = s_ / 10; + size++; + } + length = size; + body = new char[size + 1]; + sprintf(body, "%d", s); + } + } + + String(long s) : String((long long)s) { } + + String(long long s) { + length = 0; + body = new char[1]; + body[0] = '\0'; + if (s >= 0) { + long long s_ = s; + long size = 1; + while (s_ >= 10) { + s_ = s_ / 10; + size++; + } + length = size; + body = new char[size + 1]; + sprintf(body, "%lld", s); + } + } + + const String& operator=(const String& s) { + if (body != NULL) + delete[] body; + length = s.length; + body = new char[length + 1]; + for (long i = 0; i < length; ++i) + body[i] = s.body[i]; + body[length] = '\0'; + return *this; + } + + static String DQuotes(const String& s) { String res; - for (long i=0; ilength) return false; - long k=0; - long start=-1; - for (long i=0; i length) return false; + long k = 0; + long start = -1; + for (long i = 0; i < length; ++i) { + if (search_on) { + if (k < s.length) { + if (body[i] == s.body[k]) { + k++; + } + else { //обрыв поиска. - search_on =false; - k=0; - start=-1; - } - } - else { + search_on = false; + k = 0; + start = -1; + } + } + else { //printf("starts with %ld", start); - return true; - } - }else { - if (body[i]== s.body[0]){ - k=1; - start=i; - search_on=true; + return true; + } + } + else { + if (body[i] == s.body[0]) { + k = 1; + start = i; + search_on = true; //printf("search started %d\n", start); - } - } - } - if (search_on) { + } + } + } + if (search_on) { //printf("starts with %ld\n", start); - res=true; - } - return res; - } - String toUpper(){ + res = true; + } + return res; + } + String toUpper() { String res = String(this->getCharArray()); - for (long i=0; i -#include - -int main(void) { - FILE * f; - int c; - - if ( ! ( f = fopen("file.txt", "r") ) ) - return -1; - - while ( ( c = fgetc(f) ) != EOF ) - putchar( isupper(c) ? tolower(c) : toupper(c) ); - - return ( fclose(f) ); -} - */ - -}; + long getLength() { + return length; + } + bool operator==(const String& s) const { + if (length != s.length) return false; + for (long i = 0; i < length; ++i) { + if (body[i] != s.body[i]) return false; + } + return true; + } + /* регистр. + #include + #include + + int main(void) { + FILE * f; + int c; + + if ( ! ( f = fopen("file.txt", "r") ) ) + return -1; + + while ( ( c = fgetc(f) ) != EOF ) + putchar( isupper(c) ? tolower(c) : toupper(c) ); + + return ( fclose(f) ); + } + */ +}; -String operator+(const String& a, const String& b){ - String res = String(); - res.length =a.length+b.length; - res.body = new char[res.length+1]; - for (long i=0; i +#pragma once + +#include +#include +#include +#include +#include "File.h" +#include "Task.h" +#include "Array.h" -#pragma once enum SupervisorState { WorkspacesCreation, //0 - Preparation, //1 - Execution, //2 + Preparation, //1 + Execution, //2 Archivation, //3 - End //4 + End //4 }; -#pragma once + template -class Supervisor : public Array { +class Supervisor : public Array { protected: - SupervisorState state; -public: - virtual String getStatePrefix(){ - return String(""); - } - String printState(){ - switch(state){ - case WorkspacesCreation: - return String("WorkspacesCreation"); - case Preparation: - return String("Preparation"); - case Execution: - return String("Execution"); - case Archivation: - return String("Archivation"); - case End: - return String("End"); - default: - return "?"; - } - } - //- - void print(){ - for (long i=0; i< this->length; ++i) - this->elements[i]->print(); - } - void init(const char * fileName, int recordSize){ - state = WorkspacesCreation; - File * packedTasks = new File(fileName); - Text * lines = packedTasks->readLines(); - this->length = lines->getLength()/recordSize; - this->elements = new T* [this->length]; - int offset=0; - for (int i=0; i< this->length; ++i){ - this->elements[i]= new T(lines, offset); - offset+=recordSize; - } - delete packedTasks; - delete lines; - } - void Do(){ - saveState(); - long activeCount=0; - //todo обязательно убрать отладочную печать. - printf("tasks count = %ld\n", this->length); - while (this->state!= End){ -// printf("state=%d\n", this->state); -// printf("max=%d; busy=%d; free=%d\n", maxKernels, busyKernels, freeKernels); - activeCount=0; - for (long i=0; ilength; ++i){ - T * task = this->elements[i]; - switch (this->state){ - case WorkspacesCreation: - if (task->getState()==Waiting){ - activeCount++; - task->createWorkspace(); - task->setState(WorkspaceCreated); - } - break; - case Preparation: - if (task->getState()==WorkspaceCreated){ - activeCount++; - task->prepareWorkspace(); - task->createLaunchScript(); - task->setState(WorkspaceReady); - } - break; - case Execution: - if (task->getState()==WorkspaceReady){ - activeCount++; - task->start_time=Utils::getAbsoluteTime(); - task->Start(); - }else if (task->getState()==Running){ - activeCount++; - task->Check(); - } - break; - default: -// printf("id = %ld; state = %d\n", task->getId(), task->getState()); - break; - } - } -// printf("active count = %d\n", activeCount); - if (activeCount==0){ - switch (this->state){ - case WorkspacesCreation: - this->state = Preparation; - saveState(); - break; - case Preparation: - this->state = Execution; - saveState(); - break; - case Execution: - Finalize(); - this->state = End; - saveState(); - break; - default: - this->state = End; - break; - } - } - Utils::Sleep(2); - } - } - virtual void Finalize(){} - void saveState(){ - Utils::Sleep(1); //чтобы не было одинаковых по дате файлов. - String stateFile = packageWorkspace+"/state/"+getStatePrefix()+printState(); - //printf("stateFile=<%s>\n", stateFile.getCharArray()); - File(stateFile, Utils::getDate()); - } + SupervisorState state; +public: + virtual String getStatePrefix() { + return String(""); + } + String printState() { + switch (state) { + case WorkspacesCreation: + return String("WorkspacesCreation"); + case Preparation: + return String("Preparation"); + case Execution: + return String("Execution"); + case Archivation: + return String("Archivation"); + case End: + return String("End"); + default: + return "?"; + } + } + //- + void print() { + for (auto& elem : this->getElements()) + elem->print(); + } + + void init(const char* fileName, int recordSize) { + state = WorkspacesCreation; + File* packedTasks = new File(fileName); + Text* lines = packedTasks->readLines(); + + const long length = lines->getLength() / recordSize; + int offset = 0; + for (int i = 0; i < length; ++i) { + this->add(new T(lines, offset)); + offset += recordSize; + } + delete packedTasks; + delete lines; + } + + void changeState() { + switch (this->state) { + case WorkspacesCreation: + this->state = Preparation; + saveState(); + break; + case Preparation: + this->state = Execution; + saveState(); + break; + case Execution: + Finalize(); + this->state = End; + saveState(); + break; + default: + this->state = End; + break; + } + } + + void Do() { + saveState(); + long activeCount = 0; + //todo обязательно убрать отладочную печать. + printf("tasks count = %ld\n", this->getLength()); + while (this->state != End) { + // printf("state=%d\n", this->state); + // printf("max=%d; busy=%d; free=%d\n", maxKernels, busyKernels, freeKernels); + activeCount = 0; + for (long i = 0; i < this->getLength(); ++i) { + T* task = this->get(i); + switch (this->state) { + case WorkspacesCreation: + if (task->getState() == Waiting) { + activeCount++; + task->createWorkspace(); + task->setState(WorkspaceCreated); + } + break; + case Preparation: + if (task->getState() == WorkspaceCreated) { + activeCount++; + task->prepareWorkspace(); + task->createLaunchScript(); + task->setState(WorkspaceReady); + } + break; + case Execution: + if (task->getState() == WorkspaceReady) { + activeCount++; + task->Start(); + } + else if (task->getState() == Running) { + activeCount++; + task->Check(); + } + break; + default: + // printf("id = %ld; state = %d\n", task->getId(), task->getState()); + break; + } + } + // printf("active count = %d\n", activeCount); + if (activeCount == 0) + changeState(); + Utils::Sleep(2); + } + } + + + void DoWithSchedule(int maxKernels) { + saveState(); + + // подготовка тестов + while (this->state != Execution) { + for (auto& task : this->getElements()) { + switch (this->state) { + case WorkspacesCreation: + if (task->getState() == Waiting) { + task->createWorkspace(); + task->setState(WorkspaceCreated); + } + break; + case Preparation: + if (task->getState() == WorkspaceCreated) { + task->prepareWorkspace(); + task->createLaunchScript(); + task->setState(WorkspaceReady); + } + break; + default: + //printf("id = %ld; state = %d\n", task->getId(), task->getState()); + break; + } + } + changeState(); + } + + map, std::greater> sortedByKernelNeeds; + + long activeTasks = 0; + long done = 0; + for (auto& task : this->getElements()) { + if (task->getState() == WorkspaceReady) { + activeTasks++; + sortedByKernelNeeds[task->getKernels()].push(task); + } + } + + printf("total tasks count = %ld, active task count %ld, maxkernels %d\n", this->getLength(), activeTasks, maxKernels); + + int busyKernels = 0; + set activeTaskSet; + bool ignoreCheck = true; + + while (activeTasks) { + long oldActiveTasks = activeTasks; + vector emptyKeys; + + //ставим задачи от больших к меньшему по ядрам + for (auto& elem : sortedByKernelNeeds) { + int freeKernels = maxKernels - busyKernels; + int kernelsNeeded = elem.first; + + while (kernelsNeeded <= freeKernels && elem.second.size()) { + T* task = elem.second.front(); + elem.second.pop(); + + activeTaskSet.insert(task); + task->Start(ignoreCheck); + printf("start task with %d kernels and id %ld\n", task->getKernels(), task->getId()); + + busyKernels += task->getKernels(); + freeKernels = maxKernels - busyKernels; + } + + if (elem.second.size() == 0) + emptyKeys.push_back(kernelsNeeded); + + //если ядер не осталось, то нет смысла дальше смотреть + if (freeKernels == 0) + break; + } + + // очищаем от пустых ключей + for (auto& empty : emptyKeys) + sortedByKernelNeeds.erase(empty); + + // проверяем нет ли завершившихся задач + for (auto it = activeTaskSet.begin(); it != activeTaskSet.end(); ) + { + T* task = *(it); + + if (task->Check()) { + it++; + activeTaskSet.erase(task); + activeTasks--; + done++; + busyKernels -= task->getKernels(); + printf(" done task with %d kernels and id %ld\n", task->getKernels(), task->getId()); + + continue; + } + it++; + } + + if (oldActiveTasks != activeTasks) + printf("done %ld / %ld\n", done, this->getLength()); + } + + changeState(); + } + + virtual void Finalize() {} + + void saveState() { + Utils::Sleep(1); //чтобы не было одинаковых по дате файлов. + String stateFile = packageWorkspace + "/state/" + getStatePrefix() + printState(); + //printf("stateFile=<%s>\n", stateFile.getCharArray()); + File(stateFile, Utils::getDate()); + } }; \ No newline at end of file diff --git a/Planner/Task.h b/Planner/Task.h index 8c95d128..cb246abb 100644 --- a/Planner/Task.h +++ b/Planner/Task.h @@ -1,9 +1,12 @@ +#pragma once + +#include + #include "File.h" #include "Utils.h" #include "Global.h" - -#pragma once -enum TaskState { + +enum TaskState { Inactive, //0 Waiting, //1 WorkspaceCreated, //2 @@ -24,148 +27,165 @@ enum TaskState { NoSuchTask, //17 FailedToQueue, //18 AbortingByUser //19 -}; -#pragma once -enum TestType{ +}; + +enum TestType { Default, //0 Correctness, //1 Performance, //2 }; -#pragma once -class Task { -protected: +class Task { +protected: long id; - int maxtime; + int maxtime; int kernels; //получение зависит от типа задачи. - String workspace; - TaskState state; + String workspace; + TaskState state; + std::chrono::system_clock::time_point start_time; + public: - long start_time; - String printState(){ - switch(state){ - case Inactive: - return String("Inactive"); - case Waiting: - return String("Waiting"); - case WorkspaceCreated: - return String("WorkspaceCreated"); - case WorkspaceReady: - return String("WorkspaceReady"); - case Running: - return String("Running"); - case Canceled: - return String("Canceled"); - case Finished: - return String("Finished"); - case FinishedAbortedByTimeout: - return String("FinishedAbortedByTimeout"); - case FinishedAbortedByUser: - return String("FinishedAbortedByUser"); - case Done: - return String("Done"); - case DoneWithErrors: - return String("DoneWithErrors"); - case AbortedByTimeout: - return String("AbortedByTimeout"); - case AbortedByUser: - return String("AbortedByUser"); - case Crushed: - return String("Crushed"); - case WrongTestFormat: - return String("WrongTestFormat"); - case InternalError: - return String("InternalError"); - case Queued: - return String("Queued"); - case NoSuchTask: - return String("NoSuchTask"); - case FailedToQueue: - return String("FailedToQueue"); - case AbortingByUser: - return String("AbortingByUser"); - default: - return "?"; - } - } - //-------------->> - long getId(){return id;} - long setId(String * id_s){ - return id=strtol(id_s->getCharArray(), NULL, 10); - } - int getMaxtime(){return maxtime;} - int setMaxtime(String * maxtime_s){ - return maxtime=atoi(maxtime_s->getCharArray()); - } - const String& getWorkspace(){return workspace;} - TaskState getState(){return state;} - TaskState setState(TaskState state_in){return state=state_in;} - Task(Text * lines, int offset){ - setId(lines->get(offset)); - setMaxtime(lines->get(offset+1)); - workspace = packageWorkspace+"/"+String(id); - } - virtual void print()=0; - //- - virtual void prepareWorkspace(){} - virtual String getLaunchScriptText()=0; - virtual String getStartCommand(){ - return workspace+"/run"; - } - - void createWorkspace(){ - Utils::Mkdir(workspace); - } - void createLaunchScript(){ - String launchScriptPath = workspace+"/run"; - String launchScriptText = - String("cd ")+String::DQuotes(workspace)+"\n"+ - getLaunchScriptText(); - File launchScriptFile = File(launchScriptPath, launchScriptText); - Utils::Chmod(launchScriptPath); - } - virtual void Start(){ - - if (kernels<=freeKernels){ - system(getStartCommand().getCharArray()); - state=Running; - //- - busyKernels= Utils::min(busyKernels+kernels, maxKernels); - freeKernels= Utils::max(0, maxKernels-busyKernels); - //- - } - } - virtual void analyseResults(){ - state=Finished; + String printState() { + switch (state) { + case Inactive: + return String("Inactive"); + case Waiting: + return String("Waiting"); + case WorkspaceCreated: + return String("WorkspaceCreated"); + case WorkspaceReady: + return String("WorkspaceReady"); + case Running: + return String("Running"); + case Canceled: + return String("Canceled"); + case Finished: + return String("Finished"); + case FinishedAbortedByTimeout: + return String("FinishedAbortedByTimeout"); + case FinishedAbortedByUser: + return String("FinishedAbortedByUser"); + case Done: + return String("Done"); + case DoneWithErrors: + return String("DoneWithErrors"); + case AbortedByTimeout: + return String("AbortedByTimeout"); + case AbortedByUser: + return String("AbortedByUser"); + case Crushed: + return String("Crushed"); + case WrongTestFormat: + return String("WrongTestFormat"); + case InternalError: + return String("InternalError"); + case Queued: + return String("Queued"); + case NoSuchTask: + return String("NoSuchTask"); + case FailedToQueue: + return String("FailedToQueue"); + case AbortingByUser: + return String("AbortingByUser"); + default: + return "?"; + } } - virtual void Check(){ - if (Utils::Exists(workspace+"/DONE")){ + + //-------------->> + void setStart() { start_time = std::chrono::system_clock::now(); } + + long getId() { return id; } + long setId(String* id_s) { + return id = strtol(id_s->getCharArray(), NULL, 10); + } + int getMaxtime() { return maxtime; } + int setMaxtime(String* maxtime_s) { + return maxtime = atoi(maxtime_s->getCharArray()); + } + const String& getWorkspace() { return workspace; } + TaskState getState() { return state; } + TaskState setState(TaskState state_in) { return state = state_in; } + Task(Text* lines, int offset) { + setId(lines->get(offset)); + setMaxtime(lines->get(offset + 1)); + workspace = packageWorkspace + "/" + String(id); + } + virtual void print() const = 0; + //- + virtual void prepareWorkspace() {} + virtual String getLaunchScriptText() = 0; + virtual String getStartCommand() { + return workspace + "/run"; + } + + void createWorkspace() { + Utils::Mkdir(workspace); + } + void createLaunchScript() { + String launchScriptPath = workspace + "/run"; + String launchScriptText = + String("cd ") + String::DQuotes(workspace) + "\n" + + getLaunchScriptText(); + File launchScriptFile = File(launchScriptPath, launchScriptText); + Utils::Chmod(launchScriptPath); + } + + int getKernels() const { return kernels; } + + void Start(bool dontCheck = false) { + if (kernels <= freeKernels || dontCheck) { + setStart(); + system(getStartCommand().getCharArray()); + state = Running; + //- + busyKernels = Utils::min(busyKernels + kernels, maxKernels); + freeKernels = Utils::max(0, maxKernels - busyKernels); + //- + } + } + + //return 'true' if done, 'false' - if running + virtual bool Check() { + if (Utils::Exists(workspace + "/DONE")) analyseResults(); - }else { - if (Utils::Exists(workspace+"/TIMEOUT")){ - state=AbortedByTimeout; + else { + if (Utils::Exists(workspace + "/TIMEOUT")) { + state = AbortedByTimeout; //todo определить по интервалу времени на всякий случай. - }else if (Utils::Exists(workspace+"/INTERRUPT")){ - state=AbortedByUser; - } else { - long now = Utils::getAbsoluteTime(); - long delta = now-start_time; - if (maxtime diff_time = end_time - start_time; + + if (maxtime * 1.1 < diff_time.count()) { + printf("SET STATUS ABORTED by timer to %ld with time %f sec / %f sec", id, diff_time.count(), maxtime * 1.1); + state = AbortedByTimeout; + } + } + } + + if (state != Running) { //- - busyKernels= Utils::min(busyKernels-kernels, maxKernels); - freeKernels= Utils::max(0, maxKernels-busyKernels); + busyKernels = Utils::min(busyKernels - kernels, maxKernels); + freeKernels = Utils::max(0, maxKernels - busyKernels); //- - saveState(); //не нужно. только для отладки. анализ будет делаться архивом. - } - } - virtual void saveState(){ - String stateFile = workspace+"/TaskState"; - File(stateFile, printState()); - } -}; + saveState(); + } + + return (state != Running); + } + + virtual void analyseResults() { + state = Finished; + } + + virtual void saveState() { + String stateFile = workspace + "/TaskState"; + File tmp(stateFile, printState()); + } +}; diff --git a/Planner/Text.h b/Planner/Text.h index d1a57075..fb759e31 100644 --- a/Planner/Text.h +++ b/Planner/Text.h @@ -1,25 +1,29 @@ +#pragma once + #include "String.h" #include "Array.h" -#pragma once -class Text: public Array { - public: - void Print(){ - printf("text length=%ld\n", length); - - for (long i=0; igetCharArray()); - // elements[i]->println(); + +class Text : public Array { +public: + void Print() const { + printf("text length=%ld\n", this->getLength()); + + auto elems = this->getElements(); + for (long i = 0; i < elems.size(); ++i) { + printf("i=%ld; [%s]\n", i, elems[i]->getCharArray()); + // elements[i]->println(); + } + } + + bool hasMatch(const String& s) const { + + for (auto& elem : this->getElements()) { + if (s.contains(*elem)) { + //printf("match: [%s]\n", elements[i]->getCharArray()); + return true; + } } - } - bool hasMatch(const String& s){ - - for (long i=0; igetCharArray()); - return true; - } - } //printf("no matches for [%s]\n", s.getCharArray()); return false; } -}; \ No newline at end of file +}; diff --git a/Planner/Utils.h b/Planner/Utils.h index eb077069..c3658b9d 100644 --- a/Planner/Utils.h +++ b/Planner/Utils.h @@ -1,49 +1,65 @@ +#pragma once + #include #include #include -#include #include +#include +#include + +#if __cplusplus >= 201703L +#include +#endif + #include "String.h" -#pragma once + class Utils { public: - static int max(int a, int b){ - return (a > b)? a:b; - } - static int min(int a, int b){ - return (a > b)? b:a; + static int max(int a, int b) { + return (a > b) ? a : b; } - static void Mkdir(const String& path){ + static int min(int a, int b) { + return (a > b) ? b : a; + } + static void Mkdir(const String& path) { +#if __cplusplus >= 201703L + std::filesystem::create_directory(path.getCharArray()); +#else mkdir(path.getCharArray(), 0777); - } +#endif + } + //https://stackoverflow.com/questions/4568681/using-chmod-in-a-c-program - static void Chmod(const String& path){ - String command = "chmod 777 "+String::DQuotes(path); + static void Chmod(const String& path) { + String command = "chmod 777 " + String::DQuotes(path); system(command.getCharArray()); - } + } + //https://stackoverflow.com/questions/230062/whats-the-best-way-to-check-if-a-file-exists-in-c - static bool Exists(const String& path){ - struct stat buffer; - return (stat (path.getCharArray(), &buffer) == 0); + static bool Exists(const String& path) { + struct stat buffer; + return (stat(path.getCharArray(), &buffer) == 0); } - static void Sleep(int s){ - usleep(s* 1000000); - } - static void Copy(const String& src, const String& dst){ - String command = "cp "+String::DQuotes(src)+" "+String::DQuotes(dst); - system(command.getCharArray()); + + //in seconds + static void Sleep(int s) { + std::chrono::seconds timespan(s); + std::this_thread::sleep_for(timespan); } - static long getAbsoluteTime(){ - return time (NULL); - } - static String getDate(){ - long int ttime; - ttime = time (NULL); - String res(ctime (&ttime)); - return res; - } - static void ZipFolder(const String& src, const String& dst){ - String command = "zip -r "+String::DQuotes(dst)+" "+String::DQuotes(src); + static void Copy(const String& src, const String& dst) { + String command = "cp " + String::DQuotes(src) + " " + String::DQuotes(dst); system(command.getCharArray()); } -}; \ No newline at end of file + static time_t getAbsoluteTime() { + return time(NULL); + } + static String getDate() { + auto ttime = time(NULL); + String res(ctime(&ttime)); + return res; + } + static void ZipFolder(const String& src, const String& dst) { + String command = "zip -r " + String::DQuotes(dst) + " " + String::DQuotes(src); + system(command.getCharArray()); + } +};