]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/win32/filed/plugins/storage_group_node.c
e2e45e6825396a3185fabef467c096cce90664b8
[bacula/bacula] / bacula / src / win32 / filed / plugins / storage_group_node.c
1 /*
2    Bacula® - The Network Backup Solution
3
4    Copyright (C) 2008-2008 Free Software Foundation Europe e.V.
5
6    The main author of Bacula is Kern Sibbald, with contributions from
7    many others, a complete list can be found in the file AUTHORS.
8    This program is Free Software; you can redistribute it and/or
9    modify it under the terms of version two of the GNU General Public
10    License as published by the Free Software Foundation, which is 
11    listed in the file LICENSE.
12
13    This program is distributed in the hope that it will be useful, but
14    WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16    General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21    02110-1301, USA.
22
23    Bacula® is a registered trademark of Kern Sibbald.
24    The licensor of Bacula is the Free Software Foundation Europe
25    (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
26    Switzerland, email:ftf@fsfeurope.org.
27 */
28 /* 
29  *  Written by James Harper, October 2008
30  */
31
32 #include "exchange-fd.h"
33
34 storage_group_node_t::storage_group_node_t(char *name, node_t *parent_node) : node_t(name, NODE_TYPE_STORAGE_GROUP, parent_node)
35 {
36    ibi = NULL;
37    store_node = NULL;
38    current_dbi = 0;
39    restore_environment = NULL;
40    saved_log_path = NULL;
41    next = NULL;
42 }
43
44 storage_group_node_t::~storage_group_node_t()
45 {
46 /*
47    if (dbi_node != NULL)
48       delete dbi_node;
49
50    if (file_node != NULL)
51       delete file_node;
52 */
53 }
54
55 bRC
56 storage_group_node_t::startBackupFile(exchange_fd_context_t *context, struct save_pkt *sp)
57 {
58    HRESULT result;
59    int len;
60    WCHAR *tmp_logfiles, *tmp_logfile_ptr;
61    char *tmp;
62
63    for(;;)
64    {
65       _DebugMessage(100, "startBackupNode_STORAGE_GROUP state = %d, name = %s\n", state, name);
66       switch(state)
67       {
68       case 0:
69          current_dbi = 0;
70          store_node = NULL;
71          logfile_ptr = NULL;
72          if (context->job_level == 'F')
73          {
74             _DebugMessage(100, "Calling HrESEBackupSetup (BACKUP_TYPE_FULL)\n");
75             result = HrESEBackupSetup(hccx, ibi->hInstanceId, BACKUP_TYPE_FULL);
76             state = 1;
77          }
78          else
79          {
80             _DebugMessage(100, "Calling HrESEBackupSetup (BACKUP_TYPE_LOGS_ONLY)\n");
81             result = HrESEBackupSetup(hccx, ibi->hInstanceId, BACKUP_TYPE_LOGS_ONLY);
82             if (context->accurate)
83                state = 1;
84             else
85                state = 2;
86          }
87          if (result != 0)
88          {
89             _JobMessage(M_ERROR, "HrESEBackupSetup failed with error 0x%08x - %s\n", result, ESEErrorMessage(result));
90             state = 999;
91             return bRC_Error;
92          }
93          break;
94       case 1:
95          if (context->path_bits[level + 1] == NULL)
96          {
97             _DebugMessage(100, "No specific database specified - backing them all up\n");
98             DATABASE_BACKUP_INFO *dbi = &ibi->rgDatabase[current_dbi];
99             char *tmp = new char[wcslen(dbi->wszDatabaseDisplayName) + 1];
100             wcstombs(tmp, dbi->wszDatabaseDisplayName, wcslen(dbi->wszDatabaseDisplayName) + 1);
101             store_node = new store_node_t(tmp, this);
102             store_node->dbi = dbi;
103             store_node->hccx = hccx;
104             context->current_node = store_node;
105          }
106          else
107          {
108             DATABASE_BACKUP_INFO *dbi = NULL;
109             char *tmp = NULL;
110             for (current_dbi = 0; current_dbi < ibi->cDatabase; current_dbi++)
111             {
112                dbi = &ibi->rgDatabase[current_dbi];
113                char *tmp = new char[wcslen(dbi->wszDatabaseDisplayName) + 1];
114                wcstombs(tmp, dbi->wszDatabaseDisplayName, wcslen(dbi->wszDatabaseDisplayName) + 1);
115                if (stricmp(tmp, context->path_bits[level + 1]) == 0)
116                   break;
117                delete tmp;
118             }
119             if (current_dbi == ibi->cDatabase)
120             {
121                _JobMessage(M_ERROR, "Invalid Database '%s'\n", context->path_bits[level + 1]);
122                return bRC_Error;
123             }
124             store_node = new store_node_t(tmp, this);
125             _DebugMessage(100, "Database name = %s\n", store_node->name);
126             delete tmp;
127             store_node->hccx = hccx;
128             store_node->dbi = dbi;
129             context->current_node = store_node;
130          }
131          return bRC_OK;
132       case 2:
133          _DebugMessage(100, "Calling HrESEBackupGetLogAndPatchFiles\n");
134          result = HrESEBackupGetLogAndPatchFiles(hccx, &tmp_logfiles);
135          if (result != 0)
136          {
137             _JobMessage(M_ERROR, "HrESEBackupGetLogAndPatchFiles failed with error 0x%08x - %s\n", result, ESEErrorMessage(result));
138             return bRC_Error;
139          }
140          for (len = 0, tmp_logfile_ptr = tmp_logfiles; *tmp_logfile_ptr != 0; tmp_logfile_ptr += wcslen(tmp_logfile_ptr) + 1)
141          {
142             len += wcslen(tmp_logfile_ptr) + 1;
143          }
144          logfiles = new WCHAR[len + 1];
145          logfile_ptr = logfiles;
146          for (tmp_logfile_ptr = tmp_logfiles; *tmp_logfile_ptr != 0; tmp_logfile_ptr += wcslen(tmp_logfile_ptr) + 1)
147          {
148             // check file modification date
149             HANDLE handle;
150             FILETIME modified_time;
151             //int64_t tmp_time;
152             __int64 tmp_time;
153             bool include_file;
154             include_file = false;
155             handle = INVALID_HANDLE_VALUE;
156             if (context->job_since == 0)
157                include_file = true;
158             if (!include_file)
159             {
160                handle = CreateFileW(tmp_logfile_ptr, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
161                if (handle == INVALID_HANDLE_VALUE)
162                {
163                   //_JobMessage(M_WARNING, "Could not open '%S' to check last modified date (0x%08x), including anyway\n", tmp_logfile_ptr, GetLastError());
164                   include_file = true;
165                }
166             }
167             if (!include_file)
168             {
169                if (GetFileTime(handle, NULL, NULL, &modified_time) == 0)
170                {
171                   //_JobMessage(M_WARNING, "Could check last modified date for '%S' (0x%08x), including anyway\n", tmp_logfile_ptr, GetLastError());
172                   include_file = true;
173                }
174             }
175             if (!include_file)
176             {
177                tmp_time = (((int64_t)modified_time.dwHighDateTime) << 32) | modified_time.dwLowDateTime;
178                tmp_time -= 116444736000000000LL;
179                tmp_time /= 10000000;
180                if (tmp_time > context->job_since)
181                {
182                   include_file = true;
183                }
184             }
185             if (include_file)
186             {
187                memcpy(logfile_ptr, tmp_logfile_ptr, (wcslen(tmp_logfile_ptr) + 1) * 2);
188                logfile_ptr += wcslen(logfile_ptr) + 1;
189                //_DebugMessage(100, "Including file %S\n", logfile_ptr);
190             }
191             else
192             {
193                if (context->accurate) {
194                   tmp = new char[strlen(full_path) + wcslen(tmp_logfile_ptr) + 1];
195                   strcpy(tmp, full_path);
196                   wcstombs(tmp + strlen(full_path), tmp_logfile_ptr, wcslen(tmp_logfile_ptr) + 1);
197                   bfuncs->setBaculaValue(context->bpContext, bVarFileSeen, (void *)tmp);
198                   delete tmp;
199                }
200             }
201
202             if (handle != INVALID_HANDLE_VALUE)
203                CloseHandle(handle);
204
205          }
206          *logfile_ptr = 0;
207          logfile_ptr = logfiles;
208          state = 3;
209          break;
210       case 3:
211          tmp = new char[wcslen(logfile_ptr) + 1];
212          wcstombs(tmp, logfile_ptr, wcslen(logfile_ptr) + 1);
213          file_node = new file_node_t(tmp, this);
214          delete tmp;
215          file_node->hccx = hccx;
216          file_node->filename = logfile_ptr;
217          context->current_node = file_node;
218          return bRC_OK;
219       case 4:
220          time_t now = time(NULL);
221          sp->fname = full_path;
222          sp->link = full_path;
223          _DebugMessage(100, "fname = %s\n", sp->fname);
224          sp->statp.st_mode = 0700 | S_IFDIR;
225          sp->statp.st_ctime = now;
226          sp->statp.st_mtime = now;
227          sp->statp.st_atime = now;
228          sp->statp.st_size = 0;
229          //sp->statp.st_blocks = 0;
230          sp->type = FT_DIREND;
231          return bRC_OK;
232       }
233    }
234 }
235
236 bRC
237 storage_group_node_t::endBackupFile(exchange_fd_context_t *context)
238 {
239    HRESULT result;
240    bRC retval = bRC_Error;
241
242    _DebugMessage(100, "endBackupNode_STORAGE_GROUP state = %d\n", state);
243
244    switch(state)
245    {
246    case 0:
247       // should never happen
248       break;
249    case 1:
250       // free node->storage_group_node
251       if (context->path_bits[level + 1] == NULL)
252       {
253          current_dbi++;
254          if (current_dbi == ibi->cDatabase)
255             state = 2;
256       }
257       else
258          state = 2;
259       retval = bRC_More;
260       break;
261    case 2:
262       // should never happen
263       break;
264    case 3:
265       delete file_node;
266       logfile_ptr += wcslen(logfile_ptr) + 1;
267       if (*logfile_ptr == 0)
268          state = 4;
269       retval = bRC_More;
270       break;
271    case 4:
272       if (context->truncate_logs)
273       {
274          _DebugMessage(100, "Calling HrESEBackupTruncateLogs\n");
275          result = HrESEBackupTruncateLogs(hccx);
276          if (result != 0)
277          {
278             _JobMessage(M_ERROR, "HrESEBackupTruncateLogs failed with error 0x%08x - %s\n", result, ESEErrorMessage(result));
279          }
280          else
281          {
282             _JobMessage(M_INFO, "Truncated database logs for Storage Group %s\n", name);
283          }
284       }
285       else
286       {
287          _JobMessage(M_INFO, "Did NOT truncate database logs for Storage Group %s\n", name);
288       }
289       _DebugMessage(100, "Calling HrESEBackupInstanceEnd\n");
290       result = HrESEBackupInstanceEnd(hccx, ESE_BACKUP_INSTANCE_END_SUCCESS);
291       if (result != 0)
292       {
293          _JobMessage(M_ERROR, "HrESEBackupInstanceEnd failed with error 0x%08x - %s\n", result, ESEErrorMessage(result));
294          return bRC_Error;
295       }
296       retval = bRC_OK;
297       context->current_node = parent;
298       break;
299    }
300    return retval;
301 }
302
303 bRC
304 storage_group_node_t::createFile(exchange_fd_context_t *context, struct restore_pkt *rp)
305 {
306    HRESULT result;
307    int len;
308
309    _DebugMessage(0, "createFile_STORAGE_GROUP state = %d\n", state);
310
311    if (strcmp(context->path_bits[level], name) != 0)
312    {
313       _DebugMessage(0, "Different storage group - switching back to parent\n", state);
314       saved_log_path = new WCHAR[wcslen(restore_environment->m_wszRestoreLogPath) + 1];
315       wcscpy(saved_log_path, restore_environment->m_wszRestoreLogPath);
316       _DebugMessage(100, "Calling HrESERestoreSaveEnvironment\n");
317       result = HrESERestoreSaveEnvironment(hccx);
318       if (result != 0)
319       {
320          _JobMessage(M_ERROR, "HrESERestoreSaveEnvironment failed with error 0x%08x - %s\n", result, ESEErrorMessage(result));
321          state = 999;
322          rp->create_status = CF_CREATED;
323          return bRC_OK;
324       }
325       _DebugMessage(100, "Calling HrESERestoreClose\n");
326       result = HrESERestoreClose(hccx, RESTORE_CLOSE_NORMAL);
327       if (result != 0)
328       {
329          _JobMessage(M_ERROR, "HrESERestoreClose failed with error 0x%08x - %s\n", result, ESEErrorMessage(result));
330          state = 999;
331          rp->create_status = CF_CREATED;
332          return bRC_OK;
333       }
334       context->current_node = parent;
335       return bRC_OK;
336    }
337    if (saved_log_path != NULL)
338    {
339       _DebugMessage(0, "Calling HrESERestoreReopen\n");
340       result = HrESERestoreReopen(context->computer_name, service_name, saved_log_path, &hccx);
341       if (result != 0)
342       {
343          _JobMessage(M_ERROR, "HrESERestoreReopen failed with error 0x%08x - %s\n", result, ESEErrorMessage(result));
344          state = 999;
345          saved_log_path = NULL;
346          rp->create_status = CF_CREATED;
347          return bRC_OK;
348       }
349       _DebugMessage(0, "Calling HrESERestoreGetEnvironment\n");
350       result = HrESERestoreGetEnvironment(hccx, &restore_environment);
351       if (result != 0)
352       {
353          _JobMessage(M_ERROR, "HrESERestoreGetEnvironment failed with error 0x%08x - %s\n", result, ESEErrorMessage(result));
354          state = 999;
355          saved_log_path = NULL;
356          rp->create_status = CF_CREATED;
357          return bRC_OK;
358       }
359       saved_log_path = NULL;
360    }
361
362    for (;;)
363    {
364       switch (state)
365       {
366       case 0:
367          if (context->path_bits[level + 2] == NULL)
368          {
369             _JobMessage(M_ERROR, "Unexpected log file '%s%s' - expecting database\n", full_path, context->path_bits[level + 1]);
370             state = 999;
371             break;
372          }
373          service_name = new WCHAR[strlen(parent->name) + 1];
374          storage_group_name = new WCHAR[strlen(name) + 1];
375          mbstowcs(service_name, parent->name, strlen(parent->name) + 1);
376          mbstowcs(storage_group_name, name, strlen(name) + 1);
377          _DebugMessage(0, "Calling HrESERestoreOpen\n");
378          result = HrESERestoreOpen(context->computer_name, service_name, storage_group_name, NULL, &hccx);
379          if (result != 0)
380          {
381             _JobMessage(M_ERROR, "HrESERestoreOpen failed with error 0x%08x - %s\n", result, ESEErrorMessage(result));
382             state = 999;
383             break;
384          }
385          _DebugMessage(0, "Calling HrESERestoreGetEnvironment\n");
386          result = HrESERestoreGetEnvironment(hccx, &restore_environment);
387          if (result != 0)
388          {
389             _JobMessage(M_ERROR, "HrESERestoreGetEnvironment failed with error 0x%08x - %s\n", result, ESEErrorMessage(result));
390             state = 999;
391             break;
392          }
393          state = 1;
394          break;
395       case 1:
396          if (context->path_bits[level + 2] == NULL)
397          {
398             state = 2;
399             break;
400          }
401          store_node = new store_node_t(bstrdup(context->path_bits[level + 1]), this);
402          store_node->hccx = hccx;
403          context->current_node = store_node;
404          return bRC_OK;
405       case 2:
406          if (context->path_bits[level + 2] != NULL)
407          {
408             _JobMessage(M_ERROR, "Unexpected file '%s'\n", full_path);
409             state = 999;
410             break;
411          }
412          if (context->path_bits[level + 1] == NULL)
413          {
414             state = 3;
415             break;
416          }
417          state = 2;
418          file_node = new file_node_t(bstrdup(context->path_bits[level + 1]), this);
419          file_node->hccx = hccx;
420          int i;
421          for (i = strlen(file_node->name) - 1; i >= 0; i--)
422          {
423             if (file_node->name[i] == '\\')
424             {
425                i++;
426                break;
427             }
428          }
429          len = wcslen(restore_environment->m_wszRestoreLogPath) + strlen(file_node->name + i) + 1 + 1;
430          file_node->filename = new WCHAR[len];
431          wcscpy(file_node->filename, restore_environment->m_wszRestoreLogPath);
432          wcscat(file_node->filename, L"\\");
433          mbstowcs(&file_node->filename[wcslen(file_node->filename)], file_node->name + i, strlen(file_node->name + i) + 1);
434          context->current_node = file_node;
435          return bRC_OK;
436       case 3:
437          if (rp->type != FT_DIREND)
438          {
439             _JobMessage(M_ERROR, "Unexpected file '%s'\n", full_path);
440             state = 999;
441             break;
442          }
443          // must be the storage group node
444          _DebugMessage(100, "Calling HrESERestoreSaveEnvironment\n");
445          result = HrESERestoreSaveEnvironment(hccx);
446          if (result != 0)
447          {
448             _JobMessage(M_ERROR, "HrESERestoreSaveEnvironment failed with error 0x%08x - %s\n", result, ESEErrorMessage(result));
449             state = 999;
450             break;
451          }
452
453          _DebugMessage(100, "Calling HrESERestoreComplete\n");
454          result = HrESERestoreComplete(hccx, restore_environment->m_wszRestoreLogPath,
455             restore_environment->m_wszRestoreLogPath, storage_group_name, ESE_RESTORE_COMPLETE_ATTACH_DBS);
456          if (result != 0)
457          {
458             _JobMessage(M_ERROR, "HrESERestoreComplete failed with error 0x%08x - %s\n", result, ESEErrorMessage(result));
459             state = 999;
460             break;
461          }
462          else
463          {
464             _JobMessage(M_INFO, "Storage Group '%s' restored successfully\n", name);
465          }
466
467          _DebugMessage(100, "Calling HrESERestoreClose\n");
468          result = HrESERestoreClose(hccx, RESTORE_CLOSE_NORMAL);
469          if (result != 0)
470          {
471             _JobMessage(M_ERROR, "HrESERestoreClose failed with error 0x%08x - %s\n", result, ESEErrorMessage(result));
472             state = 999;
473             break;
474          }
475
476          rp->create_status = CF_CREATED;
477          return bRC_OK;
478       case 999:
479          rp->create_status = CF_CREATED;
480          return bRC_OK;
481       }
482    }
483 }
484
485 bRC
486 storage_group_node_t::endRestoreFile(exchange_fd_context_t *context)
487 {
488    _DebugMessage(0, "endRestoreFile_STORAGE_GROUP state = %d\n", state);
489    switch (state)
490    {
491    case 0:
492       return bRC_Error;
493    case 1:
494       return bRC_OK;
495    case 2:
496       return bRC_OK;
497    case 3:
498       context->current_node = parent;
499       return bRC_OK;
500    case 999:
501       return bRC_OK;
502    }
503
504    return bRC_Error;
505 }