- Read/Write locks implementation moved to libnetxms
authorVictor Kirhenshtein <victor@netxms.org>
Tue, 8 Aug 2006 13:33:33 +0000 (13:33 +0000)
committerVictor Kirhenshtein <victor@netxms.org>
Tue, 8 Aug 2006 13:33:33 +0000 (13:33 +0000)
- Updates in TODO, INSTALL, etc.

14 files changed:
.gitattributes
ChangeLog
INSTALL
THANKS
TODO
UPGRADE
configure.ac
include/nms_threads.h
include/rwlock.h [moved from src/server/include/rwlock.h with 64% similarity]
src/libnetxms/Makefile.am
src/libnetxms/libnetxms.dsp
src/libnetxms/rwlock.cpp [new file with mode: 0644]
src/server/include/nxsrvapi.h
src/server/libnxsrv/libnxsrv.dsp

index 3d59b45..58d4d6a 100644 (file)
@@ -213,6 +213,7 @@ include/nxsm_ext.h -text
 include/nxsnmp.h -text
 include/nxtools.h -text
 include/nxwinui.h -text
+include/rwlock.h -text
 include/unicode.h -text
 include/uuid.h -text
 m4/Makefile.am -text
@@ -947,6 +948,7 @@ src/libnetxms/md5.h -text
 src/libnetxms/netxms.def -text
 src/libnetxms/queue.cpp -text
 src/libnetxms/regex.c -text
+src/libnetxms/rwlock.cpp -text
 src/libnetxms/scandir.c -text
 src/libnetxms/serial.cpp -text
 src/libnetxms/sha1.cpp -text
@@ -1160,7 +1162,6 @@ src/server/include/nms_users.h -text
 src/server/include/nxcore_maps.h -text
 src/server/include/nxmodule.h -text
 src/server/include/nxsrvapi.h -text
-src/server/include/rwlock.h -text
 src/server/libnxsrv/.cvsignore -text
 src/server/libnxsrv/Makefile.am -text
 src/server/libnxsrv/agent.cpp -text
index 4d2394d..93bede3 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -7,6 +7,7 @@
   Windows agent
 - New MIBs added: S5-ETH-MULTISEG-TOPOLOGY-MIB
 - Server startup and shutdown procedures improved
+- Native operating system read/write locks used whenever possible
 - Windows console:
        - DCI history data viewer improved
 - Fixed issues: #4, #20, #67, #79, #80, #91, #92, #93, #94
diff --git a/INSTALL b/INSTALL
index ed8a21c..872d775 100644 (file)
--- a/INSTALL
+++ b/INSTALL
@@ -6,8 +6,8 @@ Basic NetXMS Installation
 =========================
 
    These are generic installation instructions. For more detailed
-installation instruction consult docs/install-guide.doc (when it will be
-ready).
+installation instruction consult NetXMS Installation Guide (located in
+doc/manuals, also available separately on NetXMS web site).
 
 The simplest way to install netxms server is:
 
@@ -48,20 +48,20 @@ The simplest way to install netxms server is:
   5. Type `make install' to install the programs and any data files and
      documentation.
  
-  6. Use sql/dbinit_[dbname].sql script and Your database client
+  6. Copy default netxms daemon configuration file ('netxmsd.conf-dist') to /etc
+     directory with name 'netxmsd.conf' and edit it to match actual settings.
+     You can do it like this: 
+     cp ./netxmsd.conf-dist /etc/netxmsd.conf
+     vi /etc/netxmsd.conf
+  
+  7. Use sql/dbinit_[dbname].sql script and Your database client
      program to initialize database for netxms. 
      For example if You're going to use mysql this could be like this:
 
      mysql> create database netxms;
      mysql> \q
-     $> mysql netxms < sql/dbinit_mysql.sql
+     $> nxdbmgr init sql/dbinit_mysql.sql
 
-  7. Copy default netxms daemon configuration file ('netxmsd.conf-dist') to /etc
-     directory with name 'netxmsd.conf' and edit it to match actual settings.
-     You can do it like this: 
-     cp ./netxmsd.conf-dist /etc/netxmsd.conf
-     vi /etc/netxmsd.conf
-  
   8. `cd' to netxms installation directory and try running bin/netxmsd.
      Check if netsmd process is running. If not try starting it again with
      --debug-all parameter and see log file for details.
