=== Applying patches on top of PostgreSQL commit ID 3881561d7715647dbb4a5bc27f116504903daf1b === /etc/rc.d/jail: WARNING: Per-jail configuration via jail_* variables is obsolete. Please consider migrating to /etc/jail.conf. Sat Nov 29 18:26:22 UTC 2025 On branch cf/6228 nothing to commit, working tree clean === using 'git am' to apply patch ./v1-0001-pgstat-support-custom-serialization-files-and-cal.patch === Applying: pgstat: support custom serialization files and callbacks Using index info to reconstruct a base tree... M src/backend/utils/activity/pgstat.c M src/include/utils/pgstat_internal.h Falling back to patching base and 3-way merge... Auto-merging src/include/utils/pgstat_internal.h Auto-merging src/backend/utils/activity/pgstat.c CONFLICT (content): Merge conflict in src/backend/utils/activity/pgstat.c error: Failed to merge in the changes. hint: Use 'git am --show-current-patch=diff' to see the failed patch Patch failed at 0001 pgstat: support custom serialization files and callbacks When you have resolved this problem, run "git am --continue". If you prefer to skip this patch, run "git am --skip" instead. To restore the original branch and stop patching, run "git am --abort". Unstaged changes after reset: M src/backend/utils/activity/pgstat.c M src/include/utils/pgstat_internal.h === using patch(1) to apply patch ./v1-0001-pgstat-support-custom-serialization-files-and-cal.patch === patching file src/backend/utils/activity/pgstat.c Hunk #3 FAILED at 1600. Hunk #4 FAILED at 1611. Hunk #5 succeeded at 1620 (offset -2 lines). Hunk #6 FAILED at 1634. Hunk #7 FAILED at 1678. Hunk #8 FAILED at 1733. Hunk #9 FAILED at 1743. Hunk #10 FAILED at 1808. Hunk #11 FAILED at 1867. Hunk #12 FAILED at 1907. Hunk #13 FAILED at 1922. Hunk #14 succeeded at 1937 (offset -4 lines). Hunk #15 FAILED at 1953. Hunk #16 FAILED at 2037. Hunk #17 succeeded at 2043 (offset -4 lines). Hunk #18 succeeded at 2085 (offset -4 lines). 12 out of 18 hunks FAILED -- saving rejects to file src/backend/utils/activity/pgstat.c.rej patching file src/include/utils/pgstat_internal.h Hunk #2 succeeded at 1000 (offset 6 lines). Unstaged changes after reset: M src/backend/utils/activity/pgstat.c M src/include/utils/pgstat_internal.h Removing src/backend/utils/activity/pgstat.c.rej === using 'git apply' to apply patch ./v1-0001-pgstat-support-custom-serialization-files-and-cal.patch === Applied patch to 'src/backend/utils/activity/pgstat.c' with conflicts. Applied patch to 'src/include/utils/pgstat_internal.h' cleanly. U src/backend/utils/activity/pgstat.c diff --cc src/backend/utils/activity/pgstat.c index 8713c7a0483,a5d0a475db0..00000000000 --- a/src/backend/utils/activity/pgstat.c +++ b/src/backend/utils/activity/pgstat.c @@@ -1551,7 -1599,7 +1599,11 @@@ pgstat_assert_is_up(void * ------------------------------------------------------------ */ ++<<<<<<< ours +/* helper for pgstat_write_statsfile() */ ++======= + /* helpers for pgstat_write_statsfile() */ ++>>>>>>> theirs void pgstat_write_chunk(FILE *fpout, void *ptr, size_t len) { @@@ -1563,6 -1611,179 +1615,182 @@@ (void) rc; } ++<<<<<<< ours ++======= + /* helpers for pgstat_read_statsfile() */ + bool + pgstat_read_chunk(FILE *fpin, void *ptr, size_t len) + { + return fread(ptr, 1, len, fpin) == len; + } + + /* + * Close and remove all files recorded in a PgStat_SerializeFiles array. + * Depending on the is_temporary flag, this will remove either the temporary + * or the permanent filenames associated with each file descriptor. + * + * Errors encountered while closing files are logged, but cleanup continues + * for all remaining files. This function assumes the structure passed in + * was allocated by pgstat_allocate_files() and contains valid file descriptors + * for each opened stats file. + * + * NB: The array includes an extra slot at files[PGSTAT_KIND_MIN-1] for the + * core stats file. The loop below iterates from 0 to PGSTAT_KIND_CUSTOM_SIZE, + * processing all allocated slots, including the extra one. + */ + static void + pgstat_cleanup_files(PgStat_SerializeFiles *files, bool is_temporary) + { + for (int i = 0; i < PGSTAT_KIND_CUSTOM_SIZE + 1; i++) + { + for (int j = 0; j < files[i].num_files; j++) + { + FILE *fd = files[i].fd[j]; + + const char *filename = is_temporary ? + files[i].tmpfiles[j] : + files[i].statfiles[j]; + const char *type_str = is_temporary ? "temporary" : "permanent"; + + elog(DEBUG2, "removing %s stats file \"%s\"", type_str, filename); + + if (fd && FreeFile(fd) < 0) + { + ereport(LOG, + (errcode_for_file_access(), + errmsg("could not close %s statistics file \"%s\": %m", + type_str, filename))); + } + + unlink(filename); + + /* free per-file strings */ + pfree(files[i].tmpfiles[j]); + pfree(files[i].statfiles[j]); + } + + /* free each file arrays */ + if (files[i].fd) + pfree(files[i].fd); + + if (files[i].tmpfiles) + pfree(files[i].tmpfiles); + + if (files[i].statfiles) + pfree(files[i].statfiles); + } + + /* finally free top-level array */ + pfree(files); + } + + /* + * Allocate and open all statistics serialization files for reading or writing. + * + * The returned array contains the core permanent stats file at index 0, + * followed by any per-kind extra files at indices PGSTAT_KIND_CUSTOM_MIN + * to PGSTAT_KIND_CUSTOM_MAX. + * + * In write mode, temporary files are opened. If any file cannot be opened, + * all partially created temporary files are removed using pgstat_cleanup_files(), + * and NULL is returned. + * + * In read mode, permanent files are opened. If the core file cannot be opened, + * all stats are reset and NULL is returned. If a per-kind extra file cannot be + * opened, we proceed to the next extra file. + * + * Returns an array of PgStat_SerializeFiles on success, or NULL on failure + * after cleanup or stats reset as described above. + * + * NB: pgstat_cleanup_files is responsible for pfree'ing the PgStat_SerializeFiles + * array. + */ + static PgStat_SerializeFiles * + pgstat_allocate_files(bool is_read) + { + const char *mode = is_read ? PG_BINARY_R : PG_BINARY_W; + const char *action = is_read ? "reading" : "writing"; + const char *core_path; + PgStat_SerializeFiles *core; + PgStat_SerializeFiles *files = palloc0(sizeof(PgStat_SerializeFiles) * (PGSTAT_KIND_CUSTOM_SIZE + 1)); + + /* --- Core pgstat file setup --- */ + core = &files[PGSTAT_KIND_MIN - 1]; + core->num_files = 1; + core->tmpfiles = palloc(sizeof(char *)); + core->statfiles = palloc(sizeof(char *)); + core->fd = palloc(sizeof(FILE *)); + + core->tmpfiles[0] = pstrdup(PGSTAT_STAT_PERMANENT_TMPFILE); + core->statfiles[0] = pstrdup(PGSTAT_STAT_PERMANENT_FILENAME); + + elog(DEBUG2, "%s stats file \"%s\"", action, core->statfiles[0]); + + core_path = is_read ? core->statfiles[0] : core->tmpfiles[0]; + core->fd[0] = AllocateFile(core_path, mode); + if (core->fd[0] == NULL) + { + if (!is_read || errno != ENOENT) + ereport(LOG, + (errcode_for_file_access(), + errmsg("could not open %s statistics file \"%s\": %m", + is_read ? "permanent" : "temporary", core_path))); + + if (!is_read) + pgstat_cleanup_files(files, true); + else + pgstat_reset_after_failure(); + + return NULL; + } + + /* --- Per-kind extra pgstat files --- */ + for (PgStat_Kind kind = PGSTAT_KIND_CUSTOM_MIN; kind <= PGSTAT_KIND_CUSTOM_MAX; kind++) + { + int nfiles; + int index = (kind - PGSTAT_KIND_CUSTOM_MIN) + 1; + PgStat_SerializeFiles *extra; + const PgStat_KindInfo *info = pgstat_get_kind_info(kind); + + if (!info || info->num_serialized_extra_files < 1) + continue; + + nfiles = info->num_serialized_extra_files; + extra = &files[index]; + + extra->num_files = nfiles; + extra->tmpfiles = palloc(sizeof(char *) * nfiles); + extra->statfiles = palloc(sizeof(char *) * nfiles); + extra->fd = palloc(sizeof(FILE *) * nfiles); + + for (int i = 0; i < nfiles; i++) + { + const char *path; + + extra->tmpfiles[i] = psprintf("%s/pgstat.%d.%d.tmp", + PGSTAT_STAT_PERMANENT_DIRECTORY, kind, i); + extra->statfiles[i] = psprintf("%s/pgstat.%d.%d.stat", + PGSTAT_STAT_PERMANENT_DIRECTORY, kind, i); + + path = is_read ? extra->statfiles[i] : extra->tmpfiles[i]; + elog(DEBUG2, "%s stats file \"%s\"", action, extra->statfiles[i]); + + extra->fd[i] = AllocateFile(path, mode); + if (extra->fd[i] == NULL) + { + if (!is_read || errno != ENOENT) + ereport(LOG, + (errcode_for_file_access(), + errmsg("could not open %s statistics file \"%s\": %m", + is_read ? "permanent" : "temporary ", path))); + } + } + } + + return files; + } + ++>>>>>>> theirs /* * This function is called in the last process that is accessing the shared * stats so locking is not required. @@@ -1696,12 -1907,23 +1914,29 @@@ pgstat_write_statsfile(void fputc(PGSTAT_FILE_ENTRY_NAME, fpout); pgstat_write_chunk_s(fpout, &ps->key.kind); pgstat_write_chunk_s(fpout, &name); ++<<<<<<< ours ++======= + } + + /* A plug-in is saving extra data */ + if (kind_info->to_serialized_extra) + { + int index = (ps->key.kind - PGSTAT_KIND_CUSTOM_MIN) + 1; + + Assert(files[index].fd); + + kind_info->to_serialized_extra(&ps->key, shstats, fpout, files[index].fd); ++>>>>>>> theirs } /* Write except the header part of the entry */ pgstat_write_chunk(fpout, pgstat_get_entry_data(ps->key.kind, shstats), pgstat_get_entry_len(ps->key.kind)); ++<<<<<<< ours ++======= + ++>>>>>>> theirs } dshash_seq_term(&hstat); @@@ -1736,13 -1972,6 +1985,16 @@@ } } ++<<<<<<< ours +/* helper for pgstat_read_statsfile() */ +bool +pgstat_read_chunk(FILE *fpin, void *ptr, size_t len) +{ + return fread(ptr, 1, len, fpin) == len; +} + ++======= ++>>>>>>> theirs /* * Reads in existing statistics file into memory. *