Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitc776cd4

Browse files
committed
Improve tzparse's handling of TZDEFRULES ("posixrules") zone data.
In the IANA timezone code, tzparse() always tries to load the zonefile named by TZDEFRULES ("posixrules"). Previously, we'd hackedthat logic to skip the load in the "lastditch" code path, which we useonly to initialize the default "GMT" zone during GUC initialization.That's critical for a couple of reasons: since we do not support leapseconds, we *must not* allow "GMT" to have leap seconds, and since thiscase runs before the GUC subsystem is fully alive, we'd really rathernot take the risk of pg_open_tzfile throwing any errors.However, that still left the code reading TZDEFRULES on every othercall, something we'd noticed to the extent of having added code to cachethe result so it was only done once per process not a lot of times.Andres Freund complained about the static data space used up for thecache; but as long as the logic was like this, there was no point intrying to get rid of that space.We can improve matters by looking a bit more closely at what the IANAcode actually needs the TZDEFRULES data for. One thing it does isthat if "posixrules" is a leap-second-aware zone, the leap-secondbehavior will be absorbed into every POSIX-style zone specification.However, that's a behavior we'd really prefer to do without, sincefor our purposes the end effect is to render every POSIX-style zonename unsupported. Otherwise, the TZDEFRULES data is used only ifthe POSIX zone name specifies DST but doesn't include a transitiondate rule (e.g., "EST5EDT" rather than "EST5EDT,M3.2.0,M11.1.0").That is a minority case for our purposes --- in particular, itnever happens when tzload() invokes tzparse() to interpret atransition date rule string found in a tzdata zone file.Hence, if we legislate that we're going to ignore leap-second datafrom "posixrules", we can postpone the TZDEFRULES load into the pathwhere we actually need to substitute for a missing date rule string.That means it will never happen at all in common scenarios, making itreasonable to dynamically allocate the cache space when it does happen.Even when the data is already loaded, this saves some cycles in thecommon code path since we avoid a memcpy of 23KB or so. And, IMO atleast, this is a less ugly hack on the IANA logic than what we hadbefore, since it's not messing with the lastditch-vs-regular code paths.Back-patch to all supported branches, not so much because this is acritical change as that I want to keep all our copies of the IANAtimezone code in sync.Discussion:https://postgr.es/m/20181015200754.7y7zfuzsoux2c4ya@alap3.anarazel.de
1 parent19ac2cb commitc776cd4

File tree

2 files changed

+54
-36
lines changed

2 files changed

+54
-36
lines changed

‎src/timezone/README

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,8 +84,10 @@ other exposed names.
8484
slightly modified the API of the former, in part because it now relies
8585
on our own pg_open_tzfile() rather than opening files for itself.
8686

87-
* tzparse() is adjusted to cache the result of loading the TZDEFRULES
88-
zone, so that that's not repeated more than once per process.
87+
* tzparse() is adjusted to avoid loading the TZDEFRULES zone unless
88+
really necessary, and to ignore any leap-second data it may supply.
89+
We also cache the result of loading the TZDEFRULES zone, so that
90+
that's not repeated more than once per process.
8991

9092
* There's a fair amount of code we don't need and have removed,
9193
including all the nonstandard optional APIs. We have also added

‎src/timezone/localtime.c

Lines changed: 50 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ static const char gmt[] = "GMT";
5454
* PG: We cache the result of trying to load the TZDEFRULES zone here.
5555
* tzdefrules_loaded is 0 if not tried yet, +1 if good, -1 if failed.
5656
*/
57-
staticstructstatetzdefrules_s;
57+
staticstructstate*tzdefrules_s=NULL;
5858
staticinttzdefrules_loaded=0;
5959

