Files
duplicati/Duplicati/Library/Main/ForestHash/Volumes/VolumeBase.cs
T
kenneth@hexad.dk a0521da54d Initial version of the new block-based storage format.
Still needs a work over in terms of error handling, progress reporting, warning output, refactoring etc.
Also misses the volume reuse/reclaim algorithms.
But it passes the unit tests now, with and without a local database.

git-svn-id: https://duplicati.googlecode.com/svn/sandboxes/Kenneth/ForestHash@1526 59da171f-624f-0410-aa54-27559c288bec
2013-02-12 21:43:14 +00:00

108 lines
4.4 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Newtonsoft.Json;
namespace Duplicati.Library.Main.ForestHash.Volumes
{
public abstract class VolumeBase
{
protected class ManifestData
{
private const string ENCODING = "utf8";
private const string PRIMARYHASH = "sha256";
private const long VERSION = 1;
public long Version;
public string Created;
public string Encoding;
public long Blocksize;
public string PrimaryHash;
public static string GetManifestInstance(long blocksize)
{
return JsonConvert.SerializeObject(new ManifestData()
{
Version = VERSION,
Encoding = ENCODING,
Blocksize = blocksize,
Created = Utility.Utility.SerializeDateTime(DateTime.UtcNow),
PrimaryHash = PRIMARYHASH,
});
}
public static void VerifyManifest(string manifest, long blocksize)
{
var d = JsonConvert.DeserializeObject<ManifestData>(manifest);
if (d.Version > VERSION)
throw new InvalidManifestException("Version", d.Version.ToString(), VERSION.ToString());
if (d.Encoding != ENCODING)
throw new InvalidManifestException("Encoding", d.Encoding, ENCODING);
if (d.PrimaryHash != PRIMARYHASH)
throw new InvalidManifestException("PrimaryHash", d.PrimaryHash, PRIMARYHASH);
}
}
private class ParsedVolume : IParsedVolume
{
public RemoteVolumeType FileType { get; private set; }
public string Prefix { get; private set; }
public string Guid { get; private set; }
public DateTime Time { get; private set; }
public string CompressionModule { get; private set; }
public string EncryptionModule { get; private set; }
public Library.Interface.IFileEntry File { get; private set; }
private static readonly System.Text.RegularExpressions.Regex FILENAME_REGEXP = new System.Text.RegularExpressions.Regex(@"(?<prefix>[^\-]+)\-(?<filetype>(" + string.Join(")|(", Enum.GetNames(typeof(RemoteVolumeType))).ToLowerInvariant() + @"))\-(((?<guid>[0-9A-Fa-f]+)|(?<time>\d{8}T\d{6}Z)))\.(?<compression>[^\.]+)(\.(?<encryption>.+))?");
private ParsedVolume() { }
public static IParsedVolume Parse(string filename, Library.Interface.IFileEntry file = null)
{
var m = FILENAME_REGEXP.Match(filename);
if (!m.Success || m.Length != filename.Length)
return null;
return new ParsedVolume()
{
Prefix = m.Groups["prefix"].Value,
FileType = (RemoteVolumeType)Enum.Parse(typeof(RemoteVolumeType), m.Groups["filetype"].Value, true),
Guid = m.Groups["guid"].Success ? m.Groups["guid"].Value : null,
Time = m.Groups["time"].Success ? DateTime.ParseExact(m.Groups["time"].Value, "yyyyMMdd'T'HHmmssK", null, System.Globalization.DateTimeStyles.AssumeUniversal).ToUniversalTime() : new DateTime(0, DateTimeKind.Local),
CompressionModule = m.Groups["compression"].Value,
EncryptionModule = m.Groups["encryption"].Success ? m.Groups["encryption"].Value : null,
File = file
};
}
}
public static IParsedVolume ParseFilename(Library.Interface.IFileEntry file)
{
return ParsedVolume.Parse(file.Name, file);
}
public static IParsedVolume ParseFilename(string filename)
{
return ParsedVolume.Parse(filename);
}
protected const string MANIFEST_FILENAME = "manifest";
protected const string FILELIST = "filelist.json";
protected const string SHADOW_VOLUME_FOLDER = "vol/";
protected const string SHADOW_BLOCKLIST_FOLDER = "list/";
protected const string CONTROL_FILES_FOLDER = "extra/";
public static readonly System.Text.Encoding ENCODING = System.Text.Encoding.UTF8;
protected readonly long m_blocksize;
public VolumeBase(FhOptions options)
{
m_blocksize = options.Fhblocksize;
}
}
}