f367297e04f6708f65ab77c3c6acac81a2edebf6
[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 //
35 // Lock structure
36 //
37
38 struct LOCK_INFO
39 {
40 UINT32 dwLockStatus;
41 const TCHAR *pszName;
42 TCHAR szOwnerInfo[MAX_OWNER_INFO];
43 };
44
45
46 //
47 // Static data
48 //
49
50 static MUTEX m_hMutexLockerAccess = NULL;
51 static LOCK_INFO m_locks[NUMBER_OF_LOCKS] =
52 {
53 { UNLOCKED, _T("Event Processing Policy"), _T("") },
54 { UNLOCKED, _T("User Database"), _T("") },
55 { UNLOCKED, _T("deprecated: Event Configuration Database"), _T("") },
56 { UNLOCKED, _T("deprecated: Action Configuration Database"), _T("") },
57 { UNLOCKED, _T("SNMP Trap Configuration"), _T("") },
58 { UNLOCKED, _T("Package Database"), _T("") },
59 { UNLOCKED, _T("deprecated: Object Tools Configuration"), _T("") }
60 };
61
62
63 //
64 // Lock entire database and clear all other locks
65 // Will return FALSE if someone already locked database
66 //
67
68 BOOL InitLocks(UINT32 *pdwIpAddr, TCHAR *pszInfo)
69 {
70 BOOL bSuccess = FALSE;
71 TCHAR szBuffer[256];
72
73 *pdwIpAddr = UNLOCKED;
74 pszInfo[0] = 0;
75
76 // Check current database lock status
77 ConfigReadStr(_T("DBLockStatus"), szBuffer, 256, _T("ERROR"));
78 DbgPrintf(6, _T("DBLockStatus=\"%s\""), szBuffer);
79 if (!_tcscmp(szBuffer, _T("UNLOCKED")))
80 {
81 IpToStr(GetLocalIpAddr(), szBuffer);
82 ConfigWriteStr(_T("DBLockStatus"), szBuffer, FALSE);
83 GetSysInfoStr(szBuffer, sizeof(szBuffer));
84 ConfigWriteStr(_T("DBLockInfo"), szBuffer, TRUE);
85 ConfigWriteULong(_T("DBLockPID"), GetCurrentProcessId(), TRUE);
86 m_hMutexLockerAccess = MutexCreate();
87 bSuccess = TRUE;
88 }
89 else
90 {
91 if (_tcscmp(szBuffer, _T("ERROR")))
92 {
93 *pdwIpAddr = ntohl(_t_inet_addr(szBuffer));
94 ConfigReadStr(_T("DBLockInfo"), pszInfo, 256, _T("<error>"));
95 }
96 }
97
98 return bSuccess;
99 }
100
101
102 //
103 // Unlock database
104 //
105
106 void NXCORE_EXPORTABLE UnlockDB()
107 {
108 ConfigWriteStr(_T("DBLockStatus"), _T("UNLOCKED"), FALSE);
109 ConfigWriteStr(_T("DBLockInfo"), _T(""), FALSE);
110 ConfigWriteULong(_T("DBLockPID"), 0, FALSE);
111 }
112
113
114 //
115 // Lock component
116 // Function will try to lock specified component. On success, will return TRUE.
117 // On failure, will return FALSE and pdwCurrentOwner will be set to the value of lock_status
118 // field, and pszCurrentOwnerInfo will be filled with the value of owner_info field.
119 //
120
121 BOOL LockComponent(UINT32 dwId, UINT32 dwLockBy, const TCHAR *pszOwnerInfo,
122 UINT32 *pdwCurrentOwner, TCHAR *pszCurrentOwnerInfo)
123 {
124 TCHAR szBuffer[256];
125 BOOL bSuccess = FALSE;
126 UINT32 dwTemp;
127
128 if (pdwCurrentOwner == NULL)
129 pdwCurrentOwner = &dwTemp;
130 if (pszCurrentOwnerInfo == NULL)
131 pszCurrentOwnerInfo = szBuffer;
132
133 if (dwId >= NUMBER_OF_LOCKS)
134 {
135 *pdwCurrentOwner = UNLOCKED;
136 _tcscpy(pszCurrentOwnerInfo, _T("Unknown component"));
137 return FALSE;
138 }
139
140 DbgPrintf(5, _T("*Locks* Attempting to lock component \"%s\" by %d (%s)"),
141 m_locks[dwId].pszName, dwLockBy, pszOwnerInfo != NULL ? pszOwnerInfo : _T("NULL"));
142 MutexLock(m_hMutexLockerAccess);
143 if (m_locks[dwId].dwLockStatus == UNLOCKED)
144 {
145 m_locks[dwId].dwLockStatus = dwLockBy;
146 nx_strncpy(m_locks[dwId].szOwnerInfo, pszOwnerInfo, MAX_OWNER_INFO);
147 bSuccess = TRUE;
148 DbgPrintf(5, _T("*Locks* Component \"%s\" successfully locked by %d (%s)"),
149 m_locks[dwId].pszName, dwLockBy, pszOwnerInfo != NULL ? pszOwnerInfo : _T("NULL"));
150 }
151 else
152 {
153 *pdwCurrentOwner = m_locks[dwId].dwLockStatus;
154 _tcscpy(pszCurrentOwnerInfo, m_locks[dwId].szOwnerInfo);
155 DbgPrintf(5, _T("*Locks* Component \"%s\" cannot be locked by %d (%s) - already locked by \"%s\""),
156 m_locks[dwId].pszName, dwLockBy, pszOwnerInfo != NULL ? pszOwnerInfo : _T("NULL"),
157 m_locks[dwId].szOwnerInfo);
158 }
159 MutexUnlock(m_hMutexLockerAccess);
160 return bSuccess;
161 }
162
163
164 //
165 // Unlock component
166 //
167
168 void UnlockComponent(UINT32 dwId)
169 {
170 MutexLock(m_hMutexLockerAccess);
171 m_locks[dwId].dwLockStatus = UNLOCKED;
172 m_locks[dwId].szOwnerInfo[0] = 0;
173 MutexUnlock(m_hMutexLockerAccess);
174 DbgPrintf(5, _T("*Locks* Component \"%s\" unlocked"), m_locks[dwId].pszName);
175 }
176
177
178 //
179 // Unlock all locks for specific session
180 //
181
182 void RemoveAllSessionLocks(UINT32 dwSessionId)
183 {
184 UINT32 i;
185
186 MutexLock(m_hMutexLockerAccess);
187 for(i = 0; i < NUMBER_OF_LOCKS; i++)
188 if (m_locks[i].dwLockStatus == dwSessionId)
189 {
190 m_locks[i].dwLockStatus = UNLOCKED;
191 m_locks[i].szOwnerInfo[0] = 0;
192 }
193 MutexUnlock(m_hMutexLockerAccess);
194 DbgPrintf(5, _T("*Locks* All locks for session %d removed"), dwSessionId);
195 }