6060
/*
@@ -908,20 +908,10 @@ tzparse(const char *name, struct state *sp, bool lastditch)
908908
stdname=name;
909909
if (lastditch)
910910
{
911-
/*
912-
* This is intentionally somewhat different from the IANA code. We do
913-
* not want to invoke tzload() in the lastditch case: we can't assume
914-
* pg_open_tzfile() is sane yet, and we don't care about leap seconds
915-
* anyway.
916-
*/
911+
/* Unlike IANA, don't assume name is exactly "GMT" */
917912
stdlen=strlen(name);/* length of standard zone name */
918913
name+=stdlen;
919-
if (stdlen >=sizeofsp->chars)
920-
stdlen= (sizeofsp->chars)-1;
921-
charcnt=stdlen+1;
922914
stdoffset=0;
923-
sp->goback=sp->goahead= false;/* simulate failed tzload() */
924-
load_ok= false;
925915
}
926916
else
927917
{
@@ -945,27 +935,23 @@ tzparse(const char *name, struct state *sp, bool lastditch)
945935
name=getoffset(name,&stdoffset);
946936
if (name==NULL)
947937
return false;
948-
charcnt=stdlen+1;
949-
if (sizeofsp->chars<charcnt)
950-
return false;
951-
952-
/*
953-
* This bit also differs from the IANA code, which doesn't make any
954-
* attempt to avoid repetitive loadings of the TZDEFRULES zone.
955-
*/
956-
if (tzdefrules_loaded==0)
957-
{
958-
if (tzload(TZDEFRULES,NULL,&tzdefrules_s, false)==0)
959-
tzdefrules_loaded=1;
960-
else
961-
tzdefrules_loaded=-1;
962-
}
963-
load_ok= (tzdefrules_loaded>0);
964-
if (load_ok)
965-
memcpy(sp,&tzdefrules_s,sizeof(structstate));
966938
}
967-
if (!load_ok)
968-
sp->leapcnt=0;/* so, we're off a little */
939+
charcnt=stdlen+1;
940+
if (sizeofsp->chars<charcnt)
941+
return false;
942+
943+
/*
944+
* The IANA code always tries tzload(TZDEFRULES) here. We do not want to
945+
* do that; it would be bad news in the lastditch case, where we can't
946+
* assume pg_open_tzfile() is sane yet. Moreover, the only reason to do
947+
* it unconditionally is to absorb the TZDEFRULES zone's leap second info,
948+
* which we don't want to do anyway. Without that, we only need to load
949+
* TZDEFRULES if the zone name specifies DST but doesn't incorporate a
950+
* POSIX-style transition date rule, which is not a common case.
951+
*/
952+
sp->goback=sp->goahead= false;/* simulate failed tzload() */
953+
sp->leapcnt=0;/* intentionally assume no leap seconds */
954+
969955
if (*name!='\0')
970956
{
971957
if (*name=='<')
@@ -996,8 +982,38 @@ tzparse(const char *name, struct state *sp, bool lastditch)
996982
}
997983
else
998984
dstoffset=stdoffset-SECSPERHOUR;
999-
if (*name=='\0'&& !load_ok)
1000-
name=TZDEFRULESTRING;
985+
if (*name=='\0')
986+
{
987+
/*
988+
* The POSIX zone name does not provide a transition-date rule.
989+
* Here we must load the TZDEFRULES zone, if possible, to serve as
990+
* source data for the transition dates. Unlike the IANA code, we
991+
* try to cache the data so it's only loaded once.
992+
*/
993+
if (tzdefrules_loaded==0)
994+
{
995+
/* Allocate on first use */
996+
if (tzdefrules_s==NULL)
997+
tzdefrules_s= (structstate*)malloc(sizeof(structstate));
998+
if (tzdefrules_s!=NULL)
999+
{
1000+
if (tzload(TZDEFRULES,NULL,tzdefrules_s, false)==0)
1001+
tzdefrules_loaded=1;
1002+
else
1003+
tzdefrules_loaded=-1;
1004+
/* In any case, we ignore leap-second data from the file */
1005+
tzdefrules_s->leapcnt=0;
1006+
}
1007+
}
1008+
load_ok= (tzdefrules_loaded>0);
1009+
if (load_ok)
1010+
memcpy(sp,tzdefrules_s,sizeof(structstate));
1011+
else
1012+
{
1013+
/* If we can't load TZDEFRULES, fall back to hard-wired rule */
1014+
name=TZDEFRULESTRING;
1015+
}
1016+
}
10011017
if (*name==','||*name==';')
10021018
{
10031019
structrulestart;

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp