131 lines
4.9 KiB
C#
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)");
|
|||
|
}
|
|||
|
}
|
|||
|
}
|