- more SLM changes
authorAlex Kalimulin <alex@netxms.org>
Sun, 21 Aug 2011 21:57:21 +0000 (21:57 +0000)
committerAlex Kalimulin <alex@netxms.org>
Sun, 21 Aug 2011 21:57:21 +0000 (21:57 +0000)
sql/schema.in
src/server/core/bizservice.cpp
src/server/core/main.cpp
src/server/core/nodelink.cpp
src/server/core/slm.cpp
src/server/core/slmcheck.cpp
src/server/include/nms_core.h
src/server/include/nms_objects.h

index 8ec76cb..046aa9d 100644 (file)
@@ -1253,7 +1253,6 @@ CREATE TABLE slm_checks
      type integer default 1 not null, // 1 - threshold, 2 - script
      content SQL_TEXT, // if type == 2
      threshold_id integer default 0 not null, // if type == 1; refers to thresholds.id
-     state integer not null,   // 1 - check ok, 0 - check failed
      reason varchar(255) not null,
      PRIMARY KEY(check_id)
 ) TABLE_TYPE;
index 6a2fcec..ebc5f36 100644 (file)
@@ -32,7 +32,9 @@
 BizService::BizService()
      :Container()
 {
-       m_busy = FALSE;
+       m_dwId = 0;
+       m_busy = false;
+       m_lastPollTime = time_t(0);
        _tcscpy(m_szName, _T("Default"));
 }
 
@@ -46,6 +48,7 @@ BizService::BizService(const TCHAR *name)
 {
        m_dwId = 0;
        m_busy = false;
+       m_lastPollTime = time_t(0);
        nx_strncpy(m_szName, name, MAX_OBJECT_NAME);
 }
 
@@ -58,15 +61,20 @@ BizService::~BizService()
 {
 }
 
+//
+// Calculate status for compound object based on childs status
+//
+
 void BizService::calculateCompoundStatus(BOOL bForcedRecalc /*= FALSE*/)
 {
        int i, iCount, iMostCriticalStatus;
+       int iOldStatus = m_iStatus;
 
+       // Calculate own status by selecting the most critical status of the kids
        LockChildList(FALSE);
-
        for(i = 0, iCount = 0, iMostCriticalStatus = -1; i < int(m_dwChildCount); i++)
        {
-               int iChildStatus = m_pChildList[i]->PropagatedStatus();
+               int iChildStatus = m_pChildList[i]->Status();
                if ((iChildStatus < STATUS_UNKNOWN) &&
                        (iChildStatus > iMostCriticalStatus))
                {
@@ -75,8 +83,17 @@ void BizService::calculateCompoundStatus(BOOL bForcedRecalc /*= FALSE*/)
                }
        }
        m_iStatus = (iCount > 0) ? iMostCriticalStatus : STATUS_UNKNOWN;
-
        UnlockChildList();
+
+       // Cause parent object(s) to recalculate it's status
+       if ((iOldStatus != m_iStatus) || bForcedRecalc)
+       {
+               LockParentList(FALSE);
+               for(i = 0; i < int(m_dwParentCount); i++)
+                       m_pParentList[i]->calculateCompoundStatus();
+               UnlockParentList();
+               Modify();   /* LOCK? */
+       }
 }
 
 //
@@ -219,22 +236,33 @@ DWORD BizService::ModifyFromMessage(CSCPMessage *pRequest, BOOL bAlreadyLocked)
    return NetObj::ModifyFromMessage(pRequest, TRUE);
 }
 
+bool BizService::isReadyForPolling()
+{
+       return time(NULL) - m_lastPollTime > g_dwSlmPollingInterval && !m_busy;
+}
+
+void BizService::lockForPolling()
+{
+       m_busy = true;
+}
+
 //
-// A callback for poller
+// A callback for poller threads
 //
 
 void BizService::poll( ClientSession *pSession, DWORD dwRqId, int nPoller )
 {
+       m_lastPollTime = time(NULL);
+
+       // Loop through the kids and execute their either scripts or thresholds
        for (int i = 0; i < int(m_dwChildCount); i++)
        {
                if (m_pChildList[i]->Type() == OBJECT_SLMCHECK)
                        ((SlmCheck*)m_pChildList[i])->execute();
        }
 
-       LockParentList(FALSE);
-       for(int i = 0; i < int(m_dwParentCount); i++)
-               m_pParentList[i]->calculateCompoundStatus();
-       UnlockParentList();
+       // Set the status based on what the kids' been up to
+       this->calculateCompoundStatus();
 
        m_busy = false;
 }
