add flag and code to handle serialization of output (one file at a time) so that publishing doesn't fail due to too many logins or similar (bug 138662 and others); r=adamlock, sr=alecf

git-svn-id: svn://10.0.0.236/trunk@122547 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
brade%netscape.com
2002-06-03 13:08:27 +00:00
parent 4b6f95ec84
commit bd45eaa9a0
3 changed files with 132 additions and 58 deletions

View File

@@ -60,6 +60,8 @@ interface nsIWebBrowserPersist : nsISupports
const unsigned long PERSIST_FLAGS_FIXUP_LINKS_TO_DESTINATION = 256;
/** Don't do any adjustments to links */
const unsigned long PERSIST_FLAGS_DONT_FIXUP_LINKS = 512;
/** Force serialization of output (one file at a time; not concurrent) */
const unsigned long PERSIST_FLAGS_SERIALIZE_OUTPUT = 1024;
/** Flags governing how data is fetched from the network. */
attribute unsigned long persistFlags;

View File

@@ -255,6 +255,7 @@ NS_IMETHODIMP nsWebBrowserPersist::SetPersistFlags(PRUint32 aPersistFlags)
{
mPersistFlags = aPersistFlags;
mReplaceExisting = (mPersistFlags & PERSIST_FLAGS_REPLACE_EXISTING_FILES) ? PR_TRUE : PR_FALSE;
mSerializingOutput = (mPersistFlags & PERSIST_FLAGS_SERIALIZE_OUTPUT) ? PR_TRUE : PR_FALSE;
return NS_OK;
}
@@ -382,54 +383,7 @@ NS_IMETHODIMP nsWebBrowserPersist::SaveDocument(
if (NS_SUCCEEDED(rv) && datapathAsURI)
{
// Count how many URIs in the URI map require persisting
PRUint32 urisToPersist = 0;
if (mURIMap.Count() > 0)
{
mURIMap.Enumerate(EnumCountURIsToPersist, &urisToPersist);
}
if (urisToPersist > 0)
{
// Persist each file in the uri map. The document(s)
// will be saved after the last one of these is saved.
mURIMap.Enumerate(EnumPersistURIs, this);
}
if (mOutputMap.Count() == 0)
{
// There are no URIs to save, so just save the document(s)
// State start notification
if (mProgressListener)
{
mProgressListener->OnStateChange(nsnull, nsnull,
nsIWebProgressListener::STATE_START |
nsIWebProgressListener::STATE_IS_NETWORK,
NS_OK);
}
rv = SaveDocuments();
if (NS_FAILED(rv))
EndDownload(rv);
else
{
// local files won't trigger OnStopRequest so we call EndDownload here
PRBool isFile = PR_FALSE;
fileAsURI->SchemeIs("file", &isFile);
if (isFile)
EndDownload(NS_OK);
}
// State stop notification
if (mProgressListener)
{
mProgressListener->OnStateChange(nsnull, nsnull,
nsIWebProgressListener::STATE_STOP |
nsIWebProgressListener::STATE_IS_NETWORK,
NS_OK);
}
}
rv = SaveGatheredURIs(fileAsURI);
}
else if (mProgressListener)
{
@@ -439,7 +393,7 @@ NS_IMETHODIMP nsWebBrowserPersist::SaveDocument(
NS_OK);
mProgressListener->OnStateChange(nsnull, nsnull,
nsIWebProgressListener::STATE_STOP,
NS_OK);
rv);
}
return rv;
@@ -484,6 +438,88 @@ nsWebBrowserPersist::StartUpload(nsIStorageStream *storStream,
return NS_OK;
}
nsresult
nsWebBrowserPersist::SaveGatheredURIs(nsIURI *aFileAsURI)
{
nsresult rv = NS_OK;
// Count how many URIs in the URI map require persisting
PRUint32 urisToPersist = 0;
if (mURIMap.Count() > 0)
{
mURIMap.Enumerate(EnumCountURIsToPersist, &urisToPersist);
}
if (urisToPersist > 0)
{
// Persist each file in the uri map. The document(s)
// will be saved after the last one of these is saved.
mURIMap.Enumerate(EnumPersistURIs, this);
}
// if we don't have anything in mOutputMap (added from above enumeration)
// then we build the doc list (SaveDocuments)
if (mOutputMap.Count() == 0)
{
// There are no URIs to save, so just save the document(s)
// State start notification
PRUint32 addToStateFlags = 0;
if (mProgressListener)
{
if (mJustStartedLoading)
{
addToStateFlags |= nsIWebProgressListener::STATE_IS_NETWORK;
}
mProgressListener->OnStateChange(nsnull, nsnull,
nsIWebProgressListener::STATE_START | addToStateFlags, NS_OK);
}
rv = SaveDocuments();
if (NS_FAILED(rv))
EndDownload(rv);
else if (aFileAsURI)
{
// local files won't trigger OnStopRequest so we call EndDownload here
PRBool isFile = PR_FALSE;
aFileAsURI->SchemeIs("file", &isFile);
if (isFile)
EndDownload(NS_OK);
}
// State stop notification
if (mProgressListener)
{
mProgressListener->OnStateChange(nsnull, nsnull,
nsIWebProgressListener::STATE_STOP | addToStateFlags, rv);
}
}
return rv;
}
// this method returns true if there is another file to persist and false if not
PRBool
nsWebBrowserPersist::SerializeNextFile()
{
if (!mSerializingOutput)
{
return PR_FALSE;
}
nsresult rv = SaveGatheredURIs(nsnull);
if (NS_FAILED(rv))
{
return PR_FALSE;
}
return (mURIMap.Count()
|| mUploadList.Count()
|| mDocList.Count()
|| mOutputMap.Count());
}
//*****************************************************************************
// nsWebBrowserPersist::nsIRequestObserver
//*****************************************************************************
@@ -552,6 +588,7 @@ NS_IMETHODIMP nsWebBrowserPersist::OnStartRequest(
mOutputMap.Remove(&key);
// cancel; we don't need to know any more
// stop request will get called
request->Cancel(NS_BINDING_ABORTED);
}
}
@@ -581,18 +618,28 @@ NS_IMETHODIMP nsWebBrowserPersist::OnStopRequest(
mUploadList.Remove(&key);
}
}
if (mOutputMap.Count() == 0 && !mCancel && !mStartSaving)
// ensure we call SaveDocuments if we:
// 1) aren't canceling
// 2) we haven't triggered the save (which we only want to trigger once)
// 3) we aren't serializing (which will call it inside SerializeNextFile)
if (mOutputMap.Count() == 0 && !mCancel && !mStartSaving
&& !mSerializingOutput)
{
mStartSaving = PR_TRUE;
nsresult rv = SaveDocuments();
NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
}
PRBool completed = PR_FALSE;
if (mOutputMap.Count() == 0 && (mUploadList.Count() == 0)
&& mDocList.Count() == 0)
if (mOutputMap.Count() == 0 && mUploadList.Count() == 0)
{
completed = PR_TRUE;
// if no documents left in mDocList, --> done
// if we have no files left to serialize and no error result, --> done
if (mDocList.Count() == 0
|| (!SerializeNextFile() && NS_SUCCEEDED(mPersistResult)))
{
completed = PR_TRUE;
}
}
if (completed)
@@ -700,11 +747,15 @@ NS_IMETHODIMP nsWebBrowserPersist::OnDataAvailable(
PRInt32 channelContentLength = -1;
if (!cancel &&
NS_SUCCEEDED(channel->GetContentLength(&channelContentLength)) &&
channelContentLength != -1)
NS_SUCCEEDED(channel->GetContentLength(&channelContentLength)))
{
if ((channelContentLength - (aOffset + aLength)) == 0)
// if we get -1 at this point, we didn't get content-length header
// assume that we got all of the data and push what we have;
// that's the best we can do now
if ((-1 == channelContentLength) ||
((channelContentLength - (aOffset + aLength)) == 0))
{
NS_ASSERTION(channelContentLength != -1, "no content length");
// we're done with this pass; see if we need to do upload
nsCAutoString contentType;
channel->GetContentType(contentType);
@@ -1371,6 +1422,8 @@ nsresult nsWebBrowserPersist::SaveDocuments()
{
nsresult rv = NS_OK;
mStartSaving = PR_TRUE;
// Iterate through all queued documents, saving them to file and fixing
// them up on the way.
@@ -1422,6 +1475,10 @@ nsresult nsWebBrowserPersist::SaveDocuments()
if (NS_FAILED(rv))
break;
// if we're serializing, bail after first iteration of loop
if (mSerializingOutput)
break;
}
// delete, cleanup regardless of errors (bug 132417)
@@ -1429,8 +1486,17 @@ nsresult nsWebBrowserPersist::SaveDocuments()
{
DocData *docData = (DocData *) mDocList.ElementAt(i);
delete docData;
if (mSerializingOutput)
{
mDocList.RemoveElementAt(i);
break;
}
}
if (!mSerializingOutput)
{
mDocList.Clear();
}
mDocList.Clear();
return rv;
}
@@ -1807,6 +1873,9 @@ nsWebBrowserPersist::EnumPersistURIs(nsHashKey *aKey, void *aData, void* closure
NS_ENSURE_SUCCESS(rv, PR_FALSE);
if (pthis->mSerializingOutput)
return PR_FALSE;
return PR_TRUE;
}

View File

@@ -129,6 +129,8 @@ private:
nsresult FixRedirectedChannelEntry(nsIChannel *aNewChannel);
void EndDownload(nsresult aResult = NS_OK);
nsresult SaveGatheredURIs(nsIURI *aFileAsURI);
PRBool SerializeNextFile();
void CalcTotalProgress();
// nsDOMWalkerCallback method
@@ -174,6 +176,7 @@ private:
PRPackedBool mCompleted;
PRPackedBool mStartSaving;
PRPackedBool mReplaceExisting;
PRPackedBool mSerializingOutput;
PRUint32 mPersistFlags;
PRUint32 mPersistResult;
PRInt32 mTotalCurrentProgress;