fixed Windows build errors
[public/netxms.git] / src / agent / core / dbupgrade.cpp
CommitLineData
7f6ecb6d
TD
1/*
2** NetXMS multiplatform core agent
3** Copyright (C) 2016 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** File: dbupgrade.cpp
20**
21**/
22
23#include "nxagentd.h"
24
25/**
26 * Execute with error check
27 */
28#define CHK_EXEC(x) do { if (!(x)) if (!g_ignoreAgentDbErrors) return false; } while (0)
29
30bool g_ignoreAgentDbErrors = FALSE;
31
32#define Query(sql) DBQuery(s_db, sql)
33
34/**
35 * Database handle
36 */
37static DB_HANDLE s_db = NULL;
38
39/**
40 * Upgrade from V1 to V2
41 */
42static BOOL H_UpgradeFromV1(int currVersion, int newVersion)
43{
a37285c8
VK
44 /*
45 This upgrade contains:
46 1. check that version and depending on version of DATACOLL_SCHEMA_VERSION apply second or both patchs
47 move upgrade of data collection database to this function
48 2. remove DATACOLL_SCHEMA_VERSION from metadata
49 3. create policy table (guid, type, server, version) unique giud
50 4. Move policy information from registry to database
51 5. Create table registry that will store (key, value) unique key
52 6. Move upgrade file storage pleace from registry to db
7f6ecb6d 53 7. Delete registry file (remove unused functions for registry)
a37285c8 54 */
7f6ecb6d
TD
55
56 //Data collection upgrade procedure
57 const TCHAR *s_upgradeQueries[] =
58 {
59 _T("CREATE TABLE dc_queue (")
60 _T(" server_id number(20) not null,")
61 _T(" dci_id integer not null,")
62 _T(" dci_type integer not null,")
63 _T(" dci_origin integer not null,")
64 _T(" snmp_target_guid varchar(36) not null,")
65 _T(" timestamp integer not null,")
66 _T(" value varchar not null,")
67 _T(" PRIMARY KEY(server_id,dci_id,timestamp))"),
68
69 _T("CREATE TABLE dc_config (")
70 _T(" server_id number(20) not null,")
71 _T(" dci_id integer not null,")
72 _T(" type integer not null,")
73 _T(" origin integer not null,")
74 _T(" name varchar(1023) null,")
75 _T(" polling_interval integer not null,")
76 _T(" last_poll integer not null,")
77 _T(" snmp_port integer not null,")
78 _T(" snmp_target_guid varchar(36) not null,")
79 _T(" snmp_raw_type integer not null,")
80 _T(" PRIMARY KEY(server_id,dci_id))"),
81
82 _T("CREATE TABLE dc_snmp_targets (")
83 _T(" guid varchar(36) not null,")
84 _T(" server_id number(20) not null,")
85 _T(" ip_address varchar(48) not null,")
86 _T(" snmp_version integer not null,")
87 _T(" port integer not null,")
88 _T(" auth_type integer not null,")
89 _T(" enc_type integer not null,")
90 _T(" auth_name varchar(63),")
91 _T(" auth_pass varchar(63),")
92 _T(" enc_pass varchar(63),")
93 _T(" PRIMARY KEY(guid))")
94 };
95
96 UINT32 dbVersion = ReadMetadataAsInt(_T("DataCollectionSchemaVersion"));
97 while(dbVersion < 3)
98 {
99 CHK_EXEC(Query(s_upgradeQueries[dbVersion]));
100 dbVersion++;
101 }
102
103 CHK_EXEC(Query(_T("DELETE FROM metadata WHERE attribute='DataCollectionSchemaVersion'")));
104
105 //Policy upgrade procedure
106 TCHAR createPolicyTable[] = _T("CREATE TABLE agent_policy (")
107 _T(" guid varchar(36) not null,")
108 _T(" type integer not null,")
109 _T(" server_info varchar(64) null,")
110 _T(" server_id number(20) not null,")
111 _T(" version integer not null,")
112 _T(" PRIMARY KEY(guid))");
113 CHK_EXEC(Query(createPolicyTable));
114
115 //Create registry table
116 TCHAR crateRegistryTable[] = _T("CREATE TABLE registry (")
117 _T(" attribute varchar(63) null,")
118 _T(" value varchar null,")
119 _T(" PRIMARY KEY(attribute))");
120 CHK_EXEC(Query(crateRegistryTable));
121
122 // Initialize persistent storage
123 bool registryExists = false;
124 Config *registry = new Config;
125 registry->setTopLevelTag(_T("registry"));
126 TCHAR regPath[MAX_PATH];
127 nx_strncpy(regPath, g_szDataDirectory, MAX_PATH - _tcslen(_T("registry.dat")) - 1);
128 if (regPath[_tcslen(regPath) - 1] != FS_PATH_SEPARATOR_CHAR)
129 _tcscat(regPath, FS_PATH_SEPARATOR);
130 _tcscat(regPath, _T("registry.dat"));
131 registryExists = registry->loadXmlConfig(regPath, "registry");
132 if(!registryExists)
133 {
134 DebugPrintf(INVALID_INDEX, 1, _T("Registry file doesn't exist. No data will be moved from registry to database\n"));
135 CHK_EXEC(WriteMetadata(_T("SchemaVersion"), 2));
136 return TRUE;
137 }
138
139 //Move policy data form registry file to agent database
140 ObjectArray<ConfigEntry> *list = registry->getSubEntries(_T("/policyRegistry"), NULL);
141 DB_STATEMENT hStmt = DBPrepare(s_db,
142 _T("INSERT INTO agent_policy (guid,type,server_info,server_id,version)")
143 _T(" VALUES (?,?,?,0,0)"));
144 if(hStmt != NULL)
145 {
146 if (list != NULL)
147 {
148 for(int i = 0; i < list->size(); i++)
149 {
150 ConfigEntry *e = list->get(i);
151 uuid_t guid;
7f6ecb6d
TD
152
153 if (MatchString(_T("policy-*"), e->getName(), TRUE))
154 {
155 _uuid_parse(&(e->getName()[7]), guid);
156
157 DBBind(hStmt, 1, DB_SQLTYPE_VARCHAR, guid);
158 DBBind(hStmt, 2, DB_SQLTYPE_INTEGER, e->getSubEntryValueAsInt(_T("type")));
159 DBBind(hStmt, 3, DB_SQLTYPE_VARCHAR, e->getSubEntryValue(_T("server")), DB_BIND_STATIC);
160 CHK_EXEC(DBExecute(hStmt));
161 }
162 }
163 delete list;
164 }
165 DBFreeStatement(hStmt);
166 }
167
168 //Move upgrade file url variable to database
169 const TCHAR* szFullPath = registry->getValue(_T("/upgrade/file"));
170 if(szFullPath != NULL)
171 {
172 TCHAR upgradeFileInsert[256];
173 _sntprintf(upgradeFileInsert, 256, _T("INSERT INTO registry (attribute,value) VALUES ('upgrade.file','%s')"), szFullPath);
174 CHK_EXEC(Query(upgradeFileInsert));
175 }
176 delete registry;
177 //Delete registry file
178 _tremove(regPath);
179
180 CHK_EXEC(WriteMetadata(_T("SchemaVersion"), 2));
181 return TRUE;
182}
183
184/**
185 * Upgrade map
186 */
187static struct
188{
189 int version;
190 int newVersion;
191 BOOL (* fpProc)(int, int);
192} m_dbUpgradeMap[] =
193{
194 { 1, 2, H_UpgradeFromV1 },
195 { 0, 0, NULL }
196};
197
198
199/**
200 * Upgrade database to new version
201 */
202bool UpgradeDatabase()
203{
204 int i;
205 UINT32 version = 0;
206 BOOL bLocked = FALSE;
207 s_db = GetLocalDatabaseHandle();
208
209 // Get database format version
210 version = ReadMetadataAsInt(_T("SchemaVersion"));
211 if (version == DB_SCHEMA_VERSION)
212 {
213 DebugPrintf(INVALID_INDEX, 1, _T("Database format is up to date"));
214 }
215 else if (version > DB_SCHEMA_VERSION)
216 {
217 DebugPrintf(INVALID_INDEX, 1, _T("Your database has format version %d, this agent is compiled for version %d.\n"), version, DB_SCHEMA_VERSION);
218 DebugPrintf(INVALID_INDEX, 1, _T("You need to upgrade your agent before using this database.\n"));
219
220 }
221 else
222 {
223 // Upgrade database
224 while(version < DB_SCHEMA_VERSION)
225 {
226 // Find upgrade procedure
227 for(i = 0; m_dbUpgradeMap[i].fpProc != NULL; i++)
228 if (m_dbUpgradeMap[i].version == version)
229 break;
230 if (m_dbUpgradeMap[i].fpProc == NULL)
231 {
232 DebugPrintf(INVALID_INDEX, 1, _T("Unable to find upgrade procedure for version %d"), version);
233 break;
234 }
235 DebugPrintf(INVALID_INDEX, 1, _T("Upgrading from version %d to %d"), version, m_dbUpgradeMap[i].newVersion);
236 DBBegin(s_db);
237 if (m_dbUpgradeMap[i].fpProc(version, m_dbUpgradeMap[i].newVersion))
238 {
239 DBCommit(s_db);
240 version = ReadMetadataAsInt(_T("SchemaVersion"));
241 }
242 else
243 {
244 DebugPrintf(INVALID_INDEX, 1, _T("Rolling back last stage due to upgrade errors..."));
245 DBRollback(s_db);
246 break;
247 }
248 }
249
250 DebugPrintf(INVALID_INDEX, 1, _T("Database upgrade %s"), (version == DB_SCHEMA_VERSION) ? _T("succeeded") : _T("failed"));
251 }
252 return version == DB_SCHEMA_VERSION;
253}