Index access mutexes changed to read/write locks in server code
authorVictor Kirhenshtein <victor@netxms.org>
Wed, 13 Oct 2004 06:47:42 +0000 (06:47 +0000)
committerVictor Kirhenshtein <victor@netxms.org>
Wed, 13 Oct 2004 06:47:42 +0000 (06:47 +0000)
25 files changed:
ChangeLog
TODO
include/netxms-version.h
include/nms_threads.h
include/nxclapi.h
src/libnxcl/actions.cpp
src/libnxcl/alarms.cpp
src/libnxcl/comm.cpp
src/libnxcl/datacoll.cpp
src/libnxcl/epp.cpp
src/libnxcl/eventdb.cpp
src/libnxcl/image.cpp
src/libnxcl/libnxcl.h
src/libnxcl/main.cpp
src/libnxcl/mib.cpp
src/libnxcl/objects.cpp
src/libnxcl/users.cpp
src/server/core/datacoll.cpp
src/server/core/debug.cpp
src/server/core/discovery.cpp
src/server/core/main.cpp
src/server/core/nms_core.h
src/server/core/nms_objects.h
src/server/core/np.cpp
src/server/core/objects.cpp

index 73ea08a..4cbf030 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+*
+* 0.1.5
+*
+
+- Object access mutexes changed to read/write locks in server to 
+  improve performance
+
+
 *
 * 0.1.4
 *
@@ -5,6 +13,7 @@
 - Created performance subagent for Windows (winperf.nsm)
 - Added SNMP OID to node type translation
 - Added support for Nortel Networks Passport routing switches
+- "configure" script improved
 
 
 *
diff --git a/TODO b/TODO
index fa9702c..b2f8e7a 100644 (file)
--- a/TODO
+++ b/TODO
@@ -27,7 +27,6 @@ GENERAL:
 SERVER:
 
 - Recalculate object status after binding change
-- Change object index lock type from mutex to read/write lock
 - Add internal stats collection:
        1. Average data collector queue length
        2. Average database writer queue length
@@ -41,6 +40,8 @@ SERVER:
   this functionality.
 - Change node into subnet placement algorithm
 - Add incorect netmask detection
+- Chech if ObjectGlobalLock()/ObjectGlobalUnlock() really needed or we can
+  use just index locking
 
 
 CORE AGENT:
index 70f48f3..d79cc72 100644 (file)
@@ -30,8 +30,8 @@
 
 #define NETXMS_VERSION_MAJOR      0
 #define NETXMS_VERSION_MINOR      1
-#define NETXMS_VERSION_BUILD      4
-#define NETXMS_VERSION_STRING     "0.1.4"
+#define NETXMS_VERSION_BUILD      5
+#define NETXMS_VERSION_STRING     "0.1.5"
 
 
 #endif
index fe6e504..6cb7a47 100644 (file)
@@ -33,9 +33,9 @@
 // Related datatypes and constants
 //
 
-#define MUTEX  HANDLE
-#define THREAD HANDLE
-#define CONDITION HANDLE
+typedef HANDLE MUTEX;
+typedef HANDLE THREAD;
+typedef HANDLE CONDITION;
 
 #define INVALID_MUTEX_HANDLE        INVALID_HANDLE_VALUE
 #define INVALID_CONDITION_HANDLE    INVALID_HANDLE_VALUE
index bd14499..a89a64b 100644 (file)
@@ -816,6 +816,7 @@ const TCHAR LIBNXCL_EXPORTABLE *NXCGetErrorText(DWORD dwError);
 
 BOOL LIBNXCL_EXPORTABLE NXCInitialize(void);
 void LIBNXCL_EXPORTABLE NXCShutdown(void);
+void LIBNXCL_EXPORTABLE NXCSetCommandTimeout(DWORD dwTimeout);
 
 DWORD LIBNXCL_EXPORTABLE NXCConnect(TCHAR *szServer, TCHAR *szLogin, TCHAR *szPassword);
 void LIBNXCL_EXPORTABLE NXCDisconnect(void);
index c71630c..3b6d1e6 100644 (file)
@@ -74,7 +74,7 @@ DWORD LIBNXCL_EXPORTABLE NXCLoadActions(DWORD *pdwNumActions, NXC_ACTION **ppAct
 
    do
    {
-      pResponce = WaitForMessage(CMD_ACTION_DATA, dwRqId, 2000);
+      pResponce = WaitForMessage(CMD_ACTION_DATA, dwRqId, g_dwCommandTimeout);
       if (pResponce != NULL)
       {
          dwActionId = pResponce->GetVariableLong(VID_ACTION_ID);
@@ -167,7 +167,7 @@ DWORD LIBNXCL_EXPORTABLE NXCCreateAction(TCHAR *pszName, DWORD *pdwNewId)
    msg.SetVariable(VID_ACTION_NAME, pszName);
    SendMsg(&msg);
 
-   pResponce = WaitForMessage(CMD_REQUEST_COMPLETED, dwRqId, 2000);
+   pResponce = WaitForMessage(CMD_REQUEST_COMPLETED, dwRqId, g_dwCommandTimeout);
    if (pResponce != NULL)
    {
       dwRetCode = pResponce->GetVariableLong(VID_RCC);
index 8610879..ba992da 100644 (file)
@@ -77,7 +77,7 @@ DWORD LIBNXCL_EXPORTABLE NXCLoadAllAlarms(BOOL bIncludeAck, DWORD *pdwNumAlarms,
 
    do
    {
-      pResponce = WaitForMessage(CMD_ALARM_DATA, dwRqId, 2000);
+      pResponce = WaitForMessage(CMD_ALARM_DATA, dwRqId, g_dwCommandTimeout);
       if (pResponce != NULL)
       {
          dwAlarmId = pResponce->GetVariableLong(VID_ALARM_ID);
index 8db52ad..b9d6dc2 100644 (file)
@@ -274,7 +274,7 @@ DWORD LIBNXCL_EXPORTABLE NXCConnect(TCHAR *szServer, TCHAR *szLogin, TCHAR *szPa
                if (SendMsg(&msg))
                {
                   // Receive responce message
-                  pResp = m_msgWaitQueue.WaitForMessage(CMD_LOGIN_RESP, msg.GetId(), 2000);
+                  pResp = m_msgWaitQueue.WaitForMessage(CMD_LOGIN_RESP, msg.GetId(), g_dwCommandTimeout);
                   if (pResp != NULL)
                   {
                      dwRetCode = pResp->GetVariableLong(VID_RCC);
@@ -355,7 +355,7 @@ DWORD WaitForRCC(DWORD dwRqId)
    CSCPMessage *pResponce;
    DWORD dwRetCode;
 
-   pResponce = WaitForMessage(CMD_REQUEST_COMPLETED, dwRqId, 2000);
+   pResponce = WaitForMessage(CMD_REQUEST_COMPLETED, dwRqId, g_dwCommandTimeout);
    if (pResponce != NULL)
    {
       dwRetCode = pResponce->GetVariableLong(VID_RCC);
index 959a480..4066685 100644 (file)
@@ -199,7 +199,7 @@ DWORD LIBNXCL_EXPORTABLE NXCCreateNewDCI(NXC_DCI_LIST *pItemList, DWORD *pdwItem
    msg.SetVariable(VID_OBJECT_ID, pItemList->dwNodeId);
    SendMsg(&msg);
 
-   pResponce = WaitForMessage(CMD_REQUEST_COMPLETED, dwRqId, 2000);
+   pResponce = WaitForMessage(CMD_REQUEST_COMPLETED, dwRqId, g_dwCommandTimeout);
    if (pResponce != NULL)
    {
       dwRetCode = pResponce->GetVariableLong(VID_RCC);
@@ -286,7 +286,7 @@ DWORD LIBNXCL_EXPORTABLE NXCUpdateDCI(DWORD dwNodeId, NXC_DCI *pItem)
    }
    SendMsg(&msg);
 
-   pResponce = WaitForMessage(CMD_REQUEST_COMPLETED, dwRqId, 2000);
+   pResponce = WaitForMessage(CMD_REQUEST_COMPLETED, dwRqId, g_dwCommandTimeout);
    if (pResponce != NULL)
    {
       dwRetCode = pResponce->GetVariableLong(VID_RCC);
index 0a3e0e0..ddedb25 100644 (file)
@@ -61,7 +61,7 @@ DWORD LIBNXCL_EXPORTABLE NXCOpenEventPolicy(NXC_EPP **ppEventPolicy)
    SendMsg(&msg);
 
    // Wait for reply
-   pResponce = WaitForMessage(CMD_REQUEST_COMPLETED, dwRqId, 2000);
+   pResponce = WaitForMessage(CMD_REQUEST_COMPLETED, dwRqId, g_dwCommandTimeout);
    if (pResponce != NULL)
    {
       dwRetCode = pResponce->GetVariableLong(VID_RCC);
@@ -78,7 +78,7 @@ DWORD LIBNXCL_EXPORTABLE NXCOpenEventPolicy(NXC_EPP **ppEventPolicy)
          // Receive policy rules, each in separate message
          for(i = 0; i < (*ppEventPolicy)->dwNumRules; i++)
          {
-            pResponce = WaitForMessage(CMD_EPP_RECORD, dwRqId, 2000);
+            pResponce = WaitForMessage(CMD_EPP_RECORD, dwRqId, g_dwCommandTimeout);
             if (pResponce != NULL)
             {
                (*ppEventPolicy)->pRuleList[i].dwFlags = pResponce->GetVariableLong(VID_FLAGS);
index afdd163..a806260 100644 (file)
@@ -209,7 +209,7 @@ DWORD LIBNXCL_EXPORTABLE NXCCloseEventDB(BOOL bSaveChanges)
       msg.SetCode(CMD_CLOSE_EVENT_DB);
       msg.SetId(dwRqId);
       SendMsg(&msg);
-      pResponce = WaitForMessage(CMD_REQUEST_COMPLETED, dwRqId, 2000);
+      pResponce = WaitForMessage(CMD_REQUEST_COMPLETED, dwRqId, g_dwCommandTimeout);
       if (pResponce != NULL)
       {
          dwRetCode = pResponce->GetVariableLong(VID_RCC);
@@ -286,7 +286,7 @@ DWORD LIBNXCL_EXPORTABLE NXCLoadEventNames(void)
    msg.SetCode(CMD_GET_EVENT_NAMES);
    msg.SetId(dwRqId);
    SendMsg(&msg);
-   pResponce = WaitForMessage(CMD_EVENT_NAME_LIST, dwRqId, 3000);
+   pResponce = WaitForMessage(CMD_EVENT_NAME_LIST, dwRqId, g_dwCommandTimeout);
    if (pResponce != NULL)
    {
       dwRetCode = pResponce->GetVariableLong(VID_RCC);
index 7b852c4..e8f0255 100644 (file)
@@ -48,7 +48,8 @@ DWORD LIBNXCL_EXPORTABLE NXCLoadImageFile(DWORD dwImageId, TCHAR *pszCacheDir, W
    msg.SetVariable(VID_IMAGE_FORMAT, wFormat);
    SendMsg(&msg);
 
-   pResponce = WaitForMessage(CMD_IMAGE_FILE, dwRqId, 30000);
+   // Loading  file can take time, so we use 60 sec. timeout instead of default
+   pResponce = WaitForMessage(CMD_IMAGE_FILE, dwRqId, 60000);
    if (pResponce != NULL)
    {
       dwRetCode = pResponce->GetVariableLong(VID_RCC);
@@ -135,7 +136,7 @@ DWORD LIBNXCL_EXPORTABLE NXCSyncImages(NXC_IMAGE_LIST **ppImageList, TCHAR *pszC
    msg.SetVariable(VID_IMAGE_FORMAT, wFormat);
    SendMsg(&msg);
 
-   pResponce = WaitForMessage(CMD_IMAGE_LIST, dwRqId, 5000);
+   pResponce = WaitForMessage(CMD_IMAGE_LIST, dwRqId, g_dwCommandTimeout * 2);
    if (pResponce != NULL)
    {
       dwRetCode = pResponce->GetVariableLong(VID_RCC);
@@ -206,7 +207,7 @@ DWORD LIBNXCL_EXPORTABLE NXCLoadDefaultImageList(DWORD *pdwListSize,
    msg.SetId(dwRqId);
    SendMsg(&msg);
 
-   pResponce = WaitForMessage(CMD_DEFAULT_IMAGE_LIST, dwRqId, 3000);
+   pResponce = WaitForMessage(CMD_DEFAULT_IMAGE_LIST, dwRqId, g_dwCommandTimeout);
    if (pResponce != NULL)
    {
       dwRetCode = pResponce->GetVariableLong(VID_RCC);
index 51a4d35..26ecdd4 100644 (file)
@@ -117,6 +117,7 @@ extern NXC_EVENT_HANDLER g_pEventHandler;
 extern NXC_DEBUG_CALLBACK g_pDebugCallBack;
 extern DWORD g_dwState;
 extern DWORD g_dwMsgId;
+extern DWORD g_dwCommandTimeout;
 
 
 //
index caa1ed2..f08a2a5 100644 (file)
@@ -31,6 +31,7 @@
 NXC_EVENT_HANDLER g_pEventHandler = NULL;
 NXC_DEBUG_CALLBACK g_pDebugCallBack = NULL;
 DWORD g_dwState = STATE_DISCONNECTED;
+DWORD g_dwCommandTimeout = 3000;    // Default timeout is 3 seconds
 
 
 //
@@ -86,7 +87,18 @@ void LIBNXCL_EXPORTABLE NXCSetDebugCallback(NXC_DEBUG_CALLBACK pFunc)
 
 
 //
-// Ge text for error
+// Set command timeout
+//
+
+void LIBNXCL_EXPORTABLE NXCSetCommandTimeout(DWORD dwTimeout)
+{
+   if ((dwTimeout >= 1000) && (dwTimeout <= 60000))
+      g_dwCommandTimeout = dwTimeout;
+}
+
+
+//
+// Get text for error
 //
 
 const TCHAR LIBNXCL_EXPORTABLE *NXCGetErrorText(DWORD dwError)
index 7bc1d72..2e671f7 100644 (file)
@@ -43,7 +43,7 @@ DWORD LIBNXCL_EXPORTABLE NXCGetMIBList(NXC_MIB_LIST **ppMibList)
    msg.SetId(dwRqId);
    SendMsg(&msg);
 
-   pResponce = WaitForMessage(CMD_MIB_LIST, dwRqId, 2000);
+   pResponce = WaitForMessage(CMD_MIB_LIST, dwRqId, g_dwCommandTimeout * 2);
    if (pResponce != NULL)
    {
       *ppMibList = (NXC_MIB_LIST *)malloc(sizeof(NXC_MIB_LIST));
@@ -107,7 +107,8 @@ DWORD LIBNXCL_EXPORTABLE NXCDownloadMIBFile(TCHAR *pszName, TCHAR *pszDestDir)
    msg.SetVariable(VID_MIB_NAME, pszName);
    SendMsg(&msg);
 
-   pResponce = WaitForMessage(CMD_MIB, dwRqId, 10000);
+   // Loading file can take time, so timeout is 60 sec. instead of default
+   pResponce = WaitForMessage(CMD_MIB, dwRqId, 60000);
    if (pResponce != NULL)
    {
       dwRetCode = pResponce->GetVariableLong(VID_RCC);
index c17a063..51e0d64 100644 (file)
@@ -548,8 +548,9 @@ DWORD LIBNXCL_EXPORTABLE NXCCreateObject(NXC_OBJECT_CREATE_INFO *pCreateInfo, DW
    // Send request
    SendMsg(&msg);
 
-   // Wait for responce
-   pResponce = WaitForMessage(CMD_REQUEST_COMPLETED, dwRqId, 60000);
+   // Wait for responce. Creating node object can include polling,
+   // which can take a minute or even more in worst cases
+   pResponce = WaitForMessage(CMD_REQUEST_COMPLETED, dwRqId, 120000);
    if (pResponce != NULL)
    {
       dwRetCode = pResponce->GetVariableLong(VID_RCC);
@@ -658,7 +659,7 @@ DWORD LIBNXCL_EXPORTABLE NXCLoadCCList(NXC_CC_LIST **ppList)
 
    do
    {
-      pResponce = WaitForMessage(CMD_CONTAINER_CAT_DATA, dwRqId, 2000);
+      pResponce = WaitForMessage(CMD_CONTAINER_CAT_DATA, dwRqId, g_dwCommandTimeout);
       if (pResponce != NULL)
       {
          dwCatId = pResponce->GetVariableLong(VID_CATEGORY_ID);
index 6abed24..89ba8b2 100644 (file)
@@ -226,7 +226,7 @@ DWORD LIBNXCL_EXPORTABLE NXCCreateUser(TCHAR *pszName, BOOL bIsGroup, DWORD *pdw
    msg.SetVariable(VID_IS_GROUP, (WORD)bIsGroup);
    SendMsg(&msg);
 
-   pResponce = WaitForMessage(CMD_REQUEST_COMPLETED, dwRqId, 2000);
+   pResponce = WaitForMessage(CMD_REQUEST_COMPLETED, dwRqId, g_dwCommandTimeout);
    if (pResponce != NULL)
    {
       dwRetCode = pResponce->GetVariableLong(VID_RCC);
index 35e823c..87412e3 100644 (file)
@@ -114,11 +114,11 @@ static THREAD_RESULT THREAD_CALL ItemPoller(void *pArg)
          break;      // Shutdown has arrived
       WatchdogNotify(dwWatchdogId);
 
-      MutexLock(g_hMutexNodeIndex, INFINITE);
+      RWLockReadLock(g_rwlockNodeIndex, INFINITE);
       qwStart = GetCurrentTimeMs();
       for(i = 0; i < g_dwNodeAddrIndexSize; i++)
          ((Node *)g_pNodeIndexByAddr[i].pObject)->QueueItemsForPolling(m_pItemQueue);
-      MutexUnlock(g_hMutexNodeIndex);
+      RWLockUnlock(g_rwlockNodeIndex);
 
       dwElapsed = (DWORD)(GetCurrentTimeMs() - qwStart);
    }
index 9b29a0a..228acbf 100644 (file)
 // Test mutex state and print to stdout
 //
 
-void DbgTestMutex(MUTEX hMutex, char *szName)
+void DbgTestMutex(MUTEX hMutex, TCHAR *szName)
 {
-   printf("  %s: ", szName);
+   _tprintf(_T("  %s: "), szName);
    if (MutexLock(hMutex, 100))
    {
-      printf("unlocked\n");
+      _tprintf(_T("unlocked\n"));
       MutexUnlock(hMutex);
    }
    else
    {
-      printf("locked\n");
+      _tprintf(_T("locked\n"));
+   }
+}
+
+
+//
+// Test read/write lock state and print to stdout
+//
+
+void DbgTestRWLock(RWLOCK hLock, TCHAR *szName)
+{
+   _tprintf(_T("  %s: "), szName);
+   if (RWLockWriteLock(hLock, 100))
+   {
+      _tprintf(_T("unlocked\n"));
+      RWLockUnlock(hLock);
+   }
+   else
+   {
+      if (RWLockReadLock(hLock, 100))
+      {
+         _tprintf(_T("locked for reading\n"));
+         RWLockUnlock(hLock);
+      }
+      else
+      {
+         _tprintf(_T("locked for writing\n"));
+      }
    }
 }
 
@@ -47,23 +74,16 @@ void DbgTestMutex(MUTEX hMutex, char *szName)
 // and specific application flag(s) is set
 //
 
-void DbgPrintf(DWORD dwFlags, char *szFormat, ...)
+void DbgPrintf(DWORD dwFlags, TCHAR *szFormat, ...)
 {
    va_list args;
-   char szBuffer[1024];
+   TCHAR szBuffer[1024];
 
    if (!(g_dwFlags & dwFlags))
       return;     // Required application flag(s) not set
 
-/*   if (IsStandalone())
-   {
-      va_start(args, szFormat);
-      vprintf(szFormat, args);
-      va_end(args);
-   }*/
-
    va_start(args, szFormat);
-   vsnprintf(szBuffer, 1024, szFormat, args);
+   _vsntprintf(szBuffer, 1024, szFormat, args);
    va_end(args);
-   WriteLog(MSG_DEBUG, EVENTLOG_INFORMATION_TYPE, "s", szBuffer);
+   WriteLog(MSG_DEBUG, EVENTLOG_INFORMATION_TYPE, _T("s"), szBuffer);
 }
index 21b2baf..7ba8bc8 100644 (file)
@@ -94,7 +94,7 @@ THREAD_RESULT THREAD_CALL DiscoveryThread(void *arg)
       CheckForMgmtNode();
 
       // Walk through nodes and poll for ARP tables
-      MutexLock(g_hMutexNodeIndex, INFINITE);
+      RWLockReadLock(g_rwlockNodeIndex, INFINITE);
       for(DWORD i = 0; i < g_dwNodeAddrIndexSize; i++)
       {
          pNode = (Node *)g_pNodeIndexByAddr[i].pObject;
@@ -131,7 +131,7 @@ THREAD_RESULT THREAD_CALL DiscoveryThread(void *arg)
             pNode->SetDiscoveryPollTimeStamp();
          }
       }
-      MutexUnlock(g_hMutexNodeIndex);
+      RWLockUnlock(g_rwlockNodeIndex);
    }
 
    DbgPrintf(AF_DEBUG_DISCOVERY, "Discovery thread terminated");
index 978d581..4cdb663 100644 (file)
@@ -442,10 +442,10 @@ static BOOL ProcessCommand(char *pszCmdLine)
    else if (IsCommand("MUTEX", szBuffer, 2))
    {
       printf("Mutex status:\n");
-      DbgTestMutex(g_hMutexIdIndex, "g_hMutexIdIndex");
-      DbgTestMutex(g_hMutexNodeIndex, "g_hMutexNodeIndex");
-      DbgTestMutex(g_hMutexSubnetIndex, "g_hMutexSubnetIndex");
-      DbgTestMutex(g_hMutexInterfaceIndex, "g_hMutexInterfaceIndex");
+      DbgTestRWLock(g_rwlockIdIndex, "g_hMutexIdIndex");
+      DbgTestRWLock(g_rwlockNodeIndex, "g_hMutexNodeIndex");
+      DbgTestRWLock(g_rwlockSubnetIndex, "g_hMutexSubnetIndex");
+      DbgTestRWLock(g_rwlockInterfaceIndex, "g_hMutexInterfaceIndex");
       DbgTestMutex(g_hMutexObjectAccess, "g_hMutexObjectAccess");
       printf("\n");
    }
index 7c264c6..d3cde1a 100644 (file)
@@ -449,8 +449,9 @@ char *GetSystemErrorText(DWORD error);
 
 #endif   /* _WIN32 */
 
-void DbgTestMutex(MUTEX hMutex, char *szName);
-void DbgPrintf(DWORD dwFlags, char *szFormat, ...);
+void DbgTestMutex(MUTEX hMutex, TCHAR *szName);
+void DbgTestRWLock(RWLOCK hLock, TCHAR *szName);
+void DbgPrintf(DWORD dwFlags, TCHAR *szFormat, ...);
 void DumpSessions(void);
 
 
index 3d36999..85c1110 100644 (file)
@@ -542,6 +542,7 @@ void NetObjDelete(NetObj *pObject);
 NetObj *FindObjectById(DWORD dwId);
 Node *FindNodeByIP(DWORD dwAddr);
 Subnet *FindSubnetByIP(DWORD dwAddr);
+Subnet *FindSubnetForNode(DWORD dwNodeAddr);
 DWORD FindLocalMgmtNode(void);
 CONTAINER_CATEGORY *FindContainerCategory(DWORD dwId);
 
@@ -570,10 +571,10 @@ extern INDEX *g_pNodeIndexByAddr;
 extern DWORD g_dwNodeAddrIndexSize;
 extern INDEX *g_pInterfaceIndexByAddr;
 extern DWORD g_dwInterfaceAddrIndexSize;
-extern MUTEX g_hMutexIdIndex;
-extern MUTEX g_hMutexNodeIndex;
-extern MUTEX g_hMutexSubnetIndex;
-extern MUTEX g_hMutexInterfaceIndex;
+extern RWLOCK g_rwlockIdIndex;
+extern RWLOCK g_rwlockNodeIndex;
+extern RWLOCK g_rwlockSubnetIndex;
+extern RWLOCK g_rwlockInterfaceIndex;
 extern MUTEX g_hMutexObjectAccess;
 extern DWORD g_dwNumCategories;
 extern CONTAINER_CATEGORY *g_pContainerCatList;
index eaf4a9c..a22c4a5 100644 (file)
@@ -48,7 +48,7 @@ NetObj *PollNewNode(DWORD dwIpAddr, DWORD dwNetMask, DWORD dwFlags, TCHAR *pszNa
    NetObjInsert(pNode, TRUE);
    if (!pNode->NewNodePoll(dwNetMask))
    {
-      DbgPrintf(AF_DEBUG_DISCOVERY, "Node::NewNodePoll(%s)failed", 
+      DbgPrintf(AF_DEBUG_DISCOVERY, "Node::NewNodePoll(%s) failed", 
                 IpToStr(dwIpAddr, szIpAddr1));
       ObjectsGlobalLock();
       NetObjDelete(pNode);
@@ -60,7 +60,7 @@ NetObj *PollNewNode(DWORD dwIpAddr, DWORD dwNetMask, DWORD dwFlags, TCHAR *pszNa
       pNode->SetName(pszName);
 
    // DEBUG
-   pNode->AddItem(new DCItem(CreateUniqueId(IDG_ITEM), "Status", DS_INTERNAL, DCI_DT_INT, 60, 30, pNode));
+   pNode->AddItem(new DCItem(CreateUniqueId(IDG_ITEM), _T("Status"), DS_INTERNAL, DCI_DT_INT, 60, 30, pNode));
    return pNode;
 }
 
index ee8b939..3f8a167 100644 (file)
@@ -42,10 +42,10 @@ INDEX *g_pInterfaceIndexByAddr = NULL;
 DWORD g_dwInterfaceAddrIndexSize = 0;
 
 MUTEX g_hMutexObjectAccess;
-MUTEX g_hMutexIdIndex;
-MUTEX g_hMutexNodeIndex;
-MUTEX g_hMutexSubnetIndex;
-MUTEX g_hMutexInterfaceIndex;
+RWLOCK g_rwlockIdIndex;
+RWLOCK g_rwlockNodeIndex;
+RWLOCK g_rwlockSubnetIndex;
+RWLOCK g_rwlockInterfaceIndex;
 
 DWORD g_dwNumCategories = 0;
 CONTAINER_CATEGORY *g_pContainerCatList = NULL;
@@ -64,10 +64,10 @@ char *g_szClassName[]={ "Generic", "Subnet", "Node", "Interface",
 void ObjectsInit(void)
 {
    g_hMutexObjectAccess = MutexCreate();
-   g_hMutexIdIndex = MutexCreate();
-   g_hMutexNodeIndex = MutexCreate();
-   g_hMutexSubnetIndex = MutexCreate();
-   g_hMutexInterfaceIndex = MutexCreate();
+   g_rwlockIdIndex = RWLockCreate();
+   g_rwlockNodeIndex = RWLockCreate();
+   g_rwlockSubnetIndex = RWLockCreate();
+   g_rwlockInterfaceIndex = RWLockCreate();
 
    // Create "Entire Network" object
    g_pEntireNet = new Network;
@@ -202,9 +202,9 @@ void NetObjInsert(NetObj *pObject, BOOL bNewObject)
          DBQuery(g_hCoreDB, szQuery);
       }
    }
-   MutexLock(g_hMutexIdIndex, INFINITE);
+   RWLockWriteLock(g_rwlockIdIndex, INFINITE);
    AddObjectToIndex(&g_pIndexById, &g_dwIdIndexSize, pObject->Id(), pObject);
-   MutexUnlock(g_hMutexIdIndex);
+   RWLockUnlock(g_rwlockIdIndex);
    if ((pObject->IpAddr() != 0) && (!pObject->IsDeleted()))
    {
       switch(pObject->Type())
@@ -215,23 +215,23 @@ void NetObjInsert(NetObj *pObject, BOOL bNewObject)
          case OBJECT_SERVICEROOT:
             break;
          case OBJECT_SUBNET:
-            MutexLock(g_hMutexSubnetIndex, INFINITE);
+            RWLockWriteLock(g_rwlockSubnetIndex, INFINITE);
             AddObjectToIndex(&g_pSubnetIndexByAddr, &g_dwSubnetAddrIndexSize, pObject->IpAddr(), pObject);
-            MutexUnlock(g_hMutexSubnetIndex);
+            RWLockUnlock(g_rwlockSubnetIndex);
             if (bNewObject)
                PostEvent(EVENT_SUBNET_ADDED, pObject->Id(), NULL);
             break;
          case OBJECT_NODE:
-            MutexLock(g_hMutexNodeIndex, INFINITE);
+            RWLockWriteLock(g_rwlockNodeIndex, INFINITE);
             AddObjectToIndex(&g_pNodeIndexByAddr, &g_dwNodeAddrIndexSize, pObject->IpAddr(), pObject);
-            MutexUnlock(g_hMutexNodeIndex);
+            RWLockUnlock(g_rwlockNodeIndex);
             if (bNewObject)
                PostEvent(EVENT_NODE_ADDED, pObject->Id(), NULL);
             break;
          case OBJECT_INTERFACE:
-            MutexLock(g_hMutexInterfaceIndex, INFINITE);
+            RWLockWriteLock(g_rwlockInterfaceIndex, INFINITE);
             AddObjectToIndex(&g_pInterfaceIndexByAddr, &g_dwInterfaceAddrIndexSize, pObject->IpAddr(), pObject);
-            MutexUnlock(g_hMutexInterfaceIndex);
+            RWLockUnlock(g_rwlockInterfaceIndex);
             break;
          default:
             WriteLog(MSG_BAD_NETOBJ_TYPE, EVENTLOG_ERROR_TYPE, "d", pObject->Type());
@@ -260,19 +260,19 @@ void NetObjDeleteFromIndexes(NetObj *pObject)
          case OBJECT_SERVICEROOT:
             break;
          case OBJECT_SUBNET:
-            MutexLock(g_hMutexSubnetIndex, INFINITE);
+            RWLockWriteLock(g_rwlockSubnetIndex, INFINITE);
             DeleteObjectFromIndex(&g_pSubnetIndexByAddr, &g_dwSubnetAddrIndexSize, pObject->IpAddr());
-            MutexUnlock(g_hMutexSubnetIndex);
+            RWLockUnlock(g_rwlockSubnetIndex);
             break;
          case OBJECT_NODE:
-            MutexLock(g_hMutexNodeIndex, INFINITE);
+            RWLockWriteLock(g_rwlockNodeIndex, INFINITE);
             DeleteObjectFromIndex(&g_pNodeIndexByAddr, &g_dwNodeAddrIndexSize, pObject->IpAddr());
-            MutexUnlock(g_hMutexNodeIndex);
+            RWLockUnlock(g_rwlockNodeIndex);
             break;
          case OBJECT_INTERFACE:
-            MutexLock(g_hMutexInterfaceIndex, INFINITE);
+            RWLockWriteLock(g_rwlockInterfaceIndex, INFINITE);
             DeleteObjectFromIndex(&g_pInterfaceIndexByAddr, &g_dwInterfaceAddrIndexSize, pObject->IpAddr());
-            MutexUnlock(g_hMutexInterfaceIndex);
+            RWLockUnlock(g_rwlockInterfaceIndex);
             break;
          default:
             WriteLog(MSG_BAD_NETOBJ_TYPE, EVENTLOG_ERROR_TYPE, "d", pObject->Type());
@@ -316,9 +316,9 @@ void NetObjDelete(NetObj *pObject)
    DBQuery(g_hCoreDB, szQuery);
 
    // Delete object from index by ID
-   MutexLock(g_hMutexIdIndex, INFINITE);
+   RWLockWriteLock(g_rwlockIdIndex, INFINITE);
    DeleteObjectFromIndex(&g_pIndexById, &g_dwIdIndexSize, pObject->Id());
-   MutexUnlock(g_hMutexIdIndex);
+   RWLockUnlock(g_rwlockIdIndex);
             
    delete pObject;
 }
@@ -336,10 +336,10 @@ Node *FindNodeByIP(DWORD dwAddr)
    if ((g_pInterfaceIndexByAddr == NULL) || (dwAddr == 0))
       return NULL;
 
-   MutexLock(g_hMutexInterfaceIndex, INFINITE);
+   RWLockReadLock(g_rwlockInterfaceIndex, INFINITE);
    dwPos = SearchIndex(g_pInterfaceIndexByAddr, g_dwInterfaceAddrIndexSize, dwAddr);
    pNode = (dwPos == INVALID_INDEX) ? NULL : (Node *)g_pInterfaceIndexByAddr[dwPos].pObject->GetParent();
-   MutexUnlock(g_hMutexInterfaceIndex);
+   RWLockUnlock(g_rwlockInterfaceIndex);
    return pNode;
 }
 
@@ -356,10 +356,35 @@ Subnet *FindSubnetByIP(DWORD dwAddr)
    if ((g_pSubnetIndexByAddr == NULL) || (dwAddr == 0))
       return NULL;
 
-   MutexLock(g_hMutexSubnetIndex, INFINITE);
+   RWLockReadLock(g_rwlockSubnetIndex, INFINITE);
    dwPos = SearchIndex(g_pSubnetIndexByAddr, g_dwSubnetAddrIndexSize, dwAddr);
    pSubnet = (dwPos == INVALID_INDEX) ? NULL : (Subnet *)g_pSubnetIndexByAddr[dwPos].pObject;
-   MutexUnlock(g_hMutexSubnetIndex);
+   RWLockUnlock(g_rwlockSubnetIndex);
+   return pSubnet;
+}
+
+
+//
+// Find subnet for given IP address
+//
+
+Subnet *FindSubnetForNode(DWORD dwNodeAddr)
+{
+   DWORD i;
+   Subnet *pSubnet = NULL;
+
+   if ((g_pSubnetIndexByAddr == NULL) || (dwNodeAddr == 0))
+      return NULL;
+
+   RWLockReadLock(g_rwlockSubnetIndex, INFINITE);
+   for(i = 0; i < g_dwSubnetAddrIndexSize; i++)
+      if ((dwNodeAddr & ((Subnet *)g_pSubnetIndexByAddr[i].pObject)->IpNetMask()) == 
+               ((Subnet *)g_pSubnetIndexByAddr[i].pObject)->IpAddr())
+      {
+         pSubnet = (Subnet *)g_pSubnetIndexByAddr[i].pObject;
+         break;
+      }
+   RWLockUnlock(g_rwlockSubnetIndex);
    return pSubnet;
 }
 
@@ -376,10 +401,10 @@ NetObj *FindObjectById(DWORD dwId)
    if (g_pIndexById == NULL)
       return NULL;
 
-   MutexLock(g_hMutexIdIndex, INFINITE);
+   RWLockReadLock(g_rwlockIdIndex, INFINITE);
    dwPos = SearchIndex(g_pIndexById, g_dwIdIndexSize, dwId);
    pObject = (dwPos == INVALID_INDEX) ? NULL : g_pIndexById[dwPos].pObject;
-   MutexUnlock(g_hMutexIdIndex);
+   RWLockUnlock(g_rwlockIdIndex);
    return pObject;
 }
 
@@ -395,14 +420,14 @@ DWORD FindLocalMgmtNode(void)
    if (g_pNodeIndexByAddr == NULL)
       return 0;
 
-   MutexLock(g_hMutexNodeIndex, INFINITE);
+   RWLockReadLock(g_rwlockNodeIndex, INFINITE);
    for(i = 0; i < g_dwNodeAddrIndexSize; i++)
       if (((Node *)g_pNodeIndexByAddr[i].pObject)->Flags() & NF_IS_LOCAL_MGMT)
       {
          dwId = g_pNodeIndexByAddr[i].pObject->Id();
          break;
       }
-   MutexUnlock(g_hMutexNodeIndex);
+   RWLockUnlock(g_rwlockNodeIndex);
    return dwId;
 }
 
@@ -617,8 +642,10 @@ void DeleteUserFromAllObjects(DWORD dwUserId)
    ObjectsGlobalLock();
 
    // Walk through all objects
+   RWLockReadLock(g_rwlockIdIndex, INFINITE);
    for(i = 0; i < g_dwIdIndexSize; i++)
       g_pIndexById[i].pObject->DropUserAccess(dwUserId);
+   RWLockUnlock(g_rwlockIdIndex);
 
    ObjectsGlobalUnlock();
 }
@@ -635,7 +662,7 @@ void DumpObjects(void)
    CONTAINER_CATEGORY *pCat;
 
    pBuffer = (char *)malloc(128000);
-   MutexLock(g_hMutexIdIndex, INFINITE);
+   RWLockReadLock(g_rwlockIdIndex, INFINITE);
    for(i = 0; i < g_dwIdIndexSize; i++)
    {
       printf("Object ID %d \"%s\"\n"
@@ -674,7 +701,7 @@ void DumpObjects(void)
             break;
       }
    }
-   MutexUnlock(g_hMutexIdIndex);
+   RWLockUnlock(g_rwlockIdIndex);
    free(pBuffer);
 }