"alarm details" view mostly working; event history for active alarms preserved; minor...
authorVictor Kirhenshtein <victor@netxms.org>
Sun, 16 Dec 2012 00:16:47 +0000 (00:16 +0000)
committerVictor Kirhenshtein <victor@netxms.org>
Sun, 16 Dec 2012 00:16:47 +0000 (00:16 +0000)
26 files changed:
.gitattributes
include/netxmsdb.h
include/nms_cscp.h
sql/schema.in
src/java/netxms-base/src/main/java/org/netxms/base/EncryptionContext.java
src/java/netxms-base/src/main/java/org/netxms/base/NXCPCodes.java
src/java/netxms-client/src/main/java/org/netxms/client/NXCSession.java
src/java/netxms-client/src/main/java/org/netxms/client/events/EventInfo.java [new file with mode: 0644]
src/java/netxms-client/src/test/java/org/netxms/client/AlarmTest.java
src/java/netxms-eclipse/AlarmViewer/META-INF/MANIFEST.MF
src/java/netxms-eclipse/AlarmViewer/src/org/netxms/ui/eclipse/alarmviewer/views/AlarmDetails.java
src/java/netxms-eclipse/AlarmViewer/src/org/netxms/ui/eclipse/alarmviewer/views/helpers/EventTreeContentProvider.java [new file with mode: 0644]
src/java/netxms-eclipse/AlarmViewer/src/org/netxms/ui/eclipse/alarmviewer/views/helpers/EventTreeLabelProvider.java [new file with mode: 0644]
src/java/netxms-eclipse/AlarmViewer/src/org/netxms/ui/eclipse/alarmviewer/widgets/AlarmList.java
src/java/netxms-eclipse/AlarmViewer/src/org/netxms/ui/eclipse/alarmviewer/widgets/helpers/AlarmComparator.java [moved from src/java/netxms-eclipse/AlarmViewer/src/org/netxms/ui/eclipse/alarmviewer/AlarmComparator.java with 73% similarity]
src/java/netxms-eclipse/AlarmViewer/src/org/netxms/ui/eclipse/alarmviewer/widgets/helpers/AlarmListFilter.java [moved from src/java/netxms-eclipse/AlarmViewer/src/org/netxms/ui/eclipse/alarmviewer/AlarmListFilter.java with 92% similarity]
src/java/netxms-eclipse/AlarmViewer/src/org/netxms/ui/eclipse/alarmviewer/widgets/helpers/AlarmListLabelProvider.java [moved from src/java/netxms-eclipse/AlarmViewer/src/org/netxms/ui/eclipse/alarmviewer/AlarmListLabelProvider.java with 88% similarity]
src/libnetxms/crypto.cpp
src/libnetxms/main.cpp
src/libnetxms/nxcp.cpp
src/server/core/alarm.cpp
src/server/core/client.cpp
src/server/core/session.cpp
src/server/include/nms_alarm.h
src/server/include/nms_core.h
src/server/tools/nxdbmgr/upgrade.cpp

index a111907..63c51c5 100644 (file)
@@ -959,10 +959,7 @@ src/java/netxms-eclipse/AlarmViewer/icons/terminated.png -text
 src/java/netxms-eclipse/AlarmViewer/icons/user.png -text
 src/java/netxms-eclipse/AlarmViewer/plugin.xml -text
 src/java/netxms-eclipse/AlarmViewer/src/org/netxms/ui/eclipse/alarmviewer/Activator.java -text
-src/java/netxms-eclipse/AlarmViewer/src/org/netxms/ui/eclipse/alarmviewer/AlarmComparator.java -text
 src/java/netxms-eclipse/AlarmViewer/src/org/netxms/ui/eclipse/alarmviewer/AlarmDetailsProvider.java -text
-src/java/netxms-eclipse/AlarmViewer/src/org/netxms/ui/eclipse/alarmviewer/AlarmListFilter.java -text
-src/java/netxms-eclipse/AlarmViewer/src/org/netxms/ui/eclipse/alarmviewer/AlarmListLabelProvider.java -text
 src/java/netxms-eclipse/AlarmViewer/src/org/netxms/ui/eclipse/alarmviewer/AlarmNotifier.java -text
 src/java/netxms-eclipse/AlarmViewer/src/org/netxms/ui/eclipse/alarmviewer/LoginListener.java -text
 src/java/netxms-eclipse/AlarmViewer/src/org/netxms/ui/eclipse/alarmviewer/Messages.java -text
index 8bb545e..cad7c0b 100644 (file)
@@ -23,6 +23,6 @@
 #ifndef _netxmsdb_h
 #define _netxmsdb_h
 
-#define DB_FORMAT_VERSION   264
+#define DB_FORMAT_VERSION   265
 
 #endif
index f6b2117..eed7542 100644 (file)
 #ifndef _nms_cscp_h_
 #define _nms_cscp_h_
 
-
-//
-// Constants
-//
-
+/**
+ * Constants
+ */
 #define NXCP_VERSION                   2
 
 #define SERVER_LISTEN_PORT_FOR_CLIENTS 4701
@@ -456,6 +454,7 @@ typedef struct
 #define CMD_FIND_IP_LOCATION           0x0108
 #define CMD_REPORT_DEVICE_STATUS       0x0109
 #define CMD_REPORT_DEVICE_INFO         0x010A
+#define CMD_GET_ALARM_EVENTS           0x010B
 
 /**
  * Variable identifiers
index c3bceb1..32662e2 100644 (file)
@@ -907,6 +907,26 @@ CREATE INDEX idx_alarm_notes_alarm_id ON alarm_notes(alarm_id);
 
 
 /*
+** Source events for alarms
+*/
+
+CREATE TABLE alarm_events
+(
+       alarm_id integer not null,
+       event_id SQL_INT64 not null,
+       event_code integer not null,
+       event_name varchar(63) null,
+       severity integer not null,
+       source_object_id integer not null,
+       event_timestamp integer not null,
+       message varchar(255) null,
+       PRIMARY KEY(alarm_id,event_id)
+) TABLE_TYPE;
+
+CREATE INDEX idx_alarm_events_alarm_id ON alarm_events(alarm_id);
+
+
+/*
 ** SNMP trap configuration
 */
 
index f28511d..dcea117 100644 (file)
@@ -74,6 +74,9 @@ public final class EncryptionContext
                                        selectedCipher = i;\r
                                        break;\r
                                }\r
+                               else\r
+                               {\r
+                               }\r
                        }\r
                        catch(Exception e)\r
                        {\r
index c6257a0..6931446 100644 (file)
@@ -290,6 +290,7 @@ public final class NXCPCodes
        public static final int CMD_FIND_IP_LOCATION         = 0x0108;\r
        public static final int CMD_REPORT_DEVICE_STATUS     = 0x0109;\r
        public static final int CMD_REPORT_DEVICE_INFO       = 0x010A;\r
+       public static final int CMD_GET_ALARM_EVENTS         = 0x010B;\r
 \r
        // Variable codes\r
        public static final long VID_LOGIN_NAME              = 1;\r
index 57906fb..2089abb 100644 (file)
@@ -87,6 +87,7 @@ import org.netxms.client.datacollection.ThresholdViolationSummary;
 import org.netxms.client.events.Alarm;\r
 import org.netxms.client.events.AlarmNote;\r
 import org.netxms.client.events.Event;\r
+import org.netxms.client.events.EventInfo;\r
 import org.netxms.client.events.EventProcessingPolicy;\r
 import org.netxms.client.events.EventProcessingPolicyRule;\r
 import org.netxms.client.events.EventTemplate;\r
@@ -211,6 +212,7 @@ public class NXCSession implements Session, ScriptLibraryManager, UserManager, S
        private int clientType = DESKTOP_CLIENT;\r
 \r
        // Information about logged in user\r
+       private int sessionId;\r
        private int userId;\r
        private int userSystemRights;\r
        private boolean passwordExpired;\r
@@ -1413,6 +1415,7 @@ public class NXCSession implements Session, ScriptLibraryManager, UserManager, S
                                throw new NXCException(rcc);\r
                        }\r
                        userId = response.getVariableAsInteger(NXCPCodes.VID_USER_ID);\r
+                       sessionId = response.getVariableAsInteger(NXCPCodes.VID_SESSION_ID);\r
                        userSystemRights = response.getVariableAsInteger(NXCPCodes.VID_USER_SYS_RIGHTS);\r
                        passwordExpired = response.getVariableAsBoolean(NXCPCodes.VID_CHANGE_PASSWD_FLAG);\r
                        zoningEnabled = response.getVariableAsBoolean(NXCPCodes.VID_ZONING_ENABLED);\r
@@ -2062,6 +2065,44 @@ public class NXCSession implements Session, ScriptLibraryManager, UserManager, S
        }\r
 \r
        /**\r
+        * Get information about events related to single active alarm. Information for terminated alarms cannot be accessed with this call.\r
+        * User must have "view alarms" permission on alarm's source node and "view event log" system-wide access.\r
+        * \r
+        * @param alarmId alarm ID\r
+        * @return list of related events\r
+        * @throws IOException if socket I/O error occurs\r
+        * @throws NXCException if NetXMS server returns an error or operation was timed out\r
+        */\r
+       public List<EventInfo> getAlarmEvents(long alarmId) throws IOException, NXCException\r
+       {\r
+               NXCPMessage msg = newMessage(NXCPCodes.CMD_GET_ALARM_EVENTS);\r
+               msg.setVariableInt32(NXCPCodes.VID_ALARM_ID, (int)alarmId);\r
+               sendMessage(msg);\r
+               final NXCPMessage response = waitForRCC(msg.getMessageId());\r
+               \r
+               int count = response.getVariableAsInteger(NXCPCodes.VID_NUM_ELEMENTS);\r
+               List<EventInfo> list = new ArrayList<EventInfo>(count);\r
+               long varId = NXCPCodes.VID_ELEMENT_LIST_BASE;\r
+               for(int i = 0; i < count; i++)\r
+               {\r
+                       EventInfo parent = null;\r
+                       long rootId = response.getVariableAsInt64(varId + 1);\r
+                       if (rootId != 0)\r
+                       {\r
+                               for(EventInfo e : list)\r
+                                       if (e.getId() == rootId)\r
+                                       {\r
+                                               parent = e;\r
+                                               break;\r
+                                       }\r
+                       }\r
+                       list.add(new EventInfo(response, varId, parent));\r
+                       varId += 10;\r
+               }\r
+               return list;\r
+       }\r
+\r
+       /**\r
         * Acknowledge alarm.\r
         * \r
         * @param alarmId Identifier of alarm to be acknowledged.\r
@@ -6242,4 +6283,14 @@ public class NXCSession implements Session, ScriptLibraryManager, UserManager, S
                        o.setSession(target);\r
                objectList = null;\r
        }\r
+\r
+       /**\r
+        * Get this session's ID on server.\r
+        *  \r
+        * @return the sessionId\r
+        */\r
+       public int getSessionId()\r
+       {\r
+               return sessionId;\r
+       }\r
 }\r
diff --git a/src/java/netxms-client/src/main/java/org/netxms/client/events/EventInfo.java b/src/java/netxms-client/src/main/java/org/netxms/client/events/EventInfo.java
new file mode 100644 (file)
index 0000000..8e950f9
--- /dev/null
@@ -0,0 +1,153 @@
+/**
+ * NetXMS - open source network management system
+ * Copyright (C) 2003-2012 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.client.events;
+
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+import org.netxms.base.NXCPMessage;
+
+/**
+ * Information about NetXMS event
+ */
+public class EventInfo
+{
+       private long id;
+       private Date timeStamp;
+       private long sourceObjectId;
+       private int code;
+       private String name;
+       private int severity;
+       private String message;
+       private EventInfo parent;
+       private List<EventInfo> children;
+       
+       /**
+        * Create from NXCP message.
+        * 
+        * @param msg
+        * @param baseId
+        */
+       public EventInfo(NXCPMessage msg, long baseId, EventInfo parent)
+       {
+               this.parent = parent;
+               if (parent != null)
+                       parent.addChild(this);
+               children = null;
+               id = msg.getVariableAsInt64(baseId);
+               code = msg.getVariableAsInteger(baseId + 2);
+               name = msg.getVariableAsString(baseId + 3);
+               severity = msg.getVariableAsInteger(baseId + 4);
+               sourceObjectId = msg.getVariableAsInt64(baseId + 5);
+               timeStamp = msg.getVariableAsDate(baseId + 6);
+               message = msg.getVariableAsString(baseId + 7);
+       }
+       
+       /**
+        * Add child event
+        * 
+        * @param e
+        */
+       private void addChild(EventInfo e)
+       {
+               if (children == null)
+                       children = new ArrayList<EventInfo>();
+               children.add(e);
+       }
+
+       /**
+        * @return the id
+        */
+       public long getId()
+       {
+               return id;
+       }
+
+       /**
+        * @return parent event or null
+        */
+       public EventInfo getParent()
+       {
+               return parent;
+       }
+
+       /**
+        * @return the timeStamp
+        */
+       public Date getTimeStamp()
+       {
+               return timeStamp;
+       }
+
+       /**
+        * @return the sourceObjectId
+        */
+       public long getSourceObjectId()
+       {
+               return sourceObjectId;
+       }
+
+       /**
+        * @return the code
+        */
+       public int getCode()
+       {
+               return code;
+       }
+
+       /**
+        * @return the name
+        */
+       public String getName()
+       {
+               return name;
+       }
+
+       /**
+        * @return the severity
+        */
+       public int getSeverity()
+       {
+               return severity;
+       }
+
+       /**
+        * @return the message
+        */
+       public String getMessage()
+       {
+               return message;
+       }
+
+       /**
+        * @return the children
+        */
+       public EventInfo[] getChildren()
+       {
+               return (children != null) ? children.toArray(new EventInfo[children.size()]) : new EventInfo[0];
+       }
+       
+       /**
+        * @return
+        */
+       public boolean hasChildren()
+       {
+               return (children != null) && (children.size() > 0);
+       }
+}
index d838e31..b1d4e42 100644 (file)
@@ -19,6 +19,7 @@
 package org.netxms.client;\r
 \r
 import java.util.HashMap;\r
+import java.util.List;\r
 import java.util.Map;\r
 import java.util.Map.Entry;\r
 import java.util.concurrent.Semaphore;\r
@@ -26,6 +27,7 @@ import java.util.concurrent.TimeUnit;
 \r
 import org.netxms.api.client.SessionNotification;\r
 import org.netxms.client.events.Alarm;\r
