[or-cvs] r10759: Change of plan and some decent progress on the IOCP Loader. (libevent-urz/trunk/loaders)

Urz at seul.org Urz at seul.org
Sat Jul 7 01:49:54 UTC 2007


Author: Urz
Date: 2007-07-06 21:49:54 -0400 (Fri, 06 Jul 2007)
New Revision: 10759

Modified:
   libevent-urz/trunk/loaders/IOCPloader.c
   libevent-urz/trunk/loaders/IOCPloader.h
Log:
Change of plan and some decent progress on the IOCP Loader.

Modified: libevent-urz/trunk/loaders/IOCPloader.c
===================================================================
--- libevent-urz/trunk/loaders/IOCPloader.c	2007-07-07 00:31:25 UTC (rev 10758)
+++ libevent-urz/trunk/loaders/IOCPloader.c	2007-07-07 01:49:54 UTC (rev 10759)
@@ -8,6 +8,9 @@
 
 HANDLE IOCP;
 HANDLE Threads[NO_WORKERS];
+WSAEVENT *eventList = NULL;
+connection *connList = NULL;
+DWORD listSize = 0;
 
 /*
  * Status :
@@ -24,12 +27,45 @@
  * I should be available to chat on your saturday / sunday nights if you want to talk.
  *
  * P.S. Sorry about not commiting for a while, I just forgot.
+ *
+ * Status update (7 July)
+ * Had a bit of time to work on it after all, and I had a bit of a eureaka moment. Instead of
+ * using the callbacks I will use an Event (the other mode of operation for Overlapped I/O.)
+ * The code required to read and fill buffers out of a given list of connections should be complete
+ * (but is probably not threadsafe...). What needs to happen now is sending, initializing and testing.
+ * initializing is partially done.
  */
 
