-
Notifications
You must be signed in to change notification settings - Fork 820
/
BackupOperation.cs
140 lines (129 loc) · 4.5 KB
/
BackupOperation.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
//-----------------------------------------------------------------------
// <copyright file="BackupOperation.cs" company="Hibernating Rhinos LTD">
// Copyright (c) Hibernating Rhinos LTD. All rights reserved.
// </copyright>
//-----------------------------------------------------------------------
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Microsoft.Isam.Esent.Interop;
using NLog;
using Raven.Abstractions;
using Raven.Abstractions.Extensions;
using Raven.Database;
using Raven.Database.Backup;
using Raven.Database.Extensions;
using Raven.Json.Linq;
namespace Raven.Storage.Esent.Backup
{
public class BackupOperation
{
private readonly JET_INSTANCE instance;
private readonly DocumentDatabase database;
private string to;
private readonly bool incrementalBackup;
private string src;
private static readonly Logger log = LogManager.GetCurrentClassLogger();
public BackupOperation(DocumentDatabase database, string src, string to, bool incrementalBackup)
{
instance = ((TransactionalStorage)database.TransactionalStorage).Instance;
this.src = src;
this.to = to;
this.incrementalBackup = incrementalBackup;
this.database = database;
this.src = src;
this.to = to;
}
public void Execute(object ignored)
{
try
{
to = to.ToFullPath();
src = src.ToFullPath();
log.Info("Starting backup of '{0}' to '{1}'", src, to);
var directoryBackups = new List<DirectoryBackup>
{
new DirectoryBackup(Path.Combine(src, "IndexDefinitions"), Path.Combine(to, "IndexDefinitions"), Path.Combine(src, "Temp" + Guid.NewGuid().ToString("N")))
};
directoryBackups.AddRange(from index in Directory.GetDirectories(database.Configuration.IndexStoragePath)
let fromIndex = Path.Combine(database.Configuration.IndexStoragePath, Path.GetFileName(index))
let toIndex = Path.Combine(to, "Indexes", Path.GetFileName(index))
let tempIndex = Path.Combine(src, Path.Combine("BackupTempDirectories",Guid.NewGuid().ToString("N")))
select new DirectoryBackup(fromIndex, toIndex, tempIndex));
foreach (var directoryBackup in directoryBackups)
{
directoryBackup.Notify += UpdateBackupStatus;
directoryBackup.Prepare();
}
foreach (var directoryBackup in directoryBackups)
{
directoryBackup.Execute();
}
var esentBackup = new EsentBackup(instance, to, incrementalBackup ? BackupGrbit.Incremental : BackupGrbit.Atomic);
esentBackup.Notify+=UpdateBackupStatus;
esentBackup.Execute();
}
catch (Exception e)
{
log.ErrorException("Failed to complete backup", e);
UpdateBackupStatus("Failed to complete backup because: " + e.Message, BackupStatus.BackupMessageSeverity.Error);
}
finally
{
CompleteBackup();
}
}
private void CompleteBackup()
{
try
{
log.Info("Backup completed");
var jsonDocument = database.Get(BackupStatus.RavenBackupStatusDocumentKey, null);
if (jsonDocument == null)
return;
var backupStatus = jsonDocument.DataAsJson.JsonDeserialization<BackupStatus>();
backupStatus.IsRunning = false;
backupStatus.Completed = SystemTime.UtcNow;
database.Put(BackupStatus.RavenBackupStatusDocumentKey, null, RavenJObject.FromObject(backupStatus),
jsonDocument.Metadata,
null);
}
catch (Exception e)
{
log.WarnException("Failed to update completed backup status, will try deleting document", e);
try
{
database.Delete(BackupStatus.RavenBackupStatusDocumentKey, null, null);
}
catch (Exception ex)
{
log.WarnException("Failed to remove out of date backup status", ex);
}
}
}
private void UpdateBackupStatus(string newMsg, BackupStatus.BackupMessageSeverity severity)
{
try
{
log.Info(newMsg);
var jsonDocument = database.Get(BackupStatus.RavenBackupStatusDocumentKey, null);
if(jsonDocument==null)
return;
var backupStatus = jsonDocument.DataAsJson.JsonDeserialization<BackupStatus>();
backupStatus.Messages.Add(new BackupStatus.BackupMessage
{
Message = newMsg,
Timestamp = SystemTime.UtcNow,
Severity = severity
});
database.Put(BackupStatus.RavenBackupStatusDocumentKey, null, RavenJObject.FromObject(backupStatus), jsonDocument.Metadata,
null);
}
catch (Exception e)
{
log.WarnException("Failed to update backup status", e);
}
}
}
}