From: Tatsuo Ishii Date: Tue, 27 May 2025 10:19:57 +0000 (+0900) Subject: Revert "Replace random() with pg_prng random function." X-Git-Url: http://git.postgresql.org/gitweb/static/gitweb.js?a=commitdiff_plain;h=a98be3837c93a97e17c75e840fbe509f571609e2;p=pgpool2.git Revert "Replace random() with pg_prng random function." This reverts commit 66fcd561d74c8f00326bad94300053bd7ea13566. It was accidentally committed. --- diff --git a/src/Makefile.am b/src/Makefile.am index 56f4121c4..efc11cb68 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -66,8 +66,7 @@ pgpool_SOURCES = main/main.c \ utils/pool_health_check_stats.c \ utils/psqlscan.l \ utils/pgstrcasecmp.c \ - utils/pg_strong_random.c \ - utils/pg_prng.c + utils/pg_strong_random.c utils/psqlscan.c: utils/psqlscan.l $(LEX) -o'utils/psqlscan.c' $< diff --git a/src/include/pool_type.h b/src/include/pool_type.h index 03eac9bb4..43f29a595 100644 --- a/src/include/pool_type.h +++ b/src/include/pool_type.h @@ -6,7 +6,7 @@ * pgpool: a language independent connection pool server for PostgreSQL * written by Tatsuo Ishii * - * Copyright (c) 2003-2025 PgPool Global Development Group + * Copyright (c) 2003-2015 PgPool Global Development Group * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby @@ -222,12 +222,6 @@ typedef uint8 bits8; /* >= 8 bits */ typedef uint16 bits16; /* >= 16 bits */ typedef uint32 bits32; /* >= 32 bits */ -/* - * 64-bit integers - */ -#define INT64CONST(x) INT64_C(x) -#define UINT64CONST(x) UINT64_C(x) - /* * stdint.h limits aren't guaranteed to be present and aren't guaranteed to * have compatible types with our fixed width types. So just define our own. diff --git a/src/main/pgpool_main.c b/src/main/pgpool_main.c index 25298eb87..d74cf12b2 100644 --- a/src/main/pgpool_main.c +++ b/src/main/pgpool_main.c @@ -210,6 +210,8 @@ volatile User1SignalSlot *user1SignalSlot = NULL; /* User 1 signal slot on * shmem */ int current_child_process_count; +struct timeval random_start_time; + /* * To track health check process ids */ @@ -301,6 +303,9 @@ PgpoolMain(bool discard_status, bool clear_memcache_oidmaps) */ volatile bool first = true; + /* For PostmasterRandom */ + gettimeofday(&random_start_time, NULL); + processState = INITIALIZING; /* diff --git a/src/pcp_con/pcp_worker.c b/src/pcp_con/pcp_worker.c index a5b88a898..de2658d5e 100644 --- a/src/pcp_con/pcp_worker.c +++ b/src/pcp_con/pcp_worker.c @@ -4,7 +4,7 @@ * pgpool: a language independent connection pool server for PostgreSQL * written by Tatsuo Ishii * - * Copyright (c) 2003-2025 PgPool Global Development Group + * Copyright (c) 2003-2024 PgPool Global Development Group * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby @@ -112,6 +112,7 @@ pcp_worker_main(int port) char salt[4]; int random_salt = 0; + struct timeval uptime; char tos; int rsize; @@ -121,6 +122,9 @@ pcp_worker_main(int port) /* Identify myself via ps */ init_ps_display("", "", "", ""); + gettimeofday(&uptime, NULL); + srandom((unsigned int) (getpid() ^ uptime.tv_usec)); + /* set up signal handlers */ signal(SIGTERM, die); signal(SIGINT, die); diff --git a/src/protocol/child.c b/src/protocol/child.c index 17585bb79..53a4cce68 100644 --- a/src/protocol/child.c +++ b/src/protocol/child.c @@ -5,7 +5,7 @@ * pgpool: a language independent connection pool server for PostgreSQL * written by Tatsuo Ishii * - * Copyright (c) 2003-2025 PgPool Global Development Group + * Copyright (c) 2003-2024 PgPool Global Development Group * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby @@ -49,7 +49,6 @@ #include "pool_config_variables.h" #include "utils/palloc.h" #include "utils/memutils.h" -#include "utils/pg_prng.h" #include "utils/pool_ssl.h" #include "utils/pool_ipc.h" #include "utils/pool_relcache.h" @@ -102,9 +101,6 @@ static int opt_sort(const void *a, const void *b); static bool unix_fds_not_isset(int* fds, int num_unix_fds, fd_set* opt); -static void initialize_prng(void); -static TimestampTz GetCurrentTimestamp(void); - /* * Non 0 means SIGTERM (smart shutdown) or SIGINT (fast shutdown) has arrived */ @@ -149,12 +145,6 @@ bool stop_now = false; */ static bool connection_pool_initialized = false; -/* - * prng state - */ -pg_prng_state prng_state_d; -pg_prng_state *prng_state; - /* * child main loop */ @@ -163,6 +153,8 @@ do_child(int *fds) { sigjmp_buf local_sigjmp_buf; POOL_CONNECTION_POOL *volatile backend = NULL; + struct timeval now; + struct timezone tz; /* counter for child_max_connections. "volatile" declaration is necessary * so that this is counted up even if long jump is issued due to @@ -223,8 +215,13 @@ do_child(int *fds) pool_init_process_context(); /* initialize random seed */ - prng_state = &prng_state_d; - initialize_prng(); + gettimeofday(&now, &tz); + +#if defined(sun) || defined(__sun) + srand((unsigned int) now.tv_usec); +#else + srandom((unsigned int) now.tv_usec); +#endif /* initialize connection pool */ if (pool_init_cp()) @@ -2222,55 +2219,3 @@ set_process_status(ProcessStatus status) { pool_get_my_process_info()->status = status; } - -/* - * imported from backend/utils/adt/timestamp.c - */ -/* - * GetCurrentTimestamp -- get the current operating system time - * - * Result is in the form of a TimestampTz value, and is expressed to the - * full precision of the gettimeofday() syscall - */ -static TimestampTz -GetCurrentTimestamp(void) -{ - TimestampTz result; - struct timeval tp; - - gettimeofday(&tp, NULL); - - result = (TimestampTz) tp.tv_sec - - ((POSTGRES_EPOCH_JDATE - UNIX_EPOCH_JDATE) * SECS_PER_DAY); - result = (result * USECS_PER_SEC) + tp.tv_usec; - - return result; -} - -/* - * imported from backend/utils/adt/pseudorandomfuncs.c - * and modified. - */ -/* - * initialize_prng() - - * - * Initialize (seed) the PRNG, if not done yet in this process. - */ -static void -initialize_prng(void) -{ - /* - * If possible, seed the PRNG using high-quality random bits. Should - * that fail for some reason, we fall back on a lower-quality seed - * based on current time and PID. - */ - if (!pg_prng_strong_seed(prng_state)) - { - TimestampTz now = GetCurrentTimestamp(); - uint64 iseed; - - /* Mix the PID with the most predictable bits of the timestamp */ - iseed = (uint64) now ^ ((uint64) getpid() << 32); - pg_prng_seed(prng_state, iseed); - } -} diff --git a/src/protocol/pool_pg_utils.c b/src/protocol/pool_pg_utils.c index 7f06628aa..25942b6cc 100644 --- a/src/protocol/pool_pg_utils.c +++ b/src/protocol/pool_pg_utils.c @@ -3,7 +3,7 @@ * pgpool: a language independent connection pool server for PostgreSQL * written by Tatsuo Ishii * - * Copyright (c) 2003-2025 PgPool Global Development Group + * Copyright (c) 2003-2020 PgPool Global Development Group * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby @@ -28,7 +28,6 @@ #include "protocol/pool_connection_pool.h" #include "utils/palloc.h" #include "utils/memutils.h" -#include "utils/pg_prng.h" #include "utils/pool_ipc.h" #include "utils/pool_stream.h" #include "utils/pool_ssl.h" @@ -45,8 +44,6 @@ static void free_persistent_db_connection_memory(POOL_CONNECTION_POOL_SLOT * cp) static void si_enter_critical_region(void); static void si_leave_critical_region(void); -extern pg_prng_state *prng_state; - /* * create a persistent connection */ @@ -327,8 +324,11 @@ select_load_balancing_node(void) */ int suggested_node_id = -2; - r = pg_prng_double(prng_state); -// elog(LOG, "pg_prng_double: %f", r); +#if defined(sun) || defined(__sun) + r = (((double) rand()) / RAND_MAX); +#else + r = (((double) random()) / RAND_MAX); +#endif /* * Check user_redirect_preference_list @@ -490,7 +490,11 @@ select_load_balancing_node(void) } } - r = pg_prng_double(prng_state) * total_weight; +#if defined(sun) || defined(__sun) + r = (((double) rand()) / RAND_MAX) * total_weight; +#else + r = (((double) random()) / RAND_MAX) * total_weight; +#endif selected_slot = PRIMARY_NODE_ID; total_weight = 0.0; @@ -569,7 +573,11 @@ select_load_balancing_node(void) } } - r = pg_prng_double(prng_state) * total_weight; +#if defined(sun) || defined(__sun) + r = (((double) rand()) / RAND_MAX) * total_weight; +#else + r = (((double) random()) / RAND_MAX) * total_weight; +#endif total_weight = 0.0; for (i = 0; i < NUM_BACKENDS; i++) @@ -634,7 +642,11 @@ select_load_balancing_node(void) } } - r = pg_prng_double(prng_state) * total_weight; +#if defined(sun) || defined(__sun) + r = (((double) rand()) / RAND_MAX) * total_weight; +#else + r = (((double) random()) / RAND_MAX) * total_weight; +#endif selected_slot = PRIMARY_NODE_ID; diff --git a/src/utils/pg_prng.c b/src/utils/pg_prng.c deleted file mode 100644 index 7ca3ab082..000000000 --- a/src/utils/pg_prng.c +++ /dev/null @@ -1,333 +0,0 @@ -/* - * This file was imported from PostgreSQL source code - * (src/common/pg_prng.c). - */ - -/*------------------------------------------------------------------------- - * - * Pseudo-Random Number Generator - * - * We use Blackman and Vigna's xoroshiro128** 1.0 algorithm - * to have a small, fast PRNG suitable for generating reasonably - * good-quality 64-bit data. This should not be considered - * cryptographically strong, however. - * - * About these generators: https://prng.di.unimi.it/ - * See also https://en.wikipedia.org/wiki/List_of_random_number_generators - * - * Portions Copyright (c) 2025, PgPool Global Development Group - * Portions Copyright (c) 2021-2025, PostgreSQL Global Development Group - * - * src/common/pg_prng.c - * - *------------------------------------------------------------------------- - */ - -#include "pool.h" - -#include - -#include "utils/pg_prng.h" - -/* X/Open (XSI) requires to provide M_PI, but core POSIX does not */ -#ifndef M_PI -#define M_PI 3.14159265358979323846 -#endif - - -/* process-wide state vector */ -pg_prng_state pg_global_prng_state; - -/* ignore likely/unlikely */ -#define likely -#define unlikely - -/* - * 64-bit rotate left - */ -static inline uint64 -rotl(uint64 x, int bits) -{ - return (x << bits) | (x >> (64 - bits)); -} - -/* - * The basic xoroshiro128** algorithm. - * Generates and returns a 64-bit uniformly distributed number, - * updating the state vector for next time. - * - * Note: the state vector must not be all-zeroes, as that is a fixed point. - */ -static uint64 -xoroshiro128ss(pg_prng_state *state) -{ - uint64 s0 = state->s0, - sx = state->s1 ^ s0, - val = rotl(s0 * 5, 7) * 9; - - /* update state */ - state->s0 = rotl(s0, 24) ^ sx ^ (sx << 16); - state->s1 = rotl(sx, 37); - - return val; -} - -/* - * We use this generator just to fill the xoroshiro128** state vector - * from a 64-bit seed. - */ -static uint64 -splitmix64(uint64 *state) -{ - /* state update */ - uint64 val = (*state += UINT64CONST(0x9E3779B97f4A7C15)); - - /* value extraction */ - val = (val ^ (val >> 30)) * UINT64CONST(0xBF58476D1CE4E5B9); - val = (val ^ (val >> 27)) * UINT64CONST(0x94D049BB133111EB); - - return val ^ (val >> 31); -} - -/* - * Initialize the PRNG state from a 64-bit integer, - * taking care that we don't produce all-zeroes. - */ -void -pg_prng_seed(pg_prng_state *state, uint64 seed) -{ - state->s0 = splitmix64(&seed); - state->s1 = splitmix64(&seed); - /* Let's just make sure we didn't get all-zeroes */ - (void) pg_prng_seed_check(state); -} - -/* - * Initialize the PRNG state from a double in the range [-1.0, 1.0], - * taking care that we don't produce all-zeroes. - */ -void -pg_prng_fseed(pg_prng_state *state, double fseed) -{ - /* Assume there's about 52 mantissa bits; the sign contributes too. */ - int64 seed = ((double) ((UINT64CONST(1) << 52) - 1)) * fseed; - - pg_prng_seed(state, (uint64) seed); -} - -/* - * Validate a PRNG seed value. - */ -bool -pg_prng_seed_check(pg_prng_state *state) -{ - /* - * If the seeding mechanism chanced to produce all-zeroes, insert - * something nonzero. Anything would do; use Knuth's LCG parameters. - */ - if (unlikely(state->s0 == 0 && state->s1 == 0)) - { - state->s0 = UINT64CONST(0x5851F42D4C957F2D); - state->s1 = UINT64CONST(0x14057B7EF767814F); - } - - /* As a convenience for the pg_prng_strong_seed macro, return true */ - return true; -} - -/* - * Select a random uint64 uniformly from the range [0, PG_UINT64_MAX]. - */ -uint64 -pg_prng_uint64(pg_prng_state *state) -{ - return xoroshiro128ss(state); -} - -/* - * We ignore some functions because we do not port pg_bitutils.c (yet). - */ -#ifdef NOT_USED -/* - * Select a random uint64 uniformly from the range [rmin, rmax]. - * If the range is empty, rmin is always produced. - */ -uint64 -pg_prng_uint64_range(pg_prng_state *state, uint64 rmin, uint64 rmax) -{ - uint64 val; - - if (likely(rmax > rmin)) - { - /* - * Use bitmask rejection method to generate an offset in 0..range. - * Each generated val is less than twice "range", so on average we - * should not have to iterate more than twice. - */ - uint64 range = rmax - rmin; - uint32 rshift = 63 - pg_leftmost_one_pos64(range); - - do - { - val = xoroshiro128ss(state) >> rshift; - } while (val > range); - } - else - val = 0; - - return rmin + val; -} - -/* - * Select a random int64 uniformly from the range [PG_INT64_MIN, PG_INT64_MAX]. - */ -int64 -pg_prng_int64(pg_prng_state *state) -{ - return (int64) xoroshiro128ss(state); -} -#endif - -/* - * Select a random int64 uniformly from the range [0, PG_INT64_MAX]. - */ -int64 -pg_prng_int64p(pg_prng_state *state) -{ - return (int64) (xoroshiro128ss(state) & UINT64CONST(0x7FFFFFFFFFFFFFFF)); -} - -#ifdef NOT_USED -/* - * Select a random int64 uniformly from the range [rmin, rmax]. - * If the range is empty, rmin is always produced. - */ -int64 -pg_prng_int64_range(pg_prng_state *state, int64 rmin, int64 rmax) -{ - int64 val; - - if (likely(rmax > rmin)) - { - uint64 uval; - - /* - * Use pg_prng_uint64_range(). Can't simply pass it rmin and rmax, - * since (uint64) rmin will be larger than (uint64) rmax if rmin < 0. - */ - uval = (uint64) rmin + - pg_prng_uint64_range(state, 0, (uint64) rmax - (uint64) rmin); - - /* - * Safely convert back to int64, avoiding implementation-defined - * behavior for values larger than PG_INT64_MAX. Modern compilers - * will reduce this to a simple assignment. - */ - if (uval > PG_INT64_MAX) - val = (int64) (uval - PG_INT64_MIN) + PG_INT64_MIN; - else - val = (int64) uval; - } - else - val = rmin; - - return val; -} -#endif - -/* - * Select a random uint32 uniformly from the range [0, PG_UINT32_MAX]. - */ -uint32 -pg_prng_uint32(pg_prng_state *state) -{ - /* - * Although xoroshiro128** is not known to have any weaknesses in - * randomness of low-order bits, we prefer to use the upper bits of its - * result here and below. - */ - uint64 v = xoroshiro128ss(state); - - return (uint32) (v >> 32); -} - -/* - * Select a random int32 uniformly from the range [PG_INT32_MIN, PG_INT32_MAX]. - */ -int32 -pg_prng_int32(pg_prng_state *state) -{ - uint64 v = xoroshiro128ss(state); - - return (int32) (v >> 32); -} - -/* - * Select a random int32 uniformly from the range [0, PG_INT32_MAX]. - */ -int32 -pg_prng_int32p(pg_prng_state *state) -{ - uint64 v = xoroshiro128ss(state); - - return (int32) (v >> 33); -} - -/* - * Select a random double uniformly from the range [0.0, 1.0). - * - * Note: if you want a result in the range (0.0, 1.0], the standard way - * to get that is "1.0 - pg_prng_double(state)". - */ -double -pg_prng_double(pg_prng_state *state) -{ - uint64 v = xoroshiro128ss(state); - - /* - * As above, assume there's 52 mantissa bits in a double. This result - * could round to 1.0 if double's precision is less than that; but we - * assume IEEE float arithmetic elsewhere in Postgres, so this seems OK. - */ - return ldexp((double) (v >> (64 - 52)), -52); -} - -/* - * Select a random double from the normal distribution with - * mean = 0.0 and stddev = 1.0. - * - * To get a result from a different normal distribution use - * STDDEV * pg_prng_double_normal() + MEAN - * - * Uses https://en.wikipedia.org/wiki/Box%E2%80%93Muller_transform - */ -double -pg_prng_double_normal(pg_prng_state *state) -{ - double u1, - u2, - z0; - - /* - * pg_prng_double generates [0, 1), but for the basic version of the - * Box-Muller transform the two uniformly distributed random numbers are - * expected to be in (0, 1]; in particular we'd better not compute log(0). - */ - u1 = 1.0 - pg_prng_double(state); - u2 = 1.0 - pg_prng_double(state); - - /* Apply Box-Muller transform to get one normal-valued output */ - z0 = sqrt(-2.0 * log(u1)) * sin(2.0 * M_PI * u2); - return z0; -} - -/* - * Select a random boolean value. - */ -bool -pg_prng_bool(pg_prng_state *state) -{ - uint64 v = xoroshiro128ss(state); - - return (bool) (v >> 63); -}