перенос кода Planner

This commit is contained in:
2023-12-03 19:43:41 +03:00
parent b1e51ce599
commit 91331ae441
14 changed files with 980 additions and 776 deletions

16
.idea/workspace.xml generated
View File

@@ -6,7 +6,21 @@
</artifacts-to-build>
</component>
<component name="ChangeListManager">
<list default="true" id="e42177c3-2328-4b27-8a01-35779b2beb99" name="Default Changelist" comment="" />
<list default="true" id="e42177c3-2328-4b27-8a01-35779b2beb99" name="Default Changelist" comment="">
<change beforePath="$PROJECT_DIR$/src/files/Planner/Array.h" beforeDir="false" afterPath="$PROJECT_DIR$/src/files/Planner/Array.h" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/files/Planner/CompilationSupervisor.h" beforeDir="false" afterPath="$PROJECT_DIR$/src/files/Planner/CompilationSupervisor.h" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/files/Planner/CompilationTask.h" beforeDir="false" afterPath="$PROJECT_DIR$/src/files/Planner/CompilationTask.h" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/files/Planner/File.h" beforeDir="false" afterPath="$PROJECT_DIR$/src/files/Planner/File.h" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/files/Planner/Global.h" beforeDir="false" afterPath="$PROJECT_DIR$/src/files/Planner/Global.h" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/files/Planner/Planner.cpp" beforeDir="false" afterPath="$PROJECT_DIR$/src/files/Planner/Planner.cpp" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/files/Planner/RunSupervisor.h" beforeDir="false" afterPath="$PROJECT_DIR$/src/files/Planner/RunSupervisor.h" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/files/Planner/RunTask.h" beforeDir="false" afterPath="$PROJECT_DIR$/src/files/Planner/RunTask.h" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/files/Planner/String.h" beforeDir="false" afterPath="$PROJECT_DIR$/src/files/Planner/String.h" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/files/Planner/Supervisor.h" beforeDir="false" afterPath="$PROJECT_DIR$/src/files/Planner/Supervisor.h" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/files/Planner/Task.h" beforeDir="false" afterPath="$PROJECT_DIR$/src/files/Planner/Task.h" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/files/Planner/Text.h" beforeDir="false" afterPath="$PROJECT_DIR$/src/files/Planner/Text.h" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/files/Planner/Utils.h" beforeDir="false" afterPath="$PROJECT_DIR$/src/files/Planner/Utils.h" afterDir="false" />
</list>
<option name="SHOW_DIALOG" value="false" />
<option name="HIGHLIGHT_CONFLICTS" value="true" />
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />

View File

