Fixed download file canceling
authorzev <zev@netxms.org>
Tue, 7 Nov 2017 16:58:26 +0000 (18:58 +0200)
committerzev <zev@netxms.org>
Tue, 7 Nov 2017 16:58:38 +0000 (18:58 +0200)
24 files changed:
include/nms_agent.h
include/nms_cscp.h
include/nxcpapi.h
src/agent/core/nxagentd.cpp
src/agent/core/nxagentd.h
src/agent/core/session.cpp
src/agent/libnxagent/bridge.cpp
src/agent/subagents/filemgr/filemgr.cpp
src/client/java/netxms-client/src/main/java/org/netxms/client/NXCSession.java
src/client/java/netxms-client/src/main/java/org/netxms/client/server/ServerJobIdUpdater.java [new file with mode: 0644]
src/java/netxms-eclipse/Core/src/org/netxms/ui/eclipse/jobs/ConsoleJobCallingServerJob.java [new file with mode: 0644]
src/java/netxms-eclipse/FileManager/src/org/netxms/ui/eclipse/filemanager/views/AgentFileManager.java
src/java/netxms-eclipse/FileManager/src/org/netxms/ui/eclipse/filemanager/widgets/DynamicFileViewer.java
src/java/netxms-eclipse/ObjectTools/src/org/netxms/ui/eclipse/objecttools/api/ObjectToolExecutor.java
src/libnetxms/nxcp.cpp
src/server/core/download_job.cpp
src/server/core/session.cpp
src/server/include/nxsrvapi.h
src/server/libnxsrv/agent.cpp
webui/webapp/Core/src/org/netxms/ui/eclipse/jobs/ConsoleJobCallingServerJob.java [new file with mode: 0644]
webui/webapp/FileManager/src/org/netxms/ui/eclipse/filemanager/views/AgentFileManager.java
webui/webapp/FileManager/src/org/netxms/ui/eclipse/filemanager/widgets/DynamicFileViewer.java
webui/webapp/ObjectTools/src/org/netxms/ui/eclipse/objecttools/api/ObjectToolExecutor.java
webui/webapp/ServerJobManager/src/org/netxms/ui/eclipse/serverjobmanager/views/ServerJobManager.java

index ba8bd0b..649c659 100644 (file)
@@ -536,7 +536,7 @@ public:
    virtual void postMessage(NXCPMessage *msg) = 0;
    virtual bool sendRawMessage(NXCP_MESSAGE *msg) = 0;
    virtual void postRawMessage(NXCP_MESSAGE *msg) = 0;
-       virtual bool sendFile(UINT32 requestId, const TCHAR *file, long offset, bool allowCompression) = 0;
+       virtual bool sendFile(UINT32 requestId, const TCHAR *file, long offset, bool allowCompression, VolatileCounter *cancelationFlag) = 0;
    virtual UINT32 doRequest(NXCPMessage *msg, UINT32 timeout) = 0;
    virtual NXCPMessage *doRequestEx(NXCPMessage *msg, UINT32 timeout) = 0;
    virtual UINT32 generateRequestId() = 0;
