diff --git a/src/cmd_compact.cpp b/src/cmd_compact.cpp index 7d009d9..ebcb6bf 100644 --- a/src/cmd_compact.cpp +++ b/src/cmd_compact.cpp @@ -10,30 +10,23 @@ static const char USAGE[] = R"( Usage: - compact export - compact quad-gc + compact )"; void cmd_compact(const std::vector &subArgs) { std::map args = docopt::docopt(USAGE, subArgs, true, ""); - if (args["export"].asBool()) { - std::string outputFile = args[""].asString(); + std::string outputFile = args[""].asString(); - if (outputFile == "-") { - env.copy_fd(1); - } else { - if (access(outputFile.c_str(), F_OK) == 0) throw herr("output file '", outputFile, "' exists, not overwriting"); + if (outputFile == "-") { + env.copy_fd(1); + } else { + if (access(outputFile.c_str(), F_OK) == 0) throw herr("output file '", outputFile, "' exists, not overwriting"); - auto *f = ::fopen(outputFile.c_str(), "w"); - if (!f) throw herr("opening output file '", outputFile, "' failed: ", strerror(errno)); + auto *f = ::fopen(outputFile.c_str(), "w"); + if (!f) throw herr("opening output file '", outputFile, "' failed: ", strerror(errno)); - env.copy_fd(::fileno(f)); - } - } else if (args["quad-gc"].asBool()) { - auto qdb = getQdbInstance(); - - quadrableGarbageCollect(qdb, 2); + env.copy_fd(::fileno(f)); } } diff --git a/src/cmd_delete.cpp b/src/cmd_delete.cpp new file mode 100644 index 0000000..ffb3a29 --- /dev/null +++ b/src/cmd_delete.cpp @@ -0,0 +1,93 @@ +#include + +#include +#include "golpe.h" + +#include "DBScan.h" +#include "events.h" +#include "gc.h" + + +static const char USAGE[] = +R"( + Usage: + delete [--age=] [--filter=] [--dry-run] [--no-gc] +)"; + + +void cmd_delete(const std::vector &subArgs) { + std::map args = docopt::docopt(USAGE, subArgs, true, ""); + + uint64_t age = MAX_U64; + if (args["--age"]) age = args["--age"].asLong(); + + std::string filterStr; + if (args["--filter"]) filterStr = args["--filter"].asString(); + + bool dryRun = args["--dry-run"].asBool(); + bool noGc = args["--no-gc"].asBool(); + + + + if (filterStr.size() == 0 && age == MAX_U64) throw herr("must specify --age and/or --filter"); + if (filterStr.size() == 0) filterStr = "{}"; + + + auto filter = tao::json::from_string(filterStr); + auto now = hoytech::curr_time_s(); + + if (age != MAX_U64) { + if (age > now) age = now; + if (filter.optional("until")) throw herr("--age is not compatible with filter containing 'until'"); + + filter["until"] = now - age; + } + + + auto filterGroup = NostrFilterGroup::unwrapped(filter, MAX_U64); + Subscription sub(1, "junkSub", filterGroup); + DBScanQuery query(sub); + + + btree_set levIds; + + { + auto txn = env.txn_ro(); + + while (1) { + bool complete = query.process(txn, MAX_U64, false, [&](const auto &sub, uint64_t levId){ + levIds.insert(levId); + }); + + if (complete) break; + } + } + + if (dryRun) { + LI << "Would delete " << levIds.size() << " events"; + return; + } + + + auto qdb = getQdbInstance(); + + LI << "Deleting " << levIds.size() << " events"; + + { + auto txn = env.txn_rw(); + + auto changes = qdb.change(); + + for (auto levId : levIds) { + auto view = env.lookup_Event(txn, levId); + if (!view) continue; // Deleted in between transactions + deleteEvent(txn, changes, *view); + } + + changes.apply(txn); + + txn.commit(); + } + + if (!noGc) quadrableGarbageCollect(qdb, 2); +} diff --git a/src/cmd_gc.cpp b/src/cmd_gc.cpp new file mode 100644 index 0000000..ca40ed1 --- /dev/null +++ b/src/cmd_gc.cpp @@ -0,0 +1,22 @@ +#include +#include + +#include +#include "golpe.h" + +#include "gc.h" + + +static const char USAGE[] = +R"( + Usage: + gc +)"; + + +void cmd_gc(const std::vector &subArgs) { + std::map args = docopt::docopt(USAGE, subArgs, true, ""); + + auto qdb = getQdbInstance(); + quadrableGarbageCollect(qdb, 2); +} diff --git a/src/cmd_scan.cpp b/src/cmd_scan.cpp index b533ac4..73786f3 100644 --- a/src/cmd_scan.cpp +++ b/src/cmd_scan.cpp @@ -20,8 +20,7 @@ void cmd_scan(const std::vector &subArgs) { uint64_t pause = 0; if (args["--pause"]) pause = args["--pause"].asLong(); - bool metrics = false; - if (args["--metrics"]) metrics = true; + bool metrics = args["--metrics"].asBool(); std::string filterStr = args[""].asString();