.svn removed from build.properties; minor changes in login dialog
[public/netxms.git] / src / server / core / dc_nxsl.cpp
CommitLineData
d02f6b92
VK
1/*
2** NetXMS - Network Management System
3** Copyright (C) 2003-2013 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: dc_nxsl.cpp
20**
21**/
22
23#include "nxcore.h"
24
25/**
26 * NXSL function: Get DCI object
27 * First argument is a node object (usually passed to script via $node variable),
28 * and second is DCI ID
29 */
30static int F_GetDCIObject(int argc, NXSL_Value **argv, NXSL_Value **ppResult, NXSL_Program *program)
31{
32 if (!argv[0]->isObject())
33 return NXSL_ERR_NOT_OBJECT;
34
35 if (!argv[1]->isInteger())
36 return NXSL_ERR_NOT_INTEGER;
37
38 NXSL_Object *object = argv[0]->getValueAsObject();
39 if (_tcscmp(object->getClass()->getName(), g_nxslNodeClass.getName()))
40 return NXSL_ERR_BAD_CLASS;
41
42 Node *node = (Node *)object->getData();
43 DCObject *dci = node->getDCObjectById(argv[1]->getValueAsUInt32());
44 if ((dci != NULL) && (dci->getType() == DCO_TYPE_ITEM))
45 {
46 *ppResult = new NXSL_Value(new NXSL_Object(&g_nxslDciClass, dci));
47 }
48 else
49 {
50 *ppResult = new NXSL_Value; // Return NULL if DCI not found
51 }
52
53 return 0;
54}
55
56/**
57 * NXSL function: Get DCI value from within transformation script
58 * First argument is a node object (passed to script via $node variable),
59 * and second is DCI ID
60 */
61static int F_GetDCIValue(int argc, NXSL_Value **argv, NXSL_Value **ppResult, NXSL_Program *program)
62{
63 if (!argv[0]->isObject())
64 return NXSL_ERR_NOT_OBJECT;
65
66 if (!argv[1]->isInteger())
67 return NXSL_ERR_NOT_INTEGER;
68
69 NXSL_Object *object = argv[0]->getValueAsObject();
70 if (_tcscmp(object->getClass()->getName(), g_nxslNodeClass.getName()))
71 return NXSL_ERR_BAD_CLASS;
72
73 Node *node = (Node *)object->getData();
74 DCObject *dci = node->getDCObjectById(argv[1]->getValueAsUInt32());
75 if ((dci != NULL) && (dci->getType() == DCO_TYPE_ITEM))
76 {
77 *ppResult = ((DCItem *)dci)->getValueForNXSL(F_LAST, 1);
78 }
79 else
80 {
81 *ppResult = new NXSL_Value; // Return NULL if DCI not found
82 }
83
84 return 0;
85}
86
87/**
88 * Internal implementation of GetDCIValueByName and GetDCIValueByDescription
89 */
90static int GetDciValueExImpl(bool byName, int argc, NXSL_Value **argv, NXSL_Value **ppResult)
91{
92 if (!argv[0]->isObject())
93 return NXSL_ERR_NOT_OBJECT;
94
95 if (!argv[1]->isString())
96 return NXSL_ERR_NOT_STRING;
97
98 NXSL_Object *object = argv[0]->getValueAsObject();
99 if (_tcscmp(object->getClass()->getName(), g_nxslNodeClass.getName()))
100 return NXSL_ERR_BAD_CLASS;
101
102 Node *node = (Node *)object->getData();
103 DCObject *dci = byName ? node->getDCObjectByName(argv[1]->getValueAsCString()) : node->getDCObjectByDescription(argv[1]->getValueAsCString());
104 if ((dci != NULL) && (dci->getType() == DCO_TYPE_ITEM))
105 {
106 *ppResult = ((DCItem *)dci)->getValueForNXSL(F_LAST, 1);
107 }
108 else
109 {
110 *ppResult = new NXSL_Value; // Return NULL if DCI not found
111 }
112
113 return 0;
114}
115
116/**
117 * NXSL function: Get DCI value from within transformation script
118 * First argument is a node object (passed to script via $node variable),
119 * and second is DCI name
120 */
121static int F_GetDCIValueByName(int argc, NXSL_Value **argv, NXSL_Value **ppResult, NXSL_Program *program)
122{
123 return GetDciValueExImpl(true, argc, argv, ppResult);
124}
125
126/**
127 * NXSL function: Get DCI value from within transformation script
128 * First argument is a node object (passed to script via $node variable),
129 * and second is DCI description
130 */
131static int F_GetDCIValueByDescription(int argc, NXSL_Value **argv, NXSL_Value **ppResult, NXSL_Program *program)
132{
133 return GetDciValueExImpl(false, argc, argv, ppResult);
134}
135
136/**
137 * NXSL function: Find DCI by name
138 */
139static int F_FindDCIByName(int argc, NXSL_Value **argv, NXSL_Value **ppResult, NXSL_Program *program)
140{
141 if (!argv[0]->isObject())
142 return NXSL_ERR_NOT_OBJECT;
143
144 if (!argv[1]->isString())
145 return NXSL_ERR_NOT_STRING;
146
147 NXSL_Object *object = argv[0]->getValueAsObject();
148 if (_tcscmp(object->getClass()->getName(), g_nxslNodeClass.getName()))
149 return NXSL_ERR_BAD_CLASS;
150
151 Node *node = (Node *)object->getData();
152 DCObject *dci = node->getDCObjectByName(argv[1]->getValueAsCString());
153 *ppResult = ((dci != NULL) && (dci->getType() == DCO_TYPE_ITEM)) ? new NXSL_Value(dci->getId()) : new NXSL_Value((DWORD)0);
154 return 0;
155}
156
157/**
158 * NXSL function: Find DCI by description
159 */
160static int F_FindDCIByDescription(int argc, NXSL_Value **argv, NXSL_Value **ppResult, NXSL_Program *program)
161{
162 if (!argv[0]->isObject())
163 return NXSL_ERR_NOT_OBJECT;
164
165 if (!argv[1]->isString())
166 return NXSL_ERR_NOT_STRING;
167
168 NXSL_Object *object = argv[0]->getValueAsObject();
169 if (_tcscmp(object->getClass()->getName(), g_nxslNodeClass.getName()))
170 return NXSL_ERR_BAD_CLASS;
171
172 Node *node = (Node *)object->getData();
173 DCObject *dci = node->getDCObjectByDescription(argv[1]->getValueAsCString());
174 *ppResult = ((dci != NULL) && (dci->getType() == DCO_TYPE_ITEM)) ? new NXSL_Value(dci->getId()) : new NXSL_Value((DWORD)0);
175 return 0;
176}
177
178/**
179 * Get min, max or average of DCI values for a period
180 */
181typedef enum { DCI_MIN, DCI_MAX, DCI_AVG } DciSqlFunc_t;
182
183static int F_GetDCIValueStat(int argc, NXSL_Value **argv, NXSL_Value **ppResult, NXSL_Program *program, DciSqlFunc_t sqlFunc)
184{
185 if (!argv[0]->isObject())
186 return NXSL_ERR_NOT_OBJECT;
187
188 if (!argv[1]->isInteger() || !argv[2]->isInteger() || !argv[3]->isInteger())
189 return NXSL_ERR_NOT_INTEGER;
190
191 NXSL_Object *object = argv[0]->getValueAsObject();
192 if (_tcscmp(object->getClass()->getName(), g_nxslNodeClass.getName()))
193 return NXSL_ERR_BAD_CLASS;
194
195 Node *node = (Node *)object->getData();
196 DWORD nodeId = node->Id();
197 DCObject *dci = node->getDCObjectById(argv[1]->getValueAsUInt32());
198 if (dci == NULL || dci->getType() != DCO_TYPE_ITEM)
199 {
200 *ppResult = new NXSL_Value; // Return NULL if DCI not found
201 }
202 else
203 {
204 *ppResult = NULL;
205
206 double result = 0.;
207 DB_HANDLE hdb = DBConnectionPoolAcquireConnection();
208 TCHAR query[1024];
209
210 if (g_nDBSyntax == DB_SYNTAX_ORACLE)
211 {
212 _sntprintf(query, 1024, _T("SELECT %s(coalesce(to_number(idata_value),0)) FROM idata_%u ")
213 _T("WHERE item_id=? and idata_timestamp between ? and ?"),
214 sqlFunc == DCI_MAX ? _T("max"): (sqlFunc == DCI_MIN ? _T("min") : _T("avg")), node->Id());
215 }
216 else if (g_nDBSyntax == DB_SYNTAX_PGSQL)
217 {
218 _sntprintf(query, 1024, _T("SELECT %s(coalesce(idata_value::double precision,0)) FROM idata_%u ")
219 _T("WHERE item_id=? and idata_timestamp between ? and ?"),
220 sqlFunc == DCI_MAX ? _T("max"): (sqlFunc == DCI_MIN ? _T("min") : _T("avg")), node->Id());
221 }
222 else
223 {
224 _sntprintf(query, 1024, _T("SELECT %s(coalesce(idata_value,0)) FROM idata_%u ")
225 _T("WHERE item_id=? and idata_timestamp between ? and ?"),
226 sqlFunc == DCI_MAX ? _T("max"): (sqlFunc == DCI_MIN ? _T("min") : _T("avg")), node->Id());
227 }
228
229 DB_STATEMENT hStmt = DBPrepare(hdb, query);
230 if (hStmt != NULL)
231 {
232 DBBind(hStmt, 1, DB_SQLTYPE_INTEGER, argv[1]->getValueAsUInt32());
233 DBBind(hStmt, 2, DB_SQLTYPE_INTEGER, argv[2]->getValueAsInt32());
234 DBBind(hStmt, 3, DB_SQLTYPE_INTEGER, argv[3]->getValueAsInt32());
235 DB_RESULT hResult = DBSelectPrepared(hStmt);
236 if (hResult != NULL)
237 {
238 if (DBGetNumRows(hResult) == 1)
239 {
240 result = DBGetFieldDouble(hResult, 0, 0);
241 }
242 *ppResult = new NXSL_Value(result);
243 DBFreeResult(hResult);
244 }
245 else
246 {
247 *ppResult = new NXSL_Value; // Return NULL if prepared select failed
248 }
249 DBFreeStatement(hStmt);
250 }
251 else
252 {
253 *ppResult = new NXSL_Value; // Return NULL if prepare failed
254 }
255
256 DBConnectionPoolReleaseConnection(hdb);
257 }
258
259 return 0;
260}
261
262/**
263 * Get min of DCI values for a period
264 */
265static int F_GetMinDCIValue(int argc, NXSL_Value **argv, NXSL_Value **ppResult, NXSL_Program *program)
266{
267 return F_GetDCIValueStat(argc, argv, ppResult, program, DCI_MIN);
268}
269
270/**
271 * Get max of DCI values for a period
272 */
273static int F_GetMaxDCIValue(int argc, NXSL_Value **argv, NXSL_Value **ppResult, NXSL_Program *program)
274{
275 return F_GetDCIValueStat(argc, argv, ppResult, program, DCI_MAX);
276}
277
278/**
279 * Get average of DCI values for a period
280 */
281static int F_GetAvgDCIValue(int argc, NXSL_Value **argv, NXSL_Value **ppResult, NXSL_Program *program)
282{
283 return F_GetDCIValueStat(argc, argv, ppResult, program, DCI_AVG);
284}
285
286/**
287 * NXSL function: create new DCI
288 * Format: CreateDCI(node, origin, name, description, dataType, pollingInterval, retentionTime)
289 * Possible origin values: "agent", "snmp", "internal", "push"
290 * Possible dataType values: "int32", "uint32", "int64", "uint64", "float", "string"
291 * Returns DCI object on success and NULL of failure
292 */
293static int F_CreateDCI(int argc, NXSL_Value **argv, NXSL_Value **ppResult, NXSL_Program *program)
294{
295 if (!argv[0]->isObject())
296 return NXSL_ERR_NOT_OBJECT;
297
298 if (!argv[1]->isString() || !argv[2]->isString() || !argv[3]->isString() || !argv[4]->isString())
299 return NXSL_ERR_NOT_STRING;
300
301 if (!argv[5]->isInteger() || !argv[6]->isInteger())
302 return NXSL_ERR_NOT_INTEGER;
303
304 NXSL_Object *object = argv[0]->getValueAsObject();
305 if (_tcscmp(object->getClass()->getName(), g_nxslNodeClass.getName()))
306 return NXSL_ERR_BAD_CLASS;
307 Node *node = (Node *)object->getData();
308
309 // Origin
310 static const TCHAR *originNames[] = { _T("internal"), _T("agent"), _T("snmp"), _T("cpsnmp"), _T("push"), NULL };
311 int origin = -1;
312 const TCHAR *name = argv[1]->getValueAsCString();
313 for(int i = 0; originNames[i] != NULL; i++)
314 if (!_tcsicmp(originNames[i], name))
315 {
316 origin = i;
317 break;
318 }
319
320 // Data types
321 static const TCHAR *dtNames[] = { _T("int32"), _T("uint32"), _T("int64"), _T("uint64"), _T("string"), _T("float"), NULL };
322 int dataType = -1;
323 name = argv[4]->getValueAsCString();
324 for(int i = 0; dtNames[i] != NULL; i++)
325 if (!_tcsicmp(dtNames[i], name))
326 {
327 dataType = i;
328 break;
329 }
330
331 int pollingInterval = argv[5]->getValueAsInt32();
332 int retentionTime = argv[6]->getValueAsInt32();
333
334 if ((origin != -1) && (dataType != -1) && (pollingInterval > 0) && (retentionTime > 0))
335 {
336 DCItem *dci = new DCItem(CreateUniqueId(IDG_ITEM), argv[2]->getValueAsCString(),
337 origin, dataType, pollingInterval, retentionTime, node, argv[3]->getValueAsCString());
338 node->addDCObject(dci);
339 *ppResult = new NXSL_Value(new NXSL_Object(&g_nxslDciClass, dci));
340 }
341 else
342 {
343 *ppResult = new NXSL_Value;
344 }
345 return 0;
346}
347
348/**
349 * Additional NXSL functions for DCI manipulation
350 */
351static NXSL_ExtFunction m_nxslDCIFunctions[] =
352{
353 { _T("CreateDCI"), F_CreateDCI, 7 },
354 { _T("FindDCIByName"), F_FindDCIByName, 2 },
355 { _T("FindDCIByDescription"), F_FindDCIByDescription, 2 },
356 { _T("GetDCIObject"), F_GetDCIObject, 2 },
357 { _T("GetDCIValue"), F_GetDCIValue, 2 },
358 { _T("GetDCIValueByName"), F_GetDCIValueByName, 2 },
359 { _T("GetDCIValueByDescription"), F_GetDCIValueByDescription, 2 },
360 { _T("GetMaxDCIValue"), F_GetMaxDCIValue, 4 },
361 { _T("GetMinDCIValue"), F_GetMinDCIValue, 4 },
362 { _T("GetAvgDCIValue"), F_GetAvgDCIValue, 4 }
363};
364
365/**
366 * Register DCI-related functions in NXSL environment
367 */
368void RegisterDCIFunctions(NXSL_Environment *pEnv)
369{
370 pEnv->registerFunctionSet(sizeof(m_nxslDCIFunctions) / sizeof(NXSL_ExtFunction), m_nxslDCIFunctions);
371}