index befa060..9fb26af 100644 (file)
@@ -121,6 +121,7 @@ DWORD g_dwTopologyPollingInterval;
 DWORD g_dwConditionPollingInterval;
 DWORD g_dwPingSize;
 DWORD g_dwAuditFlags;
+DWORD g_dwSlmPollingInterval;
 TCHAR g_szDataDir[MAX_PATH] = _T("");
 TCHAR g_szLibDir[MAX_PATH] = DEFAULT_LIBDIR;
 int g_nDBSyntax = DB_SYNTAX_UNKNOWN;
@@ -278,6 +279,7 @@ static void LoadGlobalConfig()
        g_dwRoutingTableUpdateInterval = ConfigReadInt(_T("RoutingTableUpdateInterval"), 300);
        g_dwTopologyPollingInterval = ConfigReadInt(_T("TopologyPollingInterval"), 1800);
        g_dwConditionPollingInterval = ConfigReadInt(_T("ConditionPollingInterval"), 60);
+       g_dwSlmPollingInterval = ConfigReadInt(_T("SlmPollingInterval"), 60);
        if (ConfigReadInt(_T("DeleteEmptySubnets"), 1))
                g_dwFlags |= AF_DELETE_EMPTY_SUBNETS;
        if (ConfigReadInt(_T("EnableSNMPTraps"), 1))
index 358cd52..dc1226e 100644 (file)
@@ -30,7 +30,7 @@
 //
 
 NodeLink::NodeLink()
-:NetObj()
+:Container()
 {
        _tcscpy(m_szName, _T("Default"));
 }
@@ -41,7 +41,7 @@ NodeLink::NodeLink()
 //
 
 NodeLink::NodeLink(const TCHAR *name)
-:NetObj()
+:Container()
 {
        nx_strncpy(m_szName, name, MAX_OBJECT_NAME);
 }
@@ -121,7 +121,6 @@ BOOL NodeLink::CreateFromDB(DWORD id)
 BOOL NodeLink::SaveToDB(DB_HANDLE hdb)
 {
        BOOL bNewObject = TRUE;
-       TCHAR szQuery[QUERY_LENGTH];
 
        LockData();
 
@@ -142,21 +141,18 @@ BOOL NodeLink::SaveToDB(DB_HANDLE hdb)
        }
        DBFreeStatement(hStmt);
 
-       if (bNewObject)
-               nx_strncpy(szQuery, _T("INSERT INTO node_links (node_id, nodelink_id) VALUES (?, ?)"), QUERY_LENGTH);
-       else
-               nx_strncpy(szQuery, _T("UPDATE node_links SET node_id=? WHERE nodelink_id=?"), QUERY_LENGTH);
-       hStmt = DBPrepare(g_hCoreDB, szQuery);
+       hStmt = DBPrepare(g_hCoreDB, bNewObject ? _T("INSERT INTO node_links (node_id,nodelink_id) VALUES (?,?)") :
+                                                                                         _T("UPDATE node_links SET node_id=? WHERE nodelink_id=?"));
        if (hStmt == NULL)      
        {
-               DbgPrintf(4, _T("Cannot prepare %s from node_links"), bNewObject ? _T("insert") : _T("update"));
+               // DbgPrintf(4, _T("Cannot prepare %s from node_links"), bNewObject ? _T("insert") : _T("update"));
                return FALSE;
        }
        DBBind(hStmt, 1, DB_SQLTYPE_INTEGER, m_node == NULL ? 0 : m_node->Id());
        DBBind(hStmt, 2, DB_SQLTYPE_INTEGER, m_dwId);
        if (!DBExecute(hStmt))
        {
-               DbgPrintf(4, _T("Cannot execute %s on node_links"), bNewObject ? _T("insert") : _T("update"));
+               // DbgPrintf(4, _T("Cannot execute %s on node_links"), bNewObject ? _T("insert") : _T("update"));
                DBFreeStatement(hStmt);
                return FALSE;
        }
index a0598d9..34b67af 100644 (file)
@@ -60,9 +60,9 @@ THREAD_RESULT THREAD_CALL ServiceLevelMonitoring(void *pArg)
                        break;      // Shutdown has arrived
 
                DB_HANDLE hdb = DBConnectionPoolAcquireConnection();
-
-               NetObj* curObject;
 /*
+               NetObj* curObject;
+
                for (int i = 0; i < g_pBizServiceRoot->m_dwChildCount; i++)
                {
                        curObject = g_pBizServiceRoot->m_pChildList[i];
index 615f31d..67725d1 100644 (file)
@@ -33,13 +33,11 @@ SlmCheck::SlmCheck()
 :NetObj()
 {
        _tcscpy(m_szName, _T("Default"));
-       m_state = FALSE;
        m_script = NULL;
        m_threshold = NULL;
        m_reason[0] = _T('\0');
 }
 
-
 //
 // Constructor for new check object
 //
@@ -48,7 +46,6 @@ SlmCheck::SlmCheck(const TCHAR *name)
 :NetObj()
 {
        nx_strncpy(m_szName, name, MAX_OBJECT_NAME);
-       m_state = FALSE;
        m_script = NULL;
        m_threshold = NULL;
        m_reason[0] = _T('\0');
@@ -65,15 +62,6 @@ SlmCheck::~SlmCheck()
        safe_free_and_null(m_script);
 }
 
-void SlmCheck::calculateCompoundStatus(BOOL bForcedRecalc /*= FALSE*/)
-{
-       /*
-       if (m_script == NULL && m_threshold == NULL)
-               m_iStatus = STATUS_UNKNOWN;
-       else
-               m_iStatus = STATUS_NORMAL;
-       */
-}
 
 //
 // Create object from database data
@@ -91,7 +79,7 @@ BOOL SlmCheck::CreateFromDB(DWORD id)
        if (!loadCommonProperties())
                return FALSE;
 