@@ -786,7 +786,7 @@ void LIBNXAGENT_EXPORTABLE AgentSendTrap2(UINT32 dwEvent, const TCHAR *eventName
 bool LIBNXAGENT_EXPORTABLE AgentEnumerateSessions(EnumerationCallbackResult (* callback)(AbstractCommSession *, void *), void *data);
 AbstractCommSession LIBNXAGENT_EXPORTABLE *AgentFindServerSession(UINT64 serverId);
 
-bool LIBNXAGENT_EXPORTABLE AgentSendFileToServer(void *session, UINT32 requestId, const TCHAR *file, long offset, bool allowCompression);
+bool LIBNXAGENT_EXPORTABLE AgentSendFileToServer(void *session, UINT32 requestId, const TCHAR *file, long offset, bool allowCompression, VolatileCounter *cancelationFlag);
 
 bool LIBNXAGENT_EXPORTABLE AgentPushParameterData(const TCHAR *parameter, const TCHAR *value);
 bool LIBNXAGENT_EXPORTABLE AgentPushParameterDataInt32(const TCHAR *parameter, LONG value);
index 5b71f94..7c34e95 100644 (file)
@@ -592,6 +592,7 @@ typedef struct
 #define CMD_EXPAND_MACROS                 0x0165
 #define CMD_EXECUTE_ACTION_WITH_EXPANSION 0x0166
 #define CMD_HOST_BY_IP                    0x0167
+#define CMD_CANCEL_FILE_DOWNLOAD          0x0168
 
 #define CMD_RS_LIST_REPORTS            0x1100
 #define CMD_RS_GET_REPORT              0x1101
index 06dd874..11306dc 100644 (file)
@@ -579,7 +579,8 @@ bool LIBNETXMS_EXPORTABLE SendFileOverNXCP(SOCKET hSocket, UINT32 dwId, const TC
 bool LIBNETXMS_EXPORTABLE SendFileOverNXCP(AbstractCommChannel *channel, UINT32 dwId, const TCHAR *pszFile,
                                            NXCPEncryptionContext *pCtx, long offset,
                                            void (* progressCallback)(INT64, void *), void *cbArg,
-                                           MUTEX mutex, NXCPStreamCompressionMethod compressionMethod = NXCP_STREAM_COMPRESSION_NONE);
+                                           MUTEX mutex, NXCPStreamCompressionMethod compressionMethod = NXCP_STREAM_COMPRESSION_NONE,
+                                           VolatileCounter *cancelationFlag = NULL);
 bool LIBNETXMS_EXPORTABLE NXCPGetPeerProtocolVersion(SOCKET s, int *pnVersion, MUTEX mutex);
 bool LIBNETXMS_EXPORTABLE NXCPGetPeerProtocolVersion(AbstractCommChannel *channel, int *pnVersion, MUTEX mutex);
 
index 89b34ac..a19ec88 100644 (file)
@@ -104,7 +104,7 @@ void LIBNXAGENT_EXPORTABLE InitSubAgentAPI(void (* writeLog)(int, int, const TCH
                                            void (* sendTrap2)(UINT32, const TCHAR *, int, TCHAR **),
                                            bool (* enumerateSessions)(EnumerationCallbackResult (*)(AbstractCommSession *, void *), void*),
                                            AbstractCommSession *(* findServerSession)(UINT64),
-                                           bool (* sendFile)(void *, UINT32, const TCHAR *, long, bool),
+                                           bool (* sendFile)(void *, UINT32, const TCHAR *, long, bool, VolatileCounter *),
                                            bool (* pushData)(const TCHAR *, const TCHAR *, UINT32, time_t),
                                            DB_HANDLE (* getLocalDatabaseHandle)(),
                                            CONDITION shutdownCondition, const TCHAR *dataDirectory);
@@ -683,11 +683,11 @@ static void LoadPlatformSubagent()
 /**
  * Send file to server (subagent API)
  */
-static bool SendFileToServer(void *session, UINT32 requestId, const TCHAR *file, long offset, bool allowCompression)
+static bool SendFileToServer(void *session, UINT32 requestId, const TCHAR *file, long offset, bool allowCompression, VolatileCounter *cancelationFlag)
 {
        if (session == NULL)
                return false;
-       return ((CommSession *)session)->sendFile(requestId, file, offset, allowCompression);
+       return ((CommSession *)session)->sendFile(requestId, file, offset, allowCompression, cancelationFlag);
 }
 
 /**
index 1bb9236..264ebe8 100644 (file)
@@ -376,7 +376,7 @@ public:
    virtual void postMessage(NXCPMessage *msg) { if (!m_disconnected) m_sendQueue->put(msg->serialize(m_allowCompression)); }
    virtual bool sendRawMessage(NXCP_MESSAGE *msg);
    virtual void postRawMessage(NXCP_MESSAGE *msg) { if (!m_disconnected) m_sendQueue->put(nx_memdup(msg, ntohl(msg->size))); }
-       virtual bool sendFile(UINT32 requestId, const TCHAR *file, long offset, bool allowCompression);
+       virtual bool sendFile(UINT32 requestId, const TCHAR *file, long offset, bool allowCompression, VolatileCounter *cancelationFlag);
    virtual UINT32 doRequest(NXCPMessage *msg, UINT32 timeout);
    virtual NXCPMessage *doRequestEx(NXCPMessage *msg, UINT32 timeout);
    virtual UINT32 generateRequestId();
@@ -434,7 +434,7 @@ public:
    virtual void postMessage(NXCPMessage *pMsg) { }
    virtual bool sendRawMessage(NXCP_MESSAGE *pMsg) { return false; }
    virtual void postRawMessage(NXCP_MESSAGE *pMsg) { }
-   virtual bool sendFile(UINT32 requestId, const TCHAR *file, long offset, bool allowCompression) { return false; }
+   virtual bool sendFile(UINT32 requestId, const TCHAR *file, long offset, bool allowCompression, VolatileCounter *cancelationFlag) { return false; }
    virtual UINT32 doRequest(NXCPMessage *msg, UINT32 timeout) { return RCC_NOT_IMPLEMENTED; }
    virtual NXCPMessage *doRequestEx(NXCPMessage *msg, UINT32 timeout) { return NULL; }
    virtual UINT32 generateRequestId() { return 0; }
index 5762b11..930a7cc 100644 (file)
@@ -944,12 +944,12 @@ static void SendFileProgressCallback(INT64 bytesTransferred, void *cbArg)
 /**
  * Send file to server
  */
-bool CommSession::sendFile(UINT32 requestId, const TCHAR *file, long offset, bool allowCompression)
+bool CommSession::sendFile(UINT32 requestId, const TCHAR *file, long offset, bool allowCompression, VolatileCounter *cancelationFlag)
 {
    if (m_disconnected)
       return false;
        return SendFileOverNXCP(m_channel, requestId, file, m_pCtx, offset,
-                SendFileProgressCallback, this, m_socketWriteMutex, allowCompression ? NXCP_STREAM_COMPRESSION_DEFLATE : NXCP_STREAM_COMPRESSION_NONE);
+                SendFileProgressCallback, this, m_socketWriteMutex, allowCompression ? NXCP_STREAM_COMPRESSION_DEFLATE : NXCP_STREAM_COMPRESSION_NONE, cancelationFlag);
 }
 
 /**
index fc8cd11..da16278 100644 (file)
@@ -30,7 +30,7 @@ static void (* s_fpSendTrap1)(UINT32, const TCHAR *, const char *, va_list) = NU
 static void (* s_fpSendTrap2)(UINT32, const TCHAR *, int, TCHAR **) = NULL;
 static AbstractCommSession *(* s_fpFindServerSession)(UINT64) = NULL;
 static bool (* s_fpEnumerateSessions)(EnumerationCallbackResult (*)(AbstractCommSession *, void *), void *) = NULL;
-static bool (* s_fpSendFile)(void *, UINT32, const TCHAR *, long, bool) = NULL;
+static bool (* s_fpSendFile)(void *, UINT32, const TCHAR *, long, bool, VolatileCounter *) = NULL;
 static bool (* s_fpPushData)(const TCHAR *, const TCHAR *, UINT32, time_t) = NULL;
 static CONDITION s_agentShutdownCondition = INVALID_CONDITION_HANDLE;
 static const TCHAR *s_dataDirectory = NULL;
@@ -44,7 +44,7 @@ void LIBNXAGENT_EXPORTABLE InitSubAgentAPI(void (* writeLog)(int, int, const TCH
                                            void (* sendTrap2)(UINT32, const TCHAR *, int, TCHAR **),
                                            bool (* enumerateSessions)(EnumerationCallbackResult (*)(AbstractCommSession *, void *), void*),
                                            AbstractCommSession *(* findServerSession)(UINT64),
-                                           bool (* sendFile)(void *, UINT32, const TCHAR *, long, bool),
+                                           bool (* sendFile)(void *, UINT32, const TCHAR *, long, bool, VolatileCounter *),
                                            bool (* pushData)(const TCHAR *, const TCHAR *, UINT32, time_t),
                                            DB_HANDLE (* getLocalDatabaseHandle)(),
                                            CONDITION shutdownCondition, const TCHAR *dataDirectory)
@@ -165,11 +165,11 @@ bool LIBNXAGENT_EXPORTABLE AgentEnumerateSessions(EnumerationCallbackResult (* c
 /**
  * Send file to server
  */
-bool LIBNXAGENT_EXPORTABLE AgentSendFileToServer(void *session, UINT32 requestId, const TCHAR *file, long offset, bool allowCompression)
+bool LIBNXAGENT_EXPORTABLE AgentSendFileToServer(void *session, UINT32 requestId, const TCHAR *file, long offset, bool allowCompression, VolatileCounter *cancelFlag)
 {
        if ((s_fpSendFile == NULL) || (session == NULL) || (file == NULL))
                return FALSE;
-       return s_fpSendFile(session, requestId, file, offset, allowCompression);
+       return s_fpSendFile(session, requestId, file, offset, allowCompression, cancelFlag);
 }
 
 /**
index fc5c8a4..4c853cd 100644 (file)
@@ -46,12 +46,14 @@ RootFolder::RootFolder(const TCHAR *folder)
  * Root folders
  */
 static ObjectArray<RootFolder> *g_rootFileManagerFolders;
+static HashMap<UINT32, VolatileCounter> *g_downloadFileStopMarkers;
 
 /**
  * Monitored file list
  */
 MonitoredFileList g_monitorFileList;
 
+
 #ifdef _WIN32
 
 /**
@@ -94,6 +96,7 @@ static void ConvertPathToNetwork(TCHAR *path)
 static BOOL SubagentInit(Config *config)
 {
    g_rootFileManagerFolders = new ObjectArray<RootFolder>(16, 16, true);
+   g_downloadFileStopMarkers = new HashMap<UINT32, VolatileCounter>();
    ConfigEntry *root = config->getEntry(_T("/filemgr/RootFolder"));
    if (root != NULL)
    {
@@ -114,6 +117,7 @@ static BOOL SubagentInit(Config *config)
 static void SubagentShutdown()
 {
    delete g_rootFileManagerFolders;
+   delete g_downloadFileStopMarkers;
 }
 
 #ifndef _WIN32
@@ -636,7 +640,7 @@ static BOOL MoveFile(TCHAR* oldName, TCHAR* newName)
 
    AgentWriteDebugLog(5, _T("CommSession::getLocalFile(): request for file \"%s\", follow = %s, compress = %s"),
                data->fileName, data->follow ? _T("true") : _T("false"), data->allowCompression ? _T("true") : _T("false"));
-   bool success = AgentSendFileToServer(data->session, data->id, data->fileName, (int)data->offset, data->allowCompression);
+   bool success = AgentSendFileToServer(data->session, data->id, data->fileName, (int)data->offset, data->allowCompression, g_downloadFileStopMarkers->get(data->id));
    if (data->follow && success)
    {
       g_monitorFileList.add(data->fileNameCode);
@@ -645,6 +649,7 @@ static BOOL MoveFile(TCHAR* oldName, TCHAR* newName)
    }
    free(data->fileName);
    free(data->fileNameCode);
+   g_downloadFileStopMarkers->remove(data->id);
    delete data;
    return THREAD_OK;
 }
@@ -935,6 +940,7 @@ static BOOL ProcessCommands(UINT32 command, NXCPMessage *request, NXCPMessage *r
             data->id = request->getId();
             data->offset = request->getFieldAsUInt32(VID_FILE_OFFSET);
             data->session = session;
+            g_downloadFileStopMarkers->set(request->getId(), new VolatileCounter(0));
 
             ThreadCreateEx(SendFile, 0, data);
 
@@ -946,6 +952,18 @@ static BOOL ProcessCommands(UINT32 command, NXCPMessage *request, NXCPMessage *r
          }
          return TRUE;
       }
+      case CMD_CANCEL_FILE_DOWNLOAD:
+      {
+         VolatileCounter *counter = g_downloadFileStopMarkers->get(request->getFieldAsUInt32(VID_REQUEST_ID));
+         if(counter != NULL)
+         {
+            InterlockedIncrement(counter);
+            response->setField(VID_RCC, ERR_SUCCESS);
+         }
+         else
+            response->setField(VID_RCC, ERR_INTERNAL_ERROR);
+         return TRUE;
+      }
       case CMD_CANCEL_FILE_MONITORING:
       {
          response->setId(request->getId());
index d3ebc02..3ebbbcc 100644 (file)
@@ -166,6 +166,7 @@ import org.netxms.client.server.AgentFile;
 import org.netxms.client.server.ServerConsoleListener;
 import org.netxms.client.server.ServerFile;
 import org.netxms.client.server.ServerJob;
+import org.netxms.client.server.ServerJobIdUpdater;
 import org.netxms.client.server.ServerVariable;
 import org.netxms.client.snmp.SnmpTrap;
 import org.netxms.client.snmp.SnmpTrapLogRecord;
@@ -8259,9 +8260,9 @@ public class NXCSession
     * @throws IOException  if socket or file I/O error occurs
     * @throws NXCException if NetXMS server returns an error or operation was timed out
     */
-   public AgentFileData downloadFileFromAgent(long nodeId, String remoteFileName, long maxFileSize, boolean follow, ProgressListener listener) throws IOException, NXCException
+   public AgentFileData downloadFileFromAgent(long nodeId, String remoteFileName, long maxFileSize, boolean follow, ProgressListener listener, ServerJobIdUpdater updateServerJobId) throws IOException, NXCException
    {
-      return downloadFileFromAgent(nodeId, remoteFileName, maxFileSize, follow, null, 0, listener);
+      return downloadFileFromAgent(nodeId, remoteFileName, maxFileSize, follow, null, 0, listener, updateServerJobId);
    }
    
    /**
@@ -8278,7 +8279,7 @@ public class NXCSession
     * @throws IOException  if socket or file I/O error occurs
     * @throws NXCException if NetXMS server returns an error or operation was timed out
     */
-   public AgentFileData downloadFileFromAgent(long nodeId, String remoteFileName, long maxFileSize, boolean follow, Map<String, String> inputValues, long alarmId, ProgressListener listener) throws IOException, NXCException
+   public AgentFileData downloadFileFromAgent(long nodeId, String remoteFileName, long maxFileSize, boolean follow, Map<String, String> inputValues, long alarmId, ProgressListener listener, ServerJobIdUpdater updateServerJobId) throws IOException, NXCException
    {
       final NXCPMessage msg = newMessage(NXCPCodes.CMD_GET_AGENT_FILE);
       msg.setFieldInt32(NXCPCodes.VID_OBJECT_ID, (int) nodeId);
@@ -8301,6 +8302,8 @@ public class NXCSession
       final NXCPMessage response = waitForRCC(msg.getMessageId()); // first confirmation - server job started
       final String id = response.getFieldAsString(NXCPCodes.VID_NAME);
       remoteFileName = response.getFieldAsString(NXCPCodes.VID_FILE_NAME);
+      if(updateServerJobId != null)
+         updateServerJobId.setJobIdCallback(response.getFieldAsInt32(NXCPCodes.VID_REQUEST_ID));
       if (listener != null)
       {
          final long fileSize = waitForRCC(msg.getMessageId()).getFieldAsInt64(NXCPCodes.VID_FILE_SIZE);
@@ -8315,7 +8318,7 @@ public class NXCSession
       if (remoteFile == null)
          throw new NXCException(RCC.AGENT_FILE_DOWNLOAD_ERROR);
       AgentFileData file =  new AgentFileData(id, remoteFileName, remoteFile);
-      
+
       try
       {
          waitForRCC(msg.getMessageId()); // second confirmation - file transfered from agent to console
diff --git a/src/client/java/netxms-client/src/main/java/org/netxms/client/server/ServerJobIdUpdater.java b/src/client/java/netxms-client/src/main/java/org/netxms/client/server/ServerJobIdUpdater.java
new file mode 100644 (file)
index 0000000..b3e11f5
--- /dev/null
@@ -0,0 +1,10 @@
+package org.netxms.client.server;
+
+public interface ServerJobIdUpdater
+{
+   /**
+    * Update Server Job Id in Console Job
+    * @param id server job id
+    */
+   public void setJobIdCallback(int id);
+}
diff --git a/src/java/netxms-eclipse/Core/src/org/netxms/ui/eclipse/jobs/ConsoleJobCallingServerJob.java b/src/java/netxms-eclipse/Core/src/org/netxms/ui/eclipse/jobs/ConsoleJobCallingServerJob.java
new file mode 100644 (file)
index 0000000..2b4b59e
--- /dev/null
@@ -0,0 +1,101 @@
+/**
+ * NetXMS - open source network management system
+ * Copyright (C) 2003-2015 Victor Kirhenshtein
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+package org.netxms.ui.eclipse.jobs;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.ui.IWorkbenchPart;
+import org.netxms.client.NXCSession;
+import org.netxms.client.server.ServerJobIdUpdater;
+import org.netxms.ui.eclipse.console.Activator;
+import org.netxms.ui.eclipse.shared.ConsoleSharedData;
+
+/**
+ * Tailored Job class for NetXMS console. Callers must call start() instead of schedule() for correct execution.
+ */
+public abstract class ConsoleJobCallingServerJob extends ConsoleJob implements ServerJobIdUpdater
+{
+   private NXCSession session = null;
+   private int serverJobId = 0;
+   private boolean jobCanceled = false;
+
+   public ConsoleJobCallingServerJob(String name, IWorkbenchPart wbPart, String pluginId, Object jobFamily)
+   {
+      super(name, wbPart, pluginId, jobFamily);
+      session = (NXCSession)ConsoleSharedData.getSession();
+   }
+
+   /*
+    * (non-Javadoc)
+    * 
+    * @see org.eclipse.core.runtime.jobs.Job#run(org.eclipse.core.runtime.IProgressMonitor)
+    */
+   @Override
+   protected IStatus run(IProgressMonitor monitor)
+   {
+      IStatus status;
+      try
+      {
+         runInternal(monitor);
+         status = Status.OK_STATUS;
+      }
+      catch(Exception e)
+      {
+         if(jobCanceled)
+         {
+            status = Status.CANCEL_STATUS;
+         }
+         else
+         {
+            Activator.logError("Exception in ConsoleJob", e); //$NON-NLS-1$
+            jobFailureHandler();
+            status = createFailureStatus(e);
+         }
+      }
+      finally
+      {
+         jobFinalize();
+      }
+      return status;
+   }
+
+   /* (non-Javadoc)
+    * @see org.eclipse.core.runtime.jobs.Job#canceling()
+    */
+   @Override
+   protected void canceling()
+   {
+      jobCanceled = true;
+      try
+      {
+         session.cancelServerJob(serverJobId);
+      }
+      catch(Exception e)
+      {
+         Activator.logError("Failed to cancel job", e); //$NON-NLS-1$
+      }
+      super.canceling();
+   }
+   public void setJobIdCallback(int id)
+   {
+      serverJobId = id;
+   }
+}
index f01152f..f8bea6b 100644 (file)
@@ -98,6 +98,7 @@ import org.netxms.ui.eclipse.filemanager.views.helpers.AgentFileFilter;
 import org.netxms.ui.eclipse.filemanager.views.helpers.AgentFileLabelProvider;
 import org.netxms.ui.eclipse.filemanager.views.helpers.ViewAgentFilesProvider;
 import org.netxms.ui.eclipse.jobs.ConsoleJob;
+import org.netxms.ui.eclipse.jobs.ConsoleJobCallingServerJob;
 import org.netxms.ui.eclipse.shared.ConsoleSharedData;
 import org.netxms.ui.eclipse.tools.DialogData;
 import org.netxms.ui.eclipse.tools.MessageDialogHelper;
@@ -1133,7 +1134,7 @@ public class AgentFileManager extends ViewPart
 
       final AgentFile sf = ((AgentFile)objects[0]);
 
-      ConsoleJob job = new ConsoleJob(Messages.get().AgentFileManager_DownloadJobTitle, null, Activator.PLUGIN_ID, null) {
+      ConsoleJobCallingServerJob job = new ConsoleJobCallingServerJob(Messages.get().AgentFileManager_DownloadJobTitle, null, Activator.PLUGIN_ID, null) {
          @Override
          protected String getErrorMessage()
          {
@@ -1143,7 +1144,7 @@ public class AgentFileManager extends ViewPart
          @Override
          protected void runInternal(final IProgressMonitor monitor) throws Exception
          {
-            final AgentFileData file = session.downloadFileFromAgent(objectId, sf.getFullName(), offset, followChanges, null);
+            final AgentFileData file = session.downloadFileFromAgent(objectId, sf.getFullName(), offset, followChanges, null, this);
             runInUIThread(new Runnable() {
                @Override
                public void run()
@@ -1204,7 +1205,7 @@ public class AgentFileManager extends ViewPart
       for(Object o : selection.toList())
          files.add((AgentFile)o);
       
-      ConsoleJob job = new ConsoleJob("Download from agent", null, Activator.PLUGIN_ID, null) {
+      ConsoleJobCallingServerJob job = new ConsoleJobCallingServerJob("Download from agent", null, Activator.PLUGIN_ID, null) {
          @Override
          protected void runInternal(IProgressMonitor monitor) throws Exception
          {
@@ -1222,12 +1223,12 @@ public class AgentFileManager extends ViewPart
                   {
                   }
                   monitor.beginTask(String.format("Downloading directory %s", f.getName()), (dirSize >= 0) ? (int)dirSize : IProgressMonitor.UNKNOWN);
-                  downloadDir(f, target + "/" + f.getName(), monitor);
+                  downloadDir(f, target + "/" + f.getName(), monitor, this);
                   monitor.done();
                }
                else
                {
-                  downloadFile(f, target, monitor, false);
+                  downloadFile(f, target, monitor, false, this);
                }
             }
             else
@@ -1256,11 +1257,11 @@ public class AgentFileManager extends ViewPart
                {
                   if (f.isDirectory())
                   {
-                     downloadDir(f, target + "/" + f.getName(), monitor);
+                     downloadDir(f, target + "/" + f.getName(), monitor, this);
                   }
                   else
                   {
-                     downloadFile(f, target + "/" + f.getName(), monitor, true);
+                     downloadFile(f, target + "/" + f.getName(), monitor, true, this);
                   }
                }
                monitor.done();
@@ -1281,10 +1282,11 @@ public class AgentFileManager extends ViewPart
     * 
     * @param sf
     * @param localFileName
+    * @param job 
     * @throws IOException 
     * @throws NXCException 
     */
-   private void downloadDir(final AgentFile sf, String localFileName, final IProgressMonitor monitor) throws NXCException, IOException
+   private void downloadDir(final AgentFile sf, String localFileName, final IProgressMonitor monitor, ConsoleJobCallingServerJob job) throws NXCException, IOException
    {
       File dir = new File(localFileName);
       dir.mkdir();
@@ -1298,11 +1300,11 @@ public class AgentFileManager extends ViewPart
       {
          if (f.isDirectory())
          {
-            downloadDir(f, localFileName + "/" + f.getName(), monitor); //$NON-NLS-1$
+            downloadDir(f, localFileName + "/" + f.getName(), monitor, job); //$NON-NLS-1$
          }
          else
          {
-            downloadFile(f, localFileName + "/" + f.getName(), monitor, true); //$NON-NLS-1$
+            downloadFile(f, localFileName + "/" + f.getName(), monitor, true, job); //$NON-NLS-1$
          }
       }
       dir.setLastModified(sf.getModifyicationTime().getTime());
@@ -1313,7 +1315,7 @@ public class AgentFileManager extends ViewPart
     * @throws NXCException 
     * @throws IOException 
     */
-   private void downloadFile(final AgentFile sf, final String localName, final IProgressMonitor monitor, final boolean subTask) throws IOException, NXCException
+   private void downloadFile(final AgentFile sf, final String localName, final IProgressMonitor monitor, final boolean subTask, ConsoleJobCallingServerJob job) throws IOException, NXCException
    {
       if (subTask)
          monitor.subTask(String.format("Downloading file %s", sf.getFullName()));
@@ -1330,7 +1332,7 @@ public class AgentFileManager extends ViewPart
          {
             monitor.worked((int)workDone);
          }
-      });
+      }, job);
       File outputFile = new File(localName);
       outputFile.createNewFile();
       InputStream in = new FileInputStream(file.getFile());
index 3f63969..fbb5931 100644 (file)
@@ -31,6 +31,7 @@ import org.netxms.client.SessionNotification;
 import org.netxms.ui.eclipse.filemanager.Activator;
 import org.netxms.ui.eclipse.filemanager.Messages;
 import org.netxms.ui.eclipse.jobs.ConsoleJob;
+import org.netxms.ui.eclipse.jobs.ConsoleJobCallingServerJob;
 import org.netxms.ui.eclipse.shared.ConsoleSharedData;
 
 /**
@@ -189,7 +190,7 @@ public class DynamicFileViewer extends BaseFileViewer
                   "\n----------------------------------------------------------------------\n"); //$NON-NLS-1$
       showMessage(ERROR, Messages.get().FileViewer_NotifyFollowConnectionLost);
       
-      restartJob = new ConsoleJob(Messages.get().DynamicFileViewer_RestartFileTracking, null, Activator.PLUGIN_ID, null) {
+      restartJob = new ConsoleJobCallingServerJob(Messages.get().DynamicFileViewer_RestartFileTracking, null, Activator.PLUGIN_ID, null) {
          private boolean running = true;
 
          @Override
@@ -218,7 +219,7 @@ public class DynamicFileViewer extends BaseFileViewer
                      {
                         monitor.worked((int)workDone);
                      }
-                  });
+                  }, this);
 
                   // When successfully connected - display notification to client.
                   runInUIThread(new Runnable() {
index 8189ab3..46831f4 100644 (file)
@@ -42,6 +42,7 @@ import org.netxms.client.objecttools.InputFieldType;
 import org.netxms.client.objecttools.ObjectTool;
 import org.netxms.ui.eclipse.filemanager.views.AgentFileViewer;
 import org.netxms.ui.eclipse.jobs.ConsoleJob;
+import org.netxms.ui.eclipse.jobs.ConsoleJobCallingServerJob;
 import org.netxms.ui.eclipse.objects.ObjectContext;
 import org.netxms.ui.eclipse.objecttools.Activator;
 import org.netxms.ui.eclipse.objecttools.Messages;
@@ -558,7 +559,7 @@ public final class ObjectToolExecutor
       final int maxFileSize = Integer.parseInt(parameters[1]);
       final boolean follow = parameters[2].equals("true") ? true : false; //$NON-NLS-1$
       
-      ConsoleJob job = new ConsoleJob(Messages.get().ObjectToolsDynamicMenu_DownloadFromAgent, null, Activator.PLUGIN_ID, null) {
+      ConsoleJobCallingServerJob job = new ConsoleJobCallingServerJob(Messages.get().ObjectToolsDynamicMenu_DownloadFromAgent, null, Activator.PLUGIN_ID, null) {
          @Override
          protected String getErrorMessage()
          {
@@ -580,7 +581,7 @@ public final class ObjectToolExecutor
                {
                   monitor.worked((int)workDone);
                }
-            });
+            }, this);
             runInUIThread(new Runnable() {
                @Override
                public void run()
index 5454f47..5554230 100644 (file)
@@ -395,10 +395,13 @@ TCHAR LIBNETXMS_EXPORTABLE *NXCPMessageCodeName(WORD code, TCHAR *pszBuffer)
       _T("CMD_RESTART"),
       _T("CMD_REGISTER_LORAWAN_SENSOR"),
       _T("CMD_UNREGISTER_LORAWAN_SENSOR"),
-      _T("CMD_EXPAND_MACROS")
+      _T("CMD_EXPAND_MACROS"),
+      _T("CMD_EXECUTE_ACTION_WITH_EXPANSION"),
+      _T("CMD_HOST_BY_IP"),
+      _T("CMD_CANCEL_FILE_DOWNLOAD")
    };
 
-   if ((code >= CMD_LOGIN) && (code <= CMD_EXPAND_MACROS))
+   if ((code >= CMD_LOGIN) && (code <= CMD_CANCEL_FILE_DOWNLOAD))
    {
       _tcscpy(pszBuffer, pszMsgNames[code - CMD_LOGIN]);
    }
@@ -718,7 +721,7 @@ bool LIBNETXMS_EXPORTABLE SendFileOverNXCP(SOCKET hSocket, UINT32 id, const TCHA
                                            MUTEX mutex, NXCPStreamCompressionMethod compressionMethod)
 {
    SocketCommChannel *ch = new SocketCommChannel(hSocket, false);
-   bool result = SendFileOverNXCP(ch, id, pszFile, pCtx, offset, progressCallback, cbArg, mutex, compressionMethod);
+   bool result = SendFileOverNXCP(ch, id, pszFile, pCtx, offset, progressCallback, cbArg, mutex, compressionMethod, NULL);
    ch->decRefCount();
    return result;
 }
@@ -729,7 +732,8 @@ bool LIBNETXMS_EXPORTABLE SendFileOverNXCP(SOCKET hSocket, UINT32 id, const TCHA
 bool LIBNETXMS_EXPORTABLE SendFileOverNXCP(AbstractCommChannel *channel, UINT32 id, const TCHAR *pszFile,
                                            NXCPEncryptionContext *pCtx, long offset,
                                                                                                                 void (* progressCallback)(INT64, void *), void *cbArg,
-                                                                                                                MUTEX mutex, NXCPStreamCompressionMethod compressionMethod)
+                                                                                                                MUTEX mutex, NXCPStreamCompressionMethod compressionMethod,
+                                                                                                                VolatileCounter *cancelationFlag)
 {
    int hFile, iBytes;
        INT64 bytesTransferred = 0;
@@ -761,6 +765,9 @@ bool LIBNETXMS_EXPORTABLE SendFileOverNXCP(AbstractCommChannel *channel, UINT32
 
                        while(true)
                        {
+                          if(cancelationFlag != NULL && (*cancelationFlag) > 0)
+                             break;
+
             if (compressor != NULL)
             {
                                   iBytes = _read(hFile, compBuffer, MIN(FILE_BUFFER_SIZE, bytesToRead));
index e22c7a8..0cc3a05 100644 (file)
@@ -175,7 +175,7 @@ ServerJobResult FileDownloadJob::run()
                                        {
                                                success = JOB_RESULT_SUCCESS;
                                        }
-                                       else
+                                       else if(getStatus() != JOB_CANCELLED && getStatus() != JOB_CANCEL_PENDING)
                                        {
                                                TCHAR buffer[1024];
 
@@ -265,8 +265,7 @@ ServerJobResult FileDownloadJob::run()
  */
 bool FileDownloadJob::onCancel()
 {
-   if (m_agentConnection != NULL)
-      m_agentConnection->disconnect();
+   m_agentConnection->cancelFileDownload();
        return true;
 }
 
index 70ec039..6b8c683 100644 (file)
@@ -10503,6 +10503,7 @@ void ClientSession::getAgentFile(NXCPMessage *request)
                                FileDownloadJob *job = new FileDownloadJob((Node *)object, result,
                                         request->getFieldAsUInt32(VID_FILE_SIZE_LIMIT), follow, this, request->getId());
                                msg.setField(VID_NAME, job->getLocalFileName());
+            msg.setField(VID_REQUEST_ID, job->getId());
                                msg.setField(VID_FILE_NAME, result);
                                free(result);
                                delete alarm;
index 3758360..5d8a8a5 100644 (file)
@@ -603,6 +603,7 @@ public:
    void setPort(WORD wPort) { m_wPort = wPort; }
    void setAuthData(int method, const TCHAR *secret);
    void setDeleteFileOnDownloadFailure(bool flag) { m_deleteFileOnDownloadFailure = flag; }
+   bool cancelFileDownload();
 };
 
 /**
index bb80e79..82e8b51 100644 (file)
@@ -2112,6 +2112,31 @@ NXCPMessage *AgentConnection::customRequest(NXCPMessage *pRequest, const TCHAR *
 }
 
 /**
+ * Send custom request to agent
+ */
+bool AgentConnection::cancelFileDownload()
+{
+   UINT32 dwRqId, rcc;
+   NXCPMessage msg(getProtocolVersion());
+   dwRqId = generateRequestId();
+   msg.setId(dwRqId);
+   msg.setCode(CMD_CANCEL_FILE_DOWNLOAD);
+   msg.setField(VID_REQUEST_ID, m_dwDownloadRequestId);
+   bool success = false;
+
+   if (sendMessage(&msg))
+   {
+      NXCPMessage *result = waitForMessage(CMD_REQUEST_COMPLETED, dwRqId, m_dwCommandTimeout);
+      if(result != NULL && result->getFieldAsUInt32(VID_RCC) == ERR_SUCCESS)
+      {
+         success = true;
+      }
+      delete result;
+   }
+   return success;
+}
+
+/**
  * Prepare for file download
  */
 UINT32 AgentConnection::prepareFileDownload(const TCHAR *fileName, UINT32 rqId, bool append, void (*downloadProgressCallback)(size_t, void *),
diff --git a/webui/webapp/Core/src/org/netxms/ui/eclipse/jobs/ConsoleJobCallingServerJob.java b/webui/webapp/Core/src/org/netxms/ui/eclipse/jobs/ConsoleJobCallingServerJob.java
new file mode 100644 (file)
index 0000000..2b4b59e
--- /dev/null
@@ -0,0 +1,101 @@
+/**
+ * NetXMS - open source network management system
+ * Copyright (C) 2003-2015 Victor Kirhenshtein
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+package org.netxms.ui.eclipse.jobs;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.ui.IWorkbenchPart;
+import org.netxms.client.NXCSession;
+import org.netxms.client.server.ServerJobIdUpdater;
+import org.netxms.ui.eclipse.console.Activator;
+import org.netxms.ui.eclipse.shared.ConsoleSharedData;
+
+/**
+ * Tailored Job class for NetXMS console. Callers must call start() instead of schedule() for correct execution.
+ */
+public abstract class ConsoleJobCallingServerJob extends ConsoleJob implements ServerJobIdUpdater
+{
+   private NXCSession session = null;
+   private int serverJobId = 0;
+   private boolean jobCanceled = false;
+
+   public ConsoleJobCallingServerJob(String name, IWorkbenchPart wbPart, String pluginId, Object jobFamily)
+   {
+      super(name, wbPart, pluginId, jobFamily);
+      session = (NXCSession)ConsoleSharedData.getSession();
+   }
+
+   /*
+    * (non-Javadoc)
+    * 
+    * @see org.eclipse.core.runtime.jobs.Job#run(org.eclipse.core.runtime.IProgressMonitor)
+    */
+   @Override
+   protected IStatus run(IProgressMonitor monitor)
+   {
+      IStatus status;
+      try
+      {
+         runInternal(monitor);
+         status = Status.OK_STATUS;
+      }
+      catch(Exception e)
+      {
+         if(jobCanceled)
+         {
+            status = Status.CANCEL_STATUS;
+         }
+         else
+         {
+            Activator.logError("Exception in ConsoleJob", e); //$NON-NLS-1$
+            jobFailureHandler();
+            status = createFailureStatus(e);
+         }
+      }
+      finally
+      {
+         jobFinalize();
+      }
+      return status;
+   }
+
+   /* (non-Javadoc)
+    * @see org.eclipse.core.runtime.jobs.Job#canceling()
+    */
+   @Override
+   protected void canceling()
+   {
+      jobCanceled = true;
+      try
+      {
+         session.cancelServerJob(serverJobId);
+      }
+      catch(Exception e)
+      {
+         Activator.logError("Failed to cancel job", e); //$NON-NLS-1$
+      }
+      super.canceling();
+   }
+   public void setJobIdCallback(int id)
+   {
+      serverJobId = id;
+   }
+}
index 183154c..94a6c52 100644 (file)
@@ -97,6 +97,7 @@ import org.netxms.ui.eclipse.filemanager.views.helpers.AgentFileFilter;
 import org.netxms.ui.eclipse.filemanager.views.helpers.AgentFileLabelProvider;
 import org.netxms.ui.eclipse.filemanager.views.helpers.ViewAgentFilesProvider;
 import org.netxms.ui.eclipse.jobs.ConsoleJob;
+import org.netxms.ui.eclipse.jobs.ConsoleJobCallingServerJob;
 import org.netxms.ui.eclipse.shared.ConsoleSharedData;
 import org.netxms.ui.eclipse.tools.DialogData;
 import org.netxms.ui.eclipse.tools.MessageDialogHelper;
@@ -950,7 +951,7 @@ public class AgentFileManager extends ViewPart
 
       final AgentFile sf = ((AgentFile)objects[0]);
 
-      ConsoleJob job = new ConsoleJob(Messages.get().AgentFileManager_DownloadJobTitle, null, Activator.PLUGIN_ID, null) {
+      ConsoleJobCallingServerJob job = new ConsoleJobCallingServerJob(Messages.get().AgentFileManager_DownloadJobTitle, null, Activator.PLUGIN_ID, null) {
          @Override
          protected String getErrorMessage()
          {
@@ -972,7 +973,7 @@ public class AgentFileManager extends ViewPart
                {
                   monitor.worked((int)workDone);
                }
-            });
+            }, this);
             runInUIThread(new Runnable() {
                @Override
                public void run()
@@ -1012,7 +1013,7 @@ public class AgentFileManager extends ViewPart
       }
       else
       {      
-         ConsoleJob job = new ConsoleJob("Download from agent", null, Activator.PLUGIN_ID, null) {
+         ConsoleJobCallingServerJob job = new ConsoleJobCallingServerJob("Download from agent", null, Activator.PLUGIN_ID, null) {
             @Override
             protected void runInternal(final IProgressMonitor monitor) throws Exception
             {
@@ -1030,7 +1031,7 @@ public class AgentFileManager extends ViewPart
                final File zipFile = File.createTempFile("download_", ".zip");
                FileOutputStream fos = new FileOutputStream(zipFile);
                ZipOutputStream zos = new ZipOutputStream(fos);
-               downloadDir(sf, sf.getName(), zos, monitor);
+               downloadDir(sf, sf.getName(), zos, monitor, this);
                zos.close();
                fos.close();
                
@@ -1064,7 +1065,7 @@ public class AgentFileManager extends ViewPart
     * @throws IOException 
     * @throws NXCException 
     */
-   private void downloadDir(final AgentFile sf, String localFileName, ZipOutputStream zos, final IProgressMonitor monitor) throws NXCException, IOException
+   private void downloadDir(final AgentFile sf, String localFileName, ZipOutputStream zos, final IProgressMonitor monitor, ConsoleJobCallingServerJob job) throws NXCException, IOException
    {
       List<AgentFile> files = sf.getChildren();
       if (files == null)
@@ -1076,7 +1077,7 @@ public class AgentFileManager extends ViewPart
       {
          if (f.isDirectory())
          {
-            downloadDir(f, localFileName + "/" + f.getName(), zos, monitor);
+            downloadDir(f, localFileName + "/" + f.getName(), zos, monitor, job);
          }
          else
          {
@@ -1091,7 +1092,7 @@ public class AgentFileManager extends ViewPart
                {
                   monitor.worked((int)workDone);
                }
-            });
+            }, job);
             
                        FileInputStream fis = new FileInputStream(file.getFile());
                        ZipEntry zipEntry = new ZipEntry(localFileName + "/" + f.getName());
@@ -1115,7 +1116,7 @@ public class AgentFileManager extends ViewPart
     */
    private void downloadFile(final String remoteName)
    {
-      ConsoleJob job = new ConsoleJob(Messages.get().SelectServerFileDialog_JobTitle, null, Activator.PLUGIN_ID, null) {
+          ConsoleJobCallingServerJob job = new ConsoleJobCallingServerJob(Messages.get().SelectServerFileDialog_JobTitle, null, Activator.PLUGIN_ID, null) {
          @Override
          protected void runInternal(final IProgressMonitor monitor) throws Exception
          {
@@ -1131,7 +1132,7 @@ public class AgentFileManager extends ViewPart
                {
                   monitor.worked((int)workDone);
                }
-            });
+            }, this);
             
             DownloadServiceHandler.addDownload(file.getFile().getName(), remoteName, file.getFile(), "application/octet-stream");
             runInUIThread(new Runnable() {
index a69c187..910536e 100644 (file)
@@ -31,6 +31,7 @@ import org.netxms.client.SessionNotification;
 import org.netxms.ui.eclipse.filemanager.Activator;
 import org.netxms.ui.eclipse.filemanager.Messages;
 import org.netxms.ui.eclipse.jobs.ConsoleJob;
+import org.netxms.ui.eclipse.jobs.ConsoleJobCallingServerJob;
 import org.netxms.ui.eclipse.shared.ConsoleSharedData;
 
 /**
@@ -191,7 +192,7 @@ public class DynamicFileViewer extends BaseFileViewer
                   "\n----------------------------------------------------------------------\n"); //$NON-NLS-1$
       showMessage(ERROR, Messages.get().FileViewer_NotifyFollowConnectionLost);
       
-      restartJob = new ConsoleJob(Messages.get().DynamicFileViewer_RestartFileTracking, null, Activator.PLUGIN_ID, null) {
+      restartJob = new ConsoleJobCallingServerJob(Messages.get().DynamicFileViewer_RestartFileTracking, null, Activator.PLUGIN_ID, null) {
          private boolean running = true;
 
          @Override
@@ -212,7 +213,7 @@ public class DynamicFileViewer extends BaseFileViewer
                      @Override
                      public void setTotalWorkAmount(long workTotal)
                      {
-                        monitor.beginTask("Download file " + remoteFileName, (int)workTotal);
+                        monitor.beginTask("Track file " + remoteFileName, (int)workTotal);
                      }
 
                      @Override
@@ -220,7 +221,7 @@ public class DynamicFileViewer extends BaseFileViewer
                      {
                         monitor.worked((int)workDone);
                      }
-                  });
+                  }, this);
 
                   // When successfully connected - display notification to client.
                   runInUIThread(new Runnable() {
index e535954..27495ac 100644 (file)
@@ -42,6 +42,7 @@ import org.netxms.client.objecttools.InputFieldType;
 import org.netxms.client.objecttools.ObjectTool;
 import org.netxms.ui.eclipse.filemanager.views.AgentFileViewer;
 import org.netxms.ui.eclipse.jobs.ConsoleJob;
+import org.netxms.ui.eclipse.jobs.ConsoleJobCallingServerJob;
 import org.netxms.ui.eclipse.objects.ObjectContext;
 import org.netxms.ui.eclipse.objecttools.Activator;
 import org.netxms.ui.eclipse.objecttools.Messages;
@@ -507,7 +508,7 @@ public final class ObjectToolExecutor
       final int maxFileSize = Integer.parseInt(parameters[1]);
       final boolean follow = parameters[2].equals("true") ? true : false; //$NON-NLS-1$
       
-      ConsoleJob job = new ConsoleJob(Messages.get().ObjectToolsDynamicMenu_DownloadFromAgent, null, Activator.PLUGIN_ID, null) {
+      ConsoleJobCallingServerJob job = new ConsoleJobCallingServerJob(Messages.get().ObjectToolsDynamicMenu_DownloadFromAgent, null, Activator.PLUGIN_ID, null) {
          @Override
          protected String getErrorMessage()
          {
@@ -529,7 +530,7 @@ public final class ObjectToolExecutor
                {
                   monitor.worked((int)workDone);
                }
-            });
+            }, this);
             runInUIThread(new Runnable() {
                @Override
                public void run()
index 91cfbb1..72ae6d7 100644 (file)
@@ -298,7 +298,7 @@ public class ServerJobManager extends ViewPart
         */
        private void refreshJobList(boolean userInitiated)
        {
-               ConsoleJob job = new ConsoleJob(Messages.get().ServerJobManager_RefreshJobName, this, Activator.PLUGIN_ID, JOB_FAMILY) {
+               ConsoleJob job = new ConsoleJob(Messages.get(viewer.getControl().getDisplay()).ServerJobManager_RefreshJobName, this, Activator.PLUGIN_ID, JOB_FAMILY, viewer.getControl().getDisplay()) {
                        @Override
                        protected void runInternal(IProgressMonitor monitor) throws Exception
                        {