2024-11-08 03:55:46 +01:00
using System ;
2024-11-08 05:56:48 +01:00
using System.Linq ;
2024-11-08 03:55:46 +01:00
using System.Threading.Tasks ;
using CoCoL ;
2024-11-08 05:56:48 +01:00
using Duplicati.Library.Main.Database ;
2024-11-08 03:55:46 +01:00
namespace Duplicati.Library.Main.Operation.Restore
{
internal class FileProcessor
{
2024-11-08 08:45:00 +01:00
public static Task Run ( LocalRestoreDatabase db , IChannel <( long , long )> block_request , IChannel < byte []> block_response )
2024-11-08 03:55:46 +01:00
{
return AutomationExtensions . RunTask (
new
{
Input = Channels . filesToRestore . ForRead ,
},
async self =>
{
2024-11-08 05:56:48 +01:00
// TODO preallocate the file size to avoid fragmentation / help the operating system / filesystem. Verify this in a benchmark - I think it relies on OS and filesystem.
// using (var fs = new FileStream(path, FileMode.OpenOrCreate, FileAccess.Write, FileShare.None) { fs.SetLength(size); fs.Seek(0, SeekOrigin.Begin); }
2024-11-08 03:55:46 +01:00
//while (true)
{
var file = await self . Input . ReadAsync ();
if ( file == null )
{
//break;
}
Console . WriteLine ( $"Got file to restore: '{file.Path}', {file.Length} bytes, {file.Hash}" );
2024-11-08 05:56:48 +01:00
2024-11-08 08:02:17 +01:00
var blocks = db . Connection . CreateCommand (). ExecuteReaderEnumerable ( @ $"SELECT Block.ID, Block.Hash, Block.Size, Block.VolumeID FROM BlocksetEntry INNER JOIN Block ON BlocksetEntry.BlockID = Block.ID WHERE BlocksetEntry.BlocksetID = ""{file.BlocksetID}""" ). Select ( x => ( x . GetInt64 ( 0 ), x . GetString ( 1 ), x . GetInt64 ( 2 ), x . GetInt64 ( 3 ))). ToList ();
2024-11-08 07:20:18 +01:00
2024-11-08 08:02:17 +01:00
foreach ( var ( id , hash , size , vid ) in blocks )
2024-11-08 07:20:18 +01:00
{
2024-11-08 08:45:00 +01:00
await block_request . WriteAsync (( id , vid ));
var data = await block_response . ReadAsync ();
2024-11-08 07:20:18 +01:00
}
2024-11-08 03:55:46 +01:00
}
});
}
}
}