+# ifdef HAVE_WINSOCK
+# define SLAP_EVENT_FNAME "WSselect"
+/* Winsock provides a "select" function but its fd_sets are
+ * actually arrays of sockets. Since these sockets are handles
+ * and not a contiguous range of small integers, we manage our
+ * own "fd" table of socket handles and use their indices as
+ * descriptors.
+ *
+ * All of our listener/connection structures use fds; the actual
+ * I/O functions use sockets. The SLAP_FD2SOCK macro in proto-slap.h
+ * handles the mapping.
+ *
+ * Despite the mapping overhead, this is about 45% more efficient
+ * than just using Winsock's select and FD_ISSET directly.
+ *
+ * Unfortunately Winsock's select implementation doesn't scale well
+ * as the number of connections increases. This probably needs to be
+ * rewritten to use the Winsock overlapped/asynchronous I/O functions.
+ */
+# define SLAP_EVENTS_ARE_INDEXED 1
+# define SLAP_EVENT_DECL fd_set readfds, writefds
+# define SLAP_EVENT_INIT do { \
+ int i; \
+ FD_ZERO( &readfds ); \
+ FD_ZERO( &writefds ); \
+ memset( slap_daemon.sd_rflags, 0, slap_daemon.sd_nfds ); \
+ for ( i=0; i<slap_daemon.sd_nfds; i++ ) { \
+ if ( slap_daemon.sd_flags[i] & SD_READ ) \
+ FD_SET( slapd_ws_sockets[i], &readfds );\
+ if ( slap_daemon.sd_flags[i] & SD_WRITE ) \
+ FD_SET( slapd_ws_sockets[i], &writefds ); \
+ } } while ( 0 )
+
+# define SLAP_EVENT_MAX slap_daemon.sd_nfds
+
+# define SLAP_EVENT_WAIT(tvp, nsp) do { \
+ int i; \
+ *(nsp) = select( SLAP_EVENT_MAX, &readfds, \
+ nwriters > 0 ? &writefds : NULL, NULL, (tvp) ); \
+ for ( i=0; i<readfds.fd_count; i++) { \
+ int fd = slapd_sock2fd(readfds.fd_array[i]); \
+ if ( fd >= 0 ) { \
+ slap_daemon.sd_rflags[fd] = SD_READ; \
+ if ( fd >= *(nsp)) *(nsp) = fd+1; \
+ } \
+ } \
+ for ( i=0; i<writefds.fd_count; i++) { \
+ int fd = slapd_sock2fd(writefds.fd_array[i]); \
+ if ( fd >= 0 ) { \
+ slap_daemon.sd_rflags[fd] = SD_WRITE; \
+ if ( fd >= *(nsp)) *(nsp) = fd+1; \
+ } \
+ } \
+} while (0)
+
+# define SLAP_EVENT_IS_READ(fd) (slap_daemon.sd_rflags[fd] & SD_READ)
+# define SLAP_EVENT_IS_WRITE(fd) (slap_daemon.sd_rflags[fd] & SD_WRITE)
+
+# define SLAP_EVENT_CLR_READ(fd) slap_daemon.sd_rflags[fd] &= ~SD_READ;
+# define SLAP_EVENT_CLR_WRITE(fd) slap_daemon.sd_rflags[fd] &= ~SD_WRITE;
+
+# define SLAP_SOCK_INIT do { \
+ ldap_pvt_thread_mutex_init( &slapd_ws_mutex ); \
+ slapd_ws_sockets = ch_malloc( dtblsize * ( sizeof(SOCKET) + 2)); \
+ slap_daemon.sd_flags = (char *)(slapd_ws_sockets + dtblsize); \
+ slap_daemon.sd_rflags = slap_daemon.sd_flags + dtblsize; \
+ memset( slapd_ws_sockets, -1, dtblsize * sizeof(SOCKET) ); \
+ slapd_ws_sockets[0] = wake_sds[0]; \
+ slapd_ws_sockets[1] = wake_sds[1]; \
+ wake_sds[0] = 0; \
+ wake_sds[1] = 1; \
+ slap_daemon.sd_nfds = 2; \
+ } while ( 0 )
+
+# define SLAP_SOCK_DESTROY do { \
+ ch_free( slapd_ws_sockets ); slapd_ws_sockets = NULL; \
+ slap_daemon.sd_flags = NULL; \
+ slap_daemon.sd_rflags = NULL; \
+ ldap_pvt_thread_mutex_destroy( &slapd_ws_mutex ); \
+ } while ( 0 )
+
+# define SLAP_SOCK_IS_ACTIVE(fd) ( slap_daemon.sd_flags[fd] & SD_ACTIVE )
+# define SLAP_SOCK_IS_READ(fd) ( slap_daemon.sd_flags[fd] & SD_READ )
+# define SLAP_SOCK_IS_WRITE(fd) ( slap_daemon.sd_flags[fd] & SD_WRITE )
+# define SLAP_SOCK_NOT_ACTIVE(fd) (!slap_daemon.sd_flags[fd])
+
+# define SLAP_SOCK_SET_READ(fd) ( slap_daemon.sd_flags[fd] |= SD_READ )
+# define SLAP_SOCK_SET_WRITE(fd) ( slap_daemon.sd_flags[fd] |= SD_WRITE )
+
+# define SLAP_SELECT_ADDTEST(s) do { \
+ if ((s) >= slap_daemon.sd_nfds) slap_daemon.sd_nfds = (s)+1; \
+} while (0)
+
+# define SLAP_SOCK_CLR_READ(fd) ( slap_daemon.sd_flags[fd] &= ~SD_READ )
+# define SLAP_SOCK_CLR_WRITE(fd) ( slap_daemon.sd_flags[fd] &= ~SD_WRITE )
+
+# define SLAP_SOCK_ADD(s, l) do { \
+ SLAP_SELECT_ADDTEST((s)); \
+ slap_daemon.sd_flags[s] = SD_ACTIVE|SD_READ; \
+} while ( 0 )
+
+# define SLAP_SOCK_DEL(s) do { \
+ slap_daemon.sd_flags[s] = 0; \
+ slapd_sockdel( s ); \
+} while ( 0 )
+
+# else /* !HAVE_WINSOCK */