+import org.netxms.client.events.EventInfo;\r
 \r
 /**\r
  * Alarm management tests\r
@@ -46,6 +48,25 @@ public class AlarmTest extends SessionTest
        }\r
 \r
        // NOTE: server must have at least 1 active alarm for this test.\r
+       public void testGetEvents() throws Exception\r
+       {\r
+               final NXCSession session = connect();\r
+               \r
+               HashMap<Long, Alarm> list = session.getAlarms();\r
+               if (list.size() > 0)\r
+               {\r
+                       final Long alarmId = list.keySet().iterator().next();\r
+                       List<EventInfo> events = session.getAlarmEvents(alarmId);\r
+                       for(EventInfo e : events)\r
+                       {\r
+                               System.out.println(e.getTimeStamp() + " " + e.getName() + " " + e.getMessage());\r
+                       }\r
+               }\r
+               \r
+               session.disconnect();\r
+       }\r
+       \r
+       // NOTE: server must have at least 1 active alarm for this test.\r
        //       This alarm  will be terminated during test.\r
        public void testAlarmUpdate() throws Exception\r
        {\r
index 65c743f..6d353ea 100644 (file)
@@ -10,7 +10,8 @@ Require-Bundle: org.eclipse.ui;bundle-version="3.7.0",
  org.netxms.ui.eclipse.console;bundle-version="1.2.5",
  org.netxms.ui.eclipse.library;bundle-version="1.2.5",
  org.netxms.ui.eclipse.objectview;bundle-version="1.2.5",
- org.eclipse.ui.forms;bundle-version="3.5.100"
+ org.eclipse.ui.forms;bundle-version="3.5.100",
+ org.netxms.ui.eclipse.datacollection;bundle-version="1.2.5"
 Bundle-RequiredExecutionEnvironment: JavaSE-1.6
 Bundle-ActivationPolicy: lazy
 Bundle-ClassPath: .
index c629eaf..685fa40 100644 (file)
@@ -28,6 +28,12 @@ import org.eclipse.jface.action.IToolBarManager;
 import org.eclipse.jface.window.Window;
 import org.eclipse.swt.SWT;
 import org.eclipse.swt.custom.CLabel;
+import org.eclipse.swt.custom.ScrolledComposite;
+import org.eclipse.swt.events.ControlAdapter;
+import org.eclipse.swt.events.ControlEvent;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.layout.FillLayout;
 import org.eclipse.swt.layout.GridData;
 import org.eclipse.swt.layout.GridLayout;
 import org.eclipse.swt.widgets.Composite;
@@ -35,30 +41,35 @@ import org.eclipse.swt.widgets.Label;
 import org.eclipse.ui.IActionBars;
 import org.eclipse.ui.IViewSite;
 import org.eclipse.ui.PartInitException;
+import org.eclipse.ui.forms.events.ExpansionEvent;
 import org.eclipse.ui.forms.events.HyperlinkAdapter;
 import org.eclipse.ui.forms.events.HyperlinkEvent;
+import org.eclipse.ui.forms.events.IExpansionListener;
+import org.eclipse.ui.forms.widgets.Form;
 import org.eclipse.ui.forms.widgets.FormToolkit;
 import org.eclipse.ui.forms.widgets.ImageHyperlink;
-import org.eclipse.ui.forms.widgets.ScrolledForm;
 import org.eclipse.ui.forms.widgets.Section;
-import org.eclipse.ui.forms.widgets.TableWrapData;
-import org.eclipse.ui.forms.widgets.TableWrapLayout;
 import org.eclipse.ui.model.WorkbenchLabelProvider;
 import org.eclipse.ui.part.ViewPart;
 import org.netxms.client.NXCSession;
 import org.netxms.client.events.Alarm;
 import org.netxms.client.events.AlarmNote;
+import org.netxms.client.events.EventInfo;
 import org.netxms.client.objects.GenericObject;
 import org.netxms.ui.eclipse.actions.RefreshAction;
 import org.netxms.ui.eclipse.alarmviewer.Activator;
 import org.netxms.ui.eclipse.alarmviewer.Messages;
 import org.netxms.ui.eclipse.alarmviewer.dialogs.EditCommentDialog;
+import org.netxms.ui.eclipse.alarmviewer.views.helpers.EventTreeContentProvider;
+import org.netxms.ui.eclipse.alarmviewer.views.helpers.EventTreeLabelProvider;
 import org.netxms.ui.eclipse.alarmviewer.widgets.AlarmCommentsEditor;
 import org.netxms.ui.eclipse.console.resources.StatusDisplayInfo;
+import org.netxms.ui.eclipse.datacollection.widgets.LastValuesWidget;
 import org.netxms.ui.eclipse.jobs.ConsoleJob;
 import org.netxms.ui.eclipse.shared.ConsoleSharedData;
 import org.netxms.ui.eclipse.shared.SharedIcons;
 import org.netxms.ui.eclipse.tools.ImageCache;
+import org.netxms.ui.eclipse.widgets.SortableTreeViewer;
 
 /**
  * Alarm comments
@@ -67,6 +78,11 @@ public class AlarmDetails extends ViewPart
 {
        public static final String ID = "org.netxms.ui.eclipse.alarmviewer.views.AlarmDetails"; //$NON-NLS-1$
        
+       public static final int EV_COLUMN_SEVERITY = 0;
+       public static final int EV_COLUMN_NAME = 1;
+       public static final int EV_COLUMN_MESSAGE = 2;
+       public static final int EV_COLUMN_TIMESTAMP = 3;
+       
        private static final String[] stateImage = { "icons/outstanding.png", "icons/acknowledged.png", "icons/terminated.png" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
        private static final String[] stateText = { Messages.AlarmListLabelProvider_AlarmState_Outstanding, Messages.AlarmListLabelProvider_AlarmState_Acknowledged, Messages.AlarmListLabelProvider_AlarmState_Terminated };   
        
@@ -74,8 +90,10 @@ public class AlarmDetails extends ViewPart
        private long alarmId;
        private ImageCache imageCache;
        private WorkbenchLabelProvider wbLabelProvider;
+       private ScrolledComposite scroller;
+       private Composite formContainer;
        private FormToolkit toolkit;
-       private ScrolledForm form;
+       private Form form;
        private CLabel alarmSeverity;
        private CLabel alarmState;
        private CLabel alarmSource;
@@ -83,6 +101,9 @@ public class AlarmDetails extends ViewPart
        private Composite editorsArea;
        private ImageHyperlink linkAddComment;
        private Map<Long, AlarmCommentsEditor> editors = new HashMap<Long, AlarmCommentsEditor>();
+       private Composite dataArea;
+       private LastValuesWidget lastValuesWidget = null;
+       private SortableTreeViewer eventViewer;
        private Action actionRefresh;
        
        /* (non-Javadoc)
@@ -115,15 +136,44 @@ public class AlarmDetails extends ViewPart
        {
                imageCache = new ImageCache();
                
+               scroller = new ScrolledComposite(parent, SWT.V_SCROLL);
+               scroller.setExpandVertical(true);
+               scroller.getVerticalBar().setIncrement(20);
+               
+               formContainer = new Composite(scroller, SWT.NONE);
+               GridLayout containerLayout = new GridLayout();
+               containerLayout.marginHeight = 0;
+               containerLayout.marginWidth = 0;
+               formContainer.setLayout(containerLayout);
+               scroller.setContent(formContainer);
+               scroller.addControlListener(new ControlAdapter() {
+                       @Override
+                       public void controlResized(ControlEvent e)
+                       {
+                               Rectangle r = scroller.getClientArea();
+                               Point formSize = formContainer.computeSize(r.width, SWT.DEFAULT);
+                               formContainer.setSize(r.width, formSize.y);
+                               scroller.setMinHeight(formSize.y);
+                       }
+               });
+               
                toolkit = new FormToolkit(parent.getDisplay());
-               form = toolkit.createScrolledForm(parent);
+               form = toolkit.createForm(formContainer);
+               GridData gd = new GridData();
+               gd.horizontalAlignment = SWT.FILL;
+               gd.verticalAlignment = SWT.FILL;
+               gd.grabExcessHorizontalSpace = true;
+               gd.grabExcessVerticalSpace = true;
+               form.setLayoutData(gd);
 
-               TableWrapLayout layout = new TableWrapLayout();
-               layout.numColumns = 1;
+               GridLayout layout = new GridLayout();
+               layout.numColumns = 2;
                form.getBody().setLayout(layout);
                
                createAlarmDetailsSection();
-               createEditorsSection();
+               createEventsSection();
+               createCommentsSection();
+               createDataSection();
                
                createActions();
                contributeToActionBars();
@@ -183,23 +233,24 @@ public class AlarmDetails extends ViewPart
         */
        private void createAlarmDetailsSection()
        {
-               final Section details = toolkit.createSection(form.getBody(), Section.TITLE_BAR);
-               details.setText(Messages.AlarmComments_Details);
-               TableWrapData twd = new TableWrapData();
-               twd.grabHorizontal = true;
-               twd.align = TableWrapData.FILL;
-               details.setLayoutData(twd);
+               final Section section = toolkit.createSection(form.getBody(), Section.TITLE_BAR | Section.EXPANDED | Section.TWISTIE | Section.COMPACT);
+               section.setText("Overview");
+               GridData gd = new GridData();
+               gd.horizontalAlignment = SWT.FILL;
+               gd.grabExcessHorizontalSpace = true;
+               gd.horizontalSpan = 2;
+               section.setLayoutData(gd);
 
-               final Composite clientArea = toolkit.createComposite(details);
+               final Composite clientArea = toolkit.createComposite(section);
                GridLayout layout = new GridLayout();
                layout.numColumns = 2;
                layout.makeColumnsEqualWidth = true;
                clientArea.setLayout(layout);
-               details.setClient(clientArea);
+               section.setClient(clientArea);
 
                alarmSeverity = new CLabel(clientArea, SWT.NONE);
                toolkit.adapt(alarmSeverity);
-               GridData gd = new GridData();
+               gd = new GridData();
                gd.horizontalAlignment = SWT.FILL;
                gd.grabExcessHorizontalSpace = true;
                alarmSeverity.setLayoutData(gd);
@@ -228,21 +279,23 @@ public class AlarmDetails extends ViewPart
        }
        
        /**
-        * Create comment list
+        * Create comment section
         */
-       private void createEditorsSection()
+       private void createCommentsSection()
        {
-               final Section details = toolkit.createSection(form.getBody(), Section.TITLE_BAR);
-               details.setText(Messages.AlarmComments_Comments);
-               TableWrapData twd = new TableWrapData();
-               twd.grabHorizontal = true;
-               twd.align = TableWrapData.FILL;
-               details.setLayoutData(twd);
+               final Section section = toolkit.createSection(form.getBody(), Section.TITLE_BAR | Section.EXPANDED | Section.TWISTIE | Section.COMPACT);
+               section.setText(Messages.AlarmComments_Comments);
+               GridData gd = new GridData();
+               gd.horizontalAlignment = SWT.FILL;
+               gd.verticalAlignment = SWT.FILL;
+               gd.grabExcessVerticalSpace = true;
+               gd.verticalSpan = 2;
+               section.setLayoutData(gd);
 
-               editorsArea = toolkit.createComposite(details);
+               editorsArea = toolkit.createComposite(section);
                GridLayout layout = new GridLayout();
                editorsArea.setLayout(layout);
-               details.setClient(editorsArea);
+               section.setClient(editorsArea);
                
                linkAddComment = toolkit.createImageHyperlink(editorsArea, SWT.NONE);
                linkAddComment.setImage(imageCache.add(Activator.getImageDescriptor("icons/new_comment.png"))); //$NON-NLS-1$
@@ -256,6 +309,71 @@ public class AlarmDetails extends ViewPart
                });
        }
 
+       /**
+        * Create events section
+        */
+       private void createEventsSection()
+       {
+               final Section section = toolkit.createSection(form.getBody(), Section.TITLE_BAR | Section.EXPANDED | Section.TWISTIE | Section.COMPACT);
+               section.setText("Related Events");
+               final GridData gd = new GridData();
+               gd.horizontalAlignment = SWT.FILL;
+               gd.grabExcessHorizontalSpace = true;
+               gd.verticalAlignment = SWT.FILL;
+               gd.grabExcessVerticalSpace = true;
+               section.setLayoutData(gd);
+               section.addExpansionListener(new IExpansionListener() {
+                       @Override
+                       public void expansionStateChanging(ExpansionEvent e)
+                       {
+                               gd.grabExcessVerticalSpace = e.getState();
+                       }
+                       
+                       @Override
+                       public void expansionStateChanged(ExpansionEvent e)
+                       {
+                       }
+               });
+               
+               final String[] names = { "Severity", "Name", "Message", "Timestamp" };
+               final int[] widths = { 140, 120, 400, 120 };
+               eventViewer = new SortableTreeViewer(section, names, widths, 0, SWT.UP, SWT.BORDER | SWT.FULL_SELECTION);
+               section.setClient(eventViewer.getControl());
+               eventViewer.setContentProvider(new EventTreeContentProvider());
+               eventViewer.setLabelProvider(new EventTreeLabelProvider());
+       }
+
+       /**
+        * Create data section
+        */
+       private void createDataSection()
+       {
+               final Section section = toolkit.createSection(form.getBody(), Section.TITLE_BAR | Section.EXPANDED | Section.TWISTIE | Section.COMPACT);
+               section.setText("Last Values");
+               final GridData gd = new GridData();
+               gd.horizontalAlignment = SWT.FILL;
+               gd.grabExcessHorizontalSpace = true;
+               gd.verticalAlignment = SWT.FILL;
+               gd.grabExcessVerticalSpace = true;
+               section.setLayoutData(gd);
+               section.addExpansionListener(new IExpansionListener() {
+                       @Override
+                       public void expansionStateChanging(ExpansionEvent e)
+                       {
+                               gd.grabExcessVerticalSpace = e.getState();
+                       }
+                       
+                       @Override
+                       public void expansionStateChanged(ExpansionEvent e)
+                       {
+                       }
+               });
+               
+               dataArea = toolkit.createComposite(section);
+               section.setClient(dataArea);
+               dataArea.setLayout(new FillLayout());
+       }
+
        /* (non-Javadoc)
         * @see org.eclipse.ui.part.WorkbenchPart#setFocus()
         */
@@ -276,6 +394,7 @@ public class AlarmDetails extends ViewPart
                        {
                                final Alarm alarm = session.getAlarm(alarmId);
                                final List<AlarmNote> comments = session.getAlarmNotes(alarmId);
+                               final List<EventInfo> events = session.getAlarmEvents(alarmId);
                                runInUIThread(new Runnable() {
                                        @Override
                                        public void run()
@@ -288,6 +407,18 @@ public class AlarmDetails extends ViewPart
                                                for(AlarmNote n : comments)
                                                        editors.put(n.getId(), createEditor(n));
                                                
+                                               if (lastValuesWidget == null)
+                                               {
+                                                       GenericObject object = session.findObjectById(alarm.getSourceObjectId());
+                                                       if (object != null)
+                                                       {
+                                                               lastValuesWidget = new LastValuesWidget(AlarmDetails.this, dataArea, SWT.BORDER, object, "AlarmDetails.LastValues");
+                                                               lastValuesWidget.refresh();
+                                                       }
+                                               }
+                                               
+                                               eventViewer.setInput(events);
+                                               
                                                updateLayout();
                                        }
                                });
