Skip to content

Commit

Permalink
Merge pull request #17 from professor-k/master
Browse files Browse the repository at this point in the history
Unobtrusive backups using built in backup functionality build into bedrock-server.  Replaces the old code that stopped, copied and restarted the server(s)
  • Loading branch information
ravetroll authored Sep 22, 2024
2 parents 35f8965 + 568c919 commit 9d0e543
Show file tree
Hide file tree
Showing 5 changed files with 110 additions and 42 deletions.
5 changes: 5 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
root = true

[*.cs]
indent_style = space
indent_size = 4
42 changes: 42 additions & 0 deletions BedrockService/BackupFile.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
using System;
using System.Collections.Generic;
using System.Linq;

namespace BedrockService
{
internal class BackupFile
{
public long Length { get; }

public string Path { get; }

private BackupFile(string path, long length)
{
Path = path;
Length = length;
}

public static bool IsBackupSpecification(string input)
{
return input?.Contains(".ldb:") ?? false;
}

public static List<BackupFile> ParseBackupSpecification(string input)
{
return input
.Split(new[] { ", " }, StringSplitOptions.RemoveEmptyEntries)
.Select(ParseFileSpec)
.ToList();
}

private static BackupFile ParseFileSpec(string fileSpec)
{
var chunks = fileSpec.Split(':');

// bedrock server returns paths with forward slashes,
// but since we're on windows we need to convert them to backslashes
var path = chunks[0].Replace('/', '\\');
return new BackupFile(path, long.Parse(chunks[1]));
}
}
}
85 changes: 60 additions & 25 deletions BedrockService/BedrockServerWrapper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -241,52 +241,80 @@ public static Stream GenerateStreamFromString(string s)

public void Backup()
{
if (string.IsNullOrEmpty(this.ServerConfig.BackupFolderName))
{
return;
}

try
{

BackingUp = true;
FileInfo exe = new FileInfo(ServerConfig.BedrockServerExeLocation);

if (ServerConfig.BackupFolderName.Length > 0)

process.StandardInput.WriteLine("save hold");
Thread.Sleep(100);

List<BackupFile> backupFiles;
while (true)
{
DirectoryInfo backupTo;
if (Directory.Exists(ServerConfig.BackupFolderName))
{
backupTo = new DirectoryInfo(ServerConfig.BackupFolderName);
}
else if (exe.Directory.GetDirectories().Count(t => t.Name == ServerConfig.BackupFolderName) == 1)
{
backupTo = exe.Directory.GetDirectories().Single(t => t.Name == ServerConfig.BackupFolderName);
}
else
process.StandardInput.WriteLine("save query");
Thread.Sleep(100);
var lastLine = GetLastConsoleLine();
if (BackupFile.IsBackupSpecification(lastLine))
{
backupTo = exe.Directory.CreateSubdirectory(ServerConfig.BackupFolderName);
backupFiles = BackupFile.ParseBackupSpecification(lastLine);
break;
}

var sourceDirectory = exe.Directory.GetDirectories().Single(t => t.Name == worldsFolder);
var targetDirectory = backupTo.CreateSubdirectory($"{worldsFolder}{DateTime.Now.ToString("yyyyMMddhhmmss")}");
CopyFilesRecursively(sourceDirectory, targetDirectory);


}

FileInfo exe = new FileInfo(ServerConfig.BedrockServerExeLocation);

DirectoryInfo backupTo;
if (Directory.Exists(ServerConfig.BackupFolderName))
{
backupTo = new DirectoryInfo(ServerConfig.BackupFolderName);
}
else if (exe.Directory.GetDirectories().Count(t => t.Name == ServerConfig.BackupFolderName) == 1)
{
backupTo = exe.Directory.GetDirectories().Single(t => t.Name == ServerConfig.BackupFolderName);
}
else
{
backupTo = exe.Directory.CreateSubdirectory(ServerConfig.BackupFolderName);
}

var sourceDirectory = exe.Directory.GetDirectories().Single(t => t.Name == worldsFolder);
var targetDirectory = backupTo.CreateSubdirectory($"{worldsFolder}{DateTime.Now.ToString("yyyyMMddhhmmss")}");
CopyBackupFiles(sourceDirectory, targetDirectory, backupFiles);
}
catch (Exception e)
{
_log.Error($"Error with Backup", e);
}
finally
{
process.StandardInput.WriteLine("save resume");
BackingUp = false;
}
}

