license changed to LGPL for libnxcl, libnxsnmp, libnxlp, libnxsl, and libnxmap
[public/netxms.git] / src / libnxmap / map.cpp
1 /*
2 ** NetXMS - Network Management System
3 ** Network Maps Library
4 ** Copyright (C) 2003-2010 Victor Kirhenshtein
5 **
6 ** This program is free software; you can redistribute it and/or modify
7 ** it under the terms of the GNU Lesser General Public License as published by
8 ** the Free Software Foundation; either version 3 of the License, or
9 ** (at your option) any later version.
10 **
11 ** This program is distributed in the hope that it will be useful,
12 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
13 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 ** GNU General Public License for more details.
15 **
16 ** You should have received a copy of the GNU Lesser General Public License
17 ** along with this program; if not, write to the Free Software
18 ** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 **
20 ** File: map.cpp
21 **
22 **/
23
24 #include "libnxmap.h"
25
26
27 //
28 // Default submap creation function
29 //
30
31 static nxSubmap *CreateSubmap(DWORD dwObjectId, nxMap *pMap)
32 {
33 return new nxSubmap(dwObjectId);
34 }
35
36
37 //
38 // Default map object constructor
39 //
40
41 nxMap::nxMap()
42 {
43 CommonInit();
44 }
45
46
47 //
48 // Constructor for new map object
49 //
50
51 nxMap::nxMap(DWORD dwMapId, DWORD dwObjectId, const TCHAR *pszName, const TCHAR *pszDescription)
52 {
53 CommonInit();
54 m_dwMapId = dwMapId;
55 m_dwObjectId = dwObjectId;
56 m_pszName = _tcsdup(pszName);
57 m_pszDescription = _tcsdup(pszDescription);
58 }
59
60
61 //
62 // Create map object from NXCP message
63 //
64
65 nxMap::nxMap(CSCPMessage *pMsg)
66 {
67 CommonInit();
68 ModifyFromMessage(pMsg);
69 }
70
71
72 //
73 // Common initialization code
74 //
75
76 void nxMap::CommonInit(void)
77 {
78 m_dwMapId = 0;
79 m_pszName = NULL;
80 m_pszDescription = NULL;
81 m_dwObjectId = 0;
82 m_dwNumSubmaps = 0;
83 m_ppSubmaps = NULL;
84 m_dwACLSize = 0;
85 m_pACL = NULL;
86 m_mutex = MutexCreate();
87 m_pfCreateSubmap = CreateSubmap;
88 }
89
90
91 //
92 // Destructor
93 //
94
95 nxMap::~nxMap()
96 {
97 DWORD i;
98
99 safe_free(m_pszName);
100 safe_free(m_pszDescription);
101 for(i = 0; i < m_dwNumSubmaps; i++)
102 delete m_ppSubmaps[i];
103 safe_free(m_ppSubmaps);
104 safe_free(m_pACL);
105 MutexDestroy(m_mutex);
106 }
107
108
109 //
110 // Get submap by object ID or create if one doesn't exist
111 //
112
113 nxSubmap *nxMap::GetSubmap(DWORD dwObjectId)
114 {
115 DWORD i;
116 nxSubmap *pSubmap;
117
118 Lock();
119
120 for(i = 0; i < m_dwNumSubmaps; i++)
121 {
122 if (m_ppSubmaps[i]->Id() == dwObjectId)
123 {
124 pSubmap = m_ppSubmaps[i];
125 break;
126 }
127 }
128
129 if (i == m_dwNumSubmaps)
130 {
131 // Create new submap
132 pSubmap = m_pfCreateSubmap(dwObjectId, this);
133 m_dwNumSubmaps++;
134 m_ppSubmaps = (nxSubmap **)realloc(m_ppSubmaps, sizeof(nxSubmap *) * m_dwNumSubmaps);
135 m_ppSubmaps[i] = pSubmap;
136 }
137
138 Unlock();
139 return pSubmap;
140 }
141
142
143 //
144 // Add new or replace existing submap
145 //
146
147 void nxMap::AddSubmap(nxSubmap *pSubmap)
148 {
149 DWORD i;
150
151 Lock();
152
153 // Check if submap with given ID exist
154 for(i = 0; i < m_dwNumSubmaps; i++)
155 {
156 if (m_ppSubmaps[i]->Id() == pSubmap->Id())
157 {
158 break;
159 }
160 }
161
162 if (i == m_dwNumSubmaps)
163 {
164 // Add new submap
165 m_dwNumSubmaps++;
166 m_ppSubmaps = (nxSubmap **)realloc(m_ppSubmaps, sizeof(nxSubmap *) * m_dwNumSubmaps);
167 m_ppSubmaps[i] = pSubmap;
168 }
169 else
170 {
171 // Replace existing submap
172 delete m_ppSubmaps[i];
173 m_ppSubmaps[i] = pSubmap;
174 }
175
176 Unlock();
177 }
178
179
180 //
181 // Check if submap for given object exists
182 //
183
184 BOOL nxMap::IsSubmapExist(DWORD dwObjectId, BOOL bLock)
185 {
186 BOOL bRet = FALSE;
187 DWORD i;
188
189 if (bLock)
190 Lock();
191
192 for(i = 0; i < m_dwNumSubmaps; i++)
193 {
194 if (m_ppSubmaps[i]->Id() == dwObjectId)
195 {
196 bRet = TRUE;
197 break;
198 }
199 }
200
201 if (bLock)
202 Unlock();
203 return bRet;
204 }
205
206
207 //
208 // Fill NXCP message with map data
209 //
210
211 void nxMap::CreateMessage(CSCPMessage *pMsg)
212 {
213 DWORD i, j, *pdwACL, *pdwSubmapList;
214
215 pdwACL = (DWORD *)malloc(sizeof(DWORD) * m_dwACLSize * 2);
216 for(i = 0, j = 0; i < m_dwACLSize; i++)
217 {
218 pdwACL[j++] = m_pACL[i].dwUserId;
219 pdwACL[j++] = m_pACL[i].dwAccess;
220 }
221
222 pdwSubmapList = (DWORD *)malloc(sizeof(DWORD) * m_dwNumSubmaps);
223 for(i = 0; i < m_dwNumSubmaps; i++)
224 pdwSubmapList[i] = m_ppSubmaps[i]->Id();
225
226 pMsg->SetVariable(VID_MAP_ID, m_dwMapId);
227 pMsg->SetVariable(VID_NAME, m_pszName);
228 pMsg->SetVariable(VID_DESCRIPTION, m_pszDescription);
229 pMsg->SetVariable(VID_OBJECT_ID, m_dwObjectId);
230 pMsg->SetVariable(VID_NUM_SUBMAPS, m_dwNumSubmaps);
231 pMsg->SetVariableToInt32Array(VID_SUBMAP_LIST, m_dwNumSubmaps, pdwSubmapList);
232 pMsg->SetVariable(VID_ACL_SIZE, m_dwACLSize);
233 pMsg->SetVariableToInt32Array(VID_ACL, m_dwACLSize * 2, pdwACL);
234
235 safe_free(pdwACL);
236 safe_free(pdwSubmapList);
237 }
238
239
240 //
241 // Modify map object from NXCP message
242 //
243
244 void nxMap::ModifyFromMessage(CSCPMessage *pMsg)
245 {
246 DWORD i, j, dwNumSubmaps, *pdwTemp;
247
248 // Update simple attributes
249 m_dwMapId = pMsg->GetVariableLong(VID_MAP_ID);
250 m_dwObjectId = pMsg->GetVariableLong(VID_OBJECT_ID);
251 safe_free(m_pszName);
252 m_pszName = pMsg->GetVariableStr(VID_NAME);
253 safe_free(m_pszDescription);
254 m_pszDescription = pMsg->GetVariableStr(VID_DESCRIPTION);
255
256 // Delete submaps which are no longer exist
257 dwNumSubmaps = pMsg->GetVariableLong(VID_NUM_SUBMAPS);
258 pdwTemp = (DWORD *)malloc(sizeof(DWORD) * dwNumSubmaps);
259 pMsg->GetVariableInt32Array(VID_SUBMAP_LIST, dwNumSubmaps, pdwTemp);
260 for(i = 0; i < m_dwNumSubmaps; i++)
261 {
262 for(j = 0; j < dwNumSubmaps; j++)
263 if (pdwTemp[j] == m_ppSubmaps[i]->Id())
264 break;
265 if (j == dwNumSubmaps)
266 {
267 delete m_ppSubmaps[i];
268 m_dwNumSubmaps--;
269 memmove(&m_ppSubmaps[i], &m_ppSubmaps[i + 1], sizeof(nxSubmap *) * (m_dwNumSubmaps - i));
270 i--;
271 }
272 }
273 safe_free(pdwTemp);
274
275 // Update ACL
276 m_dwACLSize = pMsg->GetVariableLong(VID_ACL_SIZE);
277 pdwTemp = (DWORD *)malloc(sizeof(DWORD) * m_dwACLSize * 2);
278 pMsg->GetVariableInt32Array(VID_ACL, m_dwACLSize * 2, pdwTemp);
279 safe_free(m_pACL);
280 m_pACL = (MAP_ACL_ENTRY *)malloc(sizeof(MAP_ACL_ENTRY) * m_dwACLSize);
281 for(i = 0, j = 0; i < m_dwACLSize; i++)
282 {
283 m_pACL[i].dwUserId = pdwTemp[j++];
284 m_pACL[i].dwAccess = pdwTemp[j++];
285 }
286 }