- Added separate mutex for controlling reference count attribute
authorVictor Kirhenshtein <victor@netxms.org>
Mon, 31 Jan 2005 12:10:29 +0000 (12:10 +0000)
committerVictor Kirhenshtein <victor@netxms.org>
Mon, 31 Jan 2005 12:10:29 +0000 (12:10 +0000)
- Implemented notification of all objects about object deletions

src/server/core/hk.cpp
src/server/core/netobj.cpp
src/server/core/netsrv.cpp
src/server/core/node.cpp
src/server/core/session.cpp
src/server/include/nms_objects.h

index 0099970..7c1008e 100644 (file)
@@ -81,7 +81,7 @@ static void DeleteEmptySubnets(void)
          if (g_pIndexById[i].pObject->IsEmpty())
          {
             PostEvent(EVENT_SUBNET_DELETED, g_pIndexById[i].pObject->Id(), NULL);
-            g_pIndexById[i].pObject->Delete();
+            g_pIndexById[i].pObject->Delete(TRUE);
          }
       }
 
index 121235a..ff65d63 100644 (file)
@@ -31,6 +31,7 @@ NetObj::NetObj()
 {
    m_dwRefCount = 0;
    m_hMutex = MutexCreate();
+   m_mutexRefCount = MutexCreate();
    m_iStatus = STATUS_UNKNOWN;
    m_szName[0] = 0;
    m_bIsModified = FALSE;
@@ -54,6 +55,7 @@ NetObj::NetObj()
 NetObj::~NetObj()
 {
    MutexDestroy(m_hMutex);
+   MutexDestroy(m_mutexRefCount);
    if (m_pChildList != NULL)
       free(m_pChildList);
    if (m_pParentList != NULL)
@@ -212,9 +214,11 @@ void NetObj::DeleteParent(NetObj *pObject)
 
 //
 // Prepare object for deletion - remove all references, etc.
+// bIndexLocked should be TRUE if object index by ID is already locked
+// by current thread
 //
 
-void NetObj::Delete(void)
+void NetObj::Delete(BOOL bIndexLocked)
 {
    DWORD i;
 
@@ -235,7 +239,7 @@ void NetObj::Delete(void)
    {
       m_pChildList[i]->DeleteParent(this);
       if (m_pChildList[i]->IsOrphaned())
-         m_pChildList[i]->Delete();
+         m_pChildList[i]->Delete(bIndexLocked);
    }
    free(m_pChildList);
    m_pChildList = NULL;
@@ -243,12 +247,32 @@ void NetObj::Delete(void)
 
    NetObjDeleteFromIndexes(this);
 
+   // Notify all other objects about object deletion
+   if (!bIndexLocked)
+      RWLockReadLock(g_rwlockIdIndex, INFINITE);
+   for(i = 0; i < g_dwIdIndexSize; i++)
+   {
+      if (g_pIndexById[i].dwKey != m_dwId)
+         g_pIndexById[i].pObject->OnObjectDelete(m_dwId);
+   }
+   if (!bIndexLocked)
+      RWLockUnlock(g_rwlockIdIndex);
+
    m_bIsDeleted = TRUE;
    Modify();
    Unlock();
 }
 
 
+//
+// Default handler for object deletion notification
+//
+
+void NetObj::OnObjectDelete(DWORD dwObjectId)
+{
+}
+
+
 //
 // Print childs IDs
 //
index e40215e..791fe5e 100644 (file)
@@ -396,3 +396,21 @@ void NetworkService::StatusPoll(ClientSession *pSession, DWORD dwRqId, Node *pPo
    }
    SendPollerMsg(dwRqId, "   Finished status poll on network service %s\r\n", m_szName);
 }
+
+
+//
+// Handler for object deletion
+//
+
+void NetworkService::OnObjectDelete(DWORD dwObjectId)
+{
+   Lock();
+   if (dwObjectId == m_dwPollerNode)
+   {
+      // If deleted object is our poller node, change it to default
+      m_dwPollerNode = 0;
+      Modify();
+      DbgPrintf(AF_DEBUG_MISC, _T("Service \"%s\": poller node %ld deleted"), m_szName, dwObjectId);
+   }
+   Unlock();
+}
index 2d95a10..2d32de9 100644 (file)
@@ -638,12 +638,12 @@ void Node::DeleteInterface(Interface *pInterface)
             if ((pSubnet->IsEmpty()) && (g_dwFlags & AF_DELETE_EMPTY_SUBNETS))
             {
                PostEvent(EVENT_SUBNET_DELETED, pSubnet->Id(), NULL);
-               pSubnet->Delete();
+               pSubnet->Delete(FALSE);
             }
          }
       }
    }
-   pInterface->Delete();
+   pInterface->Delete(FALSE);
 }
 
 
