~aleteoryx/muditaos

ref: 6b66737b13adf25c32cdae957524f522cd289403 muditaos/module-db/Database/DatabaseInitializer.cpp -rw-r--r-- 3.0 KiB
6b66737b — RobertPiet [EGD-4354] settings starting script moved to two separated scripts (#1067) 5 years ago
                                                                                
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
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "DatabaseInitializer.hpp"

#include <vfs.hpp>
#include <memory>
#include <set>

DatabaseInitializer::DatabaseInitializer(Database *db) : db(db)
{}

bool DatabaseInitializer::run(fs::path path, std::string ext)
{
    // Database name is database file path, need to strip off all filesystem related stuff(path, extension)
    fs::path dbpath    = db->getName();
    std::string dbname = dbpath.filename().replace_extension();

    auto files = listFiles(path, dbname, ext);
    for (auto file : files) {
        LOG_DEBUG("Runing db script: %s", file.c_str());
        auto commands = readCommands(file);
        if (!executeOnDb(commands)) {
            LOG_ERROR("Can't initialize database [%s] with [%s]", db->getName().c_str(), file.c_str());
            return false;
        }
    }
    return true;
}

std::vector<std::string> DatabaseInitializer::readCommands(fs::path filePath)
{
    ScopedFile file(filePath, "r");

    std::string line;
    std::string currentStatement;
    std::vector<std::string> statements;

    while (!vfs.eof(file.get())) {
        line = vfs.getline(file.get());

        if (line.empty() || starts_with(line, std::string("--"))) {
            continue;
        }

        if (ends_with(line, std::string(";"))) {
            statements.push_back(currentStatement + line);
            currentStatement.clear();
            continue;
        }

        currentStatement += line;
    }

    return statements;
}

std::array<std::string, 3> DatabaseInitializer::splitFilename(std::string filename)
{
    auto name    = filename.substr(0, filename.find("."));
    auto prefix  = name.substr(0, name.find_last_of("_"));
    auto postfix = name.substr(name.find_last_of("_") + 1, std::string::npos);

    return {name, prefix, postfix};
}

std::vector<fs::path> DatabaseInitializer::listFiles(fs::path path, std::string prefix, std::string ext)
{
    std::set<std::pair<int, fs::path>> orderedFiles;
    auto dirList = vfs.listdir(path.c_str(), ext);
    for (vfs::DirectoryEntry ent : dirList) {
        if (ent.attributes != vfs::FileAttributes::Directory) {
            try {
                auto parts      = splitFilename(ent.fileName);
                auto filePrefix = parts[1];
                if (filePrefix == prefix) {
                    auto num = std::stoi(parts[2]);
                    orderedFiles.insert({num, path / ent.fileName});
                }
            }
            catch (std::invalid_argument &e) {
                LOG_INFO("Ignoring file: %s", ent.fileName.c_str());
            }
        }
    }

    std::vector<fs::path> files;
    std::for_each(orderedFiles.begin(), orderedFiles.end(), [&](auto item) { files.push_back(item.second); });
    return files;
}

bool DatabaseInitializer::executeOnDb(const std::vector<std::string> statements)
{
    for (auto st : statements) {
        if (!db->execute(st.c_str())) {
            return false;
        }
    }
    return true;
}