Skip to content

Commit 442a083

Browse files
committed
SOCI private API usage workaround
Signed-off-by: Andrei Lebedev <lebdron@gmail.com>
1 parent 8be0b69 commit 442a083

File tree

2 files changed

+158
-66
lines changed

2 files changed

+158
-66
lines changed

irohad/ametsuchi/impl/storage_impl.cpp

Lines changed: 99 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -117,8 +117,98 @@ namespace iroha {
117117
auto *pg_connection =
118118
static_cast<soci::postgresql_session_backend *>(
119119
connection_.get_backend());
120-
pg_connection->clean_up();
121-
pg_connection->connect(parameters);
120+
auto &conn_ = pg_connection->conn_;
121+
122+
auto clean_up = [](auto &conn_) {
123+
if (0 != conn_) {
124+
PQfinish(conn_);
125+
conn_ = 0;
126+
}
127+
};
128+
129+
auto check_for_data =
130+
[](auto &sessionBackend_, auto *result_, auto *errMsg) {
131+
std::string msg(errMsg);
132+
133+
ExecStatusType const status = PQresultStatus(result_);
134+
switch (status) {
135+
case PGRES_EMPTY_QUERY:
136+
case PGRES_COMMAND_OK:
137+
// No data but don't throw neither.
138+
return false;
139+
140+
case PGRES_TUPLES_OK:
141+
return true;
142+
143+
case PGRES_FATAL_ERROR:
144+
msg += " Fatal error.";
145+
146+
if (PQstatus(sessionBackend_.conn_) == CONNECTION_BAD) {
147+
msg += " Connection failed.";
148+
}
149+
150+
break;
151+
152+
default:
153+
// Some of the other status codes are not really errors
154+
// but we're not prepared to handle them right now and
155+
// shouldn't ever receive them so throw nevertheless
156+
157+
break;
158+
}
159+
160+
const char *const pqError = PQresultErrorMessage(result_);
161+
if (pqError && *pqError) {
162+
msg += " ";
163+
msg += pqError;
164+
}
165+
166+
const char *sqlstate =
167+
PQresultErrorField(result_, PG_DIAG_SQLSTATE);
168+
const char *const blank_sql_state = " ";
169+
if (!sqlstate) {
170+
sqlstate = blank_sql_state;
171+
}
172+
173+
throw std::runtime_error(msg);
174+
};
175+
176+
auto connect = [check_for_data](auto &session_backend,
177+
auto &parameters,
178+
auto &conn_) {
179+
PGconn *conn =
180+
PQconnectdb(parameters.get_connect_string().c_str());
181+
if (0 == conn || CONNECTION_OK != PQstatus(conn)) {
182+
std::string msg =
183+
"Cannot establish connection to the database.";
184+
if (0 != conn) {
185+
msg += '\n';
186+
msg += PQerrorMessage(conn);
187+
PQfinish(conn);
188+
}
189+
190+
throw std::runtime_error(msg);
191+
}
192+
193+
// Increase the number of digits used for floating point values to
194+
// ensure that the conversions to/from text round trip correctly,
195+
// which is not the case with the default value of 0. Use the
196+
// maximal supported value, which was 2 until 9.x and is 3 since
197+
// it.
198+
int const version = PQserverVersion(conn);
199+
check_for_data(
200+
session_backend,
201+
PQexec(conn,
202+
version >= 90000 ? "SET extra_float_digits = 3"
203+
: "SET extra_float_digits = 2"),
204+
"Cannot set extra_float_digits parameter");
205+
206+
conn_ = conn;
207+
};
208+
209+
clean_up(conn_);
210+
connect(*pg_connection, parameters, conn_);
211+
122212
init_session_(connection_);
123213
successful_reconnection = true;
124214
} catch (const std::exception &e) {
@@ -208,26 +298,25 @@ namespace iroha {
208298

209299
// TODO: 2019-05-06 @muratovv rework unhandled exception with Result
210300
// IR-464
211-
on_init_db();
301+
on_init_db(session);
212302
iroha::ametsuchi::PostgresCommandExecutor::prepareStatements(session);
213303
};
214304

215305
/// lambda contains special actions which should be execute once
216-
auto init_db = [&]() {
217-
soci::session sql(*connection_);
306+
auto init_db = [&](soci::session &session) {
218307
// rollback current prepared transaction
219308
// if there exists any since last session
220309
if (prepared_blocks_enabled_) {
221-
rollbackPrepared(sql);
310+
rollbackPrepared(session);
222311
}
223-
sql << init_;
312+
session << init_;
224313
};
225314

226315
/// lambda contains actions which should be invoked once for each session
227316
auto init_failover_callback = [&](soci::session &session) {
228317
static size_t connection_index = 0;
229318
auto restore_session = [connection_initialization](soci::session &s) {
230-
return connection_initialization(s, [] {}, [](auto &) {});
319+
return connection_initialization(s, [](auto &) {}, [](auto &) {});
231320
};
232321

233322
auto &callback = callback_factory_->makeFailoverCallback(
@@ -249,7 +338,8 @@ namespace iroha {
249338
connection_->at(0), init_db, init_failover_callback);
250339
for (size_t i = 1; i != pool_size_; i++) {
251340
soci::session &session = connection_->at(i);
252-
connection_initialization(session, [] {}, init_failover_callback);
341+
connection_initialization(
342+
session, [](auto &) {}, init_failover_callback);
253343
}
254344
}
255345

libs/logger/logger.hpp

Lines changed: 59 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ auto operator<<(StreamType &os, const T &object)
2222

2323
#include <fmt/format.h>
2424
#include <fmt/ostream.h>
25+
// Windows includes transitively included by format.h define interface as
26+
// struct, leading to compilation issues
2527
#undef interface
2628

2729
namespace logger {
@@ -41,63 +43,63 @@ namespace logger {
4143
};
4244

4345
class Logger {
44-
public:
45-
using Level = LogLevel;
46-
47-
virtual ~Logger() = default;
48-
49-
// --- Logging functions ---
50-
51-
template <typename... Args>
52-
void trace(const std::string &format, const Args &... args) const {
53-
log(LogLevel::kTrace, format, args...);
54-
}
55-
56-
template <typename... Args>
57-
void debug(const std::string &format, const Args &... args) const {
58-
log(LogLevel::kDebug, format, args...);
59-
}
60-
61-
template <typename... Args>
62-
void info(const std::string &format, const Args &... args) const {
63-
log(LogLevel::kInfo, format, args...);
64-
}
65-
66-
template <typename... Args>
67-
void warn(const std::string &format, const Args &... args) const {
68-
log(LogLevel::kWarn, format, args...);
69-
}
70-
71-
template <typename... Args>
72-
void error(const std::string &format, const Args &... args) const {
73-
log(LogLevel::kError, format, args...);
74-
}
75-
76-
template <typename... Args>
77-
void critical(const std::string &format, const Args &... args) const {
78-
log(LogLevel::kCritical, format, args...);
79-
}
80-
81-
template <typename... Args>
82-
void log(Level level,
83-
const std::string &format,
84-
const Args &... args) const {
85-
if (shouldLog(level)) {
86-
try {
87-
logInternal(level, fmt::format(format, args...));
88-
} catch (const fmt::v5::format_error &error) {
89-
std::string error_msg("Exception was thrown while logging: ");
90-
logInternal(LogLevel::kError, error_msg.append(error.what()));
91-
}
92-
}
93-
}
94-
95-
protected:
96-
virtual void logInternal(Level level, const std::string &s) const = 0;
97-
98-
/// Whether the configured logging level is at least as verbose as the
99-
/// one given in parameter.
100-
virtual bool shouldLog(Level level) const = 0;
46+
public:
47+
using Level = LogLevel;
48+
49+
virtual ~Logger() = default;
50+
51+
// --- Logging functions ---
52+
53+
template <typename... Args>
54+
void trace(const std::string &format, const Args &... args) const {
55+
log(LogLevel::kTrace, format, args...);
56+
}
57+
58+
template <typename... Args>
59+
void debug(const std::string &format, const Args &... args) const {
60+
log(LogLevel::kDebug, format, args...);
61+
}
62+
63+
template <typename... Args>
64+
void info(const std::string &format, const Args &... args) const {
65+
log(LogLevel::kInfo, format, args...);
66+
}
67+
68+
template <typename... Args>
69+
void warn(const std::string &format, const Args &... args) const {
70+
log(LogLevel::kWarn, format, args...);
71+
}
72+
73+
template <typename... Args>
74+
void error(const std::string &format, const Args &... args) const {
75+
log(LogLevel::kError, format, args...);
76+
}
77+
78+
template <typename... Args>
79+
void critical(const std::string &format, const Args &... args) const {
80+
log(LogLevel::kCritical, format, args...);
81+
}
82+
83+
template <typename... Args>
84+
void log(Level level,
85+
const std::string &format,
86+
const Args &... args) const {
87+
if (shouldLog(level)) {
88+
try {
89+
logInternal(level, fmt::format(format, args...));
90+
} catch (const fmt::v5::format_error &error) {
91+
std::string error_msg("Exception was thrown while logging: ");
92+
logInternal(LogLevel::kError, error_msg.append(error.what()));
93+
}
94+
}
95+
}
96+
97+
protected:
98+
virtual void logInternal(Level level, const std::string &s) const = 0;
99+
100+
/// Whether the configured logging level is at least as verbose as the
101+
/// one given in parameter.
102+
virtual bool shouldLog(Level level) const = 0;
101103
};
102104

103105
/**

0 commit comments

Comments
 (0)