all pollers converted to single thread pool
[public/netxms.git] / src / server / core / bizservice.cpp
CommitLineData
e83d726c 1/*
ae3d7f46
AK
2** NetXMS - Network Management System
3** Copyright (C) 2003-2011 NetXMS Team
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**
efc119b9 19** File: bizservice.cpp
ae3d7f46
AK
20**
21**/
22
23#include "nxcore.h"
ae3d7f46
AK
24
25#define QUERY_LENGTH (512)
26
21c9acce
VK
27/**
28 * Service default constructor
29 */
4a1e58e5 30BusinessService::BusinessService() : ServiceContainer()
ae3d7f46 31{
52c75f5c 32 m_busy = false;
f6cd5b2f 33 m_pollingDisabled = false;
52c75f5c 34 m_lastPollTime = time_t(0);
3e2bf4aa 35 m_lastPollStatus = STATUS_UNKNOWN;
c42b4551 36 _tcscpy(m_name, _T("Default"));
ae3d7f46
AK
37}
38
f6cd5b2f
VK
39/**
40 * Constructor for new service object
41 */
4a1e58e5 42BusinessService::BusinessService(const TCHAR *name) : ServiceContainer(name)
ae3d7f46 43{
ae3d7f46 44 m_busy = false;
f6cd5b2f 45 m_pollingDisabled = false;
52c75f5c 46 m_lastPollTime = time_t(0);
3e2bf4aa 47 m_lastPollStatus = STATUS_UNKNOWN;
c42b4551 48 nx_strncpy(m_name, name, MAX_OBJECT_NAME);
ae3d7f46
AK
49}
50
f6cd5b2f
VK
51/**
52 * Destructor
53 */
1621a079 54BusinessService::~BusinessService()
ae3d7f46
AK
55{
56}
57
f6cd5b2f
VK
58/**
59 * Create object from database data
60 */
c42b4551 61BOOL BusinessService::loadFromDatabase(UINT32 id)
ae3d7f46 62{
c42b4551 63 if (!ServiceContainer::loadFromDatabase(id))
ae3d7f46
AK
64 return FALSE;
65
66 // now it doesn't make any sense but hopefully will do in the future
67 DB_STATEMENT hStmt = DBPrepare(g_hCoreDB, _T("SELECT service_id FROM business_services WHERE service_id=?"));
68 if (hStmt == NULL)
69 {
70 DbgPrintf(4, _T("Cannot prepare select from business_services"));
71 return FALSE;
72 }
c42b4551 73 DBBind(hStmt, 1, DB_SQLTYPE_INTEGER, m_id);
ae3d7f46
AK
74 DB_RESULT hResult = DBSelectPrepared(hStmt);
75 if (hResult == NULL)
76 {
77 DBFreeStatement(hStmt);
78 return FALSE;
79 }
80
81 if (DBGetNumRows(hResult) == 0)
82 {
83 DBFreeResult(hResult);
84 DBFreeStatement(hStmt);
c42b4551 85 DbgPrintf(4, _T("Cannot load biz service object %ld - record missing"), (long)m_id);
ae3d7f46
AK
86 return FALSE;
87 }
88
ae3d7f46
AK
89 DBFreeResult(hResult);
90 DBFreeStatement(hStmt);
91
ae3d7f46
AK
92 return TRUE;
93}
94
f6cd5b2f
VK
95/**
96 * Save service to database
97 */
c42b4551 98BOOL BusinessService::saveToDatabase(DB_HANDLE hdb)
ae3d7f46
AK
99{
100 BOOL bNewObject = TRUE;
101
ae3d7f46
AK
102 DB_STATEMENT hStmt = DBPrepare(hdb, _T("SELECT service_id FROM business_services WHERE service_id=?"));
103 if (hStmt == NULL)
104 return FALSE;
53dec9a6 105
c42b4551 106 lockProperties();
53dec9a6 107
c42b4551 108 DBBind(hStmt, 1, DB_SQLTYPE_INTEGER, m_id);
ae3d7f46
AK
109 DB_RESULT hResult = DBSelectPrepared(hStmt);
110 if (hResult != NULL)
111 {
112 bNewObject = (DBGetNumRows(hResult) <= 0);
113 DBFreeResult(hResult);
114 }
115 DBFreeStatement(hStmt);
116
117 hStmt = DBPrepare(g_hCoreDB, bNewObject ? _T("INSERT INTO business_services (service_id) VALUES (?)") :
118 _T("UPDATE business_services SET service_id=service_id WHERE service_id=?"));
53dec9a6
VK
119 if (hStmt == NULL)
120 {
c42b4551 121 unlockProperties();
ae3d7f46 122 return FALSE;
53dec9a6 123 }
c42b4551
VK
124 DBBind(hStmt, 1, DB_SQLTYPE_INTEGER, m_id);
125 unlockProperties();
53dec9a6 126
ae3d7f46
AK
127 if (!DBExecute(hStmt))
128 {
129 DBFreeStatement(hStmt);
130 return FALSE;
131 }
132
ae3d7f46
AK
133 DBFreeStatement(hStmt);
134
135 saveACLToDB(hdb);
136
c42b4551 137 lockProperties();
01152a54 138 m_isModified = false;
c42b4551 139 unlockProperties();
5f591e92 140
c42b4551 141 return ServiceContainer::saveToDatabase(hdb);
ae3d7f46
AK
142}
143
22ee6d97
VK
144/**
145 * Delete object from database
146 */
c42b4551 147bool BusinessService::deleteFromDatabase(DB_HANDLE hdb)
ae3d7f46 148{
c42b4551 149 bool success = ServiceContainer::deleteFromDatabase(hdb);
22ee6d97 150 if (success)
ae3d7f46 151 {
22ee6d97 152 success = executeQueryOnObject(hdb, _T("DELETE FROM business_services WHERE service_id=?"));
ae3d7f46 153 }
22ee6d97 154 return success;
ae3d7f46
AK
155}
156
22ee6d97
VK
157/**
158 * Create NXCP message with object's data
159 */
8fe90adb 160void BusinessService::fillMessageInternal(NXCPMessage *pMsg)
ae3d7f46 161{
8fe90adb 162 ServiceContainer::fillMessageInternal(pMsg);
ae3d7f46
AK
163}
164
c59466d2
VK
165/**
166 * Modify object from message
167 */
8fe90adb 168UINT32 BusinessService::modifyFromMessageInternal(NXCPMessage *pRequest)
ae3d7f46 169{
8fe90adb 170 return ServiceContainer::modifyFromMessageInternal(pRequest);
ae3d7f46
AK
171}
172
c59466d2
VK
173/**
174 * Check if service is ready for poll
175 */
1621a079 176bool BusinessService::isReadyForPolling()
52c75f5c 177{
c42b4551 178 lockProperties();
f6cd5b2f 179 bool ready = (time(NULL) - m_lastPollTime > g_slmPollingInterval) && !m_busy && !m_pollingDisabled;
c42b4551 180 unlockProperties();
f6cd5b2f 181 return ready;
52c75f5c
AK
182}
183
c59466d2
VK
184/**
185 * Lock service for polling
186 */
1621a079 187void BusinessService::lockForPolling()
52c75f5c 188{
c42b4551 189 lockProperties();
52c75f5c 190 m_busy = true;
c42b4551 191 unlockProperties();
52c75f5c
AK
192}
193
c59466d2
VK
194/**
195 * A callback for poller threads
196 */
208d7427
VK
197void BusinessService::poll(PollerInfo *poller)
198{
199 poller->startExecution();
200 poll(NULL, 0, poller);
201 delete poller;
202}
203
204/**
205 * Status poll
206 */
207void BusinessService::poll(ClientSession *pSession, UINT32 dwRqId, PollerInfo *poller)
ae3d7f46 208{
c42b4551 209 DbgPrintf(5, _T("Started polling of business service %s [%d]"), m_name, (int)m_id);
52c75f5c
AK
210 m_lastPollTime = time(NULL);
211
212 // Loop through the kids and execute their either scripts or thresholds
5a4dc0c6 213 LockChildList(FALSE);
967893bb 214 for (UINT32 i = 0; i < m_dwChildCount; i++)
ae3d7f46 215 {
c42b4551 216 if (m_pChildList[i]->getObjectClass() == OBJECT_SLMCHECK)
636e0c72 217 ((SlmCheck *)m_pChildList[i])->execute();
c42b4551 218 else if (m_pChildList[i]->getObjectClass() == OBJECT_NODELINK)
3e2bf4aa 219 ((NodeLink*)m_pChildList[i])->execute();
ae3d7f46 220 }
5a4dc0c6 221 UnlockChildList();
ae3d7f46 222
52c75f5c 223 // Set the status based on what the kids' been up to
b79e8fed 224 calculateCompoundStatus();
ae3d7f46 225
93d91beb 226 m_lastPollStatus = m_iStatus;
c42b4551 227 DbgPrintf(5, _T("Finished polling of business service %s [%d]"), m_name, (int)m_id);
93d91beb 228 m_busy = false;
ae3d7f46 229}
6ff21d27 230
21c9acce
VK
231/**
232 * Get template checks applicable for given target
233 */
6ff21d27
VK
234void BusinessService::getApplicableTemplates(ServiceContainer *target, ObjectArray<SlmCheck> *templates)
235{
236 LockChildList(FALSE);
967893bb 237 for(UINT32 i = 0; i < m_dwChildCount; i++)
6ff21d27 238 {
c42b4551 239 if ((m_pChildList[i]->getObjectClass() == OBJECT_SLMCHECK) &&
fe875bb3 240 ((SlmCheck *)m_pChildList[i])->isTemplate())
6ff21d27 241 {
21c9acce 242 m_pChildList[i]->incRefCount();
6ff21d27
VK
243 templates->add((SlmCheck *)m_pChildList[i]);
244 }
245 }
246 UnlockChildList();
fe875bb3
VK
247
248 LockParentList(FALSE);
967893bb 249 for(UINT32 i = 0; i < m_dwParentCount; i++)
fe875bb3 250 {
c42b4551 251 if (m_pParentList[i]->getObjectClass() == OBJECT_BUSINESSSERVICE)
fe875bb3
VK
252 {
253 ((BusinessService *)m_pParentList[i])->getApplicableTemplates(target, templates);
254 }
255 }
256 UnlockParentList();
6ff21d27 257}
f6cd5b2f
VK
258
259/**
260 * Prepare business service object for deletion
261 */
262void BusinessService::prepareForDeletion()
263{
264 // Prevent service from being queued for polling
c42b4551 265 lockProperties();
f6cd5b2f 266 m_pollingDisabled = true;
c42b4551 267 unlockProperties();
f6cd5b2f
VK
268
269 // wait for outstanding poll to complete
270 while(true)
271 {
c42b4551 272 lockProperties();
f6cd5b2f
VK
273 if (!m_busy)
274 {
c42b4551 275 unlockProperties();
f6cd5b2f
VK
276 break;
277 }
c42b4551 278 unlockProperties();
f6cd5b2f
VK
279 ThreadSleep(100);
280 }
c42b4551 281 DbgPrintf(4, _T("BusinessService::PrepareForDeletion(%s [%d]): no outstanding polls left"), m_name, (int)m_id);
f6cd5b2f
VK
282 ServiceContainer::prepareForDeletion();
283}