[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