Minor corrections.
[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);
554 if (db2Info == NULL)
555 {
556 return FALSE;
557 }
558
559 g_numOfThreads = 1;
560 arrDb2Info = new PDB2_INFO[1];
561 arrDb2Info[0] = db2Info;
562 }
563 else
564 {
565 const TCHAR* pathToXml = xmlFile->getValue();
566 AgentWriteDebugLog(7, _T("%s: processing configuration file '%s'"), SUBAGENT_NAME, pathToXml);
567
568 if (!config->loadXmlConfig(pathToXml))
569 {
570 AgentWriteLog(EVENTLOG_ERROR_TYPE, _T("%s: '%s' is not a valid configuration file"), SUBAGENT_NAME, pathToXml);
571 return FALSE;
572 }
573
574 ConfigEntry* db2SubXmlEntry = config->getEntry(_T("/db2sub"));
575 if (db2SubXmlEntry == NULL)
576 {
577 AgentWriteLog(EVENTLOG_ERROR_TYPE, _T("%s: '%s' doesn't contain the db2 configuration entry"), SUBAGENT_NAME, pathToXml);
578 return FALSE;
579 }
580
581 ConfigEntryList* db2SubXmlSubEntries = db2SubXmlEntry->getSubEntries(_T("db2#*"));
582 numOfPossibleThreads = db2SubXmlSubEntries->getSize();
583 AgentWriteDebugLog(7, _T("%s: '%s' loaded with number of db2 entries: %d"), SUBAGENT_NAME, pathToXml, numOfPossibleThreads);
584 arrDb2Info = new PDB2_INFO[numOfPossibleThreads];
585
586 for(int i = 0; i < numOfPossibleThreads; i++)
587 {
588 ConfigEntry* entry = db2SubXmlSubEntries->getEntry(i);
589 const PDB2_INFO db2Info = GetConfigs(config, entry);
590 if (db2Info == NULL)
591 {
592 continue;
593 }
594
595 arrDb2Info[g_numOfThreads] = db2Info;
596 g_numOfThreads++;
597 }
598 }
599
600 if(g_numOfThreads > 0)
601 {
602 AgentWriteDebugLog(7, _T("%s: loaded %d configuration section(s)"), SUBAGENT_NAME, g_numOfThreads);
603 g_threads = new THREAD_INFO[g_numOfThreads];
604 g_sdownCondition = ConditionCreate(TRUE);
605 }
606
607 for(int i = 0; i < g_numOfThreads; i++)
608 {
609 //g_threads[i] = new THREAD_INFO;
610 g_threads[i].mutex = MutexCreate();
611 g_threads[i].db2Info = arrDb2Info[i];
612 g_threads[i].threadHandle = ThreadCreateEx(RunMonitorThread, 0, (void*) &g_threads[i]);
613 }
614
615 delete[] arrDb2Info;
616
617 if (g_numOfThreads > 0)
618 {
619 AgentWriteDebugLog(7, _T("%s: starting with %d query thread(s)"), SUBAGENT_NAME, g_numOfThreads);
620 return TRUE;
621 }
622
623 return FALSE;
624 }
625
626 static void DB2Shutdown()
627 {
628 AgentWriteDebugLog(9, _T("%s: terminating"), SUBAGENT_NAME);
629 ConditionSet(g_sdownCondition);
630
631 for(int i = 0; i < g_numOfThreads; i++)
632 {
633 ThreadJoin(g_threads[i].threadHandle);
634 MutexDestroy(g_threads[i].mutex);
635 delete g_threads[i].db2Info;
636 }
637 delete[] g_threads;
638
639 DBUnloadDriver(g_drvHandle);
640 ConditionDestroy(g_sdownCondition);
641
642 g_drvHandle = NULL;
643 g_sdownCondition = NULL;
644 g_threads = NULL;
645
646 AgentWriteDebugLog(7, _T("%s: terminated"), SUBAGENT_NAME);
647 }
648
649 static BOOL DB2CommandHandler(UINT32 dwCommand, CSCPMessage* pRequest, CSCPMessage* pResponse, void* session)
650 {
651 return FALSE;
652 }
653
654 static THREAD_RESULT THREAD_CALL RunMonitorThread(void* info)
655 {
656 PTHREAD_INFO threadInfo = (PTHREAD_INFO) info;
657 PDB2_INFO db2Info = threadInfo->db2Info;
658 DB_HANDLE dbHandle = NULL;
659 TCHAR connectError[DBDRV_MAX_ERROR_TEXT];
660 DWORD reconnectInterval = (DWORD) db2Info->db2ReconnectInterval;
661
662 while(TRUE)
663 {
664 dbHandle = DBConnect(
665 g_drvHandle, db2Info->db2DbAlias, db2Info->db2DbName, db2Info->db2UName, db2Info->db2UPass, NULL, connectError);
666
667 if (dbHandle == NULL)
668 {
669 AgentWriteLog(
670 EVENTLOG_ERROR_TYPE,
671 _T("%s: failed to connect to the database \"%s\" (%s), reconnecting in %ds"),
672 SUBAGENT_NAME, db2Info->db2DbName, connectError, reconnectInterval);
673
674 if (ConditionWait(g_sdownCondition, (reconnectInterval * 1000)))
675 {
676 break;
677 }
678 else
679 {
680 continue;
681 }
682 }
683
684 threadInfo->hDb = dbHandle;
685
686 AgentWriteLog(EVENTLOG_INFORMATION_TYPE, _T("%s: connected to database '%s'"), SUBAGENT_NAME, db2Info->db2DbName);
687
688 if (PerformQueries(threadInfo))
689 {
690 break;
691 }
692 }
693
694 if(dbHandle != NULL)
695 {
696 DBDisconnect(dbHandle);
697 }
698
699 return THREAD_OK;
700 }
701
702 static BOOL PerformQueries(const PTHREAD_INFO threadInfo)
703 {
704 PDB2_INFO db2Info = threadInfo->db2Info;
705 DWORD queryInterval = (DWORD) db2Info->db2QueryInterval;
706
707 while(TRUE)
708 {
709 MutexLock(threadInfo->mutex);
710
711 DB_RESULT hResult;
712 Dci* dciList;
713
714 int queryId = 0;
715 while(*(dciList = g_queries[queryId].dciList) != DCI_NULL)
716 {
717 hResult = DBSelect(threadInfo->hDb, g_queries[queryId].query);
718
719 if (hResult == NULL)
720 {
721 AgentWriteLog(EVENTLOG_ERROR_TYPE, _T("%s: query '%s' failed"), SUBAGENT_NAME, g_queries[queryId].query);
722 queryId++;
723 continue;
724 }
725
726 int numCols = DBGetColumnCount(hResult);
727
728 for(int i = 0; i < numCols; i++)
729 {
730 TCHAR* dciVal = threadInfo->db2Params[dciList[i]];
731
732 DBGetField(hResult, 0, i, dciVal, STR_MAX);
733
734 AgentWriteDebugLog(9, _T("%s: got '%s'"), SUBAGENT_NAME, dciVal);
735 }
736
737 DBFreeResult(hResult);
738
739 queryId++;
740 }
741
742 MutexUnlock(threadInfo->mutex);
743
744 if (ConditionWait(g_sdownCondition, queryInterval * 1000))
745 {
746 break;
747 }
748 }
749
750 return TRUE;
751 }
752
753 static LONG GetParameter(const TCHAR* parameter, const TCHAR* arg, TCHAR* value)
754 {
755 Dci dci = StringToDci(arg);
756
757 if (dci == DCI_NULL)
758 {
759 return SYSINFO_RC_UNSUPPORTED;
760 }
761
762 TCHAR dbIdString[DB_ID_DIGITS_MAX];
763 unsigned long dbId;
764
765 AgentGetParameterArg(parameter, 1, dbIdString, DB_ID_DIGITS_MAX);
766 dbId = _tcstoul(dbIdString, NULL, 0);
767
768 if (dbId == 0)
769 {
770 AgentWriteDebugLog(7, _T("%s: id '%s' is invalid"), SUBAGENT_NAME, dbIdString);
771 return SYSINFO_RC_UNSUPPORTED;
772 }
773
774 THREAD_INFO threadInfo;
775
776 for(int i = 0; i < g_numOfThreads; i++)
777 {
778 if (g_threads[i].db2Info->db2Id == dbId)
779 {
780 threadInfo = g_threads[i];
781 break;
782 }
783
784 AgentWriteDebugLog(7, _T("%s: no database with id '%d' found"), SUBAGENT_NAME, dbId);
785 return SYSINFO_RC_UNSUPPORTED;
786 }
787
788 ret_string(value, threadInfo.db2Params[dci]);
789
790 return SYSINFO_RC_SUCCESS;
791 }
792
793 static const PDB2_INFO GetConfigs(Config* config, ConfigEntry* configEntry)
794 {
795 ConfigEntryList* entryList = configEntry->getSubEntries(_T("*"));
796 TCHAR entryName[STR_MAX] = _T("db2sub/");
797
798 _tcscat(entryName, configEntry->getName());
799
800 if (entryList->getSize() == 0)
801 {
802 AgentWriteLog(EVENTLOG_ERROR_TYPE, _T("%s: entry '%s' contained no values"), SUBAGENT_NAME, entryName);
803 return NULL;
804 }
805
806 const PDB2_INFO db2Info = new DB2_INFO();
807 BOOL noErr = TRUE;
808
809 db2Info->db2Id = configEntry->getId();
810
811 NX_CFG_TEMPLATE cfgTemplate[] =
812 {
813 { _T("DBName"), CT_STRING, 0, 0, DB2_DB_MAX_NAME, 0, db2Info->db2DbName },
814 { _T("DBAlias"), CT_STRING, 0, 0, DB2_DB_MAX_NAME, 0, db2Info->db2DbAlias },
815 { _T("UserName"), CT_STRING, 0, 0, DB2_MAX_USER_NAME, 0, db2Info->db2UName },
816 { _T("Password"), CT_STRING, 0, 0, STR_MAX, 0, db2Info->db2UPass },
817 { _T("ReconnectInterval"), CT_LONG, 0, 0, sizeof(LONG), 0, &(db2Info->db2ReconnectInterval) },
818 { _T("QueryInterval"), CT_LONG, 0, 0, sizeof(LONG), 0, &(db2Info->db2QueryInterval) },
819 { _T(""), CT_END_OF_LIST, 0, 0, 0, 0, NULL }
820 };
821
822 if (!config->parseTemplate(entryName, cfgTemplate))
823 {
824 AgentWriteLog(EVENTLOG_ERROR_TYPE, _T("%s: failed to process entry '%s'"), SUBAGENT_NAME, entryName);
825 noErr = FALSE;
826 }
827
828 if (noErr)
829 {
830 if (db2Info->db2DbName[0] == '\0')
831 {
832 AgentWriteDebugLog(7, _T("%s: no DBName in '%s'"), SUBAGENT_NAME, entryName);
833 noErr = FALSE;
834 }
835 else
836 {
837 AgentWriteDebugLog(9, _T("%s: got DBName entry with value '%s'"), SUBAGENT_NAME, db2Info->db2DbName);
838 }
839
840 if (db2Info->db2DbAlias[0] == '\0')
841 {
842 AgentWriteDebugLog(7, _T("%s: no DBAlias in '%s'"), SUBAGENT_NAME, entryName);
843 noErr = FALSE;
844 }
845 else
846 {
847 AgentWriteDebugLog(9, _T("%s: got DBAlias entry with value '%s'"), SUBAGENT_NAME, db2Info->db2DbAlias);
848 }
849
850 if (db2Info->db2UName[0] == '\0')
851 {
852 AgentWriteDebugLog(7, _T("%s: no UserName in '%s'"), SUBAGENT_NAME, entryName);
853 noErr = FALSE;
854 }
855 else
856 {
857 AgentWriteDebugLog(9, _T("%s: got UserName entry with value '%s'"), SUBAGENT_NAME, db2Info->db2UName);
858 }
859
860 if (db2Info->db2UPass[0] == '\0')
861 {
862 AgentWriteDebugLog(7, _T("%s: no Password in '%s'"), SUBAGENT_NAME, entryName);
863 noErr = FALSE;
864 }
865 else
866 {
867 AgentWriteDebugLog(9, _T("%s: got Password entry with value '%s'"), SUBAGENT_NAME, db2Info->db2UPass);
868 }
869
870 if (db2Info->db2ReconnectInterval == 0)
871 {
872 db2Info->db2ReconnectInterval = INTERVAL_RECONNECT_SECONDS;
873 }
874
875 if (db2Info->db2QueryInterval == 0)
876 {
877 db2Info->db2QueryInterval = INTERVAL_QUERY_SECONDS;
878 }
879 }
880
881 if (!noErr)
882 {
883 AgentWriteLog(EVENTLOG_ERROR_TYPE, _T("%s: failed to process entry '%s'"), SUBAGENT_NAME, entryName);
884 delete db2Info;
885 return NULL;
886 }
887
888 return db2Info;
889 }
890
891 DECLARE_SUBAGENT_ENTRY_POINT(DB2)
892 {
893 AgentWriteDebugLog(7, _T("%s: started"), SUBAGENT_NAME);
894 *ppInfo = &m_agentInfo;
895 return TRUE;
896 }
897
898 /**
899 * DLL entry point
900 */
901
902 #ifdef _WIN32
903
904 BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved)
905 {
906 if (fdwReason == DLL_PROCESS_ATTACH)
907 {
908 DisableThreadLibraryCalls(hinstDll);
909 }
910 return TRUE;
911 }
912
913 #endif