@@ -1,42 +1,37 @@
#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#pragma once
#include <vector>
template <class T>
class Array {
protected:
long length;
T** elements;
private:
std::vector<T*> 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<length; ++i)
delete elements[i];
delete [] elements;
}
void add(T* new_line) {
elements.push_back(new_line);
}
void add(T * new_line) {
T ** buf = new T*[length + 1];
for (long i = 0; i < length; ++i) {
buf[i] = elements[i];
}
buf[length] = new_line;
length++;
delete[] elements;
elements = buf;
buf = NULL;
long getLength() const {
return (long)elements.size();
}
long getLength(){
return length;
}
T * get(long i){
T* get(long i) {
return elements[i];
}
T** getElements(){
const std::vector<T*>& getElements() const {
return elements;
}
};

View File

@@ -1,20 +1,22 @@
#pragma once
#include "Supervisor.h"
#include "CompilationTask.h"
#pragma once
class CompilationSupervisor: public Supervisor<CompilationTask> {
class CompilationSupervisor : public Supervisor<CompilationTask> {
public:
CompilationSupervisor(){
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");
}
};

View File

@@ -1,47 +1,51 @@
#include "Task.h"
#pragma once
class CompilationTask: public Task {
#include "Task.h"
#include "Text.h"
class CompilationTask : public Task {
String test_id;
String makefile_text;
public:
void setTestId(String * test_id_in){
void setTestId(String* test_id_in) {
test_id = String(test_id_in->getCharArray());
}
void setMakefileText(String * makefile_text_in){
void setMakefileText(String* makefile_text_in) {
makefile_text = String(makefile_text_in->getCharArray(), '|');
}
virtual void print(){
virtual void print() const {
printf("id=%ld; maxtime=%d; test_id=%s\n", id, maxtime,
test_id.getCharArray());
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));
CompilationTask(Text* lines, int offset) :Task(lines, offset) {
setTestId(lines->get(offset + 2));
setMakefileText(lines->get(offset + 3));
setState(Waiting);
kernels=1;
kernels = 1;
}
virtual void prepareWorkspace(){
String makeFilePath = String(id)+"/Makefile";
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);
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("")+" "+
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;
virtual void analyseResults() {
String binary = workspace + "/0";
state = Utils::Exists(binary) ? Done : DoneWithErrors;
}
};

View File

@@ -1,67 +1,70 @@
#include "Text.h"
#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) {
File(const char* name) {
ptr = fopen(name, "r");
}
File(const String& name, const String& text){
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* readLines() {
Text* lines = new Text();
int c;
String * line = NULL;
String* line = NULL;
bool lineStarted = false;
do {
c = fgetc(ptr);
if (lineStarted){
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;
case '\r':
break;
case '\n':
case EOF:
lines->add(line);
line = NULL;
lineStarted = false;
break;
default:
line->addChar((char)c);
break;
}
}
}while (c!=EOF);
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;
}
};

View File

@@ -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;

View File

@@ -1,18 +1,27 @@
#define _CRT_SECURE_NO_WARNINGS
using namespace std;
#if __cplusplus >= 201703L
#include <filesystem>
#else
#include <unistd.h>
#endif
#include "CompilationSupervisor.h"
#include "RunSupervisor.h"
#include "Global.h"
#include <unistd.h>
#include <signal.h>
//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)
{
//+
@@ -87,11 +98,22 @@ int main(int argc, char ** argv)
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;
}

View File

@@ -1,25 +1,28 @@
#pragma once
#include "CompilationSupervisor.h"
#include "RunTask.h"
#pragma once
class RunSupervisor: public Supervisor<RunTask> {
class RunSupervisor : public Supervisor<RunTask> {
public:
RunSupervisor(CompilationSupervisor * compilationSupervisor){
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);
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;

View File

@@ -1,5 +1,7 @@
#include "CompilationTask.h"
#pragma once
#include "CompilationTask.h"
class RunTask : public Task {
long testcompilationtask_id;
String binary_name;
@@ -9,85 +11,85 @@ class RunTask : public Task {
String args;
CompilationTask* parent;
public:
virtual void print(){
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
id,
maxtime,
testcompilationtask_id,
matrix.getCharArray(),
environments.getCharArray(),
usr_par.getCharArray(),
args.getCharArray(),
kernels
);
}
int setKernels(String * kernels_s){
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 setTestCompilationTaskId(String* id_s) {
return testcompilationtask_id = strtol(id_s->getCharArray(), NULL, 10);
}
long getTestCompilationTaskId(){
long getTestCompilationTaskId() {
return testcompilationtask_id;
}
void setMatrix(String * matrix_in){
matrix= String (matrix_in->getCharArray());
void setMatrix(String* matrix_in) {
matrix = String(matrix_in->getCharArray());
}
void setEnvironments(String * environments_in){
environments= String(environments_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 setUsrPar(String* usr_par_in) {
usr_par = String(usr_par_in->getCharArray(), '|');
}
void setArgs(String * args_in){
args= String(args_in->getCharArray());
void setArgs(String* args_in) {
args = String(args_in->getCharArray());
}
void setParent(CompilationTask * parent_in){
void setParent(CompilationTask* parent_in) {
parent = parent_in;
binary_name = "spf_"+ String(id)+"_"+matrix.Replace(' ','_');
binary_name = "spf_" + String(id) + "_" + matrix.Replace(' ', '_');
}
CompilationTask * getParent(){
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));
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";
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 = 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;
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";
if (!usr_par.isEmpty()) {
String parPath = String(id) + "/usr.par";
File parFile = File(parPath, usr_par);
}
}
virtual String getStartCommand(){
String res = workspace+"/run";
virtual String getStartCommand() {
String res = workspace + "/run";
if (!environments.isEmpty())
res = environments+" "+res;
res = environments + " " + res;
printf("START %ld: %s\n", id, res.getCharArray());
return res;
}

View File

@@ -1,8 +1,10 @@
#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#pragma once
class String {
friend String operator+(const String& a, const String& b);
long length;
@@ -15,26 +17,26 @@ public:
}
String(const char* s) {
length = strlen(s);
length = (long)strlen(s);
body = new char[length + 1];
for (long i = 0; i < length; ++i)
body[i] = s[i];
body[length]='\0';
body[length] = '\0';
}
String(const char* s, char ps) {
length = strlen(s);
length = (long)strlen(s);
body = new char[length + 1];
for (long i = 0; i < length; ++i){
body[i] = (s[i]==ps)? '\n': s[i];
for (long i = 0; i < length; ++i) {
body[i] = (s[i] == ps) ? '\n' : s[i];
}
body[length]='\0';
body[length] = '\0';
}
~String() {
if (body != NULL) {
delete[] body;
}
}
void println() const{
void println() const {
printf("[%s]\n", body);
}
void addChar(char c) {
@@ -51,170 +53,174 @@ public:
body = buf;
buf = NULL;
}
char * getCharArray() const{
char* getCharArray() const {
return body;
}
String (int s){
String(int s) {
length = 0;
body = new char[1];
body[0] = '\0';
if (s>=0){
if (s >= 0) {
int s_ = s;
int size = 1;
while (s_>=10){
s_ = s_/10;
while (s_ >= 10) {
s_ = s_ / 10;
size++;
}
length = size;
body = new char [size+1];
body = new char[size + 1];
sprintf(body, "%d", s);
}
}
String (long 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 s_ = s;
if (s >= 0) {
long long s_ = s;
long size = 1;
while (s_>=10){
s_ = s_/10;
while (s_ >= 10) {
s_ = s_ / 10;
size++;
}
length = size;
body = new char [size+1];
sprintf(body, "%ld", s);
body = new char[size + 1];
sprintf(body, "%lld", s);
}
}
const String& operator=(const String& 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';
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){
static String DQuotes(const String& s) {
String res;
res.length = s.length+2;
res.body=new char[res.length+1];
res.length = s.length + 2;
res.body = new char[res.length + 1];
res.body[0] = '"';
res.body[res.length-1] = '"';
res.body[res.length - 1] = '"';
res.body[res.length] = '\0';
for (long i=0; i< s.length; ++i)
res.body[i+1]=s.body[i];
for (long i = 0; i < s.length; ++i)
res.body[i + 1] = s.body[i];
return res;
}
String Replace(char f, char t){
String Replace(char f, char t) {
String res;
res.length = length;
res.body = new char[length];
res.body[length]='\0';
res.body[length] = '\0';
for (long i = 0; i < length; ++i)
res.body[i]= (body[i]==f)? t: body[i];
res.body[i] = (body[i] == f) ? t : body[i];
return res;
}
String Remove(char f){
String Remove(char f) {
String res;
for (long i=0; i<length; ++i){
if (body[i]!=f)
for (long i = 0; i < length; ++i) {
if (body[i] != f)
res.addChar(body[i]);
}
return res;
}
bool isEmpty() const{
return length==0;
bool isEmpty() const {
return length == 0;
}
bool contains(const String& s) const{
bool contains(const String& s) const {
bool res = false;
bool search_on=false;
bool search_on = false;
if (s.isEmpty()) return true;
if (s.length>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]){
if (s.length > 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 {
}
else {
//обрыв поиска.
search_on =false;
k=0;
start=-1;
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;
}
else {
if (body[i] == s.body[0]) {
k = 1;
start = i;
search_on = true;
//printf("search started %d\n", start);
}
}
}
if (search_on) {
//printf("starts with %ld\n", start);
res=true;
res = true;
}
return res;
}
String toUpper(){
String toUpper() {
String res = String(this->getCharArray());
for (long i=0; i<length; ++i)
res.body[i]= toupper(body[i]);
for (long i = 0; i < length; ++i)
res.body[i] = toupper(body[i]);
res.println();
return res;
}
long getLength(){
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;
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 <stdio.h>
#include <ctype.h>
/* регистр.
#include <stdio.h>
#include <ctype.h>
int main(void) {
FILE * f;
int c;
int main(void) {
FILE * f;
int c;
if ( ! ( f = fopen("file.txt", "r") ) )
return -1;
if ( ! ( f = fopen("file.txt", "r") ) )
return -1;
while ( ( c = fgetc(f) ) != EOF )
putchar( isupper(c) ? tolower(c) : toupper(c) );
return ( fclose(f) );
}
*/
while ( ( c = fgetc(f) ) != EOF )
putchar( isupper(c) ? tolower(c) : toupper(c) );
return ( fclose(f) );
}
*/
};
String operator+(const String& a, const String& b){
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<a.length; ++i)
res.body[i]=a.body[i];
for (long i=0; i<b.length; ++i)
res.body[i+a.length]=b.body[i];
res.body[res.length]='\0';
res.length = a.length + b.length;
res.body = new char[res.length + 1];
for (long i = 0; i < a.length; ++i)
res.body[i] = a.body[i];
for (long i = 0; i < b.length; ++i)
res.body[i + a.length] = b.body[i];
res.body[res.length] = '\0';
return res;
}

View File

@@ -1,130 +1,246 @@
#pragma once
#include <map>
#include <set>
#include <vector>
#include <queue>
#include "File.h"
#include "Task.h"
#include <unistd.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 T>
class Supervisor : public Array <T> {
protected:
SupervisorState state;
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; i<this->length; ++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());
}
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<int, queue<T*>, std::greater<int>> 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<T*> activeTaskSet;
bool ignoreCheck = true;
while (activeTasks) {
long oldActiveTasks = activeTasks;
vector<int> 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());
}
};

View File

@@ -1,8 +1,11 @@
#pragma once
#include <chrono>
#include "File.h"
#include "Utils.h"
#include "Global.h"
#pragma once
enum TaskState {
Inactive, //0
Waiting, //1
@@ -25,14 +28,13 @@ enum TaskState {
FailedToQueue, //18
AbortingByUser //19
};
#pragma once
enum TestType{
enum TestType {
Default, //0
Correctness, //1
Performance, //2
};
#pragma once
class Task {
protected:
long id;
@@ -41,131 +43,149 @@ protected:
int kernels; //получение зависит от типа задачи.
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 "?";
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);
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());
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){
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);
setMaxtime(lines->get(offset + 1));
workspace = packageWorkspace + "/" + String(id);
}
virtual void print()=0;
virtual void print() const = 0;
//-
virtual void prepareWorkspace(){}
virtual String getLaunchScriptText()=0;
virtual String getStartCommand(){
return workspace+"/run";
virtual void prepareWorkspace() {}
virtual String getLaunchScriptText() = 0;
virtual String getStartCommand() {
return workspace + "/run";
}
void createWorkspace(){
void createWorkspace() {
Utils::Mkdir(workspace);
}
void createLaunchScript(){
String launchScriptPath = workspace+"/run";
void createLaunchScript() {
String launchScriptPath = workspace + "/run";
String launchScriptText =
String("cd ")+String::DQuotes(workspace)+"\n"+
String("cd ") + String::DQuotes(workspace) + "\n" +
getLaunchScriptText();
File launchScriptFile = File(launchScriptPath, launchScriptText);
Utils::Chmod(launchScriptPath);
}
virtual void Start(){
if (kernels<=freeKernels){
int getKernels() const { return kernels; }
void Start(bool dontCheck = false) {
if (kernels <= freeKernels || dontCheck) {
setStart();
system(getStartCommand().getCharArray());
state=Running;
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);
//-
}
}
virtual void analyseResults(){
state=Finished;
}
virtual void Check(){
if (Utils::Exists(workspace+"/DONE")){
//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<delta){
state=AbortedByTimeout;
}
}
else if (Utils::Exists(workspace + "/INTERRUPT")) {
state = AbortedByUser;
}
else {
auto end_time = std::chrono::system_clock::now();
std::chrono::duration<double> 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){
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(); //не нужно. только для отладки. анализ будет делаться архивом.
saveState();
}
return (state != Running);
}
virtual void saveState(){
String stateFile = workspace+"/TaskState";
File(stateFile, printState());
virtual void analyseResults() {
state = Finished;
}
virtual void saveState() {
String stateFile = workspace + "/TaskState";
File tmp(stateFile, printState());
}
};

View File

@@ -1,23 +1,27 @@
#pragma once
#include "String.h"
#include "Array.h"
#pragma once
class Text: public Array<String> {
public:
void Print(){
printf("text length=%ld\n", length);
for (long i=0; i<length; ++i){
printf("i=%ld; [%s]\n",i, elements[i]->getCharArray());
// elements[i]->println();
class Text : public Array<String> {
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){
for (long i=0; i<length; ++i){
if (s.contains(*elements[i])){
//printf("match: [%s]\n", elements[i]->getCharArray());
return true;
}
bool hasMatch(const String& s) const {
for (auto& elem : this->getElements()) {
if (s.contains(*elem)) {
//printf("match: [%s]\n", elements[i]->getCharArray());
return true;
}
}
//printf("no matches for [%s]\n", s.getCharArray());
return false;

View File

@@ -1,49 +1,65 @@
#pragma once
#include <sys/stat.h>
#include <sys/types.h>
#include <errno.h>
#include <unistd.h>
#include <time.h>
#include <chrono>
#include <thread>
#if __cplusplus >= 201703L
#include <filesystem>
#endif
#include "String.h"
#pragma once
class Utils {
public:
static int max(int a, int b){
return (a > b)? a:b;
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 min(int a, int b) {
return (a > b) ? b : a;
}
static void Mkdir(const String& path){
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){
static bool Exists(const String& path) {
struct stat buffer;
return (stat (path.getCharArray(), &buffer) == 0);
return (stat(path.getCharArray(), &buffer) == 0);
}
static void Sleep(int s){
usleep(s* 1000000);
//in seconds
static void Sleep(int s) {
std::chrono::seconds timespan(s);
std::this_thread::sleep_for(timespan);
}
static void Copy(const String& src, const String& dst){
String command = "cp "+String::DQuotes(src)+" "+String::DQuotes(dst);
static void Copy(const String& src, const String& dst) {
String command = "cp " + String::DQuotes(src) + " " + String::DQuotes(dst);
system(command.getCharArray());
}
static long getAbsoluteTime(){
return time (NULL);
static time_t getAbsoluteTime() {
return time(NULL);
}
static String getDate(){
long int ttime;
ttime = time (NULL);
String res(ctime (&ttime));
return res;
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);
static void ZipFolder(const String& src, const String& dst) {
String command = "zip -r " + String::DQuotes(dst) + " " + String::DQuotes(src);
system(command.getCharArray());
}
};