From cad6bb42726c20a21b88e3ec4ee246dc3d9125c4 Mon Sep 17 00:00:00 2001 From: John Ralls Date: Tue, 17 Apr 2018 16:27:24 -0700 Subject: [PATCH] Bug 792105 - Startup takes several minutes, take two. First, remove the unnecessary locale push & pop on load. Second, the registry accesses were caused by using g_win32_get_locale to convert the Microsoft locale strings to POSIX ones. We don't care what kind of string we get as long as we can pass it back to setlocale, so remove that. Third, gnc_push/pop_locale were used only in backend/dbi in a very limited way and did much more than was necessary, so convert them to C++ inlines in gnc-backend-dbi.hpp that does only what we need them to. --- libgnucash/backend/dbi/gnc-backend-dbi.cpp | 6 +-- libgnucash/backend/dbi/gnc-backend-dbi.hpp | 15 +++++++ .../backend/dbi/gnc-dbisqlconnection.cpp | 4 +- libgnucash/backend/dbi/gnc-dbisqlresult.cpp | 10 ++--- libgnucash/core-utils/gnc-locale-utils.c | 40 ------------------- libgnucash/core-utils/gnc-locale-utils.h | 22 ---------- 6 files changed, 24 insertions(+), 73 deletions(-) diff --git a/libgnucash/backend/dbi/gnc-backend-dbi.cpp b/libgnucash/backend/dbi/gnc-backend-dbi.cpp index 68b893379a..4017066117 100644 --- a/libgnucash/backend/dbi/gnc-backend-dbi.cpp +++ b/libgnucash/backend/dbi/gnc-backend-dbi.cpp @@ -1177,7 +1177,7 @@ dbi_library_test (dbi_conn conn) return GNC_DBI_FAIL_SETUP; } dbi_result_free (result); - gnc_push_locale (LC_NUMERIC, "C"); + auto locale = gnc_push_locale (LC_NUMERIC, "C"); result = dbi_conn_query (conn, "SELECT * FROM numtest"); if (result == nullptr) { @@ -1186,7 +1186,7 @@ dbi_library_test (dbi_conn conn) PWARN ("Test_DBI_Library: Failed to retrieve test row into table: %s", errmsg); dbi_conn_query (conn, "DROP TABLE numtest"); - gnc_pop_locale (LC_NUMERIC); + gnc_pop_locale (LC_NUMERIC, locale); return GNC_DBI_FAIL_SETUP; } while (dbi_result_next_row (result)) @@ -1196,7 +1196,7 @@ dbi_library_test (dbi_conn conn) resultdouble = dbi_result_get_double (result, "test_double"); } dbi_conn_query (conn, "DROP TABLE numtest"); - gnc_pop_locale (LC_NUMERIC); + gnc_pop_locale (LC_NUMERIC, locale); if (testlonglong != resultlonglong) { PWARN ("Test_DBI_Library: LongLong Failed %" PRId64 " != % " PRId64, diff --git a/libgnucash/backend/dbi/gnc-backend-dbi.hpp b/libgnucash/backend/dbi/gnc-backend-dbi.hpp index 5d027324b2..07b92e68bf 100644 --- a/libgnucash/backend/dbi/gnc-backend-dbi.hpp +++ b/libgnucash/backend/dbi/gnc-backend-dbi.hpp @@ -118,6 +118,21 @@ private: bool m_exists; // Does the database exist? }; +/* locale-stack */ +inline std::string +gnc_push_locale(const int category, const std::string locale) +{ + std::string retval(setlocale(category, nullptr)); + setlocale(category, locale.c_str()); + return retval; +} + +inline void +gnc_pop_locale(const int category, std::string locale) +{ + setlocale(category, locale.c_str()); +} + /* external access required for tests */ std::string adjust_sql_options_string(const std::string&); diff --git a/libgnucash/backend/dbi/gnc-dbisqlconnection.cpp b/libgnucash/backend/dbi/gnc-dbisqlconnection.cpp index a4172f4a35..f24f6939b6 100644 --- a/libgnucash/backend/dbi/gnc-dbisqlconnection.cpp +++ b/libgnucash/backend/dbi/gnc-dbisqlconnection.cpp @@ -252,7 +252,7 @@ GncDbiSqlConnection::execute_select_statement (const GncSqlStatementPtr& stmt) dbi_result result; DEBUG ("SQL: %s\n", stmt->to_sql()); - gnc_push_locale (LC_NUMERIC, "C"); + auto locale = gnc_push_locale (LC_NUMERIC, "C"); do { init_error (); @@ -261,7 +261,7 @@ GncDbiSqlConnection::execute_select_statement (const GncSqlStatementPtr& stmt) while (m_retry); if (result == nullptr) PERR ("Error executing SQL %s\n", stmt->to_sql()); - gnc_pop_locale (LC_NUMERIC); + gnc_pop_locale (LC_NUMERIC, locale); return GncSqlResultPtr(new GncDbiSqlResult (this, result)); } diff --git a/libgnucash/backend/dbi/gnc-dbisqlresult.cpp b/libgnucash/backend/dbi/gnc-dbisqlresult.cpp index a686fa40a5..5b2a784e2a 100644 --- a/libgnucash/backend/dbi/gnc-dbisqlresult.cpp +++ b/libgnucash/backend/dbi/gnc-dbisqlresult.cpp @@ -117,9 +117,9 @@ GncDbiSqlResult::IteratorImpl::get_float_at_col(const char* col) const if(type != DBI_TYPE_DECIMAL || (attrs & DBI_DECIMAL_SIZEMASK) != DBI_DECIMAL_SIZE4) throw (std::invalid_argument{"Requested float from non-float column."}); - gnc_push_locale (LC_NUMERIC, "C"); + auto locale = gnc_push_locale (LC_NUMERIC, "C"); auto retval = dbi_result_get_float(m_inst->m_dbi_result, col); - gnc_pop_locale (LC_NUMERIC); + gnc_pop_locale (LC_NUMERIC, locale); return retval; } @@ -131,9 +131,9 @@ GncDbiSqlResult::IteratorImpl::get_double_at_col(const char* col) const if(type != DBI_TYPE_DECIMAL || (attrs & DBI_DECIMAL_SIZEMASK) != DBI_DECIMAL_SIZE8) throw (std::invalid_argument{"Requested double from non-double column."}); - gnc_push_locale (LC_NUMERIC, "C"); + auto locale = gnc_push_locale (LC_NUMERIC, "C"); auto retval = dbi_result_get_double(m_inst->m_dbi_result, col); - gnc_pop_locale (LC_NUMERIC); + gnc_pop_locale (LC_NUMERIC, locale); return retval; } @@ -160,7 +160,6 @@ GncDbiSqlResult::IteratorImpl::get_time64_at_col (const char* col) const auto attrs = dbi_result_get_field_attribs (result, col); if (type != DBI_TYPE_DATETIME) throw (std::invalid_argument{"Requested time64 from non-time64 column."}); - gnc_push_locale (LC_NUMERIC, "C"); #if HAVE_LIBDBI_TO_LONGLONG /* A less evil hack than the one required by libdbi-0.8, but * still necessary to work around the same bug. @@ -179,7 +178,6 @@ GncDbiSqlResult::IteratorImpl::get_time64_at_col (const char* col) const #endif //HAVE_LIBDBI_TO_LONGLONG if (retval < MINTIME || retval > MAXTIME) retval = 0; - gnc_pop_locale (LC_NUMERIC); return retval; } diff --git a/libgnucash/core-utils/gnc-locale-utils.c b/libgnucash/core-utils/gnc-locale-utils.c index 94b1e1dc28..7af53593b6 100644 --- a/libgnucash/core-utils/gnc-locale-utils.c +++ b/libgnucash/core-utils/gnc-locale-utils.c @@ -150,43 +150,3 @@ gnc_locale_decimal_places (void) return places; } - - -static GList *locale_stack = NULL; - -void -gnc_push_locale (int category, const char *locale) -{ - char *saved_locale; - - g_return_if_fail (locale != NULL); - -# ifdef G_OS_WIN32 - /* On win32, setlocale() doesn't say anything useful. Use - glib's function instead. */ - saved_locale = g_win32_getlocale(); -# else - saved_locale = g_strdup(setlocale(category, NULL) ? - setlocale(category, NULL) : "C"); -#endif - locale_stack = g_list_prepend (locale_stack, saved_locale); - setlocale (category, locale); -} - -void -gnc_pop_locale (int category) -{ - char *saved_locale; - GList *node; - - g_return_if_fail (locale_stack != NULL); - - node = locale_stack; - saved_locale = node->data; - - setlocale (category, saved_locale); - - locale_stack = g_list_remove_link (locale_stack, node); - g_list_free_1 (node); - g_free (saved_locale); -} diff --git a/libgnucash/core-utils/gnc-locale-utils.h b/libgnucash/core-utils/gnc-locale-utils.h index 5dbe4b1fa8..5d9063865c 100644 --- a/libgnucash/core-utils/gnc-locale-utils.h +++ b/libgnucash/core-utils/gnc-locale-utils.h @@ -37,26 +37,4 @@ const char * gnc_locale_default_iso_currency_code (void); /* Returns the number of decimal place to print in the current locale */ int gnc_locale_decimal_places (void); -/** Temporarily change locale, pushing the old one onto a stack - * Currently, this has no effect on gnc_localeconv. i.e., after the - * first call to gnc_localeconv, subsequent calls will return the same - * information. - * - * WARNING: Be careful to maintain the correct nesting order of pushes - * or pops; otherwise, the localization results might be - * interesting. Note that the stack does not keep track of which - * category a locale was pushed from, so careless use will alse - * produce interesting results. - * - * @param category: The locale category (e.g. LC_ALL, LC_NUMERIC) to push onto - * @param locale: The new locale to set - */ -void gnc_push_locale (int category, const char *locale); - -/** Restore the last-pushed locale. - * @param category: The locale category to restore the locale to. - */ -void gnc_pop_locale (int category); - - #endif /* GNC_LOCALE_UTILS_H */