mirror of
https://github.com/davidgiven/fluxengine.git
synced 2025-10-31 11:17:01 -07:00
Merge.
This commit is contained in:
@@ -57,10 +57,10 @@ std::unique_ptr<AbstractDecoder> AbstractDecoder::create(const DecoderProto& con
|
||||
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)
|
||||
{
|
||||
_trackdata = std::make_unique<TrackDataFlux>();
|
||||
_trackdata = std::make_shared<TrackDataFlux>();
|
||||
_trackdata->fluxmap = fluxmap;
|
||||
_trackdata->physicalCylinder = physicalCylinder;
|
||||
_trackdata->physicalHead = physicalHead;
|
||||
|
||||
@@ -45,7 +45,7 @@ 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 resetFluxDecoder();
|
||||
@@ -82,7 +82,7 @@ protected:
|
||||
virtual void decodeDataRecord() {};
|
||||
|
||||
const DecoderProto& _config;
|
||||
std::unique_ptr<TrackDataFlux> _trackdata;
|
||||
std::shared_ptr<TrackDataFlux> _trackdata;
|
||||
std::shared_ptr<Sector> _sector;
|
||||
std::unique_ptr<FluxDecoder> _decoder;
|
||||
std::vector<bool> _recordBits;
|
||||
|
||||
@@ -25,13 +25,13 @@ struct TrackFlux
|
||||
{
|
||||
unsigned physicalCylinder;
|
||||
unsigned physicalHead;
|
||||
std::vector<std::unique_ptr<TrackDataFlux>> trackDatas;
|
||||
std::vector<std::shared_ptr<TrackDataFlux>> trackDatas;
|
||||
std::set<std::shared_ptr<Sector>> sectors;
|
||||
};
|
||||
|
||||
struct DiskFlux
|
||||
{
|
||||
std::vector<std::unique_ptr<TrackFlux>> tracks;
|
||||
std::vector<std::shared_ptr<TrackFlux>> tracks;
|
||||
std::unique_ptr<Image> image;
|
||||
};
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "globals.h"
|
||||
#include "flags.h"
|
||||
#include "fluxmap.h"
|
||||
#include "logger.h"
|
||||
#include "usb/usb.h"
|
||||
#include "fluxsink/fluxsink.h"
|
||||
#include "lib/fluxsink/fluxsink.pb.h"
|
||||
@@ -14,22 +15,22 @@ public:
|
||||
{
|
||||
if (config.has_hard_sector_count())
|
||||
{
|
||||
int rotationalSpeedMs;
|
||||
nanoseconds_t oneRevolution;
|
||||
int retries = 5;
|
||||
usbSetDrive(_config.drive(), _config.high_density(), _config.index_mode());
|
||||
std::cout << "Measuring rotational speed... " << std::flush;
|
||||
Logger() << BeginSpeedOperationLogMessage();
|
||||
|
||||
do {
|
||||
nanoseconds_t oneRevolution = usbGetRotationalPeriod(_config.hard_sector_count());
|
||||
oneRevolution = usbGetRotationalPeriod(_config.hard_sector_count());
|
||||
_hardSectorThreshold = oneRevolution * 3 / (4 * _config.hard_sector_count());
|
||||
rotationalSpeedMs = oneRevolution / 1e6;
|
||||
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?";
|
||||
}
|
||||
std::cout << fmt::format("{}ms\n", rotationalSpeedMs);
|
||||
|
||||
Logger() << EndSpeedOperationLogMessage(oneRevolution);
|
||||
}
|
||||
else
|
||||
_hardSectorThreshold = 0;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "globals.h"
|
||||
#include "flags.h"
|
||||
#include "fluxmap.h"
|
||||
#include "logger.h"
|
||||
#include "usb/usb.h"
|
||||
#include "fluxsource/fluxsource.h"
|
||||
#include "lib/fluxsource/fluxsource.pb.h"
|
||||
@@ -12,10 +13,9 @@ public:
|
||||
HardwareFluxSource(const HardwareFluxSourceProto& config):
|
||||
_config(config)
|
||||
{
|
||||
int rotationalSpeedMs;
|
||||
int retries = 5;
|
||||
usbSetDrive(_config.drive(), _config.high_density(), _config.index_mode());
|
||||
std::cout << "Measuring rotational speed... " << std::flush;
|
||||
Logger() << BeginSpeedOperationLogMessage();
|
||||
|
||||
do {
|
||||
_oneRevolution = usbGetRotationalPeriod(_config.hard_sector_count());
|
||||
@@ -24,15 +24,14 @@ public:
|
||||
else
|
||||
_hardSectorThreshold = 0;
|
||||
|
||||
rotationalSpeedMs = _oneRevolution / 1e6;
|
||||
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?";
|
||||
}
|
||||
|
||||
std::cout << fmt::format("{}ms\n", rotationalSpeedMs);
|
||||
Logger() << EndSpeedOperationLogMessage(_oneRevolution);
|
||||
}
|
||||
|
||||
~HardwareFluxSource()
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include <set>
|
||||
#include <cassert>
|
||||
#include <climits>
|
||||
#include <variant>
|
||||
|
||||
#if defined(_WIN32) || defined(__WIN32__)
|
||||
#include <direct.h>
|
||||
|
||||
129
lib/logger.cc
Normal file
129
lib/logger.cc
Normal 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
64
lib/logger.h
Normal 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
|
||||
@@ -12,6 +12,7 @@
|
||||
#include "flux.h"
|
||||
#include "image.h"
|
||||
#include "imagewriter/imagewriter.h"
|
||||
#include "logger.h"
|
||||
#include "fmt/format.h"
|
||||
#include "proto.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)
|
||||
{
|
||||
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);
|
||||
fluxmap->rescale(1.0/config.flux_source().rescale());
|
||||
std::cout << fmt::format(
|
||||
"{0:.0} ms in {1} bytes\n",
|
||||
fluxmap->duration()/1e6,
|
||||
fluxmap->bytes());
|
||||
Logger() << EndReadOperationLogMessage()
|
||||
<< fmt::format("{0:.0} ms in {1} bytes", fluxmap->duration()/1e6, fluxmap->bytes());
|
||||
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)
|
||||
{
|
||||
std::cout << fmt::format(
|
||||
"\n multiple conflicting copies of sector {} seen; ",
|
||||
Logger() << fmt::format("multiple conflicting copies of sector {} seen",
|
||||
std::get<2>(sectorid));
|
||||
replacing->status = replacement->status = Sector::CONFLICT;
|
||||
}
|
||||
@@ -77,7 +76,7 @@ void readDiskCommand(FluxSource& fluxsource, AbstractDecoder& decoder, ImageWrit
|
||||
{
|
||||
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<Record>> track_records;
|
||||
Fluxmap totalFlux;
|
||||
@@ -87,65 +86,49 @@ void readDiskCommand(FluxSource& fluxsource, AbstractDecoder& decoder, ImageWrit
|
||||
auto fluxmap = readFluxmap(fluxsource, cylinder, head);
|
||||
totalFlux.appendDesync().appendBytes(fluxmap->rawBytes());
|
||||
|
||||
{
|
||||
auto trackdata = decoder.decodeToSectors(fluxmap, cylinder, head);
|
||||
auto trackdataflux = decoder.decodeToSectors(fluxmap, cylinder, head);
|
||||
track->trackDatas.push_back(trackdataflux);
|
||||
|
||||
std::cout << " ";
|
||||
std::cout << fmt::format("{} records, {} sectors; ",
|
||||
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));
|
||||
}
|
||||
track_sectors.insert(trackdataflux->sectors.begin(), trackdataflux->sectors.end());
|
||||
track_records.insert(trackdataflux->records.begin(), trackdataflux->records.end());
|
||||
|
||||
auto collected_sectors = collect_sectors(track_sectors);
|
||||
std::cout << fmt::format("{} distinct sectors; ", collected_sectors.size());
|
||||
|
||||
bool hasBadSectors = false;
|
||||
std::set<unsigned> required_sectors = decoder.requiredSectors(cylinder, head);
|
||||
std::set<std::shared_ptr<Sector>> result_sectors;
|
||||
for (const auto& sector : collected_sectors)
|
||||
{
|
||||
result_sectors.insert(sector);
|
||||
required_sectors.erase(sector->logicalSector);
|
||||
|
||||
if (sector->status != Sector::OK)
|
||||
{
|
||||
std::cout << std::endl
|
||||
<< " Failed to read sector " << sector->logicalSector
|
||||
<< " (" << Sector::statusToString(sector->status) << "); ";
|
||||
hasBadSectors = true;
|
||||
}
|
||||
}
|
||||
for (unsigned logical_sector : required_sectors)
|
||||
{
|
||||
std::cout << "\n"
|
||||
<< " Required sector " << logical_sector << " missing; ";
|
||||
auto sector = std::make_shared<Sector>();
|
||||
sector->logicalSector = logical_sector;
|
||||
sector->status = Sector::MISSING;
|
||||
result_sectors.insert(sector);
|
||||
|
||||
hasBadSectors = true;
|
||||
}
|
||||
|
||||
Logger() << SingleReadLogMessage { trackdataflux, result_sectors };
|
||||
|
||||
if (hasBadSectors)
|
||||
failures = false;
|
||||
|
||||
std::cout << std::endl
|
||||
<< " ";
|
||||
|
||||
if (!hasBadSectors)
|
||||
break;
|
||||
|
||||
if (!fluxsource.retryable())
|
||||
break;
|
||||
if (retry == 0)
|
||||
std::cout << "giving up" << std::endl
|
||||
<< " ";
|
||||
Logger() << fmt::format("giving up");
|
||||
else
|
||||
std::cout << retry << " retries remaining" << std::endl;
|
||||
Logger() << fmt::format("retrying; {} retries remaining", retry);
|
||||
}
|
||||
|
||||
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);
|
||||
diskflux->tracks.push_back(std::move(track));
|
||||
Logger() << TrackReadLogMessage { track };
|
||||
diskflux->tracks.push_back(track);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
#include "sector.h"
|
||||
#include "fmt/format.h"
|
||||
|
||||
const std::string Sector::statusToString(Status status)
|
||||
std::string Sector::statusToString(Status 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)
|
||||
{
|
||||
if (value == "OK")
|
||||
|
||||
@@ -24,7 +24,8 @@ public:
|
||||
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);
|
||||
|
||||
Status status = Status::INTERNAL_ERROR;
|
||||
|
||||
251
lib/writer.cc
251
lib/writer.cc
@@ -12,144 +12,177 @@
|
||||
#include "fmt/format.h"
|
||||
#include "sector.h"
|
||||
#include "image.h"
|
||||
#include "logger.h"
|
||||
#include "lib/config.pb.h"
|
||||
#include "proto.h"
|
||||
|
||||
void writeTracks(
|
||||
FluxSink& fluxSink,
|
||||
const std::function<std::unique_ptr<Fluxmap>(int track, int side)> producer)
|
||||
void writeTracks(FluxSink& fluxSink,
|
||||
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()))
|
||||
{
|
||||
for (unsigned head : iterate(config.heads()))
|
||||
{
|
||||
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. */
|
||||
std::unique_ptr<Fluxmap> fluxmap = producer(cylinder, head);
|
||||
if (!fluxmap)
|
||||
{
|
||||
/* Erase this track rather than writing. */
|
||||
|
||||
fluxmap.reset(new Fluxmap());
|
||||
fluxSink.writeFlux(cylinder, head, *fluxmap);
|
||||
std::cout << "erased\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
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);
|
||||
std::cout << fmt::format(
|
||||
"{0} ms in {1} bytes", int(fluxmap->duration()/1e6), fluxmap->bytes()) << std::endl;
|
||||
}
|
||||
}
|
||||
fluxmap.reset(new Fluxmap());
|
||||
fluxSink.writeFlux(cylinder, head, *fluxmap);
|
||||
Logger() << "erased";
|
||||
}
|
||||
else
|
||||
{
|
||||
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);
|
||||
Logger() << fmt::format("{0} ms in {1} bytes",
|
||||
int(fluxmap->duration() / 1e6),
|
||||
fluxmap->bytes());
|
||||
}
|
||||
Logger() << EndWriteOperationLogMessage();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void writeTracksAndVerify(
|
||||
FluxSink& fluxSink,
|
||||
AbstractEncoder& encoder,
|
||||
FluxSource& fluxSource,
|
||||
AbstractDecoder& decoder,
|
||||
const Image& image)
|
||||
void writeTracksAndVerify(FluxSink& fluxSink,
|
||||
AbstractEncoder& encoder,
|
||||
FluxSource& fluxSource,
|
||||
AbstractDecoder& decoder,
|
||||
const Image& image)
|
||||
{
|
||||
std::cout << "Writing to: " << fluxSink << std::endl;
|
||||
|
||||
for (unsigned cylinder : iterate(config.cylinders()))
|
||||
{
|
||||
for (unsigned head : iterate(config.heads()))
|
||||
{
|
||||
std::cout << fmt::format("{0:>3}.{1}: Write: ", cylinder, head) << std::flush;
|
||||
auto sectors = encoder.collectSectors(cylinder, head, image);
|
||||
std::unique_ptr<Fluxmap> fluxmap = encoder.encode(cylinder, head, sectors, image);
|
||||
if (!fluxmap)
|
||||
{
|
||||
/* Erase this track rather than writing. */
|
||||
for (unsigned cylinder : iterate(config.cylinders()))
|
||||
{
|
||||
for (unsigned head : iterate(config.heads()))
|
||||
{
|
||||
Logger() << DiskContextLogMessage { cylinder, head }
|
||||
<< fmt::format("{0:>3}.{1}", cylinder, head);
|
||||
|
||||
fluxmap.reset(new Fluxmap());
|
||||
fluxSink.writeFlux(cylinder, head, *fluxmap);
|
||||
std::cout << "erased\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
fluxmap->rescale(config.flux_sink().rescale());
|
||||
std::sort(sectors.begin(), sectors.end(), sectorPointerSortPredicate);
|
||||
auto sectors = encoder.collectSectors(cylinder, head, image);
|
||||
std::unique_ptr<Fluxmap> fluxmap =
|
||||
encoder.encode(cylinder, head, sectors, image);
|
||||
if (!fluxmap)
|
||||
{
|
||||
/* Erase this track rather than writing. */
|
||||
|
||||
for (int retry = 0;; retry++)
|
||||
{
|
||||
/* 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);
|
||||
std::cout << fmt::format(
|
||||
"{0} ms in {1} bytes\n", int(fluxmap->duration()/1e6), fluxmap->bytes());
|
||||
Logger() << BeginWriteOperationLogMessage() << "erasing";
|
||||
fluxmap.reset(new Fluxmap());
|
||||
fluxSink.writeFlux(cylinder, head, *fluxmap);
|
||||
Logger() << EndWriteOperationLogMessage();
|
||||
}
|
||||
else
|
||||
{
|
||||
fluxmap->rescale(config.flux_sink().rescale());
|
||||
std::sort(
|
||||
sectors.begin(), sectors.end(), sectorPointerSortPredicate);
|
||||
|
||||
std::cout << fmt::format(" Verify: ", cylinder, head) << std::flush;
|
||||
std::shared_ptr<Fluxmap> writtenFluxmap = fluxSource.readFlux(cylinder, head);
|
||||
std::cout << fmt::format(
|
||||
"{0} ms in {1} bytes\n", int(writtenFluxmap->duration()/1e6), writtenFluxmap->bytes());
|
||||
const auto trackdata = decoder.decodeToSectors(writtenFluxmap, cylinder, head);
|
||||
for (int retry = 0;; retry++)
|
||||
{
|
||||
/* Precompensation actually seems to make things worse, so
|
||||
* let's leave it disabled for now. */
|
||||
// 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;
|
||||
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());
|
||||
Logger() << "verifying" << BeginReadOperationLogMessage();
|
||||
std::shared_ptr<Fluxmap> writtenFluxmap =
|
||||
fluxSource.readFlux(cylinder, head);
|
||||
Logger() << EndReadOperationLogMessage()
|
||||
<< fmt::format("{0} ms in {1} bytes",
|
||||
int(writtenFluxmap->duration() / 1e6),
|
||||
writtenFluxmap->bytes());
|
||||
|
||||
if (std::equal(gotSectors.begin(), gotSectors.end(), sectors.begin(), sectors.end(),
|
||||
sectorPointerEqualsPredicate))
|
||||
break;
|
||||
const auto trackdata =
|
||||
decoder.decodeToSectors(writtenFluxmap, cylinder, head);
|
||||
|
||||
if (retry == config.decoder().retries())
|
||||
Error() << "Write failed; uncorrectable error during write.";
|
||||
std::vector<std::shared_ptr<Sector>> gotSectors =
|
||||
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,
|
||||
unsigned& cursor, unsigned terminateAt,
|
||||
const std::vector<bool>& pattern)
|
||||
unsigned& cursor,
|
||||
unsigned terminateAt,
|
||||
const std::vector<bool>& pattern)
|
||||
{
|
||||
while (cursor < terminateAt)
|
||||
{
|
||||
for (bool b : pattern)
|
||||
{
|
||||
if (cursor < bitmap.size())
|
||||
bitmap[cursor++] = b;
|
||||
}
|
||||
}
|
||||
while (cursor < terminateAt)
|
||||
{
|
||||
for (bool b : pattern)
|
||||
{
|
||||
if (cursor < bitmap.size())
|
||||
bitmap[cursor++] = b;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void writeDiskCommand(const Image& image, AbstractEncoder& encoder, FluxSink& fluxSink,
|
||||
AbstractDecoder* decoder, FluxSource* fluxSource)
|
||||
void writeDiskCommand(const Image& image,
|
||||
AbstractEncoder& encoder,
|
||||
FluxSink& fluxSink,
|
||||
AbstractDecoder* decoder,
|
||||
FluxSource* fluxSource)
|
||||
{
|
||||
if (fluxSource && decoder)
|
||||
writeTracksAndVerify(fluxSink, encoder, *fluxSource, *decoder, image);
|
||||
else
|
||||
writeTracks(fluxSink,
|
||||
[&](int physicalTrack, int physicalSide) -> std::unique_ptr<Fluxmap>
|
||||
{
|
||||
const auto& sectors = encoder.collectSectors(physicalTrack, physicalSide, image);
|
||||
return encoder.encode(physicalTrack, physicalSide, sectors, image);
|
||||
}
|
||||
);
|
||||
if (fluxSource && decoder)
|
||||
writeTracksAndVerify(fluxSink, encoder, *fluxSource, *decoder, image);
|
||||
else
|
||||
writeTracks(fluxSink,
|
||||
[&](int physicalTrack, int physicalSide) -> std::unique_ptr<Fluxmap>
|
||||
{
|
||||
const auto& sectors =
|
||||
encoder.collectSectors(physicalTrack, physicalSide, image);
|
||||
return encoder.encode(
|
||||
physicalTrack, physicalSide, sectors, image);
|
||||
});
|
||||
}
|
||||
|
||||
void writeRawDiskCommand(FluxSource& fluxSource, FluxSink& fluxSink)
|
||||
{
|
||||
writeTracks(fluxSink,
|
||||
[&](int track, int side) -> std::unique_ptr<Fluxmap>
|
||||
{
|
||||
return fluxSource.readFlux(track, side);
|
||||
}
|
||||
);
|
||||
writeTracks(fluxSink,
|
||||
[&](int track, int side) -> std::unique_ptr<Fluxmap>
|
||||
{
|
||||
return fluxSource.readFlux(track, side);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -472,6 +472,7 @@ buildlibrary libbackend.a \
|
||||
lib/imagewriter/rawimagewriter.cc \
|
||||
lib/imginputoutpututils.cc \
|
||||
lib/ldbs.cc \
|
||||
lib/logger.cc \
|
||||
lib/proto.cc \
|
||||
lib/reader.cc \
|
||||
lib/sector.cc \
|
||||
|
||||
Reference in New Issue
Block a user