Веб-сайт самохостера Lotigara

summaryrefslogtreecommitdiff
path: root/source/utility/btree_repacker.cpp
blob: d711a646986272d74e66b0ea03fb202cc59b91f3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
#include "StarBTreeDatabase.hpp"
#include "StarTime.hpp"
#include "StarFile.hpp"
#include "StarVersionOptionParser.hpp"

using namespace Star;

int main(int argc, char** argv) {
  try {
    double startTime = Time::monotonicTime();

    VersionOptionParser optParse;
    optParse.setSummary("Repacks a Starbound BTree file to shrink its file size");
    optParse.addArgument("input file path", OptionParser::Required, "Path to the BTree to be repacked");
    optParse.addArgument("output filename", OptionParser::Optional, "Output BTree file");

    auto opts = optParse.commandParseOrDie(argc, argv);

    String bTreePath = opts.arguments.at(0);
    String outputFilename = opts.arguments.get(1, bTreePath + ".repack");

    outputFilename = File::relativeTo(File::fullPath(File::dirName(outputFilename)), File::baseName(outputFilename));
    //open the old db
    BTreeDatabase db;
    db.setIODevice(File::open(bTreePath, IOMode::Read));
    db.open();

    //make a new db
    BTreeDatabase newDb;
    newDb.setBlockSize(db.blockSize());
    newDb.setContentIdentifier(db.contentIdentifier());
    newDb.setKeySize(db.keySize());
    newDb.setAutoCommit(false);

    newDb.setIODevice(File::open(outputFilename, IOMode::ReadWrite | IOMode::Truncate));
    newDb.open();
    coutf("Repacking {}...\n", bTreePath);
    //copy the data over
    unsigned count = 0, overwritten = 0;
    auto visitor = [&](ByteArray key, ByteArray data) {
      if (newDb.insert(key, data))
        ++overwritten;
      ++count;
    };
    auto errorHandler = [&](String const& error, std::exception const& e) {
      coutf("{}: {}\n", error, e.what());
    };
    db.recoverAll(visitor, errorHandler);

    //close the old db
    db.close();
    //commit and close the new db
    newDb.commit();
    newDb.close();

    coutf("Repacked BTree to {} in {:.6f}s\n({} inserts, {} overwritten)\n", outputFilename, Time::monotonicTime() - startTime, count, overwritten);
    return 0;

  } catch (std::exception const& e) {
    cerrf("Exception caught: {}\n", outputException(e, true));
    return 1;
  }
}