d2e56fc4b029974f6de36bc1c7b9d4c27033eff0
[public/netxms.git] / src / agent / subagents / db2 / db2_subagent.cpp
1 /**
2 * NetXMS - open source network management system
3 * Copyright (C) 2013 Raden Solutions
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
20 #include "db2_subagent.h"
21
22 DB_DRIVER g_drvHandle = NULL;
23 CONDITION g_sdownCondition = NULL;
24 PTHREAD_INFO g_threads = NULL;;
25 UINT32 g_numOfThreads = 0;
26
27 static NETXMS_SUBAGENT_PARAM m_agentParams[] =
28 {
29 {
30 _T("DB2.Instance.Version(*)"), GetParameter, _D(DCI_DBMS_VERSION),
31 DCI_DT_STRING, _T("DB2/Instance: DBMS Version")
32 },
33 {
34 _T("DB2.Table.Available(*)"), GetParameter, _D(DCI_NUM_AVAILABLE),
35 DCI_DT_INT, _T("DB2/Table: Number of available tables")
36 },
37 {
38 _T("DB2.Table.Unavailable(*)"), GetParameter, _D(DCI_NUM_UNAVAILABLE),
39 DCI_DT_INT, _T("DB2/Table: Number of unavailable tables")
40 },
41 {
42 _T("DB2.Table.Data.LogicalSize(*)"), GetParameter, _D(DCI_DATA_L_SIZE),
43 DCI_DT_INT64, _T("DB2/Table/Data: Data object logical size in kilobytes")
44 },
45 {
46 _T("DB2.Table.Data.PhysicalSize(*)"), GetParameter, _D(DCI_DATA_P_SIZE),
47 DCI_DT_INT64, _T("DB2/Table/Data: Data object physical size in kilobytes")
48 },
49 {
50 _T("DB2.Table.Index.LogicalSize(*)"), GetParameter, _D(DCI_INDEX_L_SIZE),
51 DCI_DT_INT64, _T("DB2/Table/Index: Index object logical size in kilobytes")
52 },
53 {
54 _T("DB2.Table.Index.PhysicalSize(*)"), GetParameter, _D(DCI_INDEX_P_SIZE),
55 DCI_DT_INT64, _T("DB2/Table/Index: Index object physical size in kilobytes")
56 },
57 {
58 _T("DB2.Table.Long.LogicalSize(*)"), GetParameter, _D(DCI_LONG_L_SIZE),
59 DCI_DT_INT64, _T("DB2/Table/Long: Long object logical size in kilobytes")
60 },
61 {
62 _T("DB2.Table.Long.PhysicalSize(*)"), GetParameter, _D(DCI_LONG_P_SIZE),
63 DCI_DT_INT64, _T("DB2/Table/Long: Long object physical size in kilobytes")
64 },
65 {
66 _T("DB2.Table.Lob.LogicalSize(*)"), GetParameter, _D(DCI_LOB_L_SIZE),
67 DCI_DT_INT64, _T("DB2/Table/Lob: LOB object logical size in kilobytes")
68 },
69 {
70 _T("DB2.Table.Lob.PhysicalSize(*)"), GetParameter, _D(DCI_LOB_P_SIZE),
71 DCI_DT_INT64, _T("DB2/Table/Lob: LOB object physical size in kilobytes")
72 },
73 {
74 _T("DB2.Table.Xml.LogicalSize(*)"), GetParameter, _D(DCI_XML_L_SIZE),
75 DCI_DT_INT64, _T("DB2/Table/Xml: XML object logical size in kilobytes")
76 },
77 {
78 _T("DB2.Table.Xml.PhysicalSize(*)"), GetParameter, _D(DCI_XML_P_SIZE),
79 DCI_DT_INT64, _T("DB2/Table/Xml: XML object physical size in kilobytes")
80 },
81 {
82 _T("DB2.Table.Index.Type1(*)"), GetParameter, _D(DCI_INDEX_TYPE1),
83 DCI_DT_INT, _T("DB2/Table/Index: Number of tables using type-1 indexes")
84 },
85 {
86 _T("DB2.Table.Index.Type2(*)"), GetParameter, _D(DCI_INDEX_TYPE2),
87 DCI_DT_INT, _T("DB2/Table/Index: Number of tables using type-2 indexes")
88 },
89 {
90 _T("DB2.Table.Reorg.Pending(*)"), GetParameter, _D(DCI_REORG_PENDING),
91 DCI_DT_INT, _T("DB2/Table/Reorg: Number of tables pending reorganization")
92 },
93 {
94 _T("DB2.Table.Reorg.Aborted(*)"), GetParameter, _D(DCI_REORG_ABORTED),
95 DCI_DT_INT, _T("DB2/Table/Reorg: Number of tables in aborted reorganization state")
96 },
97 {
98 _T("DB2.Table.Reorg.Executing(*)"), GetParameter, _D(DCI_REORG_EXECUTING),
99 DCI_DT_INT, _T("DB2/Table/Reorg: Number of tables in executing reorganization state")
100 },
101 {
102 _T("DB2.Table.Reorg.Null(*)"), GetParameter, _D(DCI_REORG_NULL),
103 DCI_DT_INT, _T("DB2/Table/Reorg: Number of tables in null reorganization state")
104 },
105 {
106 _T("DB2.Table.Reorg.Paused(*)"), GetParameter, _D(DCI_REORG_PAUSED),
107 DCI_DT_INT, _T("DB2/Table/Reorg: Number of tables in paused reorganization state")
108 },
109 {
110 _T("DB2.Table.Reorg.Alters(*)"), GetParameter, _D(DCI_NUM_REORG_REC_ALTERS),
111 DCI_DT_INT, _T("DB2/Table/Reorg: Number of reorg recommend alter operations")
112 },
113 {
114 _T("DB2.Table.Load.InProgress(*)"), GetParameter, _D(DCI_LOAD_IN_PROGRESS),
115 DCI_DT_INT, _T("DB2/Table/Load: Number of tables with load in progress status")
116 },
117 {
118 _T("DB2.Table.Load.Pending(*)"), GetParameter, _D(DCI_LOAD_PENDING),
119 DCI_DT_INT, _T("DB2/Table/Load: Number of tables with load pending status")
120 },
121 {
122 _T("DB2.Table.Load.Null(*)"), GetParameter, _D(DCI_LOAD_NULL),
123 DCI_DT_INT, _T("DB2/Table/Load: Number of tables with load status neither in progress nor pending")
124 },
125 {
126 _T("DB2.Table.Readonly(*)"), GetParameter, _D(DCI_ACCESS_RO),
127 DCI_DT_INT, _T("DB2/Table: Number of tables in Read Access Only state")
128 },
129 {
130 _T("DB2.Table.NoLoadRestart(*)"), GetParameter, _D(DCI_NO_LOAD_RESTART),
131 DCI_DT_INT, _T("DB2/Table: Number of tables in a state that won't allow a load restart")
132 },
133 {
134 _T("DB2.Table.Index.Rebuild(*)"), GetParameter, _D(DCI_INDEX_REQUIRE_REBUILD),
135 DCI_DT_INT, _T("DB2/Table/Index: Number of tables with indexes that require rebuild")
136 },
137 {
138 _T("DB2.Table.Rid.Large(*)"), GetParameter, _D(DCI_LARGE_RIDS),
139 DCI_DT_INT, _T("DB2/Table/Rid: Number of tables that use large row IDs")
140 },
141 {
142 _T("DB2.Table.Rid.Usual(*)"), GetParameter, _D(DCI_NO_LARGE_RIDS),
143 DCI_DT_INT, _T("DB2/Table/Rid: Number of tables that don't use large row IDs")
144 },
145 {
146 _T("DB2.Table.Rid.Pending(*)"), GetParameter, _D(DCI_LARGE_RIDS_PENDING),
147 DCI_DT_INT, _T("DB2/Table/Rid: Number of tables that use large row Ids but not all indexes have been rebuilt yet")
148 },
149 {
150 _T("DB2.Table.Slot.Large(*)"), GetParameter, _D(DCI_LARGE_SLOTS),
151 DCI_DT_INT, _T("DB2/Table/Slot: Number of tables that use large slots")
152 },
153 {
154 _T("DB2.Table.Slot.Usual(*)"), GetParameter, _D(DCI_NO_LARGE_SLOTS),
155 DCI_DT_INT, _T("DB2/Table/Slot: Number of tables that don't use large slots")
156 },
157 {
158 _T("DB2.Table.Slot.Pending(*)"), GetParameter, _D(DCI_LARGE_SLOTS_PENDING),
159 DCI_DT_INT,
160 _T("DB2/Table/Slot: Number of tables that use large slots but there has not yet been an offline table reorganization")
161 _T(" or table truncation operation")
162 },
163 {
164 _T("DB2.Table.DictSize(*)"), GetParameter, _D(DCI_DICTIONARY_SIZE),
165 DCI_DT_INT64, _T("DB2/Table: Size of the dictionary in bytes")
166 },
167 {
168 _T("DB2.Table.Scans(*)"), GetParameter, _D(DCI_TABLE_SCANS),
169 DCI_DT_INT64, _T("DB2/Table: The number of scans on all tables")
170 },
171 {
172 _T("DB2.Table.Row.Read(*)"), GetParameter, _D(DCI_ROWS_READ),
173 DCI_DT_INT64, _T("DB2/Table/Row: The number of reads on all tables")
174 },
175 {
176 _T("DB2.Table.Row.Inserted(*)"), GetParameter, _D(DCI_ROWS_INSERTED),
177 DCI_DT_INT64, _T("DB2/Table/Row: The number of insertions attempted on all tables")
178 },
179 {
180 _T("DB2.Table.Row.Updated(*)"), GetParameter, _D(DCI_ROWS_UPDATED),
181 DCI_DT_INT64, _T("DB2/Table/Row: The number of updates attempted on all tables")
182 },
183 {
184 _T("DB2.Table.Row.Deleted(*)"), GetParameter, _D(DCI_ROWS_DELETED),
185 DCI_DT_INT64, _T("DB2/Table/Row: The number of deletes attempted on all tables")
186 },
187 {
188 _T("DB2.Table.Overflow.Accesses(*)"), GetParameter, _D(DCI_OVERFLOW_ACCESSES),
189 DCI_DT_INT64, _T("DB2/Table/Overflow: The number of r/w operations on overflowed rows of all tables")
190 },
191 {
192 _T("DB2.Table.Overflow.Creates(*)"), GetParameter, _D(DCI_OVERFLOW_CREATES),
193 DCI_DT_INT64, _T("DB2/Table/Overflow: The number of overflowed rows created on all tables")
194 },
195 {
196 _T("DB2.Table.Reorg.Page(*)"), GetParameter, _D(DCI_PAGE_REORGS),
197 DCI_DT_INT64, _T("DB2/Table/Reorg: The number of page reorganizations executed for all tables")
198 },
199 {
200 _T("DB2.Table.Data.LogicalPages(*)"), GetParameter, _D(DCI_DATA_L_PAGES),
201 DCI_DT_INT64, _T("DB2/Table/Data: The number of logical pages used on disk by data")
202 },
203 {
204 _T("DB2.Table.Lob.LogicalPages(*)"), GetParameter, _D(DCI_LOB_L_PAGES),
205 DCI_DT_INT64, _T("DB2/Table/Lob: The number of logical pages used on disk by LOBs")
206 },
207 {
208 _T("DB2.Table.Long.LogicalPages(*)"), GetParameter, _D(DCI_LONG_L_PAGES),
209 DCI_DT_INT64, _T("DB2/Table/Long: The number of logical pages used on disk by long data")
210 },
211 {
212 _T("DB2.Table.Index.LogicalPages(*)"), GetParameter, _D(DCI_INDEX_L_PAGES),
213 DCI_DT_INT64, _T("DB2/Table/Index: The number of logical pages used on disk by indexes")
214 },
215 {
216 _T("DB2.Table.Xda.LogicalPages(*)"), GetParameter, _D(DCI_XDA_L_PAGES),
217 DCI_DT_INT64, _T("DB2/Table/Xda: The number of logical pages used on disk by XDA (XML storage object)")
218 },
219 {
220 _T("DB2.Table.Row.NoChange(*)"), GetParameter, _D(DCI_NO_CHANGE_UPDATES),
221 DCI_DT_INT64, _T("DB2/Table/Row: The number of row updates that yielded no changes")
222 },
223 {
224 _T("DB2.Table.Lock.WaitTime(*)"), GetParameter, _D(DCI_LOCK_WAIT_TIME),
225 DCI_DT_INT64, _T("DB2/Table/Lock: The total elapsed time spent waiting for locks (ms)")
226 },
227 {
228 _T("DB2.Table.Lock.WaitTimeGlob(*)"), GetParameter, _D(DCI_LOCK_WAIT_TIME_GLOBAL),
229 DCI_DT_INT64, _T("DB2/Table/Lock: The total elapsed time spent on global lock waits (ms)")
230 },
231 {
232 _T("DB2.Table.Lock.Waits(*)"), GetParameter, _D(DCI_LOCK_WAITS),
233 DCI_DT_INT64, _T("DB2/Table/Lock: The total amount of locks occurred")
234 },
235 {
236 _T("DB2.Table.Lock.WaitsGlob(*)"), GetParameter, _D(DCI_LOCK_WAITS_GLOBAL),
237 DCI_DT_INT64, _T("DB2/Table/Lock: The total amount of global locks occurred")
238 },
239 {
240 _T("DB2.Table.Lock.EscalsGlob(*)"), GetParameter, _D(DCI_LOCK_ESCALS_GLOBAL),
241 DCI_DT_INT64, _T("DB2/Table/Lock: The number of lock escalations on a global lock")
242 },
243 {
244 _T("DB2.Table.Data.Sharing.Shared(*)"), GetParameter, _D(DCI_STATE_SHARED),
245 DCI_DT_INT, _T("DB2/Table/Data/Sharing: The number of fully shared tables")
246 },
247 {
248 _T("DB2.Table.Data.Sharing.BecomingShared(*)"), GetParameter, _D(DCI_STATE_SHARED_BECOMING),
249 DCI_DT_INT, _T("DB2/Table/Data/Sharing: The number of tables being in the process of becoming shared")
250 },
251 {
252 _T("DB2.Table.Data.Sharing.NotShared(*)"), GetParameter, _D(DCI_STATE_NOT_SHARED),
253 DCI_DT_INT, _T("DB2/Table/Data/Sharing: The number of tables not being shared")
254 },
255 {
256 _T("DB2.Table.Data.Sharing.BecomingNotShared(*)"), GetParameter, _D(DCI_STATE_NOT_SHARED_BECOMING),
257 DCI_DT_INT, _T("DB2/Table/Data/Sharing: The number of tables being in the process of becoming not shared")
258 },
259 {
260 _T("DB2.Table.Data.Sharing.RemoteLockWaitCount(*)"), GetParameter, _D(DCI_SHARING_LOCKWAIT_COUNT),
261 DCI_DT_INT64, _T("DB2/Table/Data/Sharing: The number of exits from the NOT_SHARED data sharing state")
262 },
263 {
264 _T("DB2.Table.Data.Sharing.RemoteLockWaitTime(*)"), GetParameter, _D(DCI_SHARING_LOCKWAIT_TIME),
265 DCI_DT_INT64, _T("DB2/Table/Data/Sharing: The time spent on waiting for a table to become shared")
266 },
267 {
268 _T("DB2.Table.DirectWrites(*)"), GetParameter, _D(DCI_DIRECT_WRITES),
269 DCI_DT_INT64, _T("DB2/Table: The number of write operations that don't use the buffer pool")
270 },
271 {
272 _T("DB2.Table.DirectWriteReqs(*)"), GetParameter, _D(DCI_DIRECT_WRITE_REQS),
273 DCI_DT_INT64, _T("DB2/Table: The number of request to perform a direct write operation")
274 },
275 {
276 _T("DB2.Table.DirectRead(*)"), GetParameter, _D(DCI_DIRECT_READS),
277 DCI_DT_INT64, _T("DB2/Table: The number of read operations that don't use the buffer pool")
278 },
279 {
280 _T("DB2.Table.DirectReadReqs(*)"), GetParameter, _D(DCI_DIRECT_READ_REQS),
281 DCI_DT_INT64, _T("DB2/Table: The number of request to perform a direct read operation")
282 },
283 {
284 _T("DB2.Table.Data.LogicalReads(*)"), GetParameter, _D(DCI_DATA_L_READS),
285 DCI_DT_INT64, _T("DB2/Table/Data: The number of data pages that are logically read from the buffer pool")
286 },
287 {
288 _T("DB2.Table.Data.PhysicalReads(*)"), GetParameter, _D(DCI_DATA_P_READS),
289 DCI_DT_INT64, _T("DB2/Table/Data: The number of data pages that are physically read")
290 },
291 {
292 _T("DB2.Table.Data.Gbp.LogicalReads(*)"), GetParameter, _D(DCI_DATA_GBP_L_READS),
293 DCI_DT_INT64, _T("DB2/Table/Data/Gbp: The number of times that a group buffer pool (GBP) page is requested from the GBP")
294 },
295 {
296 _T("DB2.Table.Data.Gbp.PhysicalReads(*)"), GetParameter, _D(DCI_DATA_GBP_P_READS),
297 DCI_DT_INT64,
298 _T("DB2/Table/Data/Gbp: The number of times that a group buffer pool (GBP) page is read into the local buffer pool (LBP)")
299 },
300 {
301 _T("DB2.Table.Data.Gbp.InvalidPages(*)"), GetParameter, _D(DCI_DATA_GBP_INVALID_PAGES),
302 DCI_DT_INT64, _T("DB2/Table/Data/Gbp: The number of times that a group buffer pool (GBP) page is requested from the GBP")
303 _T(" when the version stored in the local buffer pool (LBP) is invalid")
304 },
305 {
306 _T("DB2.Table.Data.Lbp.PagesFound(*)"), GetParameter, _D(DCI_DATA_LBP_PAGES_FOUND),
307 DCI_DT_INT64, _T("DB2/Table/Data/Lbp: The number of times that a data page is present in the local buffer pool (LBP)")
308 },
309 {
310 _T("DB2.Table.Data.Lbp.IndepPagesFound(*)"), GetParameter, _D(DCI_DATA_GBP_INDEP_PAGES_FOUND_IN_LBP),
311 DCI_DT_INT64,
312 _T("DB2/Table/Data/Lbp: The number of group buffer pool (GBP) independent pages found in a local buffer pool (LBP)")
313 },
314 {
315 _T("DB2.Table.Xda.LogicalReads(*)"), GetParameter, _D(DCI_XDA_L_READS),
316 DCI_DT_INT64,
317 _T("DB2/Table/Xda: The number of data pages for XML storage objects (XDA) that are logically read from the buffer pool")
318 },
319 {
320 _T("DB2.Table.Xda.PhysicalReads(*)"), GetParameter, _D(DCI_XDA_P_READS),
321 DCI_DT_INT64, _T("DB2/Table/Xda: The number of data pages for XML storage objects (XDA) that are physically read")
322 },
323 {
324 _T("DB2.Table.Xda.Gbp.LogicalReads(*)"), GetParameter, _D(DCI_XDA_GBP_L_READS),
325 DCI_DT_INT64, _T("DB2/Table/Xda/Gbp: The number of times that a data page for an XML storage object (XDA) is requested")
326 _T(" from the group buffer pool (GBP)")
327 },
328 {
329 _T("DB2.Table.Xda.Gbp.PhysicalReads(*)"), GetParameter, _D(DCI_XDA_GBP_P_READS),
330 DCI_DT_INT64, _T("DB2/Table/Xda/Gbp: The number of times that a group buffer pool (GBP) dependent data page for an XML")
331 _T(" storage object (XDA) is read into the local buffer pool (LBP)")
332 },
333 {
334 _T("DB2.Table.Xda.Gbp.InvalidPages(*)"), GetParameter, _D(DCI_XDA_GBP_INVALID_PAGES),
335 DCI_DT_INT64, _T("DB2/Table/Xda/Gbp: The number of times that a page for an XML storage objects (XDA) is requested from the")
336 _T(" group buffer pool (GBP) because the version in the local buffer pool (LBP) is invalid")
337 },
338 {
339 _T("DB2.Table.Xda.Lbp.PagesFound(*)"), GetParameter, _D(DCI_XDA_LBP_PAGES_FOUND),
340 DCI_DT_INT64, _T("DB2/Table/Xda/Lbp: The number of times that an XML storage objects (XDA) page is present in the local")
341 _T(" buffer pool (LBP)")
342 },
343 {
344 _T("DB2.Table.Xda.Gbp.IndepPagesFound(*)"), GetParameter, _D(DCI_XDA_GBP_INDEP_PAGES_FOUND_IN_LBP),
345 DCI_DT_INT64, _T("DB2/Table/Xda/Gbp: The number of group buffer pool (GBP) independent XML storage object (XDA) pages found")
346 _T(" in the local buffer pool (LBP)")
347 },
348 {
349 _T("DB2.Table.DictNum(*)"), GetParameter, _D(DCI_NUM_PAGE_DICT_BUILT),
350 DCI_DT_INT64, _T("DB2/Table: The number of page-level compression dictionaries created or recreated")
351 },
352 {
353 _T("DB2.Table.StatsRowsModified(*)"), GetParameter, _D(DCI_STATS_ROWS_MODIFIED),
354 DCI_DT_INT64, _T("DB2/Table: The number of rows modified since the last RUNSTATS")
355 },
356 {
357 _T("DB2.Table.ColObjectLogicalPages(*)"), GetParameter, _D(DCI_COL_OBJECT_L_PAGES),
358 DCI_DT_INT64, _T("DB2/Table: The number of logical pages used on disk by column-organized data")
359 },
360 {
361 _T("DB2.Table.Organization.Rows(*)"), GetParameter, _D(DCI_ORGANIZATION_ROWS),
362 DCI_DT_INT, _T("DB2/Table/Organization: The number of tables with row-organized data")
363 },
364 {
365 _T("DB2.Table.Organization.Cols(*)"), GetParameter, _D(DCI_ORGANIZATION_COLS),
366 DCI_DT_INT, _T("DB2/Table/Organization: The number of tables with column-organized data")
367 },
368 {
369 _T("DB2.Table.Col.LogicalReads(*)"), GetParameter, _D(DCI_COL_L_READS),
370 DCI_DT_INT, _T("DB2/Table/Col: The number of column-organized pages that are logically read from the buffer pool")
371 },
372 {
373 _T("DB2.Table.Col.PhysicalReads(*)"), GetParameter, _D(DCI_COL_P_READS),
374 DCI_DT_INT, _T("DB2/Table/Col: The number of column-organized pages that are physically read")
375 },
376 {
377 _T("DB2.Table.Col.Gbp.LogicalReads(*)"), GetParameter, _D(DCI_COL_GBP_L_READS),
378 DCI_DT_INT, _T("DB2/Table/Col/Gbp: The number of times that a group buffer pool (GBP) dependent column-organized page")
379 _T(" is requested from the GBP")
380 },
381 {
382 _T("DB2.Table.Col.Gbp.PhysicalReads(*)"), GetParameter, _D(DCI_COL_GBP_P_READS),
383 DCI_DT_INT, _T("DB2/Table/Col/Gbp: The number of times that a group buffer pool (GBP) dependent column-organized page")
384 _T(" is read into the local buffer pool (LBP) from disk")
385 },
386 {
387 _T("DB2.Table.Col.Gbp.InvalidPages(*)"), GetParameter, _D(DCI_COL_GBP_INVALID_PAGES),
388 DCI_DT_INT, _T("DB2/Table/Col/Gbp: The number of times that a column-organized page is requested from the group buffer pool")
389 _T(" (GBP) when the page in the local buffer pool (LBP) is invalid")
390 },
391 {
392 _T("DB2.Table.Col.Lbp.PagesFound(*)"), GetParameter, _D(DCI_COL_LBP_PAGES_FOUND),
393 DCI_DT_INT, _T("DB2/Table/Col/Lbp: The number of times that a column-organized page is present in")
394 _T(" the local buffer pool (LBP)")
395 },
396 {
397 _T("DB2.Table.Col.Gbp.IndepPagesFound(*)"), GetParameter, _D(DCI_COL_GBP_INDEP_PAGES_FOUND_IN_LBP),
398 DCI_DT_INT, _T("DB2/Table/Col/Gbp: The number of group buffer pool (GBP) independent column-organized pages found in")
399 _T(" the local buffer pool (LBP)")
400 },
401 {
402 _T("DB2.Table.ColsReferenced(*)"), GetParameter, _D(DCI_NUM_COL_REFS),
403 DCI_DT_INT, _T("DB2/Table: The number of columns referenced during the execution of a section for an SQL statement")
404 },
405 {
406 _T("DB2.Table.SectionExecutions(*)"), GetParameter, _D(DCI_SECTION_EXEC_WITH_COL_REFS),
407 DCI_DT_INT, _T("DB2/Table: The number of section executions that referenced columns in tables using a scan")
408 }
409 };
410
411 static NETXMS_SUBAGENT_INFO m_agentInfo =
412 {
413 NETXMS_SUBAGENT_INFO_MAGIC,
414 SUBAGENT_NAME,
415 NETXMS_VERSION_STRING,
416 DB2Init, DB2Shutdown, DB2CommandHandler,
417 (sizeof(m_agentParams) / sizeof(NETXMS_SUBAGENT_PARAM)), m_agentParams,
418 0, NULL,
419 0, NULL,
420 0, NULL,
421 0, NULL
422 };
423
424 static QUERY g_queries[] =
425 {
426 { { DCI_DBMS_VERSION }, _T("SELECT service_level FROM TABLE (sysproc.env_get_inst_info())") },
427 { { DCI_NUM_AVAILABLE }, _T("SELECT count(available) FROM sysibmadm.admintabinfo WHERE available = 'Y'") },
428 { { DCI_NUM_UNAVAILABLE }, _T("SELECT count(available) FROM sysibmadm.admintabinfo WHERE available = 'N'") },
429 {
430 {
431 DCI_DATA_L_SIZE, DCI_DATA_P_SIZE, DCI_INDEX_L_SIZE, DCI_INDEX_P_SIZE, DCI_LONG_L_SIZE, DCI_LONG_P_SIZE,
432 DCI_LOB_L_SIZE, DCI_LOB_P_SIZE, DCI_XML_L_SIZE, DCI_XML_P_SIZE, DCI_DICTIONARY_SIZE, DCI_NUM_REORG_REC_ALTERS
433 },
434 _T("SELECT sum(data_object_l_size), sum(data_object_p_size), sum(index_object_l_size), sum(index_object_p_size),")
435 _T("sum(long_object_l_size), sum(long_object_p_size), sum(lob_object_l_size), sum(lob_object_p_size),")
436 _T("sum(xml_object_l_size), sum(xml_object_p_size), sum(dictionary_size), sum(num_reorg_rec_alters) ")
437 _T("FROM sysibmadm.admintabinfo")
438 },
439 { { DCI_INDEX_TYPE1 }, _T("SELECT count(index_type) FROM sysibmadm.admintabinfo WHERE index_type = 1") },
440 { { DCI_INDEX_TYPE2 }, _T("SELECT count(index_type) FROM sysibmadm.admintabinfo WHERE index_type = 2") },
441 { { DCI_REORG_PENDING }, _T("SELECT count(reorg_pending) FROM sysibmadm.admintabinfo WHERE reorg_pending = 'Y'") },
442 {
443 { DCI_REORG_ABORTED },
444 _T("SELECT count(inplace_reorg_status) FROM sysibmadm.admintabinfo WHERE inplace_reorg_status = 'ABORTED'") },
445 {
446 { DCI_REORG_EXECUTING },
447 _T("SELECT count(inplace_reorg_status) FROM sysibmadm.admintabinfo WHERE inplace_reorg_status = 'EXECUTING'")
448 },
449 {
450 { DCI_REORG_PAUSED },
451 _T("SELECT count(inplace_reorg_status) FROM sysibmadm.admintabinfo WHERE inplace_reorg_status = 'PAUSED'")
452 },
453 {
454 { DCI_REORG_NULL },
455 _T("SELECT count(inplace_reorg_status) FROM sysibmadm.admintabinfo WHERE inplace_reorg_status = 'NULL'")
456 },
457 { { DCI_LOAD_IN_PROGRESS }, _T("SELECT count(load_status) FROM sysibmadm.admintabinfo WHERE load_status = 'IN_PROGRESS'") },
458 { { DCI_LOAD_PENDING }, _T("SELECT count(load_status) FROM sysibmadm.admintabinfo WHERE load_status = 'PENDING'") },
459 { { DCI_LOAD_NULL }, _T("SELECT count(load_status) FROM sysibmadm.admintabinfo WHERE load_status = 'NULL'") },
460 { { DCI_ACCESS_RO }, _T("SELECT count(read_access_only) FROM sysibmadm.admintabinfo WHERE read_access_only = 'Y'") },
461 { { DCI_NO_LOAD_RESTART }, _T("SELECT count(no_load_restart) FROM sysibmadm.admintabinfo WHERE no_load_restart = 'Y'") },
462 {
463 { DCI_INDEX_REQUIRE_REBUILD },
464 _T("SELECT count(indexes_require_rebuild) FROM sysibmadm.admintabinfo WHERE indexes_require_rebuild = 'Y'")
465 },
466 { { DCI_LARGE_RIDS }, _T("SELECT count(large_rids) FROM sysibmadm.admintabinfo WHERE large_rids = 'Y'") },
467 { { DCI_NO_LARGE_RIDS }, _T("SELECT count(large_rids) FROM sysibmadm.admintabinfo WHERE large_rids = 'N'") },
468 { { DCI_LARGE_RIDS_PENDING }, _T("SELECT count(large_rids) FROM sysibmadm.admintabinfo WHERE large_rids = 'P'") },
469 { { DCI_LARGE_SLOTS }, _T("SELECT count(large_slots) FROM sysibmadm.admintabinfo WHERE large_slots = 'Y'") },
470 { { DCI_NO_LARGE_SLOTS }, _T("SELECT count(large_slots) FROM sysibmadm.admintabinfo WHERE large_slots = 'N'") },
471 { { DCI_LARGE_SLOTS_PENDING }, _T("SELECT count(large_slots) FROM sysibmadm.admintabinfo WHERE large_slots = 'P'") },
472 {
473 {
474 DCI_TABLE_SCANS, DCI_ROWS_READ, DCI_ROWS_INSERTED, DCI_ROWS_UPDATED, DCI_ROWS_DELETED, DCI_OVERFLOW_ACCESSES,
475 DCI_OVERFLOW_CREATES, DCI_PAGE_REORGS, DCI_DATA_L_PAGES, DCI_LOB_L_PAGES, DCI_LONG_L_PAGES, DCI_INDEX_L_PAGES,
476 DCI_XDA_L_PAGES, DCI_NO_CHANGE_UPDATES, DCI_LOCK_WAIT_TIME, DCI_LOCK_WAIT_TIME_GLOBAL, DCI_LOCK_WAITS,
477 DCI_LOCK_WAITS_GLOBAL, DCI_LOCK_ESCALS, DCI_LOCK_ESCALS_GLOBAL, DCI_SHARING_LOCKWAIT_COUNT, DCI_SHARING_LOCKWAIT_TIME,
478 DCI_DIRECT_WRITES, DCI_DIRECT_WRITE_REQS, DCI_DIRECT_READS, DCI_DIRECT_READ_REQS, DCI_DATA_L_READS, DCI_DATA_P_READS,
479 DCI_DATA_GBP_L_READS, DCI_DATA_GBP_P_READS, DCI_DATA_GBP_INVALID_PAGES, DCI_DATA_LBP_PAGES_FOUND,
480 DCI_DATA_GBP_INDEP_PAGES_FOUND_IN_LBP, DCI_XDA_L_READS, DCI_XDA_P_READS, DCI_XDA_GBP_L_READS, DCI_XDA_GBP_P_READS,
481 DCI_XDA_GBP_INVALID_PAGES, DCI_XDA_LBP_PAGES_FOUND, DCI_XDA_GBP_INDEP_PAGES_FOUND_IN_LBP, DCI_NUM_PAGE_DICT_BUILT,
482 DCI_STATS_ROWS_MODIFIED, DCI_RTS_ROWS_MODIFIED, DCI_COL_OBJECT_L_PAGES, DCI_COL_L_READS, DCI_COL_P_READS,
483 DCI_COL_GBP_L_READS, DCI_COL_GBP_P_READS, DCI_COL_GBP_INVALID_PAGES, DCI_COL_LBP_PAGES_FOUND,
484 DCI_COL_GBP_INDEP_PAGES_FOUND_IN_LBP, DCI_NUM_COL_REFS, DCI_SECTION_EXEC_WITH_COL_REFS
485 },
486 _T("SELECT sum(table_scans), sum(rows_read), sum(rows_inserted), sum(rows_updated), sum(rows_deleted),")
487 _T("sum(overflow_accesses), sum(overflow_creates), sum(page_reorgs), sum(data_object_l_pages), sum(lob_object_l_pages),")
488 _T("sum(long_object_l_pages), sum(index_object_l_pages), sum(xda_object_l_pages), sum(no_change_updates),")
489 _T("sum(lock_wait_time), sum(lock_wait_time_global), sum(lock_waits), sum(lock_waits_global), sum(lock_escals),")
490 _T("sum(lock_escals_global), sum(data_sharing_remote_lockwait_count), sum(data_sharing_remote_lockwait_time),")
491 _T("sum(direct_writes), sum(direct_write_reqs), sum(direct_reads), sum(direct_read_reqs), sum(object_data_l_reads),")
492 _T("sum(object_data_p_reads), sum(object_data_gbp_l_reads), sum(object_data_gbp_p_reads),")
493 _T("sum(object_data_gbp_invalid_pages), sum(object_data_lbp_pages_found), sum(object_data_gbp_indep_pages_found_in_lbp),")
494 _T("sum(object_xda_l_reads), sum(object_xda_p_reads), sum(object_xda_gbp_l_reads), sum(object_xda_gbp_p_reads),")
495 _T("sum(object_xda_gbp_invalid_pages), sum(object_xda_lbp_pages_found), sum(object_xda_gbp_indep_pages_found_in_lbp),")
496 _T("sum(num_page_dict_built), sum(stats_rows_modified), sum(rts_rows_modified), sum(col_object_l_pages),")
497 _T("sum(object_col_l_reads), sum(object_col_p_reads), sum(object_col_gbp_l_reads), sum(object_col_gbp_p_reads),")
498 _T("sum(object_col_gbp_invalid_pages), sum(object_col_lbp_pages_found), sum(object_col_gbp_indep_pages_found_in_lbp),")
499 _T("sum(num_columns_referenced), sum(section_exec_with_col_references) FROM TABLE (mon_get_table('', '', -2))")
500 },
501 { { DCI_STATE_SHARED }, _T("SELECT count(*) FROM TABLE (mon_get_table('', '', -2)) WHERE data_sharing_state = 'SHARED'") },
502 {
503 { DCI_STATE_NOT_SHARED },
504 _T("SELECT count(*) FROM TABLE (mon_get_table('', '', -2)) WHERE data_sharing_state = 'NOT_SHARED'")
505 },
506 {
507 { DCI_STATE_SHARED_BECOMING },
508 _T("SELECT count(*) FROM TABLE (mon_get_table('', '', -2)) WHERE data_sharing_state = 'BECOMING_SHARED'")
509 },
510 {
511 { DCI_STATE_NOT_SHARED_BECOMING },
512 _T("SELECT count(*) FROM TABLE (mon_get_table('', '', -2)) WHERE data_sharing_state = 'BECOMING_NOT_SHARED'")
513 },
514 { { DCI_ORGANIZATION_ROWS }, _T("SELECT count(*) FROM TABLE (mon_get_table('', '', -2)) WHERE tab_organization = 'R'") },
515 { { DCI_ORGANIZATION_COLS }, _T("SELECT count(*) FROM TABLE (mon_get_table('', '', -2)) WHERE tab_organization = 'C'") },
516 { { DCI_NULL }, _T("\0") }
517 };
518
519 static BOOL DB2Init(Config* config)
520 {
521 AgentWriteDebugLog(7, _T("%s: initializing"), SUBAGENT_NAME);
522
523 #ifdef _WIN32
524 g_drvHandle = DBLoadDriver(_T("db2.ddr"), NULL, TRUE, NULL, NULL);
525 #else
526 g_drvHandle = DBLoadDriver(LIBDIR _T("/netxms/dbdrv/db2.ddr"), NULL, TRUE, NULL, NULL);
527 #endif
528
529 if (g_drvHandle == NULL)
530 {
531 AgentWriteLog(EVENTLOG_ERROR_TYPE, _T("%s: failed to load the database driver"), SUBAGENT_NAME);
532 return FALSE;
533 }
534
535 AgentWriteDebugLog(7, _T("%s: loaded the database driver"), SUBAGENT_NAME);
536
537 ConfigEntry* db2IniEntry = config->getEntry(_T("/db2"));
538
539 if (db2IniEntry == NULL)
540 {
541 AgentWriteLog(EVENTLOG_ERROR_TYPE, _T("%s: no entries found in the configuration file"), SUBAGENT_NAME);
542 return FALSE;
543 }
544
545 PDB2_INFO* arrDb2Info;
546 int numOfPossibleThreads = 0;
547
548 ConfigEntry* xmlFile = db2IniEntry->findEntry(_T("ConfigFile"));
549 if (xmlFile == NULL)
550 {
551 AgentWriteDebugLog(7, _T("%s: processing configuration entries in section '%s'"), SUBAGENT_NAME, db2IniEntry->getName());
552
553 const PDB2_INFO db2Info = GetConfigs(config, db2IniEntry, _T("db2"));
554 if (db2Info == NULL)
555 {
556 return FALSE;
557 }
558
559 db2Info->db2Id = 1;
560
561 g_numOfThreads = 1;
562 arrDb2Info = new PDB2_INFO[1];
563 arrDb2Info[0] = db2Info;
564 }
565 else
566 {
567 const TCHAR* pathToXml = xmlFile->getValue();
568 AgentWriteDebugLog(7, _T("%s: processing configuration file '%s'"), SUBAGENT_NAME, pathToXml);
569
570 if (!config->loadXmlConfig(pathToXml))
571 {
572 AgentWriteLog(EVENTLOG_ERROR_TYPE, _T("%s: '%s' is not a valid configuration file"), SUBAGENT_NAME, pathToXml);
573 return FALSE;
574 }
575
576 ConfigEntry* db2SubXmlEntry = config->getEntry(_T("/db2sub"));
577 if (db2SubXmlEntry == NULL)
578 {
579 AgentWriteLog(EVENTLOG_ERROR_TYPE, _T("%s: '%s' doesn't contain the db2 configuration entry"), SUBAGENT_NAME, pathToXml);
580 return FALSE;
581 }
582
583 ConfigEntryList* db2SubXmlSubEntries = db2SubXmlEntry->getSubEntries(_T("db2#*"));
584 numOfPossibleThreads = db2SubXmlSubEntries->getSize();
585 AgentWriteDebugLog(7, _T("%s: '%s' loaded with number of db2 entries: %d"), SUBAGENT_NAME, pathToXml, numOfPossibleThreads);
586 arrDb2Info = new PDB2_INFO[numOfPossibleThreads];
587 TCHAR entryName[STR_MAX];
588
589 for(int i = 0; i < numOfPossibleThreads; i++)
590 {
591 ConfigEntry* entry = db2SubXmlSubEntries->getEntry(i);
592 _tcscpy(entryName, _T("db2sub/"));
593 _tcscat_s(entryName, STR_MAX, entry->getName());
594
595 const PDB2_INFO db2Info = GetConfigs(config, entry, entryName);
596 if (db2Info == NULL)
597 {
598 continue;
599 }
600
601 arrDb2Info[g_numOfThreads] = db2Info;
602 g_numOfThreads++;
603 }
604 }
605
606 if(g_numOfThreads > 0)
607 {
608 AgentWriteDebugLog(7, _T("%s: loaded %d configuration section(s)"), SUBAGENT_NAME, g_numOfThreads);
609 g_threads = new THREAD_INFO[g_numOfThreads];
610 g_sdownCondition = ConditionCreate(TRUE);
611 }
612
613 for(int i = 0; i < g_numOfThreads; i++)
614 {
615 //g_threads[i] = new THREAD_INFO;
616 g_threads[i].mutex = MutexCreate();
617 g_threads[i].db2Info = arrDb2Info[i];
618 g_threads[i].threadHandle = ThreadCreateEx(RunMonitorThread, 0, (void*) &g_threads[i]);
619 }
620
621 delete[] arrDb2Info;
622
623 if (g_numOfThreads > 0)
624 {
625 AgentWriteDebugLog(7, _T("%s: starting with %d query thread(s)"), SUBAGENT_NAME, g_numOfThreads);
626 return TRUE;
627 }
628
629 return FALSE;
630 }
631
632 static void DB2Shutdown()
633 {
634 AgentWriteDebugLog(9, _T("%s: terminating"), SUBAGENT_NAME);
635 ConditionSet(g_sdownCondition);
636
637 for(int i = 0; i < g_numOfThreads; i++)
638 {
639 ThreadJoin(g_threads[i].threadHandle);
640 MutexDestroy(g_threads[i].mutex);
641 delete g_threads[i].db2Info;
642 }
643 delete[] g_threads;
644
645 DBUnloadDriver(g_drvHandle);
646 ConditionDestroy(g_sdownCondition);
647
648 g_drvHandle = NULL;
649 g_sdownCondition = NULL;
650 g_threads = NULL;
651
652 AgentWriteDebugLog(7, _T("%s: terminated"), SUBAGENT_NAME);
653 }
654
655 static BOOL DB2CommandHandler(UINT32 dwCommand, CSCPMessage* pRequest, CSCPMessage* pResponse, void* session)
656 {
657 return FALSE;
658 }
659
660 static THREAD_RESULT THREAD_CALL RunMonitorThread(void* info)
661 {
662 PTHREAD_INFO threadInfo = (PTHREAD_INFO) info;
663 PDB2_INFO db2Info = threadInfo->db2Info;
664 DB_HANDLE dbHandle = NULL;
665 TCHAR connectError[DBDRV_MAX_ERROR_TEXT];
666 DWORD reconnectInterval = (DWORD) db2Info->db2ReconnectInterval;
667
668 while(TRUE)
669 {
670 dbHandle = DBConnect(
671 g_drvHandle, db2Info->db2DbAlias, db2Info->db2DbName, db2Info->db2UName, db2Info->db2UPass, NULL, connectError);
672
673 if (dbHandle == NULL)
674 {
675 AgentWriteLog(
676 EVENTLOG_ERROR_TYPE,
677 _T("%s: failed to connect to the database \"%s\" (%s), reconnecting in %ds"),
678 SUBAGENT_NAME, db2Info->db2DbName, connectError, reconnectInterval);
679
680 if (ConditionWait(g_sdownCondition, (reconnectInterval * 1000)))
681 {
682 break;
683 }
684 else
685 {
686 continue;
687 }
688 }
689
690 threadInfo->hDb = dbHandle;
691
692 AgentWriteLog(EVENTLOG_INFORMATION_TYPE, _T("%s: connected to database '%s'"), SUBAGENT_NAME, db2Info->db2DbName);
693
694 if (PerformQueries(threadInfo))
695 {
696 break;
697 }
698 }
699
700 if(dbHandle != NULL)
701 {
702 DBDisconnect(dbHandle);
703 }
704
705 return THREAD_OK;
706 }
707
708 static BOOL PerformQueries(const PTHREAD_INFO threadInfo)
709 {
710 PDB2_INFO db2Info = threadInfo->db2Info;
711 DWORD queryInterval = (DWORD) db2Info->db2QueryInterval;
712
713 while(TRUE)
714 {
715 MutexLock(threadInfo->mutex);
716
717 DB_RESULT hResult;
718 Dci* dciList;
719
720 int queryId = 0;
721 while(*(dciList = g_queries[queryId].dciList) != DCI_NULL)
722 {
723 hResult = DBSelect(threadInfo->hDb, g_queries[queryId].query);
724
725 if (hResult == NULL)
726 {
727 AgentWriteLog(EVENTLOG_ERROR_TYPE, _T("%s: query '%s' failed"), SUBAGENT_NAME, g_queries[queryId].query);
728 queryId++;
729 continue;
730 }
731
732 int numCols = DBGetColumnCount(hResult);
733
734 for(int i = 0; i < numCols; i++)
735 {
736 TCHAR* dciVal = threadInfo->db2Params[dciList[i]];
737
738 DBGetField(hResult, 0, i, dciVal, STR_MAX);
739
740 AgentWriteDebugLog(9, _T("%s: got '%s'"), SUBAGENT_NAME, dciVal);
741 }
742
743 DBFreeResult(hResult);
744
745 queryId++;
746 }
747
748 MutexUnlock(threadInfo->mutex);
749
750 if (ConditionWait(g_sdownCondition, queryInterval * 1000))
751 {
752 break;
753 }
754 }
755
756 return TRUE;
757 }
758
759 static LONG GetParameter(const TCHAR* parameter, const TCHAR* arg, TCHAR* value)
760 {
761 Dci dci = StringToDci(arg);
762
763 if (dci == DCI_NULL)
764 {
765 return SYSINFO_RC_UNSUPPORTED;
766 }
767
768 TCHAR dbIdString[DB_ID_DIGITS_MAX];
769 unsigned long dbId;
770
771 AgentGetParameterArg(parameter, 1, dbIdString, DB_ID_DIGITS_MAX);
772 dbId = _tcstoul(dbIdString, NULL, 0);
773
774 if (dbId == 0)
775 {
776 AgentWriteDebugLog(7, _T("%s: id '%s' is invalid"), SUBAGENT_NAME, dbIdString);
777 return SYSINFO_RC_UNSUPPORTED;
778 }
779
780 THREAD_INFO threadInfo;
781
782 for(int i = 0; i < g_numOfThreads; i++)
783 {
784 if (g_threads[i].db2Info->db2Id == dbId)
785 {
786 threadInfo = g_threads[i];
787 break;
788 }
789
790 AgentWriteDebugLog(7, _T("%s: no database with id '%d' found"), SUBAGENT_NAME, dbId);
791 return SYSINFO_RC_UNSUPPORTED;
792 }
793
794 ret_string(value, threadInfo.db2Params[dci]);
795
796 return SYSINFO_RC_SUCCESS;
797 }
798
799 static const PDB2_INFO GetConfigs(Config* config, ConfigEntry* configEntry, const TCHAR* entryName)
800 {
801 ConfigEntryList* entryList = configEntry->getSubEntries(_T("*"));
802
803 if (entryList->getSize() == 0)
804 {
805 AgentWriteLog(EVENTLOG_ERROR_TYPE, _T("%s: entry '%s' contained no values"), SUBAGENT_NAME, entryName);
806 return NULL;
807 }
808
809 const PDB2_INFO db2Info = new DB2_INFO();
810 BOOL noErr = TRUE;
811 TCHAR dbPassEncrypted[MAX_DB_STRING] = _T("");
812
813 db2Info->db2Id = configEntry->getId();
814
815 NX_CFG_TEMPLATE cfgTemplate[] =
816 {
817 { _T("DBName"), CT_STRING, 0, 0, DB2_DB_MAX_NAME, 0, db2Info->db2DbName },
818 { _T("DBAlias"), CT_STRING, 0, 0, DB2_DB_MAX_NAME, 0, db2Info->db2DbAlias },
819 { _T("UserName"), CT_STRING, 0, 0, DB2_MAX_USER_NAME, 0, db2Info->db2UName },
820 { _T("Password"), CT_STRING, 0, 0, STR_MAX, 0, db2Info->db2UPass },
821 { _T("EncryptedPassword"), CT_STRING, 0, 0, MAX_DB_STRING, 0, dbPassEncrypted },
822 { _T("ReconnectInterval"), CT_LONG, 0, 0, sizeof(LONG), 0, &db2Info->db2ReconnectInterval },
823 { _T("QueryInterval"), CT_LONG, 0, 0, sizeof(LONG), 0, &db2Info->db2QueryInterval },
824 { _T(""), CT_END_OF_LIST, 0, 0, 0, 0, NULL }
825 };
826
827 if (!config->parseTemplate(entryName, cfgTemplate))
828 {
829 AgentWriteLog(EVENTLOG_ERROR_TYPE, _T("%s: failed to process entry '%s'"), SUBAGENT_NAME, entryName);
830 noErr = FALSE;
831 }
832
833 if (*dbPassEncrypted != '\0')
834 {
835 noErr = DecryptPassword(db2Info->db2UName, dbPassEncrypted, db2Info->db2UPass);
836 if(!noErr)
837 AgentWriteDebugLog(EVENTLOG_ERROR_TYPE, _T("%s: failed to decrypt password"), SUBAGENT_NAME);
838 }
839
840 if (noErr)
841 {
842 if (*db2Info->db2DbName == '\0')
843 {
844 AgentWriteDebugLog(7, _T("%s: no DBName in '%s'"), SUBAGENT_NAME, entryName);
845 noErr = FALSE;
846 }
847 else
848 {
849 AgentWriteDebugLog(9, _T("%s: got DBName entry with value '%s'"), SUBAGENT_NAME, db2Info->db2DbName);
850 }
851
852 if (*db2Info->db2DbAlias == '\0')
853 {
854 AgentWriteDebugLog(7, _T("%s: no DBAlias in '%s'"), SUBAGENT_NAME, entryName);
855 noErr = FALSE;
856 }
857 else
858 {
859 AgentWriteDebugLog(9, _T("%s: got DBAlias entry with value '%s'"), SUBAGENT_NAME, db2Info->db2DbAlias);
860 }
861
862 if (*db2Info->db2UName == '\0')
863 {
864 AgentWriteDebugLog(7, _T("%s: no UserName in '%s'"), SUBAGENT_NAME, entryName);
865 noErr = FALSE;
866 }
867 else
868 {
869 AgentWriteDebugLog(9, _T("%s: got UserName entry with value '%s'"), SUBAGENT_NAME, db2Info->db2UName);
870 }
871
872 if (*db2Info->db2UPass == '\0')
873 {
874 AgentWriteDebugLog(7, _T("%s: no Password in '%s'"), SUBAGENT_NAME, entryName);
875 noErr = FALSE;
876 }
877 else
878 {
879 AgentWriteDebugLog(9, _T("%s: got Password entry."), SUBAGENT_NAME);
880 }
881
882 if (db2Info->db2ReconnectInterval == 0)
883 {
884 db2Info->db2ReconnectInterval = INTERVAL_RECONNECT_SECONDS;
885 }
886
887 if (db2Info->db2QueryInterval == 0)
888 {
889 db2Info->db2QueryInterval = INTERVAL_QUERY_SECONDS;
890 }
891 }
892
893 if (!noErr)
894 {
895 AgentWriteLog(EVENTLOG_ERROR_TYPE, _T("%s: failed to process entry '%s'"), SUBAGENT_NAME, entryName);
896 delete db2Info;
897 return NULL;
898 }
899
900 return db2Info;
901 }
902
903 DECLARE_SUBAGENT_ENTRY_POINT(DB2)
904 {
905 AgentWriteDebugLog(7, _T("%s: started"), SUBAGENT_NAME);
906 *ppInfo = &m_agentInfo;
907 return TRUE;
908 }
909
910 /**
911 * DLL entry point
912 */
913
914 #ifdef _WIN32
915
916 BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved)
917 {
918 if (fdwReason == DLL_PROCESS_ATTACH)
919 {
920 DisableThreadLibraryCalls(hinstDll);
921 }
922 return TRUE;
923 }
924
925 #endif