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

@@ -160,6 +160,24 @@ Bytes Bytes::slice(unsigned start) const
return slice(start, len);
}
std::vector<Bytes> Bytes::split(uint8_t separator) const
{
std::vector<Bytes> vector;
int lastEnd = 0;
for (int i=0; i<size(); i++)
{
if ((*this)[i] == separator)
{
vector.push_back(this->slice(lastEnd, i-lastEnd));
lastEnd = i + 1;
}
}
vector.push_back(this->slice(lastEnd));
return vector;
}
std::vector<bool> Bytes::toBits() const
{
std::vector<bool> bits;

View File

@@ -51,6 +51,8 @@ public:
Bytes& clear()
{ resize(0); return *this; }
std::vector<Bytes> split(uint8_t separator) const;
Bytes slice(unsigned start, unsigned len) const;
Bytes slice(unsigned start) const;
Bytes swab() const;

View File

@@ -4,8 +4,8 @@
Fluxmap& Fluxmap::appendBytes(const Bytes& bytes)
{
if (bytes.size() == 0)
return *this;
if (bytes.size() == 0)
return *this;
return appendBytes(&bytes[0], bytes.size());
}
@@ -18,7 +18,7 @@ Fluxmap& Fluxmap::appendBytes(const uint8_t* ptr, size_t len)
while (len--)
{
uint8_t byte = *ptr++;
_ticks += byte & 0x3f;
_ticks += byte & 0x3f;
bw.write_8(byte);
}
@@ -28,9 +28,9 @@ Fluxmap& Fluxmap::appendBytes(const uint8_t* ptr, size_t len)
uint8_t& Fluxmap::findLastByte()
{
if (_bytes.empty())
appendByte(0x00);
return *(_bytes.end() - 1);
if (_bytes.empty())
appendByte(0x00);
return *(_bytes.end() - 1);
}
Fluxmap& Fluxmap::appendInterval(uint32_t ticks)
@@ -46,19 +46,19 @@ Fluxmap& Fluxmap::appendInterval(uint32_t ticks)
Fluxmap& Fluxmap::appendPulse()
{
findLastByte() |= 0x80;
findLastByte() |= 0x80;
return *this;
}
Fluxmap& Fluxmap::appendIndex()
{
findLastByte() |= 0x40;
findLastByte() |= 0x40;
return *this;
}
Fluxmap& Fluxmap::appendDesync()
{
appendByte(F_DESYNC);
appendByte(F_DESYNC);
return *this;
}
@@ -66,65 +66,66 @@ void Fluxmap::precompensate(int threshold_ticks, int amount_ticks)
{
uint8_t junk = 0xff;
for (unsigned i=0; i<_bytes.size(); i++)
for (unsigned i = 0; i < _bytes.size(); i++)
{
uint8_t& prev = (i == 0) ? junk : _bytes[i-1];
uint8_t prevticks = prev & 0x3f;
uint8_t& prev = (i == 0) ? junk : _bytes[i - 1];
uint8_t prevticks = prev & 0x3f;
uint8_t currticks = _bytes[i] & 0x3f;
if (currticks < (3*threshold_ticks))
if (currticks < (3 * threshold_ticks))
{
if ((prevticks <= threshold_ticks) && (currticks > threshold_ticks))
{
/* 01001; move the previous bit backwards. */
if (prevticks >= (1+amount_ticks))
if (prevticks >= (1 + amount_ticks))
prev -= amount_ticks;
if (currticks <= (0x7f-amount_ticks))
if (currticks <= (0x7f - amount_ticks))
currticks += amount_ticks;
}
else if ((prevticks > threshold_ticks) && (currticks <= threshold_ticks))
else if ((prevticks > threshold_ticks) &&
(currticks <= threshold_ticks))
{
/* 00101; move the current bit forwards. */
if (prevticks <= (0x7f-amount_ticks))
if (prevticks <= (0x7f - amount_ticks))
prev += amount_ticks;
if (currticks >= (1+amount_ticks))
if (currticks >= (1 + amount_ticks))
currticks -= amount_ticks;
}
}
}
}
std::vector<Fluxmap> Fluxmap::split() {
std::vector<Fluxmap> maps;
Fluxmap map;
for (unsigned i=0; i<_bytes.size(); i++) {
if (_bytes[i] == F_DESYNC) {
if (i > 0)
maps.push_back(map);
map = Fluxmap();
} else {
map.appendByte(_bytes[i]);
}
std::vector<std::unique_ptr<const Fluxmap>> Fluxmap::split() const
{
std::vector<std::unique_ptr<const Fluxmap>> maps;
auto bytesVector = rawBytes().split(F_DESYNC);
for (auto bytes : bytesVector)
{
if (bytes.size() != 0)
maps.push_back(std::move(std::make_unique<Fluxmap>(bytes)));
}
maps.push_back(map);
return maps;
}
void Fluxmap::rescale(double scale) {
if (scale != 1.0) {
auto bytesOrig = _bytes;
_bytes = Bytes();
_duration = 0;
_ticks = 0;
int lastEvent = 0;
for (unsigned i=0; i<bytesOrig.size(); i++)
std::unique_ptr<const Fluxmap> Fluxmap::rescale(double scale) const
{
if (scale == 1.0)
return std::make_unique<Fluxmap>(rawBytes());
auto newFluxmap = std::make_unique<Fluxmap>();
int lastEvent = 0;
for (uint8_t b : _bytes)
{
lastEvent += b & 0x3f;
if (b & 0xc0)
{
lastEvent += bytesOrig[i] & 0x3f;
if (bytesOrig[i] & 0xc0) {
appendInterval(lastEvent * scale + 0.5);
findLastByte() |= bytesOrig[i] & 0xc0;
lastEvent = 0;
}
newFluxmap->appendInterval(lastEvent * scale + 0.5);
newFluxmap->findLastByte() |= b & 0xc0;
lastEvent = 0;
}
}
return newFluxmap;
}

View File

@@ -64,8 +64,8 @@ public:
Fluxmap& appendBits(const std::vector<bool>& bits, nanoseconds_t clock);
void precompensate(int threshold_ticks, int amount_ticks);
std::vector<Fluxmap> split();
void rescale(double scale);
std::vector<std::unique_ptr<const Fluxmap>> split() const;
std::unique_ptr<const Fluxmap> rescale(double scale) const;
private:
uint8_t& findLastByte();

View File

@@ -26,7 +26,7 @@ public:
}
public:
void writeFlux(int cylinder, int head, Fluxmap& fluxmap)
void writeFlux(int cylinder, int head, const Fluxmap& fluxmap) override
{
unsigned totalTicks = fluxmap.ticks() + 2;
unsigned channels = _config.index_markers() ? 2 : 1;

View File

@@ -39,7 +39,8 @@ public:
auto track = proto.add_track();
track->set_cylinder(e.first.first);
track->set_head(e.first.second);
track->set_flux(e.second);
for (const auto& fluxBytes : e.second)
track->add_flux(fluxBytes);
}
if (!proto.SerializeToOstream(&_of))
@@ -50,9 +51,10 @@ public:
}
public:
void writeFlux(int cylinder, int head, Fluxmap& fluxmap)
void writeFlux(int cylinder, int head, const Fluxmap& fluxmap) override
{
_data[std::make_pair(cylinder, head)] = fluxmap.rawBytes();
auto& vector = _data[std::make_pair(cylinder, head)];
vector.push_back(fluxmap.rawBytes());
}
operator std::string () const
@@ -63,7 +65,7 @@ public:
private:
std::string _filename;
std::ofstream _of;
std::map<std::pair<unsigned, unsigned>, Bytes> _data;
std::map<std::pair<unsigned, unsigned>, std::vector<Bytes>> _data;
};
std::unique_ptr<FluxSink> FluxSink::createFl2FluxSink(const Fl2FluxSinkProto& config)

View File

@@ -29,7 +29,7 @@ public:
static void updateConfigForFilename(FluxSinkProto* proto, const std::string& filename);
public:
virtual void writeFlux(int track, int side, Fluxmap& fluxmap) = 0;
virtual void writeFlux(int track, int side, const Fluxmap& fluxmap) = 0;
virtual operator std::string () const = 0;
};

View File

@@ -41,7 +41,7 @@ public:
}
public:
void writeFlux(int track, int side, Fluxmap& fluxmap)
void writeFlux(int track, int side, const Fluxmap& fluxmap) override
{
usbSetDrive(_config.drive(), _config.high_density(), _config.index_mode());
#if 0

View File

@@ -8,6 +8,7 @@
#include "lib/fluxsink/fluxsink.pb.h"
#include "proto.h"
#include "fmt/format.h"
#include "fluxmap.h"
#include "scp.h"
#include <fstream>
#include <sys/stat.h>
@@ -79,7 +80,7 @@ public:
}
public:
void writeFlux(int cylinder, int head, Fluxmap& fluxmap)
void writeFlux(int cylinder, int head, const Fluxmap& fluxmap) override
{
ByteWriter trackdataWriter(_trackdata);
trackdataWriter.seekToEnd();
@@ -97,9 +98,7 @@ public:
trackheader.header.track_id[2] = 'K';
trackheader.header.strack = strack;
auto lastFluxmap = fluxmap.split().back();
FluxmapReader fmr(lastFluxmap);
FluxmapReader fmr(fluxmap);
Bytes fluxdata;
ByteWriter fluxdataWriter(fluxdata);

View File

@@ -20,7 +20,7 @@ public:
{}
public:
void writeFlux(int cylinder, int head, Fluxmap& fluxmap)
void writeFlux(int cylinder, int head, const Fluxmap& fluxmap) override
{
mkdir(_config.directory().c_str(), 0744);
std::ofstream of(

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);
}

View File

@@ -22,11 +22,10 @@
static std::unique_ptr<FluxSink> outputFluxSink;
static std::shared_ptr<Fluxmap> readFluxmap(FluxSource& fluxsource, unsigned cylinder, unsigned head)
static std::shared_ptr<const Fluxmap> readFluxmap(FluxSourceIterator& fluxsourceIterator, unsigned cylinder, unsigned head)
{
Logger() << BeginReadOperationLogMessage { cylinder, head };
std::shared_ptr<Fluxmap> fluxmap = fluxsource.readFlux(cylinder, head);
fluxmap->rescale(1.0/config.flux_source().rescale());
auto fluxmap = fluxsourceIterator.next()->rescale(1.0/config.flux_source().rescale());
Logger() << EndReadOperationLogMessage()
<< fmt::format("{0:.0} ms in {1} bytes", fluxmap->duration()/1e6, fluxmap->bytes());
return fluxmap;
@@ -107,9 +106,11 @@ std::shared_ptr<const DiskFlux> readDiskCommand(FluxSource& fluxsource, Abstract
std::set<std::shared_ptr<const Record>> track_records;
Fluxmap totalFlux;
for (int retry = config.decoder().retries(); retry >= 0; retry--)
auto fluxsourceIterator = fluxsource.readFlux(cylinder, head);
int retry = 0;
while (fluxsourceIterator->hasNext())
{
auto fluxmap = readFluxmap(fluxsource, cylinder, head);
auto fluxmap = readFluxmap(*fluxsourceIterator, cylinder, head);
totalFlux.appendDesync().appendBytes(fluxmap->rawBytes());
auto trackdataflux =
@@ -154,13 +155,17 @@ std::shared_ptr<const DiskFlux> readDiskCommand(FluxSource& fluxsource, Abstract
if (!hasBadSectors)
break;
if (!fluxsource.retryable())
if (!fluxsourceIterator->hasNext())
break;
if (retry == 0)
Logger() << fmt::format("giving up");
else
Logger()
<< fmt::format("retrying; {} retries remaining", retry);
if (fluxsource.isHardware())
{
retry++;
if (retry == 0)
Logger() << fmt::format("giving up");
else
Logger()
<< fmt::format("retrying; {} retries remaining", retry);
}
}
if (outputFluxSink)
@@ -232,7 +237,8 @@ void rawReadDiskCommand(FluxSource& fluxsource, FluxSink& fluxsink)
for (int head : iterate(config.heads()))
{
testForEmergencyStop();
auto fluxmap = readFluxmap(fluxsource, cylinder, head);
auto fluxsourceIterator = fluxsource.readFlux(cylinder, head);
auto fluxmap = readFluxmap(*fluxsourceIterator, cylinder, head);
fluxsink.writeFlux(cylinder, head, *fluxmap);
}
}

View File

@@ -18,7 +18,7 @@
#include "proto.h"
void writeTracks(FluxSink& fluxSink,
const std::function<std::unique_ptr<Fluxmap>(int track, int side)> producer)
const std::function<std::unique_ptr<const Fluxmap>(int track, int side)> producer)
{
for (unsigned cylinder : iterate(config.cylinders()))
{
@@ -27,7 +27,7 @@ void writeTracks(FluxSink& fluxSink,
testForEmergencyStop();
Logger() << BeginWriteOperationLogMessage{cylinder, head};
std::unique_ptr<Fluxmap> fluxmap = producer(cylinder, head);
auto fluxmap = producer(cylinder, head);
if (!fluxmap)
{
/* Erase this track rather than writing. */
@@ -38,11 +38,11 @@ void writeTracks(FluxSink& fluxSink,
}
else
{
fluxmap->rescale(config.flux_sink().rescale());
auto scaled = fluxmap->rescale(config.flux_sink().rescale());
/* Precompensation actually seems to make things worse, so let's
* leave it disabled for now. */
// fluxmap->precompensate(PRECOMPENSATION_THRESHOLD_TICKS, 2);
fluxSink.writeFlux(cylinder, head, *fluxmap);
fluxSink.writeFlux(cylinder, head, *scaled);
Logger() << fmt::format("{0} ms in {1} bytes",
int(fluxmap->duration() / 1e6),
fluxmap->bytes());
@@ -99,8 +99,7 @@ void writeTracksAndVerify(FluxSink& fluxSink,
fluxmap->bytes());
Logger() << BeginReadOperationLogMessage{cylinder, head};
std::shared_ptr<Fluxmap> writtenFluxmap =
fluxSource.readFlux(cylinder, head);
std::shared_ptr<const Fluxmap> writtenFluxmap = fluxSource.readFlux(cylinder, head)->next();
Logger() << EndReadOperationLogMessage()
<< fmt::format("verifying {0} ms in {1} bytes",
int(writtenFluxmap->duration() / 1e6),
@@ -183,8 +182,8 @@ void writeDiskCommand(const Image& image,
void writeRawDiskCommand(FluxSource& fluxSource, FluxSink& fluxSink)
{
writeTracks(fluxSink,
[&](int track, int side) -> std::unique_ptr<Fluxmap>
[&](int track, int side) -> std::unique_ptr<const Fluxmap>
{
return fluxSource.readFlux(track, side);
return fluxSource.readFlux(track, side)->next();
});
}

View File

@@ -9,14 +9,20 @@ class FluxSource;
class FluxSink;
class Image;
extern void writeTracks(FluxSink& fluxSink, const std::function<std::unique_ptr<Fluxmap>(int track, int side)> producer);
extern void writeTracks(FluxSink& fluxSink,
const std::function<std::unique_ptr<const Fluxmap>(int track, int side)>
producer);
extern void fillBitmapTo(std::vector<bool>& bitmap,
unsigned& cursor, unsigned terminateAt,
const std::vector<bool>& pattern);
extern void writeDiskCommand(const Image& image, AbstractEncoder& encoder, FluxSink& fluxSink,
AbstractDecoder* decoder = nullptr, FluxSource* fluxSource = nullptr);
unsigned& cursor,
unsigned terminateAt,
const std::vector<bool>& pattern);
extern void writeDiskCommand(const Image& image,
AbstractEncoder& encoder,
FluxSink& fluxSink,
AbstractDecoder* decoder = nullptr,
FluxSource* fluxSource = nullptr);
extern void writeRawDiskCommand(FluxSource& fluxSource, FluxSink& fluxSink);
#endif

View File

@@ -89,7 +89,7 @@ enum
{
F_BIT_PULSE = 0x80,
F_BIT_INDEX = 0x40,
F_DESYNC = 0x00,
F_DESYNC = 0x00, /* obsolete */
F_EOF = 0x100 /* synthetic, only produced by library */
};

View File

@@ -204,7 +204,7 @@ int mainInspect(int argc, const char* argv[])
flags.parseFlagsWithConfigFiles(argc, argv, {});
std::unique_ptr<FluxSource> fluxSource(FluxSource::create(config.flux_source()));
const auto fluxmap = fluxSource->readFlux(cylinderFlag, headFlag);
const auto fluxmap = fluxSource->readFlux(cylinderFlag, headFlag)->next();
std::cout << fmt::format("0x{:x} bytes of data in {:.3f}ms\n",
fluxmap->bytes(),

View File

@@ -1,5 +1,8 @@
#include "globals.h"
#include "bytes.h"
#include "snowhouse/snowhouse.h"
using namespace snowhouse;
static void check_oob(Bytes& b, unsigned pos)
{
@@ -115,6 +118,49 @@ static void test_slice()
assert((bs == Bytes{ 0, 0 }));
}
static void test_split()
{
AssertThat(
(Bytes{ }).split(0),
Equals(std::vector<Bytes> {
Bytes{}
}));
AssertThat(
(Bytes{ 0 }).split(0),
Equals(std::vector<Bytes> {
Bytes{},
Bytes{}
}));
AssertThat(
(Bytes{ 1 }).split(0),
Equals(std::vector<Bytes> {
Bytes{ 1 }
}));
AssertThat(
(Bytes{ 1, 0 }).split(0),
Equals(std::vector<Bytes> {
Bytes{ 1 },
Bytes{ }
}));
AssertThat(
(Bytes{ 0, 1 }).split(0),
Equals(std::vector<Bytes> {
Bytes{ },
Bytes{ 1 }
}));
AssertThat(
(Bytes{ 1, 0, 1 }).split(0),
Equals(std::vector<Bytes> {
Bytes{ 1 },
Bytes{ 1 }
}));
}
static void test_tobits()
{
Bytes b = {1, 2};
@@ -139,6 +185,7 @@ int main(int argc, const char* argv[])
test_reads();
test_writes();
test_slice();
test_split();
test_tobits();
test_tostring();
return 0;