diff --git a/THANKS b/THANKS
index 0b5eb48..9c728aa 100644 (file)
--- a/THANKS
+++ b/THANKS
@@ -1,6 +1,13 @@
 NetXMS THANKS file
 
-NetXMS has originally been written by NetXMS Team.
-Many people have further contributed to FOO by reporting problems, 
+NetXMS has originally been written by Victor Kirhenshtein and Alex Kirhenshtein.
+Many people have further contributed to NetXMS by reporting problems, 
 suggesting various improvements, or submitting actual code. Here is
 a list of these people. Help me keep it complete and exempt of errors.
+
+People from C.T.Co:
+
+Igor Kopman
+Roman Lazarenko
+Victoria Almazova
+
diff --git a/TODO b/TODO
index e81a9a6..55f53d4 100644 (file)
--- a/TODO
+++ b/TODO
@@ -10,7 +10,6 @@ GENERAL:
 - Finish AIX subagent
 - HP-UX subagent
 - Write README for NetWare
-- Add check for read/write locks support to configure script
 - Add ability to clear collected DCI data
 - Add possibility to set different polling timeouts for different nodes
 - Planned outages (maintenance schedule)
diff --git a/UPGRADE b/UPGRADE
index 553e15c..0a0c4b2 100644 (file)
--- a/UPGRADE
+++ b/UPGRADE
@@ -1,26 +1,2 @@
-Upgrading NetXMS server
-=======================
-1. Unpack source package
-2. Run ./configure --with-agent --with-server --with-<your_db_driver>
-3. Run make
-4. Stop NetXMS server
-5. Stop NetXMS agent
-6. Run "nxdbmgr check"
-7. Run make install
-8. Run "nxdbmgr upgrade"
-9. Unpack new image and MIB files to appropriate directories (usually under
-/var/netxms)
-10. Start NetXMS agent
-11. Start NetXMS server
-
-Upgrading NetXMS agent
-======================
-    Normally netxms agent is upgraded automatically from netxms console via
-netxms server. This makes possible upgrade of hundreds of servers with just
-a few clicks.
-    However if want to upgrade netxms agent manually this can be done in 4
-generic steps:
-    1. Backup agent config file
-    2. Erase agent installation tree
-    3. Install netxms agent
-    4. Restore config from backup.
+For upgrade instructions, please consult NetXMS Installation Guide (located
+in doc/manuals, also available separately on NetXMS website).
index f39f3ce..97bf0f2 100644 (file)
@@ -1,4 +1,4 @@
-# $Id: configure.ac,v 1.163 2006-08-07 21:52:17 victor Exp $
+# $Id: configure.ac,v 1.164 2006-08-08 13:33:29 victor Exp $
 #
 # Process this file with autoconf to produce a configure script.
 #
@@ -575,7 +575,7 @@ if test "$ac_cv_func_pthread_rwlock_init" = "yes"; then
                        fi
                        ])])
        if test "$ac_cv_struct_pthread_rw" = "yes"; then
-               AC_DEFINE(HAVE_PTHREAD_RWLOCK_T, 1, Define to 1 if you have the 'pthread_rwlock_t' defined)
+               AC_DEFINE(HAVE_PTHREAD_RWLOCK, 1, Define to 1 if you have working pthread read/write locks)
        fi
 fi
 
index 851cd08..bc48347 100644 (file)
@@ -30,7 +30,7 @@
 #ifdef _WIN32
 
 #ifndef UNDER_CE
-# include <process.h>
+#include <process.h>
 #endif
 
 //
@@ -530,6 +530,8 @@ inline DWORD GetCurrentProcessId(void)
 
 #endif   /* _WIN32 */
 
