mirror of
https://github.com/davidgiven/fluxengine.git
synced 2025-10-31 11:17:01 -07:00
Rework the flux data structures to be a bit more sensibly designed and
more amenable to copying.
This commit is contained in:
@@ -84,11 +84,9 @@ void renderLogMessage(
|
|||||||
void renderLogMessage(
|
void renderLogMessage(
|
||||||
LogRenderer& r, std::shared_ptr<const TrackReadLogMessage> m)
|
LogRenderer& r, std::shared_ptr<const TrackReadLogMessage> m)
|
||||||
{
|
{
|
||||||
const auto& track = *m->track;
|
|
||||||
|
|
||||||
std::set<std::shared_ptr<const Sector>> rawSectors;
|
std::set<std::shared_ptr<const Sector>> rawSectors;
|
||||||
std::set<std::shared_ptr<const Record>> rawRecords;
|
std::set<std::shared_ptr<const Record>> rawRecords;
|
||||||
for (const auto& trackDataFlux : track.trackDatas)
|
for (const auto& trackDataFlux : m->fluxes)
|
||||||
{
|
{
|
||||||
rawSectors.insert(
|
rawSectors.insert(
|
||||||
trackDataFlux->sectors.begin(), trackDataFlux->sectors.end());
|
trackDataFlux->sectors.begin(), trackDataFlux->sectors.end());
|
||||||
@@ -114,7 +112,7 @@ void renderLogMessage(
|
|||||||
r.newline().add("sectors:");
|
r.newline().add("sectors:");
|
||||||
|
|
||||||
std::vector<std::shared_ptr<const Sector>> sectors(
|
std::vector<std::shared_ptr<const Sector>> sectors(
|
||||||
track.sectors.begin(), track.sectors.end());
|
m->sectors.begin(), m->sectors.end());
|
||||||
std::sort(sectors.begin(), sectors.end(), sectorPointerSortPredicate);
|
std::sort(sectors.begin(), sectors.end(), sectorPointerSortPredicate);
|
||||||
|
|
||||||
for (const auto& sector : sectors)
|
for (const auto& sector : sectors)
|
||||||
@@ -126,7 +124,7 @@ void renderLogMessage(
|
|||||||
|
|
||||||
int size = 0;
|
int size = 0;
|
||||||
std::set<std::pair<int, int>> track_ids;
|
std::set<std::pair<int, int>> track_ids;
|
||||||
for (const auto& sector : m->track->sectors)
|
for (const auto& sector : m->sectors)
|
||||||
{
|
{
|
||||||
track_ids.insert(
|
track_ids.insert(
|
||||||
std::make_pair(sector->logicalCylinder, sector->logicalHead));
|
std::make_pair(sector->logicalCylinder, sector->logicalHead));
|
||||||
@@ -229,14 +227,14 @@ void measureDiskRotation()
|
|||||||
/* Given a set of sectors, deduplicates them sensibly (e.g. if there is a good
|
/* Given a set of sectors, deduplicates them sensibly (e.g. if there is a good
|
||||||
* and bad version of the same sector, the bad version is dropped). */
|
* and bad version of the same sector, the bad version is dropped). */
|
||||||
|
|
||||||
static std::set<std::shared_ptr<const Sector>> collectSectors(
|
static std::vector<std::shared_ptr<const Sector>> collectSectors(
|
||||||
std::set<std::shared_ptr<const Sector>>& track_sectors,
|
std::vector<std::shared_ptr<const Sector>>& trackSectors,
|
||||||
bool collapse_conflicts = true)
|
bool collapse_conflicts = true)
|
||||||
{
|
{
|
||||||
typedef std::tuple<unsigned, unsigned, unsigned> key_t;
|
typedef std::tuple<unsigned, unsigned, unsigned> key_t;
|
||||||
std::multimap<key_t, std::shared_ptr<const Sector>> sectors;
|
std::multimap<key_t, std::shared_ptr<const Sector>> sectors;
|
||||||
|
|
||||||
for (const auto& sector : track_sectors)
|
for (const auto& sector : trackSectors)
|
||||||
{
|
{
|
||||||
key_t sectorid = {sector->logicalCylinder,
|
key_t sectorid = {sector->logicalCylinder,
|
||||||
sector->logicalHead,
|
sector->logicalHead,
|
||||||
@@ -282,20 +280,28 @@ static std::set<std::shared_ptr<const Sector>> collectSectors(
|
|||||||
sector_set.insert(new_sector);
|
sector_set.insert(new_sector);
|
||||||
it = ub;
|
it = ub;
|
||||||
}
|
}
|
||||||
return sector_set;
|
return sector_set | std::ranges::to<std::vector>();
|
||||||
}
|
}
|
||||||
|
|
||||||
BadSectorsState combineRecordAndSectors(TrackFlux& trackFlux,
|
struct CombinationResult
|
||||||
|
{
|
||||||
|
BadSectorsState result;
|
||||||
|
std::vector<std::shared_ptr<const Sector>> sectors;
|
||||||
|
};
|
||||||
|
|
||||||
|
static CombinationResult combineRecordAndSectors(
|
||||||
|
std::vector<std::shared_ptr<const TrackDataFlux>>& fluxes,
|
||||||
Decoder& decoder,
|
Decoder& decoder,
|
||||||
std::shared_ptr<const TrackInfo>& trackLayout)
|
std::shared_ptr<const TrackInfo>& trackLayout)
|
||||||
{
|
{
|
||||||
std::set<std::shared_ptr<const Sector>> track_sectors;
|
CombinationResult cr = {HAS_NO_BAD_SECTORS};
|
||||||
|
std::vector<std::shared_ptr<const Sector>> track_sectors;
|
||||||
|
|
||||||
/* Add the sectors which were there. */
|
/* Add the sectors which were there. */
|
||||||
|
|
||||||
for (auto& trackdataflux : trackFlux.trackDatas)
|
for (auto& trackdataflux : fluxes)
|
||||||
track_sectors.insert(
|
for (auto& sector : trackdataflux->sectors)
|
||||||
trackdataflux->sectors.begin(), trackdataflux->sectors.end());
|
track_sectors.push_back(sector);
|
||||||
|
|
||||||
/* Add the sectors which should be there. */
|
/* Add the sectors which should be there. */
|
||||||
|
|
||||||
@@ -307,19 +313,19 @@ BadSectorsState combineRecordAndSectors(TrackFlux& trackFlux,
|
|||||||
sectorId});
|
sectorId});
|
||||||
|
|
||||||
sector->status = Sector::MISSING;
|
sector->status = Sector::MISSING;
|
||||||
track_sectors.insert(sector);
|
track_sectors.push_back(sector);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Deduplicate. */
|
/* Deduplicate. */
|
||||||
|
|
||||||
trackFlux.sectors = collectSectors(track_sectors);
|
cr.sectors = collectSectors(track_sectors);
|
||||||
if (trackFlux.sectors.empty())
|
if (cr.sectors.empty())
|
||||||
return HAS_BAD_SECTORS;
|
cr.result = HAS_BAD_SECTORS;
|
||||||
for (const auto& sector : trackFlux.sectors)
|
for (const auto& sector : cr.sectors)
|
||||||
if (sector->status != Sector::OK)
|
if (sector->status != Sector::OK)
|
||||||
return HAS_BAD_SECTORS;
|
cr.result = HAS_BAD_SECTORS;
|
||||||
|
|
||||||
return HAS_NO_BAD_SECTORS;
|
return cr;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void adjustTrackOnError(FluxSource& fluxSource, int baseTrack)
|
static void adjustTrackOnError(FluxSource& fluxSource, int baseTrack)
|
||||||
@@ -342,16 +348,25 @@ static void adjustTrackOnError(FluxSource& fluxSource, int baseTrack)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ReadResult readGroup(FluxSourceIteratorHolder& fluxSourceIteratorHolder,
|
struct ReadGroupResult
|
||||||
|
{
|
||||||
|
ReadResult result;
|
||||||
|
std::vector<std::shared_ptr<const Sector>> sectors;
|
||||||
|
};
|
||||||
|
|
||||||
|
static ReadGroupResult readGroup(
|
||||||
|
FluxSourceIteratorHolder& fluxSourceIteratorHolder,
|
||||||
std::shared_ptr<const TrackInfo>& trackInfo,
|
std::shared_ptr<const TrackInfo>& trackInfo,
|
||||||
TrackFlux& trackFlux,
|
std::vector<std::shared_ptr<const TrackDataFlux>>& fluxes,
|
||||||
Decoder& decoder)
|
Decoder& decoder)
|
||||||
{
|
{
|
||||||
ReadResult result = BAD_AND_CAN_NOT_RETRY;
|
ReadGroupResult rgr = {BAD_AND_CAN_NOT_RETRY};
|
||||||
|
|
||||||
for (unsigned offset = 0; offset < trackInfo->groupSize;
|
for (unsigned offset = 0; offset < trackInfo->groupSize;
|
||||||
offset += Layout::getHeadWidth())
|
offset += Layout::getHeadWidth())
|
||||||
{
|
{
|
||||||
|
/* Do the physical read. */
|
||||||
|
|
||||||
log(BeginReadOperationLogMessage{
|
log(BeginReadOperationLogMessage{
|
||||||
trackInfo->physicalCylinder + offset, trackInfo->physicalHead});
|
trackInfo->physicalCylinder + offset, trackInfo->physicalHead});
|
||||||
|
|
||||||
@@ -360,28 +375,36 @@ ReadResult readGroup(FluxSourceIteratorHolder& fluxSourceIteratorHolder,
|
|||||||
if (!fluxSourceIterator.hasNext())
|
if (!fluxSourceIterator.hasNext())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
std::shared_ptr<const Fluxmap> fluxmap = fluxSourceIterator.next();
|
auto fluxmap = fluxSourceIterator.next();
|
||||||
// ->rescale(
|
|
||||||
// 1.0 / globalConfig()->flux_source().rescale());
|
|
||||||
log(EndReadOperationLogMessage());
|
log(EndReadOperationLogMessage());
|
||||||
log("{0} ms in {1} bytes",
|
log("{0} ms in {1} bytes",
|
||||||
(int)(fluxmap->duration() / 1e6),
|
(int)(fluxmap->duration() / 1e6),
|
||||||
fluxmap->bytes());
|
fluxmap->bytes());
|
||||||
|
|
||||||
auto trackdataflux = decoder.decodeToSectors(fluxmap, trackInfo);
|
auto flux = decoder.decodeToSectors(std::move(fluxmap), trackInfo);
|
||||||
trackFlux.trackDatas.push_back(trackdataflux);
|
fluxes.push_back(flux);
|
||||||
if (combineRecordAndSectors(trackFlux, decoder, trackInfo) ==
|
|
||||||
HAS_NO_BAD_SECTORS)
|
/* Decode what we've got so far. */
|
||||||
|
|
||||||
|
auto [result, sectors] =
|
||||||
|
combineRecordAndSectors(fluxes, decoder, trackInfo);
|
||||||
|
rgr.sectors = sectors;
|
||||||
|
if (result == HAS_NO_BAD_SECTORS)
|
||||||
{
|
{
|
||||||
result = GOOD_READ;
|
/* We have all necessary sectors, so can stop here. */
|
||||||
|
rgr.result = GOOD_READ;
|
||||||
if (globalConfig()->decoder().skip_unnecessary_tracks())
|
if (globalConfig()->decoder().skip_unnecessary_tracks())
|
||||||
return result;
|
break;
|
||||||
}
|
}
|
||||||
else if (fluxSourceIterator.hasNext())
|
else if (fluxSourceIterator.hasNext())
|
||||||
result = BAD_AND_CAN_RETRY;
|
{
|
||||||
|
/* The flux source claims it can do more reads, so mark this group
|
||||||
|
* as being retryable. */
|
||||||
|
rgr.result = BAD_AND_CAN_RETRY;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return rgr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void writeTracks(FluxSink& fluxSink,
|
void writeTracks(FluxSink& fluxSink,
|
||||||
@@ -490,12 +513,11 @@ void writeTracksAndVerify(FluxSink& fluxSink,
|
|||||||
},
|
},
|
||||||
[&](std::shared_ptr<const TrackInfo>& trackInfo)
|
[&](std::shared_ptr<const TrackInfo>& trackInfo)
|
||||||
{
|
{
|
||||||
auto trackFlux = std::make_shared<TrackFlux>();
|
|
||||||
trackFlux->trackInfo = trackInfo;
|
|
||||||
FluxSourceIteratorHolder fluxSourceIteratorHolder(fluxSource);
|
FluxSourceIteratorHolder fluxSourceIteratorHolder(fluxSource);
|
||||||
auto result = readGroup(
|
std::vector<std::shared_ptr<const TrackDataFlux>> fluxes;
|
||||||
fluxSourceIteratorHolder, trackInfo, *trackFlux, decoder);
|
auto [result, sectors] =
|
||||||
log(TrackReadLogMessage{trackFlux});
|
readGroup(fluxSourceIteratorHolder, trackInfo, fluxes, decoder);
|
||||||
|
log(TrackReadLogMessage{fluxes, sectors});
|
||||||
|
|
||||||
if (result != GOOD_READ)
|
if (result != GOOD_READ)
|
||||||
{
|
{
|
||||||
@@ -512,7 +534,7 @@ void writeTracksAndVerify(FluxSink& fluxSink,
|
|||||||
sector->logicalSector)
|
sector->logicalSector)
|
||||||
->data = sector->data;
|
->data = sector->data;
|
||||||
|
|
||||||
for (const auto& sector : trackFlux->sectors)
|
for (const auto& sector : sectors)
|
||||||
{
|
{
|
||||||
const auto s = wanted.get(sector->logicalCylinder,
|
const auto s = wanted.get(sector->logicalCylinder,
|
||||||
sector->logicalHead,
|
sector->logicalHead,
|
||||||
@@ -585,12 +607,11 @@ void writeRawDiskCommand(FluxSource& fluxSource, FluxSink& fluxSink)
|
|||||||
trackinfos);
|
trackinfos);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<TrackFlux> readAndDecodeTrack(FluxSource& fluxSource,
|
FluxAndSectors readAndDecodeTrack(FluxSource& fluxSource,
|
||||||
Decoder& decoder,
|
Decoder& decoder,
|
||||||
std::shared_ptr<const TrackInfo>& trackInfo)
|
std::shared_ptr<const TrackInfo>& trackInfo)
|
||||||
{
|
{
|
||||||
auto trackFlux = std::make_shared<TrackFlux>();
|
FluxAndSectors fas;
|
||||||
trackFlux->trackInfo = trackInfo;
|
|
||||||
|
|
||||||
if (fluxSource.isHardware())
|
if (fluxSource.isHardware())
|
||||||
measureDiskRotation();
|
measureDiskRotation();
|
||||||
@@ -599,8 +620,10 @@ std::shared_ptr<TrackFlux> readAndDecodeTrack(FluxSource& fluxSource,
|
|||||||
int retriesRemaining = globalConfig()->decoder().retries();
|
int retriesRemaining = globalConfig()->decoder().retries();
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
auto result =
|
auto [result, sectors] =
|
||||||
readGroup(fluxSourceIteratorHolder, trackInfo, *trackFlux, decoder);
|
readGroup(fluxSourceIteratorHolder, trackInfo, fas.fluxes, decoder);
|
||||||
|
std::copy(
|
||||||
|
sectors.begin(), sectors.end(), std::back_inserter(fas.sectors));
|
||||||
if (result == GOOD_READ)
|
if (result == GOOD_READ)
|
||||||
break;
|
break;
|
||||||
if (result == BAD_AND_CAN_NOT_RETRY)
|
if (result == BAD_AND_CAN_NOT_RETRY)
|
||||||
@@ -623,24 +646,24 @@ std::shared_ptr<TrackFlux> readAndDecodeTrack(FluxSource& fluxSource,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return trackFlux;
|
return fas;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<const DiskFlux> readDiskCommand(
|
void readDiskCommand(
|
||||||
FluxSource& fluxSource, Decoder& decoder)
|
FluxSource& fluxSource, Decoder& decoder, DiskFlux& diskflux)
|
||||||
{
|
{
|
||||||
std::unique_ptr<FluxSink> outputFluxSink;
|
std::unique_ptr<FluxSink> outputFluxSink;
|
||||||
if (globalConfig()->decoder().has_copy_flux_to())
|
if (globalConfig()->decoder().has_copy_flux_to())
|
||||||
outputFluxSink =
|
outputFluxSink =
|
||||||
FluxSink::create(globalConfig()->decoder().copy_flux_to());
|
FluxSink::create(globalConfig()->decoder().copy_flux_to());
|
||||||
|
|
||||||
auto diskflux = std::make_shared<DiskFlux>();
|
if (!diskflux.layout)
|
||||||
diskflux->layout = createDiskLayout();
|
diskflux.layout = createDiskLayout();
|
||||||
|
|
||||||
log(BeginOperationLogMessage{"Reading and decoding disk"});
|
log(BeginOperationLogMessage{"Reading and decoding disk"});
|
||||||
auto physicalLocations = Layout::computePhysicalLocations();
|
auto physicalLocations = Layout::computePhysicalLocations();
|
||||||
unsigned index = 0;
|
unsigned index = 0;
|
||||||
for (auto& physicalLocation : physicalLocations)
|
for (auto physicalLocation : physicalLocations)
|
||||||
{
|
{
|
||||||
auto trackInfo = Layout::getLayoutOfTrackPhysical(
|
auto trackInfo = Layout::getLayoutOfTrackPhysical(
|
||||||
physicalLocation.cylinder, physicalLocation.head);
|
physicalLocation.cylinder, physicalLocation.head);
|
||||||
@@ -651,12 +674,16 @@ std::shared_ptr<const DiskFlux> readDiskCommand(
|
|||||||
|
|
||||||
testForEmergencyStop();
|
testForEmergencyStop();
|
||||||
|
|
||||||
auto trackFlux = readAndDecodeTrack(fluxSource, decoder, trackInfo);
|
auto [trackFluxes, trackSectors] =
|
||||||
diskflux->tracks.push_back(trackFlux);
|
readAndDecodeTrack(fluxSource, decoder, trackInfo);
|
||||||
|
for (const auto& flux : trackFluxes)
|
||||||
|
diskflux.fluxesByTrack.insert(std::pair{physicalLocation, flux});
|
||||||
|
for (const auto& sector : trackSectors)
|
||||||
|
diskflux.sectorsByTrack.insert(std::pair{physicalLocation, sector});
|
||||||
|
|
||||||
if (outputFluxSink)
|
if (outputFluxSink)
|
||||||
{
|
{
|
||||||
for (const auto& data : trackFlux->trackDatas)
|
for (const auto& data : trackFluxes)
|
||||||
outputFluxSink->writeFlux(trackInfo->physicalCylinder,
|
outputFluxSink->writeFlux(trackInfo->physicalCylinder,
|
||||||
trackInfo->physicalHead,
|
trackInfo->physicalHead,
|
||||||
*data->fluxmap);
|
*data->fluxmap);
|
||||||
@@ -666,7 +693,7 @@ std::shared_ptr<const DiskFlux> readDiskCommand(
|
|||||||
{
|
{
|
||||||
std::vector<std::shared_ptr<const Record>> sorted_records;
|
std::vector<std::shared_ptr<const Record>> sorted_records;
|
||||||
|
|
||||||
for (const auto& data : trackFlux->trackDatas)
|
for (const auto& data : trackFluxes)
|
||||||
sorted_records.insert(sorted_records.end(),
|
sorted_records.insert(sorted_records.end(),
|
||||||
data->records.begin(),
|
data->records.begin(),
|
||||||
data->records.end());
|
data->records.end());
|
||||||
@@ -691,18 +718,15 @@ std::shared_ptr<const DiskFlux> readDiskCommand(
|
|||||||
|
|
||||||
if (globalConfig()->decoder().dump_sectors())
|
if (globalConfig()->decoder().dump_sectors())
|
||||||
{
|
{
|
||||||
auto collected_sectors = collectSectors(trackFlux->sectors, false);
|
auto sectors = collectSectors(trackSectors, false);
|
||||||
std::vector<std::shared_ptr<const Sector>> sorted_sectors(
|
std::ranges::sort(sectors,
|
||||||
collected_sectors.begin(), collected_sectors.end());
|
|
||||||
std::sort(sorted_sectors.begin(),
|
|
||||||
sorted_sectors.end(),
|
|
||||||
[](const auto& o1, const auto& o2)
|
[](const auto& o1, const auto& o2)
|
||||||
{
|
{
|
||||||
return *o1 < *o2;
|
return *o1 < *o2;
|
||||||
});
|
});
|
||||||
|
|
||||||
std::cout << "\nDecoded sectors follow:\n\n";
|
std::cout << "\nDecoded sectors follow:\n\n";
|
||||||
for (const auto& sector : sorted_sectors)
|
for (const auto& sector : sectors)
|
||||||
{
|
{
|
||||||
std::cout << fmt::format(
|
std::cout << fmt::format(
|
||||||
"{}.{:02}.{:02}: I+{:.2f}us with {:.2f}us clock: "
|
"{}.{:02}.{:02}: I+{:.2f}us with {:.2f}us clock: "
|
||||||
@@ -719,36 +743,34 @@ std::shared_ptr<const DiskFlux> readDiskCommand(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* track can't be modified below this point. */
|
/* track can't be modified below this point. */
|
||||||
log(TrackReadLogMessage{trackFlux});
|
log(TrackReadLogMessage{trackFluxes, trackSectors});
|
||||||
|
|
||||||
std::set<std::shared_ptr<const Sector>> all_sectors;
|
std::vector<std::shared_ptr<const Sector>> all_sectors;
|
||||||
for (auto& track : diskflux->tracks)
|
for (auto& [ch, sector] : diskflux.sectorsByTrack)
|
||||||
for (auto& sector : track->sectors)
|
all_sectors.push_back(sector);
|
||||||
all_sectors.insert(sector);
|
|
||||||
all_sectors = collectSectors(all_sectors);
|
all_sectors = collectSectors(all_sectors);
|
||||||
diskflux->image = std::make_shared<Image>(all_sectors);
|
diskflux.image = std::make_shared<Image>(all_sectors);
|
||||||
|
|
||||||
/* Log a _copy_ of the diskflux structure so that the logger doesn't see
|
/* Log a _copy_ of the diskflux structure so that the logger doesn't see
|
||||||
* the diskflux get mutated in subsequent reads. */
|
* the diskflux get mutated in subsequent reads. */
|
||||||
log(DiskReadLogMessage{std::make_shared<DiskFlux>(*diskflux)});
|
log(DiskReadLogMessage{std::make_shared<DiskFlux>(diskflux)});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!diskflux->image)
|
if (!diskflux.image)
|
||||||
diskflux->image = std::make_shared<Image>();
|
diskflux.image = std::make_shared<Image>();
|
||||||
|
|
||||||
/* diskflux can't be modified below this point. */
|
|
||||||
log(EndOperationLogMessage{"Read complete"});
|
log(EndOperationLogMessage{"Read complete"});
|
||||||
return diskflux;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void readDiskCommand(
|
void readDiskCommand(
|
||||||
FluxSource& fluxsource, Decoder& decoder, ImageWriter& writer)
|
FluxSource& fluxsource, Decoder& decoder, ImageWriter& writer)
|
||||||
{
|
{
|
||||||
auto diskflux = readDiskCommand(fluxsource, decoder);
|
DiskFlux diskflux;
|
||||||
|
readDiskCommand(fluxsource, decoder, diskflux);
|
||||||
|
|
||||||
writer.printMap(*diskflux->image);
|
writer.printMap(*diskflux.image);
|
||||||
if (globalConfig()->decoder().has_write_csv_to())
|
if (globalConfig()->decoder().has_write_csv_to())
|
||||||
writer.writeCsv(
|
writer.writeCsv(
|
||||||
*diskflux->image, globalConfig()->decoder().write_csv_to());
|
*diskflux.image, globalConfig()->decoder().write_csv_to());
|
||||||
writer.writeImage(*diskflux->image);
|
writer.writeImage(*diskflux.image);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,7 +14,6 @@ class Image;
|
|||||||
class ImageReader;
|
class ImageReader;
|
||||||
class ImageWriter;
|
class ImageWriter;
|
||||||
class TrackInfo;
|
class TrackInfo;
|
||||||
class TrackFlux;
|
|
||||||
class TrackDataFlux;
|
class TrackDataFlux;
|
||||||
class Sector;
|
class Sector;
|
||||||
|
|
||||||
@@ -29,7 +28,8 @@ struct EndSpeedOperationLogMessage
|
|||||||
|
|
||||||
struct TrackReadLogMessage
|
struct TrackReadLogMessage
|
||||||
{
|
{
|
||||||
std::shared_ptr<const TrackFlux> track;
|
std::vector<std::shared_ptr<const TrackDataFlux>> fluxes;
|
||||||
|
std::vector<std::shared_ptr<const Sector>> sectors;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct DiskReadLogMessage
|
struct DiskReadLogMessage
|
||||||
@@ -103,12 +103,18 @@ extern void writeDiskCommand(const Image& image,
|
|||||||
|
|
||||||
extern void writeRawDiskCommand(FluxSource& fluxSource, FluxSink& fluxSink);
|
extern void writeRawDiskCommand(FluxSource& fluxSource, FluxSink& fluxSink);
|
||||||
|
|
||||||
extern std::shared_ptr<TrackFlux> readAndDecodeTrack(FluxSource& fluxSource,
|
struct FluxAndSectors
|
||||||
|
{
|
||||||
|
std::vector<std::shared_ptr<const TrackDataFlux>> fluxes;
|
||||||
|
std::vector<std::shared_ptr<const Sector>> sectors;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern FluxAndSectors readAndDecodeTrack(FluxSource& fluxSource,
|
||||||
Decoder& decoder,
|
Decoder& decoder,
|
||||||
std::shared_ptr<const TrackInfo>& layout);
|
std::shared_ptr<const TrackInfo>& layout);
|
||||||
|
|
||||||
extern std::shared_ptr<const DiskFlux> readDiskCommand(
|
extern void readDiskCommand(
|
||||||
FluxSource& fluxsource, Decoder& decoder);
|
FluxSource& fluxsource, Decoder& decoder, DiskFlux& diskflux);
|
||||||
extern void readDiskCommand(
|
extern void readDiskCommand(
|
||||||
FluxSource& source, Decoder& decoder, ImageWriter& writer);
|
FluxSource& source, Decoder& decoder, ImageWriter& writer);
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,6 @@
|
|||||||
|
|
||||||
class DiskFlux;
|
class DiskFlux;
|
||||||
class TrackDataFlux;
|
class TrackDataFlux;
|
||||||
class TrackFlux;
|
|
||||||
class Sector;
|
class Sector;
|
||||||
class LogRenderer;
|
class LogRenderer;
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
#define FLUX_H
|
#define FLUX_H
|
||||||
|
|
||||||
#include "lib/core/bytes.h"
|
#include "lib/core/bytes.h"
|
||||||
|
#include "lib/data/locations.h"
|
||||||
|
|
||||||
class Fluxmap;
|
class Fluxmap;
|
||||||
class Sector;
|
class Sector;
|
||||||
@@ -26,16 +27,13 @@ struct TrackDataFlux
|
|||||||
std::vector<std::shared_ptr<const Sector>> sectors;
|
std::vector<std::shared_ptr<const Sector>> sectors;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct TrackFlux
|
|
||||||
{
|
|
||||||
std::shared_ptr<const TrackInfo> trackInfo;
|
|
||||||
std::vector<std::shared_ptr<TrackDataFlux>> trackDatas;
|
|
||||||
std::set<std::shared_ptr<const Sector>> sectors;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct DiskFlux
|
struct DiskFlux
|
||||||
{
|
{
|
||||||
std::vector<std::shared_ptr<TrackFlux>> tracks;
|
DiskFlux& operator=(const DiskFlux& other) = default;
|
||||||
|
|
||||||
|
std::multimap<CylinderHead, std::shared_ptr<const TrackDataFlux>>
|
||||||
|
fluxesByTrack;
|
||||||
|
std::multimap<CylinderHead, std::shared_ptr<const Sector>> sectorsByTrack;
|
||||||
std::shared_ptr<const Image> image;
|
std::shared_ptr<const Image> image;
|
||||||
std::shared_ptr<const DiskLayout> layout;
|
std::shared_ptr<const DiskLayout> layout;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
Image::Image() {}
|
Image::Image() {}
|
||||||
|
|
||||||
Image::Image(std::set<std::shared_ptr<const Sector>>& sectors):
|
Image::Image(std::vector<std::shared_ptr<const Sector>>& sectors):
|
||||||
_filesystemOrder(Layout::computeFilesystemLogicalOrdering())
|
_filesystemOrder(Layout::computeFilesystemLogicalOrdering())
|
||||||
{
|
{
|
||||||
for (auto& sector : sectors)
|
for (auto& sector : sectors)
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ class Image
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Image();
|
Image();
|
||||||
Image(std::set<std::shared_ptr<const Sector>>& sectors);
|
Image(std::vector<std::shared_ptr<const Sector>>& sectors);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
class const_iterator
|
class const_iterator
|
||||||
|
|||||||
@@ -8,24 +8,32 @@
|
|||||||
|
|
||||||
class MemoryFluxSourceIterator : public FluxSourceIterator
|
class MemoryFluxSourceIterator : public FluxSourceIterator
|
||||||
{
|
{
|
||||||
|
using multimap =
|
||||||
|
std::multimap<CylinderHead, std::shared_ptr<const TrackDataFlux>>;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
MemoryFluxSourceIterator(const TrackFlux& track): _track(track) {}
|
MemoryFluxSourceIterator(
|
||||||
|
multimap::const_iterator startIt, multimap::const_iterator endIt):
|
||||||
|
_startIt(startIt),
|
||||||
|
_endIt(endIt)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
bool hasNext() const override
|
bool hasNext() const override
|
||||||
{
|
{
|
||||||
return _count < _track.trackDatas.size();
|
return _startIt != _endIt;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<const Fluxmap> next() override
|
std::unique_ptr<const Fluxmap> next() override
|
||||||
{
|
{
|
||||||
auto bytes = _track.trackDatas[_count]->fluxmap->rawBytes();
|
auto bytes = _startIt->second->fluxmap->rawBytes();
|
||||||
_count++;
|
_startIt++;
|
||||||
return std::make_unique<Fluxmap>(bytes);
|
return std::make_unique<Fluxmap>(bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const TrackFlux& _track;
|
multimap::const_iterator _startIt;
|
||||||
int _count = 0;
|
multimap::const_iterator _endIt;
|
||||||
};
|
};
|
||||||
|
|
||||||
class MemoryFluxSource : public FluxSource
|
class MemoryFluxSource : public FluxSource
|
||||||
@@ -33,25 +41,21 @@ class MemoryFluxSource : public FluxSource
|
|||||||
public:
|
public:
|
||||||
MemoryFluxSource(const DiskFlux& flux): _flux(flux)
|
MemoryFluxSource(const DiskFlux& flux): _flux(flux)
|
||||||
{
|
{
|
||||||
std::vector<CylinderHead> chs;
|
std::set<CylinderHead> chs;
|
||||||
for (const auto& trackFlux : flux.tracks)
|
for (auto& [ch, trackDataFlux] : flux.fluxesByTrack)
|
||||||
chs.push_back(
|
chs.insert(ch);
|
||||||
CylinderHead{(unsigned)trackFlux->trackInfo->physicalCylinder,
|
|
||||||
(unsigned)trackFlux->trackInfo->logicalCylinder});
|
|
||||||
_extraConfig.mutable_drive()->set_tracks(
|
_extraConfig.mutable_drive()->set_tracks(
|
||||||
convertCylinderHeadsToString(chs));
|
convertCylinderHeadsToString(std::vector(chs.begin(), chs.end())));
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
std::unique_ptr<FluxSourceIterator> readFlux(
|
std::unique_ptr<FluxSourceIterator> readFlux(
|
||||||
int physicalCylinder, int physicalHead) override
|
int physicalCylinder, int physicalHead) override
|
||||||
{
|
{
|
||||||
for (const auto& trackFlux : _flux.tracks)
|
auto [startIt, endIt] = _flux.fluxesByTrack.equal_range(
|
||||||
{
|
{(unsigned)physicalCylinder, (unsigned)physicalHead});
|
||||||
if ((trackFlux->trackInfo->physicalCylinder == physicalCylinder) &&
|
if (startIt != _flux.fluxesByTrack.end())
|
||||||
(trackFlux->trackInfo->physicalHead == physicalHead))
|
return std::make_unique<MemoryFluxSourceIterator>(startIt, endIt);
|
||||||
return std::make_unique<MemoryFluxSourceIterator>(*trackFlux);
|
|
||||||
}
|
|
||||||
|
|
||||||
return std::make_unique<EmptyFluxSourceIterator>();
|
return std::make_unique<EmptyFluxSourceIterator>();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -132,7 +132,7 @@ private:
|
|||||||
auto trackInfo = Layout::getLayoutOfTrack(track, side);
|
auto trackInfo = Layout::getLayoutOfTrack(track, side);
|
||||||
auto trackdata = readAndDecodeTrack(*_fluxSource, *_decoder, trackInfo);
|
auto trackdata = readAndDecodeTrack(*_fluxSource, *_decoder, trackInfo);
|
||||||
|
|
||||||
for (const auto& sector : trackdata->sectors)
|
for (const auto& sector : trackdata.sectors)
|
||||||
*_loadedSectors.put(track, side, sector->logicalSector) = *sector;
|
*_loadedSectors.put(track, side, sector->logicalSector) = *sector;
|
||||||
_loadedTracks.insert(trackid_t(track, side));
|
_loadedTracks.insert(trackid_t(track, side));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -276,16 +276,15 @@ static void rebuildDiskFluxIndices()
|
|||||||
sectorByLogicalLocation.clear();
|
sectorByLogicalLocation.clear();
|
||||||
if (diskFlux)
|
if (diskFlux)
|
||||||
{
|
{
|
||||||
for (const auto& track : diskFlux->tracks)
|
for (const auto& [ch, sector] : diskFlux->sectorsByTrack)
|
||||||
for (const auto& sector : track->sectors)
|
{
|
||||||
{
|
sectorByPhysicalLocation[{sector->physicalCylinder,
|
||||||
sectorByPhysicalLocation[{sector->physicalCylinder,
|
sector->physicalHead,
|
||||||
sector->physicalHead,
|
sector->logicalSector}] = sector;
|
||||||
sector->logicalSector}] = sector;
|
sectorByLogicalLocation[{sector->logicalCylinder,
|
||||||
sectorByLogicalLocation[{sector->logicalCylinder,
|
sector->logicalHead,
|
||||||
sector->logicalHead,
|
sector->logicalSector}] = sector;
|
||||||
sector->logicalSector}] = sector;
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -526,7 +525,8 @@ void Datastore::beginRead(void)
|
|||||||
wtRebuildConfiguration();
|
wtRebuildConfiguration();
|
||||||
auto fluxSource = FluxSource::create(globalConfig());
|
auto fluxSource = FluxSource::create(globalConfig());
|
||||||
auto decoder = Arch::createDecoder(globalConfig());
|
auto decoder = Arch::createDecoder(globalConfig());
|
||||||
auto diskflux = readDiskCommand(*fluxSource, *decoder);
|
auto diskflux = std::make_shared<DiskFlux>();
|
||||||
|
readDiskCommand(*fluxSource, *decoder, *diskflux);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -25,18 +25,22 @@ SummaryView::SummaryView():
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::optional<std::set<std::shared_ptr<const Sector>>> findSectors(
|
static std::set<std::shared_ptr<const Sector>> findSectors(
|
||||||
std::shared_ptr<const DiskFlux>& diskFlux, int cylinder, int head)
|
std::shared_ptr<const DiskFlux>& diskFlux,
|
||||||
|
unsigned physicalCylinder,
|
||||||
|
unsigned physicalHead)
|
||||||
{
|
{
|
||||||
if (diskFlux)
|
std::set<std::shared_ptr<const Sector>> sectors;
|
||||||
for (auto& it : diskFlux->tracks)
|
|
||||||
{
|
|
||||||
if ((it->trackInfo->physicalCylinder == cylinder) &&
|
|
||||||
(it->trackInfo->physicalHead == head))
|
|
||||||
return std::make_optional(it->sectors);
|
|
||||||
}
|
|
||||||
|
|
||||||
return {};
|
if (diskFlux)
|
||||||
|
{
|
||||||
|
auto [startIt, endIt] = diskFlux->sectorsByTrack.equal_range(
|
||||||
|
{physicalCylinder, physicalHead});
|
||||||
|
for (auto it = startIt; it != endIt; it++)
|
||||||
|
sectors.insert(it->second);
|
||||||
|
}
|
||||||
|
|
||||||
|
return sectors;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct TrackAnalysis
|
struct TrackAnalysis
|
||||||
@@ -53,10 +57,10 @@ TrackAnalysis analyseTrack(std::shared_ptr<const DiskFlux>& diskFlux,
|
|||||||
auto sectors = findSectors(diskFlux, physicalCylinder, physicalHead);
|
auto sectors = findSectors(diskFlux, physicalCylinder, physicalHead);
|
||||||
result.colour = ImGui::GetColorU32(ImGuiCol_TextDisabled);
|
result.colour = ImGui::GetColorU32(ImGuiCol_TextDisabled);
|
||||||
result.tooltip = "No data";
|
result.tooltip = "No data";
|
||||||
if (sectors.has_value())
|
if (!sectors.empty())
|
||||||
{
|
{
|
||||||
unsigned totalSectors = sectors->size();
|
unsigned totalSectors = sectors.size();
|
||||||
unsigned goodSectors = std::ranges::count_if(*sectors,
|
unsigned goodSectors = std::ranges::count_if(sectors,
|
||||||
[](auto& e)
|
[](auto& e)
|
||||||
{
|
{
|
||||||
return e->status == Sector::OK;
|
return e->status == Sector::OK;
|
||||||
|
|||||||
Reference in New Issue
Block a user