This commit is contained in:
David Given
2022-02-21 22:22:10 +01:00
13 changed files with 396 additions and 186 deletions

View File

@@ -57,10 +57,10 @@ std::unique_ptr<AbstractDecoder> AbstractDecoder::create(const DecoderProto& con
return (decoder->second)(config); return (decoder->second)(config);
} }
std::unique_ptr<TrackDataFlux> AbstractDecoder::decodeToSectors( std::shared_ptr<TrackDataFlux> AbstractDecoder::decodeToSectors(
std::shared_ptr<const Fluxmap> fluxmap, unsigned physicalCylinder, unsigned physicalHead) std::shared_ptr<const Fluxmap> fluxmap, unsigned physicalCylinder, unsigned physicalHead)
{ {
_trackdata = std::make_unique<TrackDataFlux>(); _trackdata = std::make_shared<TrackDataFlux>();
_trackdata->fluxmap = fluxmap; _trackdata->fluxmap = fluxmap;
_trackdata->physicalCylinder = physicalCylinder; _trackdata->physicalCylinder = physicalCylinder;
_trackdata->physicalHead = physicalHead; _trackdata->physicalHead = physicalHead;

View File

@@ -45,7 +45,7 @@ public:
}; };
public: public:
std::unique_ptr<TrackDataFlux> decodeToSectors(std::shared_ptr<const Fluxmap> fluxmap, unsigned cylinder, unsigned head); std::shared_ptr<TrackDataFlux> decodeToSectors(std::shared_ptr<const Fluxmap> fluxmap, unsigned cylinder, unsigned head);
void pushRecord(const Fluxmap::Position& start, const Fluxmap::Position& end); void pushRecord(const Fluxmap::Position& start, const Fluxmap::Position& end);
void resetFluxDecoder(); void resetFluxDecoder();
@@ -82,7 +82,7 @@ protected:
virtual void decodeDataRecord() {}; virtual void decodeDataRecord() {};
const DecoderProto& _config; const DecoderProto& _config;
std::unique_ptr<TrackDataFlux> _trackdata; std::shared_ptr<TrackDataFlux> _trackdata;
std::shared_ptr<Sector> _sector; std::shared_ptr<Sector> _sector;
std::unique_ptr<FluxDecoder> _decoder; std::unique_ptr<FluxDecoder> _decoder;
std::vector<bool> _recordBits; std::vector<bool> _recordBits;

View File

@@ -25,13 +25,13 @@ struct TrackFlux
{ {
unsigned physicalCylinder; unsigned physicalCylinder;
unsigned physicalHead; unsigned physicalHead;
std::vector<std::unique_ptr<TrackDataFlux>> trackDatas; std::vector<std::shared_ptr<TrackDataFlux>> trackDatas;
std::set<std::shared_ptr<Sector>> sectors; std::set<std::shared_ptr<Sector>> sectors;
}; };
struct DiskFlux struct DiskFlux
{ {
std::vector<std::unique_ptr<TrackFlux>> tracks; std::vector<std::shared_ptr<TrackFlux>> tracks;
std::unique_ptr<Image> image; std::unique_ptr<Image> image;
}; };

View File

