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

数据库系统

开发平台:

Unix_Linux

  1. /*-------------------------------------------------------------------------
  2.  *
  3.  * pqpacket.c
  4.  *   routines for reading and writing data packets sent/received by
  5.  *   POSTGRES clients and servers
  6.  *
  7.  * Copyright (c) 1994, Regents of the University of California
  8.  *
  9.  *
  10.  * IDENTIFICATION
  11.  *   $Header: /usr/local/cvsroot/pgsql/src/backend/libpq/pqpacket.c,v 1.19 1999/02/13 23:15:47 momjian Exp $
  12.  *
  13.  *-------------------------------------------------------------------------
  14.  */
  15. #include <stdio.h>
  16. #include <unistd.h>
  17. #include <string.h>
  18. #include <sys/types.h>
  19. #include <sys/socket.h>
  20. #include <netdb.h>
  21. #include <netinet/in.h>
  22. #include <fcntl.h>
  23. #include <errno.h>
  24. #include <postgres.h>
  25. #include <miscadmin.h>
  26. #include <storage/ipc.h>
  27. #include <libpq/libpq.h>
  28. /*
  29.  * Set up a packet read for the postmaster event loop.
  30.  */
  31. void
  32. PacketReceiveSetup(Packet *pkt, PacketDoneProc iodone, void *arg)
  33. {
  34. pkt->nrtodo = sizeof(pkt->len);
  35. pkt->ptr = (char *) &pkt->len;
  36. pkt->iodone = iodone;
  37. pkt->arg = arg;
  38. pkt->state = ReadingPacketLength;
  39. /* Clear the destination. */
  40. MemSet(&pkt->pkt, 0, sizeof(pkt->pkt));
  41. }
  42. /*
  43.  * Read a packet fragment. Return STATUS_OK if the connection should stay
  44.  * open.
  45.  */
  46. int
  47. PacketReceiveFragment(Packet *pkt, int sock)
  48. {
  49. int got;
  50. if ((got = read(sock, pkt->ptr, pkt->nrtodo)) > 0)
  51. {
  52. pkt->nrtodo -= got;
  53. pkt->ptr += got;
  54. /* See if we have got what we need for the packet length. */
  55. if (pkt->nrtodo == 0 && pkt->state == ReadingPacketLength)
  56. {
  57. pkt->len = ntohl(pkt->len);
  58. if (pkt->len < sizeof(pkt->len) ||
  59. pkt->len > sizeof(pkt->len) + sizeof(pkt->pkt))
  60. {
  61. PacketSendError(pkt, "Invalid packet length");
  62. return STATUS_OK;
  63. }
  64. /* Set up for the rest of the packet. */
  65. pkt->nrtodo = pkt->len - sizeof(pkt->len);
  66. pkt->ptr = (char *) &pkt->pkt;
  67. pkt->state = ReadingPacket;
  68. }
  69. /* See if we have got what we need for the packet. */
  70. if (pkt->nrtodo == 0 && pkt->state == ReadingPacket)
  71. {
  72. pkt->state = Idle;
  73. /* Special case to close the connection. */
  74. if (pkt->iodone == NULL)
  75. return STATUS_ERROR;
  76. return (*pkt->iodone) (pkt->arg, pkt->len - sizeof(pkt->len),
  77.    (void *) &pkt->pkt);
  78. }
  79. return STATUS_OK;
  80. }
  81. if (got == 0)
  82. return STATUS_ERROR;
  83. if (errno == EINTR)
  84. return STATUS_OK;
  85. perror("PacketReceiveFragment: read() failed");
  86. return STATUS_ERROR;
  87. }
  88. /*
  89.  * Set up a packet write for the postmaster event loop.
  90.  */
  91. void
  92. PacketSendSetup(Packet *pkt, int nbytes, PacketDoneProc iodone, void *arg)
  93. {
  94. pkt->len = (PacketLen) nbytes;
  95. pkt->nrtodo = nbytes;
  96. pkt->ptr = (char *) &pkt->pkt;
  97. pkt->iodone = iodone;
  98. pkt->arg = arg;
  99. pkt->state = WritingPacket;
  100. }
  101. /*
  102.  * Write a packet fragment.  Return STATUS_OK if the connection should stay
  103.  * open.
  104.  */
  105. int
  106. PacketSendFragment(Packet *pkt, int sock)
  107. {
  108. int done;
  109. if ((done = write(sock, pkt->ptr, pkt->nrtodo)) > 0)
  110. {
  111. pkt->nrtodo -= done;
  112. pkt->ptr += done;
  113. /* See if we have written the whole packet. */
  114. if (pkt->nrtodo == 0)
  115. {
  116. pkt->state = Idle;
  117. /* Special case to close the connection. */
  118. if (pkt->iodone == NULL)
  119. return STATUS_ERROR;
  120. return (*pkt->iodone) (pkt->arg, pkt->len,
  121.    (void *) &pkt->pkt);
  122. }
  123. return STATUS_OK;
  124. }
  125. if (done == 0)
  126. return STATUS_ERROR;
  127. if (errno == EINTR)
  128. return STATUS_OK;
  129. perror("PacketSendFragment: write() failed");
  130. return STATUS_ERROR;
  131. }
  132. /*
  133.  * Send an error message from the postmaster to the frontend.
  134.  */
  135. void
  136. PacketSendError(Packet *pkt, char *errormsg)
  137. {
  138. fprintf(stderr, "%sn", errormsg);
  139. pkt->pkt.em.data[0] = 'E';
  140. StrNCpy(&pkt->pkt.em.data[1], errormsg, sizeof(pkt->pkt.em.data) - 2);
  141. /*
  142.  * The NULL i/o callback will cause the connection to be broken when
  143.  * the error message has been sent.
  144.  */
  145. PacketSendSetup(pkt, strlen(pkt->pkt.em.data) + 1, NULL, NULL);
  146. }