8
0
mirror of https://github.com/FirebirdSQL/firebird.git synced 2025-01-22 16:43:03 +01:00

Fixed performance issue #7854

This commit is contained in:
Vlad Khorsun 2023-11-20 15:03:18 +02:00
parent a0ff6b90a3
commit df87667e18
3 changed files with 37 additions and 8 deletions

View File

@ -36,6 +36,8 @@
#include "../common/os/os_utils.h"
#include "unicode/ucal.h"
#include <atomic>
using namespace Firebird;
namespace
@ -45,10 +47,21 @@ namespace
public:
TimeZoneDesc(MemoryPool& pool)
: asciiName(pool),
unicodeName(pool)
unicodeName(pool),
calendar(nullptr)
{
}
~TimeZoneDesc()
{
UCalendar* val = calendar.exchange(nullptr);
if (val)
{
auto& icuLib = Jrd::UnicodeUtil::getConversionICU();
icuLib.ucalClose(val);
}
}
public:
void setName(const char* name)
{
@ -70,9 +83,26 @@ namespace
return unicodeName.begin();
}
UCalendar* getCalendar(const Jrd::UnicodeUtil::ConversionICU& icuLib, UErrorCode* err) const
{
UCalendar* val = calendar.load();
if (!val)
{
val = icuLib.ucalOpen(getUnicodeName(), -1, NULL, UCAL_GREGORIAN, err);
if (!val)
return val;
UCalendar* old = calendar.exchange(val);
if (old)
return old;
}
return icuLib.ucalClone(val, err);
}
private:
string asciiName;
Array<UChar> unicodeName;
mutable std::atomic<UCalendar*> calendar;
};
}
@ -593,8 +623,7 @@ void TimeZoneUtil::extractOffset(const ISC_TIMESTAMP_TZ& timeStampTz, SSHORT* of
Jrd::UnicodeUtil::ConversionICU& icuLib = Jrd::UnicodeUtil::getConversionICU();
UCalendar* icuCalendar = icuLib.ucalOpen(
getDesc(timeStampTz.time_zone)->getUnicodeName(), -1, NULL, UCAL_GREGORIAN, &icuErrorCode);
UCalendar* icuCalendar = getDesc(timeStampTz.time_zone)->getCalendar(icuLib, &icuErrorCode);
if (!icuCalendar)
status_exception::raise(Arg::Gds(isc_random) << "Error calling ICU's ucal_open.");
@ -702,8 +731,7 @@ void TimeZoneUtil::localTimeStampToUtc(ISC_TIMESTAMP_TZ& timeStampTz)
Jrd::UnicodeUtil::ConversionICU& icuLib = Jrd::UnicodeUtil::getConversionICU();
UCalendar* icuCalendar = icuLib.ucalOpen(
getDesc(timeStampTz.time_zone)->getUnicodeName(), -1, NULL, UCAL_GREGORIAN, &icuErrorCode);
UCalendar* icuCalendar = getDesc(timeStampTz.time_zone)->getCalendar(icuLib, &icuErrorCode);
if (!icuCalendar)
status_exception::raise(Arg::Gds(isc_random) << "Error calling ICU's ucal_open.");
@ -771,8 +799,7 @@ bool TimeZoneUtil::decodeTimeStamp(const ISC_TIMESTAMP_TZ& timeStampTz, bool gmt
#endif
Jrd::UnicodeUtil::ConversionICU& icuLib = Jrd::UnicodeUtil::getConversionICU();
UCalendar* icuCalendar = icuLib.ucalOpen(
getDesc(timeStampTz.time_zone)->getUnicodeName(), -1, NULL, UCAL_GREGORIAN, &icuErrorCode);
UCalendar* icuCalendar = getDesc(timeStampTz.time_zone)->getCalendar(icuLib, &icuErrorCode);
if (!icuCalendar)
status_exception::raise(Arg::Gds(isc_random) << "Error calling ICU's ucal_open.");
@ -1067,7 +1094,7 @@ TimeZoneRuleIterator::TimeZoneRuleIterator(USHORT aId, const ISC_TIMESTAMP_TZ& a
{
UErrorCode icuErrorCode = U_ZERO_ERROR;
icuCalendar = icuLib.ucalOpen(getDesc(id)->getUnicodeName(), -1, NULL, UCAL_GREGORIAN, &icuErrorCode);
icuCalendar = getDesc(id)->getCalendar(icuLib, &icuErrorCode);
if (!icuCalendar)
status_exception::raise(Arg::Gds(isc_random) << "Error calling ICU's ucal_open.");

View File

@ -446,6 +446,7 @@ private:
getEntryPoint("ucal_getTZDataVersion", inModule, ucalGetTZDataVersion);
getEntryPoint("ucal_getDefaultTimeZone", inModule, ucalGetDefaultTimeZone);
getEntryPoint("ucal_open", inModule, ucalOpen);
getEntryPoint("ucal_clone", inModule, ucalClone);
getEntryPoint("ucal_close", inModule, ucalClose);
getEntryPoint("ucal_setAttribute", inModule, ucalSetAttribute);
getEntryPoint("ucal_setMillis", inModule, ucalSetMillis);

View File

@ -130,6 +130,7 @@ public:
int32_t (U_EXPORT2* ucalGetDefaultTimeZone) (UChar* result, int32_t resultCapacity, UErrorCode* ec);
UCalendar* (U_EXPORT2* ucalOpen) (const UChar* zoneID, int32_t len, const char* locale, UCalendarType type,
UErrorCode* err);
UCalendar* (U_EXPORT2* ucalClone)(const UCalendar* cal, UErrorCode* status);
void (U_EXPORT2* ucalClose) (UCalendar* cal);
void (U_EXPORT2* ucalSetAttribute) (UCalendar* cal, UCalendarAttribute attr, int32_t newValue);
void (U_EXPORT2* ucalSetMillis) (UCalendar* cal, UDate dateTime, UErrorCode* err);