@@ -306,8 +437,11 @@ public class AlarmDetails extends ViewPart
         */
        private void updateLayout()
        {
-               form.reflow(true);
-               form.getParent().layout(true, true);
+               formContainer.layout(true, true);
+               Rectangle r = scroller.getClientArea();
+               Point formSize = formContainer.computeSize(r.width, SWT.DEFAULT);
+               formContainer.setSize(r.width, formSize.y);
+               scroller.setMinHeight(formSize.y);
        }
        
        /**
diff --git a/src/java/netxms-eclipse/AlarmViewer/src/org/netxms/ui/eclipse/alarmviewer/views/helpers/EventTreeContentProvider.java b/src/java/netxms-eclipse/AlarmViewer/src/org/netxms/ui/eclipse/alarmviewer/views/helpers/EventTreeContentProvider.java
new file mode 100644 (file)
index 0000000..82f65c3
--- /dev/null
@@ -0,0 +1,88 @@
+/**
+ * NetXMS - open source network management system
+ * Copyright (C) 2003-2012 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.alarmviewer.views.helpers;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.eclipse.jface.viewers.ITreeContentProvider;
+import org.eclipse.jface.viewers.Viewer;
+import org.netxms.client.events.EventInfo;
+
+/**
+ * Content provider for event tree
+ */
+public class EventTreeContentProvider implements ITreeContentProvider
+{
+       /* (non-Javadoc)
+        * @see org.eclipse.jface.viewers.IContentProvider#inputChanged(org.eclipse.jface.viewers.Viewer, java.lang.Object, java.lang.Object)
+        */
+       @Override
+       public void inputChanged(Viewer viewer, Object oldInput, Object newInput)
+       {
+       }
+
+       /* (non-Javadoc)
+        * @see org.eclipse.jface.viewers.ITreeContentProvider#getElements(java.lang.Object)
+        */
+       @SuppressWarnings("unchecked")
+       @Override
+       public Object[] getElements(Object inputElement)
+       {
+               List<EventInfo> list = new ArrayList<EventInfo>();
+               for(EventInfo e : (List<EventInfo>)inputElement)
+                       if (e.getParent() == null)
+                               list.add(e);
+               return list.toArray();
+       }
+
+       /* (non-Javadoc)
+        * @see org.eclipse.jface.viewers.ITreeContentProvider#getChildren(java.lang.Object)
+        */
+       @Override
+       public Object[] getChildren(Object parentElement)
+       {
+               return ((EventInfo)parentElement).getChildren();
+       }
+
+       /* (non-Javadoc)
+        * @see org.eclipse.jface.viewers.ITreeContentProvider#getParent(java.lang.Object)
+        */
+       @Override
+       public Object getParent(Object element)
+       {
+               return ((EventInfo)element).getParent();
+       }
+
+       /* (non-Javadoc)
+        * @see org.eclipse.jface.viewers.ITreeContentProvider#hasChildren(java.lang.Object)
+        */
+       @Override
+       public boolean hasChildren(Object element)
+       {
+               return ((EventInfo)element).hasChildren();
+       }
+
+       /* (non-Javadoc)
+        * @see org.eclipse.jface.viewers.IContentProvider#dispose()
+        */
+       @Override
+       public void dispose()
+       {
+       }
+}
diff --git a/src/java/netxms-eclipse/AlarmViewer/src/org/netxms/ui/eclipse/alarmviewer/views/helpers/EventTreeLabelProvider.java b/src/java/netxms-eclipse/AlarmViewer/src/org/netxms/ui/eclipse/alarmviewer/views/helpers/EventTreeLabelProvider.java
new file mode 100644 (file)
index 0000000..6fd2232
--- /dev/null
@@ -0,0 +1,64 @@
+/**
+ * NetXMS - open source network management system
+ * Copyright (C) 2003-2012 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.alarmviewer.views.helpers;
+
+import org.eclipse.jface.viewers.ITableLabelProvider;
+import org.eclipse.jface.viewers.LabelProvider;
+import org.eclipse.swt.graphics.Image;
+import org.netxms.client.events.EventInfo;
+import org.netxms.ui.eclipse.alarmviewer.views.AlarmDetails;
+import org.netxms.ui.eclipse.console.resources.StatusDisplayInfo;
+import org.netxms.ui.eclipse.console.tools.RegionalSettings;
+
+/**
+ * Label provider for event tree
+ */
+public class EventTreeLabelProvider extends LabelProvider implements ITableLabelProvider
+{
+       /* (non-Javadoc)
+        * @see org.eclipse.jface.viewers.ITableLabelProvider#getColumnImage(java.lang.Object, int)
+        */
+       @Override
+       public Image getColumnImage(Object element, int columnIndex)
+       {
+               if (columnIndex == AlarmDetails.EV_COLUMN_SEVERITY)
+                       return StatusDisplayInfo.getStatusImage(((EventInfo)element).getSeverity());
+               return null;
+       }
+
+       /* (non-Javadoc)
+        * @see org.eclipse.jface.viewers.ITableLabelProvider#getColumnText(java.lang.Object, int)
+        */
+       @Override
+       public String getColumnText(Object element, int columnIndex)
+       {
+               switch(columnIndex)
+               {
+                       case AlarmDetails.EV_COLUMN_SEVERITY:
+                               return StatusDisplayInfo.getStatusText(((EventInfo)element).getSeverity());
+                       case AlarmDetails.EV_COLUMN_NAME:
+                               return ((EventInfo)element).getName();
+                       case AlarmDetails.EV_COLUMN_MESSAGE:
+                               return ((EventInfo)element).getMessage();
+                       case AlarmDetails.EV_COLUMN_TIMESTAMP:
+                               return RegionalSettings.getDateTimeFormat().format(((EventInfo)element).getTimeStamp());
+               }
+               return null;
+       }
+}
index 1050a1d..e276ecd 100644 (file)
@@ -34,6 +34,8 @@ import org.eclipse.jface.preference.IPreferenceStore;
 import org.eclipse.jface.util.IPropertyChangeListener;\r
 import org.eclipse.jface.util.PropertyChangeEvent;\r
 import org.eclipse.jface.viewers.ArrayContentProvider;\r
+import org.eclipse.jface.viewers.DoubleClickEvent;\r
+import org.eclipse.jface.viewers.IDoubleClickListener;\r
 import org.eclipse.jface.viewers.ISelectionProvider;\r
 import org.eclipse.jface.viewers.IStructuredSelection;\r
 import org.eclipse.swt.SWT;\r
@@ -56,12 +58,12 @@ import org.netxms.client.NXCSession;
 import org.netxms.client.events.Alarm;\r
 import org.netxms.client.objects.GenericObject;\r
 import org.netxms.ui.eclipse.alarmviewer.Activator;\r
-import org.netxms.ui.eclipse.alarmviewer.AlarmComparator;\r
-import org.netxms.ui.eclipse.alarmviewer.AlarmListFilter;\r
-import org.netxms.ui.eclipse.alarmviewer.AlarmListLabelProvider;\r
 import org.netxms.ui.eclipse.alarmviewer.Messages;\r
 import org.netxms.ui.eclipse.alarmviewer.views.AlarmComments;\r
 import org.netxms.ui.eclipse.alarmviewer.views.AlarmDetails;\r
+import org.netxms.ui.eclipse.alarmviewer.widgets.helpers.AlarmComparator;\r
+import org.netxms.ui.eclipse.alarmviewer.widgets.helpers.AlarmListFilter;\r
+import org.netxms.ui.eclipse.alarmviewer.widgets.helpers.AlarmListLabelProvider;\r
 import org.netxms.ui.eclipse.jobs.ConsoleJob;\r
 import org.netxms.ui.eclipse.objectview.views.TabbedObjectView;\r
 import org.netxms.ui.eclipse.shared.ConsoleSharedData;\r
@@ -135,6 +137,13 @@ public class AlarmList extends Composite
                                WidgetHelper.saveTableViewerSettings(alarmViewer, Activator.getDefault().getDialogSettings(), configPrefix);\r
                        }\r
                });\r
+               alarmViewer.addDoubleClickListener(new IDoubleClickListener() {\r
+                       @Override\r
+                       public void doubleClick(DoubleClickEvent event)\r
+                       {\r
+                               actionShowAlarmDetails.run();\r
+                       }\r
+               });\r
                \r
                createActions();\r
                createPopupMenu();\r
