mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-27 23:04:50 +02:00
8223490: Optimize search algorithm for determining default time zone
Reviewed-by: naoto, rriggs
This commit is contained in:
parent
89b0250e4a
commit
788b2414c1
1 changed files with 71 additions and 45 deletions
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 1999, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -42,6 +42,8 @@
|
|||
#include "jvm.h"
|
||||
#include "TimeZone_md.h"
|
||||
|
||||
static char *isFileIdentical(char* buf, size_t size, char *pathname);
|
||||
|
||||
#define SKIP_SPACE(p) while (*p == ' ' || *p == '\t') p++;
|
||||
|
||||
#define RESTARTABLE(_cmd, _result) do { \
|
||||
|
@ -72,6 +74,8 @@ static const char *ZONEINFO_DIR = "/usr/share/lib/zoneinfo";
|
|||
static const char *DEFAULT_ZONEINFO_FILE = "/usr/share/lib/zoneinfo/localtime";
|
||||
#endif /* defined(__linux__) || defined(_ALLBSD_SOURCE) */
|
||||
|
||||
static const char popularZones[][4] = {"UTC", "GMT"};
|
||||
|
||||
#if defined(_AIX)
|
||||
static const char *ETC_ENVIRONMENT_FILE = "/etc/environment";
|
||||
#endif
|
||||
|
@ -121,11 +125,8 @@ static char *
|
|||
findZoneinfoFile(char *buf, size_t size, const char *dir)
|
||||
{
|
||||
DIR *dirp = NULL;
|
||||
struct stat64 statbuf;
|
||||
struct dirent *dp = NULL;
|
||||
char *pathname = NULL;
|
||||
int fd = -1;
|
||||
char *dbuf = NULL;
|
||||
char *tz = NULL;
|
||||
int res;
|
||||
|
||||
|
@ -134,6 +135,22 @@ findZoneinfoFile(char *buf, size_t size, const char *dir)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
if (strcmp(dir, ZONEINFO_DIR) == 0) {
|
||||
/* fast path for 1st iteration */
|
||||
for (unsigned int i = 0; i < sizeof (popularZones) / sizeof (popularZones[0]); i++) {
|
||||
pathname = getPathName(dir, popularZones[i]);
|
||||
if (pathname == NULL) {
|
||||
continue;
|
||||
}
|
||||
tz = isFileIdentical(buf, size, pathname);
|
||||
free((void *) pathname);
|
||||
pathname = NULL;
|
||||
if (tz != NULL) {
|
||||
return tz;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
while ((dp = readdir(dirp)) != NULL) {
|
||||
/*
|
||||
* Skip '.' and '..' (and possibly other .* files)
|
||||
|
@ -162,58 +179,67 @@ findZoneinfoFile(char *buf, size_t size, const char *dir)
|
|||
if (pathname == NULL) {
|
||||
break;
|
||||
}
|
||||
RESTARTABLE(stat64(pathname, &statbuf), res);
|
||||
if (res == -1) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (S_ISDIR(statbuf.st_mode)) {
|
||||
tz = findZoneinfoFile(buf, size, pathname);
|
||||
if (tz != NULL) {
|
||||
break;
|
||||
}
|
||||
} else if (S_ISREG(statbuf.st_mode) && (size_t)statbuf.st_size == size) {
|
||||
dbuf = (char *) malloc(size);
|
||||
if (dbuf == NULL) {
|
||||
break;
|
||||
}
|
||||
RESTARTABLE(open(pathname, O_RDONLY), fd);
|
||||
if (fd == -1) {
|
||||
break;
|
||||
}
|
||||
RESTARTABLE(read(fd, dbuf, size), res);
|
||||
if (res != (ssize_t) size) {
|
||||
break;
|
||||
}
|
||||
if (memcmp(buf, dbuf, size) == 0) {
|
||||
tz = getZoneName(pathname);
|
||||
if (tz != NULL) {
|
||||
tz = strdup(tz);
|
||||
}
|
||||
break;
|
||||
}
|
||||
free((void *) dbuf);
|
||||
dbuf = NULL;
|
||||
(void) close(fd);
|
||||
fd = -1;
|
||||
}
|
||||
tz = isFileIdentical(buf, size, pathname);
|
||||
free((void *) pathname);
|
||||
pathname = NULL;
|
||||
if (tz != NULL) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (dirp != NULL) {
|
||||
(void) closedir(dirp);
|
||||
}
|
||||
if (pathname != NULL) {
|
||||
free((void *) pathname);
|
||||
return tz;
|
||||
}
|
||||
|
||||
/*
|
||||
* Checks if the file pointed to by pathname matches
|
||||
* the data contents in buf.
|
||||
* Returns a representation of the timezone file name
|
||||
* if file match is found, otherwise NULL.
|
||||
*/
|
||||
static char *
|
||||
isFileIdentical(char *buf, size_t size, char *pathname)
|
||||
{
|
||||
char *possibleMatch = NULL;
|
||||
struct stat64 statbuf;
|
||||
char *dbuf = NULL;
|
||||
int fd = -1;
|
||||
int res;
|
||||
|
||||
RESTARTABLE(stat64(pathname, &statbuf), res);
|
||||
if (res == -1) {
|
||||
return NULL;
|
||||
}
|
||||
if (fd != -1) {
|
||||
|
||||
if (S_ISDIR(statbuf.st_mode)) {
|
||||
possibleMatch = findZoneinfoFile(buf, size, pathname);
|
||||
} else if (S_ISREG(statbuf.st_mode) && (size_t)statbuf.st_size == size) {
|
||||
dbuf = (char *) malloc(size);
|
||||
if (dbuf == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
RESTARTABLE(open(pathname, O_RDONLY), fd);
|
||||
if (fd == -1) {
|
||||
goto freedata;
|
||||
}
|
||||
RESTARTABLE(read(fd, dbuf, size), res);
|
||||
if (res != (ssize_t) size) {
|
||||
goto freedata;
|
||||
}
|
||||
if (memcmp(buf, dbuf, size) == 0) {
|
||||
possibleMatch = getZoneName(pathname);
|
||||
if (possibleMatch != NULL) {
|
||||
possibleMatch = strdup(possibleMatch);
|
||||
}
|
||||
}
|
||||
freedata:
|
||||
free((void *) dbuf);
|
||||
(void) close(fd);
|
||||
}
|
||||
if (dbuf != NULL) {
|
||||
free((void *) dbuf);
|
||||
}
|
||||
return tz;
|
||||
return possibleMatch;
|
||||
}
|
||||
|
||||
#if defined(__linux__) || defined(MACOSX)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue