Index: network.c =================================================================== --- network.c (revision 24495) +++ network.c (working copy) @@ -1198,7 +1198,7 @@ DWORD ms_total = 0; int nhandles = 0; - + static HANDLE hEventPipeWrite = 0; static HANDLE hEventReadReady = 0; @@ -1208,18 +1208,25 @@ static HANDLE select_standby_event = NULL; static SOCKET select_wakeup_socket = -1; static SOCKET select_send_socket = -1; - static struct timeval select_timeout; + int readPipes = 0; int writePipePos = 0; HANDLE handle_array[FD_SETSIZE + 2]; + + /* TODO: Make this growable */ + struct GNUNET_DISK_FileHandle *readArray[50]; + int returncode = -1; int returnedpos = 0; struct GNUNET_CONTAINER_SList *handles_read; struct GNUNET_CONTAINER_SList *handles_write; struct GNUNET_CONTAINER_SList *handles_except; + + static struct timeval select_timeout; + int selectret = 0; fd_set aread; fd_set awrite; @@ -1231,8 +1238,7 @@ fd_set bexcept; #endif - /* TODO: Make this growable */ - struct GNUNET_DISK_FileHandle *readArray[50]; + #else struct timeval tv; #endif @@ -1320,8 +1326,207 @@ return 0; } - if (select_thread == NULL) + + + handles_read = GNUNET_CONTAINER_slist_create (); + handles_write = GNUNET_CONTAINER_slist_create (); + handles_except = GNUNET_CONTAINER_slist_create (); + FD_ZERO (&aread); + FD_ZERO (&awrite); + FD_ZERO (&aexcept); +#if DEBUG_NETWORK + FD_ZERO (&bread); + FD_ZERO (&bwrite); + FD_ZERO (&bexcept); +#endif + if (rfds) { + FD_COPY (&rfds->sds, &aread); +#if DEBUG_NETWORK + FD_COPY (&rfds->sds, &bread); +#endif + } + if (wfds) + { + FD_COPY (&wfds->sds, &awrite); +#if DEBUG_NETWORK + FD_COPY (&wfds->sds, &bwrite); +#endif + } + if (efds) + { + FD_COPY (&efds->sds, &aexcept); +#if DEBUG_NETWORK + FD_COPY (&efds->sds, &bexcept); +#endif + } + + + /* Run the select for all the cases. Is cheap and can save us to load all the heavy weapons. + By profiling we detected that this is the 90% of the scenarios. + */ + + /*Do the select now*/ + select_timeout.tv_sec = 0; + select_timeout.tv_usec = 0; + + /*Copy all the writes to the except, so we can detect connect() errors*/ + for (i = 0; i < awrite.fd_count; i++) + { + if (awrite.fd_array[i] != 0 && awrite.fd_array[i] != -1) + FD_SET (awrite.fd_array[i], &aexcept); + } + selectret = select (1, (rfds != NULL) ? &aread : NULL, + (wfds != NULL) ? &awrite : NULL, + &aexcept, &select_timeout); + + /* Check aexcept, add its contents to awrite */ + for (i = 0; i < aexcept.fd_count; i++) + { + if (aexcept.fd_array[i] != 0 && aexcept.fd_array[i] != -1) + FD_SET (aexcept.fd_array[i], &awrite); + } + + /*If our select returned something or is a 0-timed request. Process the pipes and get out of here !*/ + if((selectret > 0) || (ms_total == 0) ) + { + /* Read Pipes */ + if (rfds && read_handles) + { + struct GNUNET_CONTAINER_SList_Iterator i; + + for (i = GNUNET_CONTAINER_slist_begin (rfds->handles); + GNUNET_CONTAINER_slist_end (&i) != GNUNET_YES; + GNUNET_CONTAINER_slist_next (&i)) + { + struct GNUNET_DISK_FileHandle *fh; + + fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&i, + NULL); + if (fh->type == GNUNET_DISK_HANLDE_TYPE_PIPE) + { + DWORD error; + BOOL bret; + + SetLastError (0); + DWORD waitstatus = 0; + bret = + PeekNamedPipe (fh->h, NULL, 0, NULL, &waitstatus, NULL); + error = GetLastError (); + LOG (GNUNET_ERROR_TYPE_DEBUG, + "Peek at read pipe %d (0x%x) returned %d (%d bytes available) GLE %u\n", + i, fh->h, bret, waitstatus, error); + if (bret == 0) + { + /* TODO: either add more errors to this condition, or eliminate it + * entirely (failed to peek -> pipe is in serious trouble, should + * be selected as readable). + */ + if (error != ERROR_BROKEN_PIPE && error != ERROR_INVALID_HANDLE) + continue; + } + else if (waitstatus <= 0) + continue; + GNUNET_CONTAINER_slist_add (handles_read, + GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT, + fh, + sizeof (struct GNUNET_DISK_FileHandle)); + retcode++; + LOG (GNUNET_ERROR_TYPE_DEBUG, "Added read Pipe 0x%x (0x%x)\n", + fh, fh->h); + } + else + { + GNUNET_CONTAINER_slist_add (handles_read, + GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT, + fh, sizeof (struct GNUNET_DISK_FileHandle)); + retcode++; + } + } + } + if (wfds && write_handles) + { + LOG (GNUNET_ERROR_TYPE_DEBUG, + "Adding the write ready event to the array as %d\n", nhandles); + GNUNET_CONTAINER_slist_append (handles_write, wfds->handles); + retcode += write_handles; + } + if (efds && ex_handles) + { + struct GNUNET_CONTAINER_SList_Iterator i; + + for (i = GNUNET_CONTAINER_slist_begin (efds->handles); + GNUNET_CONTAINER_slist_end (&i) != GNUNET_YES; + GNUNET_CONTAINER_slist_next (&i)) + { + struct GNUNET_DISK_FileHandle *fh; + DWORD dwBytes; + + fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&i, + NULL); + if (fh->type == GNUNET_DISK_HANLDE_TYPE_PIPE) + { + if (!PeekNamedPipe (fh->h, NULL, 0, NULL, &dwBytes, NULL)) + { + GNUNET_CONTAINER_slist_add (handles_except, + GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT, + fh, + sizeof (struct GNUNET_DISK_FileHandle)); + retcode++; + } + } + } + } + + + + /*All with our select result.*/ + retcode+= selectret; + + + + if (rfds) + { + GNUNET_NETWORK_fdset_zero (rfds); + if (selectret != -1) + GNUNET_NETWORK_fdset_copy_native (rfds, &aread, selectret); + GNUNET_CONTAINER_slist_append (rfds->handles, handles_read); + } + if (wfds) + { + + GNUNET_NETWORK_fdset_zero (wfds); + if (selectret != -1) + GNUNET_NETWORK_fdset_copy_native (wfds, &awrite, selectret); + GNUNET_CONTAINER_slist_append (wfds->handles, handles_write); + } + if (efds) + { + GNUNET_NETWORK_fdset_zero (efds); + if (selectret != -1) + GNUNET_NETWORK_fdset_copy_native (efds, &aexcept, selectret); + GNUNET_CONTAINER_slist_append (efds->handles, handles_except); + } + GNUNET_CONTAINER_slist_destroy (handles_read); + GNUNET_CONTAINER_slist_destroy (handles_write); + GNUNET_CONTAINER_slist_destroy (handles_except); + + + + /*This should only happen on the 0-timed request*/ + if(retcode == -1) + return 0; + else + return retcode; + + } + + + /*If we got until here, Load the heavy weapons*/ + + + if (select_thread == NULL) + { SOCKET select_listening_socket = -1; struct sockaddr_in s_in; int alen; @@ -1371,10 +1576,9 @@ hEventPipeWrite = CreateEvent (NULL, TRUE, TRUE, NULL); readPipes = 0; writePipePos = -1; - - handles_read = GNUNET_CONTAINER_slist_create (); - handles_write = GNUNET_CONTAINER_slist_create (); - handles_except = GNUNET_CONTAINER_slist_create (); + + retcode = 0; + FD_ZERO (&aread); FD_ZERO (&awrite); FD_ZERO (&aexcept); @@ -1715,6 +1919,7 @@ else #endif return 0; + } /* end of network.c */