package TestingSystem.DVM; import Common.Constants; import Common.Current; import Common.Global; import Common.Utils.Utils; import GlobalData.Machine.Machine; import GlobalData.Machine.MachineType; import GlobalData.RemoteFile.RemoteFile; import GlobalData.Tasks.TaskState; import GlobalData.User.User; import ProjectData.Files.ProjectFile; import ProjectData.LanguageName; import Repository.Server.ServerCode; import TestingSystem.Common.TasksPackageState; import TestingSystem.Common.TestingPlanner; import TestingSystem.DVM.DVMPackage.DVMPackage; import TestingSystem.DVM.DVMTasks.DVMCompilationTask; import TestingSystem.DVM.DVMTasks.DVMRunTask; import TestingSystem.DVM.DVMTasks.DVMTask; import Visual_DVM_2021.Passes.All.UnzipFolderPass; import Visual_DVM_2021.UI.Interface.Loggable; import javafx.util.Pair; import org.apache.commons.io.FileUtils; import java.io.File; import java.io.FileFilter; import java.net.InetAddress; import java.nio.charset.Charset; import java.nio.file.Paths; import java.util.*; public class MachineQueueSupervisor extends TestingPlanner { Machine machine = null; User user = null; boolean local; RemoteFile packageRemoteWorkspace = null; File packageLocalWorkspace = null; //---- public MachineQueueSupervisor(String... args) { Global.isWindows = System.getProperty("os.name").startsWith("Windows"); //--- String machineAddress = args[0]; int machinePort = Integer.parseInt(args[1]); String userName = args[2]; String userPassword = args[3]; String userWorkspace = args[4]; String testingSystemRoot = args[5]; String supervisorHome = Global.Home; //при инициализации это текущая папка. //--- Global.Log = new Loggable() { @Override public String getLogHomePath() { return supervisorHome; } @Override public String getLogName() { return Current.mode.toString(); } }; Global.Log.ClearLog(); //-- Global.Home = testingSystemRoot; Global.CheckTestingSystemDirectories(); System.out.println(Global.TestsDirectory.getAbsolutePath()); //--- machine = new Machine(machineAddress, machineAddress, machinePort, MachineType.Server); user = new User(userName, userPassword, userWorkspace); CheckLocal(); //--- Print("machineAddress=" + Utils.Brackets(machineAddress)); Print("machinePort=" + Utils.Brackets(String.valueOf(machinePort))); Print("userName=" + Utils.Brackets(userName)); Print("userPassword=" + Utils.Brackets(userPassword)); Print("userWorkspace=" + Utils.Brackets(userWorkspace)); Print("root=" + Utils.Brackets(Global.Home)); Print("local=" + local); Print("====="); //---- } void CheckLocal() { local = false; try { InetAddress address = InetAddress.getByName(machine.address); InetAddress localAddress = InetAddress.getByName("alex-freenas.ddns.net"); Print("machine ip=" + Utils.Brackets(address.getHostAddress())); Print("server ip=" + Utils.Brackets(localAddress.getHostAddress())); local = localAddress.getHostAddress().equals(address.getHostAddress()); //todo в этом случае отдельный режим без ssh } catch (Exception ex) { Global.Log.PrintException(ex); } } public String getPlanner() { return String.join("/", user.workspace, "modules", "planner"); } @Override protected boolean Connect() { if (user.connection == null) { try { user.connection = new UserConnection(machine, user); Print("Соединение c " + machine.getURL() + " " + user.login + " успешно установлено."); } catch (Exception ex) { Print(ex.toString()); user.connection = null; Print("Не удалось установить соединение."); } } return user.connection != null; } @Override protected void Disconnect() { if (user.connection != null) { user.connection.Disconnect(); user.connection = null; Print("Соединение c " + machine.getURL() + " " + user.login + " сброшено."); } } //-- //Получить ид тестов и их папки на сервере. LinkedHashMap getTestsFromJson() { LinkedHashMap res = new LinkedHashMap<>(); for (DVMCompilationTask task : testingPackage.package_json.compilationTasks) { if (!res.containsKey(task.test_id)) { res.put(task.test_id, Paths.get(Global.TestsDirectory.getAbsolutePath(), String.valueOf(task.test_id)).toFile()); } } return res; } static LinkedHashMap> getTestPrograms(File test) { LinkedHashMap> res = new LinkedHashMap<>(); //-- res.put(LanguageName.fortran, new Vector<>()); res.put(LanguageName.c, new Vector<>()); res.put(LanguageName.cpp, new Vector<>()); //-- File[] files = test.listFiles(new FileFilter() { @Override public boolean accept(File pathname) { return pathname.isFile(); } }); if (files != null) { for (File file : files) { ProjectFile projectFile = new ProjectFile(new File(file.getName())); if (projectFile.isNotExcludedProgram()) res.get(projectFile.languageName).add(projectFile); } } return res; } static void generateForLanguage(String dvm_drv, LanguageName language, Vector language_programs, Vector titles, Vector objects, Vector bodies, String flags) { if (!language_programs.isEmpty()) { String LANG_ = language.toString().toUpperCase() + "_"; Vector module_objects = new Vector<>(); String module_body = ""; int i = 1; for (ProjectFile program : language_programs) { //-- String object = Utils.DQuotes(language + "_" + i + ".o"); module_objects.add(object); module_body += object + ":\n" + "\t" + String.join(" ", Utils.MFVar(LANG_ + "COMMAND"), Utils.MFVar(LANG_ + "FLAGS"), program.getStyleOptions(), "-c", program.getQSourceName(), "-o", object + "\n\n"); ++i; } titles.add(String.join("\n", LANG_ + "COMMAND=" + Utils.DQuotes(dvm_drv) + " " + language.getDVMCompile(), LANG_ + "FLAGS=" + flags, LANG_ + "OBJECTS=" + String.join(" ", module_objects), "")); objects.add(Utils.MFVar(LANG_ + "OBJECTS")); bodies.add(module_body); } } static String generateMakefile(File test, LanguageName test_language, String dvm_drv, String flags) { //----->> LinkedHashMap> programs = getTestPrograms(test); Vector titles = new Vector<>(); Vector objects = new Vector<>(); Vector bodies = new Vector<>(); String binary = Utils.DQuotes("0"); //----->> for (LanguageName languageName : programs.keySet()) { generateForLanguage(dvm_drv, languageName, programs.get(languageName), titles, objects, bodies, flags); } //----->> return String.join("\n", "LINK_COMMAND=" + Utils.DQuotes(dvm_drv) + " " + test_language.getDVMLink(), "LINK_FLAGS=" + flags + "\n", String.join("\n", titles), "all: " + binary, binary + " : " + String.join(" ", objects), "\t" + Utils.MFVar("LINK_COMMAND") + " " + Utils.MFVar("LINK_FLAGS") + " " + String.join(" ", objects) + " -o " + binary, String.join(" ", bodies)); } public void getTasksInfo(List tasks, String file_name) throws Exception { LinkedHashMap sorted_tasks = new LinkedHashMap<>(); for (DVMTask task : tasks) sorted_tasks.put(task.id, task); //-- File info_file = Paths.get(packageLocalWorkspace.getAbsolutePath(), "results", file_name).toFile(); List lines = FileUtils.readLines(info_file, Charset.defaultCharset()); for (String packed : lines) { if (!packed.isEmpty()) { String[] data = packed.split(" "); int id = Integer.parseInt(data[0]); TaskState state = TaskState.valueOf(data[1]); double time = Double.parseDouble(data[2]); //-- DVMTask task = sorted_tasks.get(id); task.state = state; task.Time = state.equals(TaskState.AbortedByTimeout) ? (task.maxtime + 1) : time; } } } protected boolean CheckModules() throws Exception { RemoteFile modulesDirectory = new RemoteFile(user.workspace, "modules"); RemoteFile version = new RemoteFile(modulesDirectory, "version.h"); int current_version = Constants.Nan; int actual_version = Constants.planner_version; if (user.connection.Exists(version)) { try { current_version = Integer.parseInt(user.connection.readFromFile(version)); } catch (Exception ex) { ex.printStackTrace(); } } if (current_version < actual_version) { Print("Закачка кода модулей..."); for (String resource_name : Constants.resourses_names) { Print(resource_name); user.connection.putResource(modulesDirectory, resource_name); } //-- Print("Сборка модулей..."); String modules_log = user.connection.compileModules(modulesDirectory); if (!modules_log.isEmpty()) { testingPackage.description = modules_log; testingPackage.state = TasksPackageState.Aborted; return false; } } return true; } //---- @Override protected ServerCode getActivePackagesCode() { return ServerCode.GetFirstActiveDVMPackageForMachineURL; } @Override protected ServerCode getCheckIfNeedsKillCode() { return ServerCode.DVMPackageNeedsKill; } @Override protected TasksPackageState getStateAfterStart() { return TasksPackageState.CompilationWorkspacesCreation; } @Override protected void TestsSynchronize() throws Exception { testingPackage.readJson(); LinkedHashMap tests = getTestsFromJson(); //синхронизировать их. for (int test_id : tests.keySet()) { // Print("testId="+test_id); File test = tests.get(test_id); RemoteFile test_dst = new RemoteFile(testingPackage.user_workspace + "/projects/" + test_id, true); // Print("src="+test.getAbsolutePath()); // Print("dst="+test_dst.full_name); user.connection.MKDIR(test_dst); user.connection.SynchronizeSubDirsR(test, test_dst); // Print("done"); } } @Override protected void PackageWorkspaceCreation() throws Exception { if (!CheckModules()) { return; } //-- testingPackage.readJson(); //-- LinkedHashMap tests = getTestsFromJson(); //создать папку для пакета. user.connection.sftpChannel.mkdir(packageRemoteWorkspace.full_name); //положить туда запакованные тексты задач. Vector compilationLines = new Vector<>(); Vector runLines = new Vector<>(); for (DVMCompilationTask compilationTask : testingPackage.package_json.compilationTasks) { String makefileText = generateMakefile(tests.get(compilationTask.test_id), compilationTask.language, testingPackage.drv, compilationTask.flags); compilationLines.addAll(compilationTask.pack(makefileText)); for (DVMRunTask runTask : compilationTask.runTasks) runLines.addAll(runTask.pack(null)); } RemoteFile compilationPackage = new RemoteFile(packageRemoteWorkspace, "compilationTasks"); RemoteFile runPackage = new RemoteFile(packageRemoteWorkspace, "runTasks"); user.connection.writeToFile(String.join("\n", compilationLines) + "\n", compilationPackage); user.connection.writeToFile(String.join("\n", runLines) + "\n", runPackage); // -- user.connection.MKDIR(new RemoteFile(packageRemoteWorkspace, "state")); } @Override protected void AnalyseResults() throws Exception { testingPackage.readJson(); Print("analysing results"); Vector runTasks = new Vector<>(); for (DVMCompilationTask compilationTask : testingPackage.package_json.compilationTasks) runTasks.addAll(compilationTask.runTasks); //---- getTasksInfo(testingPackage.package_json.compilationTasks, "CompilationInfo.txt"); getTasksInfo(runTasks, "RunningInfo.txt"); //-- int ct_count = 0; int rt_count = 0; //-- for (DVMCompilationTask compilationTask : testingPackage.package_json.compilationTasks) { compilationTask.dvm_package_id = testingPackage.id; ct_count++; File ct_workspace = Paths.get(packageLocalWorkspace.getAbsolutePath(), "results", String.valueOf(compilationTask.id)).toFile(); if (ct_workspace.exists()) { for (DVMRunTask runTask : compilationTask.runTasks) { runTask.dvm_package_id = testingPackage.id; rt_count++; runTask.compilation_state = compilationTask.state; runTask.compilation_time = compilationTask.Time; if (compilationTask.state == TaskState.DoneWithErrors) { runTask.state = TaskState.Canceled; } else { File rt_workspace = Paths.get(packageLocalWorkspace.getAbsolutePath(), "results", String.valueOf(runTask.id)).toFile(); if (rt_workspace.exists() && runTask.state.equals(TaskState.Finished)) { //анализ задачи на запуск. File outFile = new File(rt_workspace, Constants.out_file); File errFile = new File(rt_workspace.getAbsolutePath(), Constants.err_file); //-- String output = FileUtils.readFileToString(outFile); String errors = FileUtils.readFileToString(errFile); //-- List output_lines = Arrays.asList(output.split("\n")); List errors_lines = Arrays.asList(errors.split("\n")); //--- if (Utils.isCrushed(output_lines, errors_lines)) { runTask.state = TaskState.Crushed; } else { Pair results = new Pair<>(TaskState.Done, 100); switch (runTask.test_type) { case Correctness: results = Utils.analyzeCorrectness(output_lines); break; case Performance: results = Utils.analyzePerformance(output_lines); break; default: break; } runTask.state = results.getKey(); runTask.progress = results.getValue(); runTask.CleanTime = Utils.parseCleanTime(output); } } } } } } testingPackage.progress = 100; testingPackage.saveJson(); //запись обновленных результатов пакета в json! Print("analysis done, ct_count=" + ct_count + " rt count=" + rt_count); } @Override protected void PackageStart() throws Exception { String plannerStartCommand = String.join(" ", Utils.DQuotes(getPlanner()), Utils.DQuotes(user.workspace), Utils.DQuotes(packageRemoteWorkspace.full_name), Utils.DQuotes(testingPackage.kernels), Utils.DQuotes(testingPackage.drv)); testingPackage.PID = user.connection.startShellProcess(packageRemoteWorkspace, "PID", "ulimit -s unlimited", plannerStartCommand); System.out.println("PID=" + Utils.Brackets(testingPackage.PID)); RemoteFile STARTED = new RemoteFile(packageRemoteWorkspace, "STARTED"); while (!user.connection.Exists(STARTED)) { Print("waiting for package start..."); Utils.sleep(1000); } } @Override protected boolean CheckNextState() throws Exception { boolean progress_changed = false; boolean state_changed = false; RemoteFile progress = new RemoteFile(packageRemoteWorkspace, "progress"); if (user.connection.Exists(progress)) { String s = user.connection.readFromFile(progress); int current_progress = Integer.parseInt(s); if (current_progress != testingPackage.progress) { Print("progress changed: " + current_progress); testingPackage.progress = current_progress; progress_changed = true; } } RemoteFile stateDir = new RemoteFile(packageRemoteWorkspace, "state"); //состояния пакета могут меняться только по возрастанию. ищем, появилось ли такое. Vector higherStates = testingPackage.state.getHigherStates(); Collections.reverse(higherStates); //берем в обратном порядке, чтобы быстрее найти высшее. for (TasksPackageState state : higherStates) { RemoteFile file = new RemoteFile(stateDir, state.toString()); if (user.connection.Exists(file)) { Print("found new state: " + file.name); testingPackage.state = state; state_changed = true; break; } } //-- user.connection.iterations++; if (user.connection.iterations == 100) { Disconnect(); } //-- return progress_changed || state_changed; } @Override protected void DownloadResults() throws Exception { Utils.CheckDirectory(packageLocalWorkspace); RemoteFile remote_results_archive = new RemoteFile(packageRemoteWorkspace, "results.zip"); File results_archive = new File(packageLocalWorkspace, "results.zip"); user.connection.performScript(packageRemoteWorkspace, "zip -r " + Utils.DQuotes("results.zip") + " " + Utils.DQuotes("results")); //--- if (user.connection.Exists(remote_results_archive)) { user.connection.getSingleFile(remote_results_archive.full_name, results_archive.getAbsolutePath()); UnzipFolderPass unzipFolderPass = new UnzipFolderPass(); unzipFolderPass.Do(results_archive.getAbsolutePath(), packageLocalWorkspace.getAbsolutePath(), false); } //--- if (Global.properties.eraseTestingWorkspaces && user.connection.Exists(packageRemoteWorkspace)) user.connection.RMDIR(packageRemoteWorkspace.full_name); } @Override protected void Kill() throws Exception { if (!testingPackage.PID.isEmpty()) { user.connection.Command("kill -9 " + testingPackage.PID); } } @Override public void Perform() { try { testingPackage = null; Vector activePackages = (Vector) ServerCommand(getActivePackagesCode(), machine.getURL(), null); // System.out.println(this.getClass().getSimpleName()+": found "+activePackages.size()+" active packages"); for (DVMPackage activePackage : activePackages) PerformPackage(activePackage); } catch (Exception ex) { ex.printStackTrace(); } finally { Utils.sleep(getSleepMillis()); } } @Override protected void InitSessionCredentials() { packageRemoteWorkspace = new RemoteFile(user.workspace + "/tests", String.valueOf(testingPackage.id), true); packageLocalWorkspace = new File(Global.DVMPackagesDirectory, String.valueOf(testingPackage.id)); } /* //-- DVMPackage testingPackage = null; //текущий пакет. RemoteFile packageRemoteWorkspace = null; File packageLocalWorkspace = null; //-- protected int getSleepMillis() { return 5000; } //-- protected boolean isPrintOn() { return true; } protected void Print(String message) { try { if (isPrintOn()) { System.out.println(message); Global.Log.Print(message); } } catch (Exception ex) { ex.printStackTrace(); } } //-- protected Object ServerCommand(ServerCode code_in, String arg, Serializable object_in) throws Exception { TestingSystemPass pass = new TestingSystemPass() { @Override public String getDescription() { return ""; } @Override protected void ServerAction() throws Exception { Command(new ServerExchangeUnit_2021(code_in, arg, object_in)); target = response.object; } }; if (!pass.Do()) throw new PassException("Ошибка взаимодействия с сервером " + code_in); return pass.target; } protected Object ServerCommand(ServerCode code_in, Serializable object_in) throws Exception { return ServerCommand(code_in, "", object_in); } protected Object ServerCommand(ServerCode code_in) throws Exception { return ServerCommand(code_in, "", null); } //-- void UpdatePackageState(TasksPackageState state_in) throws Exception { testingPackage.state = state_in; testingPackage.ChangeDate = new Date().getTime(); ServerCommand(ServerCode.EditObject, testingPackage); switch (testingPackage.state) { case Done: case Aborted: case CompilationExecution: case RunningExecution: EmailPackage(); break; } } void UpdatePackage() throws Exception { testingPackage.ChangeDate = new Date().getTime(); ServerCommand(ServerCode.EditObject, testingPackage); } void EmailPackage() throws Exception { if (testingPackage.needsEmail == 1) { EmailMessage message = new EmailMessage(); message.subject = "Состояние пакета задач " + Utils.Brackets(testingPackage) + " изменилось на " + Utils.Brackets(testingPackage.state.getDescription()); message.text = testingPackage.description; message.targets.add(testingPackage.sender_address); ServerCommand(ServerCode.Email, message); } } //-- boolean Connect() { if (user.connection == null) { try { user.connection = new UserConnection(machine, user); Print("Соединение c " + machine.getURL() + " " + user.login + " успешно установлено."); } catch (Exception ex) { Print(ex.toString()); user.connection = null; Print("Не удалось установить соединение."); } } return user.connection != null; } void Disconnect() { if (user.connection != null) { user.connection.Disconnect(); user.connection = null; } } boolean CheckModules() throws Exception { RemoteFile modulesDirectory = new RemoteFile(user.workspace, "modules"); RemoteFile version = new RemoteFile(modulesDirectory, "version.h"); int current_version = Constants.Nan; int actual_version = Constants.planner_version; if (user.connection.Exists(version)) { try { current_version = Integer.parseInt(user.connection.readFromFile(version)); } catch (Exception ex) { ex.printStackTrace(); } } if (current_version < actual_version) { Print("Закачка кода модулей..."); for (String resource_name : Constants.resourses_names) { Print(resource_name); user.connection.putResource(modulesDirectory, resource_name); } //-- Print("Сборка модулей..."); String modules_log = user.connection.compileModules(modulesDirectory); if (!modules_log.isEmpty()) { testingPackage.description = modules_log; testingPackage.state = TasksPackageState.Aborted; return false; } } return true; } String getPlanner() { return String.join("/", user.workspace, "modules", "planner"); } //-- //проверка, не является ли заданная машина сервером тестирования. в этом случае, при соединении не использовать ssh. void CheckLocal() { local = false; try { InetAddress address = InetAddress.getByName(machine.address); InetAddress localAddress = InetAddress.getByName("alex-freenas.ddns.net"); Print("machine ip=" + Utils.Brackets(address.getHostAddress())); Print("server ip=" + Utils.Brackets(localAddress.getHostAddress())); local = localAddress.getHostAddress().equals(address.getHostAddress()); //todo в этом случае отдельный режим без ssh } catch (Exception ex) { Global.Log.PrintException(ex); } } //-- public void Start() { while (true) { try { testingPackage = null; testingPackage = (DVMPackage) ServerCommand(ServerCode.GetFirstActiveDVMPackageForMachineURL, machine.getURL(), null); if (testingPackage != null) { //--- Print(testingPackage.id + ":" + testingPackage.state.getDescription()); packageRemoteWorkspace = new RemoteFile(user.workspace + "/tests", String.valueOf(testingPackage.id), true); packageLocalWorkspace = new File(Global.DVMPackagesDirectory, String.valueOf(testingPackage.id)); PerformPackage(); testingPackage.destructor(); testingPackage = null; System.gc(); } else Print("Не найдено активных пакетов для машины " + machine.getURL()); } catch (Exception ex) { ex.printStackTrace(); } finally { Print("sleep"); Utils.sleep(getSleepMillis()); } } } //------------------------------------------------------------------------------- void TestsSynchronize() throws Exception { testingPackage.readJson(); LinkedHashMap tests = getTestsFromJson(); //синхронизировать их. for (int test_id : tests.keySet()) { File test = tests.get(test_id); RemoteFile test_dst = new RemoteFile(testingPackage.user_workspace + "/projects/" + test_id, true); user.connection.MKDIR(test_dst); user.connection.SynchronizeSubDirsR(test, test_dst); } } void PackageWorkspaceCreation() throws Exception { if (!CheckModules()) { return; } //-- testingPackage.readJson(); //-- LinkedHashMap tests = getTestsFromJson(); //создать папку для пакета. user.connection.sftpChannel.mkdir(packageRemoteWorkspace.full_name); //положить туда запакованные тексты задач. Vector compilationLines = new Vector<>(); Vector runLines = new Vector<>(); for (DVMCompilationTask compilationTask : testingPackage.package_json.compilationTasks) { String makefileText = generateMakefile(tests.get(compilationTask.test_id), compilationTask.language, testingPackage.drv, compilationTask.flags); compilationLines.addAll(compilationTask.pack(makefileText)); for (DVMRunTask runTask : compilationTask.runTasks) runLines.addAll(runTask.pack(null)); } RemoteFile compilationPackage = new RemoteFile(packageRemoteWorkspace, "compilationTasks"); RemoteFile runPackage = new RemoteFile(packageRemoteWorkspace, "runTasks"); user.connection.writeToFile(String.join("\n", compilationLines) + "\n", compilationPackage); user.connection.writeToFile(String.join("\n", runLines) + "\n", runPackage); // -- user.connection.MKDIR(new RemoteFile(packageRemoteWorkspace, "state")); } void PackageStart() throws Exception { String plannerStartCommand = String.join(" ", Utils.DQuotes(getPlanner()), Utils.DQuotes(user.workspace), Utils.DQuotes(packageRemoteWorkspace.full_name), Utils.DQuotes(testingPackage.kernels), Utils.DQuotes(testingPackage.drv)); testingPackage.PID = user.connection.startShellProcess(packageRemoteWorkspace,"PID", "ulimit -s unlimited", plannerStartCommand); System.out.println("PID="+Utils.Brackets(testingPackage.PID)); RemoteFile STARTED = new RemoteFile(packageRemoteWorkspace, "STARTED"); while (!user.connection.Exists(STARTED)) { Print("waiting for package start..."); Utils.sleep(1000); } } boolean CheckNextState() throws Exception { boolean progress_changed = false; boolean state_changed = false; RemoteFile progress = new RemoteFile(packageRemoteWorkspace, "progress"); if (user.connection.Exists(progress)) { String s = user.connection.readFromFile(progress); int current_progress = Integer.parseInt(s); if (current_progress != testingPackage.progress) { Print("progress changed: " + current_progress); testingPackage.progress = current_progress; progress_changed = true; } } RemoteFile stateDir = new RemoteFile(packageRemoteWorkspace, "state"); //состояния пакета могут меняться только по возрастанию. ищем, появилось ли такое. Vector higherStates = testingPackage.state.getHigherStates(); Collections.reverse(higherStates); //берем в обратном порядке, чтобы быстрее найти высшее. for (TasksPackageState state : higherStates) { RemoteFile file = new RemoteFile(stateDir, state.toString()); if (user.connection.Exists(file)) { Print("found new state: " + file.name); testingPackage.state = state; state_changed = true; break; } } //-- user.connection.iterations++; if (user.connection.iterations == 100) { Disconnect(); } //-- return progress_changed || state_changed; } void DownloadResults() throws Exception { Utils.CheckDirectory(packageLocalWorkspace); RemoteFile remote_results_archive = new RemoteFile(packageRemoteWorkspace, "results.zip"); File results_archive = new File(packageLocalWorkspace, "results.zip"); user.connection.performScript(packageRemoteWorkspace, "zip -r " + Utils.DQuotes("results.zip") + " " + Utils.DQuotes("results")); //--- if (user.connection.Exists(remote_results_archive)) { user.connection.getSingleFile(remote_results_archive.full_name, results_archive.getAbsolutePath()); UnzipFolderPass unzipFolderPass = new UnzipFolderPass(); unzipFolderPass.Do(results_archive.getAbsolutePath(), packageLocalWorkspace.getAbsolutePath(), false); } //--- // if (Global.properties.eraseTestingWorkspaces && user.connection.Exists(packageRemoteWorkspace)) // user.connection.RMDIR(packageRemoteWorkspace.full_name); } ///------------------------------------------ //жизненный цикл планировщика void Session() throws Exception { switch (testingPackage.state) { case TestsSynchronize: TestsSynchronize(); UpdatePackageState(TasksPackageState.PackageWorkspaceCreation); break; case PackageWorkspaceCreation: PackageWorkspaceCreation(); UpdatePackageState(TasksPackageState.PackageStart); break; case PackageStart: PackageStart(); testingPackage.StartDate = new Date().getTime(); UpdatePackageState(TasksPackageState.CompilationWorkspacesCreation); break; case RunningEnd: DownloadResults(); UpdatePackageState(TasksPackageState.Analysis); break; default: if (CheckNextState()) UpdatePackage(); break; } } //-- void getTasksInfo(List tasks, String file_name) throws Exception { LinkedHashMap sorted_tasks = new LinkedHashMap<>(); for (DVMTask task : tasks) sorted_tasks.put(task.id, task); //-- File info_file = Paths.get(packageLocalWorkspace.getAbsolutePath(), "results", file_name).toFile(); List lines = FileUtils.readLines(info_file, Charset.defaultCharset()); for (String packed : lines) { if (!packed.isEmpty()) { String[] data = packed.split(" "); int id = Integer.parseInt(data[0]); TaskState state = TaskState.valueOf(data[1]); double time = Double.parseDouble(data[2]); //-- DVMTask task = sorted_tasks.get(id); task.state = state; task.Time = state.equals(TaskState.AbortedByTimeout) ? (task.maxtime + 1) : time; } } } LinkedHashMap getTestsFromJson() { LinkedHashMap res = new LinkedHashMap<>(); for (DVMCompilationTask task : testingPackage.package_json.compilationTasks) { if (!res.containsKey(task.test_id)) { res.put(task.test_id, Paths.get(Global.TestsDirectory.getAbsolutePath(), String.valueOf(task.test_id)).toFile()); } } return res; } static LinkedHashMap> getTestPrograms(File test) { LinkedHashMap> res = new LinkedHashMap<>(); //-- res.put(LanguageName.fortran, new Vector<>()); res.put(LanguageName.c, new Vector<>()); res.put(LanguageName.cpp, new Vector<>()); //-- File[] files = test.listFiles(new FileFilter() { @Override public boolean accept(File pathname) { return pathname.isFile(); } }); if (files != null) { for (File file : files) { ProjectFile projectFile = new ProjectFile(new File(file.getName())); if (projectFile.isNotExcludedProgram()) res.get(projectFile.languageName).add(projectFile); } } return res; } static void generateForLanguage(String dvm_drv, LanguageName language, Vector language_programs, Vector titles, Vector objects, Vector bodies, String flags) { if (!language_programs.isEmpty()) { String LANG_ = language.toString().toUpperCase() + "_"; Vector module_objects = new Vector<>(); String module_body = ""; int i = 1; for (ProjectFile program : language_programs) { //-- String object = Utils.DQuotes(language + "_" + i + ".o"); module_objects.add(object); module_body += object + ":\n" + "\t" + String.join(" ", Utils.MFVar(LANG_ + "COMMAND"), Utils.MFVar(LANG_ + "FLAGS"), program.getStyleOptions(), "-c", program.getQSourceName(), "-o", object + "\n\n"); ++i; } titles.add(String.join("\n", LANG_ + "COMMAND=" + Utils.DQuotes(dvm_drv) + " " + language.getDVMCompile(), LANG_ + "FLAGS=" + flags, LANG_ + "OBJECTS=" + String.join(" ", module_objects), "")); objects.add(Utils.MFVar(LANG_ + "OBJECTS")); bodies.add(module_body); } } static String generateMakefile(File test, LanguageName test_language, String dvm_drv, String flags) { //----->> LinkedHashMap> programs = getTestPrograms(test); Vector titles = new Vector<>(); Vector objects = new Vector<>(); Vector bodies = new Vector<>(); String binary = Utils.DQuotes("0"); //----->> for (LanguageName languageName : programs.keySet()) { generateForLanguage(dvm_drv, languageName, programs.get(languageName), titles, objects, bodies, flags); } //----->> return String.join("\n", "LINK_COMMAND=" + Utils.DQuotes(dvm_drv) + " " + test_language.getDVMLink(), "LINK_FLAGS=" + flags + "\n", String.join("\n", titles), "all: " + binary, binary + " : " + String.join(" ", objects), "\t" + Utils.MFVar("LINK_COMMAND") + " " + Utils.MFVar("LINK_FLAGS") + " " + String.join(" ", objects) + " -o " + binary, String.join(" ", bodies)); } //--- void Kill() throws Exception { if (!testingPackage.PID.isEmpty()) user.connection.Command("kill -9 " + testingPackage.PID); } void AnalyseResults() throws Exception { testingPackage.readJson(); Print("analysing results"); Vector runTasks = new Vector<>(); for (DVMCompilationTask compilationTask : testingPackage.package_json.compilationTasks) runTasks.addAll(compilationTask.runTasks); //---- getTasksInfo(testingPackage.package_json.compilationTasks, "CompilationInfo.txt"); getTasksInfo(runTasks, "RunningInfo.txt"); //-- int ct_count = 0; int rt_count = 0; //-- for (DVMCompilationTask compilationTask : testingPackage.package_json.compilationTasks) { compilationTask.dvm_package_id = testingPackage.id; ct_count++; File ct_workspace = Paths.get(packageLocalWorkspace.getAbsolutePath(), "results", String.valueOf(compilationTask.id)).toFile(); if (ct_workspace.exists()) { for (DVMRunTask runTask : compilationTask.runTasks) { runTask.dvm_package_id = testingPackage.id; rt_count++; runTask.compilation_state = compilationTask.state; runTask.compilation_time = compilationTask.Time; if (compilationTask.state == TaskState.DoneWithErrors) { runTask.state = TaskState.Canceled; } else { File rt_workspace = Paths.get(packageLocalWorkspace.getAbsolutePath(), "results", String.valueOf(runTask.id)).toFile(); if (rt_workspace.exists() && runTask.state.equals(TaskState.Finished)) { //анализ задачи на запуск. File outFile = new File(rt_workspace, Constants.out_file); File errFile = new File(rt_workspace.getAbsolutePath(), Constants.err_file); //-- String output = FileUtils.readFileToString(outFile); String errors = FileUtils.readFileToString(errFile); //-- List output_lines = Arrays.asList(output.split("\n")); List errors_lines = Arrays.asList(errors.split("\n")); //--- if (Utils.isCrushed(output_lines, errors_lines)) { runTask.state = TaskState.Crushed; } else { Pair results = new Pair<>(TaskState.Done, 100); switch (runTask.test_type) { case Correctness: results = Utils.analyzeCorrectness(output_lines); break; case Performance: results = Utils.analyzePerformance(output_lines); break; default: break; } runTask.state = results.getKey(); runTask.progress = results.getValue(); runTask.CleanTime = Utils.parseCleanTime(output); } } } } } } testingPackage.progress = 100; testingPackage.saveJson(); //запись обновленных результатов пакета в json! Print("analysis done, ct_count=" + ct_count + " rt count=" + rt_count); } //-- void PerformPackage() throws Exception { //-- if (testingPackage.connectionErrosCount>=10){ Print(testingPackage.id+" had 10 connection errors. stop"); UpdatePackageState(TasksPackageState.ConnectionError); //todo тут надо будет завершать нить ибо испорчена и давать увед серверу? }else { //-- if (testingPackage.state.equals(TasksPackageState.Analysis)) { AnalyseResults(); UpdatePackageState(TasksPackageState.Done); } else { try { if (Connect()) { int ptk_id = (int) ServerCommand(ServerCode.DVMPackageNeedsKill, testingPackage.id); if (ptk_id != Constants.Nan) { Print("package " + testingPackage.id + " NEEDS TO KILL"); Kill(); UpdatePackageState(TasksPackageState.Aborted); ServerCommand(ServerCode.DeleteObjectByPK, new Pair(TestingPackageToKill.class, ptk_id)); } else { Session(); } } else { testingPackage.connectionErrosCount++; UpdatePackage(); } } catch (Exception ex) { Print("Ошибка сеанса. Соединение будет разорвано."); Print(ex.getMessage()); // testingPackage.connectionErrosCount++; UpdatePackage(); } finally { Disconnect(); } } } } */ }