shmqueue.c
上传用户:blenddy
上传日期:2007-01-07
资源大小:6495k
文件大小:6k
源码类别:

数据库系统

开发平台:

Unix_Linux

  1. /*-------------------------------------------------------------------------
  2.  *
  3.  * shmqueue.c
  4.  *   shared memory linked lists
  5.  *
  6.  * Copyright (c) 1994, Regents of the University of California
  7.  *
  8.  *
  9.  * IDENTIFICATION
  10.  *   $Header: /usr/local/cvsroot/pgsql/src/backend/storage/ipc/shmqueue.c,v 1.10 1999/02/13 23:18:13 momjian Exp $
  11.  *
  12.  * NOTES
  13.  *
  14.  * Package for managing doubly-linked lists in shared memory.
  15.  * The only tricky thing is that SHM_QUEUE will usually be a field
  16.  * in a larger record. SHMQueueGetFirst has to return a pointer
  17.  * to the record itself instead of a pointer to the SHMQueue field
  18.  * of the record.  It takes an extra pointer and does some extra
  19.  * pointer arithmetic to do this correctly.
  20.  *
  21.  * NOTE: These are set up so they can be turned into macros some day.
  22.  *
  23.  *-------------------------------------------------------------------------
  24.  */
  25. #include <stdio.h> /* for sprintf() */
  26. #include "postgres.h"
  27. #include "storage/shmem.h" /* where the declarations go */
  28. /*#define SHMQUEUE_DEBUG*/
  29. #ifdef SHMQUEUE_DEBUG
  30. #define SHMQUEUE_DEBUG_DEL /* deletions */
  31. #define SHMQUEUE_DEBUG_HD /* head inserts */
  32. #define SHMQUEUE_DEBUG_TL /* tail inserts */
  33. #define SHMQUEUE_DEBUG_ELOG NOTICE
  34. #endif  /* SHMQUEUE_DEBUG */
  35. /*
  36.  * ShmemQueueInit -- make the head of a new queue point
  37.  * to itself
  38.  */
  39. void
  40. SHMQueueInit(SHM_QUEUE *queue)
  41. {
  42. Assert(SHM_PTR_VALID(queue));
  43. (queue)->prev = (queue)->next = MAKE_OFFSET(queue);
  44. }
  45. /*
  46.  * SHMQueueIsDetached -- TRUE if element is not currently
  47.  * in a queue.
  48.  */
  49. #ifdef NOT_USED
  50. bool
  51. SHMQueueIsDetached(SHM_QUEUE *queue)
  52. {
  53. Assert(SHM_PTR_VALID(queue));
  54. return (queue)->prev == INVALID_OFFSET;
  55. }
  56. #endif
  57. /*
  58.  * SHMQueueElemInit -- clear an element's links
  59.  */
  60. void
  61. SHMQueueElemInit(SHM_QUEUE *queue)
  62. {
  63. Assert(SHM_PTR_VALID(queue));
  64. (queue)->prev = (queue)->next = INVALID_OFFSET;
  65. }
  66. /*
  67.  * SHMQueueDelete -- remove an element from the queue and
  68.  * close the links
  69.  */
  70. void
  71. SHMQueueDelete(SHM_QUEUE *queue)
  72. {
  73. SHM_QUEUE  *nextElem = (SHM_QUEUE *) MAKE_PTR((queue)->next);
  74. SHM_QUEUE  *prevElem = (SHM_QUEUE *) MAKE_PTR((queue)->prev);
  75. Assert(SHM_PTR_VALID(queue));
  76. Assert(SHM_PTR_VALID(nextElem));
  77. Assert(SHM_PTR_VALID(prevElem));
  78. #ifdef SHMQUEUE_DEBUG_DEL
  79. dumpQ(queue, "in SHMQueueDelete: begin");
  80. #endif  /* SHMQUEUE_DEBUG_DEL */
  81. prevElem->next = (queue)->next;
  82. nextElem->prev = (queue)->prev;
  83. #ifdef SHMQUEUE_DEBUG_DEL
  84. dumpQ((SHM_QUEUE *) MAKE_PTR(queue->prev), "in SHMQueueDelete: end");
  85. #endif  /* SHMQUEUE_DEBUG_DEL */
  86. }
  87. #ifdef SHMQUEUE_DEBUG
  88. void
  89. dumpQ(SHM_QUEUE *q, char *s)
  90. {
  91. char elem[NAMEDATALEN];
  92. char buf[1024];
  93. SHM_QUEUE  *start = q;
  94. int count = 0;
  95. sprintf(buf, "q prevs: %x", MAKE_OFFSET(q));
  96. q = (SHM_QUEUE *) MAKE_PTR(q->prev);
  97. while (q != start)
  98. {
  99. sprintf(elem, "--->%x", MAKE_OFFSET(q));
  100. strcat(buf, elem);
  101. q = (SHM_QUEUE *) MAKE_PTR(q->prev);
  102. if (q->prev == MAKE_OFFSET(q))
  103. break;
  104. if (count++ > 40)
  105. {
  106. strcat(buf, "BAD PREV QUEUE!!");
  107. break;
  108. }
  109. }
  110. sprintf(elem, "--->%x", MAKE_OFFSET(q));
  111. strcat(buf, elem);
  112. elog(SHMQUEUE_DEBUG_ELOG, "%s: %s", s, buf);
  113. sprintf(buf, "q nexts: %x", MAKE_OFFSET(q));
  114. count = 0;
  115. q = (SHM_QUEUE *) MAKE_PTR(q->next);
  116. while (q != start)
  117. {
  118. sprintf(elem, "--->%x", MAKE_OFFSET(q));
  119. strcat(buf, elem);
  120. q = (SHM_QUEUE *) MAKE_PTR(q->next);
  121. if (q->next == MAKE_OFFSET(q))
  122. break;
  123. if (count++ > 10)
  124. {
  125. strcat(buf, "BAD NEXT QUEUE!!");
  126. break;
  127. }
  128. }
  129. sprintf(elem, "--->%x", MAKE_OFFSET(q));
  130. strcat(buf, elem);
  131. elog(SHMQUEUE_DEBUG_ELOG, "%s: %s", s, buf);
  132. }
  133. #endif  /* SHMQUEUE_DEBUG */
  134. /*
  135.  * SHMQueueInsertHD -- put elem in queue between the queue head
  136.  * and its "prev" element.
  137.  */
  138. #ifdef NOT_USED
  139. void
  140. SHMQueueInsertHD(SHM_QUEUE *queue, SHM_QUEUE *elem)
  141. {
  142. SHM_QUEUE  *prevPtr = (SHM_QUEUE *) MAKE_PTR((queue)->prev);
  143. SHMEM_OFFSET elemOffset = MAKE_OFFSET(elem);
  144. Assert(SHM_PTR_VALID(queue));
  145. Assert(SHM_PTR_VALID(elem));
  146. #ifdef SHMQUEUE_DEBUG_HD
  147. dumpQ(queue, "in SHMQueueInsertHD: begin");
  148. #endif  /* SHMQUEUE_DEBUG_HD */
  149. (elem)->next = prevPtr->next;
  150. (elem)->prev = queue->prev;
  151. (queue)->prev = elemOffset;
  152. prevPtr->next = elemOffset;
  153. #ifdef SHMQUEUE_DEBUG_HD
  154. dumpQ(queue, "in SHMQueueInsertHD: end");
  155. #endif  /* SHMQUEUE_DEBUG_HD */
  156. }
  157. #endif
  158. void
  159. SHMQueueInsertTL(SHM_QUEUE *queue, SHM_QUEUE *elem)
  160. {
  161. SHM_QUEUE  *nextPtr = (SHM_QUEUE *) MAKE_PTR((queue)->next);
  162. SHMEM_OFFSET elemOffset = MAKE_OFFSET(elem);
  163. Assert(SHM_PTR_VALID(queue));
  164. Assert(SHM_PTR_VALID(elem));
  165. #ifdef SHMQUEUE_DEBUG_TL
  166. dumpQ(queue, "in SHMQueueInsertTL: begin");
  167. #endif  /* SHMQUEUE_DEBUG_TL */
  168. (elem)->prev = nextPtr->prev;
  169. (elem)->next = queue->next;
  170. (queue)->next = elemOffset;
  171. nextPtr->prev = elemOffset;
  172. #ifdef SHMQUEUE_DEBUG_TL
  173. dumpQ(queue, "in SHMQueueInsertTL: end");
  174. #endif  /* SHMQUEUE_DEBUG_TL */
  175. }
  176. /*
  177.  * SHMQueueFirst -- Get the first element from a queue
  178.  *
  179.  * First element is queue->next.  If SHMQueue is part of
  180.  * a larger structure, we want to return a pointer to the
  181.  * whole structure rather than a pointer to its SHMQueue field.
  182.  * I.E. struct {
  183.  * int stuff;
  184.  * SHMQueue elem;
  185.  * } ELEMType;
  186.  * when this element is in a queue (queue->next) is struct.elem.
  187.  * nextQueue allows us to calculate the offset of the SHMQueue
  188.  * field in the structure.
  189.  *
  190.  * call to SHMQueueFirst should take these parameters:
  191.  *
  192.  *  &(queueHead),&firstElem,&(firstElem->next)
  193.  *
  194.  * Note that firstElem may well be uninitialized.  if firstElem
  195.  * is initially K, &(firstElem->next) will be K+ the offset to
  196.  * next.
  197.  */
  198. void
  199. SHMQueueFirst(SHM_QUEUE *queue, Pointer *nextPtrPtr, SHM_QUEUE *nextQueue)
  200. {
  201. SHM_QUEUE  *elemPtr = (SHM_QUEUE *) MAKE_PTR((queue)->next);
  202. Assert(SHM_PTR_VALID(queue));
  203. *nextPtrPtr = (Pointer) (((unsigned long) *nextPtrPtr) +
  204. ((unsigned long) elemPtr) - ((unsigned long) nextQueue));
  205. /*
  206.  * nextPtrPtr a ptr to a structure linked in the queue nextQueue is
  207.  * the SHMQueue field of the structure nextPtrPtr - nextQueue is 0
  208.  * minus the offset of the queue field n the record elemPtr +
  209.  * (*nextPtrPtr - nexQueue) is the start of the structure containing
  210.  * elemPtr.
  211.  */
  212. }
  213. /*
  214.  * SHMQueueEmpty -- TRUE if queue head is only element, FALSE otherwise
  215.  */
  216. bool
  217. SHMQueueEmpty(SHM_QUEUE *queue)
  218. {
  219. Assert(SHM_PTR_VALID(queue));
  220. if (queue->prev == MAKE_OFFSET(queue))
  221. {
  222. Assert(queue->next = MAKE_OFFSET(queue));
  223. return TRUE;
  224. }
  225. return FALSE;
  226. }