-/*
-When adding new handles to the IO Completion port, the Completion Key
-_MUST_ by a pointer to a connection (see IOCPloader.h) with all fields initialized.
-*/
+DWORD new_connection_obj(SOCKET *s, sa_bufferevent * bufevent) {
+    DWORD myListElem;
+    
+    // gain global list lock
+    myListElem = listSize;
+    listSize++;
+    
+    eventList = realloc(eventList, sizeof(HANDLE *) * listSize);
+    connList = realloc(connList, sizeof(connection *) * listSize);
+    
+    
+    eventList[myListElem] = WSACreateEvent();
+    // check for errors here
+    
+    connList[myListElem] = malloc(sizeof(connection));
+    // get connection lock here
+    connList[myListElem].localbuf = bufevent;
+    
+    connList[myListElem].netbuf = malloc(sizeof(WSABUF));
+    connList[myListElem].netbuf->len = SUGGESTED_BUF_SIZE;
+    connList[myListElem].netbuf->buf = malloc(SUGGESTED_BUF_SIZE);
+    
+    connList[myListElem].sock = s;
+    
+    connList[myListElem].ol = calloc(sizeof(WSAOVERLAPPED));
+    connList[myListElem].ol->hEvent = (HANDLE) eventList[myListElem];
+    // free conneciton lock here
+    
+    // relase global list lock
+}
 
 DWORD WINAPI IOCPLoaderMain(LPVOID nodata) {
     SOCKET workaround;
@@ -59,7 +95,7 @@
     // From IOWorkerThreadProc
     LPOVERLAPPED CompletedOverlapped;
     // See http://msdn2.microsoft.com/en-us/library/ms684342.aspx
-    DWORD CompleteSize;
+    DWORD WaitRet;
     ULONG *CompletionKey;
     BOOL GQCSRet
     connection *Conn;
@@ -67,31 +103,36 @@
     ULONG WSARecvFlags = MSG_WAITALL;
 
     while(1) {
-        GQCSRet = GetQueuedCompletionStatus(
-            IOCP, // The IOCP to get statuses from
-            &CompleteSize, // "... receives the number of bytes transferred 
-                            //during an I/O operation that has completed."
-            &CompletionKey,
-            // A pointer to a variable that receives the completion key value 
-            // associated with the file handle whose I/O operation has completed.
-            // In IOCPS.cpp : (LPDWORD) &lpClientContext,
-            &CompletedOverlapped
-            // A pointer to a variable that receives the address of the OVERLAPPED
-            // structure that was specified when the completed I/O operation was started.
+    
+        WaitRet = WaitForMultipleObjects( 
+            listSize,   
+            // number of socket events in array
+            eventList,  
+            // array of socket read event handles
+            FALSE,          
+            // wait until any one event happens
             INFINITE
-            // The number of milliseconds that the caller is willing to wait for a
-            // completion packet to appear at the completion port.
+            // wait forever
             );
-        if(!GQCSRet) {
-            printf("GetQueuedCompletionStatus error %d\n", GetLastError());
-            continue;
+        
+        if(WaitRet > listSize) {
+            // An error happened.
         }
         
-        // The completion key is the associated sa_bufferevent.
-        Conn = (connection *) CompletionKey;
+        // This is no error, a completed read event has occured.
+        // Get the connection ths applies to. See semantics of
+        // return value for WaitForMultipleObjects
+        // (http://msdn2.microsoft.com/en-us/library/ms687025.aspx)
+        // to understand why this works.
+        Conn = connList + WaitRet;
         
-        // From ProcessIOMessage
+        // Now we have a completed read event, perform the operations
+        // required on the read data.
+        ReadComplete(Conn);
         
+        
+        // Now the data has been removed from the WSABUF, we can reset the
+        // read to continue reading.
         // http://msdn2.microsoft.com/en-us/library/ms741688.aspx
         WSARecvRet = WSARecv(
             Conn->sock,
@@ -106,192 +147,43 @@
             &WSARecvFlags,
             // Flags which control the operation of WSARecv. I belive MSG_WAITALL
             // is the one we want.
-            &Conn->ol, 
+            Conn->ol, 
             // The overlapped structure for the event.
-			&ReadComplete);
+			NULL
+            // The callback - we are using events for this, so that's not important
+            );
 
     }
 }
 
-void CALLBACK ReadComplete(IN DWORD dwError, IN DWORD cbTransferred, IN LPWSAOVERLAPPED lpOverlapped, IN DWORD dwFlags) {
+void ReadComplete(connection *Conn) {
+    BOOL GORRet;
+    DWORD TransferSize;
+    DWORD Flags;
+    size_t loadRet, toload, loaded;
+    char *upto;
+    
+    
+    GORRet = WSAGetOverlappedResult(
+        Conn->sock,
+        // The socket to get the read size from
+        Conn->ol,
+        // The overlapped data structure relating to the read event
+        &TransferSize,
+        // Gets the size of the transfer
+        FALSE,
+        // Whether or not to wait for completed I/O. Since we know the I/O
+        // is completed (we waited for it) we don't really care.
+        &Flags
+        // Gets the flags for the operation
+        );
+        
+    upto = Conn->netbuf.buf;
+    toload = (size_t) TransferSize;
+    
+    while(toload > 0) {
+        loaded = sa_bufferevent_load(Conn, upto, toload);
+        toload -= loaded;
+        upto += loaded;
+    }
 }
-
-/* 
-Note : Below code copied from the IOCP example at http://www.codeproject.com/internet/YourOwnSecureProtocol.asp
-The licence would seem to let me copy this here. This code will never appear in any compliable version of this
-file and is solely here for reference purposes, to understand IOCP.
-*/
-
-
-// /* UINT IOCPS::IOWorkerThreadProc(LPVOID pParam)
-// {
-	// IOCPS* pThis = reinterpret_cast<IOCPS*>(pParam);
-	// if ( pThis )
-	// {
-		// DWORD dwIoSize;
-		// ClientContext* lpClientContext;
-		// CIOCPBuffer *pOverlapBuff;
-		// bool bError=false;
-		// HANDLE hCompletionPort = pThis->m_hCompletionPort;
-		// LPOVERLAPPED lpOverlapped;
-
-		// while ( !bError )
-		// {
-			// pOverlapBuff=NULL;
-			// lpClientContext=NULL;
-			//Get a completed IO request.
-			// BOOL bIORet = GetQueuedCompletionStatus(
-				// hCompletionPort,
-				// &dwIoSize,
-				// (LPDWORD) &lpClientContext,
-				// &lpOverlapped, INFINITE);
-			//Simulate workload (for debugging, to find possible reordering)
-			//Sleep(20);
-
-
-
-			//If Something whent wrong..
-			// if (!bIORet)  
-			// {
-                // Snip Error Handling
-            // }
-
-
-
-			// if(bIORet && lpOverlapped && lpClientContext) 
-			// {
-            // Urz:
-            // This gets the CIOCPBuffer that contains the OVERLAPPED structure we just got returned.
-            // Not sure why they didn't just use the completion key, but meh
-            // update: That's because they were using the completion key for the Client context struct.
-            // /Urz
-				// pOverlapBuff=CONTAINING_RECORD(lpOverlapped, CIOCPBuffer, m_ol);
-				// if(pOverlapBuff!=NULL)
-					// pThis->ProcessIOMessage(pOverlapBuff, lpClientContext, dwIoSize);
-			// }	
-
-			// if(lpClientContext==NULL&&pOverlapBuff==NULL&&pThis->m_bShutDown)
-			// {
-				// TRACE("lpClientContext==NULL \r\n"); 
-				// bError=true;
-			// }
-
-
-			//pThis->ReleaseBuffer(pOverlapBuff);// from previous call
-
-		// } 
-
-	// }
-
-	// TRACE("IOWorker Died!\r\n");
-	// return 0xdead;
-// } */
-
-/* void IOCPS::ProcessIOMessage(CIOCPBuffer *pOverlapBuff, ClientContext *pContext, DWORD dwSize)
-{
-
-	if(pOverlapBuff==NULL)
-		return;
-
-	//	Sleep(rand()%50);
-	switch (pOverlapBuff->GetOperation())
-	{
-
-	case IOInitialize :
-		OnInitialize(pContext,dwSize,pOverlapBuff);
-		break;
-
-	case IORead :
-		OnRead(pContext,pOverlapBuff);
-		break;	
-
-
-	case IOReadCompleted :
-		OnReadCompleted(pContext,dwSize,pOverlapBuff);
-		break;
-
-
-	case IOWrite :
-		OnWrite(pContext,dwSize,pOverlapBuff);
-		break;
-
-	case IOWriteCompleted :
-		OnWriteCompleted(pContext,dwSize,pOverlapBuff);
-		break;
-
-	case IOZeroByteRead : //  Workaround the the WSAENOBUFS error problem..See OnZeroByteRead. 
-		OnZeroByteRead(pContext,pOverlapBuff);
-		break;
-
-	case IOZeroReadCompleted : //  Workaround the the WSAENOBUFS error problem.. 
-		OnZeroByteReadCompleted(pContext,dwSize,pOverlapBuff);
-		break;
-#if defined TRANSFERFILEFUNCTIONALITY
-	case IOTransmitFileCompleted : //  Workaround the the WSAENOBUFS error problem.. 
-		OnTransmitFileCompleted(pContext,pOverlapBuff);
-		break;
-#endif
-
-	case IOPostedPackage : 
-		OnPostedPackage(pContext,pOverlapBuff);
-		break;
-
-
-	default:
-		ReleaseBuffer(pOverlapBuff);
-		break;
-
-	} 
-} */
-
-/*
-void IOCPS::OnRead(ClientContext *pContext,CIOCPBuffer *pOverlapBuff)
-{
-	// issue a read request 
-	if(pContext&&!m_bShutDown)
-	{
-		if(pOverlapBuff==NULL)
-		{
-			// Buffer allocation / error checking
-		}
-		if(pOverlapBuff!=NULL)
-		{
-			pOverlapBuff->SetOperation(IOReadCompleted);
-			pOverlapBuff->SetupRead();
-			if(m_bReadInOrder)
-				MakeOrderdRead(pContext,pOverlapBuff);
-			else
-			{
-				DWORD dwIoSize=0;
-				ULONG			ulFlags = MSG_PARTIAL;
-				UINT nRetVal = WSARecv(pContext->m_Socket, 
-					pOverlapBuff->GetWSABuffer(),
-					1,
-					&dwIoSize, 
-					&ulFlags,
-					&pOverlapBuff->m_ol, 
-					NULL);
-				if ( nRetVal == SOCKET_ERROR && WSAGetLastError() != WSA_IO_PENDING) 
-				{
-					if(WSAGetLastError()!=WSAENOTSOCK)
-					{
-#ifndef _DEBUG
-						// Remove Unnecessary disconnect messages in release mode.. 
-						if(WSAGetLastError()!=WSAECONNRESET&&WSAGetLastError()!=WSAECONNABORTED)
-#endif
-						{
-							CString msg;
-							msg.Format("Disconnect in Onread Possible Socket Error: %s",ErrorCode2Text(WSAGetLastError()));
-							AppendLog(msg);
-						}
-					}
-					ReleaseBuffer(pOverlapBuff);
-					TRACE(">OnRead(%x)\r\n",pContext);
-					DisconnectClient(pContext);
-					ReleaseClientContext(pContext);
-				}
-			}
-		}
-	}
-}
-*/
\ No newline at end of file

Modified: libevent-urz/trunk/loaders/IOCPloader.h
===================================================================
--- libevent-urz/trunk/loaders/IOCPloader.h	2007-07-07 00:31:25 UTC (rev 10758)
+++ libevent-urz/trunk/loaders/IOCPloader.h	2007-07-07 01:49:54 UTC (rev 10759)
@@ -1,11 +1,13 @@
 
 
 DWORD WINAPI IOCPLoaderMain(LPVOID);
-void CALLBACK ReadComplete(IN DWORD dwError, IN DWORD cbTransferred, IN LPWSAOVERLAPPED lpOverlapped, IN DWORD dwFlags);
 
+#define SUGGESTED_BUF_SIZE 4096
+
 typedef struct {
     sa_bufferevent *localbuf;
     WSABUF *netbuf;
     SOCKET sock;
     OVERLAPPED *ol;
+    // mutex lock
 } connection;
\ No newline at end of file



More information about the tor-commits mailing list