-/**\r
- * \r
- */\r
-package org.netxms.ui.eclipse.alarmviewer;\r
-\r
-import org.eclipse.jface.viewers.TableViewer;\r
-import org.eclipse.jface.viewers.Viewer;\r
-import org.eclipse.jface.viewers.ViewerComparator;\r
-import org.eclipse.swt.SWT;\r
-import org.eclipse.swt.widgets.TableColumn;\r
-import org.netxms.client.NXCSession;\r
-import org.netxms.client.events.Alarm;\r
-import org.netxms.client.objects.GenericObject;\r
-import org.netxms.ui.eclipse.alarmviewer.widgets.AlarmList;\r
-import org.netxms.ui.eclipse.shared.ConsoleSharedData;\r
-\r
-/**\r
- * @author victor\r
- *\r
- */\r
-public class AlarmComparator extends ViewerComparator\r
-{\r
-       /**\r
-        * \r
-        */\r
-       public AlarmComparator()\r
-       {\r
-               super();\r
-       }\r
-       \r
-       \r
-       /**\r
-        * Compare two numbers and return -1, 0, or 1\r
-        */\r
-       private int compareNumbers(long n1, long n2)\r
-       {\r
-               return (n1 < n2) ? -1 : ((n1 > n2) ? 1 : 0);\r
-       }\r
-\r
-       /* (non-Javadoc)\r
-        * @see org.eclipse.jface.viewers.ViewerComparator#compare(org.eclipse.jface.viewers.Viewer, java.lang.Object, java.lang.Object)\r
-        */\r
-       @Override\r
-       public int compare(Viewer viewer, Object e1, Object e2)\r
-       {\r
-               TableColumn sortColumn = ((TableViewer)viewer).getTable().getSortColumn();\r
-               if (sortColumn == null)\r
-                       return 0;\r
-               \r
-               int rc;\r
-               switch((Integer)sortColumn.getData("ID")) //$NON-NLS-1$\r
-               {\r
-                       case AlarmList.COLUMN_SEVERITY:\r
-                               rc = compareNumbers(((Alarm)e1).getCurrentSeverity(), ((Alarm)e2).getCurrentSeverity());\r
-                               break;\r
-                       case AlarmList.COLUMN_STATE:\r
-                               rc = compareNumbers(((Alarm)e1).getState(), ((Alarm)e2).getState());\r
-                               break;\r
-                       case AlarmList.COLUMN_SOURCE:\r
-                               GenericObject obj1 = ((NXCSession)ConsoleSharedData.getSession()).findObjectById(((Alarm)e1).getSourceObjectId());\r
-                               GenericObject obj2 = ((NXCSession)ConsoleSharedData.getSession()).findObjectById(((Alarm)e2).getSourceObjectId());\r
-                               String name1 = (obj1 != null) ? obj1.getObjectName() : Messages.AlarmComparator_Unknown;\r
-                               String name2 = (obj2 != null) ? obj2.getObjectName() : Messages.AlarmComparator_Unknown;\r
-                               rc = name1.compareToIgnoreCase(name2);\r
-                               break;\r
-                       case AlarmList.COLUMN_MESSAGE:\r
-                               rc = ((Alarm)e1).getMessage().compareToIgnoreCase(((Alarm)e2).getMessage());\r
-                               break;\r
-                       case AlarmList.COLUMN_COUNT:\r
-                               rc = compareNumbers(((Alarm)e1).getRepeatCount(), ((Alarm)e2).getRepeatCount());\r
-                               break;\r
-                       case AlarmList.COLUMN_CREATED:\r
-                               rc = ((Alarm)e1).getCreationTime().compareTo(((Alarm)e2).getCreationTime());\r
-                               break;\r
-                       case AlarmList.COLUMN_LASTCHANGE:\r
-                               rc = ((Alarm)e1).getLastChangeTime().compareTo(((Alarm)e2).getLastChangeTime());\r
-                               break;\r
-                       default:\r
-                               rc = 0;\r
-                               break;\r
-               }\r
-               int dir = ((TableViewer)viewer).getTable().getSortDirection();\r
-               return (dir == SWT.UP) ? rc : -rc;\r
-       }\r
-}\r
+/**
+ * NetXMS - open source network management system
+ * Copyright (C) 2003-2012 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.alarmviewer.widgets.helpers;
+
+import org.eclipse.jface.viewers.TableViewer;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.jface.viewers.ViewerComparator;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.TableColumn;
+import org.netxms.client.NXCSession;
+import org.netxms.client.events.Alarm;
+import org.netxms.client.objects.GenericObject;
+import org.netxms.ui.eclipse.alarmviewer.Messages;
+import org.netxms.ui.eclipse.alarmviewer.widgets.AlarmList;
+import org.netxms.ui.eclipse.shared.ConsoleSharedData;
+
+/**
+ * Comparator for alarm list
+ */
+public class AlarmComparator extends ViewerComparator
+{
+       /**
+        * 
+        */
+       public AlarmComparator()
+       {
+               super();
+       }
+       
+       
+       /**
+        * Compare two numbers and return -1, 0, or 1
+        */
+       private int compareNumbers(long n1, long n2)
+       {
+               return (n1 < n2) ? -1 : ((n1 > n2) ? 1 : 0);
+       }
+
+       /* (non-Javadoc)
+        * @see org.eclipse.jface.viewers.ViewerComparator#compare(org.eclipse.jface.viewers.Viewer, java.lang.Object, java.lang.Object)
+        */
+       @Override
+       public int compare(Viewer viewer, Object e1, Object e2)
+       {
+               TableColumn sortColumn = ((TableViewer)viewer).getTable().getSortColumn();
+               if (sortColumn == null)
+                       return 0;
+               
+               int rc;
+               switch((Integer)sortColumn.getData("ID")) //$NON-NLS-1$
+               {
+                       case AlarmList.COLUMN_SEVERITY:
+                               rc = compareNumbers(((Alarm)e1).getCurrentSeverity(), ((Alarm)e2).getCurrentSeverity());
+                               break;
+                       case AlarmList.COLUMN_STATE:
+                               rc = compareNumbers(((Alarm)e1).getState(), ((Alarm)e2).getState());
+                               break;
+                       case AlarmList.COLUMN_SOURCE:
+                               GenericObject obj1 = ((NXCSession)ConsoleSharedData.getSession()).findObjectById(((Alarm)e1).getSourceObjectId());
+                               GenericObject obj2 = ((NXCSession)ConsoleSharedData.getSession()).findObjectById(((Alarm)e2).getSourceObjectId());
+                               String name1 = (obj1 != null) ? obj1.getObjectName() : Messages.AlarmComparator_Unknown;
+                               String name2 = (obj2 != null) ? obj2.getObjectName() : Messages.AlarmComparator_Unknown;
+                               rc = name1.compareToIgnoreCase(name2);
+                               break;
+                       case AlarmList.COLUMN_MESSAGE:
+                               rc = ((Alarm)e1).getMessage().compareToIgnoreCase(((Alarm)e2).getMessage());
+                               break;
+                       case AlarmList.COLUMN_COUNT:
+                               rc = compareNumbers(((Alarm)e1).getRepeatCount(), ((Alarm)e2).getRepeatCount());
+                               break;
+                       case AlarmList.COLUMN_CREATED:
+                               rc = ((Alarm)e1).getCreationTime().compareTo(((Alarm)e2).getCreationTime());
+                               break;
+                       case AlarmList.COLUMN_LASTCHANGE:
+                               rc = ((Alarm)e1).getLastChangeTime().compareTo(((Alarm)e2).getLastChangeTime());
+                               break;
+                       default:
+                               rc = 0;
+                               break;
+               }
+               int dir = ((TableViewer)viewer).getTable().getSortDirection();
+               return (dir == SWT.UP) ? rc : -rc;
+       }
+}
@@ -1,78 +1,77 @@
-/**\r
- * NetXMS - open source network management system\r
- * Copyright (C) 2003-2010 Victor Kirhenshtein\r
- *\r
- * This program is free software; you can redistribute it and/or modify\r
- * it under the terms of the GNU General Public License as published by\r
- * the Free Software Foundation; either version 2 of the License, or\r
- * (at your option) any later version.\r
- *\r
- * This program is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
- * GNU General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU General Public License\r
- * along with this program; if not, write to the Free Software\r
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.\r
- */\r
-package org.netxms.ui.eclipse.alarmviewer;\r
-\r
-import org.eclipse.jface.viewers.Viewer;\r
-import org.eclipse.jface.viewers.ViewerFilter;\r
-import org.netxms.client.NXCSession;\r
-import org.netxms.client.events.Alarm;\r
-import org.netxms.client.objects.GenericObject;\r
-import org.netxms.ui.eclipse.shared.ConsoleSharedData;\r
-\r
-/**\r
- * Filter for alarm list\r
- *\r
- */\r
-public class AlarmListFilter extends ViewerFilter\r
-{\r
-       private long rootObject = 0;\r
-       private int stateFilter = -1;\r
-       \r
-       /**\r
-        * \r
-        */\r
-       public AlarmListFilter()\r
-       {\r
-               rootObject = 0;\r
-       }\r
-       \r
-       /* (non-Javadoc)\r
-        * @see org.eclipse.jface.viewers.ViewerFilter#select(org.eclipse.jface.viewers.Viewer, java.lang.Object, java.lang.Object)\r
-        */\r
-       @Override\r
-       public boolean select(Viewer viewer, Object parentElement, Object element)\r
-       {\r
-               if ((stateFilter != -1) && (((Alarm)element).getState() != stateFilter))\r
-                       return false;\r
-                               \r
-               if ((rootObject == 0) || (rootObject == ((Alarm)element).getSourceObjectId()))\r
-                       return true;    // No filtering by object ID or root object is a source\r
-               \r
-               GenericObject object = ((NXCSession)ConsoleSharedData.getSession()).findObjectById(((Alarm)element).getSourceObjectId());\r
-               if (object != null)\r
-                       return object.isChildOf(rootObject);\r
-               return false;\r
-       }\r
-\r
-       /**\r
-        * @param rootObject the rootObject to set\r
-        */\r
-       public final void setRootObject(long rootObject)\r
-       {\r
-               this.rootObject = rootObject;\r
-       }\r
-\r
-       /**\r
-        * @param stateFilter the stateFilter to set\r
-        */\r
-       public void setStateFilter(int stateFilter)\r
-       {\r
-               this.stateFilter = stateFilter;\r
-       }\r
-}\r
+/**
+ * NetXMS - open source network management system
+ * Copyright (C) 2003-2012 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.alarmviewer.widgets.helpers;
+
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.jface.viewers.ViewerFilter;
+import org.netxms.client.NXCSession;
+import org.netxms.client.events.Alarm;
+import org.netxms.client.objects.GenericObject;
+import org.netxms.ui.eclipse.shared.ConsoleSharedData;
+
+/**
+ * Filter for alarm list
+ */
+public class AlarmListFilter extends ViewerFilter
+{
+       private long rootObject = 0;
+       private int stateFilter = -1;
+       
+       /**
+        * 
+        */
+       public AlarmListFilter()
+       {
+               rootObject = 0;
+       }
+       
+       /* (non-Javadoc)
+        * @see org.eclipse.jface.viewers.ViewerFilter#select(org.eclipse.jface.viewers.Viewer, java.lang.Object, java.lang.Object)
+        */
+       @Override
+       public boolean select(Viewer viewer, Object parentElement, Object element)
+       {
+               if ((stateFilter != -1) && (((Alarm)element).getState() != stateFilter))
+                       return false;
+                               
+               if ((rootObject == 0) || (rootObject == ((Alarm)element).getSourceObjectId()))
+                       return true;    // No filtering by object ID or root object is a source
+               
+               GenericObject object = ((NXCSession)ConsoleSharedData.getSession()).findObjectById(((Alarm)element).getSourceObjectId());
+               if (object != null)
+                       return object.isChildOf(rootObject);
+               return false;
+       }
+
+       /**
+        * @param rootObject the rootObject to set
+        */
+       public final void setRootObject(long rootObject)
+       {
+               this.rootObject = rootObject;
+       }
+
+       /**
+        * @param stateFilter the stateFilter to set
+        */
+       public void setStateFilter(int stateFilter)
+       {
+               this.stateFilter = stateFilter;
+       }
+}
-/**\r
- * NetXMS - open source network management system\r
- * Copyright (C) 2003-2012 Victor Kirhenshtein\r
- *\r
- * This program is free software; you can redistribute it and/or modify\r
- * it under the terms of the GNU General Public License as published by\r
- * the Free Software Foundation; either version 2 of the License, or\r
- * (at your option) any later version.\r
- *\r
- * This program is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
- * GNU General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU General Public License\r
- * along with this program; if not, write to the Free Software\r
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.\r
- */\r
-package org.netxms.ui.eclipse.alarmviewer;\r
-\r
-import org.eclipse.jface.viewers.ILabelProviderListener;\r
-import org.eclipse.jface.viewers.ITableLabelProvider;\r
-import org.eclipse.swt.graphics.Image;\r
-import org.netxms.api.client.users.AbstractUserObject;\r
-import org.netxms.client.NXCSession;\r
-import org.netxms.client.constants.Severity;\r
-import org.netxms.client.events.Alarm;\r
-import org.netxms.client.objects.GenericObject;\r
-import org.netxms.ui.eclipse.alarmviewer.widgets.AlarmList;\r
-import org.netxms.ui.eclipse.console.resources.StatusDisplayInfo;\r
-import org.netxms.ui.eclipse.console.tools.RegionalSettings;\r
-import org.netxms.ui.eclipse.shared.ConsoleSharedData;\r
-import org.netxms.ui.eclipse.shared.SharedIcons;\r
-\r
-\r
-/**\r
- * Label provider for alarm list\r
- */\r
-public class AlarmListLabelProvider implements ITableLabelProvider\r
-{\r
-       private static final String[] stateText = { Messages.AlarmListLabelProvider_AlarmState_Outstanding, Messages.AlarmListLabelProvider_AlarmState_Acknowledged, Messages.AlarmListLabelProvider_AlarmState_Resolved, Messages.AlarmListLabelProvider_AlarmState_Terminated };\r
-       \r
-       private NXCSession session;\r
-       private Image[] severityImages = new Image[5];\r
-       private Image[] stateImages = new Image[5];\r
-       private Image commentsImage;\r
-       private boolean blinkState = true;\r
-       \r
-       /**\r
-        * Default constructor \r
-        */\r
-       public AlarmListLabelProvider()\r
-       {\r
-               session = (NXCSession)ConsoleSharedData.getSession();\r
-               \r
-               severityImages[Severity.NORMAL] = StatusDisplayInfo.getStatusImage(Severity.NORMAL);\r
-               severityImages[Severity.WARNING] = StatusDisplayInfo.getStatusImage(Severity.WARNING);\r
-               severityImages[Severity.MINOR] = StatusDisplayInfo.getStatusImage(Severity.MINOR);\r
-               severityImages[Severity.MAJOR] = StatusDisplayInfo.getStatusImage(Severity.MAJOR);\r
-               severityImages[Severity.CRITICAL] = StatusDisplayInfo.getStatusImage(Severity.CRITICAL);\r
-\r
-               stateImages[0] = Activator.getImageDescriptor("icons/outstanding.png").createImage(); //$NON-NLS-1$\r
-               stateImages[1] = Activator.getImageDescriptor("icons/acknowledged.png").createImage(); //$NON-NLS-1$\r
-               stateImages[2] = Activator.getImageDescriptor("icons/resolved.png").createImage(); //$NON-NLS-1$\r
-               stateImages[3] = Activator.getImageDescriptor("icons/terminated.png").createImage(); //$NON-NLS-1$\r
-               stateImages[4] = Activator.getImageDescriptor("icons/acknowledged_sticky.png").createImage(); //$NON-NLS-1$\r
-               \r
-               commentsImage = Activator.getImageDescriptor("icons/comments.png").createImage(); //$NON-NLS-1$\r
-       }\r
-\r
-       /* (non-Javadoc)\r
-        * @see org.eclipse.jface.viewers.ITableLabelProvider#getColumnImage(java.lang.Object, int)\r
-        */\r
-       @Override\r
-       public Image getColumnImage(Object element, int columnIndex)\r
-       {\r
-               switch(columnIndex)\r
-               {\r
-                       case AlarmList.COLUMN_SEVERITY:\r
-                               return severityImages[((Alarm)element).getCurrentSeverity()];\r
-                       case AlarmList.COLUMN_STATE:\r
-                               if (((Alarm)element).getState() == Alarm.STATE_OUTSTANDING)\r
-                                       return blinkState ? stateImages[Alarm.STATE_OUTSTANDING] : SharedIcons.IMG_EMPTY;\r
-                               if ((((Alarm)element).getState() == Alarm.STATE_ACKNOWLEDGED) && ((Alarm)element).isSticky())\r
-                                       return stateImages[4];\r
-                               return stateImages[((Alarm)element).getState()];\r
-                       case AlarmList.COLUMN_COMMENTS:\r
-                               return (((Alarm)element).getCommentsCount() > 0) ? commentsImage : null;\r
-               }\r
-               return null;\r
-       }\r
-\r
-       /* (non-Javadoc)\r
-        * @see org.eclipse.jface.viewers.ITableLabelProvider#getColumnText(java.lang.Object, int)\r
-        */\r
-       @Override\r
-       public String getColumnText(Object element, int columnIndex)\r
-       {\r
-               switch(columnIndex)\r
-               {\r
-                       case AlarmList.COLUMN_SEVERITY:\r
-                               return StatusDisplayInfo.getStatusText(((Alarm)element).getCurrentSeverity());\r
-                       case AlarmList.COLUMN_STATE:\r
-                               return stateText[((Alarm)element).getState()];\r
-                       case AlarmList.COLUMN_SOURCE:\r
-                               GenericObject object = session.findObjectById(((Alarm)element).getSourceObjectId());\r
-                               return (object != null) ? object.getObjectName() : ("[" + Long.toString(((Alarm)element).getSourceObjectId()) + "]"); //$NON-NLS-1$ //$NON-NLS-2$\r
-                       case AlarmList.COLUMN_MESSAGE:\r
-                               return ((Alarm)element).getMessage();\r
-                       case AlarmList.COLUMN_COUNT:\r
-                               return Integer.toString(((Alarm)element).getRepeatCount());\r
-                       case AlarmList.COLUMN_COMMENTS:\r
-                               return (((Alarm)element).getCommentsCount() > 0) ? Integer.toString(((Alarm)element).getCommentsCount()) : null;\r
-                       case AlarmList.COLUMN_ACK_BY:\r
-                               if (((Alarm)element).getState() == Alarm.STATE_OUTSTANDING)\r
-                                       return null;\r
-                               long userId = (((Alarm)element).getState() == Alarm.STATE_ACKNOWLEDGED) ? ((Alarm)element).getAckByUser() : ((Alarm)element).getResolvedByUser();\r
-                               AbstractUserObject user = session.findUserDBObjectById(userId);\r
-                               return (user != null) ? user.getName() : ("[" + Long.toString(((Alarm)element).getAckByUser()) + "]"); //$NON-NLS-1$ //$NON-NLS-2$\r
-                       case AlarmList.COLUMN_CREATED:\r
-                               return RegionalSettings.getDateTimeFormat().format(((Alarm)element).getCreationTime());\r
-                       case AlarmList.COLUMN_LASTCHANGE:\r
-                               return RegionalSettings.getDateTimeFormat().format(((Alarm)element).getLastChangeTime());\r
-               }\r
-               return null;\r
-       }\r
-\r
-       /* (non-Javadoc)\r
-        * @see org.eclipse.jface.viewers.IBaseLabelProvider#addListener(org.eclipse.jface.viewers.ILabelProviderListener)\r
-        */\r
-       @Override\r
-       public void addListener(ILabelProviderListener listener)\r
-       {\r
-       }\r
-\r
-       /* (non-Javadoc)\r
-        * @see org.eclipse.jface.viewers.IBaseLabelProvider#dispose()\r
-        */\r
-       @Override\r
-       public void dispose()\r
-       {\r
-               for(int i = 0; i < stateImages.length; i++)\r
-                       stateImages[i].dispose();\r
-       }\r
-\r
-       /* (non-Javadoc)\r
-        * @see org.eclipse.jface.viewers.IBaseLabelProvider#isLabelProperty(java.lang.Object, java.lang.String)\r
-        */\r
-       @Override\r
-       public boolean isLabelProperty(Object element, String property)\r
-       {\r
-               return false;\r
-       }\r
-\r
-       /* (non-Javadoc)\r
-        * @see org.eclipse.jface.viewers.IBaseLabelProvider#removeListener(org.eclipse.jface.viewers.ILabelProviderListener)\r
-        */\r
-       @Override\r
-       public void removeListener(ILabelProviderListener listener)\r
-       {\r
-       }\r
-\r
-       /**\r
-        * Toggle blink state\r
-        */\r
-       public void toggleBlinkState()\r
-       {\r
-               blinkState = !blinkState;\r
-       }\r
-}\r
+/**
+ * NetXMS - open source network management system
+ * Copyright (C) 2003-2012 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.alarmviewer.widgets.helpers;
+
+import org.eclipse.jface.viewers.ILabelProviderListener;
+import org.eclipse.jface.viewers.ITableLabelProvider;
+import org.eclipse.swt.graphics.Image;
+import org.netxms.api.client.users.AbstractUserObject;
+import org.netxms.client.NXCSession;
+import org.netxms.client.events.Alarm;
+import org.netxms.client.objects.GenericObject;
+import org.netxms.ui.eclipse.alarmviewer.Activator;
+import org.netxms.ui.eclipse.alarmviewer.Messages;
+import org.netxms.ui.eclipse.alarmviewer.widgets.AlarmList;
+import org.netxms.ui.eclipse.console.resources.StatusDisplayInfo;
+import org.netxms.ui.eclipse.console.tools.RegionalSettings;
+import org.netxms.ui.eclipse.shared.ConsoleSharedData;
+import org.netxms.ui.eclipse.shared.SharedIcons;
+
+/**
+ * Label provider for alarm list
+ */
+public class AlarmListLabelProvider implements ITableLabelProvider
+{
+       private static final String[] stateText = { Messages.AlarmListLabelProvider_AlarmState_Outstanding, Messages.AlarmListLabelProvider_AlarmState_Acknowledged, Messages.AlarmListLabelProvider_AlarmState_Resolved, Messages.AlarmListLabelProvider_AlarmState_Terminated };
+       
+       private NXCSession session;
+       private Image[] stateImages = new Image[5];
+       private Image commentsImage;
+       private boolean blinkState = true;
+       
+       /**
+        * Default constructor 
+        */
+       public AlarmListLabelProvider()
+       {
+               session = (NXCSession)ConsoleSharedData.getSession();
+               
+               stateImages[0] = Activator.getImageDescriptor("icons/outstanding.png").createImage(); //$NON-NLS-1$
+               stateImages[1] = Activator.getImageDescriptor("icons/acknowledged.png").createImage(); //$NON-NLS-1$
+               stateImages[2] = Activator.getImageDescriptor("icons/resolved.png").createImage(); //$NON-NLS-1$
+               stateImages[3] = Activator.getImageDescriptor("icons/terminated.png").createImage(); //$NON-NLS-1$
+               stateImages[4] = Activator.getImageDescriptor("icons/acknowledged_sticky.png").createImage(); //$NON-NLS-1$
+               
+               commentsImage = Activator.getImageDescriptor("icons/comments.png").createImage(); //$NON-NLS-1$
+       }
+
+       /* (non-Javadoc)
+        * @see org.eclipse.jface.viewers.ITableLabelProvider#getColumnImage(java.lang.Object, int)
+        */
+       @Override
+       public Image getColumnImage(Object element, int columnIndex)
+       {
+               switch(columnIndex)
+               {
+                       case AlarmList.COLUMN_SEVERITY:
+                               return StatusDisplayInfo.getStatusImage(((Alarm)element).getCurrentSeverity());
+                       case AlarmList.COLUMN_STATE:
+                               if (((Alarm)element).getState() == Alarm.STATE_OUTSTANDING)
+                                       return blinkState ? stateImages[Alarm.STATE_OUTSTANDING] : SharedIcons.IMG_EMPTY;
+                               if ((((Alarm)element).getState() == Alarm.STATE_ACKNOWLEDGED) && ((Alarm)element).isSticky())
+                                       return stateImages[4];
+                               return stateImages[((Alarm)element).getState()];
+                       case AlarmList.COLUMN_COMMENTS:
+                               return (((Alarm)element).getCommentsCount() > 0) ? commentsImage : null;
+               }
+               return null;
+       }
+
+       /* (non-Javadoc)
+        * @see org.eclipse.jface.viewers.ITableLabelProvider#getColumnText(java.lang.Object, int)
+        */
+       @Override
+       public String getColumnText(Object element, int columnIndex)
+       {
+               switch(columnIndex)
+               {
+                       case AlarmList.COLUMN_SEVERITY:
+                               return StatusDisplayInfo.getStatusText(((Alarm)element).getCurrentSeverity());
+                       case AlarmList.COLUMN_STATE:
+                               return stateText[((Alarm)element).getState()];
+                       case AlarmList.COLUMN_SOURCE:
+                               GenericObject object = session.findObjectById(((Alarm)element).getSourceObjectId());
+                               return (object != null) ? object.getObjectName() : ("[" + Long.toString(((Alarm)element).getSourceObjectId()) + "]"); //$NON-NLS-1$ //$NON-NLS-2$
+                       case AlarmList.COLUMN_MESSAGE:
+                               return ((Alarm)element).getMessage();
+                       case AlarmList.COLUMN_COUNT:
+                               return Integer.toString(((Alarm)element).getRepeatCount());
+                       case AlarmList.COLUMN_COMMENTS:
+                               return (((Alarm)element).getCommentsCount() > 0) ? Integer.toString(((Alarm)element).getCommentsCount()) : null;
+                       case AlarmList.COLUMN_ACK_BY:
+                               if (((Alarm)element).getState() == Alarm.STATE_OUTSTANDING)
+                                       return null;
+                               long userId = (((Alarm)element).getState() == Alarm.STATE_ACKNOWLEDGED) ? ((Alarm)element).getAckByUser() : ((Alarm)element).getResolvedByUser();
+                               AbstractUserObject user = session.findUserDBObjectById(userId);
+                               return (user != null) ? user.getName() : ("[" + Long.toString(((Alarm)element).getAckByUser()) + "]"); //$NON-NLS-1$ //$NON-NLS-2$
+                       case AlarmList.COLUMN_CREATED:
+                               return RegionalSettings.getDateTimeFormat().format(((Alarm)element).getCreationTime());
+                       case AlarmList.COLUMN_LASTCHANGE:
+                               return RegionalSettings.getDateTimeFormat().format(((Alarm)element).getLastChangeTime());
+               }
+               return null;
+       }
+
+       /* (non-Javadoc)
+        * @see org.eclipse.jface.viewers.IBaseLabelProvider#addListener(org.eclipse.jface.viewers.ILabelProviderListener)
+        */
+       @Override
+       public void addListener(ILabelProviderListener listener)
+       {
+       }
+
+       /* (non-Javadoc)
+        * @see org.eclipse.jface.viewers.IBaseLabelProvider#dispose()
+        */
+       @Override
+       public void dispose()
+       {
+               for(int i = 0; i < stateImages.length; i++)
+                       stateImages[i].dispose();
+       }
+
+       /* (non-Javadoc)
+        * @see org.eclipse.jface.viewers.IBaseLabelProvider#isLabelProperty(java.lang.Object, java.lang.String)
+        */
+       @Override
+       public boolean isLabelProperty(Object element, String property)
+       {
+               return false;
+       }
+
+       /* (non-Javadoc)
+        * @see org.eclipse.jface.viewers.IBaseLabelProvider#removeListener(org.eclipse.jface.viewers.ILabelProviderListener)
+        */
+       @Override
+       public void removeListener(ILabelProviderListener listener)
+       {
+       }
+
+       /**
+        * Toggle blink state
+        */
+       public void toggleBlinkState()
+       {
+               blinkState = !blinkState;
+       }
+}
index fc0d408..30405b4 100644 (file)
@@ -1,7 +1,7 @@
 /* 
 ** NetXMS - Network Management System
 ** NetXMS Foundation Library
-** Copyright (C) 2003-2010 Victor Kirhenshtein
+** Copyright (C) 2003-2012 Victor Kirhenshtein
 **
 ** This program is free software; you can redistribute it and/or modify
 ** it under the terms of the GNU Lesser General Public License as published
 #include "libnetxms.h"
 #include "ice.h"
 
-
-//
-// Constants
-//
-
+/**
+ * Constants
+ */
 #define KEY_BUFFER_SIZE       4096
 
