зеркало из https://github.com/mozilla/gecko-dev.git
channel now runs async on a worker thread
This commit is contained in:
Родитель
73e90d4a30
Коммит
9f9a4819d7
|
@ -33,7 +33,6 @@
|
|||
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include "nspr.h"
|
||||
#include "ldap.h"
|
||||
#include "nsCOMPtr.h"
|
||||
|
@ -75,15 +74,19 @@ lds(class nsLDAPChannel *chan, const char *url)
|
|||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
#ifdef NO_URL_SEARCH
|
||||
fprintf(stderr, "starting bind\n");
|
||||
#ifdef DEBUG_dmose
|
||||
PR_fprintf(PR_STDERR, "starting bind\n");
|
||||
#endif
|
||||
|
||||
if ( !myOperation->SimpleBind(NULL, NULL) ) {
|
||||
(void)myConnection->GetErrorString(&errString);
|
||||
fprintf(stderr, "ldap_simple_bind: %s\n", errString);
|
||||
PR_fprintf(PR_STDERR, "ldap_simple_bind: %s\n", errString);
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
fprintf(stderr, "waiting for bind to complete");
|
||||
#ifdef DEBUG_dmose
|
||||
PR_fprintf(PR_STDERR, "waiting for bind to complete");
|
||||
#endif
|
||||
|
||||
myMessage = new nsLDAPMessage(myOperation);
|
||||
returnCode = myOperation->Result(0, &nullTimeval, myMessage);
|
||||
|
@ -92,7 +95,9 @@ lds(class nsLDAPChannel *chan, const char *url)
|
|||
returnCode =
|
||||
myOperation->Result(0, &nullTimeval, myMessage);
|
||||
usleep(20);
|
||||
fputc('.',stderr);
|
||||
#ifdef DEBUG_dmose
|
||||
PR_fprintf(PR_STDERR,".");
|
||||
#endif
|
||||
}
|
||||
|
||||
switch (returnCode) {
|
||||
|
@ -101,19 +106,21 @@ lds(class nsLDAPChannel *chan, const char *url)
|
|||
break;
|
||||
case -1:
|
||||
(void)myConnection->GetErrorString(&errString);
|
||||
fprintf(stderr,
|
||||
"myOperation->Result() [myOperation->SimpleBind]: %s: errno=%d\n",
|
||||
errString, errno);
|
||||
PR_fprintf(PR_STDERR,
|
||||
"myOperation->Result() [myOperation->SimpleBind]: %s: errno=%d\n",
|
||||
errString, errno);
|
||||
ldap_memfree(errString);
|
||||
return NS_ERROR_FAILURE;
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "\nmyOperation->Result() returned unexpected value: %d",
|
||||
returnCode);
|
||||
PR_fprintf(PR_STDERR,
|
||||
"\nmyOperation->Result() returned unexpected value: %d",
|
||||
returnCode);
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
fprintf(stderr, "bound\n");
|
||||
#ifdef DEBUG_dmose
|
||||
PR_fprintf(PR_STDERR, "bound\n");
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -135,14 +142,16 @@ lds(class nsLDAPChannel *chan, const char *url)
|
|||
|
||||
// poll for results
|
||||
//
|
||||
fprintf(stderr, "polling search operation");
|
||||
#ifdef DEBUG_dmose
|
||||
PR_fprintf(PR_STDERR, "polling search operation");
|
||||
#endif
|
||||
returnCode = LDAP_SUCCESS;
|
||||
while ( returnCode != LDAP_RES_SEARCH_RESULT ) {
|
||||
|
||||
char *dn, *attr;
|
||||
int rc2;
|
||||
|
||||
fputc('.', stderr);
|
||||
PR_fprintf(PR_STDERR,".");
|
||||
|
||||
// XXX is 0 the right value?
|
||||
//
|
||||
|
@ -152,7 +161,7 @@ lds(class nsLDAPChannel *chan, const char *url)
|
|||
switch (returnCode) {
|
||||
case -1: // something went wrong
|
||||
(void)myConnection->GetErrorString(&errString);
|
||||
fprintf(stderr,
|
||||
PR_fprintf(PR_STDERR,
|
||||
"\nmyOperation->Result() [URLSearch]: %s: errno=%d\n",
|
||||
errString, errno);
|
||||
ldap_memfree(errString);
|
||||
|
@ -161,7 +170,9 @@ lds(class nsLDAPChannel *chan, const char *url)
|
|||
break;
|
||||
|
||||
case LDAP_RES_SEARCH_ENTRY:
|
||||
fprintf(stderr, "\nentry returned!\n");
|
||||
#ifdef DEBUG_dmose
|
||||
PR_fprintf(PR_STDERR, "\nentry returned!\n");
|
||||
#endif
|
||||
|
||||
// get the DN
|
||||
// XXX better err handling
|
||||
|
@ -217,8 +228,9 @@ lds(class nsLDAPChannel *chan, const char *url)
|
|||
if ( lden != LDAP_SUCCESS ) {
|
||||
|
||||
(void)myConnection->GetErrorString(&errString);
|
||||
fprintf(stderr, "myMessage: error getting attribute: %s\n",
|
||||
errString);
|
||||
PR_fprintf(PR_STDERR,
|
||||
"myMessage: error getting attribute: %s\n",
|
||||
errString);
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
|
@ -232,13 +244,15 @@ lds(class nsLDAPChannel *chan, const char *url)
|
|||
break;
|
||||
|
||||
case LDAP_RES_SEARCH_REFERENCE: // referral
|
||||
fprintf(stderr,
|
||||
PR_fprintf(PR_STDERR,
|
||||
"LDAP_RES_SEARCH_REFERENCE returned; not implemented!");
|
||||
return NS_ERROR_FAILURE;
|
||||
break;
|
||||
|
||||
case LDAP_RES_SEARCH_RESULT: // all done (the while condition sees this)
|
||||
fprintf(stderr, "\nresult returned: \n");
|
||||
#ifdef DEBUG_dmose
|
||||
PR_fprintf(PR_STDERR, "\nresult returned: \n");
|
||||
#endif
|
||||
|
||||
// XXX should use GetErrorString here?
|
||||
//
|
||||
|
@ -257,7 +271,7 @@ lds(class nsLDAPChannel *chan, const char *url)
|
|||
}
|
||||
myMessage = 0;
|
||||
|
||||
usleep(200);
|
||||
PR_Sleep(200);
|
||||
}
|
||||
|
||||
#ifdef DEBUG_dmose
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s): Dan Mosedale <dmose@mozilla.org>
|
||||
* Warren Harris <warren@netscape.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the
|
||||
* terms of the GNU General Public License Version 2 or later (the
|
||||
|
@ -36,10 +37,14 @@
|
|||
#include "nsMimeTypes.h"
|
||||
#include "nsIPipe.h"
|
||||
#include "nsXPIDLString.h"
|
||||
#include "nsLDAPService.h"
|
||||
#include "nsIServiceManager.h"
|
||||
|
||||
static NS_DEFINE_CID(kLDAPServiceCID, NS_LDAPSERVICE_CID);
|
||||
// for NS_NewAsyncStreamListener
|
||||
//
|
||||
#include "nsNetUtil.h"
|
||||
|
||||
// for defintion of NS_UI_THREAD_EVENTQ for use with NS_NewAsyncStreamListener
|
||||
//
|
||||
#include "nsIEventQueueService.h"
|
||||
|
||||
#ifdef DEBUG
|
||||
#include "nspr.h"
|
||||
|
@ -47,17 +52,16 @@ static NS_DEFINE_CID(kLDAPServiceCID, NS_LDAPSERVICE_CID);
|
|||
|
||||
NS_METHOD lds(class nsLDAPChannel *chan, const char *);
|
||||
|
||||
NS_IMPL_ISUPPORTS2(nsLDAPChannel, nsIChannel, nsIRequest);
|
||||
NS_IMPL_THREADSAFE_ISUPPORTS3(nsLDAPChannel, nsIChannel, nsIRequest,
|
||||
nsIRunnable);
|
||||
|
||||
nsLDAPChannel::nsLDAPChannel()
|
||||
{
|
||||
NS_INIT_ISUPPORTS();
|
||||
/* member initializers and constructor code */
|
||||
}
|
||||
|
||||
nsLDAPChannel::~nsLDAPChannel()
|
||||
{
|
||||
/* destructor code */
|
||||
}
|
||||
|
||||
nsresult
|
||||
|
@ -100,8 +104,7 @@ nsLDAPChannel::IsPending(PRBool *result)
|
|||
NS_IMETHODIMP
|
||||
nsLDAPChannel::GetStatus(nsresult *status)
|
||||
{
|
||||
NS_NOTYETIMPLEMENTED("nsLDAPChannel::GetStatus");
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -249,10 +252,7 @@ nsLDAPChannel::SetLoadAttributes(nsLoadFlags aLoadAttributes)
|
|||
NS_IMETHODIMP
|
||||
nsLDAPChannel::GetContentType(char* *aContentType)
|
||||
{
|
||||
// XXX check for null pointers in setters / in params?
|
||||
//
|
||||
if (!aContentType)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
NS_ENSURE_ARG_POINTER(aContentType);
|
||||
|
||||
*aContentType = nsCRT::strdup(TEXT_PLAIN);
|
||||
if (!*aContentType) {
|
||||
|
@ -517,7 +517,6 @@ nsLDAPChannel::AsyncRead(nsIStreamListener* aListener,
|
|||
nsISupports* aCtxt)
|
||||
{
|
||||
nsresult rv;
|
||||
nsXPIDLCString spec;
|
||||
|
||||
// deal with the input args
|
||||
//
|
||||
|
@ -525,53 +524,17 @@ nsLDAPChannel::AsyncRead(nsIStreamListener* aListener,
|
|||
mResponseContext = aCtxt;
|
||||
|
||||
// add ourselves to the appropriate loadgroup
|
||||
// XXX - what happens on the second call to AsyncRead()?
|
||||
//
|
||||
if (mLoadGroup) {
|
||||
mLoadGroup->AddChannel(this, nsnull);
|
||||
}
|
||||
|
||||
// since the LDAP SDK does all the socket management, we don't have
|
||||
// an underlying transport channel to create an nsIInputStream to hand
|
||||
// back to the nsIStreamListener. So (only on the first call to AsyncRead)
|
||||
// we do it ourselves:
|
||||
// kick off a thread to do the work
|
||||
//
|
||||
if (!mReadPipeIn) {
|
||||
|
||||
// get a new pipe, propagating any error upwards
|
||||
//
|
||||
rv = NS_NewPipe(getter_AddRefs(mReadPipeIn), getter_AddRefs(mReadPipeOut));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
NS_ASSERTION(!mThread, "nsLDAPChannel thread already exists!");
|
||||
|
||||
NS_ENSURE_SUCCESS(mReadPipeIn->SetNonBlocking(PR_TRUE),
|
||||
NS_ERROR_UNEXPECTED);
|
||||
|
||||
// XXX - bogus: this makes it synchronous!
|
||||
//
|
||||
NS_ENSURE_SUCCESS(mReadPipeOut->SetNonBlocking(PR_FALSE),
|
||||
NS_ERROR_UNEXPECTED);
|
||||
}
|
||||
|
||||
// get the transport service
|
||||
//
|
||||
#if 0
|
||||
NS_WITH_SERVICE(nsLDAPService, ldapService,
|
||||
kLDAPServiceCID, &rv);
|
||||
rv = NS_NewThread(getter_AddRefs(mThread), this, 0, PR_JOINABLE_THREAD);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
#endif
|
||||
|
||||
// XXX should this happen earlier?
|
||||
//
|
||||
mListener->OnStartRequest(this, mResponseContext);
|
||||
|
||||
// XXX do the search; this should go away
|
||||
//
|
||||
NS_ENSURE_SUCCESS(mURI->GetSpec(getter_Copies(spec)), NS_ERROR_UNEXPECTED);
|
||||
lds(this, spec);
|
||||
|
||||
// all done
|
||||
//
|
||||
mListener->OnStopRequest(this, mResponseContext, NS_OK, nsnull);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -596,6 +559,70 @@ nsLDAPChannel::AsyncWrite(nsIInputStream* fromStream,
|
|||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
// for nsIRunnable. this is the actual LDAP server interaction code for
|
||||
// AsyncRead(). it gets executed on a worker thread so we don't block
|
||||
// the main UI thread.
|
||||
//
|
||||
NS_IMETHODIMP
|
||||
nsLDAPChannel::Run(void)
|
||||
{
|
||||
nsresult rv;
|
||||
nsXPIDLCString spec;
|
||||
|
||||
#ifdef DEBUG_dmose
|
||||
PR_fprintf(PR_STDERR, "nsLDAPService::Run() entered!\n");
|
||||
#endif
|
||||
|
||||
// XXX how does this get destroyed?
|
||||
//
|
||||
rv = NS_NewAsyncStreamListener(getter_AddRefs(mAsyncListener), mListener,
|
||||
NS_UI_THREAD_EVENTQ);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// we already know the content type, so might as well fire this now
|
||||
//
|
||||
mAsyncListener->OnStartRequest(this, mResponseContext);
|
||||
|
||||
// since the LDAP SDK does all the socket management, we don't have
|
||||
// an underlying transport channel to create an nsIInputStream to hand
|
||||
// back to the nsIStreamListener. So (only on the first call to AsyncRead)
|
||||
// we do it ourselves:
|
||||
//
|
||||
if (!mReadPipeIn) {
|
||||
|
||||
// get a new pipe, propagating any error upwards
|
||||
//
|
||||
rv = NS_NewPipe(getter_AddRefs(mReadPipeIn), getter_AddRefs(mReadPipeOut));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// the side of the pipe used on the main UI thread cannot block
|
||||
//
|
||||
NS_ENSURE_SUCCESS(mReadPipeIn->SetNonBlocking(PR_TRUE),
|
||||
NS_ERROR_UNEXPECTED);
|
||||
|
||||
// but the side of the pipe used by the worker thread can block
|
||||
//
|
||||
NS_ENSURE_SUCCESS(mReadPipeOut->SetNonBlocking(PR_FALSE),
|
||||
NS_ERROR_UNEXPECTED);
|
||||
}
|
||||
|
||||
// get the URI spec
|
||||
//
|
||||
rv = mURI->GetSpec(getter_Copies(spec));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// do the search
|
||||
//
|
||||
rv = lds(this, spec);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// all done
|
||||
//
|
||||
mAsyncListener->OnStopRequest(this, mResponseContext, NS_OK, nsnull);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// XXX this function should go away
|
||||
//
|
||||
nsresult
|
||||
|
@ -607,8 +634,9 @@ nsLDAPChannel::pipeWrite(char *str)
|
|||
rv = mReadPipeOut->Write(str, strlen(str), &bytesWritten);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
mListener->OnDataAvailable(this, mResponseContext, mReadPipeIn,
|
||||
mReadPipeOffset, strlen(str));
|
||||
mAsyncListener->OnDataAvailable(this, mResponseContext, mReadPipeIn,
|
||||
mReadPipeOffset, strlen(str));
|
||||
mReadPipeOffset += bytesWritten;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -35,6 +35,8 @@
|
|||
#define nsLDAPChannel_h__
|
||||
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsIRunnable.h"
|
||||
#include "nsIThread.h"
|
||||
#include "nsIChannel.h"
|
||||
#include "nsIURI.h"
|
||||
#include "nsILoadGroup.h"
|
||||
|
@ -44,12 +46,13 @@
|
|||
#include "nsIBufferOutputStream.h"
|
||||
|
||||
/* Header file */
|
||||
class nsLDAPChannel : public nsIChannel
|
||||
class nsLDAPChannel : public nsIChannel, public nsIRunnable
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIREQUEST
|
||||
NS_DECL_NSICHANNEL
|
||||
NS_DECL_NSIRUNNABLE
|
||||
|
||||
nsLDAPChannel();
|
||||
virtual ~nsLDAPChannel();
|
||||
|
@ -78,11 +81,15 @@ protected:
|
|||
|
||||
// various other instance vars
|
||||
//
|
||||
nsCOMPtr<nsIStreamListener> mAsyncListener; // since we can't call mListener
|
||||
// directly from the worker thread
|
||||
nsCOMPtr<nsIThread> mThread; // worker thread for this channer
|
||||
nsCOMPtr<nsIStreamListener> mListener; // whoever is listening to us
|
||||
nsCOMPtr<nsISupports> mResponseContext;
|
||||
nsCOMPtr<nsIBufferInputStream> mReadPipeIn; // this end given to the listener
|
||||
nsCOMPtr<nsIBufferOutputStream> mReadPipeOut; // for writes from the channel
|
||||
PRUint32 mReadPipeOffset; // how many bytes written so far?
|
||||
|
||||
};
|
||||
|
||||
#endif // nsLDAPChannel_h__
|
||||
|
|
Загрузка…
Ссылка в новой задаче