On Wed, Jan 15, 2020 at 03:45:12PM -0800, Jesse Zhang wrote: > On Tue, Jan 14, 2020 at 2:09 PM David Fetter <da...@fetter.org> wrote: > > > The changes in hash AM and SIMPLEHASH do look like a net positive > > > improvement. My biggest cringe might be in pg_bitutils: > > > > > > 1. Is ceil_log2_64 dead code? > > > > Let's call it nascent code. I suspect there are places it could go, if > > I look for them. Also, it seemed silly to have one without the other. > > > > While not absolutely required, I'd like us to find at least one > place and start using it. (Clang also nags at me when we have > unused functions).
Done in the expanded patches attached. > > On Tue, Jan 14, 2020 at 12:21:41PM -0800, Jesse Zhang wrote: > > > 4. It seems like you *really* would like an operation like LZCNT in x86 > > > (first appearing in Haswell) that is well defined on zero input. ISTM > > > the alternatives are: > > > > > > a) Special case 1. That seems straightforward, but the branching cost > > > on a seemingly unlikely condition seems to be a lot of performance > > > loss > > > > > > b) Use architecture specific intrinsic (and possibly with CPUID > > > shenanigans) like __builtin_ia32_lzcnt_u64 on x86 and use the CLZ > > > intrinsic elsewhere. The CLZ GCC intrinsic seems to map to > > > instructions that are well defined on zero in most ISA's other than > > > x86, so maybe we can get away with special-casing x86? > > i. We can detect LZCNT instruction by checking one of the > "extended feature" (EAX=80000001) bits using CPUID. Unlike the > "basic features" (EAX=1), extended feature flags have been more > vendor-specific, but fortunately it seems that the feature bit > for LZCNT is the same [1][2]. > > ii. We'll most likely still need to provide a fallback > implementation for processors that don't have LZCNT (either > because they are from a different vendor, or an older Intel/AMD > processor). I wonder if simply checking for 1 is "good enough". > Maybe a micro benchmark is in order? I'm not sure how I'd run one on the architectures we support. What I've done here is generalize our implementation to be basically like LZCNT and TZCNT at the cost of a brief branch that might go away at runtime. > 2. (My least favorite) use inline asm (a la our popcount > implementation). Yeah, I'd like to fix that, but I kept the scope of this one relatively narrow. Best, David. -- David Fetter <david(at)fetter(dot)org> http://fetter.org/ Phone: +1 415 235 3778 Remember to vote! Consider donating to Postgres: http://www.postgresql.org/about/donate
>From 5fcaa74146206e4de05ca8cbd863aca20bba94bf Mon Sep 17 00:00:00 2001 From: David Fetter <da...@fetter.org> Date: Wed, 29 Jan 2020 02:09:59 -0800 Subject: [PATCH v4 1/2] de-long-ify To: hackers MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="------------2.24.1" This is a multi-part message in MIME format. --------------2.24.1 Content-Type: text/plain; charset=UTF-8; format=fixed Content-Transfer-Encoding: 8bit diff --git a/src/backend/access/gist/gistbuildbuffers.c b/src/backend/access/gist/gistbuildbuffers.c index 4b562d8d3f..482a569814 100644 --- a/src/backend/access/gist/gistbuildbuffers.c +++ b/src/backend/access/gist/gistbuildbuffers.c @@ -34,11 +34,11 @@ static void gistPlaceItupToPage(GISTNodeBufferPage *pageBuffer, IndexTuple item); static void gistGetItupFromPage(GISTNodeBufferPage *pageBuffer, IndexTuple *item); -static long gistBuffersGetFreeBlock(GISTBuildBuffers *gfbb); -static void gistBuffersReleaseBlock(GISTBuildBuffers *gfbb, long blocknum); +static uint64 gistBuffersGetFreeBlock(GISTBuildBuffers *gfbb); +static void gistBuffersReleaseBlock(GISTBuildBuffers *gfbb, uint64 blocknum); -static void ReadTempFileBlock(BufFile *file, long blknum, void *ptr); -static void WriteTempFileBlock(BufFile *file, long blknum, void *ptr); +static void ReadTempFileBlock(BufFile *file, uint64 blknum, void *ptr); +static void WriteTempFileBlock(BufFile *file, uint64 blknum, void *ptr); /* @@ -64,7 +64,7 @@ gistInitBuildBuffers(int pagesPerBuffer, int levelStep, int maxLevel) /* Initialize free page management. */ gfbb->nFreeBlocks = 0; gfbb->freeBlocksLen = 32; - gfbb->freeBlocks = (long *) palloc(gfbb->freeBlocksLen * sizeof(long)); + gfbb->freeBlocks = (int64 *) palloc(gfbb->freeBlocksLen * sizeof(int64)); /* * Current memory context will be used for all in-memory data structures @@ -469,7 +469,7 @@ gistPopItupFromNodeBuffer(GISTBuildBuffers *gfbb, GISTNodeBuffer *nodeBuffer, /* * Select a currently unused block for writing to. */ -static long +static uint64 gistBuffersGetFreeBlock(GISTBuildBuffers *gfbb) { /* @@ -487,7 +487,7 @@ gistBuffersGetFreeBlock(GISTBuildBuffers *gfbb) * Return a block# to the freelist. */ static void -gistBuffersReleaseBlock(GISTBuildBuffers *gfbb, long blocknum) +gistBuffersReleaseBlock(GISTBuildBuffers *gfbb, uint64 blocknum) { int ndx; @@ -495,9 +495,9 @@ gistBuffersReleaseBlock(GISTBuildBuffers *gfbb, long blocknum) if (gfbb->nFreeBlocks >= gfbb->freeBlocksLen) { gfbb->freeBlocksLen *= 2; - gfbb->freeBlocks = (long *) repalloc(gfbb->freeBlocks, + gfbb->freeBlocks = (int64 *) repalloc(gfbb->freeBlocks, gfbb->freeBlocksLen * - sizeof(long)); + sizeof(uint64)); } /* Add blocknum to array */ @@ -755,7 +755,7 @@ gistRelocateBuildBuffersOnSplit(GISTBuildBuffers *gfbb, GISTSTATE *giststate, */ static void -ReadTempFileBlock(BufFile *file, long blknum, void *ptr) +ReadTempFileBlock(BufFile *file, uint64 blknum, void *ptr) { if (BufFileSeekBlock(file, blknum) != 0) elog(ERROR, "could not seek temporary file: %m"); @@ -764,7 +764,7 @@ ReadTempFileBlock(BufFile *file, long blknum, void *ptr) } static void -WriteTempFileBlock(BufFile *file, long blknum, void *ptr) +WriteTempFileBlock(BufFile *file, uint64 blknum, void *ptr) { if (BufFileSeekBlock(file, blknum) != 0) elog(ERROR, "could not seek temporary file: %m"); diff --git a/src/backend/executor/spi.c b/src/backend/executor/spi.c index c46764bf42..4fc478640a 100644 --- a/src/backend/executor/spi.c +++ b/src/backend/executor/spi.c @@ -70,7 +70,7 @@ static int _SPI_pquery(QueryDesc *queryDesc, bool fire_triggers, uint64 tcount); static void _SPI_error_callback(void *arg); static void _SPI_cursor_operation(Portal portal, - FetchDirection direction, long count, + FetchDirection direction, uint64 count, DestReceiver *dest); static SPIPlanPtr _SPI_make_plan_non_temp(SPIPlanPtr plan); @@ -493,7 +493,7 @@ SPI_inside_nonatomic_context(void) /* Parse, plan, and execute a query string */ int -SPI_execute(const char *src, bool read_only, long tcount) +SPI_execute(const char *src, bool read_only, int64 tcount) { _SPI_plan plan; int res; @@ -521,7 +521,7 @@ SPI_execute(const char *src, bool read_only, long tcount) /* Obsolete version of SPI_execute */ int -SPI_exec(const char *src, long tcount) +SPI_exec(const char *src, int64 tcount) { return SPI_execute(src, false, tcount); } @@ -529,7 +529,7 @@ SPI_exec(const char *src, long tcount) /* Execute a previously prepared plan */ int SPI_execute_plan(SPIPlanPtr plan, Datum *Values, const char *Nulls, - bool read_only, long tcount) + bool read_only, int64 tcount) { int res; @@ -555,7 +555,7 @@ SPI_execute_plan(SPIPlanPtr plan, Datum *Values, const char *Nulls, /* Obsolete version of SPI_execute_plan */ int -SPI_execp(SPIPlanPtr plan, Datum *Values, const char *Nulls, long tcount) +SPI_execp(SPIPlanPtr plan, Datum *Values, const char *Nulls, int64 tcount) { return SPI_execute_plan(plan, Values, Nulls, false, tcount); } @@ -563,7 +563,7 @@ SPI_execp(SPIPlanPtr plan, Datum *Values, const char *Nulls, long tcount) /* Execute a previously prepared plan */ int SPI_execute_plan_with_paramlist(SPIPlanPtr plan, ParamListInfo params, - bool read_only, long tcount) + bool read_only, int64 tcount) { int res; @@ -599,7 +599,7 @@ int SPI_execute_snapshot(SPIPlanPtr plan, Datum *Values, const char *Nulls, Snapshot snapshot, Snapshot crosscheck_snapshot, - bool read_only, bool fire_triggers, long tcount) + bool read_only, bool fire_triggers, int64 tcount) { int res; @@ -633,7 +633,7 @@ int SPI_execute_with_args(const char *src, int nargs, Oid *argtypes, Datum *Values, const char *Nulls, - bool read_only, long tcount) + bool read_only, int64 tcount) { int res; _SPI_plan plan; @@ -1530,7 +1530,7 @@ SPI_cursor_find(const char *name) * Fetch rows in a cursor */ void -SPI_cursor_fetch(Portal portal, bool forward, long count) +SPI_cursor_fetch(Portal portal, bool forward, int64 count) { _SPI_cursor_operation(portal, forward ? FETCH_FORWARD : FETCH_BACKWARD, count, @@ -1545,7 +1545,7 @@ SPI_cursor_fetch(Portal portal, bool forward, long count) * Move in a cursor */ void -SPI_cursor_move(Portal portal, bool forward, long count) +SPI_cursor_move(Portal portal, bool forward, int64 count) { _SPI_cursor_operation(portal, forward ? FETCH_FORWARD : FETCH_BACKWARD, count, @@ -1559,7 +1559,7 @@ SPI_cursor_move(Portal portal, bool forward, long count) * Fetch rows in a scrollable cursor */ void -SPI_scroll_cursor_fetch(Portal portal, FetchDirection direction, long count) +SPI_scroll_cursor_fetch(Portal portal, FetchDirection direction, int64 count) { _SPI_cursor_operation(portal, direction, count, @@ -1574,7 +1574,7 @@ SPI_scroll_cursor_fetch(Portal portal, FetchDirection direction, long count) * Move in a scrollable cursor */ void -SPI_scroll_cursor_move(Portal portal, FetchDirection direction, long count) +SPI_scroll_cursor_move(Portal portal, FetchDirection direction, int64 count) { _SPI_cursor_operation(portal, direction, count, None_Receiver); } @@ -2567,7 +2567,7 @@ _SPI_error_callback(void *arg) * Do a FETCH or MOVE in a cursor */ static void -_SPI_cursor_operation(Portal portal, FetchDirection direction, long count, +_SPI_cursor_operation(Portal portal, FetchDirection direction, uint64 count, DestReceiver *dest) { uint64 nfetched; diff --git a/src/backend/storage/file/buffile.c b/src/backend/storage/file/buffile.c index 35e8f12e62..db73a9f159 100644 --- a/src/backend/storage/file/buffile.c +++ b/src/backend/storage/file/buffile.c @@ -749,7 +749,7 @@ BufFileTell(BufFile *file, int *fileno, off_t *offset) * impossible seek is attempted. */ int -BufFileSeekBlock(BufFile *file, long blknum) +BufFileSeekBlock(BufFile *file, uint64 blknum) { return BufFileSeek(file, (int) (blknum / BUFFILE_SEG_SIZE), @@ -760,13 +760,11 @@ BufFileSeekBlock(BufFile *file, long blknum) #ifdef NOT_USED /* * BufFileTellBlock --- block-oriented tell - * - * Any fractional part of a block in the current seek position is ignored. */ -long +uint64 BufFileTellBlock(BufFile *file) { - long blknum; + uint64 blknum; blknum = (file->curOffset + file->pos) / BLCKSZ; blknum += file->curFile * BUFFILE_SEG_SIZE; @@ -820,10 +818,10 @@ BufFileSize(BufFile *file) * begins. Caller should apply this as an offset when working off block * positions that are in terms of the original BufFile space. */ -long +uint64 BufFileAppend(BufFile *target, BufFile *source) { - long startBlock = target->numFiles * BUFFILE_SEG_SIZE; + uint64 startBlock = target->numFiles * BUFFILE_SEG_SIZE; int newNumFiles = target->numFiles + source->numFiles; int i; diff --git a/src/backend/storage/ipc/latch.c b/src/backend/storage/ipc/latch.c index d677ffbda7..29219690f8 100644 --- a/src/backend/storage/ipc/latch.c +++ b/src/backend/storage/ipc/latch.c @@ -328,7 +328,7 @@ DisownLatch(Latch *latch) * function returns immediately. * * The "timeout" is given in milliseconds. It must be >= 0 if WL_TIMEOUT flag - * is given. Although it is declared as "long", we don't actually support + * is given. Although it is declared as "int64", we don't actually support * timeouts longer than INT_MAX milliseconds. Note that some extra overhead * is incurred when WL_TIMEOUT is given, so avoid using a timeout if possible. * @@ -341,7 +341,7 @@ DisownLatch(Latch *latch) * we return all of them in one call, but we will return at least one. */ int -WaitLatch(Latch *latch, int wakeEvents, long timeout, +WaitLatch(Latch *latch, int wakeEvents, int64 timeout, uint32 wait_event_info) { return WaitLatchOrSocket(latch, wakeEvents, PGINVALID_SOCKET, timeout, @@ -367,7 +367,7 @@ WaitLatch(Latch *latch, int wakeEvents, long timeout, */ int WaitLatchOrSocket(Latch *latch, int wakeEvents, pgsocket sock, - long timeout, uint32 wait_event_info) + int64 timeout, uint32 wait_event_info) { int ret = 0; int rc; @@ -950,14 +950,14 @@ WaitEventAdjustWin32(WaitEventSet *set, WaitEvent *event) * values associated with the registered event. */ int -WaitEventSetWait(WaitEventSet *set, long timeout, +WaitEventSetWait(WaitEventSet *set, int64 timeout, WaitEvent *occurred_events, int nevents, uint32 wait_event_info) { int returned_events = 0; instr_time start_time; instr_time cur_time; - long cur_timeout = -1; + int64 cur_timeout = -1; Assert(nevents > 0); @@ -1042,7 +1042,7 @@ WaitEventSetWait(WaitEventSet *set, long timeout, { INSTR_TIME_SET_CURRENT(cur_time); INSTR_TIME_SUBTRACT(cur_time, start_time); - cur_timeout = timeout - (long) INSTR_TIME_GET_MILLISEC(cur_time); + cur_timeout = timeout - INSTR_TIME_GET_MILLISEC(cur_time); if (cur_timeout <= 0) break; } diff --git a/src/backend/storage/ipc/shmem.c b/src/backend/storage/ipc/shmem.c index 2892a573e4..582c63a5e6 100644 --- a/src/backend/storage/ipc/shmem.c +++ b/src/backend/storage/ipc/shmem.c @@ -335,8 +335,8 @@ InitShmemIndex(void) */ HTAB * ShmemInitHash(const char *name, /* table string name for shmem index */ - long init_size, /* initial table size */ - long max_size, /* max size of the table */ + uint64 init_size, /* initial table size */ + uint64 max_size, /* max size of the table */ HASHCTL *infoP, /* info about key and bucket size */ int hash_flags) /* info about infoP */ { diff --git a/src/backend/storage/lmgr/condition_variable.c b/src/backend/storage/lmgr/condition_variable.c index 37b6a4eecd..43c662aaeb 100644 --- a/src/backend/storage/lmgr/condition_variable.c +++ b/src/backend/storage/lmgr/condition_variable.c @@ -129,10 +129,10 @@ ConditionVariableSleep(ConditionVariable *cv, uint32 wait_event_info) * See ConditionVariableSleep() for general usage. */ bool -ConditionVariableTimedSleep(ConditionVariable *cv, long timeout, +ConditionVariableTimedSleep(ConditionVariable *cv, int64 timeout, uint32 wait_event_info) { - long cur_timeout = -1; + int64 cur_timeout = -1; instr_time start_time; instr_time cur_time; @@ -217,7 +217,7 @@ ConditionVariableTimedSleep(ConditionVariable *cv, long timeout, { INSTR_TIME_SET_CURRENT(cur_time); INSTR_TIME_SUBTRACT(cur_time, start_time); - cur_timeout = timeout - (long) INSTR_TIME_GET_MILLISEC(cur_time); + cur_timeout = timeout - (int64) INSTR_TIME_GET_MILLISEC(cur_time); /* Have we crossed the timeout threshold? */ if (cur_timeout <= 0) diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c index 0a6f80963b..9bb9c1fda9 100644 --- a/src/backend/tcop/postgres.c +++ b/src/backend/tcop/postgres.c @@ -109,7 +109,7 @@ int PostAuthDelay = 0; */ /* max_stack_depth converted to bytes for speed of checking */ -static long max_stack_depth_bytes = 100 * 1024L; +static uint64 max_stack_depth_bytes = 100 * 1024UL; /* * Stack base pointer -- initialized by PostmasterMain and inherited by @@ -2016,7 +2016,7 @@ exec_bind_message(StringInfo input_message) * Process an "Execute" message for a portal */ static void -exec_execute_message(const char *portal_name, long max_rows) +exec_execute_message(const char *portal_name, uint64 max_rows) { CommandDest dest; DestReceiver *receiver; @@ -2302,7 +2302,7 @@ check_log_duration(char *msec_str, bool was_logged) if (log_duration || log_min_duration_sample >= 0 || log_min_duration_statement >= 0 || xact_is_sampled) { - long secs; + int64 secs; int usecs; int msecs; bool exceeded_duration; @@ -3302,12 +3302,12 @@ bool stack_is_too_deep(void) { char stack_top_loc; - long stack_depth; + int64 stack_depth; /* * Compute distance from reference point to my local variables */ - stack_depth = (long) (stack_base_ptr - &stack_top_loc); + stack_depth = (int64) (stack_base_ptr - &stack_top_loc); /* * Take abs value, since stacks grow up on some machines, down on others @@ -3336,7 +3336,7 @@ stack_is_too_deep(void) * Note we assume that the same max_stack_depth applies to both stacks. */ #if defined(__ia64__) || defined(__ia64) - stack_depth = (long) (ia64_get_bsp() - register_stack_base_ptr); + stack_depth = (int64) (ia64_get_bsp() - register_stack_base_ptr); if (stack_depth > max_stack_depth_bytes && register_stack_base_ptr != NULL) @@ -3350,8 +3350,8 @@ stack_is_too_deep(void) bool check_max_stack_depth(int *newval, void **extra, GucSource source) { - long newval_bytes = *newval * 1024L; - long stack_rlimit = get_stack_depth_rlimit(); + uint64 newval_bytes = *newval * 1024UL; + uint64 stack_rlimit = get_stack_depth_rlimit(); if (stack_rlimit > 0 && newval_bytes > stack_rlimit - STACK_DEPTH_SLOP) { @@ -3367,7 +3367,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source) void assign_max_stack_depth(int newval, void *extra) { - long newval_bytes = newval * 1024L; + uint64 newval_bytes = newval * 1024UL; max_stack_depth_bytes = newval_bytes; } @@ -4696,7 +4696,7 @@ static void log_disconnections(int code, Datum arg) { Port *port = MyProcPort; - long secs; + int64 secs; int usecs; int msecs; int hours, diff --git a/src/backend/tcop/pquery.c b/src/backend/tcop/pquery.c index 0f5801e046..f519ce7def 100644 --- a/src/backend/tcop/pquery.c +++ b/src/backend/tcop/pquery.c @@ -44,7 +44,7 @@ static void ProcessQuery(PlannedStmt *plan, static void FillPortalStore(Portal portal, bool isTopLevel); static uint64 RunFromStore(Portal portal, ScanDirection direction, uint64 count, DestReceiver *dest); -static uint64 PortalRunSelect(Portal portal, bool forward, long count, +static uint64 PortalRunSelect(Portal portal, bool forward, int64 count, DestReceiver *dest); static void PortalRunUtility(Portal portal, PlannedStmt *pstmt, bool isTopLevel, bool setHoldSnapshot, @@ -55,7 +55,7 @@ static void PortalRunMulti(Portal portal, char *completionTag); static uint64 DoPortalRunFetch(Portal portal, FetchDirection fdirection, - long count, + int64 count, DestReceiver *dest); static void DoPortalRewind(Portal portal); @@ -683,7 +683,7 @@ PortalSetResultFormat(Portal portal, int nFormats, int16 *formats) * suspended due to exhaustion of the count parameter. */ bool -PortalRun(Portal portal, long count, bool isTopLevel, bool run_once, +PortalRun(Portal portal, int64 count, bool isTopLevel, bool run_once, DestReceiver *dest, DestReceiver *altdest, char *completionTag) { @@ -871,7 +871,7 @@ PortalRun(Portal portal, long count, bool isTopLevel, bool run_once, static uint64 PortalRunSelect(Portal portal, bool forward, - long count, + int64 count, DestReceiver *dest) { QueryDesc *queryDesc; @@ -1391,7 +1391,7 @@ PortalRunMulti(Portal portal, uint64 PortalRunFetch(Portal portal, FetchDirection fdirection, - long count, + int64 count, DestReceiver *dest) { uint64 result; @@ -1493,7 +1493,7 @@ PortalRunFetch(Portal portal, static uint64 DoPortalRunFetch(Portal portal, FetchDirection fdirection, - long count, + int64 count, DestReceiver *dest) { bool forward; @@ -1531,7 +1531,7 @@ DoPortalRunFetch(Portal portal, * In practice, if the goal is less than halfway back to the * start, it's better to scan from where we are. * - * Also, if current portalPos is outside the range of "long", + * Also, if current portalPos is outside the range of "int64", * do it the hard way to avoid possible overflow of the count * argument to PortalRunSelect. We must exclude exactly * LONG_MAX, as well, lest the count look like FETCH_ALL. @@ -1549,7 +1549,7 @@ DoPortalRunFetch(Portal portal, } else { - long pos = (long) portal->portalPos; + int64 pos = (int64) portal->portalPos; if (portal->atEnd) pos++; /* need one extra fetch if off end */ diff --git a/src/backend/utils/adt/timestamp.c b/src/backend/utils/adt/timestamp.c index 0b6c9d5ea8..ddd471c059 100644 --- a/src/backend/utils/adt/timestamp.c +++ b/src/backend/utils/adt/timestamp.c @@ -1655,7 +1655,7 @@ timeofday(PG_FUNCTION_ARGS) */ void TimestampDifference(TimestampTz start_time, TimestampTz stop_time, - long *secs, int *microsecs) + int64 *secs, int *microsecs) { TimestampTz diff = stop_time - start_time; @@ -1666,7 +1666,7 @@ TimestampDifference(TimestampTz start_time, TimestampTz stop_time, } else { - *secs = (long) (diff / USECS_PER_SEC); + *secs = (int64) (diff / USECS_PER_SEC); *microsecs = (int) (diff % USECS_PER_SEC); } } diff --git a/src/backend/utils/hash/dynahash.c b/src/backend/utils/hash/dynahash.c index c9026f0e1a..43d5584eab 100644 --- a/src/backend/utils/hash/dynahash.c +++ b/src/backend/utils/hash/dynahash.c @@ -141,7 +141,7 @@ typedef HASHBUCKET *HASHSEGMENT; typedef struct { slock_t mutex; /* spinlock for this freelist */ - long nentries; /* number of entries in associated buckets */ + uint64 nentries; /* number of entries in associated buckets */ HASHELEMENT *freeList; /* chain of free elements */ } FreeListData; @@ -169,8 +169,8 @@ struct HASHHDR /* These fields can change, but not in a partitioned table */ /* Also, dsize can't change in a shared table, even if unpartitioned */ - long dsize; /* directory size */ - long nsegs; /* number of allocated segments (<= dsize) */ + uint64 dsize; /* directory size */ + uint64 nsegs; /* number of allocated segments (<= dsize) */ uint32 max_bucket; /* ID of maximum bucket in use */ uint32 high_mask; /* mask to modulo into entire table */ uint32 low_mask; /* mask to modulo into lower half of table */ @@ -178,10 +178,10 @@ struct HASHHDR /* These fields are fixed at hashtable creation */ Size keysize; /* hash key length in bytes */ Size entrysize; /* total user element size in bytes */ - long num_partitions; /* # partitions (must be power of 2), or 0 */ - long ffactor; /* target fill factor */ - long max_dsize; /* 'dsize' limit if directory is fixed size */ - long ssize; /* segment size --- must be power of 2 */ + uint64 num_partitions; /* # partitions (must be power of 2), or 0 */ + uint64 ffactor; /* target fill factor */ + uint64 max_dsize; /* 'dsize' limit if directory is fixed size */ + uint64 ssize; /* segment size --- must be power of 2 */ int sshift; /* segment shift = log2(ssize) */ int nelem_alloc; /* number of entries to allocate at once */ @@ -191,8 +191,8 @@ struct HASHHDR * Count statistics here. NB: stats code doesn't bother with mutex, so * counts could be corrupted a bit in a partitioned table. */ - long accesses; - long collisions; + uint64 accesses; + uint64 collisions; #endif }; @@ -223,7 +223,7 @@ struct HTAB /* We keep local copies of these fixed values to reduce contention */ Size keysize; /* hash key length in bytes */ - long ssize; /* segment size --- must be power of 2 */ + uint64 ssize; /* segment size --- must be power of 2 */ int sshift; /* segment shift = log2(ssize) */ }; @@ -244,9 +244,9 @@ struct HTAB #define MOD(x,y) ((x) & ((y)-1)) #ifdef HASH_STATISTICS -static long hash_accesses, - hash_collisions, - hash_expansions; +static uint64 hash_accesses, + hash_collisions, + hash_expansions; #endif /* @@ -260,10 +260,10 @@ static bool expand_table(HTAB *hashp); static HASHBUCKET get_hash_entry(HTAB *hashp, int freelist_idx); static void hdefault(HTAB *hashp); static int choose_nelem_alloc(Size entrysize); -static bool init_htab(HTAB *hashp, long nelem); +static bool init_htab(HTAB *hashp, uint64 nelem); static void hash_corrupted(HTAB *hashp); -static long next_pow2_long(long num); -static int next_pow2_int(long num); +static uint64 next_pow2_uint64(uint64 num); +static int next_pow2_int(uint64 num); static void register_seq_scan(HTAB *hashp); static void deregister_seq_scan(HTAB *hashp); static bool has_seq_scans(HTAB *hashp); @@ -313,7 +313,7 @@ string_compare(const char *key1, const char *key2, Size keysize) * large nelem will penalize hash_seq_search speed without buying much. */ HTAB * -hash_create(const char *tabname, long nelem, HASHCTL *info, int flags) +hash_create(const char *tabname, uint64 nelem, HASHCTL *info, int flags) { HTAB *hashp; HASHHDR *hctl; @@ -633,7 +633,7 @@ choose_nelem_alloc(Size entrysize) * arrays */ static bool -init_htab(HTAB *hashp, long nelem) +init_htab(HTAB *hashp, uint64 nelem) { HASHHDR *hctl = hashp->hctl; HASHSEGMENT *segp; @@ -729,10 +729,10 @@ init_htab(HTAB *hashp, long nelem) * NB: assumes that all hash structure parameters have default values! */ Size -hash_estimate_size(long num_entries, Size entrysize) +hash_estimate_size(uint64 num_entries, Size entrysize) { Size size; - long nBuckets, + uint64 nBuckets, nSegments, nDirEntries, nElementAllocs, @@ -740,9 +740,9 @@ hash_estimate_size(long num_entries, Size entrysize) elementAllocCnt; /* estimate number of buckets wanted */ - nBuckets = next_pow2_long((num_entries - 1) / DEF_FFACTOR + 1); + nBuckets = next_pow2_uint64((num_entries - 1) / DEF_FFACTOR + 1); /* # of segments needed for nBuckets */ - nSegments = next_pow2_long((nBuckets - 1) / DEF_SEGSIZE + 1); + nSegments = next_pow2_uint64((nBuckets - 1) / DEF_SEGSIZE + 1); /* directory entries */ nDirEntries = DEF_DIRSIZE; while (nDirEntries < nSegments) @@ -775,17 +775,17 @@ hash_estimate_size(long num_entries, Size entrysize) * * XXX this had better agree with the behavior of init_htab()... */ -long -hash_select_dirsize(long num_entries) +uint64 +hash_select_dirsize(uint64 num_entries) { - long nBuckets, + uint64 nBuckets, nSegments, nDirEntries; /* estimate number of buckets wanted */ - nBuckets = next_pow2_long((num_entries - 1) / DEF_FFACTOR + 1); + nBuckets = next_pow2_uint64((num_entries - 1) / DEF_FFACTOR + 1); /* # of segments needed for nBuckets */ - nSegments = next_pow2_long((nBuckets - 1) / DEF_SEGSIZE + 1); + nSegments = next_pow2_uint64((nBuckets - 1) / DEF_SEGSIZE + 1); /* directory entries */ nDirEntries = DEF_DIRSIZE; while (nDirEntries < nSegments) @@ -836,8 +836,8 @@ hash_stats(const char *where, HTAB *hashp) fprintf(stderr, "%s: this HTAB -- accesses %ld collisions %ld\n", where, hashp->hctl->accesses, hashp->hctl->collisions); - fprintf(stderr, "hash_stats: entries %ld keysize %ld maxp %u segmentcount %ld\n", - hash_get_num_entries(hashp), (long) hashp->hctl->keysize, + fprintf(stderr, "hash_stats: entries %ld keysize %llu maxp %u segmentcount %ld\n", + hash_get_num_entries(hashp), (uint64) hashp->hctl->keysize, hashp->hctl->max_bucket, hashp->hctl->nsegs); fprintf(stderr, "%s: total accesses %ld total collisions %ld\n", where, hash_accesses, hash_collisions); @@ -926,8 +926,8 @@ hash_search_with_hash_value(HTAB *hashp, int freelist_idx = FREELIST_IDX(hctl, hashvalue); Size keysize; uint32 bucket; - long segment_num; - long segment_ndx; + uint64 segment_num; + uint64 segment_ndx; HASHSEGMENT segp; HASHBUCKET currBucket; HASHBUCKET *prevBucketPtr; @@ -954,7 +954,7 @@ hash_search_with_hash_value(HTAB *hashp, * order of these tests is to try to check cheaper conditions first. */ if (!IS_PARTITIONED(hctl) && !hashp->frozen && - hctl->freeList[0].nentries / (long) (hctl->max_bucket + 1) >= hctl->ffactor && + hctl->freeList[0].nentries / (uint64) (hctl->max_bucket + 1) >= hctl->ffactor && !has_seq_scans(hashp)) (void) expand_table(hashp); } @@ -1122,8 +1122,8 @@ hash_update_hash_key(HTAB *hashp, Size keysize; uint32 bucket; uint32 newbucket; - long segment_num; - long segment_ndx; + uint64 segment_num; + uint64 segment_ndx; HASHSEGMENT segp; HASHBUCKET currBucket; HASHBUCKET *prevBucketPtr; @@ -1331,11 +1331,11 @@ get_hash_entry(HTAB *hashp, int freelist_idx) /* * hash_get_num_entries -- get the number of entries in a hashtable */ -long +uint64 hash_get_num_entries(HTAB *hashp) { int i; - long sum = hashp->hctl->freeList[0].nentries; + uint64 sum = hashp->hctl->freeList[0].nentries; /* * We currently don't bother with acquiring the mutexes; it's only @@ -1391,9 +1391,9 @@ hash_seq_search(HASH_SEQ_STATUS *status) HTAB *hashp; HASHHDR *hctl; uint32 max_bucket; - long ssize; - long segment_num; - long segment_ndx; + uint64 ssize; + uint64 segment_num; + uint64 segment_ndx; HASHSEGMENT segp; uint32 curBucket; HASHELEMENT *curElem; @@ -1504,11 +1504,11 @@ expand_table(HTAB *hashp) HASHHDR *hctl = hashp->hctl; HASHSEGMENT old_seg, new_seg; - long old_bucket, + uint64 old_bucket, new_bucket; - long new_segnum, + uint64 new_segnum, new_segndx; - long old_segnum, + uint64 old_segnum, old_segndx; HASHBUCKET *oldlink, *newlink; @@ -1576,7 +1576,7 @@ expand_table(HTAB *hashp) currElement = nextElement) { nextElement = currElement->link; - if ((long) calc_bucket(hctl, currElement->hashvalue) == old_bucket) + if ((uint64) calc_bucket(hctl, currElement->hashvalue) == old_bucket) { *oldlink = currElement; oldlink = &currElement->link; @@ -1600,9 +1600,9 @@ dir_realloc(HTAB *hashp) { HASHSEGMENT *p; HASHSEGMENT *old_p; - long new_dsize; - long old_dirsize; - long new_dirsize; + uint64 new_dsize; + uint64 old_dirsize; + uint64 new_dirsize; if (hashp->hctl->max_dsize != NO_MAX_DSIZE) return false; @@ -1715,10 +1715,10 @@ hash_corrupted(HTAB *hashp) /* calculate ceil(log base 2) of num */ int -my_log2(long num) +my_log2(uint64 num) { int i; - long limit; + uint64 limit; /* guard against too-large input, which would put us into infinite loop */ if (num > LONG_MAX / 2) @@ -1729,9 +1729,9 @@ my_log2(long num) return i; } -/* calculate first power of 2 >= num, bounded to what will fit in a long */ -static long -next_pow2_long(long num) +/* calculate first power of 2 >= num, bounded to what will fit in a uint64 */ +static uint64 +next_pow2_uint64(uint64 num) { /* my_log2's internal range check is sufficient */ return 1L << my_log2(num); @@ -1739,7 +1739,7 @@ next_pow2_long(long num) /* calculate first power of 2 >= num, bounded to what will fit in an int */ static int -next_pow2_int(long num) +next_pow2_int(uint64 num) { if (num > INT_MAX / 2) num = INT_MAX / 2; diff --git a/src/backend/utils/misc/sampling.c b/src/backend/utils/misc/sampling.c index 361c15614e..05d2fd581c 100644 --- a/src/backend/utils/misc/sampling.c +++ b/src/backend/utils/misc/sampling.c @@ -37,7 +37,7 @@ */ BlockNumber BlockSampler_Init(BlockSampler bs, BlockNumber nblocks, int samplesize, - long randseed) + uint64 randseed) { bs->N = nblocks; /* measured table size */ @@ -230,7 +230,7 @@ reservoir_get_next_S(ReservoirState rs, double t, int n) *---------- */ void -sampler_random_init_state(long seed, SamplerRandomState randstate) +sampler_random_init_state(uint64 seed, SamplerRandomState randstate) { randstate[0] = 0x330e; /* same as pg_erand48, but could be anything */ randstate[1] = (unsigned short) seed; diff --git a/src/backend/utils/sort/logtape.c b/src/backend/utils/sort/logtape.c index 42cfb1f9f9..818117e4a0 100644 --- a/src/backend/utils/sort/logtape.c +++ b/src/backend/utils/sort/logtape.c @@ -97,9 +97,9 @@ */ typedef struct TapeBlockTrailer { - long prev; /* previous block on this tape, or -1 on first + int64 prev; /* previous block on this tape, or -1 on first * block */ - long next; /* next block on this tape, or # of valid + int64 next; /* next block on this tape, or # of valid * bytes on last block (if < 0) */ } TapeBlockTrailer; @@ -142,10 +142,10 @@ typedef struct LogicalTape * When concatenation of worker tape BufFiles is performed, an offset to * the first block in the unified BufFile space is applied during reads. */ - long firstBlockNumber; - long curBlockNumber; - long nextBlockNumber; - long offsetBlockNumber; + int64 firstBlockNumber; + int64 curBlockNumber; + int64 nextBlockNumber; + int64 offsetBlockNumber; /* * Buffer for current data block(s). @@ -177,9 +177,9 @@ struct LogicalTapeSet * blocks that are in unused holes between worker spaces following BufFile * concatenation. */ - long nBlocksAllocated; /* # of blocks allocated */ - long nBlocksWritten; /* # of blocks used in underlying file */ - long nHoleBlocks; /* # of "hole" blocks left */ + uint64 nBlocksAllocated; /* # of blocks allocated */ + uint64 nBlocksWritten; /* # of blocks used in underlying file */ + uint64 nHoleBlocks; /* # of "hole" blocks left */ /* * We store the numbers of recycled-and-available blocks in freeBlocks[]. @@ -196,7 +196,7 @@ struct LogicalTapeSet */ bool forgetFreeSpace; /* are we remembering free blocks? */ bool blocksSorted; /* is freeBlocks[] currently in order? */ - long *freeBlocks; /* resizable array */ + uint64 *freeBlocks; /* resizable array */ int nFreeBlocks; /* # of currently free blocks */ int freeBlocksLen; /* current allocated length of freeBlocks[] */ @@ -205,10 +205,10 @@ struct LogicalTapeSet LogicalTape tapes[FLEXIBLE_ARRAY_MEMBER]; /* has nTapes nentries */ }; -static void ltsWriteBlock(LogicalTapeSet *lts, long blocknum, void *buffer); -static void ltsReadBlock(LogicalTapeSet *lts, long blocknum, void *buffer); -static long ltsGetFreeBlock(LogicalTapeSet *lts); -static void ltsReleaseBlock(LogicalTapeSet *lts, long blocknum); +static void ltsWriteBlock(LogicalTapeSet *lts, int64 blocknum, void *buffer); +static void ltsReadBlock(LogicalTapeSet *lts, int64 blocknum, void *buffer); +static int64 ltsGetFreeBlock(LogicalTapeSet *lts); +static void ltsReleaseBlock(LogicalTapeSet *lts, int64 blocknum); static void ltsConcatWorkerTapes(LogicalTapeSet *lts, TapeShare *shared, SharedFileSet *fileset); @@ -219,7 +219,7 @@ static void ltsConcatWorkerTapes(LogicalTapeSet *lts, TapeShare *shared, * No need for an error return convention; we ereport() on any error. */ static void -ltsWriteBlock(LogicalTapeSet *lts, long blocknum, void *buffer) +ltsWriteBlock(LogicalTapeSet *lts, int64 blocknum, void *buffer) { /* * BufFile does not support "holes", so if we're about to write a block @@ -267,7 +267,7 @@ ltsWriteBlock(LogicalTapeSet *lts, long blocknum, void *buffer) * module should never attempt to read a block it doesn't know is there. */ static void -ltsReadBlock(LogicalTapeSet *lts, long blocknum, void *buffer) +ltsReadBlock(LogicalTapeSet *lts, int64 blocknum, void *buffer) { if (BufFileSeekBlock(lts->pfile, blocknum) != 0 || BufFileRead(lts->pfile, buffer, BLCKSZ) != BLCKSZ) @@ -291,7 +291,7 @@ ltsReadFillBuffer(LogicalTapeSet *lts, LogicalTape *lt) do { char *thisbuf = lt->buffer + lt->nbytes; - long datablocknum = lt->nextBlockNumber; + int64 datablocknum = lt->nextBlockNumber; /* Fetch next block number */ if (datablocknum == -1L) @@ -327,10 +327,10 @@ ltsReadFillBuffer(LogicalTapeSet *lts, LogicalTape *lt) static int freeBlocks_cmp(const void *a, const void *b) { - long ablk = *((const long *) a); - long bblk = *((const long *) b); + int64 ablk = *((const int64 *) a); + int64 bblk = *((const int64 *) b); - /* can't just subtract because long might be wider than int */ + /* can't just subtract because int64 might be wider than int */ if (ablk < bblk) return 1; if (ablk > bblk) @@ -341,7 +341,7 @@ freeBlocks_cmp(const void *a, const void *b) /* * Select a currently unused block for writing to. */ -static long +static int64 ltsGetFreeBlock(LogicalTapeSet *lts) { /* @@ -354,7 +354,7 @@ ltsGetFreeBlock(LogicalTapeSet *lts) if (!lts->blocksSorted) { qsort((void *) lts->freeBlocks, lts->nFreeBlocks, - sizeof(long), freeBlocks_cmp); + sizeof(int64), freeBlocks_cmp); lts->blocksSorted = true; } return lts->freeBlocks[--lts->nFreeBlocks]; @@ -367,7 +367,7 @@ ltsGetFreeBlock(LogicalTapeSet *lts) * Return a block# to the freelist. */ static void -ltsReleaseBlock(LogicalTapeSet *lts, long blocknum) +ltsReleaseBlock(LogicalTapeSet *lts, int64 blocknum) { int ndx; @@ -383,8 +383,8 @@ ltsReleaseBlock(LogicalTapeSet *lts, long blocknum) if (lts->nFreeBlocks >= lts->freeBlocksLen) { lts->freeBlocksLen *= 2; - lts->freeBlocks = (long *) repalloc(lts->freeBlocks, - lts->freeBlocksLen * sizeof(long)); + lts->freeBlocks = (uint64 *) repalloc(lts->freeBlocks, + lts->freeBlocksLen * sizeof(int64)); } /* @@ -410,8 +410,8 @@ ltsConcatWorkerTapes(LogicalTapeSet *lts, TapeShare *shared, SharedFileSet *fileset) { LogicalTape *lt = NULL; - long tapeblocks = 0L; - long nphysicalblocks = 0L; + int64 tapeblocks = 0L; + int64 nphysicalblocks = 0L; int i; /* Should have at least one worker tape, plus leader's tape */ @@ -526,7 +526,7 @@ LogicalTapeSetCreate(int ntapes, TapeShare *shared, SharedFileSet *fileset, lts->forgetFreeSpace = false; lts->blocksSorted = true; /* a zero-length array is sorted ... */ lts->freeBlocksLen = 32; /* reasonable initial guess */ - lts->freeBlocks = (long *) palloc(lts->freeBlocksLen * sizeof(long)); + lts->freeBlocks = (uint64 *) palloc(lts->freeBlocksLen * sizeof(uint64)); lts->nFreeBlocks = 0; lts->nTapes = ntapes; @@ -652,7 +652,7 @@ LogicalTapeWrite(LogicalTapeSet *lts, int tapenum, if (lt->pos >= TapeBlockPayloadSize) { /* Buffer full, dump it out */ - long nextBlockNumber; + int64 nextBlockNumber; if (!lt->dirty) { @@ -984,7 +984,7 @@ LogicalTapeBackspace(LogicalTapeSet *lts, int tapenum, size_t size) seekpos = (size_t) lt->pos; /* part within this block */ while (size > seekpos) { - long prev = TapeBlockGetTrailer(lt->buffer)->prev; + int64 prev = TapeBlockGetTrailer(lt->buffer)->prev; if (prev == -1L) { @@ -1029,7 +1029,7 @@ LogicalTapeBackspace(LogicalTapeSet *lts, int tapenum, size_t size) */ void LogicalTapeSeek(LogicalTapeSet *lts, int tapenum, - long blocknum, int offset) + int64 blocknum, int offset) { LogicalTape *lt; @@ -1060,7 +1060,7 @@ LogicalTapeSeek(LogicalTapeSet *lts, int tapenum, */ void LogicalTapeTell(LogicalTapeSet *lts, int tapenum, - long *blocknum, int *offset) + int64 *blocknum, int *offset) { LogicalTape *lt; @@ -1078,7 +1078,7 @@ LogicalTapeTell(LogicalTapeSet *lts, int tapenum, /* * Obtain total disk space currently used by a LogicalTapeSet, in blocks. */ -long +int64 LogicalTapeSetBlocks(LogicalTapeSet *lts) { return lts->nBlocksAllocated - lts->nHoleBlocks; diff --git a/src/bin/pg_basebackup/receivelog.c b/src/bin/pg_basebackup/receivelog.c index 62a342f77c..488f12dc6f 100644 --- a/src/bin/pg_basebackup/receivelog.c +++ b/src/bin/pg_basebackup/receivelog.c @@ -37,8 +37,8 @@ static bool still_sending = true; /* feedback still needs to be sent? */ static PGresult *HandleCopyStream(PGconn *conn, StreamCtl *stream, XLogRecPtr *stoppos); -static int CopyStreamPoll(PGconn *conn, long timeout_ms, pgsocket stop_socket); -static int CopyStreamReceive(PGconn *conn, long timeout, pgsocket stop_socket, +static int CopyStreamPoll(PGconn *conn, int64 timeout_ms, pgsocket stop_socket); +static int CopyStreamReceive(PGconn *conn, int64 timeout, pgsocket stop_socket, char **buffer); static bool ProcessKeepaliveMsg(PGconn *conn, StreamCtl *stream, char *copybuf, int len, XLogRecPtr blockpos, TimestampTz *last_status); @@ -48,7 +48,7 @@ static PGresult *HandleEndOfCopyStream(PGconn *conn, StreamCtl *stream, char *co XLogRecPtr blockpos, XLogRecPtr *stoppos); static bool CheckCopyStreamStop(PGconn *conn, StreamCtl *stream, XLogRecPtr blockpos, XLogRecPtr *stoppos); -static long CalculateCopyStreamSleeptime(TimestampTz now, int standby_message_timeout, +static int64 CalculateCopyStreamSleeptime(TimestampTz now, int standby_message_timeout, TimestampTz last_status); static bool ReadEndOfStreamingResult(PGresult *res, XLogRecPtr *startpos, @@ -742,7 +742,7 @@ HandleCopyStream(PGconn *conn, StreamCtl *stream, { int r; TimestampTz now; - long sleeptime; + int64 sleeptime; /* * Check if we should continue streaming, or abort at this point. @@ -858,7 +858,7 @@ error: * or interrupted by signal or stop_socket input, and -1 on an error. */ static int -CopyStreamPoll(PGconn *conn, long timeout_ms, pgsocket stop_socket) +CopyStreamPoll(PGconn *conn, int64 timeout_ms, pgsocket stop_socket) { int ret; fd_set input_mask; @@ -920,7 +920,7 @@ CopyStreamPoll(PGconn *conn, long timeout_ms, pgsocket stop_socket) * -1 on error. -2 if the server ended the COPY. */ static int -CopyStreamReceive(PGconn *conn, long timeout, pgsocket stop_socket, +CopyStreamReceive(PGconn *conn, int64 timeout, pgsocket stop_socket, char **buffer) { char *copybuf = NULL; @@ -1228,12 +1228,12 @@ CheckCopyStreamStop(PGconn *conn, StreamCtl *stream, XLogRecPtr blockpos, /* * Calculate how long send/receive loops should sleep */ -static long +static int64 CalculateCopyStreamSleeptime(TimestampTz now, int standby_message_timeout, TimestampTz last_status) { TimestampTz status_targettime = 0; - long sleeptime; + int64 sleeptime; if (standby_message_timeout && still_sending) status_targettime = last_status + @@ -1241,7 +1241,7 @@ CalculateCopyStreamSleeptime(TimestampTz now, int standby_message_timeout, if (status_targettime > 0) { - long secs; + int64 secs; int usecs; feTimestampDifference(now, diff --git a/src/include/executor/spi.h b/src/include/executor/spi.h index 06de20ada5..e54c968aca 100644 --- a/src/include/executor/spi.h +++ b/src/include/executor/spi.h @@ -84,24 +84,24 @@ extern PGDLLIMPORT int SPI_result; extern int SPI_connect(void); extern int SPI_connect_ext(int options); extern int SPI_finish(void); -extern int SPI_execute(const char *src, bool read_only, long tcount); +extern int SPI_execute(const char *src, bool read_only, int64 tcount); extern int SPI_execute_plan(SPIPlanPtr plan, Datum *Values, const char *Nulls, - bool read_only, long tcount); + bool read_only, int64 tcount); extern int SPI_execute_plan_with_paramlist(SPIPlanPtr plan, ParamListInfo params, - bool read_only, long tcount); -extern int SPI_exec(const char *src, long tcount); + bool read_only, int64 tcount); +extern int SPI_exec(const char *src, int64 tcount); extern int SPI_execp(SPIPlanPtr plan, Datum *Values, const char *Nulls, - long tcount); + int64 tcount); extern int SPI_execute_snapshot(SPIPlanPtr plan, Datum *Values, const char *Nulls, Snapshot snapshot, Snapshot crosscheck_snapshot, - bool read_only, bool fire_triggers, long tcount); + bool read_only, bool fire_triggers, int64 tcount); extern int SPI_execute_with_args(const char *src, int nargs, Oid *argtypes, Datum *Values, const char *Nulls, - bool read_only, long tcount); + bool read_only, int64 tcount); extern SPIPlanPtr SPI_prepare(const char *src, int nargs, Oid *argtypes); extern SPIPlanPtr SPI_prepare_cursor(const char *src, int nargs, Oid *argtypes, int cursorOptions); @@ -151,10 +151,10 @@ extern Portal SPI_cursor_open_with_args(const char *name, extern Portal SPI_cursor_open_with_paramlist(const char *name, SPIPlanPtr plan, ParamListInfo params, bool read_only); extern Portal SPI_cursor_find(const char *name); -extern void SPI_cursor_fetch(Portal portal, bool forward, long count); -extern void SPI_cursor_move(Portal portal, bool forward, long count); -extern void SPI_scroll_cursor_fetch(Portal, FetchDirection direction, long count); -extern void SPI_scroll_cursor_move(Portal, FetchDirection direction, long count); +extern void SPI_cursor_fetch(Portal portal, bool forward, int64 count); +extern void SPI_cursor_move(Portal portal, bool forward, int64 count); +extern void SPI_scroll_cursor_fetch(Portal, FetchDirection direction, int64 count); +extern void SPI_scroll_cursor_move(Portal, FetchDirection direction, int64 count); extern void SPI_cursor_close(Portal portal); extern int SPI_register_relation(EphemeralNamedRelation enr); diff --git a/src/include/pgtime.h b/src/include/pgtime.h index 0fc76d0e60..3d2fdedd89 100644 --- a/src/include/pgtime.h +++ b/src/include/pgtime.h @@ -33,7 +33,7 @@ struct pg_tm int tm_wday; int tm_yday; int tm_isdst; - long int tm_gmtoff; + int64 tm_gmtoff; const char *tm_zone; }; @@ -48,18 +48,18 @@ typedef struct pg_tzenum pg_tzenum; extern struct pg_tm *pg_localtime(const pg_time_t *timep, const pg_tz *tz); extern struct pg_tm *pg_gmtime(const pg_time_t *timep); extern int pg_next_dst_boundary(const pg_time_t *timep, - long int *before_gmtoff, + int64 *before_gmtoff, int *before_isdst, pg_time_t *boundary, - long int *after_gmtoff, + int64 *after_gmtoff, int *after_isdst, const pg_tz *tz); extern bool pg_interpret_timezone_abbrev(const char *abbrev, const pg_time_t *timep, - long int *gmtoff, + int64 *gmtoff, int *isdst, const pg_tz *tz); -extern bool pg_get_timezone_offset(const pg_tz *tz, long int *gmtoff); +extern bool pg_get_timezone_offset(const pg_tz *tz, int64 *gmtoff); extern const char *pg_get_timezone_name(pg_tz *tz); extern bool pg_tz_acceptable(pg_tz *tz); @@ -75,7 +75,7 @@ extern pg_tz *log_timezone; extern void pg_timezone_initialize(void); extern pg_tz *pg_tzset(const char *tzname); -extern pg_tz *pg_tzset_offset(long gmtoffset); +extern pg_tz *pg_tzset_offset(int64 gmtoffset); extern pg_tzenum *pg_tzenumerate_start(void); extern pg_tz *pg_tzenumerate_next(pg_tzenum *dir); diff --git a/src/include/portability/instr_time.h b/src/include/portability/instr_time.h index d6459327cc..0a51120fc4 100644 --- a/src/include/portability/instr_time.h +++ b/src/include/portability/instr_time.h @@ -136,7 +136,7 @@ typedef struct timespec instr_time; (((double) (t).tv_sec) + ((double) (t).tv_nsec) / 1000000000.0) #define INSTR_TIME_GET_MILLISEC(t) \ - (((double) (t).tv_sec * 1000.0) + ((double) (t).tv_nsec) / 1000000.0) + (((int64) (t).tv_sec * 1000.0) + ((int64) (t).tv_nsec) / 1000000.0) #define INSTR_TIME_GET_MICROSEC(t) \ (((uint64) (t).tv_sec * (uint64) 1000000) + (uint64) ((t).tv_nsec / 1000)) diff --git a/src/include/storage/buffile.h b/src/include/storage/buffile.h index 60433f35b4..7178247396 100644 --- a/src/include/storage/buffile.h +++ b/src/include/storage/buffile.h @@ -42,9 +42,9 @@ extern size_t BufFileRead(BufFile *file, void *ptr, size_t size); extern size_t BufFileWrite(BufFile *file, void *ptr, size_t size); extern int BufFileSeek(BufFile *file, int fileno, off_t offset, int whence); extern void BufFileTell(BufFile *file, int *fileno, off_t *offset); -extern int BufFileSeekBlock(BufFile *file, long blknum); +extern int BufFileSeekBlock(BufFile *file, uint64 blknum); extern int64 BufFileSize(BufFile *file); -extern long BufFileAppend(BufFile *target, BufFile *source); +extern uint64 BufFileAppend(BufFile *target, BufFile *source); extern BufFile *BufFileCreateShared(SharedFileSet *fileset, const char *name); extern void BufFileExportShared(BufFile *file); diff --git a/src/include/storage/condition_variable.h b/src/include/storage/condition_variable.h index bfe5c89b54..cb245c09c5 100644 --- a/src/include/storage/condition_variable.h +++ b/src/include/storage/condition_variable.h @@ -43,7 +43,7 @@ extern void ConditionVariableInit(ConditionVariable *cv); * the condition variable. */ extern void ConditionVariableSleep(ConditionVariable *cv, uint32 wait_event_info); -extern bool ConditionVariableTimedSleep(ConditionVariable *cv, long timeout, +extern bool ConditionVariableTimedSleep(ConditionVariable *cv, int64 timeout, uint32 wait_event_info); extern void ConditionVariableCancelSleep(void); diff --git a/src/include/storage/latch.h b/src/include/storage/latch.h index 46ae56cae3..3c013ca860 100644 --- a/src/include/storage/latch.h +++ b/src/include/storage/latch.h @@ -169,13 +169,13 @@ extern int AddWaitEventToSet(WaitEventSet *set, uint32 events, pgsocket fd, Latch *latch, void *user_data); extern void ModifyWaitEvent(WaitEventSet *set, int pos, uint32 events, Latch *latch); -extern int WaitEventSetWait(WaitEventSet *set, long timeout, +extern int WaitEventSetWait(WaitEventSet *set, int64 timeout, WaitEvent *occurred_events, int nevents, uint32 wait_event_info); -extern int WaitLatch(Latch *latch, int wakeEvents, long timeout, +extern int WaitLatch(Latch *latch, int wakeEvents, int64 timeout, uint32 wait_event_info); extern int WaitLatchOrSocket(Latch *latch, int wakeEvents, - pgsocket sock, long timeout, uint32 wait_event_info); + pgsocket sock, int64 timeout, uint32 wait_event_info); /* * Unix implementation uses SIGUSR1 for inter-process signaling. diff --git a/src/include/storage/shmem.h b/src/include/storage/shmem.h index 0c1af89206..4b75f33be9 100644 --- a/src/include/storage/shmem.h +++ b/src/include/storage/shmem.h @@ -39,7 +39,7 @@ extern void *ShmemAllocNoError(Size size); extern void *ShmemAllocUnlocked(Size size); extern bool ShmemAddrIsValid(const void *addr); extern void InitShmemIndex(void); -extern HTAB *ShmemInitHash(const char *name, long init_size, long max_size, +extern HTAB *ShmemInitHash(const char *name, uint64 init_size, uint64 max_size, HASHCTL *infoP, int hash_flags); extern void *ShmemInitStruct(const char *name, Size size, bool *foundPtr); extern Size add_size(Size s1, Size s2); diff --git a/src/include/tcop/pquery.h b/src/include/tcop/pquery.h index 4ad6324e2d..367c31cabb 100644 --- a/src/include/tcop/pquery.h +++ b/src/include/tcop/pquery.h @@ -33,13 +33,13 @@ extern void PortalStart(Portal portal, ParamListInfo params, extern void PortalSetResultFormat(Portal portal, int nFormats, int16 *formats); -extern bool PortalRun(Portal portal, long count, bool isTopLevel, +extern bool PortalRun(Portal portal, int64 count, bool isTopLevel, bool run_once, DestReceiver *dest, DestReceiver *altdest, char *completionTag); extern uint64 PortalRunFetch(Portal portal, FetchDirection fdirection, - long count, + int64 count, DestReceiver *dest); #endif /* PQUERY_H */ diff --git a/src/include/utils/dynahash.h b/src/include/utils/dynahash.h index 768b952176..0c75534897 100644 --- a/src/include/utils/dynahash.h +++ b/src/include/utils/dynahash.h @@ -14,6 +14,6 @@ #ifndef DYNAHASH_H #define DYNAHASH_H -extern int my_log2(long num); +extern int my_log2(uint64 num); #endif /* DYNAHASH_H */ diff --git a/src/include/utils/hsearch.h b/src/include/utils/hsearch.h index b0077b7827..4559cda0f8 100644 --- a/src/include/utils/hsearch.h +++ b/src/include/utils/hsearch.h @@ -64,11 +64,11 @@ typedef struct HTAB HTAB; /* Only those fields indicated by hash_flags need be set */ typedef struct HASHCTL { - long num_partitions; /* # partitions (must be power of 2) */ - long ssize; /* segment size */ - long dsize; /* (initial) directory size */ - long max_dsize; /* limit to dsize if dir size is limited */ - long ffactor; /* fill factor */ + uint64 num_partitions; /* # partitions (must be power of 2) */ + uint64 ssize; /* segment size */ + uint64 dsize; /* (initial) directory size */ + uint64 max_dsize; /* limit to dsize if dir size is limited */ + uint64 ffactor; /* fill factor */ Size keysize; /* hash key length in bytes */ Size entrysize; /* total user element size in bytes */ HashValueFunc hash; /* hash function */ @@ -119,7 +119,7 @@ typedef struct /* * prototypes for functions in dynahash.c */ -extern HTAB *hash_create(const char *tabname, long nelem, +extern HTAB *hash_create(const char *tabname, uint64 nelem, HASHCTL *info, int flags); extern void hash_destroy(HTAB *hashp); extern void hash_stats(const char *where, HTAB *hashp); @@ -131,13 +131,13 @@ extern void *hash_search_with_hash_value(HTAB *hashp, const void *keyPtr, bool *foundPtr); extern bool hash_update_hash_key(HTAB *hashp, void *existingEntry, const void *newKeyPtr); -extern long hash_get_num_entries(HTAB *hashp); +extern uint64 hash_get_num_entries(HTAB *hashp); extern void hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp); extern void *hash_seq_search(HASH_SEQ_STATUS *status); extern void hash_seq_term(HASH_SEQ_STATUS *status); extern void hash_freeze(HTAB *hashp); -extern Size hash_estimate_size(long num_entries, Size entrysize); -extern long hash_select_dirsize(long num_entries); +extern Size hash_estimate_size(uint64 num_entries, Size entrysize); +extern uint64 hash_select_dirsize(uint64 num_entries); extern Size hash_get_shared_size(HASHCTL *info, int flags); extern void AtEOXact_HashTables(bool isCommit); extern void AtEOSubXact_HashTables(bool isCommit, int nestDepth); diff --git a/src/include/utils/sampling.h b/src/include/utils/sampling.h index 74646846b2..cbcbeb6fd7 100644 --- a/src/include/utils/sampling.h +++ b/src/include/utils/sampling.h @@ -19,7 +19,7 @@ /* Random generator for sampling code */ typedef unsigned short SamplerRandomState[3]; -extern void sampler_random_init_state(long seed, +extern void sampler_random_init_state(uint64 seed, SamplerRandomState randstate); extern double sampler_random_fract(SamplerRandomState randstate); @@ -38,7 +38,7 @@ typedef struct typedef BlockSamplerData *BlockSampler; extern BlockNumber BlockSampler_Init(BlockSampler bs, BlockNumber nblocks, - int samplesize, long randseed); + int samplesize, uint64 randseed); extern bool BlockSampler_HasMore(BlockSampler bs); extern BlockNumber BlockSampler_Next(BlockSampler bs); diff --git a/src/include/utils/timestamp.h b/src/include/utils/timestamp.h index 03a1de569f..78fdf05583 100644 --- a/src/include/utils/timestamp.h +++ b/src/include/utils/timestamp.h @@ -71,7 +71,7 @@ extern TimestampTz GetCurrentTimestamp(void); extern TimestampTz GetSQLCurrentTimestamp(int32 typmod); extern Timestamp GetSQLLocalTimestamp(int32 typmod); extern void TimestampDifference(TimestampTz start_time, TimestampTz stop_time, - long *secs, int *microsecs); + int64 *secs, int *microsecs); extern bool TimestampDifferenceExceeds(TimestampTz start_time, TimestampTz stop_time, int msec); diff --git a/src/pl/plpgsql/src/pl_exec.c b/src/pl/plpgsql/src/pl_exec.c index 5acf604f63..3ce5848247 100644 --- a/src/pl/plpgsql/src/pl_exec.c +++ b/src/pl/plpgsql/src/pl_exec.c @@ -358,7 +358,7 @@ static Datum exec_eval_expr(PLpgSQL_execstate *estate, Oid *rettype, int32 *rettypmod); static int exec_run_select(PLpgSQL_execstate *estate, - PLpgSQL_expr *expr, long maxtuples, Portal *portalP); + PLpgSQL_expr *expr, uint64 maxtuples, Portal *portalP); static int exec_for_query(PLpgSQL_execstate *estate, PLpgSQL_stmt_forq *stmt, Portal portal, bool prefetch_ok); static ParamListInfo setup_param_list(PLpgSQL_execstate *estate, @@ -4085,7 +4085,7 @@ exec_stmt_execsql(PLpgSQL_execstate *estate, PLpgSQL_stmt_execsql *stmt) { ParamListInfo paramLI; - long tcount; + int64 tcount; int rc; PLpgSQL_expr *expr = stmt->sqlstmt; int too_many_rows_level = 0; @@ -4683,7 +4683,7 @@ static int exec_stmt_fetch(PLpgSQL_execstate *estate, PLpgSQL_stmt_fetch *stmt) { PLpgSQL_var *curvar; - long how_many = stmt->how_many; + int64 how_many = stmt->how_many; SPITupleTable *tuptab; Portal portal; char *curname; @@ -5831,7 +5831,7 @@ exec_eval_expr(PLpgSQL_execstate *estate, */ static int exec_run_select(PLpgSQL_execstate *estate, - PLpgSQL_expr *expr, long maxtuples, Portal *portalP) + PLpgSQL_expr *expr, uint64 maxtuples, Portal *portalP) { ParamListInfo paramLI; int rc; diff --git a/src/pl/plpgsql/src/plpgsql.h b/src/pl/plpgsql/src/plpgsql.h index b599f67fc5..e12429e5f2 100644 --- a/src/pl/plpgsql/src/plpgsql.h +++ b/src/pl/plpgsql/src/plpgsql.h @@ -798,7 +798,7 @@ typedef struct PLpgSQL_stmt_fetch PLpgSQL_variable *target; /* target (record or row) */ int curvar; /* cursor variable to fetch from */ FetchDirection direction; /* fetch direction */ - long how_many; /* count, if constant (expr is NULL) */ + int64 how_many; /* count, if constant (expr is NULL) */ PLpgSQL_expr *expr; /* count, if expression */ bool is_move; /* is this a fetch or move? */ bool returns_multiple_rows; /* can return more than one row? */ @@ -1026,7 +1026,7 @@ typedef struct PLpgSQL_function /* these fields change when the function is used */ struct PLpgSQL_execstate *cur_estate; - unsigned long use_count; + uint64 use_count; } PLpgSQL_function; /* diff --git a/src/pl/plpython/plpy_spi.c b/src/pl/plpython/plpy_spi.c index 99c1b4f28f..91079f4c99 100644 --- a/src/pl/plpython/plpy_spi.c +++ b/src/pl/plpython/plpy_spi.c @@ -25,7 +25,7 @@ #include "utils/memutils.h" #include "utils/syscache.h" -static PyObject *PLy_spi_execute_query(char *query, long limit); +static PyObject *PLy_spi_execute_query(char *query, uint64 limit); static PyObject *PLy_spi_execute_fetch_result(SPITupleTable *tuptable, uint64 rows, int status); static void PLy_spi_exception_set(PyObject *excclass, ErrorData *edata); @@ -158,7 +158,7 @@ PLy_spi_execute(PyObject *self, PyObject *args) char *query; PyObject *plan; PyObject *list = NULL; - long limit = 0; + uint64 limit = 0; if (PyArg_ParseTuple(args, "s|l", &query, &limit)) return PLy_spi_execute_query(query, limit); @@ -174,7 +174,7 @@ PLy_spi_execute(PyObject *self, PyObject *args) } PyObject * -PLy_spi_execute_plan(PyObject *ob, PyObject *list, long limit) +PLy_spi_execute_plan(PyObject *ob, PyObject *list, uint64 limit) { volatile int nargs; int i, @@ -305,7 +305,7 @@ PLy_spi_execute_plan(PyObject *ob, PyObject *list, long limit) } static PyObject * -PLy_spi_execute_query(char *query, long limit) +PLy_spi_execute_query(char *query, uint64 limit) { int rv; volatile MemoryContext oldcontext; diff --git a/src/pl/plpython/plpy_spi.h b/src/pl/plpython/plpy_spi.h index a5e2e60da7..66e8a43aae 100644 --- a/src/pl/plpython/plpy_spi.h +++ b/src/pl/plpython/plpy_spi.h @@ -10,7 +10,7 @@ extern PyObject *PLy_spi_prepare(PyObject *self, PyObject *args); extern PyObject *PLy_spi_execute(PyObject *self, PyObject *args); -extern PyObject *PLy_spi_execute_plan(PyObject *ob, PyObject *list, long limit); +extern PyObject *PLy_spi_execute_plan(PyObject *ob, PyObject *list, uint64 limit); typedef struct PLyExceptionEntry { diff --git a/src/timezone/localtime.c b/src/timezone/localtime.c index 333f27300a..926c677c41 100644 --- a/src/timezone/localtime.c +++ b/src/timezone/localtime.c @@ -1623,10 +1623,10 @@ increment_overflow_time(pg_time_t *tp, int32 j) */ int pg_next_dst_boundary(const pg_time_t *timep, - long int *before_gmtoff, + int64 *before_gmtoff, int *before_isdst, pg_time_t *boundary, - long int *after_gmtoff, + int64 *after_gmtoff, int *after_isdst, const pg_tz *tz) { @@ -1771,7 +1771,7 @@ pg_next_dst_boundary(const pg_time_t *timep, bool pg_interpret_timezone_abbrev(const char *abbrev, const pg_time_t *timep, - long int *gmtoff, + int64 *gmtoff, int *isdst, const pg_tz *tz) { @@ -1863,7 +1863,7 @@ pg_interpret_timezone_abbrev(const char *abbrev, * into *gmtoff and return true, else return false. */ bool -pg_get_timezone_offset(const pg_tz *tz, long int *gmtoff) +pg_get_timezone_offset(const pg_tz *tz, int64 *gmtoff) { /* * The zone could have more than one ttinfo, if it's historically used --------------2.24.1--
>From 590eafcd095ad385079d5ad93a6dcf7abe094b6a Mon Sep 17 00:00:00 2001 From: David Fetter <da...@fetter.org> Date: Fri, 31 Jan 2020 07:08:48 -0800 Subject: [PATCH v4 2/2] Spread bitutils into hashing To: hackers MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="------------2.24.1" This is a multi-part message in MIME format. --------------2.24.1 Content-Type: text/plain; charset=UTF-8; format=fixed Content-Transfer-Encoding: 8bit diff --git a/src/backend/access/hash/hashpage.c b/src/backend/access/hash/hashpage.c index 55d85644a4..29dca21be2 100644 --- a/src/backend/access/hash/hashpage.c +++ b/src/backend/access/hash/hashpage.c @@ -30,6 +30,7 @@ #include "access/hash.h" #include "access/hash_xlog.h" +#include "port/pg_bitutils.h" #include "miscadmin.h" #include "storage/lmgr.h" #include "storage/predicate.h" @@ -502,7 +503,6 @@ _hash_init_metabuffer(Buffer buf, double num_tuples, RegProcedure procid, double dnumbuckets; uint32 num_buckets; uint32 spare_index; - uint32 i; /* * Choose the number of initial bucket pages to match the fill factor @@ -543,14 +543,8 @@ _hash_init_metabuffer(Buffer buf, double num_tuples, RegProcedure procid, metap->hashm_ffactor = ffactor; metap->hashm_bsize = HashGetMaxBitmapSize(page); /* find largest bitmap array size that will fit in page size */ - for (i = _hash_log2(metap->hashm_bsize); i > 0; --i) - { - if ((1 << i) <= metap->hashm_bsize) - break; - } - Assert(i > 0); - metap->hashm_bmsize = 1 << i; - metap->hashm_bmshift = i + BYTE_TO_BIT; + metap->hashm_bmsize = 1 << pg_leftmost_one_pos32(metap->hashm_bsize); + metap->hashm_bmshift = pg_leftmost_one_pos32(metap->hashm_bsize) + BYTE_TO_BIT; Assert((1 << BMPG_SHIFT(metap)) == (BMPG_MASK(metap) + 1)); /* @@ -570,7 +564,7 @@ _hash_init_metabuffer(Buffer buf, double num_tuples, RegProcedure procid, * Set highmask as next immediate ((2 ^ x) - 1), which should be * sufficient to cover num_buckets. */ - metap->hashm_highmask = (1 << (_hash_log2(num_buckets + 1))) - 1; + metap->hashm_highmask = next_power_of_2_32(num_buckets + 1) - 1; metap->hashm_lowmask = (metap->hashm_highmask >> 1); MemSet(metap->hashm_spares, 0, sizeof(metap->hashm_spares)); @@ -657,13 +651,12 @@ restart_expand: * Can't split anymore if maxbucket has reached its maximum possible * value. * - * Ideally we'd allow bucket numbers up to UINT_MAX-1 (no higher because - * the calculation maxbucket+1 mustn't overflow). Currently we restrict - * to half that because of overflow looping in _hash_log2() and - * insufficient space in hashm_spares[]. It's moot anyway because an - * index with 2^32 buckets would certainly overflow BlockNumber and hence - * _hash_alloc_buckets() would fail, but if we supported buckets smaller - * than a disk block then this would be an independent constraint. + * Ideally we'd allow bucket numbers up to UINT_MAX-1 (no higher because the + * calculation maxbucket+1 mustn't overflow). Currently we restrict to half + * that because of insufficient space in hashm_spares[]. It's moot anyway + * because an index with 2^32 buckets would certainly overflow BlockNumber + * and hence _hash_alloc_buckets() would fail, but if we supported buckets + * smaller than a disk block then this would be an independent constraint. * * If you change this, see also the maximum initial number of buckets in * _hash_init(). diff --git a/src/backend/access/hash/hashsort.c b/src/backend/access/hash/hashsort.c index 9cb41d62e7..322379788c 100644 --- a/src/backend/access/hash/hashsort.c +++ b/src/backend/access/hash/hashsort.c @@ -27,6 +27,7 @@ #include "access/hash.h" #include "commands/progress.h" +#include "port/pg_bitutils.h" #include "miscadmin.h" #include "pgstat.h" #include "utils/tuplesort.h" @@ -69,7 +70,7 @@ _h_spoolinit(Relation heap, Relation index, uint32 num_buckets) * NOTE : This hash mask calculation should be in sync with similar * calculation in _hash_init_metabuffer. */ - hspool->high_mask = (((uint32) 1) << _hash_log2(num_buckets + 1)) - 1; + hspool->high_mask = next_power_of_2_32(num_buckets + 1) - 1; hspool->low_mask = (hspool->high_mask >> 1); hspool->max_buckets = num_buckets - 1; diff --git a/src/backend/access/hash/hashutil.c b/src/backend/access/hash/hashutil.c index 9efc8016bc..738572ca40 100644 --- a/src/backend/access/hash/hashutil.c +++ b/src/backend/access/hash/hashutil.c @@ -17,6 +17,7 @@ #include "access/hash.h" #include "access/reloptions.h" #include "access/relscan.h" +#include "port/pg_bitutils.h" #include "storage/buf_internals.h" #include "utils/lsyscache.h" #include "utils/rel.h" @@ -134,21 +135,6 @@ _hash_hashkey2bucket(uint32 hashkey, uint32 maxbucket, return bucket; } -/* - * _hash_log2 -- returns ceil(lg2(num)) - */ -uint32 -_hash_log2(uint32 num) -{ - uint32 i, - limit; - - limit = 1; - for (i = 0; limit < num; limit <<= 1, i++) - ; - return i; -} - /* * _hash_spareindex -- returns spare index / global splitpoint phase of the * bucket @@ -159,7 +145,7 @@ _hash_spareindex(uint32 num_bucket) uint32 splitpoint_group; uint32 splitpoint_phases; - splitpoint_group = _hash_log2(num_bucket); + splitpoint_group = ceil_log2_32(num_bucket); if (splitpoint_group < HASH_SPLITPOINT_GROUPS_WITH_ONE_PHASE) return splitpoint_group; diff --git a/src/backend/utils/hash/dynahash.c b/src/backend/utils/hash/dynahash.c index 43d5584eab..89b394916d 100644 --- a/src/backend/utils/hash/dynahash.c +++ b/src/backend/utils/hash/dynahash.c @@ -86,6 +86,7 @@ #include <limits.h> #include "access/xact.h" +#include "port/pg_bitutils.h" #include "storage/shmem.h" #include "storage/spin.h" #include "utils/dynahash.h" @@ -1717,16 +1718,11 @@ hash_corrupted(HTAB *hashp) int my_log2(uint64 num) { - int i; - uint64 limit; - /* guard against too-large input, which would put us into infinite loop */ if (num > LONG_MAX / 2) num = LONG_MAX / 2; - for (i = 0, limit = 1; limit < num; i++, limit <<= 1) - ; - return i; + return ceil_log2_64(num); } /* calculate first power of 2 >= num, bounded to what will fit in a uint64 */ diff --git a/src/include/access/hash.h b/src/include/access/hash.h index 9fc0696096..298c05e6fe 100644 --- a/src/include/access/hash.h +++ b/src/include/access/hash.h @@ -450,7 +450,6 @@ extern uint32 _hash_datum2hashkey(Relation rel, Datum key); extern uint32 _hash_datum2hashkey_type(Relation rel, Datum key, Oid keytype); extern Bucket _hash_hashkey2bucket(uint32 hashkey, uint32 maxbucket, uint32 highmask, uint32 lowmask); -extern uint32 _hash_log2(uint32 num); extern uint32 _hash_spareindex(uint32 num_bucket); extern uint32 _hash_get_totalbuckets(uint32 splitpoint_phase); extern void _hash_checkpage(Relation rel, Buffer buf, int flags); diff --git a/src/include/lib/simplehash.h b/src/include/lib/simplehash.h index 5a6783f653..1a35a054d8 100644 --- a/src/include/lib/simplehash.h +++ b/src/include/lib/simplehash.h @@ -57,6 +57,8 @@ * backwards, unless they're empty or already at their optimal position. */ +#include "port/pg_bitutils.h" + /* helpers */ #define SH_MAKE_PREFIX(a) CppConcat(a,_) #define SH_MAKE_NAME(name) SH_MAKE_NAME_(SH_MAKE_PREFIX(SH_PREFIX),name) @@ -215,27 +217,6 @@ SH_SCOPE void SH_STAT(SH_TYPE * tb); #ifndef SIMPLEHASH_H #define SIMPLEHASH_H -/* FIXME: can we move these to a central location? */ - -/* calculate ceil(log base 2) of num */ -static inline uint64 -sh_log2(uint64 num) -{ - int i; - uint64 limit; - - for (i = 0, limit = 1; limit < num; i++, limit <<= 1) - ; - return i; -} - -/* calculate first power of 2 >= num */ -static inline uint64 -sh_pow2(uint64 num) -{ - return ((uint64) 1) << sh_log2(num); -} - #ifdef FRONTEND #define sh_error(...) pg_log_error(__VA_ARGS__) #define sh_log(...) pg_log_info(__VA_ARGS__) @@ -259,7 +240,7 @@ SH_COMPUTE_PARAMETERS(SH_TYPE * tb, uint32 newsize) size = Max(newsize, 2); /* round up size to the next power of 2, that's how bucketing works */ - size = sh_pow2(size); + size = next_power_of_2_64(size); Assert(size <= SH_MAX_SIZE); /* @@ -434,7 +415,7 @@ SH_GROW(SH_TYPE * tb, uint32 newsize) uint32 startelem = 0; uint32 copyelem; - Assert(oldsize == sh_pow2(oldsize)); + Assert(oldsize == next_power_of_2_64(oldsize)); Assert(oldsize != SH_MAX_SIZE); Assert(oldsize < newsize); diff --git a/src/include/port/pg_bitutils.h b/src/include/port/pg_bitutils.h index 498e532308..88a9ea5b7f 100644 --- a/src/include/port/pg_bitutils.h +++ b/src/include/port/pg_bitutils.h @@ -20,19 +20,18 @@ extern PGDLLIMPORT const uint8 pg_number_of_ones[256]; /* * pg_leftmost_one_pos32 * Returns the position of the most significant set bit in "word", - * measured from the least significant bit. word must not be 0. + * measured from the least significant bit. */ static inline int pg_leftmost_one_pos32(uint32 word) { #ifdef HAVE__BUILTIN_CLZ - Assert(word != 0); - - return 31 - __builtin_clz(word); + return word ? 31 - __builtin_clz(word) : 0; #else int shift = 32 - 8; - Assert(word != 0); + if (word == 0) + return 0; while ((word >> shift) == 0) shift -= 8; @@ -49,19 +48,18 @@ static inline int pg_leftmost_one_pos64(uint64 word) { #ifdef HAVE__BUILTIN_CLZ - Assert(word != 0); - #if defined(HAVE_LONG_INT_64) - return 63 - __builtin_clzl(word); + return word ? 63 - __builtin_clzl(word) : 0; #elif defined(HAVE_LONG_LONG_INT_64) - return 63 - __builtin_clzll(word); + return word ? 63 - __builtin_clzll(word) : 0; #else #error must have a working 64-bit integer datatype #endif #else /* !HAVE__BUILTIN_CLZ */ int shift = 64 - 8; - Assert(word != 0); + if (word == 0) + return 0; while ((word >> shift) == 0) shift -= 8; @@ -73,19 +71,18 @@ pg_leftmost_one_pos64(uint64 word) /* * pg_rightmost_one_pos32 * Returns the position of the least significant set bit in "word", - * measured from the least significant bit. word must not be 0. + * measured from the least significant bit. */ static inline int pg_rightmost_one_pos32(uint32 word) { #ifdef HAVE__BUILTIN_CTZ - Assert(word != 0); - - return __builtin_ctz(word); + return word ? __builtin_ctz(word) : 32; #else int result = 0; - Assert(word != 0); + if (word == 0) + return 32; while ((word & 255) == 0) { @@ -105,19 +102,18 @@ static inline int pg_rightmost_one_pos64(uint64 word) { #ifdef HAVE__BUILTIN_CTZ - Assert(word != 0); - #if defined(HAVE_LONG_INT_64) - return __builtin_ctzl(word); + return word ? __builtin_ctzl(word) : 64; #elif defined(HAVE_LONG_LONG_INT_64) - return __builtin_ctzll(word); + return word ? __builtin_ctzll(word) : 64; #else #error must have a working 64-bit integer datatype #endif #else /* !HAVE__BUILTIN_CTZ */ int result = 0; - Assert(word != 0); + if (word == 0) + return 64; while ((word & 255) == 0) { @@ -145,4 +141,34 @@ pg_rotate_right32(uint32 word, int n) return (word >> n) | (word << (sizeof(word) * BITS_PER_BYTE - n)); } +/* ceil(lg2(num)) */ +static inline uint32 +ceil_log2_32(uint32 num) +{ + Assert(num > 0); + return pg_leftmost_one_pos32(num-1) + 1; +} + +static inline uint64 +ceil_log2_64(uint64 num) +{ + Assert(num > 0); + return pg_leftmost_one_pos64(num-1) + 1; +} + +/* Calculate the first power of 2 >= num */ +static inline uint32 +next_power_of_2_32(uint32 num) +{ + Assert(num > 0); + return ((uint32) 1) << (pg_leftmost_one_pos32(num-1) + 1); +} + +static inline uint64 +next_power_of_2_64(uint64 num) +{ + Assert(num > 0); + return ((uint64) 1) << (pg_leftmost_one_pos64(num-1) + 1); +} + #endif /* PG_BITUTILS_H */ --------------2.24.1--