LCOV - code coverage report
Current view: top level - src/include/storage - proclist.h (source / functions) Hit Total Coverage
Test: PostgreSQL Lines: 45 58 77.6 %
Date: 2017-09-29 13:40:31 Functions: 6 8 75.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*-------------------------------------------------------------------------
       2             :  *
       3             :  * proclist.h
       4             :  *      operations on doubly-linked lists of pgprocnos
       5             :  *
       6             :  * The interface is similar to dlist from ilist.h, but uses pgprocno instead
       7             :  * of pointers.  This allows proclist_head to be mapped at different addresses
       8             :  * in different backends.
       9             :  *
      10             :  * See proclist_types.h for the structs that these functions operate on.  They
      11             :  * are separated to break a header dependency cycle with proc.h.
      12             :  *
      13             :  * Portions Copyright (c) 2016-2017, PostgreSQL Global Development Group
      14             :  *
      15             :  * IDENTIFICATION
      16             :  *      src/include/storage/proclist.h
      17             :  *-------------------------------------------------------------------------
      18             :  */
      19             : #ifndef PROCLIST_H
      20             : #define PROCLIST_H
      21             : 
      22             : #include "storage/proc.h"
      23             : #include "storage/proclist_types.h"
      24             : 
      25             : /*
      26             :  * Initialize a proclist.
      27             :  */
      28             : static inline void
      29      138996 : proclist_init(proclist_head *list)
      30             : {
      31      138996 :     list->head = list->tail = INVALID_PGPROCNO;
      32      138996 : }
      33             : 
      34             : /*
      35             :  * Is the list empty?
      36             :  */
      37             : static inline bool
      38        4194 : proclist_is_empty(proclist_head *list)
      39             : {
      40        4194 :     return list->head == INVALID_PGPROCNO;
      41             : }
      42             : 
      43             : /*
      44             :  * Get a pointer to a proclist_node inside a given PGPROC, given a procno and
      45             :  * an offset.
      46             :  */
      47             : static inline proclist_node *
      48        8330 : proclist_node_get(int procno, size_t node_offset)
      49             : {
      50        8330 :     char       *entry = (char *) GetPGProcByNumber(procno);
      51             : 
      52        8330 :     return (proclist_node *) (entry + node_offset);
      53             : }
      54             : 
      55             : /*
      56             :  * Insert a node at the beginning of a list.
      57             :  */
      58             : static inline void
      59         430 : proclist_push_head_offset(proclist_head *list, int procno, size_t node_offset)
      60             : {
      61         430 :     proclist_node *node = proclist_node_get(procno, node_offset);
      62             : 
      63         430 :     if (list->head == INVALID_PGPROCNO)
      64             :     {
      65         317 :         Assert(list->tail == INVALID_PGPROCNO);
      66         317 :         node->next = node->prev = INVALID_PGPROCNO;
      67         317 :         list->head = list->tail = procno;
      68             :     }
      69             :     else
      70             :     {
      71         113 :         Assert(list->tail != INVALID_PGPROCNO);
      72         113 :         Assert(list->head != procno);
      73         113 :         Assert(list->tail != procno);
      74         113 :         node->next = list->head;
      75         113 :         proclist_node_get(node->next, node_offset)->prev = procno;
      76         113 :         node->prev = INVALID_PGPROCNO;
      77         113 :         list->head = procno;
      78             :     }
      79         430 : }
      80             : 
      81             : /*
      82             :  * Insert a node at the end of a list.
      83             :  */
      84             : static inline void
      85        2130 : proclist_push_tail_offset(proclist_head *list, int procno, size_t node_offset)
      86             : {
      87        2130 :     proclist_node *node = proclist_node_get(procno, node_offset);
      88             : 
      89        2130 :     if (list->tail == INVALID_PGPROCNO)
      90             :     {
      91        1919 :         Assert(list->head == INVALID_PGPROCNO);
      92        1919 :         node->next = node->prev = INVALID_PGPROCNO;
      93        1919 :         list->head = list->tail = procno;
      94             :     }
      95             :     else
      96             :     {
      97         211 :         Assert(list->head != INVALID_PGPROCNO);
      98         211 :         Assert(list->head != procno);
      99         211 :         Assert(list->tail != procno);
     100         211 :         node->prev = list->tail;
     101         211 :         proclist_node_get(node->prev, node_offset)->next = procno;
     102         211 :         node->next = INVALID_PGPROCNO;
     103         211 :         list->tail = procno;
     104             :     }
     105        2130 : }
     106             : 
     107             : /*
     108             :  * Delete a node.  The node must be in the list.
     109             :  */
     110             : static inline void
     111        2560 : proclist_delete_offset(proclist_head *list, int procno, size_t node_offset)
     112             : {
     113        2560 :     proclist_node *node = proclist_node_get(procno, node_offset);
     114             : 
     115        2560 :     if (node->prev == INVALID_PGPROCNO)
     116        2560 :         list->head = node->next;
     117             :     else
     118           0 :         proclist_node_get(node->prev, node_offset)->next = node->next;
     119             : 
     120        2560 :     if (node->next == INVALID_PGPROCNO)
     121        2236 :         list->tail = node->prev;
     122             :     else
     123         324 :         proclist_node_get(node->next, node_offset)->prev = node->prev;
     124             : 
     125        2560 :     node->next = node->prev = INVALID_PGPROCNO;
     126        2560 : }
     127             : 
     128             : /*
     129             :  * Check if a node is currently in a list.  It must be known that the node is
     130             :  * not in any _other_ proclist that uses the same proclist_node, so that the
     131             :  * only possibilities are that it is in this list or none.
     132             :  */
     133             : static inline bool
     134           0 : proclist_contains_offset(proclist_head *list, int procno,
     135             :                          size_t node_offset)
     136             : {
     137           0 :     proclist_node *node = proclist_node_get(procno, node_offset);
     138             : 
     139             :     /*
     140             :      * If this is not a member of a proclist, then the next and prev pointers
     141             :      * should be 0. Circular lists are not allowed so this condition is not
     142             :      * confusable with a real pgprocno 0.
     143             :      */
     144           0 :     if (node->prev == 0 && node->next == 0)
     145           0 :         return false;
     146             : 
     147             :     /* If there is a previous node, then this node must be in the list. */
     148           0 :     if (node->prev != INVALID_PGPROCNO)
     149           0 :         return true;
     150             : 
     151             :     /*
     152             :      * There is no previous node, so the only way this node can be in the list
     153             :      * is if it's the head node.
     154             :      */
     155           0 :     return list->head == procno;
     156             : }
     157             : 
     158             : /*
     159             :  * Remove and return the first node from a list (there must be one).
     160             :  */
     161             : static inline PGPROC *
     162           0 : proclist_pop_head_node_offset(proclist_head *list, size_t node_offset)
     163             : {
     164             :     PGPROC     *proc;
     165             : 
     166           0 :     Assert(!proclist_is_empty(list));
     167           0 :     proc = GetPGProcByNumber(list->head);
     168           0 :     proclist_delete_offset(list, list->head, node_offset);
     169           0 :     return proc;
     170             : }
     171             : 
     172             : /*
     173             :  * Helper macros to avoid repetition of offsetof(PGPROC, <member>).
     174             :  * 'link_member' is the name of a proclist_node member in PGPROC.
     175             :  */
     176             : #define proclist_delete(list, procno, link_member) \
     177             :     proclist_delete_offset((list), (procno), offsetof(PGPROC, link_member))
     178             : #define proclist_push_head(list, procno, link_member) \
     179             :     proclist_push_head_offset((list), (procno), offsetof(PGPROC, link_member))
     180             : #define proclist_push_tail(list, procno, link_member) \
     181             :     proclist_push_tail_offset((list), (procno), offsetof(PGPROC, link_member))
     182             : #define proclist_pop_head_node(list, link_member) \
     183             :     proclist_pop_head_node_offset((list), offsetof(PGPROC, link_member))
     184             : #define proclist_contains(list, procno, link_member) \
     185             :     proclist_contains_offset((list), (procno), offsetof(PGPROC, link_member))
     186             : 
     187             : /*
     188             :  * Iterate through the list pointed at by 'lhead', storing the current
     189             :  * position in 'iter'.  'link_member' is the name of a proclist_node member in
     190             :  * PGPROC.  Access the current position with iter.cur.
     191             :  *
     192             :  * The only list modification allowed while iterating is deleting the current
     193             :  * node with proclist_delete(list, iter.cur, node_offset).
     194             :  */
     195             : #define proclist_foreach_modify(iter, lhead, link_member)                   \
     196             :     for (AssertVariableIsOfTypeMacro(iter, proclist_mutable_iter),          \
     197             :          AssertVariableIsOfTypeMacro(lhead, proclist_head *),               \
     198             :          (iter).cur = (lhead)->head,                                     \
     199             :          (iter).next = (iter).cur == INVALID_PGPROCNO ? INVALID_PGPROCNO :  \
     200             :              proclist_node_get((iter).cur,                                  \
     201             :                                offsetof(PGPROC, link_member))->next;     \
     202             :          (iter).cur != INVALID_PGPROCNO;                                    \
     203             :          (iter).cur = (iter).next,                                          \
     204             :          (iter).next = (iter).cur == INVALID_PGPROCNO ? INVALID_PGPROCNO :  \
     205             :              proclist_node_get((iter).cur,                                  \
     206             :                                offsetof(PGPROC, link_member))->next)
     207             : 
     208             : #endif

Generated by: LCOV version 1.11