Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package libqb for openSUSE:Factory checked 
in at 2021-11-18 10:33:14
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/libqb (Old)
 and      /work/SRC/openSUSE:Factory/.libqb.new.1895 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "libqb"

Thu Nov 18 10:33:14 2021 rev:31 rq:931807 version:2.0.4+20211112.a2691b9

Changes:
--------
--- /work/SRC/openSUSE:Factory/libqb/libqb.changes      2021-10-11 
16:48:50.846189828 +0200
+++ /work/SRC/openSUSE:Factory/.libqb.new.1895/libqb.changes    2021-11-18 
10:33:37.555895807 +0100
@@ -1,0 +2,9 @@
+Tue Nov 16 08:42:20 UTC 2021 - Yan Gao <y...@suse.com>
+
+- Update to version 2.0.4+20211112.a2691b9 (v2.0.4):
+- poll: Don't log in a signal handler (gh#ClusterLabs/libqb##447)
+- Fix pthread returns (gh#ClusterLabs/libqb#444)
+- doxygen2man: print structure descriptions (gh#ClusterLabs/libqb#443)
+- Implement heap based timer list (gh#ClusterLabs/libqb#439)
+
+-------------------------------------------------------------------

Old:
----
  libqb-2.0.3+20210303.404adbc.tar.xz

New:
----
  libqb-2.0.4+20211112.a2691b9.tar.xz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ libqb.spec ++++++
--- /var/tmp/diff_new_pack.cKb8C7/_old  2021-11-18 10:33:38.075896292 +0100
+++ /var/tmp/diff_new_pack.cKb8C7/_new  2021-11-18 10:33:38.079896295 +0100
@@ -21,7 +21,7 @@
 %bcond_without doxygen2man
 
 Name:           libqb
-Version:        2.0.3+20210303.404adbc
+Version:        2.0.4+20211112.a2691b9
 Release:        0
 Summary:        An IPC library for high performance servers
 License:        LGPL-2.1-or-later

++++++ _service ++++++
--- /var/tmp/diff_new_pack.cKb8C7/_old  2021-11-18 10:33:38.103896317 +0100
+++ /var/tmp/diff_new_pack.cKb8C7/_new  2021-11-18 10:33:38.103896317 +0100
@@ -8,10 +8,10 @@
     To update to a new release, change "revision" to the desired
     git commit hash and bump "version" if necessary
 
-    <param name="version">2.0.3</param>
+    <param name="version">2.0.4</param>
 -->
-    <param name="versionformat">2.0.3+%cd.%h</param>
-    <param name="revision">v2.0.3</param>
+    <param name="versionformat">2.0.4+%cd.%h</param>
+    <param name="revision">v2.0.4</param>
     <param name="changesgenerate">enable</param>
   </service>
 

++++++ _servicedata ++++++
--- /var/tmp/diff_new_pack.cKb8C7/_old  2021-11-18 10:33:38.119896332 +0100
+++ /var/tmp/diff_new_pack.cKb8C7/_new  2021-11-18 10:33:38.119896332 +0100
@@ -1,6 +1,6 @@
 <servicedata>
   <service name="tar_scm">
     <param name="url">git://github.com/ClusterLabs/libqb.git</param>
-    <param 
name="changesrevision">404adbcd998ec83643e47d92b3ea8d9c3970e68b</param>
+    <param 
name="changesrevision">a2691b96188033b5ad5c08871982048ae1f4f4e8</param>
   </service>
 </servicedata>
\ No newline at end of file

++++++ libqb-2.0.3+20210303.404adbc.tar.xz -> 
libqb-2.0.4+20211112.a2691b9.tar.xz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libqb-2.0.3+20210303.404adbc/doxygen2man/cstring.c 
new/libqb-2.0.4+20211112.a2691b9/doxygen2man/cstring.c
--- old/libqb-2.0.3+20210303.404adbc/doxygen2man/cstring.c      2021-03-03 
09:32:09.000000000 +0100
+++ new/libqb-2.0.4+20211112.a2691b9/doxygen2man/cstring.c      2021-11-12 
14:18:47.000000000 +0100
@@ -41,7 +41,7 @@
 
 char *cstring_to_chars(cstring_t cstring)
 {
-       struct cstring_header *h = (struct cstring_header *)(char *)cstring;
+       struct cstring_header *h = (struct cstring_header *)cstring;
 
        if (!h) {
                return NULL;
@@ -51,9 +51,22 @@
        return strdup(h->the_string);
 }
 
+size_t cstring_len(cstring_t cstring)
+{
+       struct cstring_header *h = (struct cstring_header *)cstring;
+
+       if (!h) {
+               return 0;
+       }
+
+       assert(h->checker == CHECKER_WORD);
+       return h->used;
+}
+
+
 cstring_t cstring_append_chars(cstring_t cstring, const char *newstring)
 {
-       struct cstring_header *h = (struct cstring_header *)(char *)cstring;
+       struct cstring_header *h = (struct cstring_header *)cstring;
        size_t newlen;
 
        if (!h) {
@@ -74,7 +87,7 @@
                }
 
                cstring = tmp;
-               h = (struct cstring_header *)(char *)cstring;
+               h = (struct cstring_header *)cstring;
                h->allocated = new_allocsize;
        }
        strncat(h->the_string, newstring, h->allocated - h->used -1);
@@ -85,7 +98,7 @@
 cstring_t cstring_append_cstring(cstring_t cstring, cstring_t newstring)
 {
        /* Just check the newstring - cstring_append_chars() will check the 
target */
-       struct cstring_header *h = (struct cstring_header *)(char *)newstring;
+       struct cstring_header *h = (struct cstring_header *)newstring;
 
        if (!h) {
                return NULL;
@@ -106,7 +119,7 @@
 
 void cstring_free(cstring_t cstring)
 {
-       struct cstring_header *h = (struct cstring_header *)(char *)cstring;
+       struct cstring_header *h = (struct cstring_header *)cstring;
 
        if (!h) {
                return;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libqb-2.0.3+20210303.404adbc/doxygen2man/cstring.h 
new/libqb-2.0.4+20211112.a2691b9/doxygen2man/cstring.h
--- old/libqb-2.0.3+20210303.404adbc/doxygen2man/cstring.h      2021-03-03 
09:32:09.000000000 +0100
+++ new/libqb-2.0.4+20211112.a2691b9/doxygen2man/cstring.h      2021-11-12 
14:18:47.000000000 +0100
@@ -10,5 +10,6 @@
 cstring_t cstring_append_chars(cstring_t cstring, const char *newstring);
 cstring_t cstring_append_cstring(cstring_t cstring, cstring_t newstring);
 void cstring_free(cstring_t cstring);
+size_t cstring_len(cstring_t cstring);
 
 #endif
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/libqb-2.0.3+20210303.404adbc/doxygen2man/doxygen2man.c 
new/libqb-2.0.4+20211112.a2691b9/doxygen2man/doxygen2man.c
--- old/libqb-2.0.3+20210303.404adbc/doxygen2man/doxygen2man.c  2021-03-03 
09:32:09.000000000 +0100
+++ new/libqb-2.0.4+20211112.a2691b9/doxygen2man/doxygen2man.c  2021-11-12 
14:18:47.000000000 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2018-2020 Red Hat, Inc.  All rights reserved.
+ * Copyright (C) 2018-2021 Red Hat, Inc.  All rights reserved.
  *
  * Author: Christine Caulfield <ccaul...@redhat.com>
  *
@@ -43,6 +43,9 @@
  */
 #define LINE_LENGTH 80
 
+/* Similar - but for structure member comments */
+#define STRUCT_COMMENT_LENGTH 50
+
 static int print_ascii = 1;
 static int print_man = 0;
 static int print_params = 0;
@@ -87,9 +90,10 @@
        struct qb_list_head list;
 };
 
-static cstring_t get_texttree(int *type, xmlNode *cur_node, char **returntext, 
char **notetext);
+static cstring_t get_texttree(int *type, xmlNode *cur_node, char **returntext, 
char **notetext, int add_nl);
 static void traverse_node(xmlNode *parentnode, const char *leafname, void 
(do_members(xmlNode*, void*)), void *arg);
 static cstring_t get_text(xmlNode *cur_node, char **returntext, char 
**notetext);
+static void man_print_long_string(FILE *manfile, char *text);
 
 static void free_paraminfo(struct param_info *pi)
 {
@@ -189,7 +193,8 @@
                                sub_tag->children->next->children) {
                                paramname = 
(char*)sub_tag->children->next->children->content;
                        }
-                       if (sub_tag->type == XML_ELEMENT_NODE && strcmp((char 
*)sub_tag->name, "parameterdescription") == 0 &&
+                       if (sub_tag->type == XML_ELEMENT_NODE &&
+                           strcmp((char *)sub_tag->name, 
"parameterdescription") == 0 &&
                            paramname && sub_tag->children->next->children) {
                                paramdesc = 
(char*)sub_tag->children->next->children->content;
 
@@ -353,7 +358,7 @@
                                buffer = cstring_append_chars(buffer, "\n");
                                cstring_free(tmp);
 
-                               tmp = get_texttree(&type,this_tag, NULL, NULL);
+                               tmp = get_texttree(&type,this_tag, NULL, NULL, 
1);
                                buffer = cstring_append_cstring(buffer, tmp);
                                buffer = cstring_append_chars(buffer, "\n");
                        }
@@ -392,12 +397,12 @@
 
        for (this_tag = cur_node->children; this_tag; this_tag = 
this_tag->next) {
                if (strcmp((char*)this_tag->name, "detaileddescription") == 0) {
-                       cstring_t desc = get_texttree(NULL, this_tag, NULL, 
NULL);
+                       cstring_t desc = get_texttree(NULL, this_tag, NULL, 
NULL, 1);
                        si->description = cstring_to_chars(desc);
                        cstring_free(desc);
                }
                if (strcmp((char*)this_tag->name, "briefdescription") == 0) {
-                       cstring_t brief = get_texttree(NULL, this_tag, NULL, 
NULL);
+                       cstring_t brief = get_texttree(NULL, this_tag, NULL, 
NULL, 1);
                        si->brief_description = cstring_to_chars(brief);
                }
        }
@@ -422,10 +427,11 @@
 {
        xmlNode *this_tag;
        struct struct_info *si=arg;
-       struct param_info *pi;
+       struct param_info *pi = NULL;
        char fullname[1024];
        char *type = NULL;
        char *name = NULL;
+       char *desc = NULL;
        const char *args="";
 
        for (this_tag = cur_node->children; this_tag; this_tag = 
this_tag->next) {
@@ -444,6 +450,13 @@
                if (this_tag->children && strcmp((char*)this_tag->name, 
"argsstring") == 0) {
                        args = (char*)this_tag->children->content;
                }
+               if (this_tag->children && strcmp((char*)this_tag->name, 
"detaileddescription") == 0) {
+                       cstring_t *desc_cs = get_texttree(NULL, this_tag, NULL, 
NULL, 0);
+                       if (cstring_len(desc_cs) > 1) {
+                               desc = cstring_to_chars(desc_cs);
+                       }
+                       cstring_free(desc_cs);
+               }
        }
 
        if (name) {
@@ -452,10 +465,14 @@
                        snprintf(fullname, sizeof(fullname), "%s%s", name, 
args);
                        pi->paramtype = type?strdup(type):strdup("");
                        pi->paramname = strdup(fullname);
-                       pi->paramdesc = NULL;
+                       pi->paramdesc = desc;
                        qb_list_add_tail(&pi->list, &si->params_list);
                }
        }
+       /* Tidy */
+       if (!name || !pi) {
+               free(desc);
+       }
 }
 
 static int read_structure_from_xml(const char *refid, const char *name)
@@ -517,7 +534,31 @@
        return buffer;
 }
 
-static void print_param(FILE *manfile, struct param_info *pi, int field_width, 
int bold, const char *delimiter)
+/*
+ * Print a structure comment that would be too long
+ * to fit after the structure member, in a style ...
+ * well, in a style like this!
+ */
+static void print_long_structure_comment(FILE *manfile, char *comment)
+{
+       char *ptr = strtok(comment, " ");
+       int column = 7;
+
+       fprintf(manfile, "\\fP    /*");
+       fprintf(manfile, "\n     *");
+       while (ptr) {
+               column += strlen(ptr)+1;
+               if (column > 80) {
+                       fprintf(manfile, "\n     *");
+                       column = 7;
+               }
+               fprintf(manfile, " %s", ptr);
+               ptr = strtok(NULL, " ");
+       }
+       fprintf(manfile, "\n     */\n");
+}
+
+static void print_param(FILE *manfile, struct param_info *pi, int 
type_field_width, int name_field_width, int bold, const char *delimiter)
 {
        const char *asterisks = "  ";
        char *type = pi->paramtype;
@@ -542,10 +583,32 @@
                }
        }
 
-       fprintf(manfile, "    %s%-*s%s%s\\fI%s\\fP%s\n",
-               bold?"\\fB":"", field_width, type,
-               asterisks, bold?"\\fP":"",
-               pi->paramname?pi->paramname:"", delimiter);
+       /* Print structure description if available */
+       if (pi->paramdesc) {
+               /* Too long to go on the same line? */
+               if (strlen(pi->paramdesc) > STRUCT_COMMENT_LENGTH) {
+                       print_long_structure_comment(manfile, pi->paramdesc);
+                       fprintf(manfile, "    %s%-*s%s%s\\fI%s\\fP%s\n",
+                               bold?"\\fB":"", type_field_width, type,
+                               asterisks, bold?"\\fP":"",
+                               pi->paramname?pi->paramname:"", delimiter);
+               } else {
+                       /* Pad out so they all line up */
+                       int pad_length = name_field_width -
+                               (pi->paramname?strlen(pi->paramname):0) + 1;
+                       fprintf(manfile, "    %s%-*s%s%s\\fI%s\\fP%s\\fR%*s/* 
%s*/\n",
+                               bold?"\\fB":"", type_field_width, type,
+                               asterisks, bold?"\\fP":"",
+                               pi->paramname?pi->paramname:"", delimiter,
+                               pad_length, " ",
+                               pi->paramdesc);
+               }
+       } else {
+               fprintf(manfile, "    %s%-*s%s%s\\fI%s\\fP%s\n",
+                       bold?"\\fB":"", type_field_width, type,
+                       asterisks, bold?"\\fP":"",
+                       pi->paramname?pi->paramname:"", delimiter);
+       }
 
        if (type != pi->paramtype) {
                free(type);
@@ -557,9 +620,9 @@
        struct param_info *pi;
        struct qb_list_head *iter;
        unsigned int max_param_length=0;
+       unsigned int max_param_name_length=0;
 
        fprintf(manfile, ".nf\n");
-       fprintf(manfile, "\\fB\n");
 
        if (si->brief_description) {
                fprintf(manfile, "%s\n", si->brief_description);
@@ -573,8 +636,12 @@
                if (strlen(pi->paramtype) > max_param_length) {
                        max_param_length = strlen(pi->paramtype);
                }
+               if (strlen(pi->paramname) > max_param_name_length) {
+                       max_param_name_length = strlen(pi->paramname);
+               }
        }
 
+       fprintf(manfile, "\\fB\n");
        if (si->kind == STRUCTINFO_STRUCT) {
                fprintf(manfile, "struct %s {\n", si->structname);
        } else if (si->kind == STRUCTINFO_ENUM) {
@@ -582,10 +649,12 @@
        } else {
                fprintf(manfile, "%s {\n", si->structname);
        }
+       fprintf(manfile, "\\fR\n");
 
        qb_list_for_each(iter, &si->params_list) {
+               fprintf(manfile, "\\fB\n");
                pi = qb_list_entry(iter, struct param_info, list);
-               print_param(manfile, pi, max_param_length, 0,";");
+               print_param(manfile, pi, max_param_length, 
max_param_name_length, 1, ";");
        }
        fprintf(manfile, "};\n");
 
@@ -593,7 +662,7 @@
        fprintf(manfile, ".fi\n");
 }
 
-cstring_t get_texttree(int *type, xmlNode *cur_node, char **returntext, char 
**notetext)
+cstring_t get_texttree(int *type, xmlNode *cur_node, char **returntext, char 
**notetext, int add_nl)
 {
        xmlNode *this_tag;
        cstring_t tmp;
@@ -604,7 +673,9 @@
                if (this_tag->type == XML_ELEMENT_NODE && strcmp((char 
*)this_tag->name, "para") == 0) {
                        tmp = get_text(this_tag, returntext, notetext);
                        buffer = cstring_append_cstring(buffer, tmp);
-                       buffer = cstring_append_chars(buffer, "\n");
+                       if (add_nl) {
+                               buffer = cstring_append_chars(buffer, "\n");
+                       }
 
                        cstring_free(tmp);
                }
@@ -779,8 +850,8 @@
                qb_list_for_each(iter, param_map) {
                        pi = qb_list_entry(iter, struct param_info, list);
 
-                       if (pi->paramtype[0] != '\0') { //CC
-                               print_param(manfile, pi, max_param_type_len, 1, 
++param_num < param_count?",":"");
+                       if (pi->paramtype[0] != '\0') {
+                               print_param(manfile, pi, max_param_type_len, 0, 
1, ++param_num < param_count?",":"");
                        }
                }
 
@@ -1007,7 +1078,7 @@
                                name = strdup((char 
*)this_tag->children->content);
 
                        if (this_tag->type == XML_ELEMENT_NODE && strcmp((char 
*)this_tag->name, "briefdescription") == 0) {
-                               cstring_t tmp = get_texttree(&type, this_tag, 
&returntext, &notetext);
+                               cstring_t tmp = get_texttree(&type, this_tag, 
&returntext, &notetext, 1);
                                if (!brief) {
                                        brief = cstring_to_chars(tmp);
                                } else {
@@ -1016,7 +1087,7 @@
                                cstring_free(tmp);
                        }
                        if (this_tag->type == XML_ELEMENT_NODE && strcmp((char 
*)this_tag->name, "detaileddescription") == 0) {
-                               cstring_t tmp = get_texttree(&type, this_tag, 
&returntext, &notetext);
+                               cstring_t tmp = get_texttree(&type, this_tag, 
&returntext, &notetext, 1);
                                if (!detailed) {
                                        detailed = cstring_to_chars(tmp);
                                } else {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libqb-2.0.3+20210303.404adbc/include/tlist.h 
new/libqb-2.0.4+20211112.a2691b9/include/tlist.h
--- old/libqb-2.0.3+20210303.404adbc/include/tlist.h    2021-03-03 
09:32:09.000000000 +0100
+++ new/libqb-2.0.4+20211112.a2691b9/include/tlist.h    2021-11-12 
14:18:47.000000000 +0100
@@ -1,7 +1,8 @@
 /*
- * Copyright (c) 2006-2007, 2009 Red Hat, Inc.
+ * Copyright (c) 2006-2007, 2009-2021 Red Hat, Inc.
  *
- * Author: Steven Dake <sd...@redhat.com>
+ * Author: Jan Friesse <jfrie...@redhat.com>
+ *         Steven Dake <sd...@redhat.com>
  *
  * This file is part of libqb.
  *
@@ -35,52 +36,284 @@
 static int64_t timerlist_hertz;
 
 struct timerlist {
-       struct qb_list_head timer_head;
+       struct timerlist_timer **heap_entries;
+       size_t allocated;
+       size_t size;
        pthread_mutex_t list_mutex;
 };
 
 struct timerlist_timer {
-       struct qb_list_head list;
        uint64_t expire_time;
        int32_t is_absolute_timer;
        void (*timer_fn) (void *data);
        void *data;
        timer_handle handle_addr;
+       size_t heap_pos;
 };
 
+/*
+ * Heap helper functions
+ */
+static inline size_t
+timerlist_heap_index_left(size_t index)
+{
+
+       return (2 * index + 1);
+}
+
+static inline size_t
+timerlist_heap_index_right(size_t index)
+{
+
+       return (2 * index + 2);
+}
+
+static inline size_t
+timerlist_heap_index_parent(size_t index)
+{
+
+       return ((index - 1) / 2);
+}
+
+static inline void
+timerlist_heap_entry_set(struct timerlist *timerlist, size_t item_pos, struct 
timerlist_timer *timer)
+{
+
+       assert(item_pos < timerlist->size);
+
+       timerlist->heap_entries[item_pos] = timer;
+       timerlist->heap_entries[item_pos]->heap_pos = item_pos;
+}
+
+static inline struct timerlist_timer *
+timerlist_heap_entry_get(struct timerlist *timerlist, size_t item_pos)
+{
+
+       assert(item_pos < timerlist->size);
+
+       return (timerlist->heap_entries[item_pos]);
+}
+
+static inline int
+timerlist_entry_cmp(const struct timerlist_timer *t1, const struct 
timerlist_timer *t2)
+{
+
+       if (t1->expire_time == t2->expire_time) {
+               return (0);
+       } else if (t1->expire_time < t2->expire_time) {
+               return (-1);
+       } else {
+               return (1);
+       }
+}
+
+static inline void
+timerlist_heap_sift_up(struct timerlist *timerlist, size_t item_pos)
+{
+       size_t parent_pos;
+       struct timerlist_timer *parent_timer;
+       struct timerlist_timer *timer;
+
+       timer = timerlist_heap_entry_get(timerlist, item_pos);
+
+       parent_pos = timerlist_heap_index_parent(item_pos);
+
+       while (item_pos > 0 &&
+           (parent_timer = timerlist_heap_entry_get(timerlist, parent_pos),
+           timerlist_entry_cmp(parent_timer, timer) > 0)) {
+               /*
+                * Swap item and parent
+                */
+               timerlist_heap_entry_set(timerlist, parent_pos, timer);
+               timerlist_heap_entry_set(timerlist, item_pos, parent_timer);
+
+               item_pos = parent_pos;
+               parent_pos = timerlist_heap_index_parent(item_pos);
+       }
+}
+
+static inline void
+timerlist_heap_sift_down(struct timerlist *timerlist, size_t item_pos)
+{
+       int cont;
+       size_t left_pos, right_pos, smallest_pos;
+       struct timerlist_timer *left_entry;
+       struct timerlist_timer *right_entry;
+       struct timerlist_timer *smallest_entry;
+       struct timerlist_timer *tmp_entry;
+
+       cont = 1;
+
+       while (cont) {
+               smallest_pos = item_pos;
+               left_pos = timerlist_heap_index_left(item_pos);
+               right_pos = timerlist_heap_index_right(item_pos);
+
+               smallest_entry = timerlist_heap_entry_get(timerlist, 
smallest_pos);
+
+               if (left_pos < timerlist->size &&
+                   (left_entry = timerlist_heap_entry_get(timerlist, left_pos),
+                   timerlist_entry_cmp(left_entry, smallest_entry) < 0)) {
+                       smallest_entry = left_entry;
+                       smallest_pos = left_pos;
+               }
+
+               if (right_pos < timerlist->size &&
+                   (right_entry = timerlist_heap_entry_get(timerlist, 
right_pos),
+                   timerlist_entry_cmp(right_entry, smallest_entry) < 0)) {
+                       smallest_entry = right_entry;
+                       smallest_pos = right_pos;
+               }
+
+               if (smallest_pos == item_pos) {
+                       /*
+                        * Item is smallest (or has no children) -> heap 
property is restored
+                        */
+                       cont = 0;
+               } else {
+                       /*
+                        * Swap item with smallest child
+                        */
+                       tmp_entry = timerlist_heap_entry_get(timerlist, 
item_pos);
+                       timerlist_heap_entry_set(timerlist, item_pos, 
smallest_entry);
+                       timerlist_heap_entry_set(timerlist, smallest_pos, 
tmp_entry);
+
+                       item_pos = smallest_pos;
+               }
+       }
+}
+
+static inline void
+timerlist_heap_delete(struct timerlist *timerlist, struct timerlist_timer 
*entry)
+{
+       size_t entry_pos;
+       struct timerlist_timer *replacement_entry;
+       int cmp_entries;
+
+       entry_pos = entry->heap_pos;
+       entry->heap_pos = (~(size_t)0);
+
+       /*
+        * Swap element with last element
+        */
+       replacement_entry = timerlist_heap_entry_get(timerlist, timerlist->size 
- 1);
+       timerlist_heap_entry_set(timerlist, entry_pos, replacement_entry);
+
+       /*
+        * And "remove" last element (= entry)
+        */
+       timerlist->size--;
+
+       /*
+        * Up (or down) heapify based on replacement item size
+        */
+       cmp_entries = timerlist_entry_cmp(replacement_entry, entry);
+
+       if (cmp_entries < 0) {
+               timerlist_heap_sift_up(timerlist, entry_pos);
+       } else if (cmp_entries > 0) {
+               timerlist_heap_sift_down(timerlist, entry_pos);
+       }
+}
+
+/*
+ * Check if heap is valid.
+ * - Shape property is always fullfiled because of storage in array
+ * - Check heap property
+ */
+static inline int
+timerlist_debug_is_valid_heap(struct timerlist *timerlist)
+{
+       size_t i;
+       size_t left_pos, right_pos;
+       struct timerlist_timer *left_entry;
+       struct timerlist_timer *right_entry;
+       struct timerlist_timer *cur_entry;
+
+       for (i = 0; i < timerlist->size; i++) {
+               cur_entry = timerlist_heap_entry_get(timerlist, i);
+
+               left_pos = timerlist_heap_index_left(i);
+               right_pos = timerlist_heap_index_right(i);
+
+               if (left_pos < timerlist->size &&
+                   (left_entry = timerlist_heap_entry_get(timerlist, left_pos),
+                   timerlist_entry_cmp(left_entry, cur_entry) < 0)) {
+                       return (0);
+               }
+
+               if (right_pos < timerlist->size &&
+                   (right_entry = timerlist_heap_entry_get(timerlist, 
right_pos),
+                   timerlist_entry_cmp(right_entry, cur_entry) < 0)) {
+                       return (0);
+               }
+       }
+
+       return (1);
+}
+
+/*
+ * Main functions implementation
+ */
 static inline void timerlist_init(struct timerlist *timerlist)
 {
-       qb_list_init(&timerlist->timer_head);
+
+       memset(timerlist, 0, sizeof(*timerlist));
+
+       timerlist->heap_entries = NULL;
        pthread_mutex_init(&timerlist->list_mutex, NULL);
        timerlist_hertz = qb_util_nano_monotonic_hz();
 }
 
+static inline void timerlist_destroy(struct timerlist *timerlist)
+{
+       size_t zi;
+
+       pthread_mutex_destroy(&timerlist->list_mutex);
+
+       for (zi = 0; zi < timerlist->size; zi++) {
+               free(timerlist->heap_entries[zi]);
+       }
+       free(timerlist->heap_entries);
+}
+
 static inline int32_t timerlist_add(struct timerlist *timerlist,
                                 struct timerlist_timer *timer)
 {
-       struct qb_list_head *timer_list = 0;
-       struct timerlist_timer *timer_from_list;
-       int32_t found = QB_FALSE;
+       size_t new_size;
+       struct timerlist_timer **new_heap_entries;
+       int32_t res = 0;
 
-       if (pthread_mutex_lock(&timerlist->list_mutex)) {
-               return -errno;
+       if ( (res=pthread_mutex_lock(&timerlist->list_mutex))) {
+               return -res;
        }
-       qb_list_for_each(timer_list, &timerlist->timer_head) {
 
-               timer_from_list = qb_list_entry(timer_list,
-                                               struct timerlist_timer, list);
+       /*
+        * Check that heap array is large enough
+        */
+       if (timerlist->size + 1 > timerlist->allocated) {
+               new_size = (timerlist->allocated + 1) * 2;
 
-               if (timer_from_list->expire_time > timer->expire_time) {
-                       qb_list_add_tail(&timer->list, timer_list);
-                       found = QB_TRUE;
-                       break;  /* for timer iteration */
+               new_heap_entries = realloc(timerlist->heap_entries,
+                   new_size * sizeof(timerlist->heap_entries[0]));
+               if (new_heap_entries == NULL) {
+                       res = -errno;
+
+                       goto cleanup;
                }
+
+               timerlist->allocated = new_size;
+               timerlist->heap_entries = new_heap_entries;
        }
-       if (found == QB_FALSE) {
-               qb_list_add_tail(&timer->list, &timerlist->timer_head);
-       }
+
+       timerlist->size++;
+
+       timerlist_heap_entry_set(timerlist, timerlist->size - 1, timer);
+       timerlist_heap_sift_up(timerlist, timerlist->size - 1);
+
+cleanup:
        pthread_mutex_unlock(&timerlist->list_mutex);
-       return 0;
+       return res;
 }
 
 static inline int32_t timerlist_add_duration(struct timerlist *timerlist,
@@ -94,7 +327,8 @@
 
        timer =
            (struct timerlist_timer *)malloc(sizeof(struct timerlist_timer));
-       if (timer == 0) {
+
+       if (timer == NULL) {
                return -ENOMEM;
        }
 
@@ -113,15 +347,23 @@
        return (0);
 }
 
-static inline void timerlist_del(struct timerlist *timerlist,
+static inline int32_t timerlist_del(struct timerlist *timerlist,
                                 timer_handle _timer_handle)
 {
        struct timerlist_timer *timer = (struct timerlist_timer *)_timer_handle;
+       int res;
+
+       if ( (res=pthread_mutex_lock(&timerlist->list_mutex))) {
+               return -res;
+       }
 
        memset(timer->handle_addr, 0, sizeof(struct timerlist_timer *));
-       qb_list_del(&timer->list);
-       qb_list_init(&timer->list);
+
+       timerlist_heap_delete(timerlist, timer);
        free(timer);
+
+       pthread_mutex_unlock(&timerlist->list_mutex);
+       return 0;
 }
 
 static inline uint64_t timerlist_expire_time(struct timerlist
@@ -140,8 +382,8 @@
        struct timerlist_timer *timer = (struct timerlist_timer *)_timer_handle;
 
        memset(timer->handle_addr, 0, sizeof(struct timerlist_timer *));
-       qb_list_del(&timer->list);
-       qb_list_init(&timer->list);
+
+       timerlist_heap_delete(timerlist, timer);
 }
 
 static inline void timerlist_post_dispatch(struct timerlist *timerlist,
@@ -162,14 +404,27 @@
        volatile uint64_t msec_duration_to_expire;
 
        /*
+        * There is really no reasonable value to return when mutex lock fails
+        */
+       if (pthread_mutex_lock(&timerlist->list_mutex)) {
+               return (-1);
+       }
+
+       /*
         * empty list, no expire
         */
-       if (qb_list_empty(&timerlist->timer_head)) {
+       if (timerlist->size == 0) {
+               pthread_mutex_unlock(&timerlist->list_mutex);
+
                return (-1);
        }
 
-       timer_from_list = qb_list_first_entry(&timerlist->timer_head,
-                                       struct timerlist_timer, list);
+       timer_from_list = timerlist_heap_entry_get(timerlist, 0);
+
+       /*
+        * Mutex is no longer needed
+        */
+       pthread_mutex_unlock(&timerlist->list_mutex);
 
        if (timer_from_list->is_absolute_timer) {
                current_time = qb_util_nano_from_epoch_get();
@@ -193,38 +448,43 @@
 /*
  * Expires any timers that should be expired
  */
-static inline void timerlist_expire(struct timerlist *timerlist)
+static inline int32_t timerlist_expire(struct timerlist *timerlist)
 {
-       struct timerlist_timer *timer_from_list;
-       struct qb_list_head *pos;
-       struct qb_list_head *next;
+       struct timerlist_timer *timer;
        uint64_t current_time_from_epoch;
        uint64_t current_monotonic_time;
        uint64_t current_time;
+       int res;
 
        current_monotonic_time = qb_util_nano_current_get();
        current_time_from_epoch = qb_util_nano_from_epoch_get();
 
-       qb_list_for_each_safe(pos, next, &timerlist->timer_head) {
+       if ( (res=pthread_mutex_lock(&timerlist->list_mutex))) {
+               return -res;
+       }
 
-               timer_from_list = qb_list_entry(pos,
-                                               struct timerlist_timer, list);
+       while (timerlist->size > 0) {
+               timer = timerlist_heap_entry_get(timerlist, 0);
 
                current_time =
-                   (timer_from_list->
+                   (timer->
                     is_absolute_timer ? current_time_from_epoch :
                     current_monotonic_time);
 
-               if (timer_from_list->expire_time < current_time) {
+               if (timer->expire_time < current_time) {
 
-                       timerlist_pre_dispatch(timerlist, timer_from_list);
+                       timerlist_pre_dispatch(timerlist, timer);
 
-                       timer_from_list->timer_fn(timer_from_list->data);
+                       timer->timer_fn(timer->data);
 
-                       timerlist_post_dispatch(timerlist, timer_from_list);
+                       timerlist_post_dispatch(timerlist, timer);
                } else {
                        break;  /* for timer iteration */
                }
        }
+
+       pthread_mutex_unlock(&timerlist->list_mutex);
+
+       return (0);
 }
 #endif /* QB_TLIST_H_DEFINED */
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libqb-2.0.3+20210303.404adbc/lib/Makefile.am 
new/libqb-2.0.4+20211112.a2691b9/lib/Makefile.am
--- old/libqb-2.0.3+20210303.404adbc/lib/Makefile.am    2021-03-03 
09:32:09.000000000 +0100
+++ new/libqb-2.0.4+20211112.a2691b9/lib/Makefile.am    2021-11-12 
14:18:47.000000000 +0100
@@ -30,7 +30,7 @@
 
 lib_LTLIBRARIES                = libqb.la
 
-libqb_la_LDFLAGS       = -version-info 102:0:2
+libqb_la_LDFLAGS       = -version-info 102:1:2
 
 source_to_lint         = util.c hdb.c ringbuffer.c ringbuffer_helper.c \
                          array.c loop.c loop_poll.c loop_job.c \
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libqb-2.0.3+20210303.404adbc/lib/loop_poll.c 
new/libqb-2.0.4+20211112.a2691b9/lib/loop_poll.c
--- old/libqb-2.0.3+20210303.404adbc/lib/loop_poll.c    2021-03-03 
09:32:09.000000000 +0100
+++ new/libqb-2.0.4+20211112.a2691b9/lib/loop_poll.c    2021-11-12 
14:18:47.000000000 +0100
@@ -475,12 +475,8 @@
                res = write(pipe_fds[1], &sig, sizeof(int32_t));
                if (res == -1 && errno == EAGAIN) {
                        goto try_again;
-               } else if (res != sizeof(int32_t)) {
-                       qb_util_log(LOG_ERR,
-                                   "failed to write signal to pipe [%d]", res);
                }
        }
-       qb_util_log(LOG_TRACE, "got real signal [%d] sent to pipe", sig);
 }
 
 static void
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libqb-2.0.3+20210303.404adbc/lib/loop_timerlist.c 
new/libqb-2.0.4+20211112.a2691b9/lib/loop_timerlist.c
--- old/libqb-2.0.3+20210303.404adbc/lib/loop_timerlist.c       2021-03-03 
09:32:09.000000000 +0100
+++ new/libqb-2.0.4+20211112.a2691b9/lib/loop_timerlist.c       2021-11-12 
14:18:47.000000000 +0100
@@ -76,7 +76,9 @@
 {
        struct qb_timer_source *ts = (struct qb_timer_source *)s;
        expired_timers = 0;
-       timerlist_expire(&ts->timerlist);
+       if (timerlist_expire(&ts->timerlist) != 0) {
+               qb_util_log(LOG_ERR, "timerlist_expire failed");
+       }
        return expired_timers;
 }
 
@@ -115,6 +117,8 @@
 {
        struct qb_timer_source *my_src =
            (struct qb_timer_source *)l->timer_source;
+
+       timerlist_destroy(&my_src->timerlist);
        qb_array_free(my_src->timers);
        free(l->timer_source);
 }
@@ -183,6 +187,7 @@
        struct qb_loop_timer *t;
        struct qb_timer_source *my_src;
        int32_t i;
+       int res;
        struct qb_loop *l = lp;
 
        if (l == NULL) {
@@ -194,8 +199,8 @@
        }
        my_src = (struct qb_timer_source *)l->timer_source;
 
-       if (pthread_mutex_lock(&my_src->lock)) {
-               return -errno;
+       if ( (res=pthread_mutex_lock(&my_src->lock))) {
+               return -res;
        }
        i = _get_empty_array_position_(my_src);
        assert(qb_array_index(my_src->timers, i, (void **)&t) >= 0);
@@ -263,7 +268,9 @@
        }
 
        if (t->timerlist_handle) {
-               timerlist_del(&s->timerlist, t->timerlist_handle);
+               if (timerlist_del(&s->timerlist, t->timerlist_handle) != 0) {
+                       qb_util_log(LOG_ERR, "Could not delete timer from 
timerlist");
+               }
        }
        t->state = QB_POLL_ENTRY_EMPTY;
        return 0;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libqb-2.0.3+20210303.404adbc/lib/rpl_sem.c 
new/libqb-2.0.4+20211112.a2691b9/lib/rpl_sem.c
--- old/libqb-2.0.3+20210303.404adbc/lib/rpl_sem.c      2021-03-03 
09:32:09.000000000 +0100
+++ new/libqb-2.0.4+20211112.a2691b9/lib/rpl_sem.c      2021-11-12 
14:18:47.000000000 +0100
@@ -76,7 +76,7 @@
 {
        int retval = pthread_mutex_lock(&sem->mutex);
        if (retval != 0) {
-               return -errno;
+               return -retval;
        }
        if (sem->destroy_request) {
                retval = -EINVAL;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libqb-2.0.3+20210303.404adbc/tests/Makefile.am 
new/libqb-2.0.4+20211112.a2691b9/tests/Makefile.am
--- old/libqb-2.0.3+20210303.404adbc/tests/Makefile.am  2021-03-03 
09:32:09.000000000 +0100
+++ new/libqb-2.0.4+20211112.a2691b9/tests/Makefile.am  2021-11-12 
14:18:47.000000000 +0100
@@ -38,7 +38,8 @@
 bmc_LDADD = $(top_builddir)/lib/libqb.la
 
 bmcpt_SOURCES = bmcpt.c
-bmcpt_LDADD = $(top_builddir)/lib/libqb.la
+bmcpt_CFLAGS = $(PTHREAD_CFLAGS)
+bmcpt_LDADD = $(PTHREAD_LIBS) $(top_builddir)/lib/libqb.la
 
 bms_SOURCES = bms.c
 bms_CFLAGS = $(GLIB_CFLAGS)
@@ -124,7 +125,7 @@
 
 check_LTLIBRARIES =
 check_PROGRAMS = array.test ipc.test list.test log.test loop.test \
-                map.test rb.test util.test \
+                map.test rb.test util.test tlist.test \
                 crash_test_dummy file_change_bytes
 dist_check_SCRIPTS = start.test resources.test blackbox-segfault.sh
 
@@ -161,6 +162,10 @@
 loop_test_CFLAGS = @CHECK_CFLAGS@
 loop_test_LDADD = $(top_builddir)/lib/libqb.la @CHECK_LIBS@
 
+tlist_test_SOURCES = check_tlist.c
+tlist_test_CFLAGS = @CHECK_CFLAGS@
+tlist_test_LDADD = $(top_builddir)/lib/libqb.la @CHECK_LIBS@
+
 ipc_test_SOURCES = check_ipc.c
 ipc_test_CFLAGS = @CHECK_CFLAGS@
 ipc_test_LDADD = $(top_builddir)/lib/libqb.la @CHECK_LIBS@
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libqb-2.0.3+20210303.404adbc/tests/check_loop.c 
new/libqb-2.0.4+20211112.a2691b9/tests/check_loop.c
--- old/libqb-2.0.3+20210303.404adbc/tests/check_loop.c 2021-03-03 
09:32:09.000000000 +0100
+++ new/libqb-2.0.4+20211112.a2691b9/tests/check_loop.c 2021-11-12 
14:18:47.000000000 +0100
@@ -448,7 +448,7 @@
        res = qb_loop_timer_add(l, QB_LOOP_LOW, 5*QB_TIME_NS_IN_MSEC, l, 
one_shot_tmo, &test_tht);
        ck_assert_int_eq(res, 0);
 
-       res = qb_loop_timer_is_running(l, test_th);
+       res = qb_loop_timer_is_running(l, test_tht);
        ck_assert_int_eq(res, QB_TRUE);
 
        sleep(5);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libqb-2.0.3+20210303.404adbc/tests/check_tlist.c 
new/libqb-2.0.4+20211112.a2691b9/tests/check_tlist.c
--- old/libqb-2.0.3+20210303.404adbc/tests/check_tlist.c        1970-01-01 
01:00:00.000000000 +0100
+++ new/libqb-2.0.4+20211112.a2691b9/tests/check_tlist.c        2021-11-12 
14:18:47.000000000 +0100
@@ -0,0 +1,294 @@
+/*
+ * Copyright (c) 2021 Red Hat, Inc.
+ *
+ * All rights reserved.
+ *
+ * Author: Jan Friesse <jfrie...@redhat.com>
+ *
+ * This file is part of libqb.
+ *
+ * libqb is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * libqb is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with libqb.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "os_base.h"
+
+#include "check_common.h"
+
+#include "tlist.h"
+
+#include <poll.h>
+
+#include <qb/qbdefs.h>
+#include <qb/qbutil.h>
+#include <qb/qblog.h>
+
+#define SHORT_TIMEOUT                  (100 * QB_TIME_NS_IN_MSEC)
+#define LONG_TIMEOUT                   (60 * QB_TIME_NS_IN_SEC)
+
+#define SPEED_TEST_NO_ITEMS            10000
+
+#define HEAP_TEST_NO_ITEMS             20
+/*
+ * Valid heap checking is slow
+ */
+#define HEAP_SPEED_TEST_NO_ITEMS       1000
+
+static int timer_list_fn1_called = 0;
+
+static void
+timer_list_fn1(void *data)
+{
+
+       ck_assert(data == &timer_list_fn1_called);
+
+       timer_list_fn1_called++;
+}
+
+static void
+sleep_ns(long long int ns)
+{
+
+       (void)poll(NULL, 0, (ns / QB_TIME_NS_IN_MSEC));
+}
+
+START_TEST(test_check_basic)
+{
+       struct timerlist tlist;
+       timer_handle thandle;
+       int res;
+       uint64_t u64;
+
+       timerlist_init(&tlist);
+
+       /*
+        * Check adding short duration and calling callback
+        */
+       res = timerlist_add_duration(&tlist, timer_list_fn1, 
&timer_list_fn1_called, SHORT_TIMEOUT / 2, &thandle);
+       ck_assert_int_eq(res, 0);
+
+       sleep_ns(SHORT_TIMEOUT);
+       u64 = timerlist_msec_duration_to_expire(&tlist);
+       ck_assert(u64 == 0);
+
+       timer_list_fn1_called = 0;
+       timerlist_expire(&tlist);
+       ck_assert_int_eq(timer_list_fn1_called, 1);
+
+       u64 = timerlist_msec_duration_to_expire(&tlist);
+       ck_assert(u64 == -1);
+
+       /*
+        * Check callback is not called (long timeout)
+        */
+       res = timerlist_add_duration(&tlist, timer_list_fn1, 
&timer_list_fn1_called, LONG_TIMEOUT / 2, &thandle);
+       ck_assert_int_eq(res, 0);
+
+       sleep_ns(SHORT_TIMEOUT);
+       u64 = timerlist_msec_duration_to_expire(&tlist);
+       ck_assert(u64 > 0);
+
+       timer_list_fn1_called = 0;
+       timerlist_expire(&tlist);
+       ck_assert_int_eq(timer_list_fn1_called, 0);
+
+       u64 = timerlist_msec_duration_to_expire(&tlist);
+       ck_assert(u64 > 0);
+
+       /*
+        * Delete timer
+        */
+       timerlist_del(&tlist, thandle);
+       u64 = timerlist_msec_duration_to_expire(&tlist);
+       ck_assert(u64 == -1);
+
+       timerlist_destroy(&tlist);
+}
+END_TEST
+
+START_TEST(test_check_speed)
+{
+       struct timerlist tlist;
+       timer_handle thandle[SPEED_TEST_NO_ITEMS];
+       int res;
+       uint64_t u64;
+       int i;
+
+       timerlist_init(&tlist);
+
+       /*
+        * Check adding a lot of short duration and deleting
+        */
+       for (i = 0; i < SPEED_TEST_NO_ITEMS; i++) {
+               res = timerlist_add_duration(&tlist, timer_list_fn1, 
&timer_list_fn1_called,
+                   SHORT_TIMEOUT / 2, &thandle[i]);
+               ck_assert_int_eq(res, 0);
+       }
+
+       for (i = 0; i < SPEED_TEST_NO_ITEMS; i++) {
+               timerlist_del(&tlist, thandle[i]);
+       }
+
+       u64 = timerlist_msec_duration_to_expire(&tlist);
+       ck_assert(u64 == -1);
+
+       /*
+        * Check adding a lot of short duration and calling callback
+        */
+       for (i = 0; i < SPEED_TEST_NO_ITEMS; i++) {
+               res = timerlist_add_duration(&tlist, timer_list_fn1, 
&timer_list_fn1_called,
+                   SHORT_TIMEOUT / 2, &thandle[i]);
+               ck_assert_int_eq(res, 0);
+       }
+
+       u64 = timerlist_msec_duration_to_expire(&tlist);
+       ck_assert(u64 != -1);
+
+       sleep_ns(SHORT_TIMEOUT);
+
+       timer_list_fn1_called = 0;
+       timerlist_expire(&tlist);
+       ck_assert_int_eq(timer_list_fn1_called, SPEED_TEST_NO_ITEMS);
+
+       u64 = timerlist_msec_duration_to_expire(&tlist);
+       ck_assert(u64 == -1);
+
+       timerlist_destroy(&tlist);
+}
+END_TEST
+
+START_TEST(test_check_heap)
+{
+       struct timerlist tlist;
+       int i;
+       timer_handle tlist_entry[HEAP_TEST_NO_ITEMS];
+       timer_handle tlist_speed_entry[HEAP_SPEED_TEST_NO_ITEMS];
+       int res;
+
+       timerlist_init(&tlist);
+
+       /*
+        * Empty tlist
+        */
+       ck_assert(timerlist_msec_duration_to_expire(&tlist) == -1);
+
+       /*
+        * Add items in standard and reverse order
+        */
+       for (i = 0; i < HEAP_TEST_NO_ITEMS / 2; i++) {
+               res = timerlist_add_duration(&tlist, timer_list_fn1, 
&timer_list_fn1_called,
+                   LONG_TIMEOUT * ((HEAP_TEST_NO_ITEMS - i) + 1), 
&tlist_entry[i * 2]);
+               ck_assert_int_eq(res, 0);
+
+               res = timerlist_add_duration(&tlist, timer_list_fn1, 
&timer_list_fn1_called,
+                   LONG_TIMEOUT * (i + 1), &tlist_entry[i * 2 + 1]);
+               ck_assert_int_eq(res, 0);
+
+               ck_assert(timerlist_debug_is_valid_heap(&tlist));
+       }
+
+       /*
+        * Remove items
+        */
+       for (i = 0; i < HEAP_TEST_NO_ITEMS; i++) {
+               timerlist_del(&tlist, tlist_entry[i]);
+
+               ck_assert(timerlist_debug_is_valid_heap(&tlist));
+       }
+
+       ck_assert(timerlist_msec_duration_to_expire(&tlist) == -1);
+
+       /*
+        * Add items again in increasing order
+        */
+       for (i = 0; i < HEAP_TEST_NO_ITEMS; i++) {
+               res = timerlist_add_duration(&tlist, timer_list_fn1, 
&timer_list_fn1_called,
+                   LONG_TIMEOUT * (i + 1), &tlist_entry[i]);
+               ck_assert_int_eq(res, 0);
+
+               ck_assert(timerlist_debug_is_valid_heap(&tlist));
+       }
+
+
+       /*
+        * Try delete every third item and test if heap property is kept
+        */
+       i = 0;
+       while (tlist.size > 0) {
+               i = (i + 3) % HEAP_TEST_NO_ITEMS;
+
+               while (tlist_entry[i] == NULL) {
+                       i = (i + 1) % HEAP_TEST_NO_ITEMS;
+               }
+
+               timerlist_del(&tlist, tlist_entry[i]);
+               tlist_entry[i] = NULL;
+               ck_assert(timerlist_debug_is_valid_heap(&tlist));
+       }
+
+       ck_assert(timerlist_msec_duration_to_expire(&tlist) == -1);
+
+       /*
+        * Speed test
+        */
+       for (i = 0; i < HEAP_SPEED_TEST_NO_ITEMS; i++) {
+               res = timerlist_add_duration(&tlist, timer_list_fn1, 
&timer_list_fn1_called,
+                   SHORT_TIMEOUT / 2, &tlist_speed_entry[i]);
+               ck_assert_int_eq(res, 0);
+
+               ck_assert(timerlist_debug_is_valid_heap(&tlist));
+       }
+
+       for (i = 0; i < HEAP_SPEED_TEST_NO_ITEMS; i++) {
+               timerlist_del(&tlist, tlist_speed_entry[i]);
+               ck_assert(timerlist_debug_is_valid_heap(&tlist));
+       }
+
+       /*
+        * Free list
+        */
+       timerlist_destroy(&tlist);
+}
+END_TEST
+
+static Suite *tlist_suite(void)
+{
+       TCase *tc;
+       Suite *s = suite_create("tlist");
+
+       add_tcase(s, tc, test_check_basic);
+       add_tcase(s, tc, test_check_speed, 30);
+       add_tcase(s, tc, test_check_heap, 30);
+
+       return s;
+}
+
+int32_t main(void)
+{
+       int32_t number_failed;
+
+       Suite *s = tlist_suite();
+       SRunner *sr = srunner_create(s);
+
+       qb_log_init("check", LOG_USER, LOG_EMERG);
+       atexit(qb_log_fini);
+       qb_log_ctl(QB_LOG_SYSLOG, QB_LOG_CONF_ENABLED, QB_FALSE);
+       qb_log_filter_ctl(QB_LOG_STDERR, QB_LOG_FILTER_ADD,
+                         QB_LOG_FILTER_FILE, "*", LOG_INFO);
+       qb_log_ctl(QB_LOG_STDERR, QB_LOG_CONF_ENABLED, QB_TRUE);
+
+       srunner_run_all(sr, CK_VERBOSE);
+       number_failed = srunner_ntests_failed(sr);
+       srunner_free(sr);
+       return (number_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
+}

Reply via email to