@@ -1369,3 +1369,21 @@ DWORD Node::CheckNetworkService(DWORD *pdwStatus, DWORD dwIpAddr, int iServiceTy
    AgentUnlock();
    return dwError;
 }
+
+
+//
+// Handler for object deletion
+//
+
+void Node::OnObjectDelete(DWORD dwObjectId)
+{
+   Lock();
+   if (dwObjectId == m_dwPollerNode)
+   {
+      // If deleted object is our poller node, change it to default
+      m_dwPollerNode = 0;
+      Modify();
+      DbgPrintf(AF_DEBUG_MISC, _T("Node \"%s\": poller node %ld deleted"), m_szName, dwObjectId);
+   }
+   Unlock();
+}
index b5fff11..2b01908 100644 (file)
@@ -2790,7 +2790,7 @@ void ClientSession::DeleteObject(CSCPMessage *pRequest)
          // Check access rights
          if (pObject->CheckAccessRights(m_dwUserId, OBJECT_ACCESS_DELETE))
          {
-            pObject->Delete();
+            pObject->Delete(FALSE);
             msg.SetVariable(VID_RCC, RCC_SUCCESS);
          }
          else
index 4997e13..80fb450 100644 (file)
@@ -92,7 +92,8 @@ protected:
    int m_iStatus;
    BOOL m_bIsModified;
    BOOL m_bIsDeleted;
-   MUTEX m_hMutex;
+   MUTEX m_hMutex;         // Generic object access mutex
+   MUTEX m_mutexRefCount;  // Reference counter access mutex
    DWORD m_dwIpAddr;       // Every object should have an IP address
    DWORD m_dwImageId;      // Custom image id or 0 if object has default image
    ClientSession *m_pPollRequestor;
@@ -116,6 +117,8 @@ protected:
 
    void SendPollerMsg(DWORD dwRqId, TCHAR *pszFormat, ...);
 
+   virtual void OnObjectDelete(DWORD dwObjectId);
+
 public:
    NetObj();
    virtual ~NetObj();
@@ -132,9 +135,9 @@ public:
    BOOL IsOrphaned(void) { return m_dwParentCount == 0 ? TRUE : FALSE; }
    BOOL IsEmpty(void) { return m_dwChildCount == 0 ? TRUE : FALSE; }
 
-   DWORD RefCount(void) { return m_dwRefCount; }
-   void IncRefCount(void) { Lock(); m_dwRefCount++; Unlock(); }
-   void DecRefCount(void) { Lock(); if (m_dwRefCount > 0) m_dwRefCount--; Unlock(); }
+   DWORD RefCount(void);
+   void IncRefCount(void);
+   void DecRefCount(void);
 
    BOOL IsChild(DWORD dwObjectId);
 
@@ -144,7 +147,7 @@ public:
    void DeleteChild(NetObj *pObject);  // Delete reference to child object
    void DeleteParent(NetObj *pObject); // Delete reference to parent object
 
-   void Delete(void);                  // Prepare object for deletion
+   void Delete(BOOL bIndexLocked);     // Prepare object for deletion
 
    virtual BOOL SaveToDB(void);
    virtual BOOL DeleteFromDB(void);
@@ -171,6 +174,36 @@ public:
 };
 
 
+//
+// Inline functions of NetObj class
+//
+
+inline DWORD NetObj::RefCount(void)
+{ 
+   DWORD dwRefCount;
+
+   MutexLock(m_mutexRefCount, INFINITE);
+   dwRefCount = m_dwRefCount;
+   MutexUnlock(m_mutexRefCount);
+   return dwRefCount; 
+}
+
+inline void NetObj::IncRefCount(void)
+{ 
+   MutexLock(m_mutexRefCount, INFINITE);
+   m_dwRefCount++;
+   MutexUnlock(m_mutexRefCount);
+}
+
+inline void NetObj::DecRefCount(void)
+{ 
+   MutexLock(m_mutexRefCount, INFINITE);
+   if (m_dwRefCount > 0) 
+      m_dwRefCount--; 
+   MutexUnlock(m_mutexRefCount);
+}
+
+
 //
 // Node template class
 //
@@ -278,6 +311,8 @@ protected:
    TCHAR *m_pszRequest;  // Service-specific request
    TCHAR *m_pszResponce; // Service-specific expected responce
 
+   virtual void OnObjectDelete(DWORD dwObjectId);
+
 public:
    NetworkService();
    NetworkService(int iServiceType, WORD wProto, WORD wPort,
@@ -336,6 +371,8 @@ protected:
    void AgentLock(void) { MutexLock(m_hAgentAccessMutex, INFINITE); }
    void AgentUnlock(void) { MutexUnlock(m_hAgentAccessMutex); }
 
+   virtual void OnObjectDelete(DWORD dwObjectId);
+
 public:
    Node();
    Node(DWORD dwAddr, DWORD dwFlags, DWORD dwDiscoveryFlags);