64ee24cf0d235306c03e9d5c555c501b3911c6bc
[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")
359 },
360 {
361 _T("DB2.Table.ColObjectLogicalPages(*)"), GetParameter, _D(DCI_COL_OBJECT_L_PAGES),
362 DCI_DT_INT64, _T("DB2/Table: The number of logical pages used on disk by column-organized data")
363 },
364 {
365 _T("DB2.Table.Organization.Rows(*)"), GetParameter, _D(DCI_ORGANIZATION_ROWS),
366 DCI_DT_INT, _T("DB2/Table/Organization: The number of tables with row-organized data")
367 },
368 {
369 _T("DB2.Table.Organization.Cols(*)"), GetParameter, _D(DCI_ORGANIZATION_COLS),
370 DCI_DT_INT, _T("DB2/Table/Organization: The number of tables with column-organized data")
371 },
372 {
373 _T("DB2.Table.Col.LogicalReads(*)"), GetParameter, _D(DCI_COL_L_READS),
374 DCI_DT_INT, _T("DB2/Table/Col: The number of column-organized pages that are logically read from the buffer pool")
375 },
376 {
377 _T("DB2.Table.Col.PhysicalReads(*)"), GetParameter, _D(DCI_COL_P_READS),
378 DCI_DT_INT, _T("DB2/Table/Col: The number of column-organized pages that are physically read")
379 },
380 {
381 _T("DB2.Table.Col.Gbp.LogicalReads(*)"), GetParameter, _D(DCI_COL_GBP_L_READS),
382 DCI_DT_INT, _T("DB2/Table/Col/Gbp: The number of times that a group buffer pool (GBP) dependent column-organized page")
383 _T(" is requested from the GBP")
384 },
385 {
386 _T("DB2.Table.Col.Gbp.PhysicalReads(*)"), GetParameter, _D(DCI_COL_GBP_P_READS),
387 DCI_DT_INT, _T("DB2/Table/Col/Gbp: The number of times that a group buffer pool (GBP) dependent column-organized page")
388 _T(" is read into the local buffer pool (LBP) from disk")
389 },
390 {
391 _T("DB2.Table.Col.Gbp.InvalidPages(*)"), GetParameter, _D(DCI_COL_GBP_INVALID_PAGES),
392 DCI_DT_INT, _T("DB2/Table/Col/Gbp: The number of times that a column-organized page is requested from the group buffer pool")
393 _T(" (GBP) when the page in the local buffer pool (LBP) is invalid")
394 },
395 {
396 _T("DB2.Table.Col.Lbp.PagesFound(*)"), GetParameter, _D(DCI_COL_LBP_PAGES_FOUND),
397 DCI_DT_INT, _T("DB2/Table/Col/Lbp: The number of times that a column-organized page is present in")
398 _T(" the local buffer pool (LBP)")
399 },
400 {
401 _T("DB2.Table.Col.Gbp.IndepPagesFound(*)"), GetParameter, _D(DCI_COL_GBP_INDEP_PAGES_FOUND_IN_LBP),
402 DCI_DT_INT, _T("DB2/Table/Col/Gbp: The number of group buffer pool (GBP) independent column-organized pages found in")
403 _T(" the local buffer pool (LBP)")
404 },
405 {
406 _T("DB2.Table.ColsReferenced(*)"), GetParameter, _D(DCI_NUM_COL_REFS),
407 DCI_DT_INT, _T("DB2/Table: The number of columns referenced during the execution of a section for an SQL statement")
408 },
409 {
410 _T("DB2.Table.SectionExecutions(*)"), GetParameter, _D(DCI_SECTION_EXEC_WITH_COL_REFS),
411 DCI_DT_INT, _T("DB2/Table: The number of section executions that referenced columns in tables using a scan")
412 }
413 };
414
415 static NETXMS_SUBAGENT_INFO m_agentInfo =
416 {
417 NETXMS_SUBAGENT_INFO_MAGIC,
418 SUBAGENT_NAME,
419 NETXMS_VERSION_STRING,
420 DB2Init, DB2Shutdown, DB2CommandHandler,
421 (sizeof(m_agentParams) / sizeof(NETXMS_SUBAGENT_PARAM)), m_agentParams,
422 0, NULL,
423 0, NULL,
424 0, NULL,
425 0, NULL
426 };
427
428 static QUERY g_queries[] =
429 {
430 { { DCI_DBMS_VERSION }, _T("SELECT service_level FROM TABLE (sysproc.env_get_inst_info())") },
431 { { DCI_NUM_AVAILABLE }, _T("SELECT count(available) FROM sysibmadm.admintabinfo WHERE available = 'Y'") },
432 { { DCI_NUM_UNAVAILABLE }, _T("SELECT count(available) FROM sysibmadm.admintabinfo WHERE available = 'N'") },
433 {
434 {
435 DCI_DATA_L_SIZE, DCI_DATA_P_SIZE, DCI_INDEX_L_SIZE, DCI_INDEX_P_SIZE, DCI_LONG_L_SIZE, DCI_LONG_P_SIZE,
436 DCI_LOB_L_SIZE, DCI_LOB_P_SIZE, DCI_XML_L_SIZE, DCI_XML_P_SIZE, DCI_DICTIONARY_SIZE, DCI_NUM_REORG_REC_ALTERS
437 },
438 _T("SELECT sum(data_object_l_size), sum(data_object_p_size), sum(index_object_l_size), sum(index_object_p_size),")
439 _T("sum(long_object_l_size), sum(long_object_p_size), sum(lob_object_l_size), sum(lob_object_p_size),")
440 _T("sum(xml_object_l_size), sum(xml_object_p_size), sum(dictionary_size), sum(num_reorg_rec_alters) ")
441 _T("FROM sysibmadm.admintabinfo")
442 },
443 { { DCI_INDEX_TYPE1 }, _T("SELECT count(index_type) FROM sysibmadm.admintabinfo WHERE index_type = 1") },
444 { { DCI_INDEX_TYPE2 }, _T("SELECT count(index_type) FROM sysibmadm.admintabinfo WHERE index_type = 2") },
445 { { DCI_REORG_PENDING }, _T("SELECT count(reorg_pending) FROM sysibmadm.admintabinfo WHERE reorg_pending = 'Y'") },
446 {
447 { DCI_REORG_ABORTED },
448 _T("SELECT count(inplace_reorg_status) FROM sysibmadm.admintabinfo WHERE inplace_reorg_status = 'ABORTED'") },
449 {
450 { DCI_REORG_EXECUTING },
451 _T("SELECT count(inplace_reorg_status) FROM sysibmadm.admintabinfo WHERE inplace_reorg_status = 'EXECUTING'")
452 },
453 {
454 { DCI_REORG_PAUSED },
455 _T("SELECT count(inplace_reorg_status) FROM sysibmadm.admintabinfo WHERE inplace_reorg_status = 'PAUSED'")
456 },
457 {
458 { DCI_REORG_NULL },
459 _T("SELECT count(inplace_reorg_status) FROM sysibmadm.admintabinfo WHERE inplace_reorg_status = 'NULL'")
460 },
461 { { DCI_LOAD_IN_PROGRESS }, _T("SELECT count(load_status) FROM sysibmadm.admintabinfo WHERE load_status = 'IN_PROGRESS'") },
462 { { DCI_LOAD_PENDING }, _T("SELECT count(load_status) FROM sysibmadm.admintabinfo WHERE load_status = 'PENDING'") },
463 { { DCI_LOAD_NULL }, _T("SELECT count(load_status) FROM sysibmadm.admintabinfo WHERE load_status = 'NULL'") },
464 { { DCI_ACCESS_RO }, _T("SELECT count(read_access_only) FROM sysibmadm.admintabinfo WHERE read_access_only = 'Y'") },
465 { { DCI_NO_LOAD_RESTART }, _T("SELECT count(no_load_restart) FROM sysibmadm.admintabinfo WHERE no_load_restart = 'Y'") },
466 {
467 { DCI_INDEX_REQUIRE_REBUILD },
468 _T("SELECT count(indexes_require_rebuild) FROM sysibmadm.admintabinfo WHERE indexes_require_rebuild = 'Y'")
469 },
470 { { DCI_LARGE_RIDS }, _T("SELECT count(large_rids) FROM sysibmadm.admintabinfo WHERE large_rids = 'Y'") },
471 { { DCI_NO_LARGE_RIDS }, _T("SELECT count(large_rids) FROM sysibmadm.admintabinfo WHERE large_rids = 'N'") },
472 { { DCI_LARGE_RIDS_PENDING }, _T("SELECT count(large_rids) FROM sysibmadm.admintabinfo WHERE large_rids = 'P'") },
473 { { DCI_LARGE_SLOTS }, _T("SELECT count(large_slots) FROM sysibmadm.admintabinfo WHERE large_slots = 'Y'") },
474 { { DCI_NO_LARGE_SLOTS }, _T("SELECT count(large_slots) FROM sysibmadm.admintabinfo WHERE large_slots = 'N'") },
475 { { DCI_LARGE_SLOTS_PENDING }, _T("SELECT count(large_slots) FROM sysibmadm.admintabinfo WHERE large_slots = 'P'") },
476 {
477 {
478 DCI_TABLE_SCANS, DCI_ROWS_READ, DCI_ROWS_INSERTED, DCI_ROWS_UPDATED, DCI_ROWS_DELETED, DCI_OVERFLOW_ACCESSES,
479 DCI_OVERFLOW_CREATES, DCI_PAGE_REORGS, DCI_DATA_L_PAGES, DCI_LOB_L_PAGES , DCI_LONG_L_PAGES, DCI_INDEX_L_PAGES,
480 DCI_XDA_L_PAGES, DCI_NO_CHANGE_UPDATES, DCI_LOCK_WAIT_TIME, DCI_LOCK_WAIT_TIME_GLOBAL, DCI_LOCK_WAITS,
481 DCI_LOCK_WAITS_GLOBAL, DCI_LOCK_ESCALS, DCI_LOCK_ESCALS_GLOBAL, DCI_SHARING_LOCKWAIT_COUNT, DCI_SHARING_LOCKWAIT_TIME,
482 DCI_DIRECT_WRITES, DCI_DIRECT_WRITE_REQS, DCI_DIRECT_READS, DCI_DIRECT_READ_REQS, DCI_DATA_L_READS, DCI_DATA_P_READS,
483 DCI_DATA_GBP_L_READS, DCI_DATA_GBP_P_READS, DCI_DATA_GBP_INVALID_PAGES, DCI_DATA_LBP_PAGES_FOUND,
484 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,
485 DCI_XDA_GBP_INVALID_PAGES, DCI_XDA_LBP_PAGES_FOUND, DCI_XDA_GBP_INDEP_PAGES_FOUND_IN_LBP, DCI_NUM_PAGE_DICT_BUILT,
486 DCI_STATS_ROWS_MODIFIED, DCI_RTS_ROWS_MODIFIED, DCI_COL_OBJECT_L_PAGES, DCI_COL_L_READS, DCI_COL_P_READS,
487 DCI_COL_GBP_L_READS, DCI_COL_GBP_P_READS, DCI_COL_GBP_INVALID_PAGES, DCI_COL_LBP_PAGES_FOUND,
488 DCI_COL_GBP_INDEP_PAGES_FOUND_IN_LBP, DCI_NUM_COL_REFS, DCI_SECTION_EXEC_WITH_COL_REFS
489 },
490 _T("SELECT sum(table_scans), sum(rows_read), sum(rows_inserted), sum(rows_updated), sum(rows_deleted),")
491 _T("sum(overflow_accesses), sum(overflow_creates), sum(page_reorgs), sum(data_object_l_pages), sum(lob_object_l_pages),")
492 _T("sum(long_object_l_pages), sum(index_object_l_pages), sum(xda_object_l_pages), sum(no_change_updates),")
493 _T("sum(lock_wait_time), sum(lock_wait_time_global), sum(lock_waits), sum(lock_waits_global), sum(lock_escals),")
494 _T("sum(lock_escals_global), sum(data_sharing_remote_lockwait_count), sum(data_sharing_remote_lockwait_time),")
495 _T("sum(direct_writes), sum(direct_write_reqs), sum(direct_reads), sum(direct_read_reqs), sum(object_data_l_reads),")
496 _T("sum(object_data_p_reads), sum(object_data_gbp_l_reads), sum(object_data_gbp_p_reads),")
497 _T("sum(object_data_gbp_invalid_pages), sum(object_data_lbp_pages_found), sum(object_data_gbp_indep_pages_found_in_lbp),")
498 _T("sum(object_xda_l_reads), sum(object_xda_p_reads), sum(object_xda_gbp_l_reads), sum(object_xda_gbp_p_reads),")
499 _T("sum(object_xda_gbp_invalid_pages), sum(object_xda_lbp_pages_found), sum(object_xda_gbp_indep_pages_found_in_lbp),")
500 _T("sum(num_page_dict_built), sum(stats_rows_modified), sum(rts_rows_modified), sum(col_object_l_pages),")
501 _T("sum(object_col_l_reads), sum(object_col_p_reads), sum(object_col_gbp_l_reads), sum(object_col_gbp_p_reads),")
502 _T("sum(object_col_gbp_invalid_pages), sum(object_col_lbp_pages_found), sum(object_col_gbp_indep_pages_found_in_lbp),")
503 _T("sum(num_columns_referenced), sum(section_exec_with_col_references) FROM TABLE (mon_get_table('', '', -2))")
504 },
505 { { DCI_STATE_SHARED }, _T("SELECT count(*) FROM TABLE (mon_get_table('', '', -2)) WHERE data_sharing_state = 'SHARED'") },
506 {
507 { DCI_STATE_NOT_SHARED },
508 _T("SELECT count(*) FROM TABLE (mon_get_table('', '', -2)) WHERE data_sharing_state = 'NOT_SHARED'")
509 },
510 {
511 { DCI_STATE_SHARED_BECOMING },
512 _T("SELECT count(*) FROM TABLE (mon_get_table('', '', -2)) WHERE data_sharing_state = 'BECOMING_SHARED'")
513 },
514 {
515 { DCI_STATE_NOT_SHARED_BECOMING },
516 _T("SELECT count(*) FROM TABLE (mon_get_table('', '', -2)) WHERE data_sharing_state = 'BECOMING_NOT_SHARED'")
517 },
518 { { DCI_ORGANIZATION_ROWS }, _T("SELECT count(*) FROM TABLE (mon_get_table('', '', -2)) WHERE tab_organization = 'R'") },
519 { { DCI_ORGANIZATION_COLS }, _T("SELECT count(*) FROM TABLE (mon_get_table('', '', -2)) WHERE tab_organization = 'C'") },
520 { { DCI_NULL }, _T("\0") }
521 };
522
523 static BOOL DB2Init(Config* config)
524 {
525 AgentWriteDebugLog(7, _T("%s: initializing"), SUBAGENT_NAME);
526
527 #ifdef _WIN32
528 g_drvHandle = DBLoadDriver(_T("db2.ddr"), NULL, TRUE, NULL, NULL);
529 #else
530 g_drvHandle = DBLoadDriver(LIBDIR _T("/netxms/dbdrv/db2.ddr"), NULL, TRUE, NULL, NULL);
531 #endif
532
533 if (g_drvHandle == NULL)
534 {
535 AgentWriteLog(EVENTLOG_ERROR_TYPE, _T("%s: failed to load the database driver"), SUBAGENT_NAME);
536 return FALSE;
537 }
538
539 AgentWriteDebugLog(7, _T("%s: loaded the database driver"), SUBAGENT_NAME);
540
541 ConfigEntry* db2IniEntry = config->getEntry(_T("/db2"));
542
543 if (db2IniEntry == NULL)
544 {
545 AgentWriteLog(EVENTLOG_ERROR_TYPE, _T("%s: no entries found in the configuration file"), SUBAGENT_NAME);
546 return FALSE;
547 }
548
549 PDB2_INFO* arrDb2Info;
550 int numOfPossibleThreads = 0;
551
552 ConfigEntry* xmlFile = db2IniEntry->findEntry(_T("ConfigFile"));
553 if (xmlFile == NULL)
554 {
555 AgentWriteDebugLog(7, _T("%s: processing configuration entries in section '%s'"), SUBAGENT_NAME, db2IniEntry->getName());
556
557 const PDB2_INFO db2Info = GetConfigs(config, db2IniEntry);
558 if (db2Info == NULL)
559 {
560 return FALSE;
561 }
562
563 g_numOfThreads = 1;
564 arrDb2Info = new PDB2_INFO[1];
565 arrDb2Info[0] = db2Info;
566 }
567 else
568 {
569 const TCHAR* pathToXml = xmlFile->getValue();
570 AgentWriteDebugLog(7, _T("%s: processing configuration file '%s'"), SUBAGENT_NAME, pathToXml);
571
572 if (!config->loadXmlConfig(pathToXml))
573 {
574 AgentWriteLog(EVENTLOG_ERROR_TYPE, _T("%s: '%s' is not a valid configuration file"), SUBAGENT_NAME, pathToXml);
575 return FALSE;
576 }
577
578 ConfigEntry* db2SubXmlEntry = config->getEntry(_T("/db2sub"));
579 if (db2SubXmlEntry == NULL)
580 {
581 AgentWriteLog(EVENTLOG_ERROR_TYPE, _T("%s: '%s' doesn't contain the db2 configuration entry"), SUBAGENT_NAME, pathToXml);
582 return FALSE;
583 }
584
585 ConfigEntryList* db2SubXmlSubEntries = db2SubXmlEntry->getSubEntries(_T("db2#*"));
586 numOfPossibleThreads = db2SubXmlSubEntries->getSize();
587 AgentWriteDebugLog(7, _T("%s: '%s' loaded with number of db2 entries: %d"), SUBAGENT_NAME, pathToXml, numOfPossibleThreads);
588 arrDb2Info = new PDB2_INFO[numOfPossibleThreads];
589
590 for(int i = 0; i < numOfPossibleThreads; i++)
591 {
592 ConfigEntry* entry = db2SubXmlSubEntries->getEntry(i);
593 const PDB2_INFO db2Info = GetConfigs(config, entry);
594 if (db2Info == NULL)
595 {
596 continue;
597 }
598
599 arrDb2Info[g_numOfThreads] = db2Info;
600 g_numOfThreads++;
601 }
602 }
603
604 if(g_numOfThreads > 0)
605 {
606 AgentWriteDebugLog(7, _T("%s: loaded %d configuration section(s)"), SUBAGENT_NAME, g_numOfThreads);
607 g_threads = new THREAD_INFO[g_numOfThreads];
608 g_sdownCondition = ConditionCreate(TRUE);
609 }
610
611 for(int i = 0; i < g_numOfThreads; i++)
612 {
613 //g_threads[i] = new THREAD_INFO;
614 g_threads[i].mutex = MutexCreate();
615 g_threads[i].db2Info = arrDb2Info[i];
616 g_threads[i].threadHandle = ThreadCreateEx(RunMonitorThread, 0, (void*) &g_threads[i]);
617 }
618
619 delete[] arrDb2Info;
620
621 if (g_numOfThreads > 0)
622 {
623 AgentWriteDebugLog(7, _T("%s: starting with %d query thread(s)"), SUBAGENT_NAME, g_numOfThreads);
624 return TRUE;
625 }
626
627 return FALSE;
628 }
629
630 static void DB2Shutdown()
631 {
632 AgentWriteDebugLog(9, _T("%s: terminating"), SUBAGENT_NAME);
633 ConditionSet(g_sdownCondition);
634
635 for(int i = 0; i < g_numOfThreads; i++)
636 {
637 ThreadJoin(g_threads[i].threadHandle);
638 MutexDestroy(g_threads[i].mutex);
639 delete g_threads[i].db2Info;
640 }
641 delete[] g_threads;
642
643 DBUnloadDriver(g_drvHandle);
644 ConditionDestroy(g_sdownCondition);
645
646 g_drvHandle = NULL;
647 g_sdownCondition = NULL;
648 g_threads = NULL;
649
650 AgentWriteDebugLog(7, _T("%s: terminated"), SUBAGENT_NAME);
651 }
652
653 static BOOL DB2CommandHandler(UINT32 dwCommand, CSCPMessage* pRequest, CSCPMessage* pResponse, void* session)
654 {
655 return FALSE;
656 }
657
658 static THREAD_RESULT THREAD_CALL RunMonitorThread(void* info)
659 {
660 PTHREAD_INFO threadInfo = (PTHREAD_INFO) info;
661 PDB2_INFO db2Info = threadInfo->db2Info;
662 DB_HANDLE dbHandle = NULL;
663 TCHAR connectError[DBDRV_MAX_ERROR_TEXT];
664 DWORD reconnectInterval = (DWORD) db2Info->db2ReconnectInterval;
665
666 while(TRUE)
667 {
668 dbHandle = DBConnect(
669 g_drvHandle, db2Info->db2DbAlias, db2Info->db2DbName, db2Info->db2UName, db2Info->db2UPass, NULL, connectError);
670
671 if (dbHandle == NULL)
672 {
673 AgentWriteLog(
674 EVENTLOG_ERROR_TYPE,
675 _T("%s: failed to connect to the database \"%s\" (%s), reconnecting in %ds"),
676 SUBAGENT_NAME, db2Info->db2DbName, connectError, reconnectInterval);
677
678 if (ConditionWait(g_sdownCondition, (reconnectInterval * 1000)))
679 {
680 break;
681 }
682 else
683 {
684 continue;
685 }
686 }
687
688 threadInfo->hDb = dbHandle;
689
690 AgentWriteLog(EVENTLOG_INFORMATION_TYPE, _T("%s: connected to database '%s'"), SUBAGENT_NAME, db2Info->db2DbName);
691
692 if (PerformQueries(threadInfo))
693 {
694 break;
695 }
696 }
697
698 if(dbHandle != NULL)
699 {
700 DBDisconnect(dbHandle);
701 }
702
703 return THREAD_OK;
704 }
705
706 static BOOL PerformQueries(const PTHREAD_INFO threadInfo)
707 {
708 PDB2_INFO db2Info = threadInfo->db2Info;
709 DWORD queryInterval = (DWORD) db2Info->db2QueryInterval;
710
711 while(TRUE)
712 {
713 MutexLock(threadInfo->mutex);
714
715 DB_RESULT hResult;
716 Dci* dciList;
717
718 int queryId = 0;
719 while(*(dciList = g_queries[queryId].dciList) != DCI_NULL)
720 {
721 hResult = DBSelect(threadInfo->hDb, g_queries[queryId].query);
722
723 if (hResult == NULL)
724 {
725 AgentWriteLog(EVENTLOG_ERROR_TYPE, _T("%s: query '%s' failed"), SUBAGENT_NAME, g_queries[queryId].query);
726 queryId++;
727 continue;
728 }
729
730 int numCols = DBGetColumnCount(hResult);
731
732 for(int i = 0; i < numCols; i++)
733 {
734 TCHAR* dciVal = threadInfo->db2Params[dciList[i]];
735
736 DBGetField(hResult, 0, i, dciVal, STR_MAX);
737
738 AgentWriteDebugLog(9, _T("%s: got '%s'"), SUBAGENT_NAME, dciVal);
739 }
740
741 DBFreeResult(hResult);
742
743 queryId++;
744 }
745
746 MutexUnlock(threadInfo->mutex);
747
748 if (ConditionWait(g_sdownCondition, queryInterval * 1000))
749 {
750 break;
751 }
752 }
753
754 return TRUE;
755 }
756
757 static LONG GetParameter(const TCHAR* parameter, const TCHAR* arg, TCHAR* value)
758 {
759 Dci dci = StringToDci(arg);
760
761 if (dci == DCI_NULL)
762 {
763 return SYSINFO_RC_UNSUPPORTED;
764 }
765
766 TCHAR dbIdString[DB_ID_DIGITS_MAX];
767 unsigned long dbId;
768
769 AgentGetParameterArg(parameter, 1, dbIdString, DB_ID_DIGITS_MAX);
770 dbId = _tcstoul(dbIdString, NULL, 0);
771
772 if (dbId == 0)
773 {
774 AgentWriteDebugLog(7, _T("%s: id '%s' is invalid"), SUBAGENT_NAME, dbIdString);
775 return SYSINFO_RC_UNSUPPORTED;
776 }
777
778 THREAD_INFO threadInfo;
779
780 for(int i = 0; i < g_numOfThreads; i++)
781 {
782 if (g_threads[i].db2Info->db2Id == dbId)
783 {
784 threadInfo = g_threads[i];
785 break;
786 }
787
788 AgentWriteDebugLog(7, _T("%s: no database with id '%d' found"), SUBAGENT_NAME, dbId);
789 return SYSINFO_RC_UNSUPPORTED;
790 }
791
792 ret_string(value, threadInfo.db2Params[dci]);
793
794 return SYSINFO_RC_SUCCESS;
795 }
796
797 static const PDB2_INFO GetConfigs(Config* config, ConfigEntry* configEntry)
798 {
799 ConfigEntryList* entryList = configEntry->getSubEntries(_T("*"));
800 TCHAR entryName[STR_MAX] = _T("db2sub/");
801
802 _tcscat(entryName, configEntry->getName());
803
804 if (entryList->getSize() == 0)
805 {
806 AgentWriteLog(EVENTLOG_ERROR_TYPE, _T("%s: entry '%s' contained no values"), SUBAGENT_NAME, entryName);
807 return NULL;
808 }
809
810 const PDB2_INFO db2Info = new DB2_INFO();
811 BOOL noErr = TRUE;
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("ReconnectInterval"), CT_LONG, 0, 0, sizeof(LONG), 0, &(db2Info->db2ReconnectInterval) },
822 { _T("QueryInterval"), CT_LONG, 0, 0, sizeof(LONG), 0, &(db2Info->db2QueryInterval) },
823 { _T(""), CT_END_OF_LIST, 0, 0, 0, 0, NULL }
824 };
825
826 if (!config->parseTemplate(entryName, cfgTemplate))
827 {
828 AgentWriteLog(EVENTLOG_ERROR_TYPE, _T("%s: failed to process entry '%s'"), SUBAGENT_NAME, entryName);
829 noErr = FALSE;
830 }
831
832 if (noErr)
833 {
834 if (db2Info->db2DbName[0] == '\0')
835 {
836 AgentWriteDebugLog(7, _T("%s: no DBName in '%s'"), SUBAGENT_NAME, entryName);
837 noErr = FALSE;
838 }
839 else
840 {
841 AgentWriteDebugLog(9, _T("%s: got DBName entry with value '%s'"), SUBAGENT_NAME, db2Info->db2DbName);
842 }
843
844 if (db2Info->db2DbAlias[0] == '\0')
845 {
846 AgentWriteDebugLog(7, _T("%s: no DBAlias in '%s'"), SUBAGENT_NAME, entryName);
847 noErr = FALSE;
848 }
849 else
850 {
851 AgentWriteDebugLog(9, _T("%s: got DBAlias entry with value '%s'"), SUBAGENT_NAME, db2Info->db2DbAlias);
852 }
853
854 if (db2Info->db2UName[0] == '\0')
855 {
856 AgentWriteDebugLog(7, _T("%s: no UserName in '%s'"), SUBAGENT_NAME, entryName);
857 noErr = FALSE;
858 }
859 else
860 {
861 AgentWriteDebugLog(9, _T("%s: got UserName entry with value '%s'"), SUBAGENT_NAME, db2Info->db2UName);
862 }
863
864 if (db2Info->db2UPass[0] == '\0')
865 {
866 AgentWriteDebugLog(7, _T("%s: no Password in '%s'"), SUBAGENT_NAME, entryName);
867 noErr = FALSE;
868 }
869 else
870 {
871 AgentWriteDebugLog(9, _T("%s: got Password entry with value '%s'"), SUBAGENT_NAME, db2Info->db2UPass);
872 }
873
874 if (db2Info->db2ReconnectInterval == 0)
875 {
876 db2Info->db2ReconnectInterval = INTERVAL_RECONNECT_SECONDS;
877 }
878
879 if (db2Info->db2QueryInterval == 0)
880 {
881 db2Info->db2QueryInterval = INTERVAL_QUERY_SECONDS;
882 }
883 }
884
885 if (!noErr)
886 {
887 AgentWriteLog(EVENTLOG_ERROR_TYPE, _T("%s: failed to process entry '%s'"), SUBAGENT_NAME, entryName);
888 delete db2Info;
889 return NULL;
890 }
891
892 return db2Info;
893 }
894
895 DECLARE_SUBAGENT_ENTRY_POINT(DB2)
896 {
897 AgentWriteDebugLog(7, _T("%s: started"), SUBAGENT_NAME);
898 *ppInfo = &m_agentInfo;
899 return TRUE;
900 }
901
902 /**
903 * DLL entry point
904 */
905
906 #ifdef _WIN32
907
908 BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved)
909 {
910 if (fdwReason == DLL_PROCESS_ATTACH)
911 {
912 DisableThreadLibraryCalls(hinstDll);
913 }
914 return TRUE;
915 }
916
917 #endif