32adfb7b3befc2a8c0eb30b266276bcad03e74c5
[public/netxms.git] / src / server / core / syncer.cpp
1 /*
2 ** NetXMS - Network Management System
3 ** Copyright (C) 2003-2016 Victor Kirhenshtein
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 ** File: syncer.cpp
20 **
21 **/
22
23 #include "nxcore.h"
24
25 /**
26 * Externals
27 */
28 void NetObjDelete(NetObj *pObject);
29
30 /**
31 * Object transaction lock
32 */
33 static RWLOCK s_objectTxnLock = RWLockCreate();
34
35 /**
36 * Start object transaction
37 */
38 void NXCORE_EXPORTABLE ObjectTransactionStart()
39 {
40 if (g_flags & AF_ENABLE_OBJECT_TRANSACTIONS)
41 RWLockReadLock(s_objectTxnLock, INFINITE);
42 }
43
44 /**
45 * End object transaction
46 */
47 void NXCORE_EXPORTABLE ObjectTransactionEnd()
48 {
49 if (g_flags & AF_ENABLE_OBJECT_TRANSACTIONS)
50 RWLockUnlock(s_objectTxnLock);
51 }
52
53 /**
54 * Save objects to database
55 */
56 void SaveObjects(DB_HANDLE hdb, UINT32 watchdogId, bool saveRuntimeData)
57 {
58 if (g_flags & AF_ENABLE_OBJECT_TRANSACTIONS)
59 RWLockWriteLock(s_objectTxnLock, INFINITE);
60
61 ObjectArray<NetObj> *objects = g_idxObjectById.getObjects(false);
62 DbgPrintf(5, _T("Syncer: %d objects to process"), objects->size());
63 for(int i = 0; i < objects->size(); i++)
64 {
65 WatchdogNotify(watchdogId);
66 NetObj *object = objects->get(i);
67 if (object->isDeleted())
68 {
69 DbgPrintf(5, _T("Syncer: object %s [%d] marked for deletion"), object->getName(), object->getId());
70 if (object->getRefCount() == 0)
71 {
72 DBBegin(hdb);
73 if (object->deleteFromDatabase(hdb))
74 {
75 DbgPrintf(4, _T("Syncer: Object %d \"%s\" deleted from database"), object->getId(), object->getName());
76 DBCommit(hdb);
77 NetObjDelete(object);
78 }
79 else
80 {
81 DBRollback(hdb);
82 DbgPrintf(4, _T("Syncer: Call to deleteFromDatabase() failed for object %s [%d], transaction rollback"), object->getName(), object->getId());
83 }
84 }
85 else
86 {
87 DbgPrintf(3, _T("Syncer: Unable to delete object with id %d because it is being referenced %d time(s)"),
88 object->getId(), object->getRefCount());
89 }
90 }
91 else if (object->isModified())
92 {
93 DbgPrintf(5, _T("Syncer: object %s [%d] modified"), object->getName(), object->getId());
94 DBBegin(hdb);
95 if (object->saveToDatabase(hdb))
96 {
97 DBCommit(hdb);
98 }
99 else
100 {
101 DBRollback(hdb);
102 }
103 }
104 else if (saveRuntimeData)
105 {
106 object->saveRuntimeData(hdb);
107 }
108 }
109
110 if (g_flags & AF_ENABLE_OBJECT_TRANSACTIONS)
111 RWLockUnlock(s_objectTxnLock);
112 delete objects;
113 DbgPrintf(5, _T("Syncer: save objects completed"));
114 }
115
116 /**
117 * Syncer thread
118 */
119 THREAD_RESULT THREAD_CALL Syncer(void *arg)
120 {
121 ThreadSetName("Syncer");
122
123 int syncInterval = ConfigReadInt(_T("SyncInterval"), 60);
124 UINT32 watchdogId = WatchdogAddThread(_T("Syncer Thread"), 30);
125
126 nxlog_debug(1, _T("Syncer thread started, sync_interval = %d"), syncInterval);
127
128 // Main syncer loop
129 WatchdogStartSleep(watchdogId);
130 while(!SleepAndCheckForShutdown(syncInterval))
131 {
132 WatchdogNotify(watchdogId);
133 if (!(g_flags & AF_DB_CONNECTION_LOST)) // Don't try to save if DB connection is lost
134 {
135 DB_HANDLE hdb = DBConnectionPoolAcquireConnection();
136 SaveObjects(hdb, watchdogId, false);
137 SaveUsers(hdb, watchdogId);
138 UpdatePStorageDatabase(hdb, watchdogId);
139 DBConnectionPoolReleaseConnection(hdb);
140 }
141 WatchdogStartSleep(watchdogId);
142 }
143
144 DbgPrintf(1, _T("Syncer thread terminated"));
145 return THREAD_OK;
146 }