*** ./src/backend/port/win32/socket.c.orig	Thu Oct 12 12:35:50 2006
--- ./src/backend/port/win32/socket.c	Thu Oct 12 13:29:54 2006
***************
*** 102,112 ****
--- 102,124 ----
  	return 0;
  }
  
+ static int
+ isDataGram(SOCKET s) {
+ 	int type;
+ 	int typelen = sizeof(type);
+ 
+ 	if ( getsockopt(s, SOL_SOCKET, SO_TYPE, (char*)&type, &typelen) )
+ 		return 1;
+ 
+ 	return ( type == SOCK_DGRAM ) ? 1 : 0;
+ }
+ 
  int
  pgwin32_waitforsinglesocket(SOCKET s, int what)
  {
  	static HANDLE waitevent = INVALID_HANDLE_VALUE;
  	static SOCKET current_socket = -1;
+ 	static int    isUDP = 0;
  	HANDLE		events[2];
  	int			r;
  
***************
*** 127,134 ****
  	 * socket from a previous call
  	 */
  
! 	if (current_socket != s && current_socket != -1)
! 		WSAEventSelect(current_socket, waitevent, 0);
  
  	current_socket = s;
  
--- 139,150 ----
  	 * socket from a previous call
  	 */
  
! 	if (current_socket != s) 
! 	{
! 		if ( current_socket != -1 )
! 			WSAEventSelect(current_socket, waitevent, 0);
! 		isUDP = isDataGram(s);
! 	}
  
  	current_socket = s;
  
***************
*** 140,146 ****
  
  	events[0] = pgwin32_signal_event;
  	events[1] = waitevent;
! 	r = WaitForMultipleObjectsEx(2, events, FALSE, INFINITE, TRUE);
  
  	if (r == WAIT_OBJECT_0 || r == WAIT_IO_COMPLETION)
  	{
--- 156,201 ----
  
  	events[0] = pgwin32_signal_event;
  	events[1] = waitevent;
! 
! 	/* 
! 	 * Just a workaround of unknown locking problem with writing
! 	 * in UDP socket under high load: 
! 	 * Client's pgsql backend sleeps infinitely in 
! 	 * WaitForMultipleObjectsEx, pgstat process sleeps in 
! 	 * pgwin32_select().  So, we will wait with small 
! 	 * timeout(0.1 sec) and if sockect is still blocked, 
! 	 * try WSASend (see comments in pgwin32_select) and wait again.
! 	 */
! 	if ((what & FD_WRITE) && isUDP)
! 	{
! 		for(;;)
! 		{
! 			r = WaitForMultipleObjectsEx(2, events, FALSE, 100, TRUE);
! 
! 			if ( r == WAIT_TIMEOUT )
! 			{
! 				char        c;
! 				WSABUF      buf;
! 				DWORD       sent;
! 
! 				buf.buf = &c;
! 				buf.len = 0;
! 
! 				r = WSASend(s, &buf, 1, &sent, 0, NULL, NULL);
! 				if (r == 0)         /* Completed - means things are fine! */
! 					return 1;
! 				else if ( WSAGetLastError() != WSAEWOULDBLOCK )
! 				{
! 					TranslateSocketError();
! 					return 0;
! 				}
! 			}
! 			else
! 				break;
! 		}
! 	}
! 	else
! 		r = WaitForMultipleObjectsEx(2, events, FALSE, INFINITE, TRUE);
  
  	if (r == WAIT_OBJECT_0 || r == WAIT_IO_COMPLETION)
  	{
***************
*** 280,309 ****
  	wbuf.len = len;
  	wbuf.buf = buf;
  
! 	r = WSASend(s, &wbuf, 1, &b, flags, NULL, NULL);
! 	if (r != SOCKET_ERROR && b > 0)
! 		/* Write succeeded right away */
! 		return b;
! 
! 	if (r == SOCKET_ERROR &&
! 		WSAGetLastError() != WSAEWOULDBLOCK)
! 	{
! 		TranslateSocketError();
! 		return -1;
! 	}
  
! 	/* No error, zero bytes (win2000+) or error+WSAEWOULDBLOCK (<=nt4) */
  
! 	if (pgwin32_waitforsinglesocket(s, FD_WRITE | FD_CLOSE) == 0)
! 		return -1;
! 
! 	r = WSASend(s, &wbuf, 1, &b, flags, NULL, NULL);
! 	if (r == SOCKET_ERROR)
! 	{
! 		TranslateSocketError();
! 		return -1;
  	}
! 	return b;
  }
  
  
--- 335,365 ----
  	wbuf.len = len;
  	wbuf.buf = buf;
  
! 	/*
! 	 * Readiness of socket to send data to UDP socket 
! 	 * may be not true: socket can become busy again! So loop
! 	 * until send or error occurs.
! 	 */
! 	for(;;) {
! 		r = WSASend(s, &wbuf, 1, &b, flags, NULL, NULL);
! 		if (r != SOCKET_ERROR && b > 0)
! 			/* Write succeeded right away */
! 			return b;
! 
! 		if (r == SOCKET_ERROR &&
! 			WSAGetLastError() != WSAEWOULDBLOCK)
! 		{
! 			TranslateSocketError();
! 			return -1;
! 		}
  
! 		/* No error, zero bytes (win2000+) or error+WSAEWOULDBLOCK (<=nt4) */
  
! 		if (pgwin32_waitforsinglesocket(s, FD_WRITE | FD_CLOSE) == 0)
! 			return -1;
  	}
! 
! 	return -1;
  }
  
  
