v++
рефакторинг. Исправлен баг. если прервать локальную задачу, не удалялся файл interrupt.
This commit is contained in:
32
.idea/workspace.xml
generated
32
.idea/workspace.xml
generated
@@ -7,16 +7,32 @@
|
|||||||
</component>
|
</component>
|
||||||
<component name="ChangeListManager">
|
<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 afterPath="$PROJECT_DIR$/src/Visual_DVM_2021/Passes/All/CloneSapforPackage.java" afterDir="false" />
|
|
||||||
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
|
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
|
||||||
<change beforePath="$PROJECT_DIR$/properties" beforeDir="false" afterPath="$PROJECT_DIR$/properties" afterDir="false" />
|
<change beforePath="$PROJECT_DIR$/src/GlobalData/RemoteFile/UI/RemoteFileChooser.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/GlobalData/RemoteFile/UI/RemoteFileChooser.java" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/src/GlobalData/Tasks/Supervisor/Remote/MVSRunSupervisor.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/GlobalData/Tasks/Supervisor/Remote/MVSRunSupervisor.java" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/src/GlobalData/Tasks/Supervisor/Remote/RemoteCompilationSupervisor.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/GlobalData/Tasks/Supervisor/Remote/RemoteCompilationSupervisor.java" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/src/GlobalData/Tasks/Supervisor/Remote/RemoteTaskSupervisor.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/GlobalData/Tasks/Supervisor/Remote/RemoteTaskSupervisor.java" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/src/GlobalData/Tasks/Supervisor/Remote/ServerRunSupervisor.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/GlobalData/Tasks/Supervisor/Remote/ServerRunSupervisor.java" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/src/GlobalData/User/User.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/GlobalData/User/User.java" afterDir="false" />
|
||||||
<change beforePath="$PROJECT_DIR$/src/Repository/Component/Visualiser.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/Repository/Component/Visualiser.java" afterDir="false" />
|
<change beforePath="$PROJECT_DIR$/src/Repository/Component/Visualiser.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/Repository/Component/Visualiser.java" afterDir="false" />
|
||||||
<change beforePath="$PROJECT_DIR$/src/TestingSystem/Common/Group/GroupsDBTable.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/TestingSystem/Common/Group/GroupsDBTable.java" afterDir="false" />
|
<change beforePath="$PROJECT_DIR$/src/TestingSystem/DVM/DVMTestingPlanner.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/TestingSystem/DVM/DVMTestingPlanner.java" afterDir="false" />
|
||||||
<change beforePath="$PROJECT_DIR$/src/TestingSystem/Common/Test/TestDBTable.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/TestingSystem/Common/Test/TestDBTable.java" afterDir="false" />
|
<change beforePath="$PROJECT_DIR$/src/TestingSystem/DVM/UserConnection.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/TestingSystem/DVM/UserConnection.java" afterDir="false" />
|
||||||
<change beforePath="$PROJECT_DIR$/src/TestingSystem/Common/TestingServer.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/TestingSystem/Common/TestingServer.java" afterDir="false" />
|
<change beforePath="$PROJECT_DIR$/src/Visual_DVM_2021/Passes/All/ArchivesBackupPass.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/Visual_DVM_2021/Passes/All/ArchivesBackupPass.java" afterDir="false" />
|
||||||
<change beforePath="$PROJECT_DIR$/src/TestingSystem/SAPFOR/SapforPackage/SapforPackagesBar.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/TestingSystem/SAPFOR/SapforPackage/SapforPackagesBar.java" afterDir="false" />
|
<change beforePath="$PROJECT_DIR$/src/Visual_DVM_2021/Passes/All/Compile.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/Visual_DVM_2021/Passes/All/Compile.java" afterDir="false" />
|
||||||
<change beforePath="$PROJECT_DIR$/src/Visual_DVM_2021/Passes/All/CloneDVMPackage.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/Visual_DVM_2021/Passes/All/CloneDVMPackage.java" afterDir="false" />
|
<change beforePath="$PROJECT_DIR$/src/Visual_DVM_2021/Passes/All/DownloadProject.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/Visual_DVM_2021/Passes/All/DownloadProject.java" afterDir="false" />
|
||||||
<change beforePath="$PROJECT_DIR$/src/Visual_DVM_2021/Passes/PassCode_2021.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/Visual_DVM_2021/Passes/PassCode_2021.java" afterDir="false" />
|
<change beforePath="$PROJECT_DIR$/src/Visual_DVM_2021/Passes/All/InstallServerSapfor.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/Visual_DVM_2021/Passes/All/InstallServerSapfor.java" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/src/Visual_DVM_2021/Passes/All/LocalInitaliseUser.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/Visual_DVM_2021/Passes/All/LocalInitaliseUser.java" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/src/Visual_DVM_2021/Passes/All/RemoteInitialiseUser.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/Visual_DVM_2021/Passes/All/RemoteInitialiseUser.java" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/src/Visual_DVM_2021/Passes/All/RemoteSingleCommand.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/Visual_DVM_2021/Passes/All/RemoteSingleCommand.java" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/src/Visual_DVM_2021/Passes/All/Run.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/Visual_DVM_2021/Passes/All/Run.java" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/src/Visual_DVM_2021/Passes/OLD/AttachFileToProject.java" beforeDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/src/Visual_DVM_2021/Passes/OLD/DeleteAttachments.java" beforeDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/src/Visual_DVM_2021/Passes/SSH/ConnectionPass_2023.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/Visual_DVM_2021/Passes/SSH/ConnectionPass.java" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/src/Visual_DVM_2021/Passes/SSH/CurrentConnectionPass.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/Visual_DVM_2021/Passes/SSH/CurrentConnectionPass.java" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/src/Visual_DVM_2021/Passes/SSH/TaskConnectionPass.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/Visual_DVM_2021/Passes/SSH/TaskConnectionPass.java" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/src/Visual_DVM_2021/Passes/SapforPass.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/Visual_DVM_2021/Passes/SapforPass.java" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/src/Visual_DVM_2021/Passes/SilentSapforPass.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/Visual_DVM_2021/Passes/SilentSapforPass.java" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/src/files/ConnectionPass.java" beforeDir="false" />
|
||||||
</list>
|
</list>
|
||||||
<option name="SHOW_DIALOG" value="false" />
|
<option name="SHOW_DIALOG" value="false" />
|
||||||
<option name="HIGHLIGHT_CONFLICTS" value="true" />
|
<option name="HIGHLIGHT_CONFLICTS" value="true" />
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import Common.Global;
|
|||||||
import Common.UI.UI;
|
import Common.UI.UI;
|
||||||
import Common.UI.Windows.Dialog.Dialog;
|
import Common.UI.Windows.Dialog.Dialog;
|
||||||
import GlobalData.RemoteFile.RemoteFile;
|
import GlobalData.RemoteFile.RemoteFile;
|
||||||
import files.ConnectionPass;
|
import Visual_DVM_2021.Passes.SSH.ConnectionPass;
|
||||||
import com.jcraft.jsch.ChannelSftp.LsEntry;
|
import com.jcraft.jsch.ChannelSftp.LsEntry;
|
||||||
|
|
||||||
import javax.swing.tree.DefaultMutableTreeNode;
|
import javax.swing.tree.DefaultMutableTreeNode;
|
||||||
@@ -28,7 +28,7 @@ public class RemoteFileChooser extends Dialog<String, RemoteFileChooserFields> {
|
|||||||
session = (ConnectionPass) params[0];
|
session = (ConnectionPass) params[0];
|
||||||
target_is_directory = (boolean) params[1];
|
target_is_directory = (boolean) params[1];
|
||||||
try {
|
try {
|
||||||
Refresh(session.getSftpChannel().pwd());
|
Refresh(session.user.connection.sftpChannel.pwd());
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
Global.Log.PrintException(ex);
|
Global.Log.PrintException(ex);
|
||||||
onCancel(); //закрываем окно.
|
onCancel(); //закрываем окно.
|
||||||
@@ -45,7 +45,7 @@ public class RemoteFileChooser extends Dialog<String, RemoteFileChooserFields> {
|
|||||||
root_file = new RemoteFile(path, true);
|
root_file = new RemoteFile(path, true);
|
||||||
root = new DefaultMutableTreeNode(root_file);
|
root = new DefaultMutableTreeNode(root_file);
|
||||||
//-------------------------------------------------------
|
//-------------------------------------------------------
|
||||||
Vector<LsEntry> files = session.getSftpChannel().ls(path);
|
Vector<LsEntry> files = session.user.connection.sftpChannel.ls(path);
|
||||||
Vector<RemoteFile> directories_ = new Vector<>();
|
Vector<RemoteFile> directories_ = new Vector<>();
|
||||||
Vector<RemoteFile> files_ = new Vector<>();
|
Vector<RemoteFile> files_ = new Vector<>();
|
||||||
//отсортировать по принадлежности.
|
//отсортировать по принадлежности.
|
||||||
@@ -74,7 +74,7 @@ public class RemoteFileChooser extends Dialog<String, RemoteFileChooserFields> {
|
|||||||
}
|
}
|
||||||
public void goHome() {
|
public void goHome() {
|
||||||
try {
|
try {
|
||||||
Refresh(session.getSftpChannel().getHome());
|
Refresh(session.user.connection.sftpChannel.getHome());
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
Global.Log.PrintException(ex);
|
Global.Log.PrintException(ex);
|
||||||
onCancel(); //закрываем окно.
|
onCancel(); //закрываем окно.
|
||||||
|
|||||||
@@ -35,9 +35,11 @@ public class MVSRunSupervisor extends ServerRunSupervisor {
|
|||||||
String res = "maxtime=" + Utils.DQuotes(mvs_time) + " ./run";
|
String res = "maxtime=" + Utils.DQuotes(mvs_time) + " ./run";
|
||||||
if (!env.isEmpty())
|
if (!env.isEmpty())
|
||||||
res = env + " " + res;
|
res = env + " " + res;
|
||||||
|
/*
|
||||||
mvs.enqueueTask(pass.ShellCommand(
|
mvs.enqueueTask(pass.ShellCommand(
|
||||||
"cd " + Utils.DQuotes(getRemoteProject().full_name),
|
"cd " + Utils.DQuotes(getRemoteProject().full_name),
|
||||||
res), task);
|
res), task);
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
protected boolean isTaskActive() {
|
protected boolean isTaskActive() {
|
||||||
@@ -45,11 +47,11 @@ public class MVSRunSupervisor extends ServerRunSupervisor {
|
|||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
protected void CheckTask() throws Exception {
|
protected void CheckTask() throws Exception {
|
||||||
mvs.checkTask(pass.ShellCommand(mvs.getCheckTaskCommand(task)), task);
|
// mvs.checkTask(pass.ShellCommand(mvs.getCheckTaskCommand(task)), task);
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
protected void AbortTask() throws Exception {
|
protected void AbortTask() throws Exception {
|
||||||
pass.ShellCommand(mvs.getCancelTaskCommand(task));
|
// pass.ShellCommand(mvs.getCancelTaskCommand(task));
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
protected void CalculatePerformanceTime() throws Exception {
|
protected void CalculatePerformanceTime() throws Exception {
|
||||||
|
|||||||
@@ -10,36 +10,41 @@ public class RemoteCompilationSupervisor extends RemoteTaskSupervisor<Compilatio
|
|||||||
@Override
|
@Override
|
||||||
protected void PrepareWorkspace() throws Exception {
|
protected void PrepareWorkspace() throws Exception {
|
||||||
//0. если нет папки с его именем создаем.
|
//0. если нет папки с его именем создаем.
|
||||||
pass.tryMKDir(getRemoteProject());
|
pass.user.connection.MKDIR(getRemoteProject());
|
||||||
pass.SynchronizeProjectSubDirsR(project, project.Home, getRemoteProject(), false);
|
pass.user.connection.SynchronizeProjectSubDirsR(project, project.Home, getRemoteProject(), false);
|
||||||
pass.tryRM(getBinary());
|
pass.user.connection.tryRM(getBinary());
|
||||||
if (!task.binary_name.isEmpty()) {
|
if (!task.binary_name.isEmpty()) {
|
||||||
RemoteFile old_binary = new RemoteFile(getRemoteProject().full_name, task.binary_name);
|
RemoteFile old_binary = new RemoteFile(getRemoteProject().full_name, task.binary_name);
|
||||||
pass.tryRM(old_binary);
|
pass.user.connection.tryRM(old_binary);
|
||||||
}
|
}
|
||||||
//отправить мейкфайл.
|
//отправить мейкфайл.
|
||||||
Makefile makefile = task.getMakefile();
|
Makefile makefile = task.getMakefile();
|
||||||
File makefile_text = Utils.CreateTempFile("makefile", makefile.Generate(project));
|
File makefile_text = Utils.CreateTempFile("makefile", makefile.Generate(project));
|
||||||
pass.putSingleFile(makefile_text, new RemoteFile(getRemoteProject().full_name, "Makefile"));
|
pass.user.connection.putSingleFile(makefile_text, new RemoteFile(getRemoteProject().full_name, "Makefile"));
|
||||||
//очистить все что связано с gcov
|
//очистить все что связано с gcov
|
||||||
//файлы gcda, gcno, gcov
|
//файлы gcda, gcno, gcov
|
||||||
pass.deleteFilesByExtensions(getRemoteProject(), "gcda", "gcno", "gcov");
|
pass.user.connection.deleteFilesByExtensions(getRemoteProject(), "gcda", "gcno", "gcov");
|
||||||
//очистить служебные файлы.
|
//очистить служебные файлы.
|
||||||
super.PrepareWorkspace();
|
super.PrepareWorkspace();
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
protected void StartTask() throws Exception {
|
protected void StartTask() throws Exception {
|
||||||
//UI.Info("starting task");
|
//UI.Info("starting task");
|
||||||
task.PID = pass.ShellCommand(
|
pass.user.connection.performScript(getRemoteProject(), getStartCommand()+" 1>PID");
|
||||||
"cd " + Utils.DQuotes(getRemoteProject().full_name),
|
RemoteFile PID = getPID();
|
||||||
getStartCommand());
|
while (!pass.user.connection.Exists(PID)){
|
||||||
|
System.out.println("PID NOT FOUND");
|
||||||
|
Utils.sleep(1000);
|
||||||
|
}
|
||||||
|
task.PID = pass.user.connection.readFromFile(PID).replace("\n","").replace("\r","");
|
||||||
|
System.out.println("PID="+Utils.Brackets(task.PID));
|
||||||
task.state = TaskState.Running;
|
task.state = TaskState.Running;
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
protected void ValidateTaskResults() throws Exception {
|
protected void ValidateTaskResults() throws Exception {
|
||||||
if (pass.Exists(getBinary())) {
|
if (pass.user.connection.Exists(getBinary())) {
|
||||||
RemoteFile renamed_binary = new RemoteFile(getRemoteProject().full_name, Utils.getDateName("spf_" + getBinary().name));
|
RemoteFile renamed_binary = new RemoteFile(getRemoteProject().full_name, Utils.getDateName("spf_" + getBinary().name));
|
||||||
pass.sftpChannel.rename(getBinary().full_name, renamed_binary.full_name);
|
pass.user.connection.sftpChannel.rename(getBinary().full_name, renamed_binary.full_name);
|
||||||
task.binary_name = renamed_binary.name;
|
task.binary_name = renamed_binary.name;
|
||||||
task.state = TaskState.Done;
|
task.state = TaskState.Done;
|
||||||
} else task.state = TaskState.DoneWithErrors;
|
} else task.state = TaskState.DoneWithErrors;
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import GlobalData.RemoteFile.RemoteFile;
|
|||||||
import GlobalData.Tasks.Supervisor.TaskSupervisor;
|
import GlobalData.Tasks.Supervisor.TaskSupervisor;
|
||||||
import GlobalData.Tasks.Task;
|
import GlobalData.Tasks.Task;
|
||||||
import GlobalData.Tasks.TaskState;
|
import GlobalData.Tasks.TaskState;
|
||||||
import files.ConnectionPass;
|
import Visual_DVM_2021.Passes.SSH.ConnectionPass;
|
||||||
public abstract class RemoteTaskSupervisor<T extends Task> extends TaskSupervisor<T, ConnectionPass> {
|
public abstract class RemoteTaskSupervisor<T extends Task> extends TaskSupervisor<T, ConnectionPass> {
|
||||||
protected RemoteFile getRemoteProjectsPath() {
|
protected RemoteFile getRemoteProjectsPath() {
|
||||||
return new RemoteFile(pass.user.getRemoteProjectsPath(), true);
|
return new RemoteFile(pass.user.getRemoteProjectsPath(), true);
|
||||||
@@ -16,6 +16,9 @@ public abstract class RemoteTaskSupervisor<T extends Task> extends TaskSuperviso
|
|||||||
protected RemoteFile getBinary() {
|
protected RemoteFile getBinary() {
|
||||||
return new RemoteFile(getRemoteProject().full_name, "0");
|
return new RemoteFile(getRemoteProject().full_name, "0");
|
||||||
}
|
}
|
||||||
|
protected RemoteFile getPID() {
|
||||||
|
return new RemoteFile(getRemoteProject().full_name, "PID");
|
||||||
|
}
|
||||||
protected RemoteFile getRemoteTime() {
|
protected RemoteFile getRemoteTime() {
|
||||||
return new RemoteFile(getRemoteProject().full_name, Constants.time_file);
|
return new RemoteFile(getRemoteProject().full_name, Constants.time_file);
|
||||||
}
|
}
|
||||||
@@ -34,40 +37,48 @@ public abstract class RemoteTaskSupervisor<T extends Task> extends TaskSuperviso
|
|||||||
@Override
|
@Override
|
||||||
protected void PrepareWorkspace() throws Exception {
|
protected void PrepareWorkspace() throws Exception {
|
||||||
super.PrepareWorkspace(); //локальная подготовка
|
super.PrepareWorkspace(); //локальная подготовка
|
||||||
pass.tryRM(getDONE_file());
|
pass.user.connection.tryRM(getDONE_file());
|
||||||
pass.tryRM(getTIMEOUT_file());
|
pass.user.connection.tryRM(getPID());
|
||||||
pass.tryRM(getRemoteOutput());
|
pass.user.connection.tryRM(getTIMEOUT_file());
|
||||||
pass.tryRM(getRemoteErrors());
|
pass.user.connection.tryRM(getRemoteOutput());
|
||||||
pass.tryRM(getRemoteTime());
|
pass.user.connection.tryRM(getRemoteErrors());
|
||||||
|
pass.user.connection.tryRM(getRemoteTime());
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
protected void CheckTask() throws Exception {
|
protected void CheckTask() throws Exception {
|
||||||
RemoteFile DONE = new RemoteFile(getRemoteProject(), Constants.DONE);
|
RemoteFile DONE = new RemoteFile(getRemoteProject(), Constants.DONE);
|
||||||
RemoteFile TIMEOUT = new RemoteFile(getRemoteProject(), Constants.TIMEOUT);
|
RemoteFile TIMEOUT = new RemoteFile(getRemoteProject(), Constants.TIMEOUT);
|
||||||
if (pass.Exists(DONE))
|
if (pass.user.connection.Exists(DONE))
|
||||||
task.state = TaskState.Finished;
|
task.state = TaskState.Finished;
|
||||||
else if (pass.Exists(TIMEOUT))
|
else if (pass.user.connection.Exists(TIMEOUT))
|
||||||
task.state = TaskState.AbortedByTimeout;
|
task.state = TaskState.AbortedByTimeout;
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
protected void AchieveResults() throws Exception {
|
protected void AchieveResults() throws Exception {
|
||||||
pass.tryGetSingleFileWithMaxSize(getRemoteOutput(), task.getOutputFile(), 10240);
|
pass.user.connection.tryGetSingleFileWithMaxSize(getRemoteOutput(), task.getOutputFile(), 10240);
|
||||||
pass.tryGetSingleFileWithMaxSize(getRemoteErrors(), task.getErrorsFile(), 10240);
|
pass.user.connection.tryGetSingleFileWithMaxSize(getRemoteErrors(), task.getErrorsFile(), 10240);
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
protected void AbortTask() throws Exception {
|
protected void AbortTask() throws Exception {
|
||||||
pass.ShellCommand("kill -2 " + task.PID);
|
pass.user.connection.ShellCommand("kill -2 " + task.PID);
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
protected void CalculatePerformanceTime() throws Exception {
|
protected void CalculatePerformanceTime() throws Exception {
|
||||||
if (pass.tryGetSingleFileWithMaxSize(getRemoteTime(), task.getTimeFile(), 0))
|
if (pass.user.connection.tryGetSingleFileWithMaxSize(getRemoteTime(), task.getTimeFile(), 0))
|
||||||
task.RefreshTime();
|
task.RefreshTime();
|
||||||
}
|
}
|
||||||
|
public String getStarter() {
|
||||||
|
return String.join("/", pass.user.workspace, "modules", "starter");
|
||||||
|
}
|
||||||
|
public String getLauncher() {
|
||||||
|
return String.join("/", pass.user.workspace, "modules", "launcher");
|
||||||
|
}
|
||||||
|
|
||||||
protected String getStartCommand() {
|
protected String getStartCommand() {
|
||||||
String res =
|
String res =
|
||||||
String.join(" ",
|
String.join(" ",
|
||||||
Utils.DQuotes(pass.getStarter()),
|
Utils.DQuotes(getStarter()),
|
||||||
Utils.DQuotes(pass.getLauncher()),
|
Utils.DQuotes(getLauncher()),
|
||||||
String.valueOf(task.maxtime),
|
String.valueOf(task.maxtime),
|
||||||
Utils.DQuotes(getCoupDeGrace()),
|
Utils.DQuotes(getCoupDeGrace()),
|
||||||
task.getFullCommand()
|
task.getFullCommand()
|
||||||
|
|||||||
@@ -16,10 +16,14 @@ public class ServerRunSupervisor extends RemoteTaskSupervisor<RunTask> {
|
|||||||
String res = "./run";
|
String res = "./run";
|
||||||
String env = String.join(" ", Current.getRunConfiguration().getEnvList());
|
String env = String.join(" ", Current.getRunConfiguration().getEnvList());
|
||||||
if (!env.isEmpty()) res = env + " " + res;
|
if (!env.isEmpty()) res = env + " " + res;
|
||||||
task.PID = pass.ShellCommand(
|
pass.user.connection.performScript(getRemoteProject(), "ulimit -s unlimited", res+" 1>PID");
|
||||||
"cd " + Utils.DQuotes(getRemoteProject().full_name),
|
RemoteFile PID = getPID();
|
||||||
"ulimit -s unlimited",
|
while (!pass.user.connection.Exists(PID)){
|
||||||
res);
|
System.out.println("PID NOT FOUND");
|
||||||
|
Utils.sleep(1000);
|
||||||
|
}
|
||||||
|
task.PID = pass.user.connection.readFromFile(PID).replace("\n","").replace("\r","");
|
||||||
|
System.out.println("PID="+Utils.Brackets(task.PID));
|
||||||
task.state = TaskState.Running;
|
task.state = TaskState.Running;
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
@@ -32,21 +36,21 @@ public class ServerRunSupervisor extends RemoteTaskSupervisor<RunTask> {
|
|||||||
//-------------------------
|
//-------------------------
|
||||||
//удалить старую статистику если оная есть.
|
//удалить старую статистику если оная есть.
|
||||||
if (!task.last_sts_name.isEmpty()) {
|
if (!task.last_sts_name.isEmpty()) {
|
||||||
pass.tryRM(new RemoteFile(getRemoteProject().full_name, task.last_sts_name));
|
pass.user.connection.tryRM(new RemoteFile(getRemoteProject().full_name, task.last_sts_name));
|
||||||
task.UpdateLastStsName("");
|
task.UpdateLastStsName("");
|
||||||
}
|
}
|
||||||
//-------------------------
|
//-------------------------
|
||||||
String launchScriptText = getLaunchScriptText();
|
String launchScriptText = getLaunchScriptText();
|
||||||
RemoteFile launchScript = new RemoteFile(getRemoteProject().full_name, "run");
|
RemoteFile launchScript = new RemoteFile(getRemoteProject().full_name, "run");
|
||||||
pass.sftpChannel.put(
|
pass.user.connection.sftpChannel.put(
|
||||||
new ByteArrayInputStream(
|
new ByteArrayInputStream(
|
||||||
launchScriptText.getBytes(StandardCharsets.UTF_8)), launchScript.full_name);
|
launchScriptText.getBytes(StandardCharsets.UTF_8)), launchScript.full_name);
|
||||||
pass.sftpChannel.chmod(0777, launchScript.full_name);
|
pass.user.connection.sftpChannel.chmod(0777, launchScript.full_name);
|
||||||
//-
|
//-
|
||||||
//отправить usr.par.
|
//отправить usr.par.
|
||||||
if (task.hasDVMPar()) {
|
if (task.hasDVMPar()) {
|
||||||
File par_text = Utils.CreateTempFile("usr", String.join("\n", task.getRunConfiguration().getParList()));
|
File par_text = Utils.CreateTempFile("usr", String.join("\n", task.getRunConfiguration().getParList()));
|
||||||
pass.putSingleFile(par_text, new RemoteFile(getRemoteProject().full_name, "usr.par"));
|
pass.user.connection.putSingleFile(par_text, new RemoteFile(getRemoteProject().full_name, "usr.par"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
protected String getLaunchScriptText() {
|
protected String getLaunchScriptText() {
|
||||||
@@ -62,7 +66,7 @@ public class ServerRunSupervisor extends RemoteTaskSupervisor<RunTask> {
|
|||||||
task.parseCleanTime();
|
task.parseCleanTime();
|
||||||
//теперь ищем статистику.
|
//теперь ищем статистику.
|
||||||
//статистика
|
//статистика
|
||||||
Vector<ChannelSftp.LsEntry> files = pass.sftpChannel.ls(getRemoteProject().full_name);
|
Vector<ChannelSftp.LsEntry> files = pass.user.connection.sftpChannel.ls(getRemoteProject().full_name);
|
||||||
for (ChannelSftp.LsEntry file : files) {
|
for (ChannelSftp.LsEntry file : files) {
|
||||||
if (file.getFilename().endsWith("sts.gz+")) {
|
if (file.getFilename().endsWith("sts.gz+")) {
|
||||||
task.UpdateLastStsName(file.getFilename());
|
task.UpdateLastStsName(file.getFilename());
|
||||||
@@ -71,7 +75,7 @@ public class ServerRunSupervisor extends RemoteTaskSupervisor<RunTask> {
|
|||||||
}
|
}
|
||||||
if (!task.last_sts_name.isEmpty()) {
|
if (!task.last_sts_name.isEmpty()) {
|
||||||
RemoteFile remote_sts = new RemoteFile(getRemoteProject().full_name, task.last_sts_name);
|
RemoteFile remote_sts = new RemoteFile(getRemoteProject().full_name, task.last_sts_name);
|
||||||
task.hasDvmSts = pass.tryGetSingleFileWithMaxSize(remote_sts, task.getLocalStsFile(), 10240);
|
task.hasDvmSts = pass.user.connection.tryGetSingleFileWithMaxSize(remote_sts, task.getLocalStsFile(), 10240);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ import Common.Current;
|
|||||||
import Common.Database.iDBObject;
|
import Common.Database.iDBObject;
|
||||||
import GlobalData.Machine.Machine;
|
import GlobalData.Machine.Machine;
|
||||||
import TestingSystem.DVM.UserConnection;
|
import TestingSystem.DVM.UserConnection;
|
||||||
import files.ConnectionPass;
|
|
||||||
import com.sun.org.glassfish.gmbal.Description;
|
import com.sun.org.glassfish.gmbal.Description;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
@@ -53,20 +52,21 @@ public class User extends iDBObject {
|
|||||||
public File getLocalModulesDir() {
|
public File getLocalModulesDir() {
|
||||||
return Paths.get(workspace, "modules").toFile();
|
return Paths.get(workspace, "modules").toFile();
|
||||||
}
|
}
|
||||||
|
|
||||||
public File getHeaderCodeFile() {
|
public File getHeaderCodeFile() {
|
||||||
return Paths.get(workspace, "modules", ConnectionPass.Process_r_header).toFile();
|
return Paths.get(workspace, "modules", "Process_r.h").toFile();
|
||||||
}
|
}
|
||||||
public File getStarterCodeFile() {
|
public File getStarterCodeFile() {
|
||||||
return Paths.get(workspace, "modules", ConnectionPass.starter_code).toFile();
|
return Paths.get(workspace, "modules", "starter.cpp").toFile();
|
||||||
}
|
}
|
||||||
public File getStarterFile() {
|
public File getStarterFile() {
|
||||||
return Paths.get(workspace, "modules", ConnectionPass.starter).toFile();
|
return Paths.get(workspace, "modules", "starter").toFile();
|
||||||
}
|
}
|
||||||
public File getLauncherCodeFile() {
|
public File getLauncherCodeFile() {
|
||||||
return Paths.get(workspace, "modules", ConnectionPass.launcher_code).toFile();
|
return Paths.get(workspace, "modules", "launcher.cpp").toFile();
|
||||||
}
|
}
|
||||||
public File getLauncherFile() {
|
public File getLauncherFile() {
|
||||||
return Paths.get(workspace, "modules", ConnectionPass.launcher).toFile();
|
return Paths.get(workspace, "modules", "launcher").toFile();
|
||||||
}
|
}
|
||||||
//-
|
//-
|
||||||
@Description("IGNORE")
|
@Description("IGNORE")
|
||||||
|
|||||||
@@ -62,7 +62,7 @@ public class Visualiser extends Component {
|
|||||||
//http://www.seostella.com/ru/article/2012/02/05/formatirovanie-daty-v-java.html
|
//http://www.seostella.com/ru/article/2012/02/05/formatirovanie-daty-v-java.html
|
||||||
@Override
|
@Override
|
||||||
public void GetVersionInfo() {
|
public void GetVersionInfo() {
|
||||||
version = 1062;
|
version = 1063;
|
||||||
String pattern = "MMM dd yyyy HH:mm:ss";
|
String pattern = "MMM dd yyyy HH:mm:ss";
|
||||||
DateFormat df = new SimpleDateFormat(pattern, Locale.ENGLISH);
|
DateFormat df = new SimpleDateFormat(pattern, Locale.ENGLISH);
|
||||||
date_text = df.format(getClassBuildTime());
|
date_text = df.format(getClassBuildTime());
|
||||||
|
|||||||
@@ -16,7 +16,6 @@ import TestingSystem.DVM.DVMTasks.DVMCompilationTask;
|
|||||||
import TestingSystem.DVM.DVMTasks.DVMRunTask;
|
import TestingSystem.DVM.DVMTasks.DVMRunTask;
|
||||||
import TestingSystem.DVM.DVMTasks.DVMTask;
|
import TestingSystem.DVM.DVMTasks.DVMTask;
|
||||||
import Visual_DVM_2021.Passes.All.UnzipFolderPass;
|
import Visual_DVM_2021.Passes.All.UnzipFolderPass;
|
||||||
import files.ConnectionPass;
|
|
||||||
import javafx.util.Pair;
|
import javafx.util.Pair;
|
||||||
import org.apache.commons.io.FileUtils;
|
import org.apache.commons.io.FileUtils;
|
||||||
|
|
||||||
@@ -38,7 +37,7 @@ public class DVMTestingPlanner extends TestingPlanner<DVMPackage> {
|
|||||||
protected File packageLocalWorkspace;
|
protected File packageLocalWorkspace;
|
||||||
//--
|
//--
|
||||||
public String getPlanner() {
|
public String getPlanner() {
|
||||||
return String.join("/", user.workspace, ConnectionPass.modules, ConnectionPass.planner);
|
return String.join("/", user.workspace, "modules", "planner");
|
||||||
}
|
}
|
||||||
//--
|
//--
|
||||||
//Получить ид тестов и их папки на сервере.
|
//Получить ид тестов и их папки на сервере.
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import Common.Utils.Validators.ShellParser;
|
|||||||
import GlobalData.Machine.Machine;
|
import GlobalData.Machine.Machine;
|
||||||
import GlobalData.RemoteFile.RemoteFile;
|
import GlobalData.RemoteFile.RemoteFile;
|
||||||
import GlobalData.User.User;
|
import GlobalData.User.User;
|
||||||
|
import ProjectData.Project.db_project_info;
|
||||||
import Visual_DVM_2021.Passes.PassException;
|
import Visual_DVM_2021.Passes.PassException;
|
||||||
import com.jcraft.jsch.*;
|
import com.jcraft.jsch.*;
|
||||||
import javafx.util.Pair;
|
import javafx.util.Pair;
|
||||||
@@ -19,6 +20,7 @@ public class UserConnection {
|
|||||||
//--
|
//--
|
||||||
public ChannelSftp sftpChannel = null;
|
public ChannelSftp sftpChannel = null;
|
||||||
public ChannelShell shellChannel = null;
|
public ChannelShell shellChannel = null;
|
||||||
|
public ChannelExec execChannel = null;
|
||||||
//--
|
//--
|
||||||
JSch jsch = null;
|
JSch jsch = null;
|
||||||
Session session = null;
|
Session session = null;
|
||||||
@@ -92,10 +94,12 @@ public class UserConnection {
|
|||||||
}
|
}
|
||||||
if (sftpChannel != null) sftpChannel.disconnect();
|
if (sftpChannel != null) sftpChannel.disconnect();
|
||||||
if (shellChannel != null) shellChannel.disconnect();
|
if (shellChannel != null) shellChannel.disconnect();
|
||||||
|
if (execChannel != null) execChannel.disconnect();
|
||||||
if (session != null) session.disconnect();
|
if (session != null) session.disconnect();
|
||||||
//----------------------
|
//----------------------
|
||||||
sftpChannel = null;
|
sftpChannel = null;
|
||||||
shellChannel = null;
|
shellChannel = null;
|
||||||
|
execChannel = null;
|
||||||
jsch = null;
|
jsch = null;
|
||||||
session = null;
|
session = null;
|
||||||
//---
|
//---
|
||||||
@@ -289,4 +293,122 @@ public class UserConnection {
|
|||||||
}
|
}
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
//--
|
||||||
|
public void tryRM(RemoteFile file) throws Exception {
|
||||||
|
if (Exists(file)) {
|
||||||
|
sftpChannel.rm(file.full_name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//с проверкой.
|
||||||
|
public boolean tryGetSingleFileWithMaxSize(RemoteFile src, File dst, int maxSize) throws Exception {
|
||||||
|
if (Exists(src)) {
|
||||||
|
if ((maxSize == 0) || (getFileKBSize(src.full_name) <= maxSize)) {
|
||||||
|
getSingleFile(src.full_name, dst.getAbsolutePath());
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
Utils.WriteToFile(dst, "Размер файла превышает " + maxSize + " KB.\n" + "Файл не загружен. Его можно просмотреть на машине по адресу\n" + Utils.Brackets(src.full_name));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
//--
|
||||||
|
public void SynchronizeProjectSubDirsR(db_project_info project, File local_dir, RemoteFile remote_dir, boolean data) throws Exception {
|
||||||
|
// ShowMessage2("синхронизация: " + local_dir.getName());
|
||||||
|
Vector<File> local_subdirs = project.getSubdirectoriesSimple(local_dir);
|
||||||
|
Vector<File> local_files = project.getActiveFilesForSynchronization(local_dir, data);
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
LinkedHashMap<String, RemoteFile> remote_subdirs = new LinkedHashMap<>();
|
||||||
|
LinkedHashMap<String, RemoteFile> remote_files = new LinkedHashMap<>();
|
||||||
|
Vector<ChannelSftp.LsEntry> files = sftpChannel.ls(remote_dir.full_name);
|
||||||
|
for (ChannelSftp.LsEntry file : files) {
|
||||||
|
if (file.getAttrs().isDir()) {
|
||||||
|
if (!file.getFilename().equals(".") && !file.getFilename().equals(".."))
|
||||||
|
remote_subdirs.put(file.getFilename(), new RemoteFile(remote_dir.full_name, file.getFilename(), true));
|
||||||
|
} else {
|
||||||
|
RemoteFile rf = new RemoteFile(remote_dir.full_name, file.getFilename());
|
||||||
|
rf.updateTime = RemoteFile.convertUpdateTime(file.getAttrs().getMTime());
|
||||||
|
remote_files.put(file.getFilename(), rf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (File lsd : local_subdirs) {
|
||||||
|
RemoteFile rsd = null;
|
||||||
|
if (!remote_subdirs.containsKey(lsd.getName()))
|
||||||
|
sftpChannel.mkdir((rsd = new RemoteFile(remote_dir.full_name, lsd.getName(), true)).full_name);
|
||||||
|
else rsd = remote_subdirs.get(lsd.getName());
|
||||||
|
SynchronizeProjectSubDirsR(project, lsd, rsd, data);
|
||||||
|
}
|
||||||
|
for (File lf : local_files) {
|
||||||
|
RemoteFile rf = null;
|
||||||
|
if (!remote_files.containsKey(lf.getName())) {
|
||||||
|
rf = new RemoteFile(remote_dir.full_name, lf.getName());
|
||||||
|
// ShowMessage2(lf.getName());
|
||||||
|
putSingleFile(lf, rf);
|
||||||
|
} else {
|
||||||
|
rf = remote_files.get(lf.getName());
|
||||||
|
if (lf.lastModified() > rf.updateTime) {
|
||||||
|
// ShowMessage2(lf.getName());
|
||||||
|
putSingleFile(lf, rf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//--
|
||||||
|
public Vector<RemoteFile> getFilesByExtensions(RemoteFile dir, String... extensions) throws Exception {
|
||||||
|
Vector<RemoteFile> res = new Vector<>();
|
||||||
|
Vector<ChannelSftp.LsEntry> files = sftpChannel.ls(dir.full_name);
|
||||||
|
for (ChannelSftp.LsEntry file : files) {
|
||||||
|
String[] data = file.getFilename().split("\\.");
|
||||||
|
if (data.length > 1) {
|
||||||
|
String file_extension = data[data.length - 1];
|
||||||
|
for (String extension : extensions) {
|
||||||
|
if (file_extension.equalsIgnoreCase(extension))
|
||||||
|
res.add(new RemoteFile(dir.full_name, file.getFilename()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
public void deleteFilesByExtensions(RemoteFile dir, String... extensions) throws Exception {
|
||||||
|
Vector<RemoteFile> to_delete = getFilesByExtensions(dir, extensions);
|
||||||
|
for (RemoteFile file : to_delete)
|
||||||
|
sftpChannel.rm(file.full_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Command(String... commands) throws Exception {
|
||||||
|
if (commands.length > 0) {
|
||||||
|
String command = String.join("\n", commands);
|
||||||
|
// UI.Print(DebugPrintLevel.Session, command);
|
||||||
|
// UI.Print(DebugPrintLevel.Session, "Creating Exec Channel.");
|
||||||
|
execChannel = (ChannelExec) session.openChannel("exec");
|
||||||
|
execChannel.setErrStream(System.err);
|
||||||
|
execChannel.setCommand(command);
|
||||||
|
execChannel.connect();
|
||||||
|
BufferedReader in = new BufferedReader(new InputStreamReader(execChannel.getInputStream()));
|
||||||
|
while (in.readLine() != null) ;
|
||||||
|
execChannel.disconnect();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public String CommandWithAnswer(char end, String... commands) throws Exception {
|
||||||
|
String output = "";
|
||||||
|
if (commands.length > 0) {
|
||||||
|
String command = String.join("\n", commands);
|
||||||
|
// UI.Print(DebugPrintLevel.Session, command);
|
||||||
|
// UI.Print(DebugPrintLevel.Session, "Creating Exec Channel.");
|
||||||
|
// System.out.println(Utils.Brackets(command));
|
||||||
|
execChannel = (ChannelExec) session.openChannel("exec");
|
||||||
|
execChannel.setErrStream(System.err);
|
||||||
|
InputStreamReader reader = new InputStreamReader(execChannel.getInputStream());
|
||||||
|
execChannel.setCommand(command);
|
||||||
|
execChannel.connect();
|
||||||
|
char[] chars = new char[1];
|
||||||
|
while (reader.read(chars) >= 0) if (chars[0] == end) break;
|
||||||
|
else output += chars[0];
|
||||||
|
execChannel.disconnect();
|
||||||
|
}
|
||||||
|
// System.out.println(Utils.Brackets(output));
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
public void copy(RemoteFile src, RemoteFile dst) throws Exception {
|
||||||
|
ShellCommand("cp " + Utils.DQuotes(src.full_name) + " " + Utils.DQuotes(dst.full_name));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import Common.Utils.Utils;
|
|||||||
import GlobalData.Machine.Machine;
|
import GlobalData.Machine.Machine;
|
||||||
import GlobalData.RemoteFile.RemoteFile;
|
import GlobalData.RemoteFile.RemoteFile;
|
||||||
import GlobalData.User.User;
|
import GlobalData.User.User;
|
||||||
import files.ConnectionPass;
|
import Visual_DVM_2021.Passes.SSH.ConnectionPass;
|
||||||
import com.jcraft.jsch.ChannelSftp;
|
import com.jcraft.jsch.ChannelSftp;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
@@ -20,18 +20,14 @@ public class ArchivesBackupPass extends ConnectionPass<File> {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
protected boolean needsInitialize() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
@Override
|
|
||||||
protected void ServerAction() throws Exception {
|
protected void ServerAction() throws Exception {
|
||||||
String workspace_path = Utils.toU(Paths.get(sftpChannel.getHome(),Global.properties.BackupWorkspace).toString());
|
String workspace_path = Utils.toU(Paths.get(user.connection.sftpChannel.getHome(), Global.properties.BackupWorkspace).toString());
|
||||||
RemoteFile workspace = new RemoteFile(workspace_path, true);
|
RemoteFile workspace = new RemoteFile(workspace_path, true);
|
||||||
tryMKDir(workspace);
|
user.connection.MKDIR(workspace);
|
||||||
RemoteFile dst = new RemoteFile(workspace.full_name, src.getName());
|
RemoteFile dst = new RemoteFile(workspace.full_name, src.getName());
|
||||||
putSingleFile(src, dst);
|
user.connection.putSingleFile(src, dst);
|
||||||
//-теперь, удалить старые файлы.
|
//-теперь, удалить старые файлы.
|
||||||
Vector<ChannelSftp.LsEntry> raw_files = sftpChannel.ls(workspace.full_name);
|
Vector<ChannelSftp.LsEntry> raw_files = user.connection.sftpChannel.ls(workspace.full_name);
|
||||||
Vector<RemoteFile> files = new Vector<>();
|
Vector<RemoteFile> files = new Vector<>();
|
||||||
for (ChannelSftp.LsEntry file : raw_files) {
|
for (ChannelSftp.LsEntry file : raw_files) {
|
||||||
if (!file.getAttrs().isDir()) {
|
if (!file.getAttrs().isDir()) {
|
||||||
@@ -44,7 +40,7 @@ public class ArchivesBackupPass extends ConnectionPass<File> {
|
|||||||
files.sort((o1, o2) -> (int) (o2.updateTime - o1.updateTime));
|
files.sort((o1, o2) -> (int) (o2.updateTime - o1.updateTime));
|
||||||
for (int i = 2; i < files.size(); ++i) {
|
for (int i = 2; i < files.size(); ++i) {
|
||||||
System.out.println(files.get(i).full_name + ":" + files.get(i).updateTime);
|
System.out.println(files.get(i).full_name + ":" + files.get(i).updateTime);
|
||||||
sftpChannel.rm(files.get(i).full_name);
|
user.connection.sftpChannel.rm(files.get(i).full_name);
|
||||||
}
|
}
|
||||||
//--------------
|
//--------------
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -70,6 +70,7 @@ public class Compile extends Pass_2021<db_project_info> {
|
|||||||
subpass = passes.get(PassCode_2021.LinuxLocalCompilation);
|
subpass = passes.get(PassCode_2021.LinuxLocalCompilation);
|
||||||
break;
|
break;
|
||||||
case Undefined:
|
case Undefined:
|
||||||
|
case MVS_cluster:
|
||||||
throw new PassException("Компиляция не реализована для типа машины " + Utils.DQuotes(Current.getMachine().type));
|
throw new PassException("Компиляция не реализована для типа машины " + Utils.DQuotes(Current.getMachine().type));
|
||||||
default:
|
default:
|
||||||
subpass = passes.get(PassCode_2021.RemoteCompilation);
|
subpass = passes.get(PassCode_2021.RemoteCompilation);
|
||||||
|
|||||||
@@ -24,19 +24,19 @@ public class DownloadProject extends CurrentConnectionPass {
|
|||||||
System.out.println(Current.getRemoteFile());
|
System.out.println(Current.getRemoteFile());
|
||||||
remote_archive = new RemoteFile(src.full_name, src.name + ".zip", false);
|
remote_archive = new RemoteFile(src.full_name, src.name + ".zip", false);
|
||||||
local_archive = Utils.getTempFileName(remote_archive.name);
|
local_archive = Utils.getTempFileName(remote_archive.name);
|
||||||
if ((getFileKBSize(src.full_name)) <= maxSize) {
|
if ((user.connection.getFileKBSize(src.full_name)) <= maxSize) {
|
||||||
ShowMessage2("Запаковка папки проекта..");
|
ShowMessage2("Запаковка папки проекта..");
|
||||||
Command(
|
user.connection.Command(
|
||||||
"cd " + Utils.DQuotes(src.full_name),
|
"cd " + Utils.DQuotes(src.full_name),
|
||||||
"zip -r " + Utils.DQuotes(remote_archive.full_name) + " ./"
|
"zip -r " + Utils.DQuotes(remote_archive.full_name) + " ./"
|
||||||
);
|
);
|
||||||
// try {
|
// try {
|
||||||
ShowMessage2("Загрузка проекта..");
|
ShowMessage2("Загрузка проекта..");
|
||||||
getSingleFile(remote_archive.full_name, local_archive.getAbsolutePath());
|
user.connection.getSingleFile(remote_archive.full_name, local_archive.getAbsolutePath());
|
||||||
// } catch (Exception ex) {
|
// } catch (Exception ex) {
|
||||||
// throw new PassException("Ошибка загрузки");
|
// throw new PassException("Ошибка загрузки");
|
||||||
// }
|
// }
|
||||||
sftpChannel.rm(remote_archive.full_name);
|
user.connection.sftpChannel.rm(remote_archive.full_name);
|
||||||
} else throw new PassException("Размер проекта превышает " + maxSize + " KB.\n");
|
} else throw new PassException("Размер проекта превышает " + maxSize + " KB.\n");
|
||||||
} else {
|
} else {
|
||||||
//диалога не вышло, сбрасываем файл.
|
//диалога не вышло, сбрасываем файл.
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import Repository.Server.ServerCode;
|
|||||||
import Repository.Server.ServerExchangeUnit_2021;
|
import Repository.Server.ServerExchangeUnit_2021;
|
||||||
import TestingSystem.SAPFOR.ServerSapfor.ServerSapfor;
|
import TestingSystem.SAPFOR.ServerSapfor.ServerSapfor;
|
||||||
import Visual_DVM_2021.Passes.PassCode_2021;
|
import Visual_DVM_2021.Passes.PassCode_2021;
|
||||||
import files.ConnectionPass;
|
import Visual_DVM_2021.Passes.SSH.ConnectionPass;
|
||||||
import Visual_DVM_2021.Passes.Server.TestingSystemPass;
|
import Visual_DVM_2021.Passes.Server.TestingSystemPass;
|
||||||
|
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
@@ -39,39 +39,39 @@ public class InstallServerSapfor extends ConnectionPass<Object> {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
protected boolean needsInitialize() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
@Override
|
|
||||||
protected boolean needsAnimation() {
|
protected boolean needsAnimation() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
protected void ServerAction() throws Exception {
|
protected void ServerAction() throws Exception {
|
||||||
RemoteFile testingSystemHome = new RemoteFile(sftpChannel.pwd(), "_testing_system", true);
|
RemoteFile testingSystemHome = new RemoteFile(user.connection.sftpChannel.pwd(), "_testing_system", true);
|
||||||
RemoteFile repo = new RemoteFile(testingSystemHome.full_name, "Repo", true);
|
RemoteFile repo = new RemoteFile(testingSystemHome.full_name, "Repo", true);
|
||||||
RemoteFile repoSapforHome = new RemoteFile(repo.full_name + Constants.SAPFOR_REPOSITORY_BIN, true);
|
RemoteFile repoSapforHome = new RemoteFile(repo.full_name + Constants.SAPFOR_REPOSITORY_BIN, true);
|
||||||
//--
|
//--
|
||||||
ShowMessage1("Синхронизация ветви DVM...");
|
ShowMessage1("Синхронизация ветви DVM...");
|
||||||
ShellCommand("cd " + Utils.DQuotes(repo.full_name), "svn checkout " + Constants.REPOSITORY_AUTHENTICATION + " " + Constants.DVM_REPOSITORY + "\n");
|
user.connection.performScript(repo,
|
||||||
|
"svn checkout " + Constants.REPOSITORY_AUTHENTICATION + " " + Constants.DVM_REPOSITORY + "\n"
|
||||||
|
);
|
||||||
ShowMessage1("Синхронизация ветви SAPFOR...");
|
ShowMessage1("Синхронизация ветви SAPFOR...");
|
||||||
ShellCommand("cd " + Utils.DQuotes(repo.full_name), "svn checkout " + Constants.REPOSITORY_AUTHENTICATION + " " + Constants.SAPFOR_REPOSITORY + "\n");
|
user.connection.performScript(repo,
|
||||||
|
"svn checkout " + Constants.REPOSITORY_AUTHENTICATION + " " + Constants.SAPFOR_REPOSITORY + "\n"
|
||||||
|
);
|
||||||
ShowMessage1("Сборка SAPFOR...");
|
ShowMessage1("Сборка SAPFOR...");
|
||||||
//-
|
//-
|
||||||
RemoteFile repo_bin = new RemoteFile(repoSapforHome.full_name, "Sapfor_F");
|
RemoteFile repo_bin = new RemoteFile(repoSapforHome.full_name, "Sapfor_F");
|
||||||
if (Exists(repo_bin))
|
if (user.connection.Exists(repo_bin))
|
||||||
sftpChannel.rm(repo_bin.full_name);
|
user.connection.sftpChannel.rm(repo_bin.full_name);
|
||||||
//--
|
//--
|
||||||
performScript(repoSapforHome, "cmake ../", "make -j 4");
|
user.connection.performScript(repoSapforHome, "cmake ../", "make -j 4");
|
||||||
RemoteFile repoSapfor = new RemoteFile(repoSapforHome, "Sapfor_F");
|
RemoteFile repoSapfor = new RemoteFile(repoSapforHome, "Sapfor_F");
|
||||||
result = Exists(repoSapfor);
|
result = user.connection.Exists(repoSapfor);
|
||||||
if (result) {
|
if (result) {
|
||||||
RemoteFile sapforsDirectory = new RemoteFile(testingSystemHome.full_name, "Sapfors", true);
|
RemoteFile sapforsDirectory = new RemoteFile(testingSystemHome.full_name, "Sapfors", true);
|
||||||
//создать папку. Для того чтобы скопировать из репозитория.
|
//создать папку. Для того чтобы скопировать из репозитория.
|
||||||
RemoteFile sapforHome = new RemoteFile(sapforsDirectory.full_name, Utils.getDateName("sapfor"));
|
RemoteFile sapforHome = new RemoteFile(sapforsDirectory.full_name, Utils.getDateName("sapfor"));
|
||||||
tryMKDir(sapforHome);
|
user.connection.MKDIR(sapforHome);
|
||||||
RemoteFile sapforBin = new RemoteFile(sapforHome, "Sapfor_F");
|
RemoteFile sapforBin = new RemoteFile(sapforHome, "Sapfor_F");
|
||||||
copy(repo_bin, sapforBin);
|
user.connection.copy(repo_bin, sapforBin);
|
||||||
//-->>>
|
//-->>>
|
||||||
serverSapfor = new ServerSapfor();
|
serverSapfor = new ServerSapfor();
|
||||||
serverSapfor.home_path = sapforHome.full_name;
|
serverSapfor.home_path = sapforHome.full_name;
|
||||||
@@ -79,9 +79,13 @@ public class InstallServerSapfor extends ConnectionPass<Object> {
|
|||||||
serverSapfor.languageName = LanguageName.fortran;
|
serverSapfor.languageName = LanguageName.fortran;
|
||||||
serverSapfor.buildDate = new Date().getTime();
|
serverSapfor.buildDate = new Date().getTime();
|
||||||
///--->>
|
///--->>
|
||||||
String raw = ShellCommand(serverSapfor.getVersionCommand());
|
RemoteFile version =new RemoteFile(sapforHome, "version.txt");
|
||||||
|
user.connection.ShellCommand(serverSapfor.getVersionCommand()+" 1>"+Utils.DQuotes(version.full_name));
|
||||||
|
if (user.connection.Exists(version)){
|
||||||
|
String raw = user.connection.readFromFile(version);
|
||||||
String[] data = raw.split(" ");
|
String[] data = raw.split(" ");
|
||||||
if (data.length >= 4) serverSapfor.version = data[3].replace(",", "");
|
if (data.length >= 4) serverSapfor.version = data[3].replace(",", "");
|
||||||
|
}
|
||||||
//---
|
//---
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ import Common.Utils.Utils;
|
|||||||
import GlobalData.User.User;
|
import GlobalData.User.User;
|
||||||
import GlobalData.User.UserState;
|
import GlobalData.User.UserState;
|
||||||
import Visual_DVM_2021.Passes.ProcessPass;
|
import Visual_DVM_2021.Passes.ProcessPass;
|
||||||
import files.ConnectionPass;
|
|
||||||
import org.apache.commons.io.FileUtils;
|
import org.apache.commons.io.FileUtils;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
@@ -38,13 +37,13 @@ public class LocalInitaliseUser extends ProcessPass<User> {
|
|||||||
PerformScript(
|
PerformScript(
|
||||||
String.join("\n",
|
String.join("\n",
|
||||||
"cd " + Utils.DQuotes(target.getLocalModulesDir()),
|
"cd " + Utils.DQuotes(target.getLocalModulesDir()),
|
||||||
"g++ " + ConnectionPass.starter_code + " -o " + ConnectionPass.starter,
|
"g++ starter -o starter",
|
||||||
"chmod 0777 " + ConnectionPass.starter
|
"chmod 0777 starter"
|
||||||
));
|
));
|
||||||
PerformScript(String.join("\n",
|
PerformScript(String.join("\n",
|
||||||
"cd " + Utils.DQuotes(target.getLocalModulesDir()),
|
"cd " + Utils.DQuotes(target.getLocalModulesDir()),
|
||||||
"g++ " + ConnectionPass.launcher_code + " -o " + ConnectionPass.launcher,
|
"g++ launcher.cpp -o launcher",
|
||||||
"chmod 0777 " + ConnectionPass.launcher
|
"chmod 0777 launcher"
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
//-
|
//-
|
||||||
|
|||||||
@@ -4,10 +4,10 @@ import Common.Current;
|
|||||||
import Common.Utils.Utils;
|
import Common.Utils.Utils;
|
||||||
import GlobalData.RemoteFile.RemoteFile;
|
import GlobalData.RemoteFile.RemoteFile;
|
||||||
import Visual_DVM_2021.Passes.PassException;
|
import Visual_DVM_2021.Passes.PassException;
|
||||||
import Visual_DVM_2021.Passes.SSH.ConnectionPass_2023;
|
import Visual_DVM_2021.Passes.SSH.ConnectionPass;
|
||||||
|
|
||||||
import java.util.Vector;
|
import java.util.Vector;
|
||||||
public class RemoteInitialiseUser extends ConnectionPass_2023<RemoteFile> {
|
public class RemoteInitialiseUser extends ConnectionPass<RemoteFile> {
|
||||||
RemoteFile modulesDirectory;
|
RemoteFile modulesDirectory;
|
||||||
@Override
|
@Override
|
||||||
protected boolean needsAnimation() {
|
protected boolean needsAnimation() {
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
package Visual_DVM_2021.Passes.All;
|
package Visual_DVM_2021.Passes.All;
|
||||||
|
import Common.Utils.Utils;
|
||||||
|
import GlobalData.RemoteFile.RemoteFile;
|
||||||
import Visual_DVM_2021.Passes.SSH.CurrentConnectionPass;
|
import Visual_DVM_2021.Passes.SSH.CurrentConnectionPass;
|
||||||
public class RemoteSingleCommand extends CurrentConnectionPass<String> {
|
public class RemoteSingleCommand extends CurrentConnectionPass<String> {
|
||||||
String command = "";
|
String command = "";
|
||||||
@@ -12,6 +14,10 @@ public class RemoteSingleCommand extends CurrentConnectionPass<String> {
|
|||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
protected void ServerAction() throws Exception {
|
protected void ServerAction() throws Exception {
|
||||||
target = ShellCommand(command);
|
RemoteFile file = new RemoteFile(user.connection.sftpChannel.getHome(), Utils.getDateName("out"));
|
||||||
|
user.connection.ShellCommand(command+" 1>"+Utils.DQuotes(file.full_name));
|
||||||
|
if (user.connection.Exists(file)){
|
||||||
|
target = user.connection.readFromFile(file);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -64,10 +64,13 @@ public class Run extends Pass_2021<db_project_info> {
|
|||||||
subpass = passes.get(PassCode_2021.LinuxLocalRun);
|
subpass = passes.get(PassCode_2021.LinuxLocalRun);
|
||||||
break;
|
break;
|
||||||
case Undefined:
|
case Undefined:
|
||||||
|
case MVS_cluster:
|
||||||
throw new PassException("Запуск не реализован для типа машины " + Utils.DQuotes(Current.getMachine().type));
|
throw new PassException("Запуск не реализован для типа машины " + Utils.DQuotes(Current.getMachine().type));
|
||||||
|
/*
|
||||||
case MVS_cluster:
|
case MVS_cluster:
|
||||||
subpass = passes.get(PassCode_2021.MVSRun);
|
subpass = passes.get(PassCode_2021.MVSRun);
|
||||||
break;
|
break;
|
||||||
|
*/
|
||||||
default:
|
default:
|
||||||
subpass = passes.get(PassCode_2021.ServerRun);
|
subpass = passes.get(PassCode_2021.ServerRun);
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -1,38 +0,0 @@
|
|||||||
package Visual_DVM_2021.Passes.OLD;
|
|
||||||
public class AttachFileToProject {
|
|
||||||
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
extends ToolBarPass<File> {
|
|
||||||
VFileChooser fileChooser = new VFileChooser(
|
|
||||||
"Выбор вложения",
|
|
||||||
"png",
|
|
||||||
"jpg",
|
|
||||||
"bmp",
|
|
||||||
"zip",
|
|
||||||
"7z",
|
|
||||||
"rar"
|
|
||||||
);
|
|
||||||
@Override
|
|
||||||
protected String getIconPath() {
|
|
||||||
return "/icons/LastOpened.png";
|
|
||||||
}
|
|
||||||
@Override
|
|
||||||
protected boolean CanStart() {
|
|
||||||
return Current.Check(Log, Current.Project) &&
|
|
||||||
((target = fileChooser.ShowDialog()) != null) &&
|
|
||||||
Current.getProject().CheckAttachmentFile(target, Log);
|
|
||||||
}
|
|
||||||
@Override
|
|
||||||
protected void Action() throws Exception {
|
|
||||||
Utils.CheckDirectory(Current.getProject().getAttachmentsDirectory());
|
|
||||||
Path src = target.toPath();
|
|
||||||
Path dst = Paths.get(Current.getProject().getAttachmentsDirectory().getAbsolutePath(), target.getName());
|
|
||||||
Files.copy(src, dst, StandardCopyOption.REPLACE_EXISTING);
|
|
||||||
}
|
|
||||||
@Override
|
|
||||||
protected void PerformDone() throws Exception {
|
|
||||||
// UI.getMainWindow().ShowAttachments();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
package Visual_DVM_2021.Passes.OLD;
|
|
||||||
|
|
||||||
public class DeleteAttachments {}
|
|
||||||
/*
|
|
||||||
extends ToolBarPass {
|
|
||||||
@Override
|
|
||||||
protected String getIconPath() {
|
|
||||||
return "/icons/Delete.png";
|
|
||||||
}
|
|
||||||
@Override
|
|
||||||
protected boolean CanStart() {
|
|
||||||
return Current.Check(Log, Current.Project) && UI.Warning("Удалить все вложения текущего проекта");
|
|
||||||
}
|
|
||||||
@Override
|
|
||||||
protected void Action() throws Exception {
|
|
||||||
Utils.CleanDirectory(Current.getProject().getAttachmentsDirectory());
|
|
||||||
}
|
|
||||||
@Override
|
|
||||||
protected void PerformFinish() {
|
|
||||||
// UI.getMainWindow().ShowAttachments();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
@@ -3,9 +3,9 @@ import GlobalData.Machine.Machine;
|
|||||||
import GlobalData.User.User;
|
import GlobalData.User.User;
|
||||||
import TestingSystem.DVM.UserConnection;
|
import TestingSystem.DVM.UserConnection;
|
||||||
import Visual_DVM_2021.Passes.Pass_2021;
|
import Visual_DVM_2021.Passes.Pass_2021;
|
||||||
public class ConnectionPass_2023<T> extends Pass_2021<T> {
|
public class ConnectionPass<T> extends Pass_2021<T> {
|
||||||
protected Machine machine = null;
|
protected Machine machine = null;
|
||||||
protected User user = null;
|
public User user = null;
|
||||||
//--
|
//--
|
||||||
protected void Connect() throws Exception{
|
protected void Connect() throws Exception{
|
||||||
user.connection = null;
|
user.connection = null;
|
||||||
@@ -1,6 +1,5 @@
|
|||||||
package Visual_DVM_2021.Passes.SSH;
|
package Visual_DVM_2021.Passes.SSH;
|
||||||
import Common.Current;
|
import Common.Current;
|
||||||
import files.ConnectionPass;
|
|
||||||
//завязан на текущие машину и юзера
|
//завязан на текущие машину и юзера
|
||||||
public abstract class CurrentConnectionPass<T> extends ConnectionPass<T> {
|
public abstract class CurrentConnectionPass<T> extends ConnectionPass<T> {
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
package Visual_DVM_2021.Passes.SSH;
|
package Visual_DVM_2021.Passes.SSH;
|
||||||
import Common.Current;
|
import Common.Current;
|
||||||
import Common.Global;
|
import Common.Global;
|
||||||
|
import Common.Utils.Utils;
|
||||||
|
import GlobalData.RemoteFile.RemoteFile;
|
||||||
import GlobalData.Tasks.Supervisor.Remote.RemoteTaskSupervisor;
|
import GlobalData.Tasks.Supervisor.Remote.RemoteTaskSupervisor;
|
||||||
import files.ConnectionPass;
|
|
||||||
public abstract class TaskConnectionPass<S extends RemoteTaskSupervisor> extends ConnectionPass {
|
public abstract class TaskConnectionPass<S extends RemoteTaskSupervisor> extends ConnectionPass {
|
||||||
public S supervisor; //инициализация идет в конструкторе потомка.
|
public S supervisor; //инициализация идет в конструкторе потомка.
|
||||||
public TaskConnectionPass(Class<S> s_class) {
|
public TaskConnectionPass(Class<S> s_class) {
|
||||||
@@ -21,6 +22,14 @@ public abstract class TaskConnectionPass<S extends RemoteTaskSupervisor> extends
|
|||||||
machine = supervisor.task.getMachine();
|
machine = supervisor.task.getMachine();
|
||||||
user = supervisor.task.getUser();
|
user = supervisor.task.getUser();
|
||||||
super.Connect();
|
super.Connect();
|
||||||
|
RemoteFile userWorkspace = new RemoteFile(user.workspace, true);
|
||||||
|
if (!user.connection.Exists(userWorkspace))
|
||||||
|
throw new WorkspaceNotFoundException(
|
||||||
|
"Рабочее пространство пользователя " + Utils.Brackets(user.login)
|
||||||
|
+ " на машине " + Utils.Brackets(machine.getURL())
|
||||||
|
+ "\n" + Utils.Brackets(user.workspace) + "\nне найдено.\n" +
|
||||||
|
"Требуется выполнить повторную инициализацию пользователя."
|
||||||
|
);
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
protected void ServerAction() throws Exception {
|
protected void ServerAction() throws Exception {
|
||||||
|
|||||||
@@ -4,10 +4,6 @@ import Common.UI.UI;
|
|||||||
public class SapforPass extends SilentSapforPass {
|
public class SapforPass extends SilentSapforPass {
|
||||||
//отличается наличием журнала и сообщений
|
//отличается наличием журнала и сообщений
|
||||||
@Override
|
@Override
|
||||||
protected void performPreparation() throws Exception {
|
|
||||||
// target.CleanInterruptFile();
|
|
||||||
}
|
|
||||||
@Override
|
|
||||||
protected void performFinish() throws Exception {
|
protected void performFinish() throws Exception {
|
||||||
target.db.BeginTransaction();
|
target.db.BeginTransaction();
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -19,6 +19,10 @@ public class SilentSapforPass extends CurrentProjectPass {
|
|||||||
return super.canStart(args) && ((sapfor = Current.getSapfor()) != null);
|
return super.canStart(args) && ((sapfor = Current.getSapfor()) != null);
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
|
protected void performPreparation() throws Exception {
|
||||||
|
target.CleanInterruptFile();
|
||||||
|
}
|
||||||
|
@Override
|
||||||
protected boolean validate() {
|
protected boolean validate() {
|
||||||
switch (sapfor.getErrorCode()) {
|
switch (sapfor.getErrorCode()) {
|
||||||
case Sapfor.empty_code:
|
case Sapfor.empty_code:
|
||||||
|
|||||||
@@ -1,416 +0,0 @@
|
|||||||
package files;
|
|
||||||
import Common.Constants;
|
|
||||||
import Common.Utils.Utils;
|
|
||||||
import Common.Utils.Validators.ShellParser;
|
|
||||||
import GlobalData.Machine.Machine;
|
|
||||||
import GlobalData.RemoteFile.RemoteFile;
|
|
||||||
import GlobalData.User.User;
|
|
||||||
import ProjectData.Project.db_project_info;
|
|
||||||
import Visual_DVM_2021.Passes.PassException;
|
|
||||||
import Visual_DVM_2021.Passes.Pass_2021;
|
|
||||||
import Visual_DVM_2021.Passes.SSH.WorkspaceNotFoundException;
|
|
||||||
import com.jcraft.jsch.*;
|
|
||||||
import javafx.util.Pair;
|
|
||||||
|
|
||||||
import java.io.*;
|
|
||||||
import java.net.SocketException;
|
|
||||||
import java.net.SocketTimeoutException;
|
|
||||||
import java.net.UnknownHostException;
|
|
||||||
import java.nio.charset.StandardCharsets;
|
|
||||||
import java.util.LinkedHashMap;
|
|
||||||
import java.util.Vector;
|
|
||||||
//убираем лишний класс-прослойку.
|
|
||||||
//старый server pass Пока не трогаем.
|
|
||||||
//https://stackoverflow.com/questions/15108923/sftp-file-transfer-using-java-jsch
|
|
||||||
//https://javadevblog.com/kak-dobavit-biblioteku-jar-fajl-v-proekt-intellij-idea.html
|
|
||||||
//http://www.jcraft.com/jsch/
|
|
||||||
//http://developer-remarks.blogspot.com/2013/05/ssh-via-jsch-example.html
|
|
||||||
//https://stackoverflow.com/questions/4194439/sending-commands-to-server-via-jsch-shell-channel
|
|
||||||
//todo вывести его. уже есть UserConnection.
|
|
||||||
public abstract class ConnectionPass<T> extends Pass_2021<T> {
|
|
||||||
//-----------------------------------------------
|
|
||||||
public static final String modules = "modules";
|
|
||||||
//--------------
|
|
||||||
public static final String starter = "starter";
|
|
||||||
public static final String launcher = "launcher";
|
|
||||||
public static final String planner = "planner";
|
|
||||||
//--------------
|
|
||||||
public static final String Process_r_header = "Process_r.h";
|
|
||||||
public static final String starter_code = "starter.cpp";
|
|
||||||
public static final String launcher_code = "launcher.cpp";
|
|
||||||
//--------------
|
|
||||||
public static final String projects = "projects";
|
|
||||||
public static final String compilers = "compilers";
|
|
||||||
public static final String tests = "tests";
|
|
||||||
public Machine machine = null;
|
|
||||||
public User user = null;
|
|
||||||
//тут как в WinScp - 2 независимых канала. один для файлов. другой для команд.
|
|
||||||
public ChannelSftp sftpChannel = null;
|
|
||||||
public ChannelShell shellChannel = null;
|
|
||||||
public ChannelExec execChannel = null;
|
|
||||||
//----------------------------------------------------
|
|
||||||
protected JSch jsch;
|
|
||||||
protected Session session = null;
|
|
||||||
protected boolean needsInitialize() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
//-------------------------------------
|
|
||||||
protected boolean isConnected = false; //пока
|
|
||||||
public ChannelSftp getSftpChannel() {
|
|
||||||
return sftpChannel;
|
|
||||||
}
|
|
||||||
//учитывать. что пока сокет не создан, прервать соединение нельзя.
|
|
||||||
public void Connect() throws Exception {
|
|
||||||
isConnected = false;
|
|
||||||
session = (jsch = new JSch()).getSession(user.login, machine.address, machine.port);
|
|
||||||
switch (user.authentication) {
|
|
||||||
case password:
|
|
||||||
session.setPassword(user.password);
|
|
||||||
break;
|
|
||||||
/* пока не совсем ясно как это делать.
|
|
||||||
case key:
|
|
||||||
// https://stackoverflow.com/questions/47422025/java-sftp-authentication-with-ppk-file
|
|
||||||
//todo перешифровать ключ https://www.example-code.com/java/ssh_ppk_to_pem.asp
|
|
||||||
jsch.addIdentity(user.password);
|
|
||||||
break;
|
|
||||||
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
session.setConfig("StrictHostKeyChecking", "no");
|
|
||||||
//UI.Print("Establishing Connection...");
|
|
||||||
ShowMessage1("соединение с машиной " + Utils.Brackets(machine.getURL()) + "..");
|
|
||||||
session.connect(0);
|
|
||||||
//UI.Print("Connection established.");
|
|
||||||
//UI.Print("Creating SFTP Channel.");
|
|
||||||
sftpChannel = (ChannelSftp) session.openChannel("sftp");
|
|
||||||
sftpChannel.connect();
|
|
||||||
isConnected = true; // теперь можно прерывать метод.
|
|
||||||
if (needsInitialize()) {
|
|
||||||
RemoteFile userWorkspace = new RemoteFile(user.workspace, true);
|
|
||||||
if (!Exists(userWorkspace))
|
|
||||||
throw new WorkspaceNotFoundException(
|
|
||||||
"Рабочее пространство пользователя " + Utils.Brackets(user.login)
|
|
||||||
+ " на машине " + Utils.Brackets(machine.getURL())
|
|
||||||
+ "\n" + Utils.Brackets(user.workspace) + "\nне найдено.\n" +
|
|
||||||
"Требуется выполнить повторную инициализацию пользователя."
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public void Disconnect() {
|
|
||||||
if (sftpChannel != null) sftpChannel.disconnect();
|
|
||||||
if (execChannel != null) execChannel.disconnect();
|
|
||||||
if (session != null) session.disconnect();
|
|
||||||
//----------------------
|
|
||||||
sftpChannel = null;
|
|
||||||
execChannel = null;
|
|
||||||
session = null;
|
|
||||||
isConnected = false;
|
|
||||||
//---------------------
|
|
||||||
// UI.Print(DebugPrintLevel.Session, "session ended");
|
|
||||||
}
|
|
||||||
@Override
|
|
||||||
protected void performFinish() throws Exception {
|
|
||||||
Disconnect();
|
|
||||||
}
|
|
||||||
public void Command(String... commands) throws Exception {
|
|
||||||
if (commands.length > 0) {
|
|
||||||
String command = String.join("\n", commands);
|
|
||||||
// UI.Print(DebugPrintLevel.Session, command);
|
|
||||||
// UI.Print(DebugPrintLevel.Session, "Creating Exec Channel.");
|
|
||||||
execChannel = (ChannelExec) session.openChannel("exec");
|
|
||||||
execChannel.setErrStream(System.err);
|
|
||||||
execChannel.setCommand(command);
|
|
||||||
execChannel.connect();
|
|
||||||
BufferedReader in = new BufferedReader(new InputStreamReader(execChannel.getInputStream()));
|
|
||||||
while (in.readLine() != null) ;
|
|
||||||
execChannel.disconnect();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public String CommandWithAnswer(char end, String... commands) throws Exception {
|
|
||||||
String output = "";
|
|
||||||
if (commands.length > 0) {
|
|
||||||
String command = String.join("\n", commands);
|
|
||||||
// UI.Print(DebugPrintLevel.Session, command);
|
|
||||||
// UI.Print(DebugPrintLevel.Session, "Creating Exec Channel.");
|
|
||||||
// System.out.println(Utils.Brackets(command));
|
|
||||||
execChannel = (ChannelExec) session.openChannel("exec");
|
|
||||||
execChannel.setErrStream(System.err);
|
|
||||||
InputStreamReader reader = new InputStreamReader(execChannel.getInputStream());
|
|
||||||
execChannel.setCommand(command);
|
|
||||||
execChannel.connect();
|
|
||||||
char[] chars = new char[1];
|
|
||||||
while (reader.read(chars) >= 0) if (chars[0] == end) break;
|
|
||||||
else output += chars[0];
|
|
||||||
execChannel.disconnect();
|
|
||||||
}
|
|
||||||
// System.out.println(Utils.Brackets(output));
|
|
||||||
return output;
|
|
||||||
}
|
|
||||||
//https://stackoverflow.com/questions/4194439/sending-commands-to-server-via-jsch-shell-channel
|
|
||||||
@Override
|
|
||||||
protected void CheckException(Exception ex) {
|
|
||||||
if (ex instanceof WorkspaceNotFoundException) {
|
|
||||||
Log.Writeln_(ex.getMessage());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
Throwable cause = getCauseRec(ex);
|
|
||||||
if ((cause instanceof UnknownHostException) || (cause instanceof SocketException)) {
|
|
||||||
Log.Writeln(machine.getFullDescription() + " не найден(а).\n" + "Проверьте наличие подключения к сети.");
|
|
||||||
} else if (cause instanceof SocketTimeoutException) {
|
|
||||||
Log.Writeln(machine.getFullDescription() + " не отвечает.");
|
|
||||||
} else super.CheckException(ex);
|
|
||||||
}
|
|
||||||
public Vector<String> read_file_lines(String path_r) throws Exception {
|
|
||||||
Vector<String> res = new Vector<>();
|
|
||||||
InputStream out = sftpChannel.get(path_r);
|
|
||||||
BufferedReader br = new BufferedReader(new InputStreamReader(out));
|
|
||||||
String line;
|
|
||||||
while ((line = br.readLine()) != null) res.add(line);
|
|
||||||
br.close();
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
public void getSingleFile(String src, String dst) throws Exception {
|
|
||||||
sftpChannel.get(src, dst);
|
|
||||||
}
|
|
||||||
//с проверкой.
|
|
||||||
public boolean tryGetSingleFileWithMaxSize(RemoteFile src, File dst, int maxSize) throws Exception {
|
|
||||||
if (Exists(src)) {
|
|
||||||
if ((maxSize == 0) || (getFileKBSize(src.full_name) <= maxSize)) {
|
|
||||||
getSingleFile(src.full_name, dst.getAbsolutePath());
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
Utils.WriteToFile(dst, "Размер файла превышает " + maxSize + " KB.\n" + "Файл не загружен. Его можно просмотреть на машине по адресу\n" + Utils.Brackets(src.full_name));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
public void putSingleFile(File src, RemoteFile dst) throws Exception {
|
|
||||||
sftpChannel.put(src.getAbsolutePath(), dst.full_name);
|
|
||||||
}
|
|
||||||
public void tryMKDir(RemoteFile dir) throws Exception {
|
|
||||||
if (!Exists(dir)) sftpChannel.mkdir(dir.full_name);
|
|
||||||
}
|
|
||||||
public void tryRM(RemoteFile file) throws Exception {
|
|
||||||
if (Exists(file))
|
|
||||||
sftpChannel.rm(file.full_name);
|
|
||||||
}
|
|
||||||
public void putSingleFile(String src, String dst) throws Exception {
|
|
||||||
sftpChannel.put(src, dst);
|
|
||||||
}
|
|
||||||
public void put_resource(String res_name) throws Exception {
|
|
||||||
putSingleFile(Utils.CreateTempResourceFile(res_name).getAbsolutePath(), res_name);
|
|
||||||
}
|
|
||||||
@Override
|
|
||||||
public void body() throws Exception {
|
|
||||||
Connect();
|
|
||||||
ServerAction();
|
|
||||||
}
|
|
||||||
protected void ServerAction() throws Exception {
|
|
||||||
}
|
|
||||||
//https://losst.ru/komanda-find-v-linux#%D0%9E%D1%81%D0%BD%D0%BE%D0%B2%D0%BD%D1%8B%D0%B5_%D0%BF%D0%B0%D1%80%D0%B0%D0%BC%D0%B5%D1%82%D1%80%D1%8B_%D0%BA%D0%BE%D0%BC%D0%B0%D0%BD%D0%B4%D1%8B_find
|
|
||||||
public String getStarter() {
|
|
||||||
return String.join("/", user.workspace, modules, starter);
|
|
||||||
}
|
|
||||||
public String getLauncher() {
|
|
||||||
return String.join("/", user.workspace, modules, launcher);
|
|
||||||
}
|
|
||||||
//насчет даты.
|
|
||||||
//http://i-leon.ru/tools/time
|
|
||||||
//этот метод для того чтобы не пересылать подверсии. В случае тестов их наличие исключено!
|
|
||||||
public void SynchronizeProjectSubDirsR(db_project_info project, File local_dir, RemoteFile remote_dir, boolean data) throws Exception {
|
|
||||||
ShowMessage2("синхронизация: " + local_dir.getName());
|
|
||||||
Vector<File> local_subdirs = project.getSubdirectoriesSimple(local_dir);
|
|
||||||
Vector<File> local_files = project.getActiveFilesForSynchronization(local_dir, data);
|
|
||||||
//------------------------------------------------------------------------
|
|
||||||
LinkedHashMap<String, RemoteFile> remote_subdirs = new LinkedHashMap<>();
|
|
||||||
LinkedHashMap<String, RemoteFile> remote_files = new LinkedHashMap<>();
|
|
||||||
Vector<ChannelSftp.LsEntry> files = sftpChannel.ls(remote_dir.full_name);
|
|
||||||
for (ChannelSftp.LsEntry file : files) {
|
|
||||||
if (file.getAttrs().isDir()) {
|
|
||||||
if (!file.getFilename().equals(".") && !file.getFilename().equals(".."))
|
|
||||||
remote_subdirs.put(file.getFilename(), new RemoteFile(remote_dir.full_name, file.getFilename(), true));
|
|
||||||
} else {
|
|
||||||
RemoteFile rf = new RemoteFile(remote_dir.full_name, file.getFilename());
|
|
||||||
rf.updateTime = RemoteFile.convertUpdateTime(file.getAttrs().getMTime());
|
|
||||||
remote_files.put(file.getFilename(), rf);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (File lsd : local_subdirs) {
|
|
||||||
RemoteFile rsd = null;
|
|
||||||
if (!remote_subdirs.containsKey(lsd.getName()))
|
|
||||||
sftpChannel.mkdir((rsd = new RemoteFile(remote_dir.full_name, lsd.getName(), true)).full_name);
|
|
||||||
else rsd = remote_subdirs.get(lsd.getName());
|
|
||||||
SynchronizeProjectSubDirsR(project, lsd, rsd, data);
|
|
||||||
}
|
|
||||||
for (File lf : local_files) {
|
|
||||||
RemoteFile rf = null;
|
|
||||||
if (!remote_files.containsKey(lf.getName())) {
|
|
||||||
rf = new RemoteFile(remote_dir.full_name, lf.getName());
|
|
||||||
ShowMessage2(lf.getName());
|
|
||||||
putSingleFile(lf, rf);
|
|
||||||
} else {
|
|
||||||
rf = remote_files.get(lf.getName());
|
|
||||||
if (lf.lastModified() > rf.updateTime) {
|
|
||||||
ShowMessage2(lf.getName());
|
|
||||||
putSingleFile(lf, rf);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
protected int getFileKBSize(String path) throws Exception {
|
|
||||||
return Integer.parseInt(CommandWithAnswer('\t', "du " + Utils.DQuotes(path)));
|
|
||||||
}
|
|
||||||
//https://stackoverflow.com/questions/4194439/sending-commands-to-server-via-jsch-shell-channel
|
|
||||||
public String ShellCommand(String... commands) throws Exception {
|
|
||||||
shellChannel = (ChannelShell) session.openChannel("shell");
|
|
||||||
PipedInputStream in = new PipedInputStream();
|
|
||||||
PipedOutputStream out = new PipedOutputStream();
|
|
||||||
shellChannel.setInputStream(in);
|
|
||||||
shellChannel.setOutputStream(out);
|
|
||||||
PipedOutputStream pin = new PipedOutputStream(in);
|
|
||||||
PipedInputStream pout = new PipedInputStream(out);
|
|
||||||
shellChannel.connect();
|
|
||||||
InputStreamReader fromServer = new InputStreamReader(pout);
|
|
||||||
ShellParser.setUserName(user.login);
|
|
||||||
ShellParser.ReadInvitation(fromServer);
|
|
||||||
// System.out.println("first invitation read");
|
|
||||||
String result = "";
|
|
||||||
//формат работы с шеллом.
|
|
||||||
//<эхо-команды\n><ответ команды><приглашение\n><приглашение>
|
|
||||||
for (String command : commands) {
|
|
||||||
// System.out.println(command);
|
|
||||||
pin.write((command + "\r\n").getBytes());
|
|
||||||
ShellParser.ReadLine(fromServer);
|
|
||||||
// UI.Info("echo read");
|
|
||||||
ShellParser.ReadInvitation(fromServer);
|
|
||||||
// UI.Info("first invitation read");
|
|
||||||
result = ShellParser.getCommandResult(fromServer);
|
|
||||||
// UI.Info("result = " + Utils.Brackets(result));
|
|
||||||
}
|
|
||||||
shellChannel.disconnect();
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
public Vector<RemoteFile> getFilesByExtensions(RemoteFile dir, String... extensions) throws Exception {
|
|
||||||
Vector<RemoteFile> res = new Vector<>();
|
|
||||||
Vector<ChannelSftp.LsEntry> files = sftpChannel.ls(dir.full_name);
|
|
||||||
for (ChannelSftp.LsEntry file : files) {
|
|
||||||
String[] data = file.getFilename().split("\\.");
|
|
||||||
if (data.length > 1) {
|
|
||||||
String file_extension = data[data.length - 1];
|
|
||||||
for (String extension : extensions) {
|
|
||||||
if (file_extension.equalsIgnoreCase(extension))
|
|
||||||
res.add(new RemoteFile(dir.full_name, file.getFilename()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
public void deleteFilesByExtensions(RemoteFile dir, String... extensions) throws Exception {
|
|
||||||
Vector<RemoteFile> to_delete = getFilesByExtensions(dir, extensions);
|
|
||||||
for (RemoteFile file : to_delete)
|
|
||||||
sftpChannel.rm(file.full_name);
|
|
||||||
}
|
|
||||||
public void copy(RemoteFile src, RemoteFile dst) throws Exception {
|
|
||||||
ShellCommand("cp " + Utils.DQuotes(src.full_name) + " " + Utils.DQuotes(dst.full_name));
|
|
||||||
}
|
|
||||||
//-------
|
|
||||||
public void writeToFile(String text, RemoteFile dst) throws Exception {
|
|
||||||
sftpChannel.put(new ByteArrayInputStream(text.getBytes(StandardCharsets.UTF_8)), dst.full_name);
|
|
||||||
sftpChannel.chmod(0777, dst.full_name);
|
|
||||||
}
|
|
||||||
public void SynchronizeSubDirsR(File local_dir, RemoteFile remote_dir) throws Exception {
|
|
||||||
File[] local_subdirs = local_dir.listFiles(File::isDirectory);
|
|
||||||
File[] local_files = local_dir.listFiles(File::isFile);
|
|
||||||
//------------------------------------------------------------------------
|
|
||||||
LinkedHashMap<String, RemoteFile> remote_subdirs = new LinkedHashMap<>();
|
|
||||||
LinkedHashMap<String, RemoteFile> remote_files = new LinkedHashMap<>();
|
|
||||||
Vector<ChannelSftp.LsEntry> files = sftpChannel.ls(remote_dir.full_name);
|
|
||||||
for (ChannelSftp.LsEntry file : files) {
|
|
||||||
if (file.getAttrs().isDir()) {
|
|
||||||
if (!file.getFilename().equals(".") && !file.getFilename().equals(".."))
|
|
||||||
remote_subdirs.put(file.getFilename(), new RemoteFile(remote_dir.full_name, file.getFilename(), true));
|
|
||||||
} else {
|
|
||||||
RemoteFile rf = new RemoteFile(remote_dir.full_name, file.getFilename());
|
|
||||||
rf.updateTime = RemoteFile.convertUpdateTime(file.getAttrs().getMTime());
|
|
||||||
remote_files.put(file.getFilename(), rf);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (local_subdirs != null) {
|
|
||||||
for (File lsd : local_subdirs) {
|
|
||||||
if (!lsd.getName().equals(Constants.data)) {
|
|
||||||
RemoteFile rsd = null;
|
|
||||||
if (!remote_subdirs.containsKey(lsd.getName()))
|
|
||||||
sftpChannel.mkdir((rsd = new RemoteFile(remote_dir.full_name, lsd.getName(), true)).full_name);
|
|
||||||
else rsd = remote_subdirs.get(lsd.getName());
|
|
||||||
SynchronizeSubDirsR(lsd, rsd);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (local_files != null) {
|
|
||||||
for (File lf : local_files) {
|
|
||||||
RemoteFile rf = null;
|
|
||||||
if (!remote_files.containsKey(lf.getName())) {
|
|
||||||
rf = new RemoteFile(remote_dir.full_name, lf.getName());
|
|
||||||
putSingleFile(lf, rf);
|
|
||||||
} else {
|
|
||||||
rf = remote_files.get(lf.getName());
|
|
||||||
if (lf.lastModified() > rf.updateTime) {
|
|
||||||
putSingleFile(lf, rf);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public void RMDIR(String dir) throws Exception {
|
|
||||||
if (!dir.isEmpty() && !dir.equals("/") && !dir.equals("\\") && !dir.equals("*")) {
|
|
||||||
ShellCommand("rm -rf " + Utils.DQuotes(dir));
|
|
||||||
} else throw new PassException("Недопустимый путь для удаления папки " + Utils.DQuotes(dir));
|
|
||||||
}
|
|
||||||
//скорее всего,временные методы. они есть в UserConnection, при удаленном запуске тестирования
|
|
||||||
//--------------------------------------------------------------------------------
|
|
||||||
public void MKDIR(RemoteFile dir) throws Exception {
|
|
||||||
if (!Exists(dir)) sftpChannel.mkdir(dir.full_name);
|
|
||||||
}
|
|
||||||
//--
|
|
||||||
public Pair<RemoteFile, RemoteFile> performScript(RemoteFile directory, String... commands) throws Exception {
|
|
||||||
RemoteFile script_file = new RemoteFile(directory.full_name, Constants.script);
|
|
||||||
RemoteFile out = new RemoteFile(directory.full_name, Constants.out_file);
|
|
||||||
RemoteFile err = new RemoteFile(directory.full_name, Constants.err_file);
|
|
||||||
//
|
|
||||||
Vector<RemoteFile> files = new Vector<>();
|
|
||||||
files.add(script_file);
|
|
||||||
files.add(out);
|
|
||||||
files.add(err);
|
|
||||||
for (RemoteFile file : files) {
|
|
||||||
if (Exists(file))
|
|
||||||
sftpChannel.rm(file.full_name);
|
|
||||||
}
|
|
||||||
//--
|
|
||||||
writeToFile(String.join("\n", commands), script_file);
|
|
||||||
//--
|
|
||||||
ShellCommand("cd " + Utils.DQuotes(directory.full_name),
|
|
||||||
script_file.full_name + " 1>" + Constants.out_file + " 2>" + Constants.err_file);
|
|
||||||
return new Pair<>(out, err);
|
|
||||||
}
|
|
||||||
//--
|
|
||||||
//--сам себя
|
|
||||||
public boolean Exists(String file_full_name) throws Exception {
|
|
||||||
try {
|
|
||||||
sftpChannel.stat(file_full_name);
|
|
||||||
return true;
|
|
||||||
} catch (SftpException e) {
|
|
||||||
if (e.id == ChannelSftp.SSH_FX_NO_SUCH_FILE) {
|
|
||||||
// file doesn't exist
|
|
||||||
return false;
|
|
||||||
} else {
|
|
||||||
// something else went wrong
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public boolean Exists(RemoteFile file) throws Exception {
|
|
||||||
return Exists(file.full_name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Reference in New Issue
Block a user