Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package pg_top for openSUSE:Factory checked in at 2026-06-30 15:13:55 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/pg_top (Old) and /work/SRC/openSUSE:Factory/.pg_top.new.11887 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "pg_top" Tue Jun 30 15:13:55 2026 rev:2 rq:1362587 version:4.1.3 Changes: -------- --- /work/SRC/openSUSE:Factory/pg_top/pg_top.changes 2025-05-22 16:57:08.162595950 +0200 +++ /work/SRC/openSUSE:Factory/.pg_top.new.11887/pg_top.changes 2026-06-30 15:14:13.757658294 +0200 @@ -1,0 +2,19 @@ +Tue Jun 30 07:14:19 UTC 2026 - Felix Niederwanger <[email protected]> + +- Update to version 4.1.3: + * v4.1.3 release + * linux: fix handling of i/o stats + * v4.1.2 release + * Update man page template to use version supplied by CMake + * Add CMake rules to check for rst2man + * Fix column display alignment on remote connections + * More libbsd usage cleanup + * Print connections errors to stderr + * Fixup Linux i/o display + * Update cmake_minimum_required + * linux: use included tree.h + * add tree.h + * linux: increase size of some i/o columns + * build-appimage: podman run with --userns=keep-id + +------------------------------------------------------------------- Old: ---- pg_top-4.1.1.obscpio New: ---- pg_top-4.1.3.obscpio ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ pg_top.spec ++++++ --- /var/tmp/diff_new_pack.iTTFaG/_old 2026-06-30 15:14:14.761692291 +0200 +++ /var/tmp/diff_new_pack.iTTFaG/_new 2026-06-30 15:14:14.765692427 +0200 @@ -17,7 +17,7 @@ Name: pg_top -Version: 4.1.1 +Version: 4.1.3 Release: 0 Summary: top for postgresql License: BSD-3-Clause ++++++ _service ++++++ --- /var/tmp/diff_new_pack.iTTFaG/_old 2026-06-30 15:14:14.809693916 +0200 +++ /var/tmp/diff_new_pack.iTTFaG/_new 2026-06-30 15:14:14.813694052 +0200 @@ -2,7 +2,7 @@ <service mode="disabled" name="obs_scm"> <param name="url">https://gitlab.com/pg_top/pg_top.git</param> <param name="scm">git</param> - <param name="revision">v4.1.1</param> + <param name="revision">v4.1.3</param> <param name="versionformat">@PARENT_TAG@</param> <param name="versionrewrite-pattern">.*v(\d+\.\d+\.\d+)</param> <param name="versionrewrite-replacement">\1</param> ++++++ _servicedata ++++++ --- /var/tmp/diff_new_pack.iTTFaG/_old 2026-06-30 15:14:14.853695406 +0200 +++ /var/tmp/diff_new_pack.iTTFaG/_new 2026-06-30 15:14:14.857695542 +0200 @@ -1,6 +1,6 @@ <servicedata> <service name="tar_scm"> <param name="url">https://gitlab.com/pg_top/pg_top.git</param> - <param name="changesrevision">3fffe83e7132e1a119b2f12f94011cf0b2394fc0</param></service></servicedata> + <param name="changesrevision">510b6801cdf9ec9d5aa6d2aeccf39fc0df673787</param></service></servicedata> (No newline at EOF) ++++++ pg_top-4.1.1.obscpio -> pg_top-4.1.3.obscpio ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pg_top-4.1.1/CMakeLists.txt new/pg_top-4.1.3/CMakeLists.txt --- old/pg_top-4.1.1/CMakeLists.txt 2024-06-06 23:45:12.000000000 +0200 +++ new/pg_top-4.1.3/CMakeLists.txt 2025-06-30 21:40:53.000000000 +0200 @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.1.0) +cmake_minimum_required(VERSION 3.1...4.0) include(CheckFunctionExists) include(CheckLibraryExists) @@ -9,7 +9,7 @@ set(PROJECT_VERSION_MAJOR 4) set(PROJECT_VERSION_MINOR 1) -set(PROJECT_VERSION_PATCH 1) +set(PROJECT_VERSION_PATCH 3) set(PROJECT_VERSION ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}) @@ -131,6 +131,12 @@ # Build manual page with appropriate machine specific notes. +find_program(RST2MAN NAMES rst2man.py rst2man) + +if(NOT RST2MAN) + message(WARNING "Cannot build man page without rst2man.py or rst2man...") +endif() + configure_file( ${CMAKE_SOURCE_DIR}/pg_top.1.rst.in ${CMAKE_BINARY_DIR}/pg_top.1.rst @@ -144,7 +150,7 @@ endif(EXISTS "${CMAKE_SOURCE_DIR}/machine/m_${MACHINE}.man.rst") file(APPEND ${CMAKE_BINARY_DIR}/pg_top.1 "${MANUAL_SUPPLIMENT}") execute_process( - COMMAND rst2man.py ${CMAKE_BINARY_DIR}/pg_top.1.rst + COMMAND ${RST2MAN} ${CMAKE_BINARY_DIR}/pg_top.1.rst OUTPUT_FILE ${CMAKE_BINARY_DIR}/pg_top.1 ) @@ -353,7 +359,6 @@ COMMAND mkdir -p AppDir/usr/lib COMMAND cp -aL `ldd pg_top | grep libpq\\\\\\\\. | cut -d \" \" -f 3` `ldd pg_top | grep libtinfo\\\\\\\\. | cut -d \" \" -f 3` - `ldd pg_top | grep libbsd\\\\\\\\. | cut -d \" \" -f 3` `ldd pg_top | grep libssl\\\\\\\\. | cut -d \" \" -f 3` `ldd pg_top | grep libcrypto\\\\\\\\. | cut -d \" \" -f 3` `ldd pg_top | grep libgssapi_krb5\\\\\\\\. | cut -d \" \" -f 3` diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pg_top-4.1.1/Containerfile.appimage new/pg_top-4.1.3/Containerfile.appimage --- old/pg_top-4.1.1/Containerfile.appimage 2024-06-06 23:45:12.000000000 +0200 +++ new/pg_top-4.1.3/Containerfile.appimage 2025-06-30 21:40:53.000000000 +0200 @@ -15,7 +15,6 @@ flex \ gcc \ libc6-dev \ - libbsd-dev \ libncurses5-dev \ make \ wget \ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pg_top-4.1.1/HISTORY.rst new/pg_top-4.1.3/HISTORY.rst --- old/pg_top-4.1.1/HISTORY.rst 2024-06-06 23:45:12.000000000 +0200 +++ new/pg_top-4.1.3/HISTORY.rst 2025-06-30 21:40:53.000000000 +0200 @@ -1,6 +1,21 @@ Release Notes ============= +2025-06-30 v4.1.3 +----------------- + +* Fix bug in displaying correct I/O values in Linux, introduced in v4.0.0. + +2025-06-04 v4.1.2 +----------------- + +* Increase display size of some Linux i/o columns +* Import and use tree.h from *BSD instead of using libbsd on Linux +* Hopefully improved display of error message on failures to connect to + databases +* Fix column display alignment on remote connections +* Update CMake to throw warning if rst2man is not found + 2024-06-06 v4.1.1 ----------------- diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pg_top-4.1.1/appimage/pg_top.appdata.xml new/pg_top-4.1.3/appimage/pg_top.appdata.xml --- old/pg_top-4.1.1/appimage/pg_top.appdata.xml 2024-06-06 23:45:12.000000000 +0200 +++ new/pg_top-4.1.3/appimage/pg_top.appdata.xml 2025-06-30 21:40:53.000000000 +0200 @@ -30,9 +30,9 @@ </provides> <releases> - <release version="4.0.0" date="2020-10-8"> + <release version="4.1.3" date="2025-06-30"> <description> - <p>4.0.0 release.</p> + <p>4.1.3 release.</p> </description> </release> </releases> diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pg_top-4.1.1/machine/m_linux.c new/pg_top-4.1.3/machine/m_linux.c --- old/pg_top-4.1.1/machine/m_linux.c 2024-06-06 23:45:12.000000000 +0200 +++ new/pg_top-4.1.3/machine/m_linux.c 2025-06-30 21:40:53.000000000 +0200 @@ -29,8 +29,6 @@ #include <fcntl.h> #include <unistd.h> #include <stdlib.h> -#include <bsd/stdlib.h> -#include <bsd/sys/tree.h> #include <errno.h> #include <dirent.h> #include <string.h> @@ -66,6 +64,7 @@ #include "machine.h" #include "utils.h" +#include "tree.h" #define PROCFS "/proc" extern char *myname; @@ -171,7 +170,7 @@ " PID X SIZE RES STATE XTIME QTIME %CPU LOCKS COMMAND"; char fmt_header_io[] = -" PID IOPS IORPS IOWPS READS WRITES COMMAND"; +" PID IOPS IORPS IOWPS READS WRITES COMMAND"; /* these are names given to allowed sorting orders -- first is default */ static char *ordernames[] = @@ -760,8 +759,10 @@ buffer[len] = '\0'; p = buffer; - p = skip_token(p); /* rchar */ - p = skip_token(p); /* wchar */ + p = skip_token(p); /* rchar label */ + p = skip_token(p); /* rchar value */ + p = skip_token(p); /* wchar label */ + p = skip_token(p); /* wchar value */ GET_VALUE(tmp); /* syscr */ proc->syscr[proc->index] = tmp; @@ -776,9 +777,6 @@ GET_VALUE(tmp); /* write_bytes */ proc->write_bytes[proc->index] = tmp; - - GET_VALUE(tmp); /* cancelled_write_bytes */ - proc->write_bytes[proc->index] -= tmp; } caddr_t @@ -975,7 +973,7 @@ struct top_proc *p = &pgtable[proc_index++]; snprintf(fmt, sizeof(fmt), - "%7d %7.0f %7.0f %7.0f %5s %6s %s", + "%7d %10.0f %10.0f %10.0f %5s %6s %s", p->pid, diff_stat(p->iops, p->index) / timediff, diff_stat(p->syscr, p->index) / timediff, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pg_top-4.1.1/machine/m_remote.c new/pg_top-4.1.3/machine/m_remote.c --- old/pg_top-4.1.1/machine/m_remote.c 2024-06-06 23:45:12.000000000 +0200 +++ new/pg_top-4.1.3/machine/m_remote.c 2025-06-30 21:40:53.000000000 +0200 @@ -11,8 +11,7 @@ #include <sys/tree.h> #endif /* __FreeBSD__*/ #ifdef __linux__ -#include <bsd/stdlib.h> -#include <bsd/sys/tree.h> +#include "tree.h" #endif /* __linux__ */ #include <string.h> #include <sys/time.h> @@ -209,7 +208,7 @@ }; static char fmt_header[] = -" PID X SIZE RES STATE XTIME QTIME %CPU LOCKS COMMAND"; +" PID X SIZE RES STATE XTIME QTIME %CPU LOCKS COMMAND"; char fmt_header_io_r[] = " PID RCHAR WCHAR SYSCR SYSCW READS WRITES CWRITES COMMAND"; @@ -714,7 +713,7 @@ struct top_proc_r *p = &pgrtable[proc_r_index++]; snprintf(fmt, sizeof(fmt), - "%7d %-8.8s %5s %5s %-6s %5s %5s %5.1f %5d %s", + "%7d %-10.8s %5s %5s %-6s %5s %5s %5.1f %5d %s", (int) p->pid, /* Some OS's need to cast pid_t to int. */ p->usename, format_k(p->size), diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pg_top-4.1.1/pg.c new/pg_top-4.1.3/pg.c --- old/pg_top-4.1.1/pg.c 2024-06-06 23:45:12.000000000 +0200 +++ new/pg_top-4.1.3/pg.c 2025-06-30 21:40:53.000000000 +0200 @@ -114,8 +114,15 @@ conninfo->connection = PQconnectdbParams(keywords, conninfo->values, 1); if (PQstatus(conninfo->connection) != CONNECTION_OK) { + /* + * I don't think this is pretty, but certain code paths will lose the + * error message because of a screen refresh. I think it's more + * important that the error message gets out there otherwise users + * might not know why the connection failed. + */ new_message(MT_standout | MT_delayed, " %s", PQerrorMessage(conninfo->connection)); + fprintf(stderr, "%s\n", PQerrorMessage(conninfo->connection)); PQfinish(conninfo->connection); conninfo->connection = NULL; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pg_top-4.1.1/pg_top.1.rst.in new/pg_top-4.1.3/pg_top.1.rst.in --- old/pg_top-4.1.1/pg_top.1.rst.in 2024-06-06 23:45:12.000000000 +0200 +++ new/pg_top-4.1.3/pg_top.1.rst.in 2025-06-30 21:40:53.000000000 +0200 @@ -8,7 +8,7 @@ :Author: William LeFebvre, Mark Wong :Manual section: 1 -:Version: 4.0.0 +:Version: @PROJECT_VERSION@ SYNOPSIS ======== diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pg_top-4.1.1/tools/build-appimage new/pg_top-4.1.3/tools/build-appimage --- old/pg_top-4.1.1/tools/build-appimage 2024-06-06 23:45:12.000000000 +0200 +++ new/pg_top-4.1.3/tools/build-appimage 2025-06-30 21:40:53.000000000 +0200 @@ -16,15 +16,9 @@ podman run \ --rm \ + --user "$(id -u):$(id -u)" \ + --userns=keep-id \ -v "${CONTAINER_DIR}/..:/usr/local/src/pg_top:rw,Z" \ -w /usr/local/src/pg_top \ $CONTAINER_TAG \ make -f Makefile.cmake appimage - -podman run \ - --rm \ - -v "${CONTAINER_DIR}/..:/usr/local/src/pg_top:rw,Z" \ - -w /usr/local/src/pg_top \ - -u root \ - $CONTAINER_TAG \ - chown -R root:root builds/appimage/ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pg_top-4.1.1/tree.h new/pg_top-4.1.3/tree.h --- old/pg_top-4.1.1/tree.h 1970-01-01 01:00:00.000000000 +0100 +++ new/pg_top-4.1.3/tree.h 2025-06-30 21:40:53.000000000 +0200 @@ -0,0 +1,517 @@ +/* $NetBSD: tree.h,v 1.8 2004/03/28 19:38:30 provos Exp $ */ +/* $OpenBSD: tree.h,v 1.7 2002/10/17 21:51:54 art Exp $ */ +/* $FreeBSD$ */ + +/*- + * Copyright 2002 Niels Provos <[email protected]> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * pg_top - a top PostgreSQL users display for Unix + * + * SYNOPSIS: Red-black tree implementation ported from BSD + * + * DESCRIPTION: + * This is a standalone implementation of BSD's red-black tree + * data structure, extracted from libbsd for improved portability. + * Originally from BSD's sys/tree.h, modified to work independently + * of libbsd. + * + * Original BSD tree.h by: Niels Provos + */ + + +#ifndef PG_TOP_TREE_H +#define PG_TOP_TREE_H + +/* Macros that define a red-black tree */ +#define RB_HEAD(name, type) \ +struct name { \ + struct type *rbh_root; /* root of the tree */ \ +} + +#define RB_INITIALIZER(root) \ + { NULL } + +#define RB_INIT(root) do { \ + (root)->rbh_root = NULL; \ +} while (/*CONSTCOND*/ 0) + +#define RB_BLACK 0 +#define RB_RED 1 +#define RB_ENTRY(type) \ +struct { \ + struct type *rbe_left; /* left element */ \ + struct type *rbe_right; /* right element */ \ + struct type *rbe_parent; /* parent element */ \ + int rbe_color; /* node color */ \ +} + +#define RB_LEFT(elm, field) (elm)->field.rbe_left +#define RB_RIGHT(elm, field) (elm)->field.rbe_right +#define RB_PARENT(elm, field) (elm)->field.rbe_parent +#define RB_COLOR(elm, field) (elm)->field.rbe_color +#define RB_ROOT(head) (head)->rbh_root +#define RB_EMPTY(head) (RB_ROOT(head) == NULL) + +#define RB_SET(elm, parent, field) do { \ + RB_PARENT(elm, field) = parent; \ + RB_LEFT(elm, field) = RB_RIGHT(elm, field) = NULL; \ + RB_COLOR(elm, field) = RB_RED; \ +} while (/*CONSTCOND*/ 0) + +#define RB_SET_BLACKRED(black, red, field) do { \ + RB_COLOR(black, field) = RB_BLACK; \ + RB_COLOR(red, field) = RB_RED; \ +} while (/*CONSTCOND*/ 0) + +#ifndef RB_AUGMENT +#define RB_AUGMENT(x) do {} while (0) +#endif + +#define RB_ROTATE_LEFT(head, elm, tmp, field) do { \ + (tmp) = RB_RIGHT(elm, field); \ + if ((RB_RIGHT(elm, field) = RB_LEFT(tmp, field)) != NULL) { \ + RB_PARENT(RB_LEFT(tmp, field), field) = (elm); \ + } \ + RB_AUGMENT(elm); \ + if ((RB_PARENT(tmp, field) = RB_PARENT(elm, field)) != NULL) { \ + if ((elm) == RB_LEFT(RB_PARENT(elm, field), field)) \ + RB_LEFT(RB_PARENT(elm, field), field) = (tmp); \ + else \ + RB_RIGHT(RB_PARENT(elm, field), field) = (tmp); \ + } else \ + (head)->rbh_root = (tmp); \ + RB_LEFT(tmp, field) = (elm); \ + RB_PARENT(elm, field) = (tmp); \ + RB_AUGMENT(tmp); \ + if ((RB_PARENT(tmp, field))) \ + RB_AUGMENT(RB_PARENT(tmp, field)); \ +} while (/*CONSTCOND*/ 0) + +#define RB_ROTATE_RIGHT(head, elm, tmp, field) do { \ + (tmp) = RB_LEFT(elm, field); \ + if ((RB_LEFT(elm, field) = RB_RIGHT(tmp, field)) != NULL) { \ + RB_PARENT(RB_RIGHT(tmp, field), field) = (elm); \ + } \ + RB_AUGMENT(elm); \ + if ((RB_PARENT(tmp, field) = RB_PARENT(elm, field)) != NULL) { \ + if ((elm) == RB_LEFT(RB_PARENT(elm, field), field)) \ + RB_LEFT(RB_PARENT(elm, field), field) = (tmp); \ + else \ + RB_RIGHT(RB_PARENT(elm, field), field) = (tmp); \ + } else \ + (head)->rbh_root = (tmp); \ + RB_RIGHT(tmp, field) = (elm); \ + RB_PARENT(elm, field) = (tmp); \ + RB_AUGMENT(tmp); \ + if ((RB_PARENT(tmp, field))) \ + RB_AUGMENT(RB_PARENT(tmp, field)); \ +} while (/*CONSTCOND*/ 0) + +/* Generates prototypes and inline functions */ +#define RB_PROTOTYPE(name, type, field, cmp) \ + RB_PROTOTYPE_INTERNAL(name, type, field, cmp,) +#define RB_PROTOTYPE_STATIC(name, type, field, cmp) \ + RB_PROTOTYPE_INTERNAL(name, type, field, cmp, __unused static) +#define RB_PROTOTYPE_INTERNAL(name, type, field, cmp, attr) \ +attr void name##_RB_INSERT_COLOR(struct name *, struct type *); \ +attr void name##_RB_REMOVE_COLOR(struct name *, struct type *, struct type *);\ +attr struct type *name##_RB_REMOVE(struct name *, struct type *); \ +attr struct type *name##_RB_INSERT(struct name *, struct type *); \ +attr struct type *name##_RB_FIND(struct name *, struct type *); \ +attr struct type *name##_RB_NFIND(struct name *, struct type *); \ +attr struct type *name##_RB_NEXT(struct type *); \ +attr struct type *name##_RB_PREV(struct type *); \ +attr struct type *name##_RB_MINMAX(struct name *, int); \ + \ + +/* Main rb operation. + * Moves node close to the key of elm to top + */ +#define RB_GENERATE(name, type, field, cmp) \ + RB_GENERATE_INTERNAL(name, type, field, cmp,) +#define RB_GENERATE_STATIC(name, type, field, cmp) \ + RB_GENERATE_INTERNAL(name, type, field, cmp, __unused static) +#define RB_GENERATE_INTERNAL(name, type, field, cmp, attr) \ +attr void \ +name##_RB_INSERT_COLOR(struct name *head, struct type *elm) \ +{ \ + struct type *parent, *gparent, *tmp; \ + while ((parent = RB_PARENT(elm, field)) != NULL && \ + RB_COLOR(parent, field) == RB_RED) { \ + gparent = RB_PARENT(parent, field); \ + if (parent == RB_LEFT(gparent, field)) { \ + tmp = RB_RIGHT(gparent, field); \ + if (tmp && RB_COLOR(tmp, field) == RB_RED) { \ + RB_COLOR(tmp, field) = RB_BLACK; \ + RB_SET_BLACKRED(parent, gparent, field);\ + elm = gparent; \ + continue; \ + } \ + if (RB_RIGHT(parent, field) == elm) { \ + RB_ROTATE_LEFT(head, parent, tmp, field);\ + tmp = parent; \ + parent = elm; \ + elm = tmp; \ + } \ + RB_SET_BLACKRED(parent, gparent, field); \ + RB_ROTATE_RIGHT(head, gparent, tmp, field); \ + } else { \ + tmp = RB_LEFT(gparent, field); \ + if (tmp && RB_COLOR(tmp, field) == RB_RED) { \ + RB_COLOR(tmp, field) = RB_BLACK; \ + RB_SET_BLACKRED(parent, gparent, field);\ + elm = gparent; \ + continue; \ + } \ + if (RB_LEFT(parent, field) == elm) { \ + RB_ROTATE_RIGHT(head, parent, tmp, field);\ + tmp = parent; \ + parent = elm; \ + elm = tmp; \ + } \ + RB_SET_BLACKRED(parent, gparent, field); \ + RB_ROTATE_LEFT(head, gparent, tmp, field); \ + } \ + } \ + RB_COLOR(head->rbh_root, field) = RB_BLACK; \ +} \ + \ +attr void \ +name##_RB_REMOVE_COLOR(struct name *head, struct type *parent, struct type *elm) \ +{ \ + struct type *tmp; \ + while ((elm == NULL || RB_COLOR(elm, field) == RB_BLACK) && \ + elm != RB_ROOT(head)) { \ + if (RB_LEFT(parent, field) == elm) { \ + tmp = RB_RIGHT(parent, field); \ + if (RB_COLOR(tmp, field) == RB_RED) { \ + RB_SET_BLACKRED(tmp, parent, field); \ + RB_ROTATE_LEFT(head, parent, tmp, field);\ + tmp = RB_RIGHT(parent, field); \ + } \ + if ((RB_LEFT(tmp, field) == NULL || \ + RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) &&\ + (RB_RIGHT(tmp, field) == NULL || \ + RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK)) {\ + RB_COLOR(tmp, field) = RB_RED; \ + elm = parent; \ + parent = RB_PARENT(elm, field); \ + } else { \ + if (RB_RIGHT(tmp, field) == NULL || \ + RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK) {\ + struct type *oleft; \ + if ((oleft = RB_LEFT(tmp, field)) \ + != NULL) \ + RB_COLOR(oleft, field) = RB_BLACK;\ + RB_COLOR(tmp, field) = RB_RED; \ + RB_ROTATE_RIGHT(head, tmp, oleft, field);\ + tmp = RB_RIGHT(parent, field); \ + } \ + RB_COLOR(tmp, field) = RB_COLOR(parent, field);\ + RB_COLOR(parent, field) = RB_BLACK; \ + if (RB_RIGHT(tmp, field)) \ + RB_COLOR(RB_RIGHT(tmp, field), field) = RB_BLACK;\ + RB_ROTATE_LEFT(head, parent, tmp, field);\ + elm = RB_ROOT(head); \ + break; \ + } \ + } else { \ + tmp = RB_LEFT(parent, field); \ + if (RB_COLOR(tmp, field) == RB_RED) { \ + RB_SET_BLACKRED(tmp, parent, field); \ + RB_ROTATE_RIGHT(head, parent, tmp, field);\ + tmp = RB_LEFT(parent, field); \ + } \ + if ((RB_LEFT(tmp, field) == NULL || \ + RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) &&\ + (RB_RIGHT(tmp, field) == NULL || \ + RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK)) {\ + RB_COLOR(tmp, field) = RB_RED; \ + elm = parent; \ + parent = RB_PARENT(elm, field); \ + } else { \ + if (RB_LEFT(tmp, field) == NULL || \ + RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) {\ + struct type *oright; \ + if ((oright = RB_RIGHT(tmp, field)) \ + != NULL) \ + RB_COLOR(oright, field) = RB_BLACK;\ + RB_COLOR(tmp, field) = RB_RED; \ + RB_ROTATE_LEFT(head, tmp, oright, field);\ + tmp = RB_LEFT(parent, field); \ + } \ + RB_COLOR(tmp, field) = RB_COLOR(parent, field);\ + RB_COLOR(parent, field) = RB_BLACK; \ + if (RB_LEFT(tmp, field)) \ + RB_COLOR(RB_LEFT(tmp, field), field) = RB_BLACK;\ + RB_ROTATE_RIGHT(head, parent, tmp, field);\ + elm = RB_ROOT(head); \ + break; \ + } \ + } \ + } \ + if (elm) \ + RB_COLOR(elm, field) = RB_BLACK; \ +} \ + \ +attr struct type * \ +name##_RB_REMOVE(struct name *head, struct type *elm) \ +{ \ + struct type *child, *parent, *old = elm; \ + int color; \ + if (RB_LEFT(elm, field) == NULL) \ + child = RB_RIGHT(elm, field); \ + else if (RB_RIGHT(elm, field) == NULL) \ + child = RB_LEFT(elm, field); \ + else { \ + struct type *left; \ + elm = RB_RIGHT(elm, field); \ + while ((left = RB_LEFT(elm, field)) != NULL) \ + elm = left; \ + child = RB_RIGHT(elm, field); \ + parent = RB_PARENT(elm, field); \ + color = RB_COLOR(elm, field); \ + if (child) \ + RB_PARENT(child, field) = parent; \ + if (parent) { \ + if (RB_LEFT(parent, field) == elm) \ + RB_LEFT(parent, field) = child; \ + else \ + RB_RIGHT(parent, field) = child; \ + RB_AUGMENT(parent); \ + } else \ + RB_ROOT(head) = child; \ + if (RB_PARENT(elm, field) == old) \ + parent = elm; \ + (elm)->field = (old)->field; \ + if (RB_PARENT(old, field)) { \ + if (RB_LEFT(RB_PARENT(old, field), field) == old)\ + RB_LEFT(RB_PARENT(old, field), field) = elm;\ + else \ + RB_RIGHT(RB_PARENT(old, field), field) = elm;\ + RB_AUGMENT(RB_PARENT(old, field)); \ + } else \ + RB_ROOT(head) = elm; \ + RB_PARENT(RB_LEFT(old, field), field) = elm; \ + if (RB_RIGHT(old, field)) \ + RB_PARENT(RB_RIGHT(old, field), field) = elm; \ + if (parent) { \ + left = parent; \ + do { \ + RB_AUGMENT(left); \ + } while ((left = RB_PARENT(left, field)) != NULL); \ + } \ + goto color; \ + } \ + parent = RB_PARENT(elm, field); \ + color = RB_COLOR(elm, field); \ + if (child) \ + RB_PARENT(child, field) = parent; \ + if (parent) { \ + if (RB_LEFT(parent, field) == elm) \ + RB_LEFT(parent, field) = child; \ + else \ + RB_RIGHT(parent, field) = child; \ + RB_AUGMENT(parent); \ + } else \ + RB_ROOT(head) = child; \ +color: \ + if (color == RB_BLACK) \ + name##_RB_REMOVE_COLOR(head, parent, child); \ + return (old); \ +} \ + \ +/* Inserts a node into the RB tree */ \ +attr struct type * \ +name##_RB_INSERT(struct name *head, struct type *elm) \ +{ \ + struct type *tmp; \ + struct type *parent = NULL; \ + int comp = 0; \ + tmp = RB_ROOT(head); \ + while (tmp) { \ + parent = tmp; \ + comp = (cmp)(elm, parent); \ + if (comp < 0) \ + tmp = RB_LEFT(tmp, field); \ + else if (comp > 0) \ + tmp = RB_RIGHT(tmp, field); \ + else \ + return (tmp); \ + } \ + RB_SET(elm, parent, field); \ + if (parent != NULL) { \ + if (comp < 0) \ + RB_LEFT(parent, field) = elm; \ + else \ + RB_RIGHT(parent, field) = elm; \ + RB_AUGMENT(parent); \ + } else \ + RB_ROOT(head) = elm; \ + name##_RB_INSERT_COLOR(head, elm); \ + return (NULL); \ +} \ + \ +/* Finds the node with the same key as elm */ \ +attr struct type * \ +name##_RB_FIND(struct name *head, struct type *elm) \ +{ \ + struct type *tmp = RB_ROOT(head); \ + int comp; \ + while (tmp) { \ + comp = cmp(elm, tmp); \ + if (comp < 0) \ + tmp = RB_LEFT(tmp, field); \ + else if (comp > 0) \ + tmp = RB_RIGHT(tmp, field); \ + else \ + return (tmp); \ + } \ + return (NULL); \ +} \ + \ +/* Finds the first node greater than or equal to the search key */ \ +attr struct type * \ +name##_RB_NFIND(struct name *head, struct type *elm) \ +{ \ + struct type *tmp = RB_ROOT(head); \ + struct type *res = NULL; \ + int comp; \ + while (tmp) { \ + comp = cmp(elm, tmp); \ + if (comp < 0) { \ + res = tmp; \ + tmp = RB_LEFT(tmp, field); \ + } \ + else if (comp > 0) \ + tmp = RB_RIGHT(tmp, field); \ + else \ + return (tmp); \ + } \ + return (res); \ +} \ + \ +/* ARGSUSED */ \ +attr struct type * \ +name##_RB_NEXT(struct type *elm) \ +{ \ + if (RB_RIGHT(elm, field)) { \ + elm = RB_RIGHT(elm, field); \ + while (RB_LEFT(elm, field)) \ + elm = RB_LEFT(elm, field); \ + } else { \ + if (RB_PARENT(elm, field) && \ + (elm == RB_LEFT(RB_PARENT(elm, field), field))) \ + elm = RB_PARENT(elm, field); \ + else { \ + while (RB_PARENT(elm, field) && \ + (elm == RB_RIGHT(RB_PARENT(elm, field), field)))\ + elm = RB_PARENT(elm, field); \ + elm = RB_PARENT(elm, field); \ + } \ + } \ + return (elm); \ +} \ + \ +/* ARGSUSED */ \ +attr struct type * \ +name##_RB_PREV(struct type *elm) \ +{ \ + if (RB_LEFT(elm, field)) { \ + elm = RB_LEFT(elm, field); \ + while (RB_RIGHT(elm, field)) \ + elm = RB_RIGHT(elm, field); \ + } else { \ + if (RB_PARENT(elm, field) && \ + (elm == RB_RIGHT(RB_PARENT(elm, field), field))) \ + elm = RB_PARENT(elm, field); \ + else { \ + while (RB_PARENT(elm, field) && \ + (elm == RB_LEFT(RB_PARENT(elm, field), field)))\ + elm = RB_PARENT(elm, field); \ + elm = RB_PARENT(elm, field); \ + } \ + } \ + return (elm); \ +} \ + \ +attr struct type * \ +name##_RB_MINMAX(struct name *head, int val) \ +{ \ + struct type *tmp = RB_ROOT(head); \ + struct type *parent = NULL; \ + while (tmp) { \ + parent = tmp; \ + if (val < 0) \ + tmp = RB_LEFT(tmp, field); \ + else \ + tmp = RB_RIGHT(tmp, field); \ + } \ + return (parent); \ +} + +#define RB_NEGINF -1 +#define RB_INF 1 + +#define RB_INSERT(name, x, y) name##_RB_INSERT(x, y) +#define RB_REMOVE(name, x, y) name##_RB_REMOVE(x, y) +#define RB_FIND(name, x, y) name##_RB_FIND(x, y) +#define RB_NFIND(name, x, y) name##_RB_NFIND(x, y) +#define RB_NEXT(name, x, y) name##_RB_NEXT(y) +#define RB_PREV(name, x, y) name##_RB_PREV(y) +#define RB_MIN(name, x) name##_RB_MINMAX(x, RB_NEGINF) +#define RB_MAX(name, x) name##_RB_MINMAX(x, RB_INF) + +#define RB_FOREACH(x, name, head) \ + for ((x) = RB_MIN(name, head); \ + (x) != NULL; \ + (x) = name##_RB_NEXT(x)) + +#define RB_FOREACH_FROM(x, name, y) \ + for ((x) = (y); \ + ((x) != NULL) && ((y) = name##_RB_NEXT(x), (x) != NULL); \ + (x) = (y)) + +#define RB_FOREACH_SAFE(x, name, head, y) \ + for ((x) = RB_MIN(name, head); \ + ((x) != NULL) && ((y) = name##_RB_NEXT(x), (x) != NULL); \ + (x) = (y)) + +#define RB_FOREACH_REVERSE(x, name, head) \ + for ((x) = RB_MAX(name, head); \ + (x) != NULL; \ + (x) = name##_RB_PREV(x)) + +#define RB_FOREACH_REVERSE_FROM(x, name, y) \ + for ((x) = (y); \ + ((x) != NULL) && ((y) = name##_RB_PREV(x), (x) != NULL); \ + (x) = (y)) + +#define RB_FOREACH_REVERSE_SAFE(x, name, head, y) \ + for ((x) = RB_MAX(name, head); \ + ((x) != NULL) && ((y) = name##_RB_PREV(x), (x) != NULL); \ + (x) = (y)) +#endif \ No newline at end of file ++++++ pg_top.obsinfo ++++++ --- /var/tmp/diff_new_pack.iTTFaG/_old 2026-06-30 15:14:15.077702992 +0200 +++ /var/tmp/diff_new_pack.iTTFaG/_new 2026-06-30 15:14:15.081703127 +0200 @@ -1,5 +1,5 @@ name: pg_top -version: 4.1.1 -mtime: 1717710312 -commit: 3fffe83e7132e1a119b2f12f94011cf0b2394fc0 +version: 4.1.3 +mtime: 1751312453 +commit: 510b6801cdf9ec9d5aa6d2aeccf39fc0df673787