-
-//
-// Supported ciphers. By default, we support all ciphers compiled
-// into OpenSSL library.
-//
-
+/**
+ * Supported ciphers. By default, we support all ciphers compiled
+ * into OpenSSL library.
+ */
 static DWORD m_dwSupportedCiphers = 
 #ifdef _WITH_ENCRYPTION
 #ifndef OPENSSL_NO_AES
@@ -55,11 +51,9 @@ static DWORD m_dwSupportedCiphers =
 #endif   /* _WITH_ENCRYPTION */
    0;
 
-
-//
-// Static data
-//
-
+/**
+ * Static data
+ */
 #ifdef _WITH_ENCRYPTION
 
 typedef OPENSSL_CONST EVP_CIPHER * (*CIPHER_FUNC)();
@@ -94,11 +88,9 @@ static CIPHER_FUNC m_pfCipherList[NETXMS_MAX_CIPHERS] =
 static WORD m_wNoEncryptionFlag = 0;
 static MUTEX *m_pCryptoMutexList = NULL;
 
-
-//
-// Locking callback for CRYPTO library
-//
-
+/**
+ * Locking callback for CRYPTO library
+ */
 static void CryptoLockingCallback(int nMode, int nLock, const char *pszFile, int nLine)
 {
    if (nMode & CRYPTO_LOCK)
@@ -107,11 +99,9 @@ static void CryptoLockingCallback(int nMode, int nLock, const char *pszFile, int
       MutexUnlock(m_pCryptoMutexList[nLock]);
 }
 
-
-//
-// ID callback for CRYPTO library
-//
-
+/**
+ * ID callback for CRYPTO library
+ */
 #ifndef _WIN32
 
 static unsigned long CryptoIdCallback()
@@ -123,11 +113,9 @@ static unsigned long CryptoIdCallback()
 
 #endif   /* _WITH_ENCRYPTION */
 
-
-//
-// Initialize OpenSSL library
-//
-
+/**
+ * Initialize OpenSSL library
+ */
 BOOL LIBNETXMS_EXPORTABLE InitCryptoLib(DWORD dwEnabledCiphers)
 {
 #ifdef _WITH_ENCRYPTION
@@ -151,21 +139,17 @@ BOOL LIBNETXMS_EXPORTABLE InitCryptoLib(DWORD dwEnabledCiphers)
    return TRUE;
 }
 
-
-//
-// Get supported ciphers
-//
-
+/**
+ * Get supported ciphers
+ */
 DWORD LIBNETXMS_EXPORTABLE CSCPGetSupportedCiphers()
 {
    return m_dwSupportedCiphers;
 }
 
-
-//
-// Encrypt message
-//
-
+/**
+ * Encrypt message
+ */
 CSCP_ENCRYPTED_MESSAGE LIBNETXMS_EXPORTABLE *CSCPEncryptMessage(NXCPEncryptionContext *pCtx, CSCP_MESSAGE *pMsg)
 {
 #ifdef _WITH_ENCRYPTION
@@ -258,14 +242,12 @@ BOOL LIBNETXMS_EXPORTABLE CSCPDecryptMessage(NXCPEncryptionContext *pCtx,
 #endif
 }
 
-
-//
-// Setup encryption context
-// Function will determine is it called on initiator or responder side
-// by message code. Initiator should provide it's private key,
-// and responder should provide pointer to response message.
-//
-
+/**
+ * Setup encryption context
+ * Function will determine is it called on initiator or responder side
+ * by message code. Initiator should provide it's private key,
+ * and responder should provide pointer to response message.
+ */
 DWORD LIBNETXMS_EXPORTABLE SetupEncryptionContext(CSCPMessage *pMsg, 
                                                   NXCPEncryptionContext **ppCtx,
                                                   CSCPMessage **ppResponse,
@@ -356,11 +338,9 @@ DWORD LIBNETXMS_EXPORTABLE SetupEncryptionContext(CSCPMessage *pMsg,
    return dwResult;
 }
 
-
-//
-// Prepare session key request message
-//
-
+/**
+ * Prepare session key request message
+ */
 void LIBNETXMS_EXPORTABLE PrepareKeyRequestMsg(CSCPMessage *pMsg, RSA *pServerKey, bool useX509Format)
 {
 #ifdef _WITH_ENCRYPTION
index b5bc175..c5732c7 100644 (file)
@@ -1,7 +1,7 @@
 /* 
 ** NetXMS - Network Management System
 ** Utility Library
-** Copyright (C) 2003-2010 Victor Kirhenshtein
+** Copyright (C) 2003-2012 Victor Kirhenshtein
 **
 ** This program is free software; you can redistribute it and/or modify
 ** it under the terms of the GNU Lesser General Public License as published
 
 #include "libnetxms.h"
 
-
-//
-// Swap byte order in 64-bit integer
-//
-
+/**
+ * Swap byte order in 64-bit integer
+ */
 #if defined(_WIN32) || !(HAVE_DECL___BSWAP_64)
 
 QWORD LIBNETXMS_EXPORTABLE __bswap_64(QWORD qwVal)
index fe29b22..b82f2a0 100644 (file)
@@ -305,10 +305,11 @@ TCHAR LIBNETXMS_EXPORTABLE *NXCPMessageCodeName(WORD wCode, TCHAR *pszBuffer)
                _T("CMD_RESOLVE_ALARM"),
                _T("CMD_FIND_IP_LOCATION"),
                _T("CMD_REPORT_DEVICE_STATUS"),
-               _T("CMD_REPORT_DEVICE_INFO")
+               _T("CMD_REPORT_DEVICE_INFO"),
+               _T("CMD_GET_ALARM_EVENTS")
    };
 
-   if ((wCode >= CMD_LOGIN) && (wCode <= CMD_REPORT_DEVICE_INFO))
+   if ((wCode >= CMD_LOGIN) && (wCode <= CMD_GET_ALARM_EVENTS))
       _tcscpy(pszBuffer, pszMsgNames[wCode - CMD_LOGIN]);
    else
       _sntprintf(pszBuffer, 64, _T("CMD_0x%04X"), wCode);
index b7ff9ab..f50836f 100644 (file)
 
 #include "nxcore.h"
 
-
-//
-// Global instance of alarm manager
-//
-
+/**
+ * Global instance of alarm manager
+ */
 AlarmManager g_alarmMgr;
 
-
-//
-// Fill CSCP message with alarm data
-//
-
+/**
+ * Fill NXCP message with alarm data
+ */
 void FillAlarmInfoMessage(CSCPMessage *pMsg, NXC_ALARM *pAlarm)
 {
    pMsg->SetVariable(VID_ALARM_ID, pAlarm->dwAlarmId);
@@ -59,11 +55,89 @@ void FillAlarmInfoMessage(CSCPMessage *pMsg, NXC_ALARM *pAlarm)
        pMsg->SetVariable(VID_NUM_COMMENTS, pAlarm->noteCount);
 }
 
+/**
+ * Fill NXCP message with event data from SQL query
+ * Expected field order: event_id,event_code,event_name,severity,source_object_id,event_timestamp,message
+ */
+static void FillEventData(CSCPMessage *msg, DWORD baseId, DB_RESULT hResult, int row, QWORD rootId)
+{
+       TCHAR buffer[MAX_DB_STRING];
+
+       msg->SetVariable(baseId, DBGetFieldUInt64(hResult, row, 0));
+       msg->SetVariable(baseId + 1, rootId);
+       msg->SetVariable(baseId + 2, DBGetFieldULong(hResult, row, 1));
+       msg->SetVariable(baseId + 3, DBGetField(hResult, row, 2, buffer, MAX_DB_STRING));
+       msg->SetVariable(baseId + 4, (WORD)DBGetFieldLong(hResult, row, 3));    // severity
+       msg->SetVariable(baseId + 5, DBGetFieldULong(hResult, row, 4));  // source object
+       msg->SetVariable(baseId + 6, DBGetFieldULong(hResult, row, 5));  // timestamp
+       msg->SetVariable(baseId + 7, DBGetField(hResult, row, 6, buffer, MAX_DB_STRING));
+}
 
-//
-// Alarm manager constructor
-//
+/**
+ * Get events correlated to given event into NXCP message
+ *
+ * @return number of consumed variable identifiers
+ */
+static DWORD GetCorrelatedEvents(QWORD eventId, CSCPMessage *msg, DWORD baseId, DB_HANDLE hdb)
+{
+       DWORD varId = baseId;
+       DB_STATEMENT hStmt = DBPrepare(hdb, 
+               _T("SELECT e.event_id,e.event_code,c.event_name,e.event_severity,e.event_source,e.event_timestamp,e.event_message ")
+               _T("FROM event_log e,event_cfg c WHERE e.root_event_id=? AND c.event_code=e.event_code"));
+       if (hStmt != NULL)
+       {
+               DBBind(hStmt, 1, DB_SQLTYPE_BIGINT, eventId);
+               DB_RESULT hResult = DBSelectPrepared(hStmt);
+               if (hResult != NULL)
+               {
+                       int count = DBGetNumRows(hResult);
+                       for(int i = 0; i < count; i++)
+                       {
+                               FillEventData(msg, varId, hResult, i, eventId);
+                               varId += 10;
+                               QWORD eventId = DBGetFieldUInt64(hResult, i, 0);
+                               varId += GetCorrelatedEvents(eventId, msg, varId, hdb);
+                       }
+                       DBFreeResult(hResult);
+               }
+               DBFreeStatement(hStmt);
+       }
+       return varId - baseId;
+}
+
+/**
+ * Fill NXCP message with alarm's related events
+ */
+static void FillAlarmEventsMessage(CSCPMessage *msg, DWORD alarmId)
+{
+       DB_HANDLE hdb = DBConnectionPoolAcquireConnection();
+       DB_STATEMENT hStmt = DBPrepare(hdb, _T("SELECT event_id,event_code,event_name,severity,source_object_id,event_timestamp,message FROM alarm_events WHERE alarm_id=?"));
+       if (hStmt != NULL)
+       {
+               DBBind(hStmt, 1, DB_SQLTYPE_INTEGER, alarmId);
+               DB_RESULT hResult = DBSelectPrepared(hStmt);
+               if (hResult != NULL)
+               {
+                       int count = DBGetNumRows(hResult);
+                       DWORD varId = VID_ELEMENT_LIST_BASE;
+                       for(int i = 0; i < count; i++)
+                       {
+                               FillEventData(msg, varId, hResult, i, 0);
+                               varId += 10;
+                               QWORD eventId = DBGetFieldUInt64(hResult, i, 0);
+                               varId += GetCorrelatedEvents(eventId, msg, varId, hdb);
+                       }
+                       DBFreeResult(hResult);
+                       msg->SetVariable(VID_NUM_ELEMENTS, (varId - VID_ELEMENT_LIST_BASE) / 10);
+               }
+               DBFreeStatement(hStmt);
+       }
+       DBConnectionPoolReleaseConnection(hdb);
+}
 
+/**
+ * Alarm manager constructor
+ */
 AlarmManager::AlarmManager()
 {
    m_dwNumAlarms = 0;
@@ -73,11 +147,9 @@ AlarmManager::AlarmManager()
        m_hWatchdogThread = INVALID_THREAD_HANDLE;
 }
 
-
-//
-// Alarm manager destructor
-//
-
+/**
+ * Alarm manager destructor
+ */
 AlarmManager::~AlarmManager()
 {
    safe_free(m_pAlarmList);
@@ -86,22 +158,18 @@ AlarmManager::~AlarmManager()
        ThreadJoin(m_hWatchdogThread);
 }
 
-
-//
-// Watchdog thread starter
-//
-
+/**
+ * Watchdog thread starter
+ */
 static THREAD_RESULT THREAD_CALL WatchdogThreadStarter(void *pArg)
 {
        ((AlarmManager *)pArg)->watchdogThread();
        return THREAD_OK;
 }
 
-
-//
-// Get number of notes for alarm
-//
-
+/**
+ * Get number of notes for alarm
+ */
 static DWORD GetNoteCount(DB_HANDLE hdb, DWORD alarmId)
 {
        DWORD value = 0;
@@ -121,11 +189,9 @@ static DWORD GetNoteCount(DB_HANDLE hdb, DWORD alarmId)
        return value;
 }
 
-
-//
-// Initialize alarm manager at system startup
-//
-
+/**
+ * Initialize alarm manager at system startup
+ */
 BOOL AlarmManager::init()
 {
    DB_RESULT hResult;
@@ -177,11 +243,9 @@ BOOL AlarmManager::init()
    return TRUE;
 }
 
-
-//
-// Create new alarm
-//
-
+/**
+ * Create new alarm
+ */
 void AlarmManager::newAlarm(TCHAR *pszMsg, TCHAR *pszKey, int nState,
                             int iSeverity, DWORD dwTimeout,
                                                                         DWORD dwTimeoutEvent, Event *pEvent)
@@ -284,15 +348,26 @@ void AlarmManager::newAlarm(TCHAR *pszMsg, TCHAR *pszKey, int nState,
    if ((dwObjectId != 0) && ((alarm.nState & ALARM_STATE_MASK) != ALARM_STATE_TERMINATED))
       updateObjectStatus(dwObjectId);
 
+       // Add record to alarm_events table
+       TCHAR valAlarmId[16], valEventId[32], valEventCode[16], valSeverity[16], valSource[16], valTimestamp[16];
+       const TCHAR *values[8] = { valAlarmId, valEventId, valEventCode, pEvent->getName(), valSeverity, valSource, valTimestamp, pEvent->getMessage() };
+       _sntprintf(valAlarmId, 16, _T("%d"), (int)alarm.dwAlarmId);
+       _sntprintf(valEventId, 32, UINT64_FMT, pEvent->getId());
+       _sntprintf(valEventCode, 16, _T("%d"), (int)pEvent->getCode());
+       _sntprintf(valSeverity, 16, _T("%d"), (int)pEvent->getSeverity());
+       _sntprintf(valSource, 16, _T("%d"), pEvent->getSourceId());
+       _sntprintf(valTimestamp, 16, _T("%u"), (DWORD)pEvent->getTimeStamp());
+       static int sqlTypes[8] = { DB_SQLTYPE_INTEGER, DB_SQLTYPE_BIGINT, DB_SQLTYPE_INTEGER, DB_SQLTYPE_VARCHAR, DB_SQLTYPE_INTEGER, DB_SQLTYPE_INTEGER, DB_SQLTYPE_INTEGER, DB_SQLTYPE_VARCHAR };
+       QueueSQLRequest(_T("INSERT INTO alarm_events (alarm_id,event_id,event_code,event_name,severity,source_object_id,event_timestamp,message) VALUES (?,?,?,?,?,?,?,?)"),
+                       8, sqlTypes, values);
+
        free(pszExpMsg);
    free(pszExpKey);
 }
 
-
-//
-// Acknowledge alarm with given ID
-//
-
+/**
+ * Acknowledge alarm with given ID
+ */
 DWORD AlarmManager::ackById(DWORD dwAlarmId, DWORD dwUserId, bool sticky)
 {
    DWORD i, dwObject, dwRet = RCC_INVALID_ALARM_ID;
@@ -326,12 +401,10 @@ DWORD AlarmManager::ackById(DWORD dwAlarmId, DWORD dwUserId, bool sticky)
    return dwRet;
 }
 
-
-//
-// Resolve and possibly terminate alarm with given ID
-// Should return RCC which can be sent to client
-//
-
+/**
+ * Resolve and possibly terminate alarm with given ID
+ * Should return RCC which can be sent to client
+ */
 DWORD AlarmManager::resolveById(DWORD dwAlarmId, DWORD dwUserId, bool terminate)
 {
    DWORD i, dwObject, dwRet = RCC_INVALID_ALARM_ID;
@@ -372,11 +445,9 @@ DWORD AlarmManager::resolveById(DWORD dwAlarmId, DWORD dwUserId, bool terminate)
    return dwRet;
 }
 
-
-//
-// Resolve and possibly terminate all alarms with given key
-//
-
+/**
+ * Resolve and possibly terminate all alarms with given key
+ */
 void AlarmManager::resolveByKey(const TCHAR *pszKey, bool useRegexp, bool terminate)
 {
    DWORD i, j, dwNumObjects, *pdwObjectList, dwCurrTime;
@@ -400,7 +471,7 @@ void AlarmManager::resolveByKey(const TCHAR *pszKey, bool useRegexp, bool termin
             pdwObjectList[dwNumObjects++] = m_pAlarmList[i].dwSourceObject;
          }
 
-         // Terminate alarm
+         // Resolve or terminate alarm
                        m_pAlarmList[i].nState = terminate ? ALARM_STATE_TERMINATED : ALARM_STATE_RESOLVED;
          m_pAlarmList[i].dwLastChangeTime = dwCurrTime;
                        if (terminate)
@@ -424,11 +495,9 @@ void AlarmManager::resolveByKey(const TCHAR *pszKey, bool useRegexp, bool termin
    free(pdwObjectList);
 }
 
-
-//
-// Delete alarm with given ID
-//
-
+/**
+ * Delete alarm with given ID
+ */
 void AlarmManager::deleteAlarm(DWORD dwAlarmId)
 {
    DWORD i, dwObject;
@@ -448,7 +517,9 @@ void AlarmManager::deleteAlarm(DWORD dwAlarmId)
    unlock();
 
    // Delete from database
-   _sntprintf(szQuery, 256, _T("DELETE FROM alarms WHERE alarm_id=%d"), dwAlarmId);
+   _sntprintf(szQuery, 256, _T("DELETE FROM alarms WHERE alarm_id=%d"), (int)dwAlarmId);
+   QueueSQLRequest(szQuery);
+   _sntprintf(szQuery, 256, _T("DELETE FROM alarm_events WHERE alarm_id=%d"), (int)dwAlarmId);
    QueueSQLRequest(szQuery);
 
        DB_HANDLE hdb = DBConnectionPoolAcquireConnection();
@@ -458,11 +529,9 @@ void AlarmManager::deleteAlarm(DWORD dwAlarmId)
    updateObjectStatus(dwObject);
 }
 
-
-//
-// Update alarm information in database
-//
-
+/**
+ * Update alarm information in database
+ */
 void AlarmManager::updateAlarmInDB(NXC_ALARM *pAlarm)
 {
    TCHAR szQuery[2048];
@@ -479,24 +548,26 @@ void AlarmManager::updateAlarmInDB(NXC_ALARM *pAlarm)
                             (const TCHAR *)DBPrepareString(g_hCoreDB, pAlarm->szMessage),
                                  pAlarm->dwResolvedByUser, pAlarm->dwAlarmId);
    QueueSQLRequest(szQuery);
-}
 
+       if (pAlarm->nState == ALARM_STATE_TERMINATED)
+       {
+               _sntprintf(szQuery, 256, _T("DELETE FROM alarm_events WHERE alarm_id=%d"), (int)pAlarm->dwAlarmId);
+               QueueSQLRequest(szQuery);
+       }
+}
 
-//
-// Callback for client session enumeration
-//
-
+/**
+ * Callback for client session enumeration
+ */
 void AlarmManager::sendAlarmNotification(ClientSession *pSession, void *pArg)
 {
    pSession->onAlarmUpdate(((AlarmManager *)pArg)->m_dwNotifyCode,
                            ((AlarmManager *)pArg)->m_pNotifyAlarmInfo);
 }
 
-
-//
-// Notify connected clients about changes
-//
-
+/**
+ * Notify connected clients about changes
+ */
 void AlarmManager::notifyClients(DWORD dwCode, NXC_ALARM *pAlarm)
 {
    m_dwNotifyCode = dwCode;
@@ -504,11 +575,9 @@ void AlarmManager::notifyClients(DWORD dwCode, NXC_ALARM *pAlarm)
    EnumerateClientSessions(sendAlarmNotification, this);
 }
 
-
-//
-// Send all alarms to client
-//
-
+/**
+ * Send all alarms to client
+ */
 void AlarmManager::sendAlarmsToClient(DWORD dwRqId, ClientSession *pSession)
 {
    DWORD i, dwUserId;
@@ -542,12 +611,10 @@ void AlarmManager::sendAlarmsToClient(DWORD dwRqId, ClientSession *pSession)
    pSession->sendMessage(&msg);
 }
 
-
-//
-// Get alarm with given ID into NXCP message
-// Should return RCC which can be sent to client
-//
-
+/**
+ * Get alarm with given ID into NXCP message
+ * Should return RCC that can be sent to client
+ */
 DWORD AlarmManager::getAlarm(DWORD dwAlarmId, CSCPMessage *msg)
 {
    DWORD i, dwRet = RCC_INVALID_ALARM_ID;
@@ -565,11 +632,34 @@ DWORD AlarmManager::getAlarm(DWORD dwAlarmId, CSCPMessage *msg)
        return dwRet;
 }
 
+/**
+ * Get all related events for alarm with given ID into NXCP message
+ * Should return RCC that can be sent to client
+ */
+DWORD AlarmManager::getAlarmEvents(DWORD dwAlarmId, CSCPMessage *msg)
+{
+   DWORD i, dwRet = RCC_INVALID_ALARM_ID;
 
-//
-// Get source object for given alarm id
-//
+   lock();
+   for(i = 0; i < m_dwNumAlarms; i++)
+      if (m_pAlarmList[i].dwAlarmId == dwAlarmId)
+      {
+                       dwRet = RCC_SUCCESS;
+         break;
+      }
+   unlock();
 
+       // we don't call FillAlarmEventsMessage from within loop
+       // to prevent alarm list lock for a long time
+       if (dwRet == RCC_SUCCESS)
+               FillAlarmEventsMessage(msg, dwAlarmId);
+
+       return dwRet;
+}
+
+/**
+ * Get source object for given alarm id
+ */
 NetObj *AlarmManager::getAlarmSourceObject(DWORD dwAlarmId)
 {
    DWORD i, dwObjectId = 0;
@@ -604,12 +694,10 @@ NetObj *AlarmManager::getAlarmSourceObject(DWORD dwAlarmId)
    return FindObjectById(dwObjectId);
 }
 
-
-//
-// Get most critical status among active alarms for given object
-// Will return STATUS_UNKNOWN if there are no active alarms
-//
-
+/**
+ * Get most critical status among active alarms for given object
+ * Will return STATUS_UNKNOWN if there are no active alarms
+ */
 int AlarmManager::getMostCriticalStatusForObject(DWORD dwObjectId)
 {
    DWORD i;
index 476b9dc..59c99b4 100644 (file)
@@ -325,13 +325,13 @@ void DumpClientSessions(CONSOLE_CTX pCtx)
 /**
  * Enumerate active sessions
  */
-void NXCORE_EXPORTABLE EnumerateClientSessions(void (*pHandler)(ClientSession *, void *), void *pArg, ClientSession *current)
+void NXCORE_EXPORTABLE EnumerateClientSessions(void (*pHandler)(ClientSession *, void *), void *pArg)
 {
    int i;
 
    RWLockReadLock(m_rwlockSessionListAccess, INFINITE);
    for(i = 0; i < MAX_CLIENT_SESSIONS; i++)
-      if (m_pSessionList[i] != NULL && (current != NULL && m_pSessionList[i] != current))
+      if (m_pSessionList[i] != NULL)
          pHandler(m_pSessionList[i], pArg);
    RWLockUnlock(m_rwlockSessionListAccess);
 }
index 5716a5a..82b55c0 100644 (file)
@@ -137,8 +137,8 @@ DEFINE_THREAD_STARTER(getCollectedData)
 DEFINE_THREAD_STARTER(getTableCollectedData)
 DEFINE_THREAD_STARTER(clearDCIData)
 DEFINE_THREAD_STARTER(queryL2Topology)
-DEFINE_THREAD_STARTER(SendEventLog)
-DEFINE_THREAD_STARTER(SendSyslog)
+DEFINE_THREAD_STARTER(sendEventLog)
+DEFINE_THREAD_STARTER(sendSyslog)
 DEFINE_THREAD_STARTER(createObject)
 DEFINE_THREAD_STARTER(getServerFile)
 DEFINE_THREAD_STARTER(getAgentFile)
@@ -736,16 +736,16 @@ void ClientSession::processingThread()
             sendSelectedObjects(pMsg);
             break;
          case CMD_GET_EVENTS:
-            CALL_IN_NEW_THREAD(SendEventLog, pMsg);
+            CALL_IN_NEW_THREAD(sendEventLog, pMsg);
             break;
          case CMD_GET_CONFIG_VARLIST:
-            SendAllConfigVars(pMsg->GetId());
+            sendAllConfigVars(pMsg->GetId());
             break;
          case CMD_SET_CONFIG_VARIABLE:
-            SetConfigVariable(pMsg);
+            setConfigVariable(pMsg);
             break;
          case CMD_DELETE_CONFIG_VARIABLE:
-            DeleteConfigVariable(pMsg);
+            deleteConfigVariable(pMsg);
             break;
                        case CMD_CONFIG_GET_CLOB:
                                getConfigCLOB(pMsg);
@@ -772,25 +772,25 @@ void ClientSession::processingThread()
             changeObjectMgmtStatus(pMsg);
             break;
          case CMD_LOAD_USER_DB:
-            SendUserDB(pMsg->GetId());
+            sendUserDB(pMsg->GetId());
             break;
          case CMD_CREATE_USER:
-            CreateUser(pMsg);
+            createUser(pMsg);
             break;
          case CMD_UPDATE_USER:
-            UpdateUser(pMsg);
+            updateUser(pMsg);
             break;
          case CMD_DELETE_USER:
-            DeleteUser(pMsg);
+            deleteUser(pMsg);
             break;
          case CMD_LOCK_USER_DB:
-            LockUserDB(pMsg->GetId(), TRUE);
+            lockUserDB(pMsg->GetId(), TRUE);
             break;
          case CMD_UNLOCK_USER_DB:
-            LockUserDB(pMsg->GetId(), FALSE);
+            lockUserDB(pMsg->GetId(), FALSE);
             break;
          case CMD_SET_PASSWORD:
-            SetPassword(pMsg);
+            setPassword(pMsg);
             break;
          case CMD_GET_NODE_DCI_LIST:
             openNodeDCIList(pMsg);
@@ -863,6 +863,9 @@ void ClientSession::processingThread()
          case CMD_GET_ALARM:
             getAlarm(pMsg);
             break;
+         case CMD_GET_ALARM_EVENTS:
+            getAlarmEvents(pMsg);
+            break;
          case CMD_ACK_ALARM:
             acknowledgeAlarm(pMsg);
             break;
@@ -897,10 +900,10 @@ void ClientSession::processingThread()
             forcedNodePoll(pMsg);
             break;
          case CMD_TRAP:
-            OnTrap(pMsg);
+            onTrap(pMsg);
             break;
          case CMD_WAKEUP_NODE:
-            OnWakeUpNode(pMsg);
+            onWakeUpNode(pMsg);
             break;
          case CMD_CREATE_TRAP:
             EditTrap(TRAP_CREATE, pMsg);
@@ -999,13 +1002,13 @@ void ClientSession::processingThread()
             generateObjectToolId(pMsg->GetId());
             break;
          case CMD_CHANGE_SUBSCRIPTION:
-            ChangeSubscription(pMsg);
+            changeSubscription(pMsg);
             break;
          case CMD_GET_SYSLOG:
-            CALL_IN_NEW_THREAD(SendSyslog, pMsg);
+            CALL_IN_NEW_THREAD(sendSyslog, pMsg);
             break;
          case CMD_GET_SERVER_STATS:
-            SendServerStats(pMsg->GetId());
+            sendServerStats(pMsg->GetId());
             break;
          case CMD_GET_SCRIPT_LIST:
             sendScriptList(pMsg->GetId());
@@ -1113,7 +1116,7 @@ void ClientSession::processingThread()
                                CALL_IN_NEW_THREAD(queryL2Topology, pMsg);
                                break;
                        case CMD_SEND_SMS:
-                               SendSMS(pMsg);
+                               sendSMS(pMsg);
                                break;
                        case CMD_GET_COMMUNITY_LIST:
                                SendCommunityList(pMsg->GetId());
@@ -1610,6 +1613,7 @@ void ClientSession::login(CSCPMessage *pRequest)
          msg.SetVariable(VID_RCC, RCC_SUCCESS);
          msg.SetVariable(VID_USER_SYS_RIGHTS, m_dwSystemAccess);
          msg.SetVariable(VID_USER_ID, m_dwUserId);
+                       msg.SetVariable(VID_SESSION_ID, m_dwIndex);
                        msg.SetVariable(VID_CHANGE_PASSWD_FLAG, (WORD)changePasswd);
          msg.SetVariable(VID_DBCONN_STATUS, (WORD)((g_dwFlags & AF_DB_CONNECTION_LOST) ? 0 : 1));
                        msg.SetVariable(VID_ZONING_ENABLED, (WORD)((g_dwFlags & AF_ENABLE_ZONING) ? 1 : 0));
@@ -2005,12 +2009,10 @@ void ClientSession::sendSelectedObjects(CSCPMessage *pRequest)
        }
 }
 
-
-//
-// Send event log records to client
-//
-
-void ClientSession::SendEventLog(CSCPMessage *pRequest)
+/**
+ * Send event log records to client
+ */
+void ClientSession::sendEventLog(CSCPMessage *pRequest)
 {
    CSCPMessage msg;
    DB_ASYNC_RESULT hResult = NULL;
@@ -2117,12 +2119,10 @@ void ClientSession::SendEventLog(CSCPMessage *pRequest)
    MutexUnlock(m_mutexSendEvents);
 }
 
-
-//
-// Send all configuration variables to client
-//
-
-void ClientSession::SendAllConfigVars(DWORD dwRqId)
+/**
+ * Send all configuration variables to client
+ */
+void ClientSession::sendAllConfigVars(DWORD dwRqId)
 {
    DWORD i, dwId, dwNumRecords;
    CSCPMessage msg;
@@ -2164,12 +2164,10 @@ void ClientSession::SendAllConfigVars(DWORD dwRqId)
    sendMessage(&msg);
 }
 
-
-//
-// Set configuration variable's value
-//
-
-void ClientSession::SetConfigVariable(CSCPMessage *pRequest)
+/**
+ * Set configuration variable's value
+ */
+void ClientSession::setConfigVariable(CSCPMessage *pRequest)
 {
    CSCPMessage msg;
    TCHAR szName[MAX_OBJECT_NAME], szValue[MAX_DB_STRING];
@@ -2203,12 +2201,10 @@ void ClientSession::SetConfigVariable(CSCPMessage *pRequest)
    sendMessage(&msg);
 }
 
-
-//
-// Delete configuration variable
-//
-
-void ClientSession::DeleteConfigVariable(CSCPMessage *pRequest)
+/**
+ * Delete configuration variable
+ */
+void ClientSession::deleteConfigVariable(CSCPMessage *pRequest)
 {
    CSCPMessage msg;
    TCHAR szName[MAX_OBJECT_NAME], szQuery[1024];
@@ -2376,11 +2372,9 @@ void ClientSession::onObjectChange(NetObj *pObject)
       }
 }
 
