Previously pgpool assumed that time_t to be a simple long. This causes
a lot of compile time warnings on certain systems, for example
OpenBSD because on the system time_t is __int64, which results in long
long. This commit upcasts such calculations to long long to avoid the
issue.
This way times can't get truncated and for the places where time_t is
actually used as a time and not a time diff this would allow pgpool to
keep working correctly post Y2038 on 64 bit clean time_t systems
(e.g. i386 OpenBSD).
Moreover, json_get_long_value_for_key is changed to
json_get_llong_value_for_key and changed the parameter to long long.
This makes it more in line _json_value's integer, which is defined as
int64. This should also give 32 bit platforms proper retrieval of the
max value of an integer and may or may not solve some weird integer
overflow issues.
Backpatch for 4.6 was rebased by Gyorgy Sarvari.
Author: Martijn van Duren <pgpool@list.imperialat.at>
Reviewed-by: Tatsuo Ishii <ishii@postgresql.org>
Reviewed-by: Gyorgy Sarvari <skandigraun@gmail.com>
Backpatch-through: v4.6
Discussion: https://www.pgpool.net/pipermail/pgpool-hackers/2025-May/004584.html
Discussion: https://www.postgresql.org/message-id/
20251003.211957.
2067537305399895611.ishii%40postgresql.org
Discussion: https://github.com/pgpool/pgpool2/pull/128
/* pgpool-II extensions */
json_value *json_get_value_for_key(json_value *source, const char *key);
int json_get_int_value_for_key(json_value *source, const char *key, int *value);
-int json_get_long_value_for_key(json_value *source, const char *key, long *value);
+int json_get_llong_value_for_key(json_value * source, const char *key, long long *value);
char *json_get_string_value_for_key(json_value *source, const char *key);
int json_get_bool_value_for_key(json_value *source, const char *key, bool *value);
char *stringVal;
int intVal;
bool boolVal;
- long longVal;
+ long long longVal;
} data;
} WDGenericData;
extern bool parse_beacon_message_json(char *json_data, int data_len, int *state,
- long *seconds_since_node_startup,
- long *seconds_since_current_state,
+ long long *seconds_since_node_startup,
+ long long *seconds_since_current_state,
int *quorumStatus,
int *standbyNodesCount,
bool *escalated);
#include "main/pgpool_logger.h"
#define DEVNULL "/dev/null"
-typedef int64 pg_time_t;
+typedef time_t pg_time_t;
/*
* We read() into a temp buffer twice as big as a chunk, so that any fragment
snprintf(standby_delay_by_time_str, sizeof(standby_delay_by_time_str), "%d", bi->standby_delay_by_time);
- snprintf(standby_delay_str, sizeof(standby_delay_str), UINT64_FORMAT, bi->standby_delay);
+ snprintf(standby_delay_str, sizeof(standby_delay_str), "%lld", (long long)bi->standby_delay);
- snprintf(status_changed_time_str, sizeof(status_changed_time_str), UINT64_FORMAT, bi->status_changed_time);
+ snprintf(status_changed_time_str, sizeof(status_changed_time_str), "%lld", (long long)bi->status_changed_time);
pcp_write(frontend, "i", 1);
wsize = htonl(sizeof(code) +
ereport(DEBUG1,
(errmsg("creating connection pool"),
- errdetail("user: %s database: %s closetime: %ld",
+ errdetail("user: %s database: %s closetime: %lld",
CONNECTION_SLOT(p, main_node_id)->sp->user,
CONNECTION_SLOT(p, main_node_id)->sp->database,
- CONNECTION_SLOT(p, main_node_id)->closetime)));
+ (long long)CONNECTION_SLOT(p, main_node_id)->closetime)));
if (CONNECTION_SLOT(p, main_node_id)->closetime < closetime)
{
ereport(DEBUG1,
(errmsg("setting backend connection close timer"),
- errdetail("close time %ld", time(NULL))));
+ errdetail("close time %lld", (long long)time(NULL))));
/* Set connection close time */
for (i = 0; i < NUM_BACKENDS; i++)
now = time(NULL);
ereport(DEBUG1,
- (errmsg("backend timer handler called at %ld", now)));
+ (errmsg("backend timer handler called at %lld", (long long)now)));
for (i = 0; i < pool_config->max_pool; i++, p++)
{
ereport(DEBUG1,
(errmsg("backend timer handler called"),
- errdetail("expire time: %ld",
- MAIN_CONNECTION(p)->closetime + pool_config->connection_life_time)));
+ errdetail("expire time: %lld",
+ (long long)(MAIN_CONNECTION(p)->closetime + pool_config->connection_life_time))));
if (now >= (MAIN_CONNECTION(p)->closetime + pool_config->connection_life_time))
{
memqcache_expire = pool_config->memqcache_expire;
ereport(DEBUG1,
(errmsg("committing SELECT results to cache storage"),
- errdetail("memqcache_expire = %ld", memqcache_expire)));
+ errdetail("memqcache_expire = %lld", (long long)memqcache_expire)));
if (pool_is_shmem_cache())
{
memqcache_expire = pool_config->relcache_expire;
ereport(DEBUG1,
(errmsg("committing relation cache to cache storage"),
- errdetail("memqcache_expire = %ld", memqcache_expire)));
+ errdetail("memqcache_expire = %lld", (long long)memqcache_expire)));
if (pool_is_shmem_cache())
{
{
ereport(DEBUG1,
(errmsg("memcache finding item"),
- errdetail("cache expired: now: %ld timestamp: %ld",
- now, cih->timestamp + cih->expire)));
+ errdetail("cache expired: now: %lld timestamp: %lld",
+ (long long)now, (long long)(cih->timestamp + cih->expire))));
pool_delete_item_shmem_cache(c);
return NULL;
}
}
int
-json_get_long_value_for_key(json_value *source, const char *key, long *value)
+json_get_llong_value_for_key(json_value * source, const char *key, long long *value)
{
json_value *jNode;
/* status last changed */
t = bi->status_changed_time;
- ereport(LOG, (errmsg("status_changed_time %ld", t)));
+ ereport(LOG,(errmsg("status_changed_time %lld", (long long)t)));
strftime(stats[i].last_status_change, POOLCONFIG_MAXDATELEN, "%F %T", localtime(&t));
snprintf(stats[i].total_count, POOLCONFIG_MAXLONGCOUNTLEN, UINT64_FORMAT, health_check_stats[i].total_count);
{
ereport(DEBUG1,
(errmsg("searching relcache"),
- errdetail("relcache for database:%s table:%s expired. now:%ld expiration time:%ld", dbname, table, now, relcache->cache[i].expire)));
+ errdetail("relcache for database:%s table:%s expired. now:%lld expiration time:%lld", dbname, table, (long long)now, (long long)relcache->cache[i].expire)));
relcache->cache[i].refcnt = 0;
break;
static bool
beacon_message_received_from_node(WatchdogNode *wdNode, WDPacketData *pkt)
{
- long seconds_since_node_startup;
- long seconds_since_current_state;
+ long long seconds_since_node_startup;
+ long long seconds_since_current_state;
int quorum_status;
int standby_nodes_count;
bool escalated;
case VALUE_DATA_TYPE_LONG:
{
- long longVal;
+ long long longVal;
- if (json_get_long_value_for_key(root, WD_JSON_KEY_VALUE_DATA, &longVal))
+ if (json_get_llong_value_for_key(root, WD_JSON_KEY_VALUE_DATA, &longVal))
{
ereport(WARNING,
(errmsg("get runtime variable value from watchdog failed"),
{
int len;
- len = snprintf(str, maxlen, "tv_sec=%ld tv_usec=%ld from=%s",
- pkt->send_time.tv_sec, pkt->send_time.tv_usec, pkt->from);
+ len = snprintf(str, maxlen, "tv_sec=%lld tv_usec=%lld from=%s",
+ (long long)pkt->send_time.tv_sec, (long long)pkt->send_time.tv_usec, pkt->from);
return len;
}
{
json_value *root = NULL;
char *ptr;
+ long long longVal;
WatchdogNode *wdNode = palloc0(sizeof(WatchdogNode));
root = json_parse(json_data, data_len);
if (root == NULL || root->type != json_object)
goto ERROR_EXIT;
- if (json_get_long_value_for_key(root, "StartupTimeSecs", &wdNode->startup_time.tv_sec))
+ if (json_get_llong_value_for_key(root, "StartupTimeSecs", &longVal))
{
bool escalated;
- long seconds_since_node_startup;
- long seconds_since_current_state;
+ long long seconds_since_node_startup;
+ long long seconds_since_current_state;
struct timeval current_time;
+ wdNode->startup_time.tv_sec = longVal;
gettimeofday(¤t_time, NULL);
/* The new version does not have StartupTimeSecs Key */
- if (json_get_long_value_for_key(root, "SecondsSinceStartup", &seconds_since_node_startup))
+ if (json_get_llong_value_for_key(root, "SecondsSinceStartup", &seconds_since_node_startup))
goto ERROR_EXIT;
- if (json_get_long_value_for_key(root, "SecondsSinceCurrentState", &seconds_since_current_state))
+ if (json_get_llong_value_for_key(root, "SecondsSinceCurrentState", &seconds_since_current_state))
goto ERROR_EXIT;
if (json_get_bool_value_for_key(root, "Escalated", &escalated))
goto ERROR_EXIT;
bool
parse_beacon_message_json(char *json_data, int data_len,
int *state,
- long *seconds_since_node_startup,
- long *seconds_since_current_state,
+ long long *seconds_since_node_startup,
+ long long *seconds_since_current_state,
int *quorumStatus,
int *standbyNodesCount,
bool *escalated)
if (json_get_int_value_for_key(root, "State", state))
goto ERROR_EXIT;
- if (json_get_long_value_for_key(root, "SecondsSinceStartup", seconds_since_node_startup))
+ if (json_get_llong_value_for_key(root, "SecondsSinceStartup", seconds_since_node_startup))
goto ERROR_EXIT;
- if (json_get_long_value_for_key(root, "SecondsSinceCurrentState", seconds_since_current_state))
+ if (json_get_llong_value_for_key(root, "SecondsSinceCurrentState", seconds_since_current_state))
goto ERROR_EXIT;
if (json_get_bool_value_for_key(root, "Escalated", escalated))
goto ERROR_EXIT;