Skip to content

Commit 3d063e9

Browse files
committed
Rereading disks through the GUI now works.
1 parent 157ec56 commit 3d063e9

File tree

9 files changed

+141
-39
lines changed

9 files changed

+141
-39
lines changed

lib/algorithms/readerwriter.cc

Lines changed: 52 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -349,7 +349,7 @@ static void adjustTrackOnError(FluxSource& fluxSource, int baseTrack)
349349
struct ReadGroupResult
350350
{
351351
ReadResult result;
352-
std::vector<std::shared_ptr<const Sector>> sectors;
352+
std::vector<std::shared_ptr<const Sector>> combinedSectors;
353353
};
354354

355355
static ReadGroupResult readGroup(const DiskLayout& diskLayout,
@@ -360,6 +360,21 @@ static ReadGroupResult readGroup(const DiskLayout& diskLayout,
360360
{
361361
ReadGroupResult rgr = {BAD_AND_CAN_NOT_RETRY};
362362

363+
/* Before doing the read, look to see if we already have the necessary
364+
* sectors. */
365+
366+
{
367+
auto [result, sectors] = combineRecordAndSectors(tracks, decoder, ltl);
368+
rgr.combinedSectors = sectors;
369+
if (result == HAS_NO_BAD_SECTORS)
370+
{
371+
/* We have all necessary sectors, so can stop here. */
372+
rgr.result = GOOD_READ;
373+
if (globalConfig()->decoder().skip_unnecessary_tracks())
374+
return rgr;
375+
}
376+
}
377+
363378
for (unsigned offset = 0; offset < ltl->groupSize;
364379
offset += diskLayout.headWidth)
365380
{
@@ -389,7 +404,7 @@ static ReadGroupResult readGroup(const DiskLayout& diskLayout,
389404
/* Decode what we've got so far. */
390405

391406
auto [result, sectors] = combineRecordAndSectors(tracks, decoder, ltl);
392-
rgr.sectors = sectors;
407+
rgr.combinedSectors = sectors;
393408
if (result == HAS_NO_BAD_SECTORS)
394409
{
395410
/* We have all necessary sectors, so can stop here. */
@@ -399,8 +414,8 @@ static ReadGroupResult readGroup(const DiskLayout& diskLayout,
399414
}
400415
else if (fluxSourceIterator.hasNext())
401416
{
402-
/* The flux source claims it can do more reads, so mark this group
403-
* as being retryable. */
417+
/* The flux source claims it can do more reads, so mark this
418+
* group as being retryable. */
404419
rgr.result = BAD_AND_CAN_RETRY;
405420
}
406421
}
@@ -634,13 +649,13 @@ void writeRawDiskCommand(const DiskLayout& diskLayout,
634649
diskLayout.logicalLocations);
635650
}
636651

637-
TracksAndSectors readAndDecodeTrack(const DiskLayout& diskLayout,
652+
void readAndDecodeTrack(const DiskLayout& diskLayout,
638653
FluxSource& fluxSource,
639654
Decoder& decoder,
640-
const std::shared_ptr<const LogicalTrackLayout>& ltl)
655+
const std::shared_ptr<const LogicalTrackLayout>& ltl,
656+
std::vector<std::shared_ptr<const Track>>& tracks,
657+
std::vector<std::shared_ptr<const Sector>>& combinedSectors)
641658
{
642-
TracksAndSectors fas;
643-
644659
if (fluxSource.isHardware())
645660
measureDiskRotation();
646661

@@ -649,9 +664,8 @@ TracksAndSectors readAndDecodeTrack(const DiskLayout& diskLayout,
649664
for (;;)
650665
{
651666
auto [result, sectors] = readGroup(
652-
diskLayout, fluxSourceIteratorHolder, ltl, fas.tracks, decoder);
653-
std::copy(
654-
sectors.begin(), sectors.end(), std::back_inserter(fas.sectors));
667+
diskLayout, fluxSourceIteratorHolder, ltl, tracks, decoder);
668+
combinedSectors = sectors;
655669
if (result == GOOD_READ)
656670
break;
657671
if (result == BAD_AND_CAN_NOT_RETRY)
@@ -673,8 +687,6 @@ TracksAndSectors readAndDecodeTrack(const DiskLayout& diskLayout,
673687
retriesRemaining--;
674688
}
675689
}
676-
677-
return fas;
678690
}
679691

680692
void readDiskCommand(const DiskLayout& diskLayout,
@@ -687,6 +699,13 @@ void readDiskCommand(const DiskLayout& diskLayout,
687699
outputFluxSinkFactory =
688700
FluxSinkFactory::create(globalConfig()->decoder().copy_flux_to());
689701

702+
std::map<CylinderHead, std::vector<std::shared_ptr<const Track>>>
703+
tracksByLogicalLocation;
704+
for (auto& [ch, track] : disk.tracksByPhysicalLocation)
705+
tracksByLogicalLocation[CylinderHead(track->ltl->logicalCylinder,
706+
track->ltl->logicalHead)]
707+
.push_back(track);
708+
690709
log(BeginOperationLogMessage{"Reading and decoding disk"});
691710
{
692711
std::unique_ptr<FluxSink> outputFluxSink;
@@ -702,13 +721,31 @@ void readDiskCommand(const DiskLayout& diskLayout,
702721

703722
testForEmergencyStop();
704723

705-
auto [trackFluxes, trackSectors] =
706-
readAndDecodeTrack(diskLayout, fluxSource, decoder, ltl);
724+
auto& trackFluxes = tracksByLogicalLocation[logicalLocation];
725+
std::vector<std::shared_ptr<const Sector>> trackSectors;
726+
readAndDecodeTrack(diskLayout,
727+
fluxSource,
728+
decoder,
729+
ltl,
730+
trackFluxes,
731+
trackSectors);
732+
733+
/* Replace all tracks on the disk by the new combined set. */
734+
735+
for (const auto& flux : trackFluxes)
736+
disk.tracksByPhysicalLocation.erase(CylinderHead{
737+
flux->ptl->physicalCylinder, flux->ptl->physicalHead});
707738
for (const auto& flux : trackFluxes)
708739
disk.tracksByPhysicalLocation.emplace(
709740
CylinderHead{
710741
flux->ptl->physicalCylinder, flux->ptl->physicalHead},
711742
flux);
743+
744+
/* Likewise for sectors. */
745+
746+
for (const auto& sector : trackSectors)
747+
disk.sectorsByPhysicalLocation.erase(
748+
sector->physicalLocation.value());
712749
for (const auto& sector : trackSectors)
713750
disk.sectorsByPhysicalLocation.emplace(
714751
sector->physicalLocation.value(), sector);

lib/algorithms/readerwriter.h

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -107,19 +107,19 @@ extern void writeDiskCommand(const DiskLayout& diskLayout,
107107
Decoder* decoder = nullptr,
108108
FluxSource* fluxSource = nullptr);
109109

110-
extern void writeRawDiskCommand(
111-
const DiskLayout& diskLayout, FluxSource& fluxSource, FluxSinkFactory& fluxSinkFactory);
110+
extern void writeRawDiskCommand(const DiskLayout& diskLayout,
111+
FluxSource& fluxSource,
112+
FluxSinkFactory& fluxSinkFactory);
112113

113-
struct TracksAndSectors
114-
{
115-
std::vector<std::shared_ptr<const Track>> tracks;
116-
std::vector<std::shared_ptr<const Sector>> sectors;
117-
};
114+
/* Reads a single group of tracks. tracks and combinedSectors are populated.
115+
* tracks may contain preexisting data which will be taken into account. */
118116

119-
extern TracksAndSectors readAndDecodeTrack(const DiskLayout& diskLayout,
117+
extern void readAndDecodeTrack(const DiskLayout& diskLayout,
120118
FluxSource& fluxSource,
121119
Decoder& decoder,
122-
const std::shared_ptr<const LogicalTrackLayout>& ltl);
120+
const std::shared_ptr<const LogicalTrackLayout>& ltl,
121+
std::vector<std::shared_ptr<const Track>>& tracks,
122+
std::vector<std::shared_ptr<const Sector>>& combinedSectors);
123123

124124
extern void readDiskCommand(const DiskLayout& diskLayout,
125125
FluxSource& fluxSource,

lib/core/utils.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,15 @@ std::map<V, K> reverseMap(const std::map<K, V>& map)
3737
return reverse;
3838
}
3939

40+
template <typename K, typename V>
41+
std::map<K, std::vector<V>> multimapToMapOfVectors(const std::multimap<K, V>& multimap)
42+
{
43+
std::map<K, std::vector<V>> results;
44+
for (auto& [k, v] : multimap)
45+
results[k].push_back(v);
46+
return results;
47+
}
48+
4049
/* If set, any running job will terminate as soon as possible (with an error).
4150
*/
4251

lib/vfs/fluxsectorinterface.cc

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -132,10 +132,16 @@ class FluxSectorInterface : public SectorInterface
132132
{
133133
CylinderHead logicalLocation = {logicalCylinder, logicalSide};
134134
auto& ltl = _diskLayout->layoutByLogicalLocation.at(logicalLocation);
135-
auto trackdata =
136-
readAndDecodeTrack(*_diskLayout, *_fluxSource, *_decoder, ltl);
137-
138-
for (const auto& sector : trackdata.sectors)
135+
std::vector<std::shared_ptr<const Track>> trackFluxes;
136+
std::vector<std::shared_ptr<const Sector>> trackSectors;
137+
readAndDecodeTrack(*_diskLayout,
138+
*_fluxSource,
139+
*_decoder,
140+
ltl,
141+
trackFluxes,
142+
trackSectors);
143+
144+
for (const auto& sector : trackSectors)
139145
*_loadedSectors.put(logicalLocation, sector->logicalSector) =
140146
*sector;
141147
_loadedTracks.insert(logicalLocation);

src/gui2/controlpanelview.cc

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -85,9 +85,13 @@ void ControlPanelView::drawContent()
8585
};
8686

8787
ImGui::TableNextRow();
88-
button(ICON_TA_DEVICE_FLOPPY,
88+
button(
89+
ICON_TA_DEVICE_FLOPPY,
8990
"fluxengine.view.controlpanel.readDevice"_lang,
90-
Datastore::beginRead,
91+
[]
92+
{
93+
Datastore::beginRead(false);
94+
},
9195
busy);
9296
ImGui::TableNextColumn();
9397
button(ICON_VS_SAVE_AS,
@@ -96,9 +100,13 @@ void ControlPanelView::drawContent()
96100
busy || !hasImage);
97101

98102
ImGui::TableNextRow();
99-
button(ICON_TA_REPEAT,
103+
button(
104+
ICON_TA_REPEAT,
100105
"fluxengine.view.controlpanel.rereadBad"_lang,
101-
nullptr,
106+
[]
107+
{
108+
Datastore::beginRead(true);
109+
},
102110
busy || !disk);
103111
ImGui::TableNextColumn();
104112
button(ICON_TA_DOWNLOAD,

src/gui2/datastore.cc

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -526,11 +526,11 @@ void Datastore::onLogMessage(const AnyLogMessage& message)
526526
message);
527527
}
528528

529-
void Datastore::beginRead()
529+
void Datastore::beginRead(bool rereadBadSectors)
530530
{
531531
Events::OperationStart::post("fluxengine.view.status.readDevice"_lang);
532532
Datastore::runOnWorkerThread(
533-
[]
533+
[=]
534534
{
535535
busy = true;
536536
failed = false;
@@ -539,12 +539,19 @@ void Datastore::beginRead()
539539
try
540540
{
541541
wtRebuildConfiguration();
542-
wtClearDiskData();
543-
wtWaitForUiThreadToCatchUp();
542+
if (!rereadBadSectors)
543+
wtClearDiskData();
544+
545+
std::shared_ptr<Disk> disk;
546+
wtRunSynchronouslyOnUiThread((std::function<void()>)[&] {
547+
if (::disk)
548+
disk = std::make_shared<Disk>(*::disk);
549+
else
550+
disk = std::make_shared<Disk>();
551+
});
544552
auto fluxSource = FluxSource::create(globalConfig());
545553
auto decoder = Arch::createDecoder(globalConfig());
546554

547-
auto disk = std::make_shared<Disk>();
548555
readDiskCommand(*diskLayout, *fluxSource, *decoder, *disk);
549556
}
550557
catch (...)

src/gui2/datastore.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ class Datastore
3535

3636
/* Begins a transation. Rebuilds the configuration. */
3737
static void reset();
38-
static void beginRead();
38+
static void beginRead(bool rereadBadSectors);
3939
static void beginWrite();
4040
static void readImage(const std::fs::path& path);
4141
static void writeImage(const std::fs::path& path);

src/gui2/diskprovider.cc

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,9 @@ void DiskProvider::readRaw(u64 offset, void* buffer, size_t size)
8080
unsigned blockOffset = realOffset - offset;
8181
unsigned bytesRemaining =
8282
std::min((unsigned)size, ltl->sectorSize - blockOffset);
83-
auto bytes = sector->data.slice(blockOffset, bytesRemaining);
83+
auto bytes = sector
84+
? sector->data.slice(blockOffset, bytesRemaining)
85+
: Bytes(bytesRemaining);
8486
memcpy(buffer, bytes.cbegin(), bytes.size());
8587

8688
offset += bytesRemaining;

tests/utils.cc

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,18 @@
44

55
using namespace snowhouse;
66

7+
template <typename F, typename S>
8+
struct snowhouse::Stringizer<std::pair<F, S>>
9+
{
10+
static std::string ToString(const std::pair<F, S>& a)
11+
{
12+
std::stringstream stream;
13+
stream << "pair(" << Stringizer<F>::ToString(a.first) << ", "
14+
<< Stringizer<S>::ToString(a.second) << ')';
15+
return stream.str();
16+
}
17+
};
18+
719
static void testJoin()
820
{
921
AssertThat(join({}, "/"), Equals(""));
@@ -56,6 +68,26 @@ static void testUnbcd()
5668
AssertThat(unbcd(0x87654321), Equals(87654321));
5769
}
5870

71+
static void testMultimapToMap()
72+
{
73+
std::multimap<int, std::string> input = {
74+
{0, "zero" },
75+
{0, "nil" },
76+
{1, "one" },
77+
{3, "two" },
78+
{3, "drei" },
79+
{3, "trois"}
80+
};
81+
std::map<int, std::vector<std::string>> wanted = {
82+
{0, {"zero", "nil"} },
83+
{1, {"one"} },
84+
{3, {"two", "drei", "trois"}}
85+
};
86+
87+
auto output = multimapToMapOfVectors(input);
88+
AssertThat(output, Equals(wanted));
89+
}
90+
5991
int main(void)
6092
{
6193
testJoin();
@@ -65,5 +97,6 @@ int main(void)
6597
testLeafname();
6698
testUnhex();
6799
testUnbcd();
100+
testMultimapToMap();
68101
return 0;
69102
}

0 commit comments

Comments
 (0)