-
-//
-// Send notification message to server
-//
-
+/**
+ * Send notification message to server
+ */
 void ClientSession::notify(DWORD dwCode, DWORD dwData)
 {
    CSCPMessage msg;
@@ -2391,11 +2385,9 @@ void ClientSession::notify(DWORD dwCode, DWORD dwData)
    sendMessage(&msg);
 }
 
-
-//
-// Modify object
-//
-
+/**
+ * Modify object
+ */
 void ClientSession::modifyObject(CSCPMessage *pRequest)
 {
    DWORD dwObjectId, dwResult = RCC_SUCCESS;
@@ -2465,12 +2457,10 @@ void ClientSession::modifyObject(CSCPMessage *pRequest)
    sendMessage(&msg);
 }
 
-
-//
-// Send users database to client
-//
-
-void ClientSession::SendUserDB(DWORD dwRqId)
+/**
+ * Send users database to client
+ */
+void ClientSession::sendUserDB(DWORD dwRqId)
 {
    CSCPMessage msg;
        UserDatabaseObject **users;
@@ -2499,12 +2489,10 @@ void ClientSession::SendUserDB(DWORD dwRqId)
    sendMessage(&msg);
 }
 
-
-//
-// Create new user
-//
-
-void ClientSession::CreateUser(CSCPMessage *pRequest)
+/**
+ * Create new user
+ */
+void ClientSession::createUser(CSCPMessage *pRequest)
 {
    CSCPMessage msg;
 
@@ -2548,12 +2536,10 @@ void ClientSession::CreateUser(CSCPMessage *pRequest)
    sendMessage(&msg);
 }
 
