278 lines
13 KiB
Java
278 lines
13 KiB
Java
package _VisualDVM.TestingSystem.DVM;
|
||
import Common.Utils.Utils_;
|
||
import _VisualDVM.Constants;
|
||
import _VisualDVM.Global;
|
||
import _VisualDVM.Utils;
|
||
import _VisualDVM.GlobalData.RemoteFile.RemoteFile;
|
||
import _VisualDVM.GlobalData.Tasks.TaskState;
|
||
import _VisualDVM.TestingSystem.Common.TasksPackageState;
|
||
import _VisualDVM.TestingSystem.DVM.DVMTasks.DVMCompilationTask;
|
||
import _VisualDVM.TestingSystem.DVM.DVMTasks.DVMRunTask;
|
||
import _VisualDVM.Passes.All.UnzipFolderPass;
|
||
import javafx.util.Pair;
|
||
import org.apache.commons.io.FileUtils;
|
||
|
||
import java.io.File;
|
||
import java.nio.file.Paths;
|
||
import java.util.*;
|
||
public class RemoteDVMTestingPlanner extends DVMTestingPlanner {
|
||
RemoteFile packageRemoteWorkspace = null;
|
||
public RemoteDVMTestingPlanner(String... args) {
|
||
super(args);
|
||
}
|
||
@Override
|
||
protected boolean Connect() {
|
||
if (user.connection == null) {
|
||
try {
|
||
user.connection = new UserConnection(machine, user);
|
||
Print("Соединение c " + machine.getURL() + " " + user.login + " успешно установлено.");
|
||
Print("Проверка инициализации..");
|
||
user.connection.CheckUserInitialization(testingPackage.sender_address);
|
||
} 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 + " сброшено.");
|
||
}
|
||
}
|
||
//----
|
||
@Override
|
||
protected void TestsSynchronize() throws Exception {
|
||
System.out.println("--");
|
||
testingPackage.readJson();
|
||
System.out.println("+");
|
||
LinkedHashMap<Integer, File> tests = getTestsFromJson();
|
||
//синхронизировать их.
|
||
for (int test_id : tests.keySet()) {
|
||
System.out.println("test=" + test_id);
|
||
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);
|
||
}
|
||
System.out.println("++");
|
||
}
|
||
@Override
|
||
protected void PackageWorkspaceCreation() throws Exception {
|
||
System.out.println("package workspace creation");
|
||
if (!CheckModules()) {
|
||
return;
|
||
}
|
||
System.out.println("modules checked");
|
||
//--
|
||
testingPackage.readJson();
|
||
//--
|
||
LinkedHashMap<Integer, File> tests = getTestsFromJson();
|
||
//создать папку для пакета.
|
||
user.connection.RMDIR(packageRemoteWorkspace.full_name);
|
||
user.connection.sftpChannel.mkdir(packageRemoteWorkspace.full_name);
|
||
//положить туда запакованные тексты задач.
|
||
Vector<String> compilationLines = new Vector<>();
|
||
Vector<String> 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 {
|
||
boolean hasErrors = false;
|
||
testingPackage.readJson();
|
||
Print("analysing results");
|
||
Vector<DVMRunTask> 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;
|
||
int good=0;
|
||
//--
|
||
for (DVMCompilationTask compilationTask : testingPackage.package_json.compilationTasks) {
|
||
compilationTask.dvm_package_id = testingPackage.id;
|
||
if (!compilationTask.state.equals(TaskState.Done))
|
||
hasErrors = true;
|
||
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<String> output_lines = Arrays.asList(output.split("\n"));
|
||
List<String> errors_lines = Arrays.asList(errors.split("\n"));
|
||
//---
|
||
if (Utils.isCrushed(output_lines, errors_lines)) {
|
||
runTask.state = TaskState.Crushed;
|
||
} else {
|
||
Pair<TaskState, Integer> 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);
|
||
}
|
||
}
|
||
}
|
||
if (!runTask.state.equals(TaskState.Done))
|
||
hasErrors = true;
|
||
else good++;
|
||
}
|
||
}
|
||
}
|
||
testingPackage.progress = 100;
|
||
testingPackage.saveJson(); //запись обновленных результатов пакета в json!
|
||
Print("analysis done, ct_count=" + ct_count + " rt count=" + rt_count);
|
||
testingPackage.state = hasErrors ? TasksPackageState.DoneWithErrors : TasksPackageState.Done;
|
||
double percent = ( ((double)(good))/testingPackage.tasksCount)*100.0;
|
||
testingPackage.description = "Выполнено на "+((int)percent)+"%\n"+
|
||
"Всего задач: "+testingPackage.tasksCount+", из них с ошибками "+(testingPackage.tasksCount-good);
|
||
UpdatePackageState();
|
||
}
|
||
@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));
|
||
user.connection.startShellProcess(packageRemoteWorkspace, "planner_output",
|
||
"ulimit -s unlimited", plannerStartCommand);
|
||
//---
|
||
RemoteFile PID = new RemoteFile(packageRemoteWorkspace, "PID");
|
||
while (!user.connection.Exists(PID)) {
|
||
Print("PID not found");
|
||
Utils_.sleep(1000);
|
||
}
|
||
testingPackage.PID = user.connection.readFromFile(PID).replace("\n", "").replace("\r", "");
|
||
//---
|
||
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<TasksPackageState> 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 MachineConnectionError() {
|
||
Finalize("Количество безуспешных попыток соединения с машиной " + machine.getURL() + " превысило 10");
|
||
}
|
||
@Override
|
||
protected void Kill() throws Exception {
|
||
if (!testingPackage.PID.isEmpty()) {
|
||
user.connection.Command("kill -9 " + testingPackage.PID);
|
||
}
|
||
}
|
||
@Override
|
||
protected void InitSessionCredentials() {
|
||
packageRemoteWorkspace = new RemoteFile(user.workspace + "/tests", String.valueOf(testingPackage.id), true);
|
||
packageLocalWorkspace = new File(Global.DVMPackagesDirectory, String.valueOf(testingPackage.id));
|
||
}
|
||
@Override
|
||
protected boolean CheckModules() throws Exception {
|
||
String log = user.connection.CheckModulesVersion();
|
||
if (!log.isEmpty()) {
|
||
testingPackage.description = log;
|
||
testingPackage.state = TasksPackageState.Aborted;
|
||
return false;
|
||
}
|
||
return true;
|
||
}
|
||
@Override
|
||
public String packageDescription() {
|
||
return "DVM";
|
||
}
|
||
}
|