rippled
Loading...
Searching...
No Matches
PeerFinder.cpp
1//------------------------------------------------------------------------------
2/*
3 This file is part of rippled: https://github.com/ripple/rippled
4 Copyright (c) 2021 Ripple Labs Inc.
5
6 Permission to use, copy, modify, and/or distribute this software for any
7 purpose with or without fee is hereby granted, provided that the above
8 copyright notice and this permission notice appear in all copies.
9
10 THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17*/
18//==============================================================================
19
20#include <xrpld/app/rdb/PeerFinder.h>
21
22namespace ripple {
23
24void
26 soci::session& session,
27 BasicConfig const& config,
29{
30 DBConfig m_sociConfig(config, "peerfinder");
31 m_sociConfig.open(session);
32
33 JLOG(j.info()) << "Opening database at '" << m_sociConfig.connectionString()
34 << "'";
35
36 soci::transaction tr(session);
37 session << "PRAGMA encoding=\"UTF-8\";";
38
39 session << "CREATE TABLE IF NOT EXISTS SchemaVersion ( "
40 " name TEXT PRIMARY KEY, "
41 " version INTEGER"
42 ");";
43
44 session << "CREATE TABLE IF NOT EXISTS PeerFinder_BootstrapCache ( "
45 " id INTEGER PRIMARY KEY AUTOINCREMENT, "
46 " address TEXT UNIQUE NOT NULL, "
47 " valence INTEGER"
48 ");";
49
50 session << "CREATE INDEX IF NOT EXISTS "
51 " PeerFinder_BootstrapCache_Index ON "
52 "PeerFinder_BootstrapCache "
53 " ( "
54 " address "
55 " ); ";
56
57 tr.commit();
58}
59
60void
62 soci::session& session,
63 int currentSchemaVersion,
65{
66 soci::transaction tr(session);
67 // get version
68 int version(0);
69 {
70 // SOCI requires a boost::optional (not std::optional) parameter.
71 boost::optional<int> vO;
72 session << "SELECT "
73 " version "
74 "FROM SchemaVersion WHERE "
75 " name = 'PeerFinder';",
76 soci::into(vO);
77
78 version = vO.value_or(0);
79
80 JLOG(j.info()) << "Opened version " << version << " database";
81 }
82
83 {
84 if (version < currentSchemaVersion)
85 {
86 JLOG(j.info()) << "Updating database to version "
87 << currentSchemaVersion;
88 }
89 else if (version > currentSchemaVersion)
90 {
91 Throw<std::runtime_error>(
92 "The PeerFinder database version is higher than expected");
93 }
94 }
95
96 if (version < 4)
97 {
98 //
99 // Remove the "uptime" column from the bootstrap table
100 //
101
102 session << "CREATE TABLE IF NOT EXISTS "
103 "PeerFinder_BootstrapCache_Next ( "
104 " id INTEGER PRIMARY KEY AUTOINCREMENT, "
105 " address TEXT UNIQUE NOT NULL, "
106 " valence INTEGER"
107 ");";
108
109 session << "CREATE INDEX IF NOT EXISTS "
110 " PeerFinder_BootstrapCache_Next_Index ON "
111 " PeerFinder_BootstrapCache_Next "
112 " ( address ); ";
113
114 std::size_t count;
115 session << "SELECT COUNT(*) FROM PeerFinder_BootstrapCache;",
116 soci::into(count);
117
119
120 {
121 list.reserve(count);
122 std::string s;
123 int valence;
124 soci::statement st =
125 (session.prepare << "SELECT "
126 " address, "
127 " valence "
128 "FROM PeerFinder_BootstrapCache;",
129 soci::into(s),
130 soci::into(valence));
131
132 st.execute();
133 while (st.fetch())
134 {
136 entry.endpoint = beast::IP::Endpoint::from_string(s);
137 if (!is_unspecified(entry.endpoint))
138 {
139 entry.valence = valence;
140 list.push_back(entry);
141 }
142 else
143 {
144 JLOG(j.error()) << "Bad address string '" << s
145 << "' in Bootcache table";
146 }
147 }
148 }
149
150 if (!list.empty())
151 {
153 std::vector<int> valence;
154 s.reserve(list.size());
155 valence.reserve(list.size());
156
157 for (auto iter(list.cbegin()); iter != list.cend(); ++iter)
158 {
159 s.emplace_back(to_string(iter->endpoint));
160 valence.emplace_back(iter->valence);
161 }
162
163 session << "INSERT INTO PeerFinder_BootstrapCache_Next ( "
164 " address, "
165 " valence "
166 ") VALUES ( "
167 " :s, :valence"
168 ");",
169 soci::use(s), soci::use(valence);
170 }
171
172 session << "DROP TABLE IF EXISTS PeerFinder_BootstrapCache;";
173
174 session << "DROP INDEX IF EXISTS PeerFinder_BootstrapCache_Index;";
175
176 session << "ALTER TABLE PeerFinder_BootstrapCache_Next "
177 " RENAME TO PeerFinder_BootstrapCache;";
178
179 session << "CREATE INDEX IF NOT EXISTS "
180 " PeerFinder_BootstrapCache_Index ON "
181 "PeerFinder_BootstrapCache "
182 " ( "
183 " address "
184 " ); ";
185 }
186
187 if (version < 3)
188 {
189 //
190 // Remove legacy endpoints from the schema
191 //
192
193 session << "DROP TABLE IF EXISTS LegacyEndpoints;";
194
195 session << "DROP TABLE IF EXISTS PeerFinderLegacyEndpoints;";
196
197 session << "DROP TABLE IF EXISTS PeerFinder_LegacyEndpoints;";
198
199 session << "DROP TABLE IF EXISTS PeerFinder_LegacyEndpoints_Index;";
200 }
201
202 {
203 int const v(currentSchemaVersion);
204 session << "INSERT OR REPLACE INTO SchemaVersion ("
205 " name "
206 " ,version "
207 ") VALUES ( "
208 " 'PeerFinder', :version "
209 ");",
210 soci::use(v);
211 }
212
213 tr.commit();
214}
215
216void
218 soci::session& session,
219 std::function<void(std::string const&, int)> const& func)
220{
221 std::string s;
222 int valence;
223 soci::statement st =
224 (session.prepare << "SELECT "
225 " address, "
226 " valence "
227 "FROM PeerFinder_BootstrapCache;",
228 soci::into(s),
229 soci::into(valence));
230
231 st.execute();
232 while (st.fetch())
233 {
234 func(s, valence);
235 }
236}
237
238void
240 soci::session& session,
242{
243 soci::transaction tr(session);
244 session << "DELETE FROM PeerFinder_BootstrapCache;";
245
246 if (!v.empty())
247 {
249 std::vector<int> valence;
250 s.reserve(v.size());
251 valence.reserve(v.size());
252
253 for (auto const& e : v)
254 {
255 s.emplace_back(to_string(e.endpoint));
256 valence.emplace_back(e.valence);
257 }
258
259 session << "INSERT INTO PeerFinder_BootstrapCache ( "
260 " address, "
261 " valence "
262 ") VALUES ( "
263 " :s, :valence "
264 ");",
265 soci::use(s), soci::use(valence);
266 }
267
268 tr.commit();
269}
270
271} // namespace ripple
T cbegin(T... args)
static Endpoint from_string(std::string const &s)
A generic endpoint for log messages.
Definition Journal.h:60
Stream error() const
Definition Journal.h:346
Stream info() const
Definition Journal.h:334
Holds unparsed configuration information.
DBConfig is used when a client wants to delay opening a soci::session after parsing the config parame...
Definition SociDB.h:61
void open(soci::session &s) const
Definition SociDB.cpp:95
std::string connectionString() const
Definition SociDB.cpp:89
T emplace_back(T... args)
T empty(T... args)
T cend(T... args)
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:25
void readPeerFinderDB(soci::session &session, std::function< void(std::string const &, int)> const &func)
readPeerFinderDB Reads all entries from the peer finder database and invokes the given callback for e...
void updatePeerFinderDB(soci::session &session, int currentSchemaVersion, beast::Journal j)
updatePeerFinderDB Updates the peer finder database to a new version.
std::string to_string(base_uint< Bits, Tag > const &a)
Definition base_uint.h:630
void initPeerFinderDB(soci::session &session, BasicConfig const &config, beast::Journal j)
initPeerFinderDB Opens a session with the peer finder database.
void savePeerFinderDB(soci::session &session, std::vector< PeerFinder::Store::Entry > const &v)
savePeerFinderDB Saves a new entry to the peer finder database.
T push_back(T... args)
T reserve(T... args)
T size(T... args)