From 89b0f7af2e3dd0a4de2c0eb1f8d3600a3e351938 Mon Sep 17 00:00:00 2001 From: Natalia Portillo Date: Tue, 31 Dec 2019 21:39:18 +0000 Subject: [PATCH] Move lead-out retrial. --- .../Devices/Dumping/CompactDisc/Dump.cs | 113 ++----------- .../Devices/Dumping/CompactDisc/LeadOuts.cs | 151 +++++++++++++++++- 2 files changed, 159 insertions(+), 105 deletions(-) diff --git a/DiscImageChef.Core/Devices/Dumping/CompactDisc/Dump.cs b/DiscImageChef.Core/Devices/Dumping/CompactDisc/Dump.cs index 6c6d522fb..57b07cc2c 100644 --- a/DiscImageChef.Core/Devices/Dumping/CompactDisc/Dump.cs +++ b/DiscImageChef.Core/Devices/Dumping/CompactDisc/Dump.cs @@ -1425,9 +1425,11 @@ namespace DiscImageChef.Core.Devices.Dumping EndProgress?.Invoke(); // TODO: Enable when underlying images support lead-outs + /* DumpCdLeadOuts(blocks, blockSize, ref currentSpeed, currentTry, extents, ibgLog, ref imageWriteDuration, leadOutExtents, ref maxSpeed, mhddLog, ref minSpeed, read6, read10, read12, read16, readcd, supportedSubchannel, subSize, ref totalDuration); + */ end = DateTime.UtcNow; mhddLog.Close(); @@ -1848,6 +1850,13 @@ namespace DiscImageChef.Core.Devices.Dumping EndProgress?.Invoke(); + // TODO: Enable when underlying images support lead-outs + /* + RetryCdLeadOuts(blocks, blockSize, ref currentSpeed, currentTry, extents, ibgLog, ref imageWriteDuration, + leadOutExtents, ref maxSpeed, mhddLog, ref minSpeed, read6, read10, read12, read16, readcd, + supportedSubchannel, subSize, ref totalDuration); + */ + // Try to ignore read errors, on some drives this allows to recover partial even if damaged data if(_persistent && sectorsNotEvenPartial.Count > 0) { @@ -1930,110 +1939,6 @@ namespace DiscImageChef.Core.Devices.Dumping if(runningPersistent && currentModePage.HasValue) { - // TODO: Enable when underlying images support lead-outs - /* - dumpLog.WriteLine("Retrying lead-outs"); - - InitProgress?.Invoke(); - foreach(Tuple leadout in leadOutExtents.ToArray()) - for(ulong i = leadout.Item1; i <= leadout.Item2; i++) - { - if(aborted) - { - currentTry.Extents = ExtentsConverter.ToMetadata(extents); - dumpLog.WriteLine("Aborted!"); - break; - } - - double cmdDuration = 0; - - #pragma warning disable RECS0018 // Comparison of floating point numbers with equality operator - if(currentSpeed > maxSpeed && currentSpeed != 0) maxSpeed = currentSpeed; - if(currentSpeed < minSpeed && currentSpeed != 0) minSpeed = currentSpeed; - #pragma warning restore RECS0018 // Comparison of floating point numbers with equality operator - - PulseProgress?.Invoke(string.Format("Reading sector {0} at lead-out ({1:F3} MiB/sec.)", i, - blocks, currentSpeed)); - - if(readcd) - { - sense = dev.ReadCd(out cmdBuf, out senseBuf, (uint)i, blockSize, 1, - MmcSectorTypes.AllTypes, false, false, true, - MmcHeaderCodes.AllHeaders, true, true, MmcErrorField.None, - supportedSubchannel, dev.Timeout, out cmdDuration); - totalDuration += cmdDuration; - } - else if(read16) - sense = dev.Read16(out cmdBuf, out senseBuf, 0, false, true, false, i, blockSize, 0, - 1, false, dev.Timeout, out cmdDuration); - else if(read12) - sense = dev.Read12(out cmdBuf, out senseBuf, 0, false, true, false, false, (uint)i, - blockSize, 0, 1, false, dev.Timeout, out cmdDuration); - else if(read10) - sense = dev.Read10(out cmdBuf, out senseBuf, 0, false, true, false, false, (uint)i, - blockSize, 0, 1, dev.Timeout, out cmdDuration); - else if(read6) - sense = dev.Read6(out cmdBuf, out senseBuf, (uint)i, blockSize, 1, dev.Timeout, - out cmdDuration); - - if(!sense && !dev.Error) - { - mhddLog.Write(i, cmdDuration); - ibgLog.Write(i, currentSpeed * 1024); - extents.Add(i, blocksToRead, true); - leadOutExtents.Remove(i); - DateTime writeStart = DateTime.Now; - if(supportedSubchannel != MmcSubchannel.None) - { - byte[] data = new byte[SECTOR_SIZE * blocksToRead]; - byte[] sub = new byte[subSize * blocksToRead]; - - for(int b = 0; b < blocksToRead; b++) - { - Array.Copy(cmdBuf, (int)(0 + b * blockSize), data, SECTOR_SIZE * b, - SECTOR_SIZE); - Array.Copy(cmdBuf, (int)(SECTOR_SIZE + b * blockSize), sub, subSize * b, - subSize); - } - - outputPlugin.WriteSectorsLong(data, i, blocksToRead); - outputPlugin.WriteSectorsTag(sub, i, blocksToRead, - SectorTagType.CdSectorSubchannel); - } - else outputPlugin.WriteSectors(cmdBuf, i, blocksToRead); - - imageWriteDuration += (DateTime.Now - writeStart).TotalSeconds; - } - else - { - // TODO: Reset device after X errors - if(stopOnError) return; // TODO: Return more cleanly - - // Write empty data - DateTime writeStart = DateTime.Now; - if(supportedSubchannel != MmcSubchannel.None) - { - outputPlugin.WriteSectorsLong(new byte[SECTOR_SIZE * skip], i, 1); - outputPlugin.WriteSectorsTag(new byte[subSize * skip], i, 1, - SectorTagType.CdSectorSubchannel); - } - else outputPlugin.WriteSectors(new byte[blockSize * skip], i, 1); - - imageWriteDuration += (DateTime.Now - writeStart).TotalSeconds; - - mhddLog.Write(i, cmdDuration < 500 ? 65535 : cmdDuration); - - ibgLog.Write(i, 0); - } - - double newSpeed = - (double)blockSize * blocksToRead / 1048576 / (cmdDuration / 1000); - if(!double.IsInfinity(newSpeed)) currentSpeed = newSpeed; - } - - EndProgress?.Invoke(); - */ - var md = new Modes.DecodedMode { Header = new Modes.ModeHeader(), Pages = new[] diff --git a/DiscImageChef.Core/Devices/Dumping/CompactDisc/LeadOuts.cs b/DiscImageChef.Core/Devices/Dumping/CompactDisc/LeadOuts.cs index 6b7f18878..575a2055d 100644 --- a/DiscImageChef.Core/Devices/Dumping/CompactDisc/LeadOuts.cs +++ b/DiscImageChef.Core/Devices/Dumping/CompactDisc/LeadOuts.cs @@ -45,7 +45,7 @@ namespace DiscImageChef.Core.Devices.Dumping { partial class Dump { - /// + /// Dumps inter-session lead-outs /// Total number of positive sectors /// Size of the read sector in bytes /// Current read speed @@ -194,5 +194,154 @@ namespace DiscImageChef.Core.Devices.Dumping EndProgress?.Invoke(); } + + /// Retries inter-session lead-outs + /// Total number of positive sectors + /// Size of the read sector in bytes + /// Current read speed + /// Current dump hardware try + /// Extents + /// IMGBurn log + /// Duration of image write + /// Lead-out extents + /// Maximum speed + /// MHDD log + /// Minimum speed + /// Device supports READ(6) + /// Device supports READ(10) + /// Device supports READ(12) + /// Device supports READ(16) + /// Device supports READ CD + /// Drive's maximum supported subchannel + /// Subchannel size in bytes + /// Total commands duration + void RetryCdLeadOuts(ulong blocks, uint blockSize, ref double currentSpeed, DumpHardwareType currentTry, + ExtentsULong extents, IbgLog ibgLog, ref double imageWriteDuration, + ExtentsULong leadOutExtents, ref double maxSpeed, MhddLog mhddLog, ref double minSpeed, + bool read6, bool read10, bool read12, bool read16, bool readcd, + MmcSubchannel supportedSubchannel, uint subSize, ref double totalDuration) + { + byte[] cmdBuf = null; // Data buffer + const uint sectorSize = 2352; // Full sector size + bool sense = true; // Sense indicator + + _dumpLog.WriteLine("Retrying lead-outs"); + + InitProgress?.Invoke(); + + foreach((ulong item1, ulong item2) in leadOutExtents.ToArray()) + for(ulong i = item1; i <= item2; i++) + { + if(_aborted) + { + currentTry.Extents = ExtentsConverter.ToMetadata(extents); + _dumpLog.WriteLine("Aborted!"); + + break; + } + + double cmdDuration = 0; + + #pragma warning disable RECS0018 // Comparison of floating point numbers with equality operator + + // ReSharper disable CompareOfFloatsByEqualityOperator + if(currentSpeed > maxSpeed && + currentSpeed != 0) + maxSpeed = currentSpeed; + + if(currentSpeed < minSpeed && + currentSpeed != 0) + minSpeed = currentSpeed; + + // ReSharper restore CompareOfFloatsByEqualityOperator + #pragma warning restore RECS0018 // Comparison of floating point numbers with equality operator + + PulseProgress?.Invoke(string.Format("Reading sector {0} at lead-out ({1:F3} MiB/sec.)", i, blocks, + currentSpeed)); + + if(readcd) + { + sense = _dev.ReadCd(out cmdBuf, out _, (uint)i, blockSize, 1, MmcSectorTypes.AllTypes, false, + false, true, MmcHeaderCodes.AllHeaders, true, true, MmcErrorField.None, + supportedSubchannel, _dev.Timeout, out cmdDuration); + + totalDuration += cmdDuration; + } + else if(read16) + sense = _dev.Read16(out cmdBuf, out _, 0, false, true, false, i, blockSize, 0, 1, false, + _dev.Timeout, out cmdDuration); + else if(read12) + sense = _dev.Read12(out cmdBuf, out _, 0, false, true, false, false, (uint)i, blockSize, 0, 1, + false, _dev.Timeout, out cmdDuration); + else if(read10) + sense = _dev.Read10(out cmdBuf, out _, 0, false, true, false, false, (uint)i, blockSize, 0, 1, + _dev.Timeout, out cmdDuration); + else if(read6) + sense = _dev.Read6(out cmdBuf, out _, (uint)i, blockSize, 1, _dev.Timeout, out cmdDuration); + + if(!sense && + !_dev.Error) + { + mhddLog.Write(i, cmdDuration); + ibgLog.Write(i, currentSpeed * 1024); + extents.Add(i, _maximumReadable, true); + leadOutExtents.Remove(i); + DateTime writeStart = DateTime.Now; + + if(supportedSubchannel != MmcSubchannel.None) + { + byte[] data = new byte[sectorSize * _maximumReadable]; + byte[] sub = new byte[subSize * _maximumReadable]; + + for(int b = 0; b < _maximumReadable; b++) + { + Array.Copy(cmdBuf, (int)(0 + (b * blockSize)), data, sectorSize * b, + sectorSize); + + Array.Copy(cmdBuf, (int)(sectorSize + (b * blockSize)), sub, subSize * b, subSize); + } + + _outputPlugin.WriteSectorsLong(data, i, _maximumReadable); + _outputPlugin.WriteSectorsTag(sub, i, _maximumReadable, SectorTagType.CdSectorSubchannel); + } + else + _outputPlugin.WriteSectors(cmdBuf, i, _maximumReadable); + + imageWriteDuration += (DateTime.Now - writeStart).TotalSeconds; + } + else + { + // TODO: Reset device after X errors + if(_stopOnError) + return; // TODO: Return more cleanly + + // Write empty data + DateTime writeStart = DateTime.Now; + + if(supportedSubchannel != MmcSubchannel.None) + { + _outputPlugin.WriteSectorsLong(new byte[sectorSize * _skip], i, 1); + + _outputPlugin.WriteSectorsTag(new byte[subSize * _skip], i, 1, + SectorTagType.CdSectorSubchannel); + } + else + _outputPlugin.WriteSectors(new byte[blockSize * _skip], i, 1); + + imageWriteDuration += (DateTime.Now - writeStart).TotalSeconds; + + mhddLog.Write(i, cmdDuration < 500 ? 65535 : cmdDuration); + + ibgLog.Write(i, 0); + } + + double newSpeed = ((double)blockSize * _maximumReadable) / 1048576 / (cmdDuration / 1000); + + if(!double.IsInfinity(newSpeed)) + currentSpeed = newSpeed; + } + + EndProgress?.Invoke(); + } } } \ No newline at end of file