@@ -1,6 +1,7 @@
#include "globals.h" #include "globals.h"
#include "flags.h" #include "flags.h"
#include "fluxmap.h" #include "fluxmap.h"
#include "logger.h"
#include "usb/usb.h" #include "usb/usb.h"
#include "fluxsink/fluxsink.h" #include "fluxsink/fluxsink.h"
#include "lib/fluxsink/fluxsink.pb.h" #include "lib/fluxsink/fluxsink.pb.h"
@@ -14,22 +15,22 @@ public:
{ {
if (config.has_hard_sector_count()) if (config.has_hard_sector_count())
{ {
int rotationalSpeedMs; nanoseconds_t oneRevolution;
int retries = 5; int retries = 5;
usbSetDrive(_config.drive(), _config.high_density(), _config.index_mode()); usbSetDrive(_config.drive(), _config.high_density(), _config.index_mode());
std::cout << "Measuring rotational speed... " << std::flush; Logger() << BeginSpeedOperationLogMessage();
do { do {
nanoseconds_t oneRevolution = usbGetRotationalPeriod(_config.hard_sector_count()); oneRevolution = usbGetRotationalPeriod(_config.hard_sector_count());
_hardSectorThreshold = oneRevolution * 3 / (4 * _config.hard_sector_count()); _hardSectorThreshold = oneRevolution * 3 / (4 * _config.hard_sector_count());
rotationalSpeedMs = oneRevolution / 1e6;
retries--; retries--;
} while ((rotationalSpeedMs == 0) && (retries > 0)); } while ((oneRevolution == 0) && (retries > 0));
if (rotationalSpeedMs == 0) { if (oneRevolution == 0) {
Error() << "Failed\nIs a disk in the drive?"; Error() << "Failed\nIs a disk in the drive?";
} }
std::cout << fmt::format("{}ms\n", rotationalSpeedMs);
Logger() << EndSpeedOperationLogMessage(oneRevolution);
} }
else else
_hardSectorThreshold = 0; _hardSectorThreshold = 0;

View File

@@ -1,6 +1,7 @@
#include "globals.h" #include "globals.h"
#include "flags.h" #include "flags.h"
#include "fluxmap.h" #include "fluxmap.h"
#include "logger.h"
#include "usb/usb.h" #include "usb/usb.h"
#include "fluxsource/fluxsource.h" #include "fluxsource/fluxsource.h"
#include "lib/fluxsource/fluxsource.pb.h" #include "lib/fluxsource/fluxsource.pb.h"
@@ -12,10 +13,9 @@ public:
HardwareFluxSource(const HardwareFluxSourceProto& config): HardwareFluxSource(const HardwareFluxSourceProto& config):
_config(config) _config(config)
{ {
int rotationalSpeedMs;
int retries = 5; int retries = 5;
usbSetDrive(_config.drive(), _config.high_density(), _config.index_mode()); usbSetDrive(_config.drive(), _config.high_density(), _config.index_mode());
std::cout << "Measuring rotational speed... " << std::flush; Logger() << BeginSpeedOperationLogMessage();
do { do {
_oneRevolution = usbGetRotationalPeriod(_config.hard_sector_count()); _oneRevolution = usbGetRotationalPeriod(_config.hard_sector_count());
@@ -24,15 +24,14 @@ public:
else else
_hardSectorThreshold = 0; _hardSectorThreshold = 0;
rotationalSpeedMs = _oneRevolution / 1e6;
retries--; retries--;
} while ((rotationalSpeedMs == 0) && (retries > 0)); } while ((_oneRevolution == 0) && (retries > 0));
if (rotationalSpeedMs == 0) { if (_oneRevolution == 0) {
Error() << "Failed\nIs a disk in the drive?"; Error() << "Failed\nIs a disk in the drive?";
} }
std::cout << fmt::format("{}ms\n", rotationalSpeedMs); Logger() << EndSpeedOperationLogMessage(_oneRevolution);
} }
~HardwareFluxSource() ~HardwareFluxSource()

View File

@@ -12,6 +12,7 @@
#include <set> #include <set>
#include <cassert> #include <cassert>
#include <climits> #include <climits>
#include <variant>
#if defined(_WIN32) || defined(__WIN32__) #if defined(_WIN32) || defined(__WIN32__)
#include <direct.h> #include <direct.h>

129
lib/logger.cc Normal file
View File

@@ -0,0 +1,129 @@
#include "globals.h"
#include "bytes.h"
#include "fluxmap.h"
#include "sector.h"
#include "flux.h"
#include "fmt/format.h"
#include "logger.h"
template <class... Ts>
struct overloaded : Ts...
{
using Ts::operator()...;
};
template <class... Ts>
overloaded(Ts...) -> overloaded<Ts...>;
static bool indented = false;
static void indent()
{
if (!indented)
std::cout << " ";
indented = false;
}
Logger& Logger::operator<<(std::shared_ptr<AnyLogMessage> message)
{
std::visit(
overloaded{
/* Fallback --- do nothing */
[](const auto& m)
{
},
/* Start measuring the rotational speed */
[](const BeginSpeedOperationLogMessage& m)
{
std::cout << "Measuring rotational speed... " << std::flush;
},
/* Finish measuring the rotational speed */
[](const EndSpeedOperationLogMessage& m)
{
std::cout << fmt::format("{:.1f}ms ({:.1f}rpm)\n",
m.rotationalPeriod / 1e6,
60e9 / m.rotationalPeriod);
},
/* Indicates that we're working on a given cylinder and head */
[](const DiskContextLogMessage& m)
{
std::cout << fmt::format("{:2}.{}: ", m.cylinder, m.head)
<< std::flush;
indented = true;
},
/* A single read has happened */
[](const SingleReadLogMessage& m)
{
const auto& trackdataflux = m.trackDataFlux;
indent();
std::cout << fmt::format("{} records, {} sectors",
trackdataflux->records.size(),
trackdataflux->sectors.size());
if (trackdataflux->sectors.size() > 0)
{
nanoseconds_t clock =
(*trackdataflux->sectors.begin())->clock;
std::cout << fmt::format("; {:.2f}us clock ({:.0f}kHz)",
clock / 1000.0,
1000000.0 / clock);
}
std::cout << '\n';
indent();
std::cout << "sectors:";
std::vector<std::shared_ptr<Sector>> sectors(m.sectors.begin(), m.sectors.end());
std::sort(sectors.begin(), sectors.end(),
[](const std::shared_ptr<Sector>& s1, const std::shared_ptr<Sector>&s2)
{
return s1->logicalSector < s2->logicalSector;
}
);
for (const auto& sector : sectors)
std::cout << fmt::format(" {}{}", sector->logicalSector, Sector::statusToChar(sector->status));
std::cout << '\n';
},
/* We've finished reading a track */
[](const TrackReadLogMessage& m)
{
int size = 0;
std::set<std::pair<int, int>> track_ids;
for (const auto& sector : m.track->sectors)
{
track_ids.insert(std::make_pair(sector->logicalTrack, sector->logicalSide));
size += sector->data.size();
}
if (!track_ids.empty())
{
std::vector<std::string> ids;
for (const auto& i : track_ids)
ids.push_back(fmt::format("{}.{}", i.first, i.second));
indent();
std::cout << fmt::format("logical track {}\n", fmt::join(ids, "; "));
}
indent();
std::cout << fmt::format("{} bytes decoded\n", size);
},
/* Generic text message */
[](const std::string& s)
{
indent();
std::cout << s << '\n';
},
},
*message);
return *this;
}

64
lib/logger.h Normal file
View File

@@ -0,0 +1,64 @@
#ifndef LOGGER_H
#define LOGGER_H
#include "fmt/format.h"
class TrackDataFlux;
class TrackFlux;
class Sector;
struct BeginSpeedOperationLogMessage {};
struct EndSpeedOperationLogMessage
{
nanoseconds_t rotationalPeriod;
};
struct DiskContextLogMessage
{
unsigned cylinder;
unsigned head;
};
struct SingleReadLogMessage
{
std::shared_ptr<TrackDataFlux> trackDataFlux;
std::set<std::shared_ptr<Sector>> sectors;
};
struct TrackReadLogMessage
{
std::shared_ptr<TrackFlux> track;
};
struct BeginReadOperationLogMessage { };
struct EndReadOperationLogMessage { };
struct BeginWriteOperationLogMessage { };
struct EndWriteOperationLogMessage { };
class TrackFlux;
typedef std::variant<std::string,
SingleReadLogMessage,
TrackReadLogMessage,
DiskContextLogMessage,
BeginSpeedOperationLogMessage,
EndSpeedOperationLogMessage,
BeginReadOperationLogMessage,
EndReadOperationLogMessage,
BeginWriteOperationLogMessage,
EndWriteOperationLogMessage>
AnyLogMessage;
class Logger
{
public:
Logger& operator<<(std::shared_ptr<AnyLogMessage> message);
template <class T>
Logger& operator<<(const T& message)
{
return *this << std::make_shared<AnyLogMessage>(message);
}
};
#endif

View File

@@ -12,6 +12,7 @@
#include "flux.h" #include "flux.h"
#include "image.h" #include "image.h"
#include "imagewriter/imagewriter.h" #include "imagewriter/imagewriter.h"
#include "logger.h"
#include "fmt/format.h" #include "fmt/format.h"
#include "proto.h" #include "proto.h"
#include "lib/decoders/decoders.pb.h" #include "lib/decoders/decoders.pb.h"
@@ -22,13 +23,12 @@ static std::unique_ptr<FluxSink> outputFluxSink;
static std::shared_ptr<Fluxmap> readFluxmap(FluxSource& fluxsource, unsigned cylinder, unsigned head) static std::shared_ptr<Fluxmap> readFluxmap(FluxSource& fluxsource, unsigned cylinder, unsigned head)
{ {
std::cout << fmt::format("{0:>3}.{1}: ", cylinder, head) << std::flush; Logger() << DiskContextLogMessage { cylinder, head }
<< BeginReadOperationLogMessage();
std::shared_ptr<Fluxmap> fluxmap = fluxsource.readFlux(cylinder, head); std::shared_ptr<Fluxmap> fluxmap = fluxsource.readFlux(cylinder, head);
fluxmap->rescale(1.0/config.flux_source().rescale()); fluxmap->rescale(1.0/config.flux_source().rescale());
std::cout << fmt::format( Logger() << EndReadOperationLogMessage()
"{0:.0} ms in {1} bytes\n", << fmt::format("{0:.0} ms in {1} bytes", fluxmap->duration()/1e6, fluxmap->bytes());
fluxmap->duration()/1e6,
fluxmap->bytes());
return fluxmap; return fluxmap;
} }
@@ -50,8 +50,7 @@ static std::set<std::shared_ptr<Sector>> collect_sectors(std::set<std::shared_pt
{ {
if (replacement->data != replacing->data) if (replacement->data != replacing->data)
{ {
std::cout << fmt::format( Logger() << fmt::format("multiple conflicting copies of sector {} seen",
"\n multiple conflicting copies of sector {} seen; ",
std::get<2>(sectorid)); std::get<2>(sectorid));
replacing->status = replacement->status = Sector::CONFLICT; replacing->status = replacement->status = Sector::CONFLICT;
} }
@@ -77,7 +76,7 @@ void readDiskCommand(FluxSource& fluxsource, AbstractDecoder& decoder, ImageWrit
{ {
for (int head : iterate(config.heads())) for (int head : iterate(config.heads()))
{ {
auto track = std::make_unique<TrackFlux>(); auto track = std::make_shared<TrackFlux>();
std::set<std::shared_ptr<Sector>> track_sectors; std::set<std::shared_ptr<Sector>> track_sectors;
std::set<std::shared_ptr<Record>> track_records; std::set<std::shared_ptr<Record>> track_records;
Fluxmap totalFlux; Fluxmap totalFlux;
@@ -87,65 +86,49 @@ void readDiskCommand(FluxSource& fluxsource, AbstractDecoder& decoder, ImageWrit
auto fluxmap = readFluxmap(fluxsource, cylinder, head); auto fluxmap = readFluxmap(fluxsource, cylinder, head);
totalFlux.appendDesync().appendBytes(fluxmap->rawBytes()); totalFlux.appendDesync().appendBytes(fluxmap->rawBytes());
{ auto trackdataflux = decoder.decodeToSectors(fluxmap, cylinder, head);
auto trackdata = decoder.decodeToSectors(fluxmap, cylinder, head); track->trackDatas.push_back(trackdataflux);
std::cout << " "; track_sectors.insert(trackdataflux->sectors.begin(), trackdataflux->sectors.end());
std::cout << fmt::format("{} records, {} sectors; ", track_records.insert(trackdataflux->records.begin(), trackdataflux->records.end());
trackdata->records.size(),
trackdata->sectors.size());
if (trackdata->sectors.size() > 0)
{
nanoseconds_t clock = (*trackdata->sectors.begin())->clock;
std::cout << fmt::format("{:.2f}us clock ({:.0f}kHz); ",
clock / 1000.0, 1000000.0 / clock);
}
track_sectors.insert(trackdata->sectors.begin(), trackdata->sectors.end());
track_records.insert(trackdata->records.begin(), trackdata->records.end());
track->trackDatas.push_back(std::move(trackdata));
}
auto collected_sectors = collect_sectors(track_sectors); auto collected_sectors = collect_sectors(track_sectors);
std::cout << fmt::format("{} distinct sectors; ", collected_sectors.size());
bool hasBadSectors = false; bool hasBadSectors = false;
std::set<unsigned> required_sectors = decoder.requiredSectors(cylinder, head); std::set<unsigned> required_sectors = decoder.requiredSectors(cylinder, head);
std::set<std::shared_ptr<Sector>> result_sectors;
for (const auto& sector : collected_sectors) for (const auto& sector : collected_sectors)
{ {
result_sectors.insert(sector);
required_sectors.erase(sector->logicalSector); required_sectors.erase(sector->logicalSector);
if (sector->status != Sector::OK) if (sector->status != Sector::OK)
{
std::cout << std::endl
<< " Failed to read sector " << sector->logicalSector
<< " (" << Sector::statusToString(sector->status) << "); ";
hasBadSectors = true; hasBadSectors = true;
}
} }
for (unsigned logical_sector : required_sectors) for (unsigned logical_sector : required_sectors)
{ {
std::cout << "\n" auto sector = std::make_shared<Sector>();
<< " Required sector " << logical_sector << " missing; "; sector->logicalSector = logical_sector;
sector->status = Sector::MISSING;
result_sectors.insert(sector);
hasBadSectors = true; hasBadSectors = true;
} }
Logger() << SingleReadLogMessage { trackdataflux, result_sectors };
if (hasBadSectors) if (hasBadSectors)
failures = false; failures = false;
std::cout << std::endl
<< " ";
if (!hasBadSectors) if (!hasBadSectors)
break; break;
if (!fluxsource.retryable()) if (!fluxsource.retryable())
break; break;
if (retry == 0) if (retry == 0)
std::cout << "giving up" << std::endl Logger() << fmt::format("giving up");
<< " ";
else else
std::cout << retry << " retries remaining" << std::endl; Logger() << fmt::format("retrying; {} retries remaining", retry);
} }
if (outputFluxSink) if (outputFluxSink)
@@ -181,24 +164,9 @@ void readDiskCommand(FluxSource& fluxsource, AbstractDecoder& decoder, ImageWrit
} }
} }
int size = 0;
std::set<std::pair<int, int>> track_ids;
for (const auto& sector : track_sectors)
{
track_ids.insert(std::make_pair(sector->logicalTrack, sector->logicalSide));
size += sector->data.size();
}
if (!track_ids.empty())
{
std::cout << "logical track ";
for (const auto& i : track_ids)
std::cout << fmt::format("{}.{}; ", i.first, i.second);
}
std::cout << size << " bytes decoded." << std::endl;
track->sectors = collect_sectors(track_sectors); track->sectors = collect_sectors(track_sectors);
diskflux->tracks.push_back(std::move(track)); Logger() << TrackReadLogMessage { track };
diskflux->tracks.push_back(track);
} }
} }

View File

@@ -2,7 +2,7 @@
#include "sector.h" #include "sector.h"
#include "fmt/format.h" #include "fmt/format.h"
const std::string Sector::statusToString(Status status) std::string Sector::statusToString(Status status)
{ {
switch (status) switch (status)
{ {
@@ -15,6 +15,19 @@ const std::string Sector::statusToString(Status status)
} }
} }
std::string Sector::statusToChar(Status status)
{
switch (status)
{
case Status::OK: return "";
case Status::MISSING: return "?";
case Status::BAD_CHECKSUM: return "!";
case Status::DATA_MISSING: return "!";
case Status::CONFLICT: return "*";
default: return "?";
}
}
Sector::Status Sector::stringToStatus(const std::string& value) Sector::Status Sector::stringToStatus(const std::string& value)
{ {
if (value == "OK") if (value == "OK")

View File

@@ -24,7 +24,8 @@ public:
INTERNAL_ERROR INTERNAL_ERROR
}; };
static const std::string statusToString(Status status); static std::string statusToString(Status status);
static std::string statusToChar(Status status);
static Status stringToStatus(const std::string& value); static Status stringToStatus(const std::string& value);
Status status = Status::INTERNAL_ERROR; Status status = Status::INTERNAL_ERROR;

View File

@@ -12,144 +12,177 @@
#include "fmt/format.h" #include "fmt/format.h"
#include "sector.h" #include "sector.h"
#include "image.h" #include "image.h"
#include "logger.h"
#include "lib/config.pb.h" #include "lib/config.pb.h"
#include "proto.h" #include "proto.h"
void writeTracks( void writeTracks(FluxSink& fluxSink,
FluxSink& fluxSink, const std::function<std::unique_ptr<Fluxmap>(int track, int side)> producer)
const std::function<std::unique_ptr<Fluxmap>(int track, int side)> producer)
{ {
std::cout << "Writing to: " << fluxSink << std::endl; for (unsigned cylinder : iterate(config.cylinders()))
{
for (unsigned head : iterate(config.heads()))
{
Logger() << DiskContextLogMessage(cylinder, head)
<< fmt::format("{0:>3}.{1}: writing", cylinder, head)
<< BeginWriteOperationLogMessage();
for (unsigned cylinder : iterate(config.cylinders())) std::unique_ptr<Fluxmap> fluxmap = producer(cylinder, head);
{ if (!fluxmap)
for (unsigned head : iterate(config.heads())) {
{ /* Erase this track rather than writing. */
std::cout << fmt::format("{0:>3}.{1}: ", cylinder, head) << std::flush;
std::unique_ptr<Fluxmap> fluxmap = producer(cylinder, head);
if (!fluxmap)
{
/* Erase this track rather than writing. */
fluxmap.reset(new Fluxmap()); fluxmap.reset(new Fluxmap());
fluxSink.writeFlux(cylinder, head, *fluxmap); fluxSink.writeFlux(cylinder, head, *fluxmap);
std::cout << "erased\n"; Logger() << "erased";
} }
else else
{ {
fluxmap->rescale(config.flux_sink().rescale()); fluxmap->rescale(config.flux_sink().rescale());
/* Precompensation actually seems to make things worse, so let's leave /* Precompensation actually seems to make things worse, so let's
* it disabled for now. */ * leave it disabled for now. */
//fluxmap->precompensate(PRECOMPENSATION_THRESHOLD_TICKS, 2); // fluxmap->precompensate(PRECOMPENSATION_THRESHOLD_TICKS, 2);
fluxSink.writeFlux(cylinder, head, *fluxmap); fluxSink.writeFlux(cylinder, head, *fluxmap);
std::cout << fmt::format( Logger() << fmt::format("{0} ms in {1} bytes",
"{0} ms in {1} bytes", int(fluxmap->duration()/1e6), fluxmap->bytes()) << std::endl; int(fluxmap->duration() / 1e6),
} fluxmap->bytes());
} }
Logger() << EndWriteOperationLogMessage();
}
} }
} }
void writeTracksAndVerify( void writeTracksAndVerify(FluxSink& fluxSink,
FluxSink& fluxSink, AbstractEncoder& encoder,
AbstractEncoder& encoder, FluxSource& fluxSource,
FluxSource& fluxSource, AbstractDecoder& decoder,
AbstractDecoder& decoder, const Image& image)
const Image& image)
{ {
std::cout << "Writing to: " << fluxSink << std::endl; std::cout << "Writing to: " << fluxSink << std::endl;
for (unsigned cylinder : iterate(config.cylinders())) for (unsigned cylinder : iterate(config.cylinders()))
{ {
for (unsigned head : iterate(config.heads())) for (unsigned head : iterate(config.heads()))
{ {
std::cout << fmt::format("{0:>3}.{1}: Write: ", cylinder, head) << std::flush; Logger() << DiskContextLogMessage { cylinder, head }
auto sectors = encoder.collectSectors(cylinder, head, image); << fmt::format("{0:>3}.{1}", cylinder, head);
std::unique_ptr<Fluxmap> fluxmap = encoder.encode(cylinder, head, sectors, image);
if (!fluxmap)
{
/* Erase this track rather than writing. */
fluxmap.reset(new Fluxmap()); auto sectors = encoder.collectSectors(cylinder, head, image);
fluxSink.writeFlux(cylinder, head, *fluxmap); std::unique_ptr<Fluxmap> fluxmap =
std::cout << "erased\n"; encoder.encode(cylinder, head, sectors, image);
} if (!fluxmap)
else {
{ /* Erase this track rather than writing. */
fluxmap->rescale(config.flux_sink().rescale());
std::sort(sectors.begin(), sectors.end(), sectorPointerSortPredicate);
for (int retry = 0;; retry++) Logger() << BeginWriteOperationLogMessage() << "erasing";
{ fluxmap.reset(new Fluxmap());
/* Precompensation actually seems to make things worse, so let's leave fluxSink.writeFlux(cylinder, head, *fluxmap);
* it disabled for now. */ Logger() << EndWriteOperationLogMessage();
//fluxmap->precompensate(PRECOMPENSATION_THRESHOLD_TICKS, 2); }
fluxSink.writeFlux(cylinder, head, *fluxmap); else
std::cout << fmt::format( {
"{0} ms in {1} bytes\n", int(fluxmap->duration()/1e6), fluxmap->bytes()); fluxmap->rescale(config.flux_sink().rescale());
std::sort(
sectors.begin(), sectors.end(), sectorPointerSortPredicate);
std::cout << fmt::format(" Verify: ", cylinder, head) << std::flush; for (int retry = 0;; retry++)
std::shared_ptr<Fluxmap> writtenFluxmap = fluxSource.readFlux(cylinder, head); {
std::cout << fmt::format( /* Precompensation actually seems to make things worse, so
"{0} ms in {1} bytes\n", int(writtenFluxmap->duration()/1e6), writtenFluxmap->bytes()); * let's leave it disabled for now. */
const auto trackdata = decoder.decodeToSectors(writtenFluxmap, cylinder, head); // fluxmap->precompensate(PRECOMPENSATION_THRESHOLD_TICKS,
// 2);
Logger() << BeginWriteOperationLogMessage() << "writing";
fluxSink.writeFlux(cylinder, head, *fluxmap);
Logger() << EndWriteOperationLogMessage()
<< fmt::format("{0} ms in {1} bytes",
int(fluxmap->duration() / 1e6),
fluxmap->bytes());
std::vector<std::shared_ptr<Sector>> gotSectors = trackdata->sectors; Logger() << "verifying" << BeginReadOperationLogMessage();
gotSectors.erase(std::remove_if(gotSectors.begin(), gotSectors.end(), std::shared_ptr<Fluxmap> writtenFluxmap =
[](const auto& s) { return s->status != Sector::OK; }), gotSectors.end()); fluxSource.readFlux(cylinder, head);
std::sort(gotSectors.begin(), gotSectors.end(), sectorPointerSortPredicate); Logger() << EndReadOperationLogMessage()
gotSectors.erase(std::unique(gotSectors.begin(), gotSectors.end(), << fmt::format("{0} ms in {1} bytes",
sectorPointerEqualsPredicate), gotSectors.end()); int(writtenFluxmap->duration() / 1e6),
writtenFluxmap->bytes());
if (std::equal(gotSectors.begin(), gotSectors.end(), sectors.begin(), sectors.end(), const auto trackdata =
sectorPointerEqualsPredicate)) decoder.decodeToSectors(writtenFluxmap, cylinder, head);
break;
if (retry == config.decoder().retries()) std::vector<std::shared_ptr<Sector>> gotSectors =
Error() << "Write failed; uncorrectable error during write."; trackdata->sectors;
gotSectors.erase(std::remove_if(gotSectors.begin(),
gotSectors.end(),
[](const auto& s)
{
return s->status != Sector::OK;
}),
gotSectors.end());
std::sort(gotSectors.begin(),
gotSectors.end(),
sectorPointerSortPredicate);
gotSectors.erase(std::unique(gotSectors.begin(),
gotSectors.end(),
sectorPointerEqualsPredicate),
gotSectors.end());
std::cout << fmt::format(" Rewrite: ", cylinder, head) << std::flush; if (std::equal(gotSectors.begin(),
} gotSectors.end(),
} sectors.begin(),
} sectors.end(),
sectorPointerEqualsPredicate))
break;
if (retry == config.decoder().retries())
Error() << "Write failed; uncorrectable error during "
"write.";
Logger() << "retrying";
}
}
}
} }
} }
void fillBitmapTo(std::vector<bool>& bitmap, void fillBitmapTo(std::vector<bool>& bitmap,
unsigned& cursor, unsigned terminateAt, unsigned& cursor,
const std::vector<bool>& pattern) unsigned terminateAt,
const std::vector<bool>& pattern)
{ {
while (cursor < terminateAt) while (cursor < terminateAt)
{ {
for (bool b : pattern) for (bool b : pattern)
{ {
if (cursor < bitmap.size()) if (cursor < bitmap.size())
bitmap[cursor++] = b; bitmap[cursor++] = b;
} }
} }
} }
void writeDiskCommand(const Image& image, AbstractEncoder& encoder, FluxSink& fluxSink, void writeDiskCommand(const Image& image,
AbstractDecoder* decoder, FluxSource* fluxSource) AbstractEncoder& encoder,
FluxSink& fluxSink,
AbstractDecoder* decoder,
FluxSource* fluxSource)
{ {
if (fluxSource && decoder) if (fluxSource && decoder)
writeTracksAndVerify(fluxSink, encoder, *fluxSource, *decoder, image); writeTracksAndVerify(fluxSink, encoder, *fluxSource, *decoder, image);
else else
writeTracks(fluxSink, writeTracks(fluxSink,
[&](int physicalTrack, int physicalSide) -> std::unique_ptr<Fluxmap> [&](int physicalTrack, int physicalSide) -> std::unique_ptr<Fluxmap>
{ {
const auto& sectors = encoder.collectSectors(physicalTrack, physicalSide, image); const auto& sectors =
return encoder.encode(physicalTrack, physicalSide, sectors, image); encoder.collectSectors(physicalTrack, physicalSide, image);
} return encoder.encode(
); physicalTrack, physicalSide, sectors, image);
});
} }
void writeRawDiskCommand(FluxSource& fluxSource, FluxSink& fluxSink) void writeRawDiskCommand(FluxSource& fluxSource, FluxSink& fluxSink)
{ {
writeTracks(fluxSink, writeTracks(fluxSink,
[&](int track, int side) -> std::unique_ptr<Fluxmap> [&](int track, int side) -> std::unique_ptr<Fluxmap>
{ {
return fluxSource.readFlux(track, side); return fluxSource.readFlux(track, side);
} });
);
} }

View File

@@ -472,6 +472,7 @@ buildlibrary libbackend.a \
lib/imagewriter/rawimagewriter.cc \ lib/imagewriter/rawimagewriter.cc \
lib/imginputoutpututils.cc \ lib/imginputoutpututils.cc \
lib/ldbs.cc \ lib/ldbs.cc \
lib/logger.cc \
lib/proto.cc \ lib/proto.cc \
lib/reader.cc \ lib/reader.cc \
lib/sector.cc \ lib/sector.cc \