private static void CopyFilesRecursively(DirectoryInfo source, DirectoryInfo target)
private static void CopyBackupFiles(DirectoryInfo source, DirectoryInfo target, List<BackupFile> backupFiles)
{
_log.Info("Starting Backup");
foreach (DirectoryInfo dir in source.GetDirectories())
CopyFilesRecursively(dir, target.CreateSubdirectory(dir.Name));
foreach (FileInfo file in source.GetFiles())
file.CopyTo(Path.Combine(target.FullName, file.Name));

foreach (var file in backupFiles)
{
var destFileName = Path.Combine(target.FullName, file.Path);

// Make sure that target directory exists
new FileInfo(destFileName).Directory.Create();

File.Copy(Path.Combine(source.FullName, file.Path), destFileName);

// This trims file to specified length
new FileStream(destFileName, FileMode.Open).SetLength(file.Length);
}

_log.Info("Finished Backup");
}

Expand All @@ -308,5 +336,12 @@ public string GetCurrentConsole()

return sendConsole;
}

private string GetLastConsoleLine()
{
return GetCurrentConsole()
.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries)
.LastOrDefault();
}
}
}
5 changes: 3 additions & 2 deletions BedrockService/BedrockService.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,8 @@
<Reference Include="INIFileParser, Version=2.5.2.0, Culture=neutral, PublicKeyToken=79af7b307b65cf3c, processorArchitecture=MSIL">
<HintPath>packages\ini-parser.2.5.2\lib\net20\INIFileParser.dll</HintPath>
</Reference>
<Reference Include="log4net, Version=2.0.8.0, Culture=neutral, PublicKeyToken=669e0ddf0bb1aa2a, processorArchitecture=MSIL">
<HintPath>packages\log4net.2.0.8\lib\net45-full\log4net.dll</HintPath>
<Reference Include="log4net, Version=2.0.9.0, Culture=neutral, PublicKeyToken=669e0ddf0bb1aa2a, processorArchitecture=MSIL">
<HintPath>packages\log4net.2.0.10\lib\net45\log4net.dll</HintPath>
</Reference>
<Reference Include="NCrontab.Signed, Version=3.3.2.0, Culture=neutral, PublicKeyToken=5247b4370afff365, processorArchitecture=MSIL">
<HintPath>packages\NCrontab.Signed.3.3.2\lib\net35\NCrontab.Signed.dll</HintPath>
Expand All @@ -93,6 +93,7 @@
</ItemGroup>
<ItemGroup>
<Compile Include="AppSettings.cs" />
<Compile Include="BackupFile.cs" />
<Compile Include="BedrockServerWrapper.cs" />
<Compile Include="BedrockServiceWrapper.cs" />
<Compile Include="IWCFConsoleServer.cs" />
Expand Down
15 changes: 0 additions & 15 deletions BedrockService/BedrockServiceWrapper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -133,24 +133,9 @@ private void CronTimer_Elapsed(object sender, ElapsedEventArgs e)

private void Backup()
{
foreach (var brs in bedrockServers.OrderByDescending(t => t.ServerConfig.Primary).ToList())
{
brs.Stopping = true;
if (!stopping) brs.StopControl();
Thread.Sleep(1000);
}

foreach (var brs in bedrockServers.OrderByDescending(t => t.ServerConfig.Primary).ToList())
{
if (!stopping) brs.Backup();

}
foreach (var brs in bedrockServers.OrderByDescending(t => t.ServerConfig.Primary).ToList())
{
brs.Stopping = false;
if (!stopping) brs.StartControl(_hostControl);
Thread.Sleep(2000);

}
}

Expand Down

0 comments on commit 9d0e543

Please sign in to comment.