hp-raid45-recovery/hp-raid45-recovery/CopyProcess.cs
2020-05-22 13:25:22 +02:00

131 lines
4.9 KiB
C#

using System;
using System.IO;
namespace BlubbFish.Tools.Raid.HP.Raid45
{
internal class CopyProcess
{
public Int32[,] Mode { get; }
public UInt32 Sector { get; private set; }
public UInt32 Stripe { get; private set; }
public UInt32 Parity { get; private set; }
public Int64 Start { get; private set; }
public Int64 End { get; private set; }
public FileStream[] InputDisks { get; private set; }
public FileStream OutputDisk { get; private set; }
public CopyProcess() {
this.Mode = new Int32[4, 3] {
{ 0, 1, 2 },
{ 0, 1, 3 },
{ 0, 2, 3 },
{ 1, 2, 3 }
};
}
internal void SetInputFiles(String disk1, String disk2, String disk3, String disk4) {
this.InputDisks = new FileStream[] {
File.OpenRead(disk1),
File.OpenRead(disk2),
File.OpenRead(disk3),
File.OpenRead(disk4)
};
}
internal void SetOutputFile(String output) {
this.OutputDisk = File.OpenWrite(output);
}
private void Close() {
this.OutputDisk.Close();
this.InputDisks[0].Close();
this.InputDisks[1].Close();
this.InputDisks[2].Close();
this.InputDisks[3].Close();
}
internal void SetParameters(UInt32 sector, UInt32 stripe, UInt32 parity) {
this.Sector = sector;
this.Stripe = stripe;
this.Parity = parity;
}
internal void SetStartEnd(Int64 start, Int64 end) {
this.Start = start;
this.End = end;
}
internal void Running() {
Int64 incount = this.Start / this.Stripe;
Int64 outcount = 0;
Console.WriteLine("alloc buffer " + this.Sector);
Span<Byte> buffer = new Span<Byte>(new Byte[this.Sector]);
UInt32 startmode = (UInt32)(this.Start / (this.Stripe * this.Parity)) % 4;
while (true) {
for (UInt32 diskmode = startmode; diskmode < 4; diskmode++) {
Console.WriteLine("Disk Mode: " + diskmode + ", [" + this.Mode[diskmode, 0] + ", " + this.Mode[diskmode, 1] + ", " + this.Mode[diskmode, 2] + "]");
for (UInt32 paritys = 0; paritys < this.Parity; paritys++) {
try {
for (UInt32 disk = 0; disk < 3; disk++) {
this.Copy(this.Mode[diskmode, disk], incount, outcount, buffer);
outcount++;
}
} catch (Exception e) {
Console.WriteLine("We have an Error while copy, maybe we are at EOF.\n\n" + e.Message);
this.Close();
return;
}
incount++;
if (incount * this.Stripe >= this.End && this.End != 0) {
Console.WriteLine("done");
this.Close();
return;
}
}
}
startmode = 0;
}
}
private void Copy(Int32 inputdisk, Int64 incount, Int64 outcount, Span<Byte> buffer) {
try {
if(this.InputDisks[inputdisk].Length <= incount * this.Stripe * this.Sector) {
throw new OverflowException("EOF of " + this.InputDisks[inputdisk].Name + " reached");
}
if(this.InputDisks[inputdisk].Length <= (incount * this.Stripe * this.Sector) + this.Sector) {
buffer.Clear();
}
this.InputDisks[inputdisk].Seek(incount * this.Stripe * this.Sector, SeekOrigin.Begin);
this.InputDisks[inputdisk].Read(buffer);
} catch (Exception e) {
Console.WriteLine("Error while reading: " + this.InputDisks[inputdisk].Name);
Console.WriteLine(this.InputDisks[inputdisk].Name + " Seek(" + incount * this.Stripe * this.Sector + ", Begin)");
Console.WriteLine(this.InputDisks[inputdisk].Name + " Read(" + buffer.Length + ", 0, " + (Int32)this.Sector + ")");
throw e;
}
try {
this.OutputDisk.Seek(outcount * this.Stripe * this.Sector, SeekOrigin.Begin);
this.OutputDisk.Write(buffer);
this.OutputDisk.Flush();
} catch (Exception e) {
Console.WriteLine("Error while writing: " + this.OutputDisk.Name);
Console.WriteLine(this.OutputDisk.Name + "Seek(" + outcount * this.Stripe * this.Sector + ", Begin)");
Console.WriteLine(this.OutputDisk.Name + " Write(" + buffer.Length + ", 0, " + (Int32)this.Sector + ")");
Console.WriteLine(this.OutputDisk.Name + "Flush()");
throw e;
}
Console.WriteLine("["+Math.Round(((Double)outcount/4)*100, 3)+"] " +
"Copy disk" + (inputdisk + 1) + " " +
"[" + (incount * this.Stripe) + " s, " + ((incount + 1) * this.Stripe) + " s] " +
"(" + (incount * this.Stripe * this.Sector) + " b, " + ((incount + 1) * this.Stripe * this.Sector) + " b) " +
"-> out " +
"[" + (outcount * this.Stripe) + " s, " + ((outcount + 1) * this.Stripe) + " s] " +
"(" + (outcount * this.Stripe * this.Sector) + " b, " + ((outcount + 1) * this.Stripe * this.Sector) + " b)");
}
}
}