+#include <rwlock.h>
+
 #endif   /* __cplusplus */
 
 #endif   /* _nms_threads_h_ */
similarity index 64%
rename from src/server/include/rwlock.h
rename to include/rwlock.h
index 9c1beda..8eb628e 100644 (file)
@@ -1,7 +1,7 @@
 /* 
 ** NetXMS - Network Management System
-** Server Library
-** Copyright (C) 2003, 2004 Victor Kirhenshtein
+** NetXMS Foundation Library
+** Copyright (C) 2003, 2004, 2005, 2006 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
 ** along with this program; if not, write to the Free Software
 ** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 **
-** $module: rwlock.h
+** File: rwlock.h
 **
 **/
 
 #ifndef _rwlock_h_
 #define _rwlock_h_
 
-#include <nms_threads.h>
-
 #if HAVE_PTHREAD_RWLOCK
 
 typedef pthread_rwlock_t * RWLOCK;
@@ -54,7 +52,6 @@ inline void RWLockDestroy(RWLOCK hLock)
 
 inline BOOL RWLockReadLock(RWLOCK hLock, DWORD dwTimeOut)
 {
-       int i;
        BOOL ret = FALSE;
 
    if (hLock != NULL) 
@@ -68,7 +65,21 @@ inline BOOL RWLockReadLock(RWLOCK hLock, DWORD dwTimeOut)
                }
                else
                {
-                       for (i = (dwTimeOut / 50) + 1; i > 0; i--) 
+#if HAVE_PTHREAD_RWLOCK_TIMEDRDLOCK
+                       struct timeval now;
+                       struct timespec timeout;
+
+                       // FIXME: there should be more accurate way
+                       gettimeofday(&now, NULL);
+                       timeout.tv_sec = now.tv_sec + (dwTimeOut / 1000);
+
+                       now.tv_usec += (dwTimeOut % 1000) * 1000;
+                       timeout.tv_sec += now.tv_usec / 1000000;
+                       timeout.tv_nsec = (now.tv_usec % 1000000) * 1000;
+
+                       retcode = pthread_rwlock_timedrdlock(hLock, &timeout);
+#else
+                       for(int i = (dwTimeOut / 50) + 1; i > 0; i--) 
          {
                                if (pthread_rwlock_tryrdlock(hLock) == 0) 
             {
@@ -77,6 +88,7 @@ inline BOOL RWLockReadLock(RWLOCK hLock, DWORD dwTimeOut)
                                }
                                ThreadSleepMs(50);
                        }
+#endif
                }
        }
    return ret;
@@ -84,7 +96,6 @@ inline BOOL RWLockReadLock(RWLOCK hLock, DWORD dwTimeOut)
 
 inline BOOL RWLockWriteLock(RWLOCK hLock, DWORD dwTimeOut)
 {
-       int i;
        BOOL ret = FALSE;
 
    if (hLock != NULL) 
@@ -98,7 +109,21 @@ inline BOOL RWLockWriteLock(RWLOCK hLock, DWORD dwTimeOut)
                }
                else
                {
-                       for (i = (dwTimeOut / 50) + 1; i > 0; i--) 
+#if HAVE_PTHREAD_RWLOCK_TIMEDWRLOCK
+                       struct timeval now;
+                       struct timespec timeout;
+
+                       // FIXME: there should be more accurate way
+                       gettimeofday(&now, NULL);
+                       timeout.tv_sec = now.tv_sec + (dwTimeOut / 1000);
+
+                       now.tv_usec += (dwTimeOut % 1000) * 1000;
+                       timeout.tv_sec += now.tv_usec / 1000000;
+                       timeout.tv_nsec = (now.tv_usec % 1000000) * 1000;
+
+                       retcode = pthread_rwlock_timedwrlock(hLock, &timeout);
+#else
+                       for(int i = (dwTimeOut / 50) + 1; i > 0; i--) 
          {
                                if (pthread_rwlock_trywrlock(hLock) == 0) 
             {
@@ -107,6 +132,7 @@ inline BOOL RWLockWriteLock(RWLOCK hLock, DWORD dwTimeOut)
                                }
                                ThreadSleepMs(50);
                        }
+#endif
                }
        }
    return ret;
