fixed compiler warnings
[public/netxms.git] / src / server / core / dctable.cpp
CommitLineData
4016c0df 1/*
16d6f798 2** NetXMS - Network Management System
a31a2d32 3** Copyright (C) 2003-2017 Victor Kirhenshtein
16d6f798
VK
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: dctable.cpp
20**
21**/
22
23#include "nxcore.h"
24
480e036b
VK
25/**
26 * Column ID cache
27 */
ba89fed2
VK
28TC_ID_MAP_ENTRY *DCTable::m_cache = NULL;
29int DCTable::m_cacheSize = 0;
30int DCTable::m_cacheAllocated = 0;
31MUTEX DCTable::m_cacheMutex = MutexCreate();
32
480e036b
VK
33/**
34 * Compare cache element's name to string key
35 */
ba89fed2
VK
36static int CompareCacheElements(const void *key, const void *element)
37{
38 return _tcsicmp((const TCHAR *)key, ((TC_ID_MAP_ENTRY *)element)->name);
39}
40
480e036b
VK
41/**
42 * Compare names of two cache elements
43 */
ba89fed2
VK
44static int CompareCacheElements2(const void *e1, const void *e2)
45{
46 return _tcsicmp(((TC_ID_MAP_ENTRY *)e1)->name, ((TC_ID_MAP_ENTRY *)e2)->name);
47}
48
480e036b
VK
49/**
50 * Get column ID from column name
51 */
967893bb 52INT32 DCTable::columnIdFromName(const TCHAR *name)
ba89fed2
VK
53{
54 TC_ID_MAP_ENTRY buffer;
55
56 // check that column name is valid
57 if ((name == NULL) || (*name == 0))
58 return 0;
59
60 MutexLock(m_cacheMutex);
61
62 TC_ID_MAP_ENTRY *entry = (TC_ID_MAP_ENTRY *)bsearch(name, m_cache, m_cacheSize, sizeof(TC_ID_MAP_ENTRY), CompareCacheElements);
63 if (entry == NULL)
64 {
65 // Not in cache, go to database
66 DB_HANDLE hdb = DBConnectionPoolAcquireConnection();
67
68 DB_STATEMENT hStmt = DBPrepare(hdb, _T("SELECT column_id FROM dct_column_names WHERE column_name=?"));
69 if (hStmt != NULL)
70 {
71 DBBind(hStmt, 1, DB_SQLTYPE_VARCHAR, name, DB_BIND_STATIC);
72 DB_RESULT hResult = DBSelectPrepared(hStmt);
73 if (hResult != NULL)
74 {
75 entry = &buffer;
76 nx_strncpy(entry->name, name, MAX_COLUMN_NAME);
77 if (DBGetNumRows(hResult) > 0)
78 {
79 // found in database
80 entry->id = DBGetFieldLong(hResult, 0, 0);
81 }
82 else
83 {
84 // no such column name in database
85 entry->id = CreateUniqueId(IDG_DCT_COLUMN);
86
87 // update database
88 DB_STATEMENT hStmt2 = DBPrepare(hdb, _T("INSERT INTO dct_column_names (column_id,column_name) VALUES (?,?)"));
89 if (hStmt2 != NULL)
90 {
91 DBBind(hStmt2, 1, DB_SQLTYPE_INTEGER, entry->id);
92 DBBind(hStmt2, 2, DB_SQLTYPE_VARCHAR, name, DB_BIND_STATIC);
93 DBExecute(hStmt2);
94 DBFreeStatement(hStmt2);
95 }
96 }
4016c0df 97
ba89fed2
VK
98 DBFreeResult(hResult);
99
100 // Add to cache
101 if (m_cacheSize == m_cacheAllocated)
102 {
103 m_cacheAllocated += 16;
104 m_cache = (TC_ID_MAP_ENTRY *)realloc(m_cache, sizeof(TC_ID_MAP_ENTRY) * m_cacheAllocated);
105 }
106 memcpy(&m_cache[m_cacheSize++], entry, sizeof(TC_ID_MAP_ENTRY));
107 qsort(m_cache, m_cacheSize, sizeof(TC_ID_MAP_ENTRY), CompareCacheElements2);
108
109 DbgPrintf(6, _T("DCTable::columnIdFromName(): column name %s added to cache, ID=%d"), name, (int)entry->id);
110 }
111 DBFreeStatement(hStmt);
112 }
113
114 DBConnectionPoolReleaseConnection(hdb);
115 }
116
117 MutexUnlock(m_cacheMutex);
118 return (entry != NULL) ? entry->id : 0;
119}
120
480e036b
VK
121/**
122 * Default constructor
123 */
16d6f798
VK
124DCTable::DCTable() : DCObject()
125{
df94e0ce 126 m_columns = new ObjectArray<DCTableColumn>(8, 8, true);
9098ad59 127 m_thresholds = new ObjectArray<DCTableThreshold>(0, 4, true);
b9a8e081 128 m_lastValue = NULL;
16d6f798
VK
129}
130
480e036b
VK
131/**
132 * Copy constructor
133 */
16d6f798
VK
134DCTable::DCTable(const DCTable *src) : DCObject(src)
135{
df94e0ce
VK
136 m_columns = new ObjectArray<DCTableColumn>(src->m_columns->size(), 8, true);
137 for(int i = 0; i < src->m_columns->size(); i++)
138 m_columns->add(new DCTableColumn(src->m_columns->get(i)));
9098ad59
VK
139 m_thresholds = new ObjectArray<DCTableThreshold>(src->m_thresholds->size(), 4, true);
140 for(int i = 0; i < src->m_thresholds->size(); i++)
141 m_thresholds->add(new DCTableThreshold(src->m_thresholds->get(i)));
b9a8e081 142 m_lastValue = NULL;
16d6f798
VK
143}
144
480e036b
VK
145/**
146 * Constructor for creating new DCTable from scratch
147 */
967893bb 148DCTable::DCTable(UINT32 id, const TCHAR *name, int source, int pollingInterval, int retentionTime,
22aaa779 149 Template *node, const TCHAR *description, const TCHAR *systemTag)
ba89fed2
VK
150 : DCObject(id, name, source, pollingInterval, retentionTime, node, description, systemTag)
151{
ba89fed2 152 m_columns = new ObjectArray<DCTableColumn>(8, 8, true);
9098ad59 153 m_thresholds = new ObjectArray<DCTableThreshold>(0, 4, true);
b9a8e081 154 m_lastValue = NULL;
ba89fed2
VK
155}
156
480e036b
VK
157/**
158 * Constructor for creating DCTable from database
159 * Assumes that fields in SELECT query are in following order:
22aaa779 160 * item_id,template_id,template_item_id,name,
480e036b 161 * description,flags,source,snmp_port,polling_interval,retention_time,
55bdca5a 162 * status,system_tag,resource_id,proxy_node,perftab_settings,
27c21485 163 * transformation_script,comments,guid,visibility_rights
480e036b 164 */
9bd1bace 165DCTable::DCTable(DB_HANDLE hdb, DB_RESULT hResult, int iRow, Template *pNode) : DCObject()
ba89fed2 166{
c42b4551 167 m_id = DBGetFieldULong(hResult, iRow, 0);
ba89fed2
VK
168 m_dwTemplateId = DBGetFieldULong(hResult, iRow, 1);
169 m_dwTemplateItemId = DBGetFieldULong(hResult, iRow, 2);
c42b4551 170 DBGetField(hResult, iRow, 3, m_name, MAX_ITEM_NAME);
4804be4e 171 DBGetField(hResult, iRow, 4, m_description, MAX_DB_STRING);
22aaa779
VK
172 m_flags = (WORD)DBGetFieldLong(hResult, iRow, 5);
173 m_source = (BYTE)DBGetFieldLong(hResult, iRow, 6);
174 m_snmpPort = (WORD)DBGetFieldLong(hResult, iRow, 7);
175 m_iPollingInterval = DBGetFieldLong(hResult, iRow, 8);
176 m_iRetentionTime = DBGetFieldLong(hResult, iRow, 9);
177 m_status = (BYTE)DBGetFieldLong(hResult, iRow, 10);
178 DBGetField(hResult, iRow, 11, m_systemTag, MAX_DB_STRING);
179 m_dwResourceId = DBGetFieldULong(hResult, iRow, 12);
191e4784 180 m_sourceNode = DBGetFieldULong(hResult, iRow, 13);
22aaa779
VK
181 m_pszPerfTabSettings = DBGetField(hResult, iRow, 14, NULL, 0);
182 TCHAR *pszTmp = DBGetField(hResult, iRow, 15, NULL, 0);
4016c0df 183 m_comments = DBGetField(hResult, iRow, 16, NULL, 0);
98ef8e4a 184 m_guid = DBGetFieldGUID(hResult, iRow, 17);
55bdca5a
VK
185 setTransformationScript(pszTmp);
186 free(pszTmp);
ba89fed2 187
4804be4e 188 m_owner = pNode;
b4369830 189 m_columns = new ObjectArray<DCTableColumn>(8, 8, true);
b9a8e081 190 m_lastValue = NULL;
b4369830 191
9bd1bace 192 DB_STATEMENT hStmt = DBPrepare(hdb, _T("SELECT column_name,flags,snmp_oid,display_name FROM dc_table_columns WHERE table_id=? ORDER BY sequence_number"));
b4369830
VK
193 if (hStmt != NULL)
194 {
c42b4551 195 DBBind(hStmt, 1, DB_SQLTYPE_INTEGER, m_id);
b4369830
VK
196 DB_RESULT hColumnList = DBSelectPrepared(hStmt);
197 if (hColumnList != NULL)
198 {
199 int count = DBGetNumRows(hColumnList);
200 for(int i = 0; i < count; i++)
201 m_columns->add(new DCTableColumn(hColumnList, i));
202 DBFreeResult(hColumnList);
203 }
204 DBFreeStatement(hStmt);
205 }
ba89fed2 206
9bd1bace 207 loadCustomSchedules(hdb);
c16e83db
VK
208
209 m_thresholds = new ObjectArray<DCTableThreshold>(0, 4, true);
9bd1bace 210 loadThresholds(hdb);
e9c75749
EJ
211
212 m_instanceDiscoveryMethod = (WORD)DBGetFieldLong(hResult, iRow, 18);
213 m_instanceDiscoveryData = DBGetField(hResult, iRow, 19, NULL, 0);
214 m_instanceFilterSource = NULL;
215 m_instanceFilter = NULL;
216 pszTmp = DBGetField(hResult, iRow, 20, NULL, 0);
217 setInstanceFilter(pszTmp);
218 free(pszTmp);
219 DBGetField(hResult, iRow, 21, m_instance, MAX_DB_STRING);
27c21485 220 //set visibility rights
221 pszTmp = DBGetField(hResult, iRow, 21, NULL, 0);
222 StringList list;
223 list.splitAndAdd(pszTmp, _T(","));
224 for(int i = 0; i < list.size(); i++)
225 {
226 if(*(list.get(i)) != 0)
74f70b59 227 m_visibilityRights->add(_tcstol(list.get(i), NULL, 0));
27c21485 228 }
229 free(pszTmp);
ba89fed2
VK
230}
231
480e036b 232/**
9387bc59
VK
233 * Create DCTable from import file
234 */
235DCTable::DCTable(ConfigEntry *config, Template *owner) : DCObject(config, owner)
236{
237 ConfigEntry *columnsRoot = config->findEntry(_T("columns"));
238 if (columnsRoot != NULL)
239 {
8b7ae7eb
VK
240 ObjectArray<ConfigEntry> *columns = columnsRoot->getSubEntries(_T("column#*"));
241 m_columns = new ObjectArray<DCTableColumn>(columns->size(), 8, true);
242 for(int i = 0; i < columns->size(); i++)
9387bc59 243 {
8b7ae7eb 244 m_columns->add(new DCTableColumn(columns->get(i)));
9387bc59
VK
245 }
246 delete columns;
247 }
248 else
249 {
250 m_columns = new ObjectArray<DCTableColumn>(8, 8, true);
251 }
252
253 ConfigEntry *thresholdsRoot = config->findEntry(_T("thresholds"));
254 if (thresholdsRoot != NULL)
255 {
8b7ae7eb
VK
256 ObjectArray<ConfigEntry> *thresholds = thresholdsRoot->getSubEntries(_T("threshold#*"));
257 m_thresholds = new ObjectArray<DCTableThreshold>(thresholds->size(), 8, true);
258 for(int i = 0; i < thresholds->size(); i++)
9387bc59 259 {
8b7ae7eb 260 m_thresholds->add(new DCTableThreshold(thresholds->get(i)));
9387bc59
VK
261 }
262 delete thresholds;
263 }
264 else
265 {
266 m_thresholds = new ObjectArray<DCTableThreshold>(0, 4, true);
267 }
268
269 m_lastValue = NULL;
270}
271
272/**
480e036b
VK
273 * Destructor
274 */
16d6f798
VK
275DCTable::~DCTable()
276{
df94e0ce 277 delete m_columns;
9098ad59 278 delete m_thresholds;
a0ddfb29
VK
279 if (m_lastValue != NULL)
280 m_lastValue->decRefCount();
16d6f798 281}
533ce8c0 282
480e036b 283/**
480e036b
VK
284 * Delete all collected data
285 */
ba89fed2
VK
286bool DCTable::deleteAllData()
287{
288 TCHAR szQuery[256];
289 bool success;
290
291 lock();
035745fc 292 DB_HANDLE hdb = DBConnectionPoolAcquireConnection();
4804be4e 293 _sntprintf(szQuery, 256, _T("DELETE FROM tdata_%d WHERE item_id=%d"), m_owner->getId(), (int)m_id);
035745fc
VK
294 success = DBQuery(hdb, szQuery) ? true : false;
295 DBConnectionPoolReleaseConnection(hdb);
ba89fed2
VK
296 unlock();
297 return success;
298}
299
480e036b 300/**
0156d6b2
VK
301 * Process new collected value. Should return true on success.
302 * If returns false, current poll result will be converted into data collection error.
303 *
304 * @return true on success
480e036b 305 */
9664e8df 306bool DCTable::processNewValue(time_t timestamp, const void *value, bool *updateStatus)
533ce8c0 307{
cd68963b 308 *updateStatus = false;
ba89fed2
VK
309 lock();
310
4804be4e
VK
311 // Normally m_owner shouldn't be NULL for polled items, but who knows...
312 if (m_owner == NULL)
ba89fed2
VK
313 {
314 unlock();
8b2df485 315 ((Table *)value)->decRefCount();
0156d6b2 316 return false;
ba89fed2
VK
317 }
318
7de1151b 319 // Transform input value
f877ac05
VK
320 // Cluster can have only aggregated data, and transformation
321 // should not be used on aggregation
4804be4e 322 if ((m_owner->getObjectClass() != OBJECT_CLUSTER) || (m_flags & DCF_TRANSFORM_AGGREGATED))
0156d6b2
VK
323 {
324 if (!transform((Table *)value))
325 {
326 unlock();
1693f955 327 ((Table *)value)->decRefCount();
0156d6b2
VK
328 return false;
329 }
330 }
7de1151b 331
ba89fed2 332 m_dwErrorCount = 0;
a0ddfb29
VK
333 if (m_lastValue != NULL)
334 m_lastValue->decRefCount();
b9a8e081 335 m_lastValue = (Table *)value;
4804be4e 336 m_lastValue->setTitle(m_description);
5891329f 337 m_lastValue->setSource(m_source);
ba89fed2
VK
338
339 // Copy required fields into local variables
c42b4551 340 UINT32 tableId = m_id;
4804be4e 341 UINT32 nodeId = m_owner->getId();
a58454c9 342 bool save = (m_flags & DCF_NO_STORAGE) == 0;
ba89fed2 343
57c9050f
VK
344 ((Table *)value)->incRefCount();
345
ba89fed2
VK
346 unlock();
347
348 // Save data to database
349 // Object is unlocked, so only local variables can be used
a58454c9 350 if (save)
22aaa779 351 {
a58454c9
VK
352 DB_HANDLE hdb = DBConnectionPoolAcquireConnection();
353 if (!DBBegin(hdb))
354 {
355 DBConnectionPoolReleaseConnection(hdb);
0156d6b2 356 return true;
a58454c9 357 }
22aaa779 358
5d53c0e4 359 bool success = false;
a58454c9 360 Table *data = (Table *)value;
ba89fed2 361
a58454c9 362 TCHAR query[256];
89e5f052 363 _sntprintf(query, 256, _T("INSERT INTO tdata_%d (item_id,tdata_timestamp,tdata_value) VALUES (?,?,?)"), (int)nodeId);
22aaa779
VK
364 DB_STATEMENT hStmt = DBPrepare(hdb, query);
365 if (hStmt != NULL)
366 {
a58454c9 367 DBBind(hStmt, 1, DB_SQLTYPE_INTEGER, tableId);
9664e8df 368 DBBind(hStmt, 2, DB_SQLTYPE_INTEGER, (INT32)timestamp);
89e5f052 369 DBBind(hStmt, 3, DB_SQLTYPE_TEXT, DB_CTYPE_UTF8_STRING, data->createPackedXML(), DB_BIND_DYNAMIC);
a58454c9
VK
370 success = DBExecute(hStmt);
371 DBFreeStatement(hStmt);
22aaa779 372 }
22aaa779 373
a58454c9 374 if (success)
a58454c9
VK
375 DBCommit(hdb);
376 else
377 DBRollback(hdb);
50633e41 378
a58454c9
VK
379 DBConnectionPoolReleaseConnection(hdb);
380 }
f6456d80 381 if ((g_offlineDataRelevanceTime <= 0) || (timestamp > (time(NULL) - g_offlineDataRelevanceTime)))
7f418694 382 checkThresholds((Table *)value);
ea50bc33
VK
383
384 if (g_flags & AF_PERFDATA_STORAGE_DRIVER_LOADED)
9664e8df 385 PerfDataStorageRequest(this, timestamp, (Table *)value);
ea50bc33 386
57c9050f 387 ((Table *)value)->decRefCount();
0156d6b2 388 return true;
533ce8c0
VK
389}
390
480e036b 391/**
7de1151b
VK
392 * Transform received value
393 */
0156d6b2 394bool DCTable::transform(Table *value)
7de1151b 395{
c2b7c9ae 396 if (m_transformationScript == NULL)
0156d6b2 397 return true;
c2b7c9ae 398
4804be4e
VK
399 bool success = false;
400 NXSL_VM *vm = new NXSL_VM(new NXSL_ServerEnv());
401 if (vm->load(m_transformationScript))
7de1151b 402 {
4804be4e
VK
403 NXSL_Value *nxslValue = new NXSL_Value(new NXSL_Object(&g_nxslStaticTableClass, value));
404 vm->setGlobalVariable(_T("$object"), m_owner->createNXSLObject());
405 if (m_owner->getObjectClass() == OBJECT_NODE)
b32b325d 406 {
4804be4e 407 vm->setGlobalVariable(_T("$node"), m_owner->createNXSLObject());
b32b325d 408 }
4804be4e
VK
409 vm->setGlobalVariable(_T("$dci"), createNXSLObject());
410 vm->setGlobalVariable(_T("$isCluster"), new NXSL_Value((m_owner->getObjectClass() == OBJECT_CLUSTER) ? 1 : 0));
7de1151b 411
4804be4e
VK
412 // remove lock from DCI for script execution to avoid deadlocks
413 unlock();
414 success = vm->run(1, &nxslValue);
415 lock();
416 if (!success)
417 {
418 if (vm->getErrorCode() == NXSL_ERR_EXECUTION_ABORTED)
419 {
420 DbgPrintf(6, _T("Transformation script for DCI \"%s\" [%d] on node %s [%d] aborted"),
421 m_description, m_id, getOwnerName(), getOwnerId());
422 }
423 else
424 {
425 TCHAR buffer[1024];
426 _sntprintf(buffer, 1024, _T("DCI::%s::%d::TransformationScript"), getOwnerName(), m_id);
427 PostDciEvent(EVENT_SCRIPT_ERROR, g_dwMgmtNode, m_id, "ssd", buffer, vm->getErrorText(), m_id);
428 nxlog_write(MSG_TRANSFORMATION_SCRIPT_EXECUTION_ERROR, NXLOG_WARNING, "dsdss",
429 getOwnerId(), getOwnerName(), m_id, m_name, vm->getErrorText());
430 }
b32b325d 431 }
7de1151b 432 }
4804be4e
VK
433 else
434 {
435 TCHAR buffer[1024];
436 _sntprintf(buffer, 1024, _T("DCI::%s::%d::TransformationScript"), getOwnerName(), m_id);
437 PostDciEvent(EVENT_SCRIPT_ERROR, g_dwMgmtNode, m_id, "ssd", buffer, vm->getErrorText(), m_id);
438 nxlog_write(MSG_TRANSFORMATION_SCRIPT_EXECUTION_ERROR, NXLOG_WARNING, "dsdss",
439 getOwnerId(), getOwnerName(), m_id, m_name, vm->getErrorText());
440 }
441 delete vm;
0156d6b2 442 return success;
7de1151b
VK
443}
444
445/**
50633e41
VK
446 * Check thresholds
447 */
448void DCTable::checkThresholds(Table *value)
449{
a0dc14f9
VK
450 static const TCHAR *paramNames[] = { _T("dciName"), _T("dciDescription"), _T("dciId"), _T("row"), _T("instance") };
451
50633e41 452 lock();
a0dc14f9 453 for(int row = 0; row < value->getNumRows(); row++)
50633e41 454 {
a0dc14f9
VK
455 TCHAR instance[MAX_RESULT_LENGTH];
456 value->buildInstanceString(row, instance, MAX_RESULT_LENGTH);
457 for(int i = 0; i < m_thresholds->size(); i++)
458 {
459 DCTableThreshold *t = m_thresholds->get(i);
460 ThresholdCheckResult result = t->check(value, row, instance);
461 switch(result)
462 {
463 case ACTIVATED:
4804be4e 464 PostDciEventWithNames(t->getActivationEvent(), m_owner->getId(), m_id, "ssids", paramNames, m_name, m_description, m_id, row, instance);
a0dc14f9
VK
465 if (!(m_flags & DCF_ALL_THRESHOLDS))
466 i = m_thresholds->size(); // Stop processing (for current row)
467 break;
468 case DEACTIVATED:
4804be4e 469 PostDciEventWithNames(t->getDeactivationEvent(), m_owner->getId(), m_id, "ssids", paramNames, m_name, m_description, m_id, row, instance);
a0dc14f9
VK
470 break;
471 case ALREADY_ACTIVE:
472 i = m_thresholds->size(); // Threshold condition still true, stop processing
473 break;
474 default:
475 break;
476 }
477 }
50633e41
VK
478 }
479 unlock();
480}
481
482/**
480e036b
VK
483 * Process new data collection error
484 */
df94243f 485void DCTable::processNewError(bool noInstance, time_t now)
533ce8c0 486{
c5c77583 487 m_dwErrorCount++;
533ce8c0 488}
ba89fed2 489
480e036b
VK
490/**
491 * Save to database
492 */
e7450f3b 493bool DCTable::saveToDatabase(DB_HANDLE hdb)
ba89fed2
VK
494{
495 DB_STATEMENT hStmt;
c42b4551 496 if (IsDatabaseRecordExist(hdb, _T("dc_tables"), _T("item_id"), m_id))
ba89fed2
VK
497 {
498 hStmt = DBPrepare(hdb, _T("UPDATE dc_tables SET node_id=?,template_id=?,template_item_id=?,name=?,")
22aaa779 499 _T("description=?,flags=?,source=?,snmp_port=?,polling_interval=?,")
ba89fed2 500 _T("retention_time=?,status=?,system_tag=?,resource_id=?,proxy_node=?,")
e9c75749 501 _T("perftab_settings=?,transformation_script=?,comments=?,guid=?,")
27c21485 502 _T("instd_method=?,instd_data=?,instd_filter=?,instance=?,visibility_rights=? WHERE item_id=?"));
ba89fed2
VK
503 }
504 else
505 {
506 hStmt = DBPrepare(hdb, _T("INSERT INTO dc_tables (node_id,template_id,template_item_id,name,")
22aaa779 507 _T("description,flags,source,snmp_port,polling_interval,")
ba89fed2 508 _T("retention_time,status,system_tag,resource_id,proxy_node,perftab_settings,")
e9c75749 509 _T("transformation_script,comments,guid, ")
27c21485 510 _T("instd_method,instd_data,instd_filter,instance,visibility_rights,item_id) ")
511 _T("VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)"));
ba89fed2
VK
512 }
513 if (hStmt == NULL)
514 return FALSE;
515
516 lock();
517
4804be4e 518 DBBind(hStmt, 1, DB_SQLTYPE_INTEGER, (m_owner == NULL) ? (UINT32)0 : m_owner->getId());
ba89fed2
VK
519 DBBind(hStmt, 2, DB_SQLTYPE_INTEGER, m_dwTemplateId);
520 DBBind(hStmt, 3, DB_SQLTYPE_INTEGER, m_dwTemplateItemId);
c42b4551 521 DBBind(hStmt, 4, DB_SQLTYPE_VARCHAR, m_name, DB_BIND_STATIC);
4804be4e 522 DBBind(hStmt, 5, DB_SQLTYPE_VARCHAR, m_description, DB_BIND_STATIC);
22aaa779
VK
523 DBBind(hStmt, 6, DB_SQLTYPE_INTEGER, (UINT32)m_flags);
524 DBBind(hStmt, 7, DB_SQLTYPE_INTEGER, (INT32)m_source);
525 DBBind(hStmt, 8, DB_SQLTYPE_INTEGER, (UINT32)m_snmpPort);
526 DBBind(hStmt, 9, DB_SQLTYPE_INTEGER, (INT32)m_iPollingInterval);
527 DBBind(hStmt, 10, DB_SQLTYPE_INTEGER, (INT32)m_iRetentionTime);
528 DBBind(hStmt, 11, DB_SQLTYPE_INTEGER, (INT32)m_status);
529 DBBind(hStmt, 12, DB_SQLTYPE_VARCHAR, m_systemTag, DB_BIND_STATIC);
530 DBBind(hStmt, 13, DB_SQLTYPE_INTEGER, m_dwResourceId);
191e4784 531 DBBind(hStmt, 14, DB_SQLTYPE_INTEGER, m_sourceNode);
22aaa779
VK
532 DBBind(hStmt, 15, DB_SQLTYPE_TEXT, m_pszPerfTabSettings, DB_BIND_STATIC);
533 DBBind(hStmt, 16, DB_SQLTYPE_TEXT, m_transformationScriptSource, DB_BIND_STATIC);
4016c0df 534 DBBind(hStmt, 17, DB_SQLTYPE_TEXT, m_comments, DB_BIND_STATIC);
98ef8e4a 535 DBBind(hStmt, 18, DB_SQLTYPE_VARCHAR, m_guid);
e9c75749
EJ
536 DBBind(hStmt, 19, DB_SQLTYPE_INTEGER, (INT32)m_instanceDiscoveryMethod);
537 DBBind(hStmt, 20, DB_SQLTYPE_VARCHAR, m_instanceDiscoveryData, DB_BIND_STATIC);
538 DBBind(hStmt, 21, DB_SQLTYPE_TEXT, m_instanceFilterSource, DB_BIND_STATIC);
539 DBBind(hStmt, 22, DB_SQLTYPE_VARCHAR, m_instance, DB_BIND_STATIC);
27c21485 540 String tmp;
541 int size = m_visibilityRights->size();
542 for(int i = 0; i < size; i++)
543 {
544 tmp.append(m_visibilityRights->get(i));
545 if(i != (size - 1))
546 tmp.append(_T(','));
547 }
548 DBBind(hStmt, 23, DB_SQLTYPE_VARCHAR, tmp, DB_BIND_STATIC);
549 DBBind(hStmt, 24, DB_SQLTYPE_INTEGER, m_id);
ba89fed2 550
e7450f3b 551 bool result = DBExecute(hStmt);
ba89fed2
VK
552 DBFreeStatement(hStmt);
553
554 if (result)
555 {
556 // Save column configuration
557 hStmt = DBPrepare(hdb, _T("DELETE FROM dc_table_columns WHERE table_id=?"));
558 if (hStmt != NULL)
559 {
c42b4551 560 DBBind(hStmt, 1, DB_SQLTYPE_INTEGER, m_id);
ba89fed2
VK
561 result = DBExecute(hStmt);
562 DBFreeStatement(hStmt);
563 }
564 else
565 {
e7450f3b 566 result = false;
ba89fed2
VK
567 }
568
569 if (result && (m_columns->size() > 0))
570 {
9387bc59 571 hStmt = DBPrepare(hdb, _T("INSERT INTO dc_table_columns (table_id,sequence_number,column_name,snmp_oid,flags,display_name) VALUES (?,?,?,?,?,?)"));
ba89fed2
VK
572 if (hStmt != NULL)
573 {
c42b4551 574 DBBind(hStmt, 1, DB_SQLTYPE_INTEGER, m_id);
ba89fed2
VK
575 for(int i = 0; i < m_columns->size(); i++)
576 {
577 DCTableColumn *column = m_columns->get(i);
9387bc59
VK
578 DBBind(hStmt, 2, DB_SQLTYPE_INTEGER, (INT32)(i + 1));
579 DBBind(hStmt, 3, DB_SQLTYPE_VARCHAR, column->getName(), DB_BIND_STATIC);
ba89fed2 580 SNMP_ObjectId *oid = column->getSnmpOid();
9ceab287 581 DBBind(hStmt, 4, DB_SQLTYPE_VARCHAR, (oid != NULL) ? (const TCHAR *)oid->toString() : NULL, DB_BIND_TRANSIENT);
9387bc59
VK
582 DBBind(hStmt, 5, DB_SQLTYPE_INTEGER, (INT32)column->getFlags());
583 DBBind(hStmt, 6, DB_SQLTYPE_VARCHAR, column->getDisplayName(), DB_BIND_STATIC);
ba89fed2
VK
584
585 result = DBExecute(hStmt);
586 if (!result)
587 break;
588 }
589 DBFreeStatement(hStmt);
590 }
591 else
592 {
e7450f3b 593 result = false;
ba89fed2
VK
594 }
595 }
596 }
597
9098ad59
VK
598 saveThresholds(hdb);
599
ba89fed2 600 unlock();
e7450f3b 601 return result ? DCObject::saveToDatabase(hdb) : false;
ba89fed2
VK
602}
603
480e036b 604/**
9098ad59
VK
605 * Load thresholds from database
606 */
9bd1bace 607bool DCTable::loadThresholds(DB_HANDLE hdb)
9098ad59 608{
4ca9d9c0 609 DB_STATEMENT hStmt = DBPrepare(hdb, _T("SELECT id,activation_event,deactivation_event,sample_count FROM dct_thresholds WHERE table_id=? ORDER BY sequence_number"));
9098ad59
VK
610 if (hStmt == NULL)
611 return false;
612
c42b4551 613 DBBind(hStmt, 1, DB_SQLTYPE_INTEGER, m_id);
9098ad59
VK
614 DB_RESULT hResult = DBSelectPrepared(hStmt);
615 if (hResult != NULL)
616 {
617 int count = DBGetNumRows(hResult);
618 for(int i = 0; i < count; i++)
619 {
9bd1bace 620 DCTableThreshold *t = new DCTableThreshold(hdb, hResult, i);
9098ad59
VK
621 m_thresholds->add(t);
622 }
623 DBFreeResult(hResult);
624 }
625 DBFreeStatement(hStmt);
626 return true;
627}
628
629/**
630 * Save thresholds to database
631 */
632bool DCTable::saveThresholds(DB_HANDLE hdb)
633{
634 DB_STATEMENT hStmt = DBPrepare(hdb, _T("DELETE FROM dct_threshold_conditions WHERE threshold_id=?"));
635 if (hStmt == NULL)
636 return false;
637
638 for(int i = 0; i < m_thresholds->size(); i++)
639 {
640 DBBind(hStmt, 1, DB_SQLTYPE_INTEGER, m_thresholds->get(i)->getId());
641 DBExecute(hStmt);
642 }
643 DBFreeStatement(hStmt);
644
4ca9d9c0
VK
645 hStmt = DBPrepare(hdb, _T("DELETE FROM dct_threshold_instances WHERE threshold_id=?"));
646 if (hStmt == NULL)
647 return false;
648
649 for(int i = 0; i < m_thresholds->size(); i++)
650 {
651 DBBind(hStmt, 1, DB_SQLTYPE_INTEGER, m_thresholds->get(i)->getId());
652 DBExecute(hStmt);
653 }
654 DBFreeStatement(hStmt);
655
9098ad59
VK
656 hStmt = DBPrepare(hdb, _T("DELETE FROM dct_thresholds WHERE table_id=?"));
657 if (hStmt == NULL)
658 return false;
c42b4551 659 DBBind(hStmt, 1, DB_SQLTYPE_INTEGER, m_id);
9098ad59
VK
660 DBExecute(hStmt);
661 DBFreeStatement(hStmt);
662
663 for(int i = 0; i < m_thresholds->size(); i++)
c42b4551 664 m_thresholds->get(i)->saveToDatabase(hdb, m_id, i);
9098ad59
VK
665 return true;
666}
667
668/**
480e036b
VK
669 * Delete table object and collected data from database
670 */
c42b4551 671void DCTable::deleteFromDatabase()
ba89fed2 672{
c42b4551 673 DCObject::deleteFromDatabase();
ba89fed2 674
b41a29fd 675 TCHAR szQuery[256];
c42b4551 676 _sntprintf(szQuery, sizeof(szQuery) / sizeof(TCHAR), _T("DELETE FROM dc_tables WHERE item_id=%d"), (int)m_id);
ba89fed2 677 QueueSQLRequest(szQuery);
c42b4551 678 _sntprintf(szQuery, sizeof(szQuery) / sizeof(TCHAR), _T("DELETE FROM dc_table_columns WHERE table_id=%d"), (int)m_id);
ba89fed2 679 QueueSQLRequest(szQuery);
9098ad59
VK
680
681 for(int i = 0; i < m_thresholds->size(); i++)
682 {
683 _sntprintf(szQuery, 256, _T("DELETE FROM dct_threshold_conditions WHERE threshold_id=%d"), (int)m_thresholds->get(i)->getId());
684 QueueSQLRequest(szQuery);
685 }
686
c42b4551 687 _sntprintf(szQuery, sizeof(szQuery) / sizeof(TCHAR), _T("DELETE FROM dct_thresholds WHERE table_id=%d"), (int)m_id);
9098ad59 688 QueueSQLRequest(szQuery);
b41a29fd
VK
689
690 if (m_owner->isDataCollectionTarget())
691 static_cast<DataCollectionTarget*>(m_owner)->scheduleItemDataCleanup(m_id);
ba89fed2 692}
b4369830 693
480e036b
VK
694/**
695 * Create NXCP message with item data
696 */
b368969c 697void DCTable::createMessage(NXCPMessage *pMsg)
b4369830
VK
698{
699 DCObject::createMessage(pMsg);
700
701 lock();
b368969c 702 pMsg->setField(VID_NUM_COLUMNS, (UINT32)m_columns->size());
967893bb 703 UINT32 varId = VID_DCI_COLUMN_BASE;
b4369830
VK
704 for(int i = 0; i < m_columns->size(); i++)
705 {
706 DCTableColumn *column = m_columns->get(i);
b368969c
VK
707 pMsg->setField(varId++, column->getName());
708 pMsg->setField(varId++, column->getFlags());
b4369830
VK
709 SNMP_ObjectId *oid = column->getSnmpOid();
710 if (oid != NULL)
9ceab287 711 pMsg->setFieldFromInt32Array(varId++, (UINT32)oid->length(), oid->value());
b4369830
VK
712 else
713 varId++;
b368969c 714 pMsg->setField(varId++, column->getDisplayName());
0b77b73e 715 varId += 6;
b4369830 716 }
9098ad59 717
b368969c 718 pMsg->setField(VID_NUM_THRESHOLDS, (UINT32)m_thresholds->size());
9098ad59
VK
719 varId = VID_DCI_THRESHOLD_BASE;
720 for(int i = 0; i < m_thresholds->size(); i++)
721 {
722 varId = m_thresholds->get(i)->fillMessage(pMsg, varId);
723 }
724
b4369830
VK
725 unlock();
726}
727
480e036b
VK
728/**
729 * Update data collection object from NXCP message
730 */
b368969c 731void DCTable::updateFromMessage(NXCPMessage *pMsg)
b4369830
VK
732{
733 DCObject::updateFromMessage(pMsg);
734
735 lock();
736
b4369830 737 m_columns->clear();
b368969c 738 int count = (int)pMsg->getFieldAsUInt32(VID_NUM_COLUMNS);
967893bb 739 UINT32 varId = VID_DCI_COLUMN_BASE;
b4369830
VK
740 for(int i = 0; i < count; i++)
741 {
742 m_columns->add(new DCTableColumn(pMsg, varId));
743 varId += 10;
744 }
745
b368969c 746 count = (int)pMsg->getFieldAsUInt32(VID_NUM_THRESHOLDS);
fa493140 747 ObjectArray<DCTableThreshold> *newThresholds = new ObjectArray<DCTableThreshold>(count, 8, true);
9098ad59
VK
748 varId = VID_DCI_THRESHOLD_BASE;
749 for(int i = 0; i < count; i++)
750 {
fa493140
VK
751 DCTableThreshold *t = new DCTableThreshold(pMsg, &varId);
752 newThresholds->add(t);
753 for(int j = 0; j < m_thresholds->size(); j++)
754 {
755 DCTableThreshold *old = m_thresholds->get(j);
756 if (old->getId() == t->getId())
757 {
758 t->copyState(old);
759 break;
760 }
761 }
9098ad59 762 }
fa493140
VK
763 delete m_thresholds;
764 m_thresholds = newThresholds;
9098ad59 765
b4369830
VK
766 unlock();
767}
b9a8e081 768
480e036b
VK
769/**
770 * Get last collected value
771 */
b368969c 772void DCTable::fillLastValueMessage(NXCPMessage *msg)
b9a8e081 773{
a567a02a 774 lock();
b9a8e081
VK
775 if (m_lastValue != NULL)
776 {
777 m_lastValue->fillMessage(*msg, 0, -1);
b9a8e081 778 }
a567a02a 779 unlock();
b9a8e081 780}
92c51b1d 781
480e036b
VK
782/**
783 * Get summary of last collected value (to show along simple DCI values)
784 */
b368969c 785void DCTable::fillLastValueSummaryMessage(NXCPMessage *pMsg, UINT32 dwId)
92c51b1d
VK
786{
787 lock();
b368969c
VK
788 pMsg->setField(dwId++, m_id);
789 pMsg->setField(dwId++, m_name);
4804be4e 790 pMsg->setField(dwId++, m_description);
b368969c
VK
791 pMsg->setField(dwId++, (WORD)m_source);
792 pMsg->setField(dwId++, (WORD)DCI_DT_NULL); // compatibility: data type
793 pMsg->setField(dwId++, _T("")); // compatibility: value
794 pMsg->setField(dwId++, (UINT32)m_tLastPoll);
795 pMsg->setField(dwId++, (WORD)(matchClusterResource() ? m_status : ITEM_STATUS_DISABLED)); // show resource-bound DCIs as inactive if cluster resource is not on this node
796 pMsg->setField(dwId++, (WORD)getType());
797 pMsg->setField(dwId++, m_dwErrorCount);
798 pMsg->setField(dwId++, m_dwTemplateItemId);
799 pMsg->setField(dwId++, (WORD)0); // compatibility: number of thresholds
92c51b1d
VK
800
801 unlock();
802}
803
480e036b 804/**
a567a02a
VK
805 * Get data type of given column
806 */
807int DCTable::getColumnDataType(const TCHAR *name)
808{
809 int dt = DCI_DT_STRING;
810 bool found = false;
4016c0df 811
a567a02a
VK
812 lock();
813
814 // look in column definition first
815 for(int i = 0; i < m_columns->size(); i++)
816 {
817 DCTableColumn *column = m_columns->get(i);
818 if (!_tcsicmp(column->getName(), name))
819 {
820 dt = column->getDataType();
821 break;
822 }
823 }
824
825 // use last values if not found in definitions
826 if (!found && (m_lastValue != NULL))
827 {
828 int index = m_lastValue->getColumnIndex(name);
829 if (index != -1)
967893bb 830 dt = m_lastValue->getColumnDataType(index);
a567a02a
VK
831 }
832
833 unlock();
834 return dt;
835}
a0ddfb29
VK
836
837/**
838 * Get last collected value
839 */
840Table *DCTable::getLastValue()
841{
842 lock();
843 Table *value;
844 if (m_lastValue != NULL)
845 {
846 value = m_lastValue;
847 value->incRefCount();
848 }
849 else
850 {
851 value = NULL;
852 }
853 unlock();
854 return value;
855}
856
857/**
858 * Update destination value from source value
859 */
860#define RECALCULATE_VALUE(dst, src, func, count) \
861 { \
862 switch(func) \
863 { \
864 case DCF_FUNCTION_MIN: \
865 if (src < dst) dst = src; \
866 break; \
867 case DCF_FUNCTION_MAX: \
868 if (src > dst) dst = src; \
869 break; \
870 case DCF_FUNCTION_SUM: \
871 dst += src; \
872 break; \
873 case DCF_FUNCTION_AVG: \
874 dst = (dst * count + src) / (count + 1); \
875 break; \
876 } \
877 }
878
879/**
880 * Merge values
881 */
882void DCTable::mergeValues(Table *dest, Table *src, int count)
883{
884 for(int sRow = 0; sRow < src->getNumRows(); sRow++)
885 {
886 TCHAR instance[MAX_RESULT_LENGTH];
887
888 src->buildInstanceString(sRow, instance, MAX_RESULT_LENGTH);
889 int dRow = dest->findRowByInstance(instance);
890 if (dRow >= 0)
891 {
892 for(int j = 0; j < m_columns->size(); j++)
893 {
894 DCTableColumn *cd = m_columns->get(j);
895 if ((cd == NULL) || cd->isInstanceColumn() || (cd->getDataType() == DCI_DT_STRING))
896 continue;
897 int column = dest->getColumnIndex(cd->getName());
898 if (column == -1)
899 continue;
900
901 if (cd->getDataType() == DCI_DT_FLOAT)
902 {
903 double sval = src->getAsDouble(sRow, column);
904 double dval = dest->getAsDouble(dRow, column);
905
906 RECALCULATE_VALUE(dval, sval, cd->getAggregationFunction(), count);
907
908 dest->setAt(dRow, column, dval);
909 }
ae0e5359 910 else if ((cd->getDataType() == DCI_DT_UINT) || (cd->getDataType() == DCI_DT_UINT64))
a0ddfb29
VK
911 {
912 UINT64 sval = src->getAsUInt64(sRow, column);
913 UINT64 dval = dest->getAsUInt64(dRow, column);
914
915 RECALCULATE_VALUE(dval, sval, cd->getAggregationFunction(), count);
916
917 dest->setAt(dRow, column, dval);
918 }
919 else
920 {
921 INT64 sval = src->getAsInt64(sRow, column);
922 INT64 dval = dest->getAsInt64(dRow, column);
923
924 RECALCULATE_VALUE(dval, sval, cd->getAggregationFunction(), count);
925
926 dest->setAt(dRow, column, dval);
927 }
928 }
929 }
930 else
931 {
932 // no such instance
933 dest->copyRow(src, sRow);
934 }
935 }
936}
937
938/**
939 * Update columns in resulting table according to definition
940 */
941void DCTable::updateResultColumns(Table *t)
942{
943 lock();
944 for(int i = 0; i < m_columns->size(); i++)
945 {
946 DCTableColumn *col = m_columns->get(i);
947 int index = t->getColumnIndex(col->getName());
948 if (index != -1)
949 {
950 TableColumnDefinition *cd = t->getColumnDefinitions()->get(index);
951 if (cd != NULL)
952 {
953 cd->setDataType(col->getDataType());
954 cd->setInstanceColumn(col->isInstanceColumn());
955 cd->setDisplayName(col->getDisplayName());
956 }
957 }
958 }
959 unlock();
960}
961
962/**
963 * Update from template item
964 */
965void DCTable::updateFromTemplate(DCObject *src)
966{
967 DCObject::updateFromTemplate(src);
968
969 if (src->getType() != DCO_TYPE_TABLE)
970 {
c42b4551 971 DbgPrintf(2, _T("INTERNAL ERROR: DCTable::updateFromTemplate(%d, %d): source type is %d"), (int)m_id, (int)src->getId(), src->getType());
a0ddfb29
VK
972 return;
973 }
974
975 lock();
976 DCTable *table = (DCTable *)src;
977
978 m_columns->clear();
979 for(int i = 0; i < table->m_columns->size(); i++)
980 m_columns->add(new DCTableColumn(table->m_columns->get(i)));
9098ad59
VK
981
982 m_thresholds->clear();
983 for(int i = 0; i < table->m_thresholds->size(); i++)
984 m_thresholds->add(new DCTableThreshold(table->m_thresholds->get(i)));
985
a0ddfb29
VK
986 unlock();
987}
6e102d6e
VK
988
989/**
990 * Create management pack record
991 */
98ef8e4a 992void DCTable::createExportRecord(String &str)
6e102d6e 993{
6e102d6e 994 lock();
4016c0df 995
4e0e77e6 996 str.appendFormattedString(_T("\t\t\t\t<dctable id=\"%d\">\n")
98ef8e4a 997 _T("\t\t\t\t\t<guid>%s</guid>\n")
6e102d6e
VK
998 _T("\t\t\t\t\t<name>%s</name>\n")
999 _T("\t\t\t\t\t<description>%s</description>\n")
1000 _T("\t\t\t\t\t<origin>%d</origin>\n")
1001 _T("\t\t\t\t\t<interval>%d</interval>\n")
1002 _T("\t\t\t\t\t<retention>%d</retention>\n")
1003 _T("\t\t\t\t\t<systemTag>%s</systemTag>\n")
50ea73e3 1004 _T("\t\t\t\t\t<flags>%d</flags>\n")
e9c75749
EJ
1005 _T("\t\t\t\t\t<snmpPort>%d</snmpPort>\n")
1006 _T("\t\t\t\t\t<instanceDiscoveryMethod>%d</instanceDiscoveryMethod>\n")
1007 _T("\t\t\t\t\t<instance>%s</instance>\n"),
98ef8e4a
VK
1008 (int)m_id, (const TCHAR *)m_guid.toString(),
1009 (const TCHAR *)EscapeStringForXML2(m_name),
4804be4e 1010 (const TCHAR *)EscapeStringForXML2(m_description),
6e102d6e
VK
1011 (int)m_source, m_iPollingInterval, m_iRetentionTime,
1012 (const TCHAR *)EscapeStringForXML2(m_systemTag),
d0500810
VK
1013 (int)m_flags, (int)m_snmpPort, (int)m_instanceDiscoveryMethod,
1014 (const TCHAR *)EscapeStringForXML2(m_instance));
6e102d6e
VK
1015
1016 if (m_transformationScriptSource != NULL)
1017 {
ef607e62 1018 str.append(_T("\t\t\t\t\t<transformation>"));
4e0e77e6 1019 str.appendPreallocated(EscapeStringForXML(m_transformationScriptSource, -1));
ef607e62 1020 str.append(_T("</transformation>\n"));
6e102d6e
VK
1021 }
1022
e7450f3b 1023 if ((m_schedules != NULL) && (m_schedules->size() > 0))
6e102d6e 1024 {
ef607e62
VK
1025 str.append(_T("\t\t\t\t\t<schedules>\n"));
1026 for(int i = 0; i < m_schedules->size(); i++)
1027 {
1028 str.append(_T("\t\t\t\t\t\t<schedule>"));
1029 str.append(EscapeStringForXML2(m_schedules->get(i)));
1030 str.append(_T("</schedule>\n"));
1031 }
1032 str.append(_T("\t\t\t\t\t</schedules>\n"));
6e102d6e
VK
1033 }
1034
1035 if (m_columns != NULL)
1036 {
1037 str += _T("\t\t\t\t\t<columns>\n");
ef607e62 1038 for(int i = 0; i < m_columns->size(); i++)
6e102d6e
VK
1039 {
1040 m_columns->get(i)->createNXMPRecord(str, i + 1);
1041 }
1042 str += _T("\t\t\t\t\t</columns>\n");
1043 }
1044
1045 if (m_thresholds != NULL)
1046 {
1047 str += _T("\t\t\t\t\t<thresholds>\n");
ef607e62 1048 for(int i = 0; i < m_thresholds->size(); i++)
6e102d6e
VK
1049 {
1050 m_thresholds->get(i)->createNXMPRecord(str, i + 1);
1051 }
1052 str += _T("\t\t\t\t\t</thresholds>\n");
1053 }
1054
1055 if (m_pszPerfTabSettings != NULL)
1056 {
ef607e62 1057 str.append(_T("\t\t\t\t\t<perfTabSettings>"));
4e0e77e6 1058 str.appendPreallocated(EscapeStringForXML(m_pszPerfTabSettings, -1));
ef607e62 1059 str.append(_T("</perfTabSettings>\n"));
6e102d6e
VK
1060 }
1061
e9c75749
EJ
1062 if (m_instanceDiscoveryData != NULL)
1063 {
1064 str += _T("\t\t\t\t\t<instanceDiscoveryData>");
1065 str.appendPreallocated(EscapeStringForXML(m_instanceDiscoveryData, -1));
1066 str += _T("</instanceDiscoveryData>\n");
1067 }
1068
1069 if (m_instanceFilterSource != NULL)
1070 {
1071 str += _T("\t\t\t\t\t<instanceFilter>");
1072 str.appendPreallocated(EscapeStringForXML(m_instanceFilterSource, -1));
1073 str += _T("</instanceFilter>\n");
1074 }
1075
6e102d6e 1076 unlock();
ef607e62 1077 str.append(_T("\t\t\t\t</dctable>\n"));
6e102d6e 1078}
e7450f3b
VK
1079
1080/**
1081 * Create DCObject from import file
1082 */
1083void DCTable::updateFromImport(ConfigEntry *config)
1084{
1085 DCObject::updateFromImport(config);
1086
77b2c6de 1087 lock();
e7450f3b
VK
1088 m_columns->clear();
1089 ConfigEntry *columnsRoot = config->findEntry(_T("columns"));
1090 if (columnsRoot != NULL)
1091 {
1092 ObjectArray<ConfigEntry> *columns = columnsRoot->getSubEntries(_T("column#*"));
1093 for(int i = 0; i < columns->size(); i++)
1094 {
1095 m_columns->add(new DCTableColumn(columns->get(i)));
1096 }
1097 delete columns;
1098 }
1099
1100 m_thresholds->clear();
1101 ConfigEntry *thresholdsRoot = config->findEntry(_T("thresholds"));
1102 if (thresholdsRoot != NULL)
1103 {
1104 ObjectArray<ConfigEntry> *thresholds = thresholdsRoot->getSubEntries(_T("threshold#*"));
1105 for(int i = 0; i < thresholds->size(); i++)
1106 {
1107 m_thresholds->add(new DCTableThreshold(thresholds->get(i)));
1108 }
1109 delete thresholds;
1110 }
77b2c6de 1111 unlock();
e7450f3b 1112}
faa89331
VK
1113
1114/**
47282713
VK
1115 * Get list of used events
1116 */
1117void DCTable::getEventList(IntegerArray<UINT32> *eventList)
1118{
1119 lock();
1120 if (m_thresholds != NULL)
1121 {
1122 for(int i = 0; i < m_thresholds->size(); i++)
1123 {
1124 eventList->add(m_thresholds->get(i)->getActivationEvent());
1125 eventList->add(m_thresholds->get(i)->getDeactivationEvent());
1126 }
1127 }
1128 unlock();
1129}
e9c75749
EJ
1130
1131/*
1132 * Clone DCTable
1133 */
1134DCObject *DCTable::clone()
1135{
1136 return new DCTable(this);
1137}
a31a2d32
VK
1138
1139/**
1140 * Serialize object to JSON
1141 */
1142json_t *DCTable::toJson()
1143{
1144 json_t *root = DCObject::toJson();
1145 json_object_set_new(root, "columns", json_object_array(m_columns));
1146 json_object_set_new(root, "thresholds", json_object_array(m_thresholds));
1147 return root;
1148}