2020-10-17 23:30:15 +01:00
// /***************************************************************************
// Aaru Data Preservation Suite
// ----------------------------------------------------------------------------
//
// Filename : Data.cs
// Author(s) : Natalia Portillo <claunia@claunia.com>
//
// --[ License ] --------------------------------------------------------------
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
// ----------------------------------------------------------------------------
// Copyright © 2011-2020 Natalia Portillo
// ****************************************************************************/
using System ;
using Aaru.CommonTypes.Extents ;
using Aaru.Core.Logging ;
using Schemas ;
// ReSharper disable JoinDeclarationAndInitializer
// ReSharper disable InlineOutVariableDeclaration
// ReSharper disable TooWideLocalVariableScope
namespace Aaru.Core.Devices.Dumping
{
partial class Dump
{
void ReadSbcData ( in ulong blocks , in uint maxBlocksToRead , in uint blockSize , DumpHardwareType currentTry ,
ExtentsULong extents , ref double currentSpeed , ref double minSpeed , ref double maxSpeed ,
ref double totalDuration , Reader scsiReader , MhddLog mhddLog , IbgLog ibgLog ,
ref double imageWriteDuration , ref bool newTrim )
{
ulong sectorSpeedStart = 0 ;
bool sense ;
DateTime timeSpeedStart = DateTime . UtcNow ;
byte [ ] buffer ;
uint blocksToRead = maxBlocksToRead ;
2020-10-23 01:21:35 +01:00
InitProgress ? . Invoke ( ) ;
2020-10-17 23:30:15 +01:00
for ( ulong i = _resume . NextBlock ; i < blocks ; i + = blocksToRead )
{
if ( _aborted )
{
currentTry . Extents = ExtentsConverter . ToMetadata ( extents ) ;
UpdateStatus ? . Invoke ( "Aborted!" ) ;
_dumpLog . WriteLine ( "Aborted!" ) ;
break ;
}
if ( blocks - i < blocksToRead )
blocksToRead = ( uint ) ( blocks - i ) ;
if ( currentSpeed > maxSpeed & &
currentSpeed > 0 )
maxSpeed = currentSpeed ;
if ( currentSpeed < minSpeed & &
currentSpeed > 0 )
minSpeed = currentSpeed ;
UpdateProgress ? . Invoke ( $"Reading sector {i} of {blocks} ({currentSpeed:F3} MiB/sec.)" , ( long ) i ,
( long ) blocks ) ;
2020-10-23 01:21:35 +01:00
sense = scsiReader . ReadBlocks ( out buffer , i , blocksToRead , out double cmdDuration , out _ , out _ ) ;
2020-10-17 23:30:15 +01:00
totalDuration + = cmdDuration ;
if ( ! sense & &
! _dev . Error )
{
mhddLog . Write ( i , cmdDuration ) ;
ibgLog . Write ( i , currentSpeed * 1024 ) ;
DateTime writeStart = DateTime . Now ;
_outputPlugin . WriteSectors ( buffer , i , blocksToRead ) ;
imageWriteDuration + = ( DateTime . Now - writeStart ) . TotalSeconds ;
extents . Add ( i , blocksToRead , true ) ;
}
else
{
if ( _dev . Manufacturer . ToLowerInvariant ( ) = = "insite" )
{
_resume . BadBlocks . Add ( i ) ;
_resume . NextBlock + + ;
_aborted = true ;
_dumpLog ? .
WriteLine ( "INSITE floptical drives get crazy on the SCSI bus when an error is found, stopping so you can reboot the computer or reset the scsi bus appropriately." ) ;
UpdateStatus ? .
Invoke ( "INSITE floptical drives get crazy on the SCSI bus when an error is found, stopping so you can reboot the computer or reset the scsi bus appropriately" ) ;
continue ;
}
// TODO: Reset device after X errors
if ( _stopOnError )
return ; // TODO: Return more cleanly
if ( i + _skip > blocks )
_skip = ( uint ) ( blocks - i ) ;
// Write empty data
DateTime writeStart = DateTime . Now ;
_outputPlugin . WriteSectors ( new byte [ blockSize * _skip ] , i , _skip ) ;
imageWriteDuration + = ( DateTime . Now - writeStart ) . TotalSeconds ;
for ( ulong b = i ; b < i + _skip ; b + + )
_resume . BadBlocks . Add ( b ) ;
mhddLog . Write ( i , cmdDuration < 500 ? 65535 : cmdDuration ) ;
ibgLog . Write ( i , 0 ) ;
_dumpLog . WriteLine ( "Skipping {0} blocks from errored block {1}." , _skip , i ) ;
i + = _skip - blocksToRead ;
newTrim = true ;
}
sectorSpeedStart + = blocksToRead ;
_resume . NextBlock = i + blocksToRead ;
double elapsed = ( DateTime . UtcNow - timeSpeedStart ) . TotalSeconds ;
if ( elapsed < 1 )
continue ;
currentSpeed = ( sectorSpeedStart * blockSize ) / ( 1048576 * elapsed ) ;
sectorSpeedStart = 0 ;
timeSpeedStart = DateTime . UtcNow ;
}
2020-10-23 01:21:35 +01:00
EndProgress ? . Invoke ( ) ;
2020-10-17 23:30:15 +01:00
}
}
}