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