• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

mendersoftware / mender / 1022567176

02 Oct 2023 07:50AM UTC coverage: 80.127% (+2.5%) from 77.645%
1022567176

push

gitlab-ci

kacf
chore: Centralize selection of `std::filesystem` library.

Signed-off-by: Kristian Amlie <kristian.amlie@northern.tech>

6447 of 8046 relevant lines covered (80.13%)

9912.21 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

84.21
/common/key_value_database/platform/lmdb/lmdb.cpp
1
// Copyright 2023 Northern.tech AS
2
//
3
//    Licensed under the Apache License, Version 2.0 (the "License");
4
//    you may not use this file except in compliance with the License.
5
//    You may obtain a copy of the License at
6
//
7
//        http://www.apache.org/licenses/LICENSE-2.0
8
//
9
//    Unless required by applicable law or agreed to in writing, software
10
//    distributed under the License is distributed on an "AS IS" BASIS,
11
//    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
//    See the License for the specific language governing permissions and
13
//    limitations under the License.
14

15
#include <common/common.hpp>
16
#include <common/key_value_database_lmdb.hpp>
17

18
#include <lmdb++.h>
19

20
namespace mender {
21
namespace common {
22
namespace key_value_database {
23

24
class LmdbTransaction : public Transaction {
2,028✔
25
public:
26
        LmdbTransaction(lmdb::txn &txn, lmdb::dbi &dbi);
27

28
        expected::ExpectedBytes Read(const string &key) override;
29
        error::Error Write(const string &key, const vector<uint8_t> &value) override;
30
        error::Error Remove(const string &key) override;
31

32
private:
33
        lmdb::txn &txn_;
34
        lmdb::dbi &dbi_;
35
};
36

37
LmdbTransaction::LmdbTransaction(lmdb::txn &txn, lmdb::dbi &dbi) :
2,028✔
38
        txn_ {txn},
39
        dbi_ {dbi} {
2,028✔
40
}
×
41

42
expected::ExpectedBytes LmdbTransaction::Read(const string &key) {
1,300✔
43
        try {
44
                std::string_view value;
1,300✔
45
                bool exists = dbi_.get(txn_, key, value);
1,300✔
46
                if (!exists) {
1,300✔
47
                        return expected::unexpected(
770✔
48
                                MakeError(KeyError, "Key " + key + " not found in database"));
2,310✔
49
                }
50

51
                return common::ByteVectorFromString(value);
1,060✔
52
        } catch (std::runtime_error &e) {
×
53
                return expected::unexpected(MakeError(LmdbError, e.what()));
×
54
        }
55
}
56

57
error::Error LmdbTransaction::Write(const string &key, const vector<uint8_t> &value) {
995✔
58
        try {
59
                string_view data(reinterpret_cast<const char *>(value.data()), value.size());
60
                bool exists = dbi_.put(txn_, key, data);
995✔
61
                if (!exists) {
995✔
62
                        return MakeError(AlreadyExistsError, "Key " + key + " already exists");
×
63
                }
64

65
                return error::NoError;
995✔
66
        } catch (std::runtime_error &e) {
×
67
                return MakeError(LmdbError, e.what());
×
68
        }
69
}
70

71
error::Error LmdbTransaction::Remove(const string &key) {
1,500✔
72
        try {
73
                // We don't treat !exists as an error, just ignore return code.
74
                dbi_.del(txn_, key);
1,500✔
75

76
                return error::NoError;
1,500✔
77
        } catch (std::runtime_error &e) {
×
78
                return MakeError(LmdbError, e.what());
×
79
        }
80
}
81

82
KeyValueDatabaseLmdb::KeyValueDatabaseLmdb() :
380✔
83
        env_ {make_unique<lmdb::env>(lmdb::env::create())},
760✔
84
        successfully_opened_ {false} {
760✔
85
}
380✔
86

87
KeyValueDatabaseLmdb::~KeyValueDatabaseLmdb() {
760✔
88
        Close();
380✔
89
}
380✔
90

91
error::Error KeyValueDatabaseLmdb::Open(const string &path) {
353✔
92
        Close();
353✔
93

94
        try {
95
                env_->open(path.c_str(), MDB_NOSUBDIR, 0600);
353✔
96
        } catch (std::runtime_error &e) {
4✔
97
                return MakeError(LmdbError, e.what());
4✔
98
        }
99

100
        successfully_opened_ = true;
351✔
101
        return error::NoError;
351✔
102
}
103

104
void KeyValueDatabaseLmdb::Close() {
734✔
105
        if (!successfully_opened_) {
734✔
106
                return;
107
        }
108

109
        env_->close();
351✔
110
        successfully_opened_ = false;
351✔
111
}
112

113
expected::ExpectedBytes KeyValueDatabaseLmdb::Read(const string &key) {
131✔
114
        vector<uint8_t> ret;
115
        auto err = ReadTransaction([&key, &ret](Transaction &txn) -> error::Error {
176✔
116
                auto result = txn.Read(key);
131✔
117
                if (result) {
131✔
118
                        ret = std::move(result.value());
45✔
119
                        return error::NoError;
45✔
120
                } else {
121
                        return result.error();
86✔
122
                }
123
        });
131✔
124
        if (mender::common::error::NoError != err) {
131✔
125
                return expected::unexpected(err);
172✔
126
        } else {
127
                return ret;
45✔
128
        }
129
}
130

131
error::Error KeyValueDatabaseLmdb::Write(const string &key, const vector<uint8_t> &value) {
203✔
132
        return WriteTransaction(
133
                [&key, &value](Transaction &txn) -> error::Error { return txn.Write(key, value); });
609✔
134
}
135

136
error::Error KeyValueDatabaseLmdb::Remove(const string &key) {
593✔
137
        return WriteTransaction([&key](Transaction &txn) -> error::Error { return txn.Remove(key); });
1,779✔
138
}
139

140
error::Error KeyValueDatabaseLmdb::WriteTransaction(function<error::Error(Transaction &)> txnFunc) {
1,615✔
141
        AssertOrReturnError(successfully_opened_);
1,615✔
142

143
        try {
144
                lmdb::txn lmdb_txn = lmdb::txn::begin(*env_, nullptr, 0);
3,230✔
145
                lmdb::dbi lmdb_dbi = lmdb::dbi::open(lmdb_txn, nullptr, 0);
1,615✔
146
                LmdbTransaction txn(lmdb_txn, lmdb_dbi);
147
                auto error = txnFunc(txn);
1,615✔
148
                if (error::NoError != error) {
1,615✔
149
                        lmdb_txn.abort();
55✔
150
                } else {
151
                        lmdb_txn.commit();
1,560✔
152
                }
153
                return error;
1,615✔
154
        } catch (std::runtime_error &e) {
×
155
                return MakeError(LmdbError, e.what());
×
156
        }
157
}
158

159
error::Error KeyValueDatabaseLmdb::ReadTransaction(function<error::Error(Transaction &)> txnFunc) {
414✔
160
        AssertOrReturnError(successfully_opened_);
415✔
161

162
        try {
163
                lmdb::txn lmdb_txn = lmdb::txn::begin(*env_, nullptr, MDB_RDONLY);
826✔
164
                lmdb::dbi lmdb_dbi = lmdb::dbi::open(lmdb_txn, nullptr, 0);
413✔
165
                LmdbTransaction txn(lmdb_txn, lmdb_dbi);
166
                return txnFunc(txn);
413✔
167
        } catch (std::runtime_error &e) {
×
168
                return MakeError(LmdbError, e.what());
×
169
        }
170
}
171

172
} // namespace key_value_database
173
} // namespace common
174
} // namespace mender
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc