Refactor for better multi-read support. Each read is now held separately, with

F_DESYNC being deprecated, and FluxSource returns an iterator which can be used
to retry reads.
This commit is contained in:
David Given
2022-03-07 00:07:42 +01:00
parent 78186d8a45
commit 96214bf3fd
25 changed files with 347 additions and 146 deletions

View File

@@ -30,7 +30,7 @@ struct CwfTrack
uint8_t length[4]; // little-endian
};
class CwfFluxSource : public FluxSource
class CwfFluxSource : public TrivialFluxSource
{
public:
CwfFluxSource(const CwfFluxSourceProto& config):
@@ -79,11 +79,11 @@ public:
}
public:
std::unique_ptr<Fluxmap> readFlux(int track, int side)
std::unique_ptr<const Fluxmap> readSingleFlux(int track, int side)
{
const auto& p = _trackOffsets.find(std::make_pair(track, side));
if (p == _trackOffsets.end())
return std::unique_ptr<Fluxmap>();
return std::make_unique<const Fluxmap>();
off_t pos = p->second.first;;
size_t length = p->second.second;

View File

@@ -4,16 +4,16 @@
#include "lib/fluxsource/fluxsource.pb.h"
#include "fmt/format.h"
class EraseFluxSource : public FluxSource
class EraseFluxSource : public TrivialFluxSource
{
public:
EraseFluxSource(const EraseFluxSourceProto& config) {}
~EraseFluxSource() {}
public:
std::unique_ptr<Fluxmap> readFlux(int track, int side)
std::unique_ptr<const Fluxmap> readSingleFlux(int track, int side) override
{
return std::unique_ptr<Fluxmap>();
return std::unique_ptr<const Fluxmap>();
}
void recalibrate() {}
@@ -21,7 +21,7 @@ public:
std::unique_ptr<FluxSource> FluxSource::createEraseFluxSource(const EraseFluxSourceProto& config)
{
return std::unique_ptr<FluxSource>(new EraseFluxSource(config));
return std::make_unique<EraseFluxSource>(config);
}

View File

@@ -5,8 +5,46 @@
#include "fluxsource/fluxsource.h"
#include "proto.h"
#include "fmt/format.h"
#include "fluxmap.h"
#include <fstream>
class Fl2FluxSourceIterator : public FluxSourceIterator
{
public:
Fl2FluxSourceIterator(const TrackFluxProto& proto):
_proto(proto)
{}
bool hasNext() const override
{
return _count < _proto.flux_size();
}
std::unique_ptr<const Fluxmap> next() override
{
auto bytes = _proto.flux(_count);
_count++;
return std::make_unique<Fluxmap>(bytes);
}
private:
const TrackFluxProto& _proto;
int _count = 0;
};
class EmptyFluxSourceIterator : public FluxSourceIterator
{
bool hasNext() const override
{
return false;
}
std::unique_ptr<const Fluxmap> next() override
{
Error() << "no flux to read";
}
};
class Fl2FluxSource : public FluxSource
{
public:
@@ -24,15 +62,15 @@ public:
}
public:
std::unique_ptr<Fluxmap> readFlux(int cylinder, int head)
std::unique_ptr<FluxSourceIterator> readFlux(int cylinder, int head) override
{
for (const auto& track : _proto.track())
{
if ((track.cylinder() == cylinder) && (track.head() == head))
return std::make_unique<Fluxmap>(track.flux());
return std::make_unique<Fl2FluxSourceIterator>(track);
}
return std::make_unique<Fluxmap>();
return std::make_unique<EmptyFluxSourceIterator>();
}
void recalibrate() {}
@@ -51,14 +89,18 @@ private:
/* Change a flux datastream with multiple segments separated by F_DESYNC into multiple
* flux segments. */
for (auto* track = _proto.mutable_track())
for (auto& track : *_proto.mutable_track())
{
Fluxmap old_flux(track.flux(0));
auto split_flux = old_flux.split();
if (track.flux_size() == 0)
track.clear_flux();
else
{
Fluxmap oldFlux(track.flux(0));
track.clear_flux();
for (const auto& flux : split_flux)
track.add_flux(flux.rawBytes());
track.clear_flux();
for (const auto& flux : oldFlux.split())
track.add_flux(flux->rawBytes());
}
}
_proto.set_version(FluxFileVersion::VERSION_2);

View File

@@ -1,6 +1,7 @@
#include "globals.h"
#include "flags.h"
#include "fluxsource/fluxsource.h"
#include "fluxmap.h"
#include "lib/config.pb.h"
#include "proto.h"
#include "utils.h"
@@ -72,5 +73,36 @@ void FluxSource::updateConfigForFilename(FluxSourceProto* proto, const std::stri
Error() << fmt::format("unrecognised flux filename '{}'", filename);
}
class TrivialFluxSourceIterator : public FluxSourceIterator
{
public:
TrivialFluxSourceIterator(TrivialFluxSource* fluxSource, int cylinder, int head):
_fluxSource(fluxSource),
_cylinder(cylinder),
_head(head)
{}
bool hasNext() const override
{
return !!_fluxSource;
}
std::unique_ptr<const Fluxmap> next() override
{
auto fluxmap = _fluxSource->readSingleFlux(_cylinder, _head);
_fluxSource = nullptr;
return fluxmap;
}
private:
TrivialFluxSource* _fluxSource;
int _cylinder;
int _head;
};
std::unique_ptr<FluxSourceIterator> TrivialFluxSource::readFlux(int cylinder, int head)
{
return std::make_unique<TrivialFluxSourceIterator>(this, cylinder, head);
}

View File

@@ -14,6 +14,15 @@ class KryofluxFluxSourceProto;
class ScpFluxSourceProto;
class TestPatternFluxSourceProto;
class FluxSourceIterator
{
public:
virtual ~FluxSourceIterator() {}
virtual bool hasNext() const = 0;
virtual std::unique_ptr<const Fluxmap> next() = 0;
};
class FluxSource
{
public:
@@ -33,9 +42,16 @@ public:
static void updateConfigForFilename(FluxSourceProto* proto, const std::string& filename);
public:
virtual std::unique_ptr<Fluxmap> readFlux(int track, int side) = 0;
virtual std::unique_ptr<FluxSourceIterator> readFlux(int track, int side) = 0;
virtual void recalibrate() {}
virtual bool retryable() { return false; }
virtual bool isHardware() { return false; }
};
class TrivialFluxSource : public FluxSource
{
public:
std::unique_ptr<FluxSourceIterator> readFlux(int track, int side);
virtual std::unique_ptr<const Fluxmap> readSingleFlux(int track, int side) = 0;
};
#endif

View File

@@ -9,54 +9,87 @@
class HardwareFluxSource : public FluxSource
{
private:
class HardwareFluxSourceIterator : public FluxSourceIterator
{
public:
HardwareFluxSourceIterator(
const HardwareFluxSource& fluxsource, int cylinder, int head):
_fluxsource(fluxsource),
_cylinder(cylinder),
_head(head)
{
}
bool hasNext() const
{
return true;
}
std::unique_ptr<const Fluxmap> next()
{
usbSetDrive(_fluxsource._config.drive(),
_fluxsource._config.high_density(),
_fluxsource._config.index_mode());
usbSeek(_cylinder);
Bytes data = usbRead(_head,
_fluxsource._config.sync_with_index(),
_fluxsource._config.revolutions() * _fluxsource._oneRevolution,
_fluxsource._hardSectorThreshold);
auto fluxmap = std::make_unique<Fluxmap>();
fluxmap->appendBytes(data);
return fluxmap;
}
private:
const HardwareFluxSource& _fluxsource;
int _cylinder;
int _head;
};
public:
HardwareFluxSource(const HardwareFluxSourceProto& config):
_config(config)
HardwareFluxSource(const HardwareFluxSourceProto& config): _config(config)
{
int retries = 5;
usbSetDrive(_config.drive(), _config.high_density(), _config.index_mode());
Logger() << BeginSpeedOperationLogMessage();
do {
_oneRevolution = usbGetRotationalPeriod(_config.hard_sector_count());
usbSetDrive(
_config.drive(), _config.high_density(), _config.index_mode());
Logger() << BeginSpeedOperationLogMessage();
do
{
_oneRevolution =
usbGetRotationalPeriod(_config.hard_sector_count());
if (_config.hard_sector_count() != 0)
_hardSectorThreshold = _oneRevolution * 3 / (4 * _config.hard_sector_count());
_hardSectorThreshold =
_oneRevolution * 3 / (4 * _config.hard_sector_count());
else
_hardSectorThreshold = 0;
retries--;
} while ((_oneRevolution == 0) && (retries > 0));
if (_oneRevolution == 0) {
Error() << "Failed\nIs a disk in the drive?";
}
if (_oneRevolution == 0)
Error() << "Failed\nIs a disk in the drive?";
Logger() << EndSpeedOperationLogMessage { _oneRevolution };
Logger() << EndSpeedOperationLogMessage{_oneRevolution};
}
~HardwareFluxSource()
{
}
~HardwareFluxSource() {}
public:
std::unique_ptr<Fluxmap> readFlux(int track, int side)
std::unique_ptr<FluxSourceIterator> readFlux(int cylinder, int head) override
{
usbSetDrive(_config.drive(), _config.high_density(), _config.index_mode());
usbSeek(track);
Bytes data = usbRead(
side, _config.sync_with_index(), _config.revolutions() * _oneRevolution, _hardSectorThreshold);
auto fluxmap = std::make_unique<Fluxmap>();
fluxmap->appendBytes(data);
return fluxmap;
return std::make_unique<HardwareFluxSourceIterator>(
*this, cylinder, head);
}
void recalibrate()
void recalibrate() override
{
usbRecalibrate();
}
bool retryable()
bool isHardware() override
{
return true;
}
@@ -67,10 +100,8 @@ private:
nanoseconds_t _hardSectorThreshold;
};
std::unique_ptr<FluxSource> FluxSource::createHardwareFluxSource(const HardwareFluxSourceProto& config)
std::unique_ptr<FluxSource> FluxSource::createHardwareFluxSource(
const HardwareFluxSourceProto& config)
{
return std::unique_ptr<FluxSource>(new HardwareFluxSource(config));
}

View File

@@ -4,7 +4,7 @@
#include "lib/fluxsource/fluxsource.pb.h"
#include "fluxsource/fluxsource.h"
class KryofluxFluxSource : public FluxSource
class KryofluxFluxSource : public TrivialFluxSource
{
public:
KryofluxFluxSource(const KryofluxFluxSourceProto& config):
@@ -12,7 +12,7 @@ public:
{}
public:
std::unique_ptr<Fluxmap> readFlux(int track, int side)
std::unique_ptr<const Fluxmap> readSingleFlux(int track, int side) override
{
return readStream(_path, track, side);
}
@@ -25,5 +25,5 @@ private:
std::unique_ptr<FluxSource> FluxSource::createKryofluxFluxSource(const KryofluxFluxSourceProto& config)
{
return std::unique_ptr<FluxSource>(new KryofluxFluxSource(config));
return std::make_unique<KryofluxFluxSource>(config);
}

View File

@@ -24,7 +24,7 @@ static int strackno(int track, int side)
return (track << 1) | side;
}
class ScpFluxSource : public FluxSource
class ScpFluxSource : public TrivialFluxSource
{
public:
ScpFluxSource(const ScpFluxSourceProto& config):
@@ -55,14 +55,14 @@ public:
}
public:
std::unique_ptr<Fluxmap> readFlux(int track, int side)
std::unique_ptr<const Fluxmap> readSingleFlux(int track, int side) override
{
int strack = strackno(track, side);
if (strack >= ARRAY_SIZE(_header.track))
return std::unique_ptr<Fluxmap>();
return std::make_unique<Fluxmap>();
uint32_t offset = Bytes(_header.track[strack], 4).reader().read_le32();
if (offset == 0)
return std::unique_ptr<Fluxmap>();
return std::make_unique<Fluxmap>();
ScpTrackHeader trackheader;
_if.seekg(offset, std::ios::beg);
@@ -83,7 +83,7 @@ public:
revs[revolution] = trackrev;
}
std::unique_ptr<Fluxmap> fluxmap(new Fluxmap);
auto fluxmap = std::make_unique<Fluxmap>();
nanoseconds_t pending = 0;
unsigned inputBytes = 0;
for (int revolution = 0; revolution < _header.revolutions; revolution++)

View File

@@ -4,7 +4,7 @@
#include "lib/fluxsource/fluxsource.pb.h"
#include "fmt/format.h"
class TestPatternFluxSource : public FluxSource
class TestPatternFluxSource : public TrivialFluxSource
{
public:
TestPatternFluxSource(const TestPatternFluxSourceProto& config):
@@ -14,9 +14,9 @@ public:
~TestPatternFluxSource() {}
public:
std::unique_ptr<Fluxmap> readFlux(int track, int side)
std::unique_ptr<const Fluxmap> readSingleFlux(int track, int side) override
{
std::unique_ptr<Fluxmap> fluxmap(new Fluxmap);
auto fluxmap = std::make_unique<Fluxmap>();
while (fluxmap->duration() < (_config.sequence_length_us()*1000000.0))
{
@@ -35,7 +35,7 @@ private:
std::unique_ptr<FluxSource> FluxSource::createTestPatternFluxSource(const TestPatternFluxSourceProto& config)
{
return std::unique_ptr<FluxSource>(new TestPatternFluxSource(config));
return std::make_unique<TestPatternFluxSource>(config);
}