-
-//
-// Update existing user's data
-//
-
-void ClientSession::UpdateUser(CSCPMessage *pRequest)
+/**
+ * Update existing user's data
+ */
+void ClientSession::updateUser(CSCPMessage *pRequest)
 {
    CSCPMessage msg;
 
@@ -2581,12 +2567,10 @@ void ClientSession::UpdateUser(CSCPMessage *pRequest)
    sendMessage(&msg);
 }
 
-
-//
-// Delete user
-//
-
-void ClientSession::DeleteUser(CSCPMessage *pRequest)
+/**
+ * Delete user
+ */
+void ClientSession::deleteUser(CSCPMessage *pRequest)
 {
    CSCPMessage msg;
    DWORD dwUserId;
@@ -2629,12 +2613,10 @@ void ClientSession::DeleteUser(CSCPMessage *pRequest)
    sendMessage(&msg);
 }
 
-
-//
-// Lock/unlock user database
-//
-
-void ClientSession::LockUserDB(DWORD dwRqId, BOOL bLock)
+/**
+ * Lock/unlock user database
+ */
+void ClientSession::lockUserDB(DWORD dwRqId, BOOL bLock)
 {
    CSCPMessage msg;
    TCHAR szBuffer[256];
@@ -2762,7 +2744,7 @@ void ClientSession::changeObjectMgmtStatus(CSCPMessage *pRequest)
 /**
  * Set user's password
  */
-void ClientSession::SetPassword(CSCPMessage *pRequest)
+void ClientSession::setPassword(CSCPMessage *pRequest)
 {
    CSCPMessage msg;
    DWORD dwUserId;
@@ -4557,11 +4539,9 @@ void ClientSession::onAlarmUpdate(DWORD dwCode, NXC_ALARM *pAlarm)
    }
 }
 
-
-//
-// Send all alarms to client
-//
-
+/**
+ * Send all alarms to client
+ */
 void ClientSession::sendAllAlarms(DWORD dwRqId)
 {
    MutexLock(m_mutexSendAlarms);
@@ -4569,28 +4549,24 @@ void ClientSession::sendAllAlarms(DWORD dwRqId)
    MutexUnlock(m_mutexSendAlarms);
 }
 