@@ -118,7 +144,7 @@ inline void RWLockUnlock(RWLOCK hLock)
       pthread_rwlock_unlock(hLock);
 }
 
-#else
+#else    /* HAVE_PTHREAD_RWLOCK */
 
 struct __rwlock_data
 {
@@ -138,11 +164,11 @@ struct __rwlock_data
 
 typedef struct __rwlock_data * RWLOCK;
 
-RWLOCK LIBNXSRV_EXPORTABLE RWLockCreate(void);
-void LIBNXSRV_EXPORTABLE RWLockDestroy(RWLOCK hLock);
-BOOL LIBNXSRV_EXPORTABLE RWLockReadLock(RWLOCK hLock, DWORD dwTimeOut);
-BOOL LIBNXSRV_EXPORTABLE RWLockWriteLock(RWLOCK hLock, DWORD dwTimeOut);
-void LIBNXSRV_EXPORTABLE RWLockUnlock(RWLOCK hLock);
+RWLOCK LIBNETXMS_EXPORTABLE RWLockCreate(void);
+void LIBNETXMS_EXPORTABLE RWLockDestroy(RWLOCK hLock);
+BOOL LIBNETXMS_EXPORTABLE RWLockReadLock(RWLOCK hLock, DWORD dwTimeOut);
+BOOL LIBNETXMS_EXPORTABLE RWLockWriteLock(RWLOCK hLock, DWORD dwTimeOut);
+void LIBNETXMS_EXPORTABLE RWLockUnlock(RWLOCK hLock);
 
 #endif
 
index ea22712..0fa1721 100644 (file)
@@ -1,7 +1,7 @@
 INCLUDES=-I@top_srcdir@/include
 
 lib_LTLIBRARIES = libnetxms.la
-libnetxms_la_SOURCES = config.cpp gen_uuid.c dload.cpp hash.cpp icmp.cpp inline.cpp main.cpp md5.cpp queue.cpp scandir.c serial.cpp sha1.cpp strtoll.c strtoull.c threads.cpp tools.cpp unicode.cpp uuid.c
+libnetxms_la_SOURCES = config.cpp gen_uuid.c dload.cpp hash.cpp icmp.cpp inline.cpp main.cpp md5.cpp queue.cpp rwlock.cpp scandir.c serial.cpp sha1.cpp strtoll.c strtoull.c threads.cpp tools.cpp unicode.cpp uuid.c
 libnetxms_la_LDFLAGS = -version-info $(LIBNETXMS_LIBRARY_VERSION) $(PTHREAD_LIBS)
 
 EXTRA_DIST = \
index bf58931..c32e99e 100644 (file)
@@ -221,6 +221,10 @@ SOURCE=.\regex.c
 # End Source File
 # Begin Source File
 
+SOURCE=.\rwlock.cpp
+# End Source File
+# Begin Source File
+
 SOURCE=.\scandir.c
 # End Source File
 # Begin Source File
@@ -297,6 +301,10 @@ SOURCE=..\..\include\nxqueue.h
 # End Source File
 # Begin Source File
 
+SOURCE=..\..\include\rwlock.h
+# End Source File
+# Begin Source File
+
 SOURCE=.\sha1.h
 # End Source File
 # Begin Source File
diff --git a/src/libnetxms/rwlock.cpp b/src/libnetxms/rwlock.cpp
new file mode 100644 (file)
index 0000000..b4c7f5f
--- /dev/null
@@ -0,0 +1,344 @@
+/* 
+** NetXMS - Network Management System
+** NetXMS Foundation Library
+** Copyright (C) 2003, 2004, 2005, 2006 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.
+**
+** File: rwlock.cpp
+**
+**/
+
+#include "libnetxms.h"
+#include <assert.h>
+
+#if !HAVE_PTHREAD_RWLOCK
+
+//
+// Create read/write lock
+//
+
+RWLOCK LIBNETXMS_EXPORTABLE RWLockCreate(void)
+{
+   RWLOCK hLock;
+
+   hLock = (RWLOCK)malloc(sizeof(struct __rwlock_data));
+   if (hLock != NULL)
+   {
+#ifdef _WIN32
+      hLock->m_mutex = CreateMutex(NULL, FALSE, NULL);
+      hLock->m_condRead = CreateEvent(NULL, TRUE, FALSE, NULL);
+      hLock->m_condWrite = CreateEvent(NULL, FALSE, FALSE, NULL);
+#else
+      pthread_mutex_init(&hLock->m_mutex, NULL);
+      pthread_cond_init(&hLock->m_condRead, NULL);
+      pthread_cond_init(&hLock->m_condWrite, NULL);
+#endif
+      hLock->m_dwWaitReaders = 0;
+      hLock->m_dwWaitWriters = 0;
+      hLock->m_iRefCount = 0;
+   }
+
+   return hLock;
+}
+
+
+//
+// Destroy read/write lock
+//
+
+void LIBNETXMS_EXPORTABLE RWLockDestroy(RWLOCK hLock)
+{
+   if (hLock != NULL)
+   {
+      if (hLock->m_iRefCount == 0)
+      {
+#ifdef _WIN32
+         CloseHandle(hLock->m_mutex);
+         CloseHandle(hLock->m_condRead);
+         CloseHandle(hLock->m_condWrite);
+#else
+         pthread_mutex_destroy(&hLock->m_mutex);
+         pthread_cond_destroy(&hLock->m_condRead);
+         pthread_cond_destroy(&hLock->m_condWrite);
+#endif
+         free(hLock);
+      }
+   }
+}
+
+
+//
+// Lock read/write lock for reading
+//
+
+BOOL LIBNETXMS_EXPORTABLE RWLockReadLock(RWLOCK hLock, DWORD dwTimeOut)
+{
+   BOOL bResult = FALSE;
+   int retcode;
+
+   // Check if handle is valid
+   if (hLock == NULL)
+      return FALSE;
+
+#ifdef _WIN32
+   DWORD dwStart, dwElapsed;
+   BOOL bTimeOut = FALSE;
+
+   // Acquire access to handle
+   WaitForSingleObject(hLock->m_mutex, INFINITE);
+
+   do
+   {
+      if ((hLock->m_iRefCount == -1) || (hLock->m_dwWaitWriters > 0))
+      {
+         // Object is locked for writing or somebody wish to lock it for writing
+         hLock->m_dwWaitReaders++;
+         ReleaseMutex(hLock->m_mutex);
+         dwStart = GetTickCount();
+         retcode = WaitForSingleObject(hLock->m_condRead, dwTimeOut);
+         dwElapsed = GetTickCount() - dwStart;
+         WaitForSingleObject(hLock->m_mutex, INFINITE);   // Re-acquire mutex
+         hLock->m_dwWaitReaders--;
+         if (retcode == WAIT_TIMEOUT)
+         {
+            bTimeOut = TRUE;
+         }
+         else
+         {
+            if (dwTimeOut != INFINITE)
+            {
+               dwTimeOut -= min(dwElapsed, dwTimeOut);
+            }
+         }
+      }
+      else
+      {
+         hLock->m_iRefCount++;
+         bResult = TRUE;
+      }
+   } while((!bResult) && (!bTimeOut));
+
+   ReleaseMutex(hLock->m_mutex);
+#else
+   // Acquire access to handle
+   if (pthread_mutex_lock(&hLock->m_mutex) != 0)
+      return FALSE;     // Problem with mutex
+
+   if ((hLock->m_iRefCount == -1) || (hLock->m_dwWaitWriters > 0))
+   {
+      // Object is locked for writing or somebody wish to lock it for writing
+      hLock->m_dwWaitReaders++;
+
+      if (dwTimeOut == INFINITE)
+      {
+         retcode = pthread_cond_wait(&hLock->m_condRead, &hLock->m_mutex);
+      }
+      else
+      {
+#if HAVE_PTHREAD_COND_RELTIMEDWAIT_NP
+                  struct timespec timeout;
+
+                  timeout.tv_sec = dwTimeOut / 1000;
+                  timeout.tv_nsec = (dwTimeOut % 1000) * 1000000;
+                  retcode = pthread_cond_reltimedwait_np(&hLock->m_condRead, &hLock->m_mutex, &timeout);
+#else
+                  struct timeval now;
+                  struct timespec timeout;
+
+                  gettimeofday(&now, NULL);
+                  timeout.tv_sec = now.tv_sec + (dwTimeOut / 1000);
+                  timeout.tv_nsec = ( now.tv_usec + ( dwTimeOut % 1000 ) * 1000) * 1000;
+                  retcode = pthread_cond_timedwait(&hLock->m_condRead, &hLock->m_mutex, &timeout);
+#endif
+      }
+
+      hLock->m_dwWaitReaders--;
+      if (retcode == 0)
+      {
+         assert(hLock->m_iRefCount != -1);
+         hLock->m_iRefCount++;
+         bResult = TRUE;
+      }
+   }
+   else
+   {
+      hLock->m_iRefCount++;
+      bResult = TRUE;
+   }
+
+   pthread_mutex_unlock(&hLock->m_mutex);
+#endif
+
+   return bResult;
+}
+
+
+//
+// Lock read/write lock for writing
+//
+
+BOOL LIBNETXMS_EXPORTABLE RWLockWriteLock(RWLOCK hLock, DWORD dwTimeOut)
+{
+   BOOL bResult = FALSE;
+   int retcode;
+
+   // Check if handle is valid
+   if (hLock == NULL)
+      return FALSE;
+
+#ifdef _WIN32
+   DWORD dwStart, dwElapsed;
+   BOOL bTimeOut = FALSE;
+
+   WaitForSingleObject(hLock->m_mutex, INFINITE);
+   // Reset reader event because it can be set by previous Unlock() call
+   ResetEvent(hLock->m_condRead);
+
+   do
+   {
+      if (hLock->m_iRefCount != 0)
+      {
+         hLock->m_dwWaitWriters++;
+         ReleaseMutex(hLock->m_mutex);
+         dwStart = GetTickCount();
+         retcode = WaitForSingleObject(hLock->m_condWrite, dwTimeOut);
+         dwElapsed = GetTickCount() - dwStart;
+         WaitForSingleObject(hLock->m_mutex, INFINITE);   // Re-acquire mutex
+         hLock->m_dwWaitWriters--;
+         if (retcode == WAIT_TIMEOUT)
+         {
+            bTimeOut = TRUE;
+         }
+         else
+         {
+            if (dwTimeOut != INFINITE)
+            {
+               dwTimeOut -= min(dwElapsed, dwTimeOut);
+            }
+         }
+      }
+      else
+      {
+         hLock->m_iRefCount--;
+         bResult = TRUE;
+      }
+   } while((!bResult) && (!bTimeOut));
+
+   ReleaseMutex(hLock->m_mutex);
+#else
+   if (pthread_mutex_lock(&hLock->m_mutex) != 0)
+      return FALSE;     // Problem with mutex
+
+   if (hLock->m_iRefCount != 0)
+   {
+      // Object is locked, wait for unlock
+      hLock->m_dwWaitWriters++;
+
+      if (dwTimeOut == INFINITE)
+      {
+         retcode = pthread_cond_wait(&hLock->m_condWrite, &hLock->m_mutex);
+      }
+      else
+      {
+#if HAVE_PTHREAD_COND_RELTIMEDWAIT_NP
+                  struct timespec timeout;
+
+                  timeout.tv_sec = dwTimeOut / 1000;
+                  timeout.tv_nsec = (dwTimeOut % 1000) * 1000000;
+                  retcode = pthread_cond_reltimedwait_np(&hLock->m_condWrite, &hLock->m_mutex, &timeout);
+#else
+                  struct timeval now;
+                  struct timespec timeout;
+
+                  gettimeofday(&now, NULL);
+                  timeout.tv_sec = now.tv_sec + (dwTimeOut / 1000);
+                  timeout.tv_nsec = ( now.tv_usec + ( dwTimeOut % 1000 ) * 1000) * 1000;
+                  retcode = pthread_cond_timedwait(&hLock->m_condWrite, &hLock->m_mutex, &timeout);
+#endif
+      }
+
+      hLock->m_dwWaitWriters--;
+      if (retcode == 0)
+      {
+         assert(hLock->m_iRefCount == 0);
+         hLock->m_iRefCount--;
+         bResult = TRUE;
+      }
+   }
+   else
+   {
+      hLock->m_iRefCount--;
+      bResult = TRUE;
+   }
+
+   pthread_mutex_unlock(&hLock->m_mutex);
+#endif
+
+   return bResult;
+}
+
+
+//
+// Unlock read/write lock
+//
+
+void LIBNETXMS_EXPORTABLE RWLockUnlock(RWLOCK hLock)
+{
+   // Check if handle is valid
+   if (hLock == NULL)
+      return;
+
+   // Acquire access to handle
+#ifdef _WIN32
+   WaitForSingleObject(hLock->m_mutex, INFINITE);
+#else
+   if (pthread_mutex_lock(&hLock->m_mutex) != 0)
+      return;     // Problem with mutex
+#endif
+
+   // Remove lock
+   if (hLock->m_iRefCount > 0)
+      hLock->m_iRefCount--;
+   else if (hLock->m_iRefCount == -1)
+      hLock->m_iRefCount = 0;
+
+   // Notify waiting threads
+   if (hLock->m_dwWaitWriters > 0)
+   {
+      if (hLock->m_iRefCount == 0)
+#ifdef _WIN32
+         SetEvent(hLock->m_condWrite);
+#else
+         pthread_cond_signal(&hLock->m_condWrite);
+#endif
+   }
+   else if (hLock->m_dwWaitReaders > 0)
+   {
+#ifdef _WIN32
+      SetEvent(hLock->m_condRead);
+#else
+      pthread_cond_broadcast(&hLock->m_condRead);
+#endif
+   }
+
+#ifdef _WIN32
+   ReleaseMutex(hLock->m_mutex);
+#else
+   pthread_mutex_unlock(&hLock->m_mutex);
+#endif
+}
+
+#endif   /* !HAVE_PTHREAD_RWLOCK */
index 683850f..1746595 100644 (file)
@@ -1,7 +1,7 @@
 /* 
 ** NetXMS - Network Management System
 ** Server Library
-** Copyright (C) 2003, 2004 Victor Kirhenshtein
+** Copyright (C) 2003, 2004, 2005, 2006 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
@@ -17,7 +17,7 @@
 ** along with this program; if not, write to the Free Software
 ** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 **
-** $module: nxsrvapi.h
+** File: nxsrvapi.h
 **
 **/
 
@@ -40,7 +40,6 @@
 #include <nxclapi.h>
 #include <nxcscpapi.h>
 #include <nms_agent.h>
-#include <rwlock.h>
 #include <messages.h>
 #include <dbdrv.h>
 
index 11cdaaf..927894c 100644 (file)
@@ -188,10 +188,6 @@ SOURCE=.\log.cpp
 
 SOURCE=.\main.cpp
 # End Source File
-# Begin Source File
-
-SOURCE=.\rwlock.cpp
-# End Source File
 # End Group
 # Begin Group "Header Files"
 
@@ -240,10 +236,6 @@ SOURCE=..\..\..\include\nxcscpapi.h
 
 SOURCE=..\include\nxsrvapi.h
 # End Source File
-# Begin Source File
-
-SOURCE=..\include\rwlock.h
-# End Source File
 # End Group
 # Begin Group "Resource Files"