mirror of
				https://github.com/davidgiven/fluxengine.git
				synced 2025-10-24 11:11:02 -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