mirror of
https://github.com/davidgiven/fluxengine.git
synced 2025-10-31 11:17:01 -07:00
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:
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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++)
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user