-       DB_STATEMENT hStmt = DBPrepare(g_hCoreDB, _T("SELECT type,content,threshold_id,state,reason FROM slm_checks WHERE check_id=?"));
+       DB_STATEMENT hStmt = DBPrepare(g_hCoreDB, _T("SELECT type,content,threshold_id,reason FROM slm_checks WHERE check_id=?"));
        if (hStmt == NULL)
        {
                DbgPrintf(4, _T("Cannot prepare select from slm_checks"));
@@ -117,8 +105,7 @@ BOOL SlmCheck::CreateFromDB(DWORD id)
        m_type          = SlmCheck::CheckType(DBGetFieldLong(hResult, 0, 0));
        m_script = DBGetField(hResult, 0, 1, NULL, script_length);
        thresholdId = DBGetFieldLong(hResult, 0, 2);
-       m_state         = DBGetFieldLong(hResult, 0, 3);
-       DBGetField(hResult, 0, 4, m_reason, 255);
+       DBGetField(hResult, 0, 3, m_reason, 255);
 
        if (thresholdId > 0)
        {
@@ -171,9 +158,9 @@ BOOL SlmCheck::SaveToDB(DB_HANDLE hdb)
        }
        DBFreeStatement(hStmt);
 
-       hStmt = DBPrepare(g_hCoreDB, bNewObject ? _T("INSERT INTO slm_checks (check_id,type,content,threshold_id,state,reason) ")
+       hStmt = DBPrepare(g_hCoreDB, bNewObject ? _T("INSERT INTO slm_checks (check_id,type,content,threshold_id,reason) ")
                                                                                          _T("VALUES (?,?,?,?,?,?)") :
-                                                                                         _T("UPDATE slm_checks SET check_id=?,type=?,content=?,threshold_id=?,state=?,reason=? ")
+                                                                                         _T("UPDATE slm_checks SET check_id=?,type=?,content=?,threshold_id=?,reason=? ")
                                                                                          _T("WHERE service_id=?"));
        if (hStmt == NULL)      
                goto finish;
@@ -181,10 +168,9 @@ BOOL SlmCheck::SaveToDB(DB_HANDLE hdb)
        DBBind(hStmt, 2, DB_SQLTYPE_INTEGER, DWORD(m_type));
        DBBind(hStmt, 3, DB_SQLTYPE_TEXT, m_script, DB_BIND_STATIC);
        DBBind(hStmt, 4, DB_SQLTYPE_INTEGER, m_threshold ? m_threshold->getId() : 0);
-       DBBind(hStmt, 5, DB_SQLTYPE_INTEGER, DWORD(m_state));
-       DBBind(hStmt, 6, DB_SQLTYPE_VARCHAR, m_reason, DB_BIND_STATIC);
+       DBBind(hStmt, 5, DB_SQLTYPE_VARCHAR, m_reason, DB_BIND_STATIC);
        if (!bNewObject)
-               DBBind(hStmt, 7, DB_SQLTYPE_INTEGER, m_dwId);
+               DBBind(hStmt, 6, DB_SQLTYPE_INTEGER, m_dwId);
        
        if (!DBExecute(hStmt))
        {
@@ -260,26 +246,28 @@ DWORD SlmCheck::ModifyFromMessage(CSCPMessage *pRequest, BOOL bAlreadyLocked)
 
 void SlmCheck::execute()
 {
-       NXSL_ServerEnv pEnv;
+       NXSL_ServerEnv *pEnv;
        NXSL_Value *pValue;
 
+       pEnv = new NXSL_ServerEnv;
+
        switch (m_type)
        {
        case check_script:
-               if (m_pCompiledScript->run(&pEnv, 0, NULL) == 0)
+               if (m_pCompiledScript->run(pEnv, 0, NULL) == 0)
                {
                        pValue = m_pCompiledScript->getResult();
                        m_iStatus = pValue->getValueAsInt32() == 0 ? STATUS_NORMAL : STATUS_CRITICAL;
-                       DbgPrintf(9, _T("%s/%ld ret value %d"), m_szName, (long)m_dwId, pValue->getValueAsInt32());
+                       DbgPrintf(9, _T("SlmCheck::execute: %s/%ld ret value %d"), m_szName, (long)m_dwId, pValue->getValueAsInt32());
                }
                else
                {
-                       DbgPrintf(4, _T("%s/%ld nxsl run() failed, %s"),  m_szName, (long)m_dwId, m_pCompiledScript->getErrorText());
+                       DbgPrintf(4, _T("SlmCheck::execute: %s/%ld nxsl run() failed, %s"),  m_szName, (long)m_dwId, m_pCompiledScript->getErrorText());
                }
                break;
        case check_threshold:
        default:
-               DbgPrintf(4, _T("execute() called for undefined check type, check %s/%ld"), m_szName, (long)m_dwId);
+               DbgPrintf(4, _T("SlmCheck::execute() called for undefined check type, check %s/%ld"), m_szName, (long)m_dwId);
                m_iStatus = STATUS_UNKNOWN;
                break;
        }
index 4d20def..5c53ba2 100644 (file)
@@ -790,6 +790,7 @@ extern DWORD g_dwLockTimeout;
 extern DWORD g_dwAgentCommandTimeout;
 extern DWORD g_dwThresholdRepeatInterval;
 extern int g_nRequiredPolls;
+extern DWORD g_dwSlmPollingInterval;
 
 extern TCHAR g_szDbDriver[];
 extern TCHAR g_szDbDrvParams[];
index 8b889b4..5218925 100644 (file)
@@ -52,7 +52,6 @@ extern DWORD g_dwRoutingTableUpdateInterval;
 extern DWORD g_dwTopologyPollingInterval;
 extern DWORD g_dwConditionPollingInterval;
 
-
 //
 // Constants
 //
@@ -1555,7 +1554,7 @@ public:
 // Node link object for biz service (actually is a node)
 //
 
-class NXCORE_EXPORTABLE NodeLink : public NetObj
+class NXCORE_EXPORTABLE NodeLink : public Container
 {
 protected:
        Node* m_node;
@@ -1586,7 +1585,6 @@ protected:
        Threshold* m_threshold;
        enum CheckType { check_undefined = 0, check_script = 1, check_threshold = 2 } m_type;
        TCHAR* m_script;
-       BOOL m_state;
        TCHAR m_reason[256];
        NXSL_Program *m_pCompiledScript;
 
@@ -1596,7 +1594,6 @@ public:
        virtual ~SlmCheck();
 
        virtual int Type() { return OBJECT_SLMCHECK; }
-       virtual void calculateCompoundStatus(BOOL bForcedRecalc = FALSE);
 
        virtual BOOL SaveToDB(DB_HANDLE hdb);
        virtual BOOL DeleteFromDB();
@@ -1634,6 +1631,7 @@ class NXCORE_EXPORTABLE BizService : public Container
 {
 protected:
        bool m_busy;
+       time_t m_lastPollTime;
 
 public:
        BizService();
@@ -1650,8 +1648,8 @@ public:
        virtual void CreateMessage(CSCPMessage *pMsg);
        virtual DWORD ModifyFromMessage(CSCPMessage *pRequest, BOOL bAlreadyLocked = FALSE);
 
-       bool isReadyForPolling() { return !m_busy; }
-       void lockForPolling() { m_busy = true; }
+       bool isReadyForPolling();
+       void lockForPolling();
        void poll(ClientSession *pSession, DWORD dwRqId, int nPoller);
 };