-
-//
-// Get specific alarm object
-//
-
-void ClientSession::getAlarm(CSCPMessage *pRequest)
+/**
+ * Get specific alarm object
+ */
+void ClientSession::getAlarm(CSCPMessage *request)
 {
    CSCPMessage msg;
-   NetObj *pObject;
-   DWORD dwAlarmId;
 
    // Prepare response message
    msg.SetCode(CMD_REQUEST_COMPLETED);
-   msg.SetId(pRequest->GetId());
+   msg.SetId(request->GetId());
 
    // Get alarm id and it's source object
-   dwAlarmId = pRequest->GetVariableLong(VID_ALARM_ID);
-   pObject = g_alarmMgr.getAlarmSourceObject(dwAlarmId);
-   if (pObject != NULL)
+   DWORD dwAlarmId = request->GetVariableLong(VID_ALARM_ID);
+   NetObj *object = g_alarmMgr.getAlarmSourceObject(dwAlarmId);
+   if (object != NULL)
    {
       // User should have "view alarm" right to the object
-      if (pObject->CheckAccessRights(m_dwUserId, OBJECT_ACCESS_READ_ALARMS))
+      if (object->CheckAccessRights(m_dwUserId, OBJECT_ACCESS_READ_ALARMS))
       {
          msg.SetVariable(VID_RCC, g_alarmMgr.getAlarm(dwAlarmId, &msg));
       }
@@ -4610,11 +4586,47 @@ void ClientSession::getAlarm(CSCPMessage *pRequest)
    sendMessage(&msg);
 }
 
+/**
+ * Get all related events for specific alarm object
+ */
+void ClientSession::getAlarmEvents(CSCPMessage *request)
+{
+   CSCPMessage msg;
 
-//
-// Acknowledge alarm
-//
+   // Prepare response message
+   msg.SetCode(CMD_REQUEST_COMPLETED);
+   msg.SetId(request->GetId());
 
+   // Get alarm id and it's source object
+   DWORD dwAlarmId = request->GetVariableLong(VID_ALARM_ID);
+   NetObj *object = g_alarmMgr.getAlarmSourceObject(dwAlarmId);
+   if (object != NULL)
+   {
+      // User should have "view alarm" right to the object and
+               // system-wide "view event log" access
+      if ((m_dwSystemAccess & SYSTEM_ACCESS_VIEW_EVENT_LOG) && object->CheckAccessRights(m_dwUserId, OBJECT_ACCESS_READ_ALARMS))
+      {
+         msg.SetVariable(VID_RCC, g_alarmMgr.getAlarmEvents(dwAlarmId, &msg));
+      }
+      else
+      {
+         msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
+      }
+   }
+   else
+   {
+      // Normally, for existing alarms pObject will not be NULL,
+      // so we assume that alarm id is invalid
+      msg.SetVariable(VID_RCC, RCC_INVALID_ALARM_ID);
+   }
+
+   // Send response
+   sendMessage(&msg);
+}
+
+/**
+ * Acknowledge alarm
+ */
 void ClientSession::acknowledgeAlarm(CSCPMessage *pRequest)
 {
    CSCPMessage msg;
@@ -5127,12 +5139,10 @@ void ClientSession::pollerThread(Node *pNode, int iPollType, DWORD dwRqId)
    sendMessage(&msg);
 }
 
-
-//
-// Receive event from user
-//
-
-void ClientSession::OnTrap(CSCPMessage *pRequest)
+/**
+ * Receive event from user
+ */
+void ClientSession::onTrap(CSCPMessage *pRequest)
 {
    CSCPMessage msg;
    DWORD dwObjectId, dwEventCode;
@@ -5221,12 +5231,10 @@ void ClientSession::OnTrap(CSCPMessage *pRequest)
    sendMessage(&msg);
 }
 
-
-//
-// Wake up node
-//
-
-void ClientSession::OnWakeUpNode(CSCPMessage *pRequest)
+/**
+ * Wake up node
+ */
+void ClientSession::onWakeUpNode(CSCPMessage *pRequest)
 {
    NetObj *pObject;
    CSCPMessage msg;
@@ -7017,12 +7025,10 @@ void ClientSession::execTableTool(CSCPMessage *pRequest)
    sendMessage(&msg);
 }
 
-
-//
-// Change current subscription
-//
-
-void ClientSession::ChangeSubscription(CSCPMessage *pRequest)
+/**
+ * Change current subscription
+ */
+void ClientSession::changeSubscription(CSCPMessage *pRequest)
 {
    CSCPMessage msg;
    DWORD dwFlags;
@@ -7044,17 +7050,18 @@ void ClientSession::ChangeSubscription(CSCPMessage *pRequest)
    sendMessage(&msg);
 }
 
-
-//
-// Send server statistics
-//
-
+/**
+ * Callback for counting DCIs in the system
+ */
 static void DciCountCallback(NetObj *object, void *data)
 {
        *((DWORD *)data) += ((Node *)object)->getItemCount();
 }
 
-void ClientSession::SendServerStats(DWORD dwRqId)
+/**
+ * Send server statistics
+ */
+void ClientSession::sendServerStats(DWORD dwRqId)
 {
    CSCPMessage msg;
 #ifdef _WIN32
@@ -7361,11 +7368,9 @@ void ClientSession::deleteScript(CSCPMessage *pRequest)
    sendMessage(&msg);
 }
 
-
-//
-// Copy session data to message
-//
-
+/**
+ * Copy session data to message
+ */
 static void CopySessionData(ClientSession *pSession, void *pArg)
 {
    DWORD dwId, dwIndex;
@@ -7380,11 +7385,9 @@ static void CopySessionData(ClientSession *pSession, void *pArg)
    ((CSCPMessage *)pArg)->SetVariable(dwId++, (TCHAR *)pSession->getClientInfo());
 }
 
-
-//
-// Send list of connected client sessions
-//
-
+/**
+ * Send list of connected client sessions
+ */
 void ClientSession::SendSessionList(DWORD dwRqId)
 {
    CSCPMessage msg;
@@ -7443,12 +7446,10 @@ void ClientSession::onSyslogMessage(NX_SYSLOG_RECORD *pRec)
    }
 }
 
-
-//
-// Get latest syslog records
-//
-
-void ClientSession::SendSyslog(CSCPMessage *pRequest)
+/**
+ * Get latest syslog records
+ */
+void ClientSession::sendSyslog(CSCPMessage *pRequest)
 {
    CSCPMessage msg;
    DWORD dwMaxRecords, dwNumRows, dwId;
@@ -9692,12 +9693,10 @@ void ClientSession::queryL2Topology(CSCPMessage *pRequest)
        sendMessage(&msg);
 }
 
-
-//
-// Send SMS
-//
-
-void ClientSession::SendSMS(CSCPMessage *pRequest)
+/**
+ * Send SMS
+ */
+void ClientSession::sendSMS(CSCPMessage *pRequest)
 {
    CSCPMessage msg;
        TCHAR phone[256], message[256];
@@ -11074,7 +11073,7 @@ void ClientSession::updateLibraryImage(CSCPMessage *request)
 
        if (rcc == RCC_SUCCESS)
        {
-               EnumerateClientSessions(SendLibraryImageUpdate, (void *)&guid, this);
+               EnumerateClientSessions(SendLibraryImageUpdate, (void *)&guid);
        }
 }
 
@@ -11137,15 +11136,13 @@ void ClientSession::deleteLibraryImage(CSCPMessage *request)
 
        if (rcc == RCC_SUCCESS)
        {
-               EnumerateClientSessions(SendLibraryImageUpdate, (void *)&guid, this);
+               EnumerateClientSessions(SendLibraryImageUpdate, (void *)&guid);
        }
 }
 
-
-//
-// Send list of available images (in category)
-//
-
+/**
+ * Send list of available images (in category)
+ */
 void ClientSession::listLibraryImages(CSCPMessage *request)
 {
        CSCPMessage msg;
@@ -11209,11 +11206,9 @@ void ClientSession::listLibraryImages(CSCPMessage *request)
        sendMessage(&msg);
 }
 
-
-//
-// Execute server side command on object
-//
-
+/**
+ * Execute server side command on object
+ */
 static THREAD_RESULT THREAD_CALL RunCommand(void *arg)
 {
        DbgPrintf(5, _T("Running server-side command: %s"), (TCHAR *)arg);
index 25679ad..fde1144 100644 (file)
@@ -64,6 +64,7 @@ public:
        DWORD updateAlarmNote(DWORD alarmId, DWORD noteId, const TCHAR *text, DWORD userId);
 
    DWORD getAlarm(DWORD dwAlarmId, CSCPMessage *msg);
+   DWORD getAlarmEvents(DWORD dwAlarmId, CSCPMessage *msg);
    void sendAlarmsToClient(DWORD dwRqId, ClientSession *pSession);
    void getAlarmStats(CSCPMessage *pMsg);
        DWORD getAlarmNotes(DWORD alarmId, CSCPMessage *msg);
index 07bf6e9..1328063 100644 (file)
@@ -453,8 +453,8 @@ private:
        DECLARE_THREAD_STARTER(queryParameter)
        DECLARE_THREAD_STARTER(queryAgentTable)
        DECLARE_THREAD_STARTER(queryL2Topology)
-       DECLARE_THREAD_STARTER(SendEventLog)
-       DECLARE_THREAD_STARTER(SendSyslog)
+       DECLARE_THREAD_STARTER(sendEventLog)
+       DECLARE_THREAD_STARTER(sendSyslog)
        DECLARE_THREAD_STARTER(createObject)
        DECLARE_THREAD_STARTER(getServerFile)
        DECLARE_THREAD_STARTER(getAgentFile)
@@ -485,17 +485,17 @@ private:
    void login(CSCPMessage *pRequest);
    void sendAllObjects(CSCPMessage *pRequest);
    void sendSelectedObjects(CSCPMessage *pRequest);
-   void SendEventLog(CSCPMessage *pRequest);
-   void SendAllConfigVars(DWORD dwRqId);
-   void SetConfigVariable(CSCPMessage *pRequest);
-   void DeleteConfigVariable(CSCPMessage *pRequest);
-   void SendUserDB(DWORD dwRqId);
+   void sendEventLog(CSCPMessage *pRequest);
+   void sendAllConfigVars(DWORD dwRqId);
+   void setConfigVariable(CSCPMessage *pRequest);
+   void deleteConfigVariable(CSCPMessage *pRequest);
+   void sendUserDB(DWORD dwRqId);
    void sendAllAlarms(DWORD dwRqId);
-   void CreateUser(CSCPMessage *pRequest);
-   void UpdateUser(CSCPMessage *pRequest);
-   void DeleteUser(CSCPMessage *pRequest);
-   void SetPassword(CSCPMessage *pRequest);
-   void LockUserDB(DWORD dwRqId, BOOL bLock);
+   void createUser(CSCPMessage *pRequest);
+   void updateUser(CSCPMessage *pRequest);
+   void deleteUser(CSCPMessage *pRequest);
+   void setPassword(CSCPMessage *pRequest);
+   void lockUserDB(DWORD dwRqId, BOOL bLock);
    void sendEventDB(DWORD dwRqId);
    void modifyEventTemplate(CSCPMessage *pRequest);
    void deleteEventTemplate(CSCPMessage *pRequest);
@@ -521,13 +521,14 @@ private:
    void processEPPRecord(CSCPMessage *pRequest);
    void sendMIBTimestamp(DWORD dwRqId);
    void sendMib(CSCPMessage *request);
-   void createObject(CSCPMessage *pRequest);
-   void changeObjectBinding(CSCPMessage *pRequest, BOOL bBind);
-   void deleteObject(CSCPMessage *pRequest);
-   void getAlarm(CSCPMessage *pRequest);
-   void acknowledgeAlarm(CSCPMessage *pRequest);
-   void resolveAlarm(CSCPMessage *pRequest, bool terminate);
-   void deleteAlarm(CSCPMessage *pRequest);
+   void createObject(CSCPMessage *request);
+   void changeObjectBinding(CSCPMessage *request, BOOL bBind);
+   void deleteObject(CSCPMessage *request);
+   void getAlarm(CSCPMessage *request);
+   void getAlarmEvents(CSCPMessage *request);
+   void acknowledgeAlarm(CSCPMessage *request);
+   void resolveAlarm(CSCPMessage *request, bool terminate);
+   void deleteAlarm(CSCPMessage *request);
        void getAlarmNotes(CSCPMessage *pRequest);
        void updateAlarmNote(CSCPMessage *pRequest);
    void createAction(CSCPMessage *pRequest);
@@ -536,8 +537,8 @@ private:
    void sendAllActions(DWORD dwRqId);
    void SendContainerCategories(DWORD dwRqId);
    void forcedNodePoll(CSCPMessage *pRequest);
-   void OnTrap(CSCPMessage *pRequest);
-   void OnWakeUpNode(CSCPMessage *pRequest);
+   void onTrap(CSCPMessage *pRequest);
+   void onWakeUpNode(CSCPMessage *pRequest);
    void queryParameter(CSCPMessage *pRequest);
    void queryAgentTable(CSCPMessage *pRequest);
    void EditTrap(int iOperation, CSCPMessage *pRequest);
@@ -565,9 +566,9 @@ private:
    void deleteObjectTool(CSCPMessage *pRequest);
    void generateObjectToolId(DWORD dwRqId);
    void execTableTool(CSCPMessage *pRequest);
-   void ChangeSubscription(CSCPMessage *pRequest);
-   void SendSyslog(CSCPMessage *pRequest);
-   void SendServerStats(DWORD dwRqId);
+   void changeSubscription(CSCPMessage *pRequest);
+   void sendSyslog(CSCPMessage *pRequest);
+   void sendServerStats(DWORD dwRqId);
    void sendScriptList(DWORD dwRqId);
    void sendScript(CSCPMessage *pRequest);
    void updateScript(CSCPMessage *pRequest);
@@ -604,7 +605,7 @@ private:
        void UpdateCertificateComments(CSCPMessage *pRequest);
        void SendCertificateList(DWORD dwRqId);
        void queryL2Topology(CSCPMessage *pRequest);
-       void SendSMS(CSCPMessage *pRequest);
+       void sendSMS(CSCPMessage *pRequest);
        void SendCommunityList(DWORD dwRqId);
        void UpdateCommunityList(CSCPMessage *pRequest);
        void SendSituationList(DWORD dwRqId);
@@ -814,7 +815,7 @@ Node *PollNewNode(DWORD dwIpAddr, DWORD dwNetMask, DWORD dwCreationFlags, WORD a
                   WORD snmpPort, TCHAR *pszName, DWORD dwProxyNode, DWORD dwSNMPProxy, Cluster *pCluster, 
                                                DWORD zoneId, bool doConfPoll, bool discoveredNode);
 
-void NXCORE_EXPORTABLE EnumerateClientSessions(void (*pHandler)(ClientSession *, void *), void *pArg, ClientSession *current = NULL);
+void NXCORE_EXPORTABLE EnumerateClientSessions(void (*pHandler)(ClientSession *, void *), void *pArg);
 void NXCORE_EXPORTABLE NotifyClientSessions(DWORD dwCode, DWORD dwData);
 int GetSessionCount();
 
index f64f37b..ed45216 100644 (file)
@@ -22,7 +22,6 @@
 
 #include "nxdbmgr.h"
 
-
 /**
  * Externals
  */
@@ -263,6 +262,26 @@ static BOOL CreateEventTemplate(int code, const TCHAR *name, int severity, int f
 }
 
 /**
+ * Upgrade from V264 to V265
+ */
+static BOOL H_UpgradeFromV264(int currVersion, int newVersion)
+{
+       CHK_EXEC(CreateTable(_T("CREATE TABLE alarm_events (")
+                            _T("alarm_id integer not null,")
+                                                               _T("event_id $SQL:INT64 not null,")
+                            _T("event_code integer not null,")
+                            _T("event_name varchar(63) null,")
+                            _T("severity integer not null,")
+                            _T("source_object_id integer not null,")
+                            _T("event_timestamp integer not null,")
+                            _T("message varchar(255) null,")
+                            _T("PRIMARY KEY(alarm_id,event_id))")));
+       CHK_EXEC(SQLQuery(_T("CREATE INDEX idx_alarm_events_alarm_id ON alarm_events(alarm_id)")));
+       CHK_EXEC(SQLQuery(_T("UPDATE metadata SET var_value='265' WHERE var_name='SchemaVersion'")));
+       return TRUE;
+}
+
+/**
  * Upgrade from V263 to V264
  */
 static BOOL H_UpgradeFromV263(int currVersion, int newVersion)
@@ -6468,6 +6487,7 @@ static struct
        { 261, 262, H_UpgradeFromV261 },
        { 262, 263, H_UpgradeFromV262 },
        { 263, 264, H_UpgradeFromV263 },
+       { 264, 265, H_UpgradeFromV264 },
    { 0, 0, NULL }
 };