From be41c1de76f67b172781943f8ed35808e034f37f Mon Sep 17 00:00:00 2001 From: David Given Date: Sat, 8 Feb 2020 12:41:50 +0100 Subject: [PATCH] You now need to explicitly specify whether flux files get merged or overwritten, because the old behaviour was weird. Reader uses SqliteFluxSink to write flux files, rather than raw database accesses. --- doc/using.md | 10 +++++----- lib/flags.h | 2 +- lib/fluxsink/fluxsink.h | 3 +-- lib/fluxsink/sqlitefluxsink.cc | 23 +++++++++++++++++++++++ lib/reader.cc | 26 ++++++++++++-------------- 5 files changed, 42 insertions(+), 22 deletions(-) diff --git a/doc/using.md b/doc/using.md index e974b351..62685066 100644 --- a/doc/using.md +++ b/doc/using.md @@ -300,13 +300,13 @@ containing valuable historical data, and you want to read them. Typically I do this: ``` -$ fluxengine read brother -s :d=0 -o brother.img --write-flux=brother.flux --write-svg=brother.svg +$ fluxengine read brother -s :d=0 -o brother.img --write-flux=brother.flux --overwrite --write-svg=brother.svg ``` -This will read the disk in drive 0 and write out a filesystem image. It'll -also copy the flux to brother.flux and write out an SVG visualisation. If I -then need to tweak the settings, I can rerun the decode without having to -physically touch the disk like this: +This will read the disk in drive 0 and write out a filesystem image. It'll also +copy the flux to `brother.flux` (replacing any old one) and write out an SVG +visualisation. If I then need to tweak the settings, I can rerun the decode +without having to physically touch the disk like this: ``` $ fluxengine read brother -s brother.flux -o brother.img --write-svg=brother.svg diff --git a/lib/flags.h b/lib/flags.h index df584e72..5becb74c 100644 --- a/lib/flags.h +++ b/lib/flags.h @@ -147,7 +147,7 @@ public: void set(const std::string& value) { _value = std::stod(value); } }; -class BoolFlag : public ValueFlag +class BoolFlag : public ValueFlag { public: BoolFlag(const std::vector& names, const std::string helptext, diff --git a/lib/fluxsink/fluxsink.h b/lib/fluxsink/fluxsink.h index b09c86fa..b42bc3d3 100644 --- a/lib/fluxsink/fluxsink.h +++ b/lib/fluxsink/fluxsink.h @@ -4,6 +4,7 @@ #include "flags.h" extern FlagGroup hardwareFluxSinkFlags; +extern FlagGroup sqliteFluxSinkFlags; class Fluxmap; class FluxSpec; @@ -13,11 +14,9 @@ class FluxSink public: virtual ~FluxSink() {} -private: static std::unique_ptr createSqliteFluxSink(const std::string& filename); static std::unique_ptr createHardwareFluxSink(unsigned drive); -public: static std::unique_ptr create(const FluxSpec& spec); public: diff --git a/lib/fluxsink/sqlitefluxsink.cc b/lib/fluxsink/sqlitefluxsink.cc index c0296234..da39b70f 100644 --- a/lib/fluxsink/sqlitefluxsink.cc +++ b/lib/fluxsink/sqlitefluxsink.cc @@ -2,14 +2,37 @@ #include "fluxmap.h" #include "sql.h" #include "fluxsink/fluxsink.h" +#include "flags.h" #include "fmt/format.h" +#include + +FlagGroup sqliteFluxSinkFlags; + +static SettableFlag mergeFlag( + { "--merge" }, + "merge new data into existing flux file"); + +static SettableFlag overwriteFlag( + { "--overwrite" }, + "overwrite existing flux file"); class SqliteFluxSink : public FluxSink { public: SqliteFluxSink(const std::string& filename) { + if (mergeFlag && overwriteFlag) + Error() << "you can't specify --merge and --overwrite"; + + if (!mergeFlag) + { + if (!overwriteFlag && (access(filename.c_str(), F_OK) == 0)) + Error() << "cowardly refusing to overwrite flux file without --merge or --overwrite specified"; + if (remove(filename.c_str()) != 0) + Error() << fmt::format("failed to overwrite flux file"); + } _outdb = sqlOpen(filename, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE); + int oldVersion = sqlReadIntProperty(_outdb, "version"); if ((oldVersion != 0) && (oldVersion != FLUX_VERSION_CURRENT)) Error() << fmt::format("that flux file is version {}, but this client is for version {}", diff --git a/lib/reader.cc b/lib/reader.cc index 159d48b2..da0139fc 100644 --- a/lib/reader.cc +++ b/lib/reader.cc @@ -2,6 +2,7 @@ #include "flags.h" #include "usb.h" #include "fluxsource/fluxsource.h" +#include "fluxsink/fluxsink.h" #include "reader.h" #include "fluxmap.h" #include "sql.h" @@ -18,7 +19,13 @@ #include "imagewriter/imagewriter.h" #include "fmt/format.h" -FlagGroup readerFlags { &hardwareFluxSourceFlags, &fluxmapReaderFlags, &visualiserFlags }; +FlagGroup readerFlags +{ + &hardwareFluxSourceFlags, + &sqliteFluxSinkFlags, + &fluxmapReaderFlags, + &visualiserFlags +}; static DataSpecFlag source( { "--source", "-s" }, @@ -61,7 +68,7 @@ static SettableFlag highDensityFlag( { "--high-density", "--hd" }, "set the drive to high density mode"); -static sqlite3* outdb; +static std::unique_ptr outputFluxSink; void setReaderDefaultSource(const std::string& source) { @@ -86,8 +93,8 @@ void Track::readFluxmap() "{0} ms in {1} bytes\n", int(fluxmap->duration()/1e6), fluxmap->bytes()); - if (outdb) - sqlWriteFlux(outdb, physicalTrack, physicalSide, *fluxmap); + if (outputFluxSink) + outputFluxSink->writeFlux(physicalTrack, physicalSide, *fluxmap); } std::vector> readTracks() @@ -100,17 +107,8 @@ std::vector> readTracks() if (!destination.get().empty()) { - outdb = sqlOpen(destination, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE); std::cout << "Writing a copy of the flux to " << destination.get() << std::endl; - sqlPrepareFlux(outdb); - sqlStmt(outdb, "BEGIN;"); - sqlWriteIntProperty(outdb, "version", FLUX_VERSION_CURRENT); - atexit([]() - { - sqlStmt(outdb, "COMMIT;"); - sqlClose(outdb); - } - ); + outputFluxSink = FluxSink::createSqliteFluxSink(destination.get()); } std::shared_ptr fluxSource = FluxSource::create(spec);