added custom lock components
[public/netxms.git] / src / server / core / locks.cpp
1 /*
2 ** NetXMS - Network Management System
3 ** Copyright (C) 2003-2010 Victor Kirhenshtein
4 **
5 ** This program is free software; you can redistribute it and/or modify
6 ** it under the terms of the GNU General Public License as published by
7 ** the Free Software Foundation; either version 2 of the License, or
8 ** (at your option) any later version.
9 **
10 ** This program is distributed in the hope that it will be useful,
11 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
12 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 ** GNU General Public License for more details.
14 **
15 ** You should have received a copy of the GNU General Public License
16 ** along with this program; if not, write to the Free Software
17 ** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 **
19 ** File: locks.cpp
20 **
21 **/
22
23 #include "nxcore.h"
24
25
26 //
27 // Constants
28 //
29
30 #define MAX_OWNER_INFO 256
31 #define NUMBER_OF_LOCKS 7
32
33 /**
34 * Lock information structure
35 */
36 struct LOCK_INFO
37 {
38 UINT32 dwLockStatus;
39 const TCHAR *pszName;
40 TCHAR szOwnerInfo[MAX_OWNER_INFO];
41 };
42
43
44 //
45 // Static data
46 //
47
48 static MUTEX m_hMutexLockerAccess = NULL;
49 static LOCK_INFO m_locks[NUMBER_OF_LOCKS] =
50 {
51 { UNLOCKED, _T("Event Processing Policy"), _T("") },
52 { UNLOCKED, _T("User Database"), _T("") },
53 { UNLOCKED, _T("deprecated: Event Configuration Database"), _T("") },
54 { UNLOCKED, _T("deprecated: Action Configuration Database"), _T("") },
55 { UNLOCKED, _T("SNMP Trap Configuration"), _T("") },
56 { UNLOCKED, _T("Package Database"), _T("") },
57 { UNLOCKED, _T("deprecated: Object Tools Configuration"), _T("") }
58 };
59
60 /**
61 * Lock entire database and clear all other locks
62 * Will return FALSE if someone already locked database
63 */
64 BOOL InitLocks(UINT32 *pdwIpAddr, TCHAR *pszInfo)
65 {
66 BOOL bSuccess = FALSE;
67 TCHAR szBuffer[256];
68
69 *pdwIpAddr = UNLOCKED;
70 pszInfo[0] = 0;
71
72 // Check current database lock status
73 ConfigReadStr(_T("DBLockStatus"), szBuffer, 256, _T("ERROR"));
74 DbgPrintf(6, _T("DBLockStatus=\"%s\""), szBuffer);
75 if (!_tcscmp(szBuffer, _T("UNLOCKED")))
76 {
77 IpToStr(GetLocalIpAddr(), szBuffer);
78 ConfigWriteStr(_T("DBLockStatus"), szBuffer, FALSE);
79 GetSysInfoStr(szBuffer, sizeof(szBuffer));
80 ConfigWriteStr(_T("DBLockInfo"), szBuffer, TRUE);
81 ConfigWriteULong(_T("DBLockPID"), GetCurrentProcessId(), TRUE);
82 m_hMutexLockerAccess = MutexCreate();
83 bSuccess = TRUE;
84 }
85 else
86 {
87 if (_tcscmp(szBuffer, _T("ERROR")))
88 {
89 *pdwIpAddr = ntohl(_t_inet_addr(szBuffer));
90 ConfigReadStr(_T("DBLockInfo"), pszInfo, 256, _T("<error>"));
91 }
92 }
93
94 return bSuccess;
95 }
96
97 /**
98 * Unlock database
99 */
100 void NXCORE_EXPORTABLE UnlockDB()
101 {
102 ConfigWriteStr(_T("DBLockStatus"), _T("UNLOCKED"), FALSE);
103 ConfigWriteStr(_T("DBLockInfo"), _T(""), FALSE);
104 ConfigWriteULong(_T("DBLockPID"), 0, FALSE);
105 }
106
107 /**
108 * Lock component
109 * Function will try to lock specified component. On success, will return TRUE.
110 * On failure, will return FALSE and pdwCurrentOwner will be set to the value of lock_status
111 * field, and pszCurrentOwnerInfo will be filled with the value of owner_info field.
112 */
113 BOOL LockComponent(UINT32 dwId, UINT32 dwLockBy, const TCHAR *pszOwnerInfo, UINT32 *pdwCurrentOwner, TCHAR *pszCurrentOwnerInfo)
114 {
115 TCHAR szBuffer[256];
116 BOOL bSuccess = FALSE;
117 UINT32 dwTemp;
118
119 if (pdwCurrentOwner == NULL)
120 pdwCurrentOwner = &dwTemp;
121 if (pszCurrentOwnerInfo == NULL)
122 pszCurrentOwnerInfo = szBuffer;
123
124 if (dwId >= NUMBER_OF_LOCKS)
125 {
126 *pdwCurrentOwner = UNLOCKED;
127 _tcscpy(pszCurrentOwnerInfo, _T("Unknown component"));
128 return FALSE;
129 }
130
131 DbgPrintf(5, _T("*Locks* Attempting to lock component \"%s\" by %d (%s)"),
132 m_locks[dwId].pszName, dwLockBy, pszOwnerInfo != NULL ? pszOwnerInfo : _T("NULL"));
133 MutexLock(m_hMutexLockerAccess);
134 if (m_locks[dwId].dwLockStatus == UNLOCKED)
135 {
136 m_locks[dwId].dwLockStatus = dwLockBy;
137 nx_strncpy(m_locks[dwId].szOwnerInfo, pszOwnerInfo, MAX_OWNER_INFO);
138 bSuccess = TRUE;
139 DbgPrintf(5, _T("*Locks* Component \"%s\" successfully locked by %d (%s)"),
140 m_locks[dwId].pszName, dwLockBy, pszOwnerInfo != NULL ? pszOwnerInfo : _T("NULL"));
141 }
142 else
143 {
144 *pdwCurrentOwner = m_locks[dwId].dwLockStatus;
145 _tcscpy(pszCurrentOwnerInfo, m_locks[dwId].szOwnerInfo);
146 DbgPrintf(5, _T("*Locks* Component \"%s\" cannot be locked by %d (%s) - already locked by \"%s\""),
147 m_locks[dwId].pszName, dwLockBy, pszOwnerInfo != NULL ? pszOwnerInfo : _T("NULL"),
148 m_locks[dwId].szOwnerInfo);
149 }
150 MutexUnlock(m_hMutexLockerAccess);
151 return bSuccess;
152 }
153
154 /**
155 * Unlock component
156 */
157 void UnlockComponent(UINT32 dwId)
158 {
159 MutexLock(m_hMutexLockerAccess);
160 m_locks[dwId].dwLockStatus = UNLOCKED;
161 m_locks[dwId].szOwnerInfo[0] = 0;
162 MutexUnlock(m_hMutexLockerAccess);
163 DbgPrintf(5, _T("*Locks* Component \"%s\" unlocked"), m_locks[dwId].pszName);
164 }
165
166 /**
167 * Unlock all locks for specific session
168 */
169 void RemoveAllSessionLocks(UINT32 dwSessionId)
170 {
171 UINT32 i;
172
173 MutexLock(m_hMutexLockerAccess);
174 for(i = 0; i < NUMBER_OF_LOCKS; i++)
175 if (m_locks[i].dwLockStatus == dwSessionId)
176 {
177 m_locks[i].dwLockStatus = UNLOCKED;
178 m_locks[i].szOwnerInfo[0] = 0;
179 }
180 MutexUnlock(m_hMutexLockerAccess);
181 DbgPrintf(5, _T("*Locks* All locks for session %d removed"), dwSessionId);
182 }