Commit | Line | Data |
---|---|---|
4d1753cd VK |
1 | /*\r |
2 | ** NetXMS subagent for Oracle monitoring\r | |
3 | ** Copyright (C) 2009-2012 Raden Solutions\r | |
4 | **/\r | |
5 | \r | |
6 | #include "oracle_subagent.h"\r | |
7 | \r | |
8 | CONDITION g_shutdownCondition;\r | |
9 | MUTEX g_paramAccessMutex;\r | |
10 | int g_dbCount;\r | |
11 | DB_DRIVER g_driverHandle = NULL;\r | |
12 | DatabaseInfo g_dbInfo[MAX_DATABASES];\r | |
13 | DatabaseData g_dbData[MAX_DATABASES];\r | |
14 | \r | |
15 | THREAD_RESULT THREAD_CALL queryThread(void *arg);\r | |
16 | \r | |
17 | DBParameterGroup g_paramGroup[] = {\r | |
18 | {\r | |
19 | 700, _T("Oracle.Sessions."),\r | |
20 | _T("select ") DB_NULLARG_MAGIC _T(" ValueName, count(*) Count from v$session"),\r | |
21 | 2, { NULL }, 0\r | |
22 | },\r | |
23 | {\r | |
24 | 700, _T("Oracle.Cursors."),\r | |
25 | _T("select ") DB_NULLARG_MAGIC _T(" ValueName, sum(a.value) Count from v$sesstat a, v$statname b, v$session s where a.statistic# = b.statistic# and s.sid=a.sid and b.name = 'opened cursors current'"),\r | |
26 | 2, { NULL }, 0\r | |
27 | },\r | |
28 | {\r | |
d6b34435 AK |
29 | 700, _T("Oracle.Objects."),\r |
30 | _T("select ") DB_NULLARG_MAGIC _T(" ValueName, count(*) InvalidCount from dba_objects where status!='VALID'"),\r | |
31 | 2, { NULL }, 0\r | |
32 | },\r | |
33 | {\r | |
34 | 700, _T("Oracle.DBInfo."), \r | |
4d1753cd VK |
35 | _T("select ") DB_NULLARG_MAGIC _T(" ValueName, name Name, to_char(created) CreateDate, log_mode LogMode, open_mode OpenMode from v$database"),\r |
36 | 5, { NULL }, 0\r | |
37 | },\r | |
38 | {\r | |
39 | 700, _T("Oracle.Instance."),\r | |
40 | _T("select ") DB_NULLARG_MAGIC _T(" ValueName, version Version, status Status, archiver ArchiverStatus, shutdown_pending ShutdownPending from v$instance"),\r | |
41 | 5, { NULL }, 0\r | |
42 | },\r | |
43 | {\r | |
44 | 1000, _T("Oracle.TableSpaces."),\r | |
45 | _T("select d.tablespace_name ValueName, d.status Status, d.contents Type, to_char(round(used_percent,2)) UsedPct from dba_tablespaces d, dba_tablespace_usage_metrics m where d.tablespace_name=m.tablespace_name"),\r | |
46 | 3, { NULL }, 0\r | |
47 | },\r | |
48 | {\r | |
d6b34435 | 49 | 700, _T("Oracle.Dual."),\r |
4d1753cd VK |
50 | _T("select ") DB_NULLARG_MAGIC _T(" ValueName, decode(count(*),1,0,1) ExcessRows from dual"),\r |
51 | 1, { NULL }, 0\r | |
52 | },\r | |
53 | {\r | |
d6b34435 | 54 | 700, _T("Oracle.Performance."),\r |
4d1753cd | 55 | _T("select ") DB_NULLARG_MAGIC _T(" ValueName, (select s.value PhysReads from v$sysstat s, v$statname n where n.name='physical reads' and n.statistic#=s.statistic#) PhysReads, ")\r |
2acc690f | 56 | _T("(select s.value LogicReads from v$sysstat s, v$statname n where n.name='session logical reads' and n.statistic#=s.statistic#) LogicReads, ")\r |
d6b34435 AK |
57 | _T("(select round((sum(decode(name,'consistent gets',value,0))+sum(decode(name,'db block gets',value,0))-sum(decode(name,'physical reads',value, 0)))/(sum(decode(name,'consistent gets',value,0))+sum(decode(name,'db block gets',value,0)))*100,2) from v$sysstat) CacheHitRatio, ")\r |
58 | _T("(select round(sum(waits)*100/sum(gets),2) from v$rollstat) RollbackWaitRatio, ")\r | |
59 | _T("(select round((1-(sum(getmisses)/sum(gets)))*100,2) from v$rowcache) DictCacheHitRatio, ")\r | |
451bad4f AK |
60 | _T("(select round(sum(pins)/(sum(pins)+sum(reloads))*100,2) from v$librarycache) LibCacheHitRatio, ")\r |
61 | _T("(select round((100*b.value)/decode((a.value+b.value),0,1,(a.value+b.value)),2) from v$sysstat a,v$sysstat b where a.name='sorts (disk)' and b.name='sorts (memory)') MemorySortRatio, ")\r | |
62 | _T("(select round(nvl((sum(busy)/(sum(busy)+sum(idle)))*100,0),2) from v$dispatcher) DispatcherWorkload, ")\r | |
63 | _T("(select bytes from v$sgastat where name='free memory' and pool='shared pool') FreeSharedPool ")\r | |
4d1753cd | 64 | _T("from DUAL "),\r |
2acc690f | 65 | 3, { NULL }, 0\r |
4d1753cd VK |
66 | },\r |
67 | {\r | |
d6b34435 | 68 | 700, _T("Oracle.CriticalStats."), \r |
451bad4f | 69 | _T("select ") DB_NULLARG_MAGIC _T(" ValueName, (select count(*) TSOFF from dba_tablespaces where status <> 'ONLINE') TSOffCount, ")\r |
4d1753cd | 70 | _T("(select count(*) DFOFF from V$DATAFILE where status not in ('ONLINE','SYSTEM')) DFOffCount, ")\r |
451bad4f AK |
71 | _T("(select count(*) from dba_segments where max_extents = extents) FullSegmentsCount, ")\r |
72 | _T("(select count(*) from dba_rollback_segs where status <> 'ONLINE') RBSegsNotOnlineCount, ")\r | |
4d1753cd VK |
73 | _T("decode(sign(decode((select upper(log_mode) from v$database),'ARCHIVELOG',1,0)-")\r |
74 | _T("decode((select upper(value) from v$parameter where upper(name)='LOG_ARCHIVE_START'),'TRUE',1,0)),1, 1, 0) AutoArchivingOff, ")\r | |
451bad4f AK |
75 | _T("(select count(file#) from v$datafile_header where recover ='YES') DatafilesNeedMediaRecovery, ")\r |
76 | _T("(select count(*) FROM dba_jobs where NVL(failures,0) <> 0) FailedJobs ")\r | |
4d1753cd VK |
77 | _T("from DUAL"), \r |
78 | 5, { NULL }, 0\r | |
79 | },\r | |
80 | 0\r | |
81 | };\r | |
82 | \r | |
83 | //\r | |
84 | // Handler functions\r | |
85 | //\r | |
86 | \r | |
87 | LONG getParameters(const TCHAR *parameter, const TCHAR *argument, TCHAR *value)\r | |
88 | {\r | |
89 | LONG ret = SYSINFO_RC_UNSUPPORTED;\r | |
90 | TCHAR dbId[MAX_STR];\r | |
91 | TCHAR entity[MAX_STR];\r | |
92 | \r | |
93 | // Get id of the database requested\r | |
94 | if (!AgentGetParameterArg(parameter, 1, dbId, MAX_STR))\r | |
95 | return ret;\r | |
96 | if (!AgentGetParameterArg(parameter, 2, entity, MAX_STR) || entity[0] == _T('\0'))\r | |
97 | nx_strncpy(entity, DB_NULLARG_MAGIC, MAX_STR);\r | |
98 | \r | |
a4be813d | 99 | AgentWriteDebugLog(7, _T("%s: got request for params: dbid='%s', param='%s'"), MYNAMESTR, dbId, parameter);\r |
4d1753cd VK |
100 | \r |
101 | // Loop through databases and find an entry in g_dbInfo[] for this id\r | |
102 | for (int i = 0; i <= g_dbCount; i++)\r | |
103 | {\r | |
104 | if (!_tcsnicmp(g_dbInfo[i].id, dbId, MAX_STR)) // found DB\r | |
105 | {\r | |
6534de9b AK |
106 | if (argument[0] == _T('R'))\r |
107 | {\r | |
108 | ret_string(value, g_dbInfo[i].connected ? _T("YES") : _T("NO"));\r | |
109 | ret = SYSINFO_RC_SUCCESS;\r | |
110 | }\r | |
4d1753cd | 111 | // Loop through parameter groups and check whose prefix matches the parameter requested\r |
6534de9b | 112 | for (int k = 0; argument[0] == _T('X') && g_paramGroup[k].prefix; k++)\r |
4d1753cd VK |
113 | {\r |
114 | if (!_tcsnicmp(g_paramGroup[k].prefix, parameter, _tcslen(g_paramGroup[k].prefix))) // found prefix\r | |
115 | {\r | |
116 | MutexLock(g_dbInfo[i].accessMutex);\r | |
117 | // Loop through the values\r | |
a4be813d | 118 | AgentWriteDebugLog(9, _T("%s: valuecount %d"), MYNAMESTR, g_paramGroup[k].valueCount[i]);\r |
4d1753cd VK |
119 | for (int j = 0; j < g_paramGroup[k].valueCount[i]; j++)\r |
120 | {\r | |
121 | StringMap* map = (g_paramGroup[k].values[i])[j].attrs;\r | |
122 | TCHAR* name = (g_paramGroup[k].values[i])[j].name;\r | |
123 | if (!_tcsnicmp(name, entity, MAX_STR)) // found value which matches the parameters argument\r | |
124 | {\r | |
125 | TCHAR key[MAX_STR];\r | |
126 | nx_strncpy(key, parameter + _tcslen(g_paramGroup[k].prefix), MAX_STR);\r | |
127 | TCHAR* place = _tcschr(key, _T('('));\r | |
128 | if (place != NULL)\r | |
129 | {\r | |
130 | *place = _T('\0');\r | |
131 | const TCHAR* dbval = map->get(key);\r | |
132 | ret_string(value, dbval);\r | |
133 | ret = SYSINFO_RC_SUCCESS;\r | |
134 | }\r | |
135 | break;\r | |
136 | }\r | |
137 | }\r | |
138 | MutexUnlock(g_dbInfo[i].accessMutex);\r | |
139 | \r | |
140 | break;\r | |
141 | }\r | |
142 | }\r | |
143 | break;\r | |
144 | }\r | |
145 | }\r | |
146 | \r | |
147 | return ret;\r | |
148 | }\r | |
149 | \r | |
150 | \r | |
151 | //\r | |
152 | // Subagent initialization\r | |
153 | //\r | |
154 | \r | |
155 | static BOOL SubAgentInit(Config *config)\r | |
156 | {\r | |
157 | BOOL result = TRUE;\r | |
158 | static DatabaseInfo info;\r | |
159 | int i;\r | |
160 | static NX_CFG_TEMPLATE configTemplate[] = \r | |
161 | {\r | |
162 | { _T("Id"), CT_STRING, 0, 0, MAX_STR, 0, info.id }, \r | |
163 | { _T("Name"), CT_STRING, 0, 0, MAX_STR, 0, info.name }, \r | |
6534de9b | 164 | { _T("TnsName"), CT_STRING, 0, 0, MAX_STR, 0, info.name }, \r |
4d1753cd VK |
165 | { _T("UserName"), CT_STRING, 0, 0, MAX_USERNAME, 0, info.username }, \r |
166 | { _T("Password"), CT_STRING, 0, 0, MAX_PASSWORD, 0, info.password },\r | |
167 | { _T(""), CT_END_OF_LIST, 0, 0, 0, 0, NULL }\r | |
168 | };\r | |
169 | \r | |
170 | // Init db driver\r | |
171 | #ifdef _WIN32\r | |
172 | g_driverHandle = DBLoadDriver(_T("oracle.ddr"), NULL, TRUE, NULL, NULL);\r | |
173 | #else\r | |
174 | g_driverHandle = DBLoadDriver(LIBDIR "/libnxddr_oracle.so", NULL, TRUE, NULL, NULL);\r | |
175 | #endif\r | |
176 | if (g_driverHandle == NULL)\r | |
177 | {\r | |
178 | AgentWriteLog(EVENTLOG_ERROR_TYPE, _T("%s: failed to load db driver"), MYNAMESTR);\r | |
179 | result = FALSE;\r | |
180 | }\r | |
181 | \r | |
182 | if (result)\r | |
183 | {\r | |
184 | g_shutdownCondition = ConditionCreate(TRUE);\r | |
185 | }\r | |
186 | \r | |
04f06779 VK |
187 | // Load configuration from "oracle" section to allow simple configuration\r |
188 | // of one database without XML includes\r | |
189 | memset(&info, 0, sizeof(info));\r | |
190 | g_dbCount = -1;\r | |
191 | if (config->parseTemplate(_T("ORACLE"), configTemplate))\r | |
192 | {\r | |
2f67972d | 193 | if (info.name[0] != 0)\r |
04f06779 VK |
194 | {\r |
195 | if (info.id[0] == 0)\r | |
2f67972d | 196 | _tcscpy(info.id, info.name);\r |
04f06779 VK |
197 | memcpy(&g_dbInfo[++g_dbCount], &info, sizeof(DatabaseInfo));\r |
198 | g_dbInfo[g_dbCount].accessMutex = MutexCreate();\r | |
199 | }\r | |
200 | }\r | |
201 | \r | |
a4be813d AK |
202 | // Load full-featured XML configuration\r |
203 | if (g_dbCount == -1) // Didn't load anything from the .conf file\r | |
4d1753cd | 204 | {\r |
a4be813d | 205 | for (i = 1; result && i <= MAX_DATABASES; i++)\r |
4d1753cd | 206 | {\r |
a4be813d AK |
207 | TCHAR section[MAX_STR];\r |
208 | memset((void*)&info, 0, sizeof(info));\r | |
209 | _sntprintf(section, MAX_STR, _T("oracle/databases/database#%d"), i);\r | |
210 | if ((result = config->parseTemplate(section, configTemplate)) != TRUE)\r | |
211 | {\r | |
212 | AgentWriteLog(EVENTLOG_ERROR_TYPE, _T("%s: error parsing configuration template"), MYNAMESTR);\r | |
213 | return FALSE;\r | |
214 | }\r | |
215 | if (info.name[0] != _T('\0'))\r | |
216 | memcpy((void*)&g_dbInfo[++g_dbCount], (void*)&info, sizeof(info));\r | |
217 | else\r | |
218 | continue;\r | |
219 | if (info.username[0] == '\0' || info.password[0] == '\0')\r | |
220 | {\r | |
221 | AgentWriteLog(EVENTLOG_ERROR_TYPE, _T("%s: error getting username and/or password for "), MYNAMESTR);\r | |
222 | result = FALSE;\r | |
223 | }\r | |
224 | if (result && (g_dbInfo[g_dbCount].accessMutex = MutexCreate()) == NULL)\r | |
225 | {\r | |
226 | AgentWriteLog(EVENTLOG_ERROR_TYPE, _T("%s: failed to create mutex (%d)"), MYNAMESTR, i);\r | |
227 | result = FALSE;\r | |
228 | }\r | |
4d1753cd VK |
229 | }\r |
230 | }\r | |
231 | \r | |
232 | // Exit if no usable configuration found\r | |
233 | if (result && g_dbCount < 0)\r | |
234 | {\r | |
235 | AgentWriteLog(EVENTLOG_ERROR_TYPE, _T("%s: no databases to monitor"), MYNAMESTR);\r | |
236 | result = FALSE;\r | |
237 | }\r | |
238 | \r | |
239 | // Run query thread for each database configured\r | |
240 | for (i = 0; result && i <= g_dbCount; i++)\r | |
241 | {\r | |
242 | g_dbInfo[i].queryThreadHandle = ThreadCreateEx(queryThread, 0, CAST_TO_POINTER(i, void *));\r | |
243 | }\r | |
244 | \r | |
245 | return result;\r | |
246 | }\r | |
247 | \r | |
248 | \r | |
249 | //\r | |
250 | // Shutdown handler\r | |
251 | //\r | |
252 | \r | |
253 | static void SubAgentShutdown(void)\r | |
254 | {\r | |
255 | AgentWriteLog(EVENTLOG_INFORMATION_TYPE, _T("%s: shutting down"), MYNAMESTR);\r | |
256 | ConditionSet(g_shutdownCondition);\r | |
257 | for (int i = 0; i <= g_dbCount; i++)\r | |
258 | {\r | |
259 | ThreadJoin(g_dbInfo[i].queryThreadHandle);\r | |
260 | MutexDestroy(g_dbInfo[i].accessMutex);\r | |
261 | }\r | |
262 | ConditionDestroy(g_shutdownCondition);\r | |
263 | }\r | |
264 | \r | |
265 | //\r | |
266 | // Figure out Oracle DBMS version\r | |
267 | //\r | |
268 | \r | |
269 | static int getOracleVersion(DB_HANDLE handle) \r | |
270 | {\r | |
271 | TCHAR versionString[32];\r | |
272 | \r | |
273 | DB_RESULT result = DBSelect(handle,_T("select version from v$instance"));\r | |
274 | if (result == NULL) \r | |
275 | {\r | |
2f67972d | 276 | AgentWriteLog(EVENTLOG_WARNING_TYPE, _T("%s: query from v$instance failed"), MYNAMESTR);\r |
4d1753cd VK |
277 | return 700; // assume Oracle 7.0 by default\r |
278 | }\r | |
279 | \r | |
280 | DBGetField(result, 0, 0, versionString, 32);\r | |
281 | int major = 0, minor = 0;\r | |
282 | _stscanf(versionString, _T("%d.%d"), &major, &minor);\r | |
283 | DBFreeResult(result);\r | |
284 | \r | |
285 | return major * 100 + minor * 10;\r | |
286 | }\r | |
287 | \r | |
288 | //\r | |
289 | // Thread for SQL queries\r | |
290 | //\r | |
291 | \r | |
292 | THREAD_RESULT THREAD_CALL queryThread(void* arg)\r | |
293 | {\r | |
294 | int dbIndex = CAST_FROM_POINTER(arg, int);\r | |
295 | DatabaseInfo& db = g_dbInfo[dbIndex];\r | |
296 | const DWORD pollInterval = 60 * 1000L; // 1 minute\r | |
297 | int waitTimeout;\r | |
298 | QWORD startTimeMs;\r | |
299 | TCHAR errorText[DBDRV_MAX_ERROR_TEXT];\r | |
300 | \r | |
301 | while (true)\r | |
302 | {\r | |
6534de9b | 303 | db.handle = DBConnect(g_driverHandle, db.name, NULL /* db.server */, db.username, db.password, NULL, errorText);\r |
a4be813d | 304 | DBEnableReconnect(db.handle, false);\r |
4d1753cd VK |
305 | if (db.handle != NULL)\r |
306 | {\r | |
a4be813d | 307 | AgentWriteLog(EVENTLOG_INFORMATION_TYPE, _T("%s: connected to DB '%s'"), MYNAMESTR, db.name);\r |
4d1753cd VK |
308 | db.connected = true;\r |
309 | db.version = getOracleVersion(db.handle);\r | |
310 | }\r | |
311 | \r | |
312 | while (db.connected)\r | |
313 | {\r | |
314 | startTimeMs = GetCurrentTimeMs();\r | |
315 | \r | |
316 | // Do queries\r | |
317 | if (!(db.connected = getParametersFromDB(dbIndex)))\r | |
318 | {\r | |
319 | break;\r | |
320 | }\r | |
321 | \r | |
322 | waitTimeout = pollInterval - DWORD(GetCurrentTimeMs() - startTimeMs);\r | |
323 | if (ConditionWait(g_shutdownCondition, waitTimeout < 0 ? 1 : waitTimeout))\r | |
324 | goto finish;\r | |
325 | }\r | |
326 | \r | |
327 | // Try to reconnect every 30 secs\r | |
328 | if (ConditionWait(g_shutdownCondition, DWORD(30 * 1000)))\r | |
329 | break;\r | |
330 | }\r | |
331 | \r | |
332 | finish:\r | |
333 | if (db.connected && db.handle != NULL)\r | |
334 | {\r | |
335 | DBDisconnect(db.handle);\r | |
336 | }\r | |
337 | \r | |
338 | return THREAD_OK;\r | |
339 | }\r | |
340 | \r | |
341 | \r | |
342 | bool getParametersFromDB( int dbIndex )\r | |
343 | {\r | |
344 | bool ret = true;\r | |
345 | DatabaseInfo& info = g_dbInfo[dbIndex];\r | |
346 | \r | |
347 | if (!info.connected)\r | |
348 | {\r | |
349 | return false;\r | |
350 | }\r | |
351 | \r | |
352 | MutexLock(info.accessMutex);\r | |
353 | \r | |
354 | for (int i = 0; g_paramGroup[i].prefix; i++)\r | |
355 | {\r | |
356 | AgentWriteDebugLog(7, _T("%s: got entry for '%s'"), MYNAMESTR, g_paramGroup[i].prefix);\r | |
357 | \r | |
358 | if (g_paramGroup[i].version > info.version) // this parameter group is not supported for this DB\r | |
359 | continue; \r | |
360 | \r | |
361 | // Release previously allocated array of values for this group\r | |
2acc690f | 362 | for (int j = 0; g_paramGroup[i].values[dbIndex] && j < g_paramGroup[i].valueCount[dbIndex]; j++)\r |
4d1753cd | 363 | delete (g_paramGroup[i].values[dbIndex])[j].attrs;\r |
2acc690f | 364 | safe_free_and_null(g_paramGroup[i].values[dbIndex]);\r |
4d1753cd VK |
365 | \r |
366 | DB_RESULT queryResult = DBSelect(info.handle, g_paramGroup[i].query);\r | |
367 | if (queryResult == NULL)\r | |
368 | {\r | |
369 | ret = false;\r | |
370 | break;\r | |
371 | }\r | |
372 | \r | |
373 | int rows = DBGetNumRows(queryResult);\r | |
374 | g_paramGroup[i].values[dbIndex] = (DBParameter*)malloc(sizeof(DBParameter) * rows);\r | |
375 | g_paramGroup[i].valueCount[dbIndex] = rows;\r | |
376 | for (int j = 0; j < rows; j++)\r | |
377 | {\r | |
378 | TCHAR colname[MAX_STR];\r | |
379 | DBGetField(queryResult, j, 0, (g_paramGroup[i].values[dbIndex])[j].name, MAX_STR);\r | |
380 | (g_paramGroup[i].values[dbIndex])[j].attrs = new StringMap;\r | |
381 | for (int k = 1; DBGetColumnName(queryResult, k, colname, MAX_STR); k++) \r | |
382 | {\r | |
383 | TCHAR colval[MAX_STR];\r | |
384 | DBGetField(queryResult, j, k, colval, MAX_STR);\r | |
385 | // AgentWriteDebugLog(9, _T("%s: getParamsFromDB: colname '%s' ::: colval '%s'"), MYNAMESTR, colname, colval);\r | |
386 | (g_paramGroup[i].values[dbIndex])[j].attrs->set(colname, colval);\r | |
387 | }\r | |
388 | }\r | |
389 | \r | |
390 | DBFreeResult(queryResult);\r | |
391 | }\r | |
392 | \r | |
393 | MutexUnlock(info.accessMutex);\r | |
394 | \r | |
395 | return ret;\r | |
396 | }\r | |
397 | \r | |
398 | //\r | |
399 | // Subagent information\r | |
400 | //\r | |
401 | \r | |
402 | \r | |
403 | static NETXMS_SUBAGENT_PARAM m_parameters[] =\r | |
404 | {\r | |
405 | { _T("Oracle.Sessions.Count(*)"), getParameters, "X", DCI_DT_INT, _T("Oracle/Sessions: Number of sessions opened") },\r | |
406 | { _T("Oracle.Cursors.Count(*)"), getParameters, "X", DCI_DT_INT, _T("Oracle/Cursors: Current number of opened cursors systemwide") },\r | |
6534de9b | 407 | { _T("Oracle.DBInfo.IsReachable(*)"), getParameters, "R", DCI_DT_STRING, _T("Oracle/Info: Database is reachable") },\r |
4d1753cd VK |
408 | { _T("Oracle.DBInfo.Name(*)"), getParameters, "X", DCI_DT_STRING, _T("Oracle/Info: Database name") },\r |
409 | { _T("Oracle.DBInfo.CreateDate(*)"), getParameters, "X", DCI_DT_STRING, _T("Oracle/Info: Database creation date") },\r | |
410 | { _T("Oracle.DBInfo.LogMode(*)"), getParameters, "X", DCI_DT_STRING, _T("Oracle/Info: Database log mode") },\r | |
411 | { _T("Oracle.DBInfo.OpenMode(*)"), getParameters, "X", DCI_DT_STRING, _T("Oracle/Info: Database open mode") },\r | |
412 | { _T("Oracle.TableSpaces.Status(*)"), getParameters, "X", DCI_DT_STRING, _T("Oracle/Tablespaces: Status") },\r | |
413 | { _T("Oracle.TableSpaces.Type(*)"), getParameters, "X", DCI_DT_STRING, _T("Oracle/Tablespaces: Type") },\r | |
414 | { _T("Oracle.TableSpaces.UsedPct(*)"), getParameters, "X", DCI_DT_INT, _T("Oracle/Tablespaces: Percentage used") },\r | |
415 | { _T("Oracle.Instance.Version(*)"), getParameters, "X", DCI_DT_STRING, _T("Oracle/Instance: DBMS Version") },\r | |
416 | { _T("Oracle.Instance.Status(*)"), getParameters, "X", DCI_DT_STRING, _T("Oracle/Instance: Status") },\r | |
417 | { _T("Oracle.Instance.ArchiverStatus(*)"), getParameters, "X", DCI_DT_STRING, _T("Oracle/Instance: Archiver status") },\r | |
418 | { _T("Oracle.Instance.ShutdownPending(*)"), getParameters, "X", DCI_DT_STRING, _T("Oracle/Instance: Is shutdown pending") },\r | |
419 | { _T("Oracle.CriticalStats.TSOffCount(*)"), getParameters, "X", DCI_DT_INT, _T("Oracle/CriticalStats: Number of offline tablespaces") },\r | |
420 | { _T("Oracle.CriticalStats.DFOffCount(*)"), getParameters, "X", DCI_DT_INT, _T("Oracle/CriticalStats: Number of offline datafiles") },\r | |
421 | { _T("Oracle.CriticalStats.FullSegmentsCount(*)"), getParameters, "X", DCI_DT_INT64, _T("Oracle/CriticalStats: Number of segments that cannot extend") },\r | |
422 | { _T("Oracle.CriticalStats.RBSegsNotOnlineCount(*)"), getParameters, "X", DCI_DT_INT64, _T("Oracle/CriticalStats: Number of rollback segments not online") },\r | |
423 | { _T("Oracle.CriticalStats.AutoArchivingOff(*)"), getParameters, "X", DCI_DT_STRING, _T("Oracle/CriticalStats: Archive logs enabled but auto archiving off ") },\r | |
424 | { _T("Oracle.CriticalStats.DatafilesNeedMediaRecovery(*)"), getParameters, "X", DCI_DT_INT64, _T("Oracle/CriticalStats: Number of datafiles that need media recovery") },\r | |
425 | { _T("Oracle.CriticalStats.FailedJobs(*)"), getParameters, "X", DCI_DT_INT64, _T("Oracle/CriticalStats: Number of failed jobs") },\r | |
426 | { _T("Oracle.Dual.ExcessRows(*)"), getParameters, "X", DCI_DT_INT64, _T("Oracle/Dual: Excessive rows") },\r | |
427 | { _T("Oracle.Performance.PhysReads(*)"), getParameters, "X", DCI_DT_INT64, _T("Oracle/Performance: Number of physical reads") },\r | |
2acc690f | 428 | { _T("Oracle.Performance.LogicReads(*)"), getParameters, "X", DCI_DT_INT64, _T("Oracle/Performance: Number of logical reads") },\r |
d6b34435 AK |
429 | { _T("Oracle.Performance.CacheHitRatio(*)"), getParameters, "X", DCI_DT_INT64, _T("Oracle/Performance: Data buffer cache hit ratio") },\r |
430 | { _T("Oracle.Performance.LibCacheHitRatio(*)"), getParameters, "X", DCI_DT_INT64, _T("Oracle/Performance: Library cache hit ratio") },\r | |
431 | { _T("Oracle.Performance.DictCacheHitRatio(*)"), getParameters, "X", DCI_DT_INT64, _T("Oracle/Performance: Dictionary cache hit ratio") },\r | |
432 | { _T("Oracle.Performance.RollbackWaitRatio(*)"), getParameters, "X", DCI_DT_INT64, _T("Oracle/Performance: Ratio of waits for requests to rollback segments") },\r | |
451bad4f AK |
433 | { _T("Oracle.Performance.MemorySortRatio(*)"), getParameters, "X", DCI_DT_INT64, _T("Oracle/Performance: PGA memory sort ratio") },\r |
434 | { _T("Oracle.Performance.DispatcherWorkload(*)"), getParameters, "X", DCI_DT_INT64, _T("Oracle/Performance: Dispatcher workload (percentage)") },\r | |
435 | { _T("Oracle.Performance.FreeSharedPool(*)"), getParameters, "X", DCI_DT_INT64, _T("Oracle/Performance: Free space in shared pool (bytes)") },\r | |
d6b34435 | 436 | { _T("Oracle.Objects.InvalidCount(*)"), getParameters, "X", DCI_DT_INT64, _T("Oracle/Objects: Number of invalid objects in DB") }\r |
4d1753cd VK |
437 | };\r |
438 | \r | |
439 | /*\r | |
440 | static NETXMS_SUBAGENT_ENUM m_enums[] =\r | |
441 | {\r | |
442 | };\r | |
443 | */\r | |
444 | \r | |
445 | static NETXMS_SUBAGENT_INFO m_info =\r | |
446 | {\r | |
447 | NETXMS_SUBAGENT_INFO_MAGIC,\r | |
448 | _T("ORACLE"), NETXMS_VERSION_STRING,\r | |
449 | SubAgentInit, SubAgentShutdown, NULL,\r | |
450 | sizeof(m_parameters) / sizeof(NETXMS_SUBAGENT_PARAM), m_parameters,\r | |
451 | 0, NULL,\r | |
452 | /*sizeof(m_parameters) / sizeof(NETXMS_SUBAGENT_PARAM),\r | |
453 | m_parameters,\r | |
454 | sizeof(m_enums) / sizeof(NETXMS_SUBAGENT_ENUM),\r | |
455 | m_enums,*/\r | |
456 | 0, NULL\r | |
457 | };\r | |
458 | \r | |
459 | \r | |
460 | //\r | |
461 | // Entry point for NetXMS agent\r | |
462 | //\r | |
463 | \r | |
464 | DECLARE_SUBAGENT_ENTRY_POINT(ORACLE)\r | |
465 | {\r | |
466 | *ppInfo = &m_info;\r | |
467 | return TRUE;\r | |
468 | }\r | |
469 | \r | |
470 | \r | |
471 | //\r | |
472 | // DLL entry point\r | |
473 | //\r | |
474 | \r | |
475 | #ifdef _WIN32\r | |
476 | \r | |
477 | BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)\r | |
478 | {\r | |
479 | if (dwReason == DLL_PROCESS_ATTACH)\r | |
480 | DisableThreadLibraryCalls(hInstance);\r | |
481 | return TRUE;\r | |
482 | }\r | |
483